All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.integratedmodelling.engine.geospace.datasources.RegularRasterGridDataSource Maven / Gradle / Ivy

The newest version!
/*******************************************************************************
 *  Copyright (C) 2007, 2015:
 *  
 *    - Ferdinando Villa 
 *    - integratedmodelling.org
 *    - any other authors listed in @author annotations
 *
 *    All rights reserved. This file is part of the k.LAB software suite,
 *    meant to enable modular, collaborative, integrated 
 *    development of interoperable data and model components. For
 *    details, see http://integratedmodelling.org.
 *    
 *    This program is free software; you can redistribute it and/or
 *    modify it under the terms of the Affero General Public License 
 *    Version 3 or any later version.
 *
 *    This program is distributed in the hope that it will be useful,
 *    but without any warranty; without even the implied warranty of
 *    merchantability or fitness for a particular purpose.  See the
 *    Affero General Public License for more details.
 *  
 *     You should have received a copy of the Affero General Public License
 *     along with this program; if not, write to the Free Software
 *     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 *     The license is also available at: https://www.gnu.org/licenses/agpl.html
 *******************************************************************************/
package org.integratedmodelling.engine.geospace.datasources;

import java.util.HashMap;
import java.util.Map;

import org.integratedmodelling.api.metadata.IMetadata;
import org.integratedmodelling.api.modelling.IDataSource;
import org.integratedmodelling.api.modelling.IExtent;
import org.integratedmodelling.api.modelling.IObserver;
import org.integratedmodelling.api.modelling.IScale;
import org.integratedmodelling.api.modelling.IValueResolver;
import org.integratedmodelling.api.modelling.contextualization.IStateContextualizer;
import org.integratedmodelling.api.modelling.scheduling.ITransition;
import org.integratedmodelling.api.monitoring.IMonitor;
import org.integratedmodelling.base.HashableObject;
import org.integratedmodelling.common.configuration.KLAB;
import org.integratedmodelling.common.data.AbstractTableSet;
import org.integratedmodelling.common.metadata.Metadata;
import org.integratedmodelling.common.model.runtime.AbstractStateContextualizer;
import org.integratedmodelling.engine.geospace.Geospace;
import org.integratedmodelling.engine.geospace.coverage.ICoverage;
import org.integratedmodelling.engine.geospace.coverage.raster.AbstractRasterCoverage;
import org.integratedmodelling.engine.geospace.coverage.raster.RasterCoverage;
import org.integratedmodelling.engine.geospace.extents.Grid;
import org.integratedmodelling.engine.geospace.extents.SpaceExtent;
import org.integratedmodelling.engine.geospace.literals.ShapeValue;
import org.integratedmodelling.engine.modelling.runtime.Scale;
import org.integratedmodelling.exceptions.KlabException;
import org.integratedmodelling.exceptions.KlabRuntimeException;
import org.integratedmodelling.exceptions.KlabValidationException;

/**
 * FIXME MONITORABLE!
 * @author ferdinando.villa
 *
 */
public abstract class RegularRasterGridDataSource extends HashableObject
        implements IDataSource {

    protected ICoverage coverage     = null;
    protected Grid      finalExtent  = null;
    private IMetadata   metadata     = new Metadata();
    protected IMonitor  monitor;
    protected String    id;
    int                 errors       = 0;
    Map           valueMapping = null;
    protected boolean   isAvailable;
    protected Double    noData       = null;

    /*
     * set in specialized constructor when we supply it with a coverage that is
     * already matched to the final context of use. This happens when a datasource
     * is created to provide an accessor for another that has transformed the
     * original coverage.
     */
    private boolean     preMatched   = false;

    public RegularRasterGridDataSource() {
    }

    @Override
    public IMetadata getMetadata() {
        return metadata;
    }

    public RegularRasterGridDataSource(ICoverage coverage, Grid Grid) {
        this.coverage = coverage;
        this.finalExtent = Grid;
        this.preMatched = true;
    }

    public RegularRasterGridDataSource(ICoverage coverage, Grid Grid, double noData) {
        this.coverage = coverage;
        this.finalExtent = Grid;
        this.preMatched = true;
        this.noData = noData;
    }

    public void setValueMapping(Map mapping) {
        valueMapping = mapping;
    }

    public Object getValue(int index) {

        if (!((AbstractRasterCoverage) coverage).isLoaded()) {
            try {
                ((RasterCoverage) (this.coverage)).loadData();
            } catch (KlabException e1) {
                throw new KlabRuntimeException(e1);
            }
        }

        try {

            Object ret = coverage.getSubdivisionValue(index, finalExtent);
            if (!(ret instanceof Number))
                return ret;
            ret = ((Number) ret).doubleValue();

            /*
             * TODO/FIXME - this is already done in the coverage, although differently (just
             * comparing the value) - will never get here as it will be already a Double.NaN
             * if the same nodata values of the coverage are used.
             */
            double[] nd = ((AbstractRasterCoverage) coverage).getNodataValue();
            if (nd != null && ret != null && (ret instanceof Double)
                    && !Double.isNaN((Double) ret)) {
                for (double d : nd) {
                    if (((Double) ret).equals(d)) {
                        ret = Double.NaN;
                        break;
                    }
                }
            }
            return valueMapping == null ? ret
                    : valueMapping.get(AbstractTableSet.sanitizeKey(ret));

        } catch (KlabException e) {
            throw new KlabRuntimeException(e);
        }
    }

    @Override
    public IStateContextualizer getContextualizer(IScale context, IObserver observer, IMonitor monitor)
            throws KlabException {

        if (coverage == null) {
            coverage = readData();
        }

        if (!preMatched)
            finalExtent = getFinalExtent(context);

        return new RasterGridContextualizer(observer, monitor);
    }

    /*
     * -------------------------------------------------------------------------------------------
     * read the coverage
     * -------------------------------------------------------------------------------------------
     */

    /**
     * Do whatever is needed to instantiate the coverage.
     * @throws KlabException
     */
    protected abstract ICoverage readData() throws KlabException;

    /**
     * Return the final grid extent implied by the context. It should also validate
     * the context, ensuring we don't want multiplicity in domains where we cannot
     * provide it.
     * 
     * @param context
     * @return
     */
    protected Grid getFinalExtent(IScale context) throws KlabException {

        IExtent space = context.getSpace();

        if (!(space instanceof SpaceExtent)) {
            throw new KlabValidationException("cannot compute a raster datasource in a non-spatial context");
        }

        return ((SpaceExtent) space).getGrid() == null ? ((SpaceExtent) space).makeGrid()
                : ((SpaceExtent) space).getGrid();
    }

    /*
     * -------------------------------------------------------------------------------------------------
     * simple accessor
     * -------------------------------------------------------------------------------------------------
     */
    class RasterGridContextualizer extends AbstractStateContextualizer
            implements IValueResolver {

        IObserver observer;
        boolean   isFirst = true;

        public RasterGridContextualizer(IObserver observer, IMonitor monitor) {
            super(monitor);
            this.observer = observer;
        }

        @Override
        public String toString() {
            return "[raster " + coverage.getLayerName() + "]";
        }

        public String getName() {
            return coverage.getLayerName();
        }

        @Override
        public String getLabel() {
            return ((AbstractRasterCoverage) coverage).isRasterized()
                    ? "vector data->rasterize" : "raster data";
        }

        public String getDatasourceLabel() {
            return "[raw data from: " + coverage.getLayerName() + "]";
        }

        @Override
        public Map initialize(int index, Map inputs)
                throws KlabException {

            Map ret = new HashMap<>();
            if (isFirst && !preMatched) {
                try {
                    KLAB.info(coverage.getEnvelope() + " -> " + finalExtent);
                    coverage = coverage
                            .requireMatch(finalExtent, observer, monitor, false);
                    KLAB.info("match achieved for " + coverage.getLayerName());
                } catch (KlabException e) {
                    throw new KlabRuntimeException("error retrieving data for "
                            + getStateName() + ": "
                            + e.getMessage());
                }
                isFirst = false;
            }

            ret.put(getStateName(), RegularRasterGridDataSource.this.getValue(index));
            return ret;
        }

        @Override
        public Map compute(int index, ITransition transition, Map inputs)
                throws KlabException {
            return null;
        }

        @Override
        public boolean isProbabilistic() {
            return false;
        }

    }

    @Override
    public IScale getCoverage() {

        Scale ret = new Scale();

        try {
            coverage = readData();
        } catch (KlabException e) {
            KLAB.warn("raster data source couldn't be read: " + e.getMessage());
            if (monitor != null && errors == 0) {
                monitor.error("raster data source " + id + " is inaccessible");
                errors++;
            }
            throw new KlabRuntimeException(e);
        }

        if (coverage == null) {
            throw new KlabRuntimeException("error reading data source " + id);
        } else {

            try {
                ShapeValue shape = new ShapeValue(coverage.getEnvelope());
                shape = shape.transform(Geospace.get().getDefaultCRS());
                int x = ((AbstractRasterCoverage) coverage).getXCells();
                int y = ((AbstractRasterCoverage) coverage).getYCells();
                ret.mergeExtent(new SpaceExtent(shape, x, y), true);
            } catch (KlabException e) {
                // shouldn't happen - just in case
                if (monitor != null && errors == 0) {
                    monitor.error("raster data source " + id + " is corrupted");
                    errors++;
                }
                throw new KlabRuntimeException(e);
            }
        }

        return ret;
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy