Program Listing for File DataMask.cpp

Return to documentation for file (necsim/DataMask.cpp)

#include "DataMask.h"
#include "Landscape.h"
#include "Logging.h"
namespace necsim
{
    DataMask::DataMask() : inputfile(""), isNullSample(true), isGridOffset(false), x_offset(0), y_offset(0), x_dim(0),
                           y_dim(0), mask_x_dim(0), mask_y_dim(0), getProportionfptr(nullptr), sample_mask(),
                           sample_mask_exact()
    {
        getProportionfptr = &DataMask::getBoolProportion;
    }

    bool DataMask::isNull()
    {
        return isNullSample;
    }

    void DataMask::setup(const shared_ptr<SimParameters> sim_parameters)
    {
#ifdef DEBUG
        if((sim_parameters->grid_x_size > sim_parameters->sample_x_size ||
            sim_parameters->grid_y_size > sim_parameters->sample_y_size) && !isNullSample)
        {
            writeLog(50, "Grid size: " + to_string(sim_parameters->grid_x_size) + ", " +
                         to_string(sim_parameters->grid_y_size));
            writeLog(50, "Sample mask size: " + to_string(sim_parameters->sample_x_size) + ", " +
                         to_string(sim_parameters->sample_y_size));
            throw FatalException("Datamask dimensions do not make sense");
        }
#endif // DEBUG
        inputfile = sim_parameters->sample_mask_file;
        x_dim = sim_parameters->grid_x_size;
        y_dim = sim_parameters->grid_y_size;
        mask_x_dim = sim_parameters->sample_x_size;
        mask_y_dim = sim_parameters->sample_y_size;
        x_offset = sim_parameters->sample_x_offset;
        y_offset = sim_parameters->sample_y_offset;
        if(x_dim != mask_x_dim || y_dim != mask_y_dim)
        {
            isGridOffset = true;
        }
        else
        {
            isGridOffset = false;
        }
    }

    bool DataMask::checkCanUseDefault(const shared_ptr<SimParameters> sim_parameters)
    {
        if(sim_parameters->sample_mask_file == "null")
        {
            if(sim_parameters->fine_map_x_size == sim_parameters->sample_x_size
               && sim_parameters->fine_map_y_size == sim_parameters->sample_y_size
               && sim_parameters->fine_map_x_offset == 0 && sim_parameters->fine_map_y_offset == 0)
            {
                isNullSample = true;
            }
            else
            {
                isNullSample = false;
            }
        }
        else
        {
            isNullSample = sim_parameters->sample_mask_file == "none";
        }
        return isNullSample;
    }

    void DataMask::importBooleanMask(unsigned long xdim, unsigned long ydim, unsigned long mask_xdim,
                                     unsigned long mask_ydim, unsigned long xoffset, unsigned long yoffset,
                                     string inputfile_in)
    {
        shared_ptr<SimParameters> tmp_sim_parameters = make_shared<SimParameters>();
        tmp_sim_parameters->sample_mask_file = inputfile_in;
        tmp_sim_parameters->grid_x_size = xdim;
        tmp_sim_parameters->grid_y_size = ydim;
        tmp_sim_parameters->sample_x_size = mask_xdim;
        tmp_sim_parameters->sample_y_size = mask_ydim;
        tmp_sim_parameters->sample_x_offset = xoffset;
        tmp_sim_parameters->sample_y_offset = yoffset;
        setup(tmp_sim_parameters);
        isNullSample = inputfile_in == "null" || inputfile_in == "none";
        if(!isNullSample)
        {
            doImport();
        }
    }

    void DataMask::doImport()
    {
        sample_mask.setSize(mask_y_dim, mask_x_dim);
        sample_mask.import(inputfile);
        sample_mask.close();
        completeBoolImport();
    }

    void DataMask::completeBoolImport()
    {
        mask_x_dim = sample_mask.getCols();
        mask_y_dim = sample_mask.getRows();
        getProportionfptr = &DataMask::getBoolProportion;
    }

    void DataMask::setupNull(const shared_ptr<SimParameters> mapvarin)
    {
        sample_mask.setSize(mapvarin->fine_map_y_size, mapvarin->fine_map_x_size);
        for(unsigned long i = 0; i < sample_mask.getRows(); i++)
        {
            for(unsigned long j = 0; j < sample_mask.getCols(); j++)
            {
                sample_mask.setValue(i, j, i + y_offset < mask_y_dim && j + x_offset < mask_x_dim);
            }
        }
        completeBoolImport();
    }

    void DataMask::importSampleMask(const shared_ptr<SimParameters> mapvarin)
    {
        setup(mapvarin);
        if(!checkCanUseDefault(mapvarin))
        {
            if(inputfile == "null")
            {
                setupNull(mapvarin);
            }
            else if(mapvarin->uses_spatial_sampling)
            {
#ifdef DEBUG
                writeLog(10, "Using spatial sampling.");
                writeLog(10, "Mask dimensions: " + to_string(mask_x_dim) + ", " + to_string(mask_y_dim));
#endif // DEBUG
                sample_mask_exact.setSize(mask_y_dim, mask_x_dim);
                sample_mask_exact.import(inputfile);
                sample_mask_exact.close();
                mask_x_dim = sample_mask_exact.getCols();
                mask_y_dim = sample_mask_exact.getRows();
                getProportionfptr = &DataMask::getSampleProportion;
            }
            else
            {
                doImport();
            }
        }
        else
        {
            if(mapvarin->uses_spatial_sampling)
            {
                // This could perhaps be a warning, but I'd prefer to have the warning/prohibit potential in python
                // and throw a full exception here.
                throw FatalException("Cannot use a spatial sampling routine when the map file is null.");
            }
            getProportionfptr = &DataMask::getNullProportion;
        }
    }

    bool DataMask::getVal(const long &x, const long &y, const long &xwrap, const long &ywrap) const
    {
        long xval = x + (xwrap * x_dim) + x_offset;
        long yval = y + (ywrap * y_dim) + y_offset;
        if(isNullSample)
        {
            return true;
        }
#ifdef DEBUG
        if(xval < 0 || xval >= (long) mask_x_dim || yval < 0 || yval >= (long) mask_y_dim)
        {
            stringstream ss;
            ss << "Get value on samplemask requested for non index." << endl;
            ss << "x, y: " << x << ", " << y << endl;
            ss << "dimensions x,y: " << mask_x_dim << ", " << mask_y_dim << endl;
            ss << "x, y wrap: " << xwrap << ", " << ywrap << endl;
            ss << "xval, yval: " << xval << ", " << yval << endl;
            ss << "offsets x, y: " << x_offset << ", " << y_offset << endl;
            writeLog(50, ss);
            ss.str("Get value on samplemask requested for non index.");
            throw out_of_range(ss.str());
        }
#endif
        return sample_mask.getCopy(yval, xval);
    }

    double DataMask::getNullProportion(const long &x, const long &y, const long &xwrap, const long &ywrap) const
    {
        return 1.0;
    }

    double DataMask::getBoolProportion(const long &x, const long &y, const long &xwrap, const long &ywrap) const
    {

        if(getVal(x, y, xwrap, ywrap))
        {
            return 1.0;
        }
        else
        {
            return 0.0;
        }
    }

    double DataMask::getSampleProportion(const long &x, const long &y, const long &xwrap, const long &ywrap) const
    {
#ifdef DEBUG
        if(isNullSample || sample_mask_exact.getCols() == 0)
        {
            throw out_of_range("Cannot get the exact value from a samplemask if we are using a null mask, or the "
                               "exact samplemask has not been properly imported.");
        }
#endif // DEBUG
        long xval = x + (xwrap * x_dim) + x_offset;
        long yval = y + (ywrap * y_dim) + y_offset;
        return sample_mask_exact.getCopy(yval, xval);
    }

    double DataMask::getExactValue(const long &x, const long &y, const long &xwrap, const long &ywrap) const
    {
        return (this->*getProportionfptr)(x, y, xwrap, ywrap);
    }

    void DataMask::convertBoolean(shared_ptr<Landscape> map1, const double &deme_sampling, const double &generation)
    {
        // Clear the old boolean object and set the new size
        sample_mask.setSize(y_dim, x_dim);
        for(unsigned long y = 0; y < y_dim; y++)
        {
            for(unsigned long x = 0; x < x_dim; x++)
            {
                long tmp_x = x;
                long tmp_y = y;
                long tmp_xwrap = 0;
                long tmp_ywrap = 0;
                recalculateCoordinates(tmp_x, tmp_y, tmp_xwrap, tmp_ywrap);
                double density = map1->getVal(tmp_x, tmp_y, tmp_xwrap, tmp_ywrap, generation) * deme_sampling;
                sample_mask.setValue(y, x, density >= 1.0);
            }
        }
    }

    void DataMask::clearSpatialMask()
    {
        sample_mask_exact.setSize(0, 0);
    }

    void DataMask::recalculateCoordinates(long &x, long &y, long &x_wrap, long &y_wrap)
    {
        if(isGridOffset)
        {
            x_wrap = (long) ((floor((x - (double) x_offset) / (double) x_dim)));
            y_wrap = (long) ((floor((y - (double) y_offset) / (double) y_dim)));
            x += -x_offset - (x_wrap * x_dim);
            y += -y_offset - (y_wrap * y_dim);
        }
    }
}