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

org.integratedmodelling.engine.geospace.gis.MapClassifier Maven / Gradle / Ivy

The newest version!
package org.integratedmodelling.engine.geospace.gis;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.integratedmodelling.api.knowledge.IKnowledge;
import org.integratedmodelling.api.modelling.IClassification;
import org.integratedmodelling.api.modelling.IClassifyingObserver;
import org.integratedmodelling.api.modelling.INumericObserver;
import org.integratedmodelling.api.modelling.IPresenceObserver;
import org.integratedmodelling.api.modelling.IRankingObserver;
import org.integratedmodelling.api.modelling.IScale;
import org.integratedmodelling.api.modelling.IScale.Locator;
import org.integratedmodelling.api.modelling.IState;
import org.integratedmodelling.api.monitoring.IMonitor;
import org.integratedmodelling.common.classification.Classification;
import org.integratedmodelling.common.states.States;
import org.integratedmodelling.common.utils.StringUtils;

/**
 * Classifies a set of states into one map of classes corresponding to different
 * configurations, discretizing each state if necessary.
 * 
 * @author Ferd
 *
 */
public class MapClassifier {

    public class MapClass {
        /*
         * classifier N per descriptor
         */
        List classifiers;
        int           index;
        String        name;

        public int getIndex() {
            return index;
        }

        @Override
        public String toString() {
            return index + ":" + classifiers;
        }

        public double getValueOf(IKnowledge k) {
            MapDescriptor mds = stateIndex.get(k);
            if (mds == null) {
                return 0;
            }
            return ((Classification) mds.discretization).getNumericCode(classifiers.get(mds.index));
        }
    }

    class MapDescriptor {

        IState                state;
        IClassification       discretization = null;
        int                   index;
        boolean               useRanks       = false;
        Map rankMap;

        public MapDescriptor(IState s, Locator... locators) {

            this.state = s;

            if (s.getObserver() instanceof INumericObserver
                    && ((INumericObserver) s.getObserver()).getDiscretization() == null) {
                if (s.getObserver() instanceof IRankingObserver
                        && ((IRankingObserver) s.getObserver()).isInteger()) {
                    useRanks = true;
                    rankMap = new HashMap<>();
                } else {
                    this.discretization = States.discretize(s, maxBinsPerState);
                }
            } else if (s.getObserver() instanceof INumericObserver
                    && ((INumericObserver) s.getObserver()).getDiscretization() != null) {
                this.discretization = ((INumericObserver) s.getObserver()).getDiscretization();
            } else if (s.getObserver() instanceof IClassifyingObserver) {
                this.discretization = ((IClassifyingObserver) s.getObserver()).getClassification();
            } else if (s.getObserver() instanceof IPresenceObserver) {
                this.discretization = Classification.createBinary();
            }
        }

        @Override
        public String toString() {
            return "D/" + index + "/" + state.getObservable().getSemantics();
        }

        public int getClass(int offset) {

            Object o = States.get(state, offset);
            if (o == null) {
                return -1;
            }
            if (useRanks) {
                Integer n = o instanceof Number ? ((Number) o).intValue() : null;
                if (n != null) {
                    if (rankMap.containsKey(n)) {
                        return rankMap.get(n);
                    } else {
                        int newv = rankMap.size();
                        rankMap.put(n, newv);
                        return newv;
                    }
                } else {
                    return -1;
                }
            }
            return this.discretization.classifyToIndex(o);
        }
    }

    IScale                         scale;
    private List    states       = new ArrayList<>();
    private int                    maxBinsPerState;
    int[]                          index;
    private Locator[]              locators;
    Map          classCatalog = new HashMap<>();
    List                 classes      = new ArrayList<>();
    Map stateIndex   = new HashMap<>();

    /**
     * Build the necessary discretizations. Check getStatesCount() before calling
     * classify() to ensure we have at least the desired number of states.
     * 
     * @param states
     * @param maxBinsPerState
     * @param monitor
     * @param locators
     */
    public MapClassifier(Collection states, int maxBinsPerState, IMonitor monitor,
            Locator... locators) {

        this.locators = locators;
        this.maxBinsPerState = maxBinsPerState;

        int i = 0;
        for (IState s : states) {
            MapDescriptor md = new MapDescriptor(s);
            if (md.discretization != null || md.useRanks) {
                this.states.add(md);
                stateIndex.put(s.getObservable().getType(), md);
                md.index = i++;
            } else {
                monitor.warn("discretizer: state " + s.getObservable().getType()
                        + " could not be discretized");
            }
        }

        if (states.size() > 0) {
            this.scale = states.iterator().next().getScale();
        }
    }

    public int getStatesCount() {
        return this.states.size();
    }
    
    
    public int getClass(int offset) {
    	return index[offset];
    }

    public int classify() {

        IScale.Index index = scale.getIndex(locators);
        this.index = new int[index.size()];

        // prepare the fastest int array we can use as key
        List mc = new ArrayList<>();
        for (int i = 0; i < states.size(); i++) {
            mc.add(-1);
        }

        int idx = 0;
        for (int offset : index) {

            int i = 0;
            boolean nodata = false;
            for (MapDescriptor md : states) {
                int n = md.getClass(offset);
                if (n < 0) {
                    nodata = true;
                    break;
                }
                mc.set(i++, n);
            }

            this.index[idx++] = nodata ? 0 : getMapClass(mc);
        }

        return classes.size();
    }

    private int getMapClass(List mc) {

        String nnc = StringUtils.join(mc, '|');

        MapClass clas = classCatalog.get(nnc);
        if (clas == null) {
            clas = new MapClass();
            clas.classifiers = new ArrayList<>(mc);
            classes.add(clas);

            clas.index = classes.size() - 1;
            classCatalog.put(nnc, clas);
        }

        return clas.index;
    }

    public Collection getClasses() {
        return classes;
    }

    /**
     * Redistribute values inside a passed state. Pass the values in the same order as the
     * classes.
     * 
     * @param state
     * @param values
     * 
     */
    public void distributeResults(IState state, double[] values) {

        int n = 0;
        for (int i : scale.getIndex(locators)) {
            if (scale.isCovered(i)) {
                States.set(state, values[classes.get(index[n]).index], i);
            }
            n++;
        }
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy