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

org.integratedmodelling.engine.visualization.VisualizationFactory Maven / Gradle / Ivy

There is a newer version: 0.9.10
Show 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.visualization;

import java.io.File;
import java.io.IOException;
import java.text.NumberFormat;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.commons.io.FileUtils;
import org.integratedmodelling.api.data.IProbabilityDistribution;
import org.integratedmodelling.api.knowledge.IConcept;
import org.integratedmodelling.api.modelling.IClassification;
import org.integratedmodelling.api.modelling.IMeasuringObserver;
import org.integratedmodelling.api.modelling.IObservation;
import org.integratedmodelling.api.modelling.IScale;
import org.integratedmodelling.api.modelling.IScale.Locator;
import org.integratedmodelling.api.modelling.IState;
import org.integratedmodelling.api.modelling.ISubject;
import org.integratedmodelling.api.modelling.visualization.IMedia;
import org.integratedmodelling.api.modelling.visualization.IViewport;
import org.integratedmodelling.api.modelling.visualization.IVisualizationFactory;
import org.integratedmodelling.common.beans.responses.ValueSummary;
import org.integratedmodelling.common.data.IndexedCategoricalDistribution;
import org.integratedmodelling.common.owl.Knowledge;
import org.integratedmodelling.common.states.State;
import org.integratedmodelling.common.storage.ProbabilityStorage;
import org.integratedmodelling.common.visualization.Viewport;
import org.integratedmodelling.engine.geospace.Geospace;
import org.integratedmodelling.engine.time.Time;
import org.integratedmodelling.exceptions.KlabException;
import org.integratedmodelling.exceptions.KlabIOException;
import org.integratedmodelling.exceptions.KlabRuntimeException;
import org.springframework.http.MediaType;

import com.google.common.primitives.Doubles;

public class VisualizationFactory extends
        org.integratedmodelling.common.visualization.VisualizationFactory implements
        IVisualizationFactory {

    private static VisualizationFactory _this = null;

    public static VisualizationFactory get() {
        if (_this == null) {
            _this = new VisualizationFactory();
        }
        return _this;
    }

    public double[] getStateDataAsNumbers(IState state, Iterable locators) {

        double[] ret = new double[(int) state.getValueCount()];
        IClassification classification = getClassification(state);
        List ls = new ArrayList<>();
        for (IScale.Locator l : locators) {
            ls.add(l);
        }

        for (int n : state.getScale().getIndex(ls.toArray(new Locator[ls.size()]))) {

            /**
             * If a specific extent offset is needed, e.g. the offset in space, the
             * following can be used, which will return the spatial offset for the given
             * overall offset. The reason for not having specific getSpatialOffset() or
             * getTemporalOffset is that there can be additional extents beyond time and
             * space, although these are not used at the moment.
             */
            int i = state.getScale().getExtentOffset(state.getScale().getSpace(), n);
            Double d = Double.NaN;
            Object o = ((State) state).getValue(n);

            if (o instanceof Number) {
                d = ((Number) o).doubleValue();
            } else if (o instanceof IndexedCategoricalDistribution) {
                d = ((IndexedCategoricalDistribution) o).getMean();
            } else if (o instanceof Boolean) {
                d = ((Boolean) o) ? 1.0 : 0.0;
            } else if (o instanceof IConcept) {
                if (classification != null) {
                    d = classification.getNumericCode((IConcept) o);
                }
            } else if (o != null) {
                throw new KlabRuntimeException("internal: unexpected state value in VisualizationFactory.getStateData");
            }

            ret[i] = d;
        }

        return ret;
    }

    public double[] getStateDataAsNumbers(IState state) {

        double[] ret = new double[(int) state.getValueCount()];
        IClassification classification = getClassification(state);

        for (int i = 0; i < state.getValueCount(); i++) {

            Double d = Double.NaN;
            Object o = ((State) state).getValue(i);

            if (o instanceof Number) {
                d = ((Number) o).doubleValue();
            } else if (o instanceof IndexedCategoricalDistribution) {
                d = ((IndexedCategoricalDistribution) o).getMean();
            } else if (o instanceof Boolean) {
                d = ((Boolean) o) ? 1.0 : 0.0;
            } else if (o instanceof IConcept) {
                if (classification != null) {
                    d = classification.getNumericCode((IConcept) o);
                }
            } else if (o != null) {
                throw new KlabRuntimeException("internal: unexpected state value in VisualizationFactory.getStateData");
            }

            ret[i] = d;
        }

        return ret;
    }

    public float[] getStateDataAsFloats(IState state) {

        float[] ret = new float[(int) state.getValueCount()];
        for (int i = 0; i < state.getValueCount(); i++) {

            Double d = Double.NaN;
            Object o = ((State) state).getValue(i);

            if (o instanceof Number) {
                d = ((Number) o).doubleValue();
            } else if (o instanceof IndexedCategoricalDistribution) {
                d = ((IndexedCategoricalDistribution) o).getMean();
            } else if (o instanceof Boolean) {
                d = ((Boolean) o) ? 1.0 : 0.0;
            } else if (o != null) {
                throw new KlabRuntimeException("internal: unexpected state value in VisualizationFactory.getStateData");
            }

            ret[i] = d.floatValue();
        }

        return ret;
    }

    @Override
    public IMedia getMedia(IObservation observation, IScale.Index index, IViewport viewport, String mimeType, Map options) {

        MediaType type = MediaType.valueOf(mimeType);

        if (type.isCompatibleWith(MediaType.IMAGE_PNG)) {
            return new ImageMedia(observation, index, viewport, type, options);
        }
        return null;
    }

    public void persist(IObservation obs, File file, boolean isVideo, Object... options)
            throws KlabException {

        /*
         * parse back options. TODO may assume that anything else is a key,value pair for
         * the media that take it, but for now let's skip the painful coding.
         */
        List locators = new ArrayList<>();
        Viewport viewport = null;

        for (Object o : options) {
            if (o instanceof IScale.Locator) {
                locators.add((Locator) o);
            } else if (o instanceof Viewport) {
                viewport = (Viewport) o;
            }
        }

        if (isVideo) {
            if (obs instanceof IState && obs.getScale().isSpatiallyDistributed()
                    && obs.getScale().isTemporallyDistributed()) {
                VideoMedia vm = new VideoMedia(obs, viewport, null);
                try {
                    FileUtils.copyFile(vm.getFile(), file);
                } catch (IOException e) {
                    throw new KlabIOException(e);
                }
            }
        } else {
            if (obs instanceof IState) {
                if (obs.getScale().isSpatiallyDistributed()) {
                    Geospace.get().persistState((IState) obs, file, locators);
                } else if (obs.getScale().isTemporallyDistributed()) {
                    Time.get().persistState((IState) obs, file, locators);
                }

            } else if (obs instanceof ISubject) {
                if (obs.getScale().isSpatiallyDistributed()) {
                    Geospace.get().persistSubject((ISubject) obs, file);
                }
            }
        }
    }

    public ValueSummary describeValue(IState state, Object o) {

        ValueSummary ret = new ValueSummary();

        if (o == null || (o instanceof Double && Double.isNaN((Double) o))) {
            o = "No data";
        } else if (o instanceof IndexedCategoricalDistribution) {

            ret.setDistribution(Doubles.asList(((IndexedCategoricalDistribution) o).getData()));
            ret.setRanges(Doubles.asList(((IndexedCategoricalDistribution) o).getRanges()));
            ret.setUncertainty(((IndexedCategoricalDistribution) o).getUncertainty());

            if (state.getStorage() instanceof ProbabilityStorage) {
                IConcept likelyClass = ((ProbabilityStorage) state.getStorage())
                        .getMostLikelyClass((IProbabilityDistribution) o);
                if (likelyClass != null) {
                    ret.setMostLikelyClass(((Knowledge) likelyClass).asText());
                }
            }

            o = "m=" +
                    NumberFormat.getInstance().format(((IndexedCategoricalDistribution) o).getMean())
                    + ", s=" +
                    NumberFormat.getInstance().format(((IndexedCategoricalDistribution) o).getUncertainty());

        } else if (o instanceof Boolean) {
            o = state.getObservable().getType().getLocalName() + ((Boolean) o ? " present" : " absent");
        } else if (o instanceof IConcept) {
            o = ((IConcept) o).getLocalName();
        } else if (o instanceof Number) {
            o = NumberFormat.getInstance().format(o);
        } else {
            o = o.toString();
        }

        if (state.getObserver() instanceof IMeasuringObserver) {
            o = o + " " + ((IMeasuringObserver) state.getObserver()).getUnit();
        }

        ret.setDescription(o.toString());
        return ret;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy