diff --git a/src/main/java/org/gcube/contentmanagement/graphtools/plotting/graphs/TransectLineGraph.java b/src/main/java/org/gcube/contentmanagement/graphtools/plotting/graphs/TransectLineGraph.java index af94f93..a877a3e 100644 --- a/src/main/java/org/gcube/contentmanagement/graphtools/plotting/graphs/TransectLineGraph.java +++ b/src/main/java/org/gcube/contentmanagement/graphtools/plotting/graphs/TransectLineGraph.java @@ -45,7 +45,10 @@ import java.awt.Color; import java.awt.Font; import java.awt.Graphics2D; import java.awt.geom.Rectangle2D; +import java.text.ParseException; +import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Date; import java.util.List; import org.gcube.contentmanagement.graphtools.abstracts.GenericStandaloneGraph; @@ -323,6 +326,58 @@ public class TransectLineGraph extends GenericStandaloneGraph { return new TransectLineGraph(title); } + + public static Date calcAnnotationTime(String annotation, String timepattern){ + String time = annotation.substring(0,annotation.indexOf(";")); + Date timeD = null; + try { + timeD = new SimpleDateFormat(timepattern).parse(time); + } catch (ParseException e) { + } + return timeD; + } + public static DefaultCategoryDataset orderByTime(DefaultCategoryDataset annotatedTimeChart, String timepattern){ + + DefaultCategoryDataset orderedChart = new DefaultCategoryDataset(); + if (annotatedTimeChart==null) + return orderedChart; + + List values = new ArrayList(); + List annotations= new ArrayList(); + List dates = new ArrayList(); + + int ncols = annotatedTimeChart.getColumnCount(); + //suppose there is only one time series here + String rowkey = annotatedTimeChart.getRowKeys().get(0).toString(); + + for (int i=0;i producedImages = new HashMap(); - public boolean displaycharts = true; - static int maxSeries = 10; + protected static String inputTableParameter = "InputTable"; + protected static String attributesParameter = "Attributes"; + protected static String quantitiesParameter = "Quantities"; + protected static String timeParameter = "Time"; + protected static String topElementsNumber = "TopElementsNumber"; + + public LinkedHashMap producedImages = new LinkedHashMap(); + public LinkedHashMap producedFiles = new LinkedHashMap(); + public boolean displaycharts = false; + protected int maxElements = 10; - SessionFactory connection = null; + protected SessionFactory connection = null; @Override protected abstract void setInputParameters(); @Override public StatisticalType getOutput() { - PrimitiveType images = new PrimitiveType(HashMap.class.getName(), producedImages, PrimitiveTypes.IMAGES, "images", "Charts"); LinkedHashMap outputmap = new LinkedHashMap(); - outputmap.put("Images", images); - + if (producedImages.size()>0){ + PrimitiveType images = new PrimitiveType(HashMap.class.getName(), producedImages, PrimitiveTypes.IMAGES, "images", "Charts"); + outputmap.put("Images", images); + } + if (producedFiles.size()>0){ + for (String file:producedFiles.keySet()){ + File f = producedFiles.get(file); + PrimitiveType p = new PrimitiveType(File.class.getName(), f, PrimitiveTypes.FILE, f.getName(), file); + outputmap.put(file, p); + } + } PrimitiveType output = new PrimitiveType(HashMap.class.getName(), outputmap, PrimitiveTypes.MAP, "ResultsMap", "Results Map"); return output; } @@ -64,7 +74,10 @@ public abstract class AbstractChartsProducer extends StandardLocalExternalAlgori public String[] getQuantities() { String quantitieS = IOHelper.getInputParameter(config, quantitiesParameter); - String[] quantities = quantitieS.split(AlgorithmConfiguration.getListSeparator()); + String[] quantities = {""}; + if (quantitieS!=null){ + quantities = quantitieS.split(AlgorithmConfiguration.getListSeparator()); + } return quantities; } @@ -76,24 +89,26 @@ public abstract class AbstractChartsProducer extends StandardLocalExternalAlgori public String InfoRetrievalQuery(String table, String[] dimensions, String quantity,String time) { if (time!=null){ if (dimensions!=null && dimensions.length>0) - return "select * from (select distinct " + Arrays.toString(dimensions).replace("[", "").replace("]", "") + " , " + quantity +","+time+" from "+table+" order by " + quantity + " limit " + maxSeries+") as a order by "+time; + return "select distinct " + Arrays.toString(dimensions).replace("[", "").replace("]", "") + " , " + quantity +" as qa123a,"+time+" as timea123a from "+table+" order by timea123a"; else - return "select * from (select distinct " +quantity +","+time+" from "+table+" order by " + quantity + " limit " + maxSeries+") as a order by "+time; + return "select distinct " +quantity +","+time+" from "+table+" order by "+time; } else{ - if (dimensions!=null && dimensions.length>0) - return "select distinct " + Arrays.toString(dimensions).replace("[", "").replace("]", "") + " , " + quantity +" from "+table+" order by " + quantity + " limit " + maxSeries; + try{maxElements = Integer.parseInt(IOHelper.getInputParameter(config, topElementsNumber));}catch(Exception e){} + if (dimensions!=null && dimensions.length>0){ + String field = Arrays.toString(dimensions).replace("[", "").replace("]", ""); + return "select distinct " +field + " , sum(CAST (" + quantity +" as real)) as qa123a from "+table+" where CAST("+quantity+" as character varying) <>'' "+" group by "+field+" order by qa123a DESC limit " + maxElements; + } else - return "select distinct row_number() over(), " + quantity +" from "+table+" order by " + quantity + " limit " + maxSeries; + return "select distinct row_number() over(), " + quantity +" from "+table+" order by " + quantity + " DESC limit " + maxElements; } } @Override protected void process() throws Exception { - status = 0; + status = 10; AnalysisLogger.setLogger(config.getConfigPath() + AlgorithmConfiguration.defaultLoggerFile); - long t0 = System.currentTimeMillis(); try { AnalysisLogger.getLogger().debug("ChartsProducer started"); String driver = config.getParam("DatabaseDriver"); @@ -118,33 +133,51 @@ public abstract class AbstractChartsProducer extends StandardLocalExternalAlgori String[] quantities = getQuantities(); String time = getTimeDimension(); - //one quantity for each chart + //one quantity for each chart + boolean noCharts = true; + status = 40; + float step = (90-status)/(float)quantities.length; for (String quantity : quantities) { //produce chart with dimensions,quantity, time String query = InfoRetrievalQuery(table,dimensions,quantity,time); AnalysisLogger.getLogger().debug("ChartsProducer: Query for retrieving information "+query); List values = DatabaseFactory.executeSQLQuery(query, connection); - JFreeChart[] charts= createCharts(dimensions,quantity,time,values,displaycharts); - for (JFreeChart chart:charts){ + if (values==null) + throw new Exception("There are issued in managing selected attributes and quantities"); + else if (values.size()==0) + throw new Exception("There are no viable values to be processed"); + + LinkedHashMap charts= createCharts(dimensions,quantity,time,values,displaycharts); + + for (String chartName:charts.keySet()){ + Object chart = charts.get(chartName); if (chart!=null){ - Image image= ImageTools.toImage(chart.createBufferedImage(680, 420)); - producedImages.put("Charts focused on "+quantity, image); + noCharts=false; + //patch for current SM visualization + if (chart instanceof File) + producedFiles.put("Chart focused on "+quantity+" - "+chartName, (File)chart); + else + producedImages.put("Chart focused on "+quantity+" - "+chartName, (Image)chart); } } + + status+=step; } - + if (noCharts) + throw new Exception("Error - no chart was produced because of incompatibility with the selected input parameters"); + AnalysisLogger.getLogger().debug("ChartsProducer: finished"); } catch (Throwable e) { e.printStackTrace(); - throw new Exception(e.getMessage()); + throw new Exception("Error during the computation: "+e.getMessage()); } finally { shutdown(); status = 100; } } - public abstract JFreeChart[] createCharts(String[] dimensions,String quantity,String time,List rows, boolean displaychart); + public abstract LinkedHashMap createCharts(String[] dimensions,String quantity,String time,List rows, boolean displaychart); @Override diff --git a/src/main/java/org/gcube/dataanalysis/ecoengine/transducers/charts/QuantitiesAttributesChartsTransducerer.java b/src/main/java/org/gcube/dataanalysis/ecoengine/transducers/charts/QuantitiesAttributesChartsTransducerer.java index 7abd4a9..16ccb1b 100644 --- a/src/main/java/org/gcube/dataanalysis/ecoengine/transducers/charts/QuantitiesAttributesChartsTransducerer.java +++ b/src/main/java/org/gcube/dataanalysis/ecoengine/transducers/charts/QuantitiesAttributesChartsTransducerer.java @@ -1,8 +1,11 @@ package org.gcube.dataanalysis.ecoengine.transducers.charts; +import java.awt.Image; import java.util.ArrayList; +import java.util.LinkedHashMap; import java.util.List; +import org.gcube.contentmanagement.graphtools.data.conversions.ImageTools; import org.gcube.contentmanagement.graphtools.plotting.graphs.GaussianDistributionGraph; import org.gcube.contentmanagement.graphtools.plotting.graphs.HistogramGraph; import org.gcube.contentmanagement.graphtools.plotting.graphs.RadarGraph; @@ -15,7 +18,6 @@ import org.gcube.dataanalysis.ecoengine.datatypes.DatabaseType; import org.gcube.dataanalysis.ecoengine.datatypes.InputTable; import org.gcube.dataanalysis.ecoengine.datatypes.enumtypes.TableTemplates; import org.gcube.dataanalysis.ecoengine.utils.IOHelper; -import org.jfree.chart.JFreeChart; import org.jfree.data.category.DefaultCategoryDataset; import org.jfree.data.function.NormalDistributionFunction2D; import org.jfree.data.general.DatasetUtilities; @@ -24,7 +26,6 @@ import org.jfree.data.xy.XYSeriesCollection; public class QuantitiesAttributesChartsTransducerer extends AbstractChartsProducer { - @Override protected void setInputParameters() { List templates = new ArrayList(); @@ -33,6 +34,7 @@ public class QuantitiesAttributesChartsTransducerer extends AbstractChartsProduc inputs.add(tinput); ColumnTypesList p1 = new ColumnTypesList(inputTableParameter, attributesParameter, "The dimensions to consider in the charts", true); ColumnTypesList p2 = new ColumnTypesList(inputTableParameter, quantitiesParameter, "The numeric quantities to visualize ", false); + IOHelper.addIntegerInput(inputs, topElementsNumber, "Max number of elements, with highest values, to visualize", "10"); inputs.add(p1); inputs.add(p2); @@ -45,7 +47,7 @@ public class QuantitiesAttributesChartsTransducerer extends AbstractChartsProduc } @Override - public JFreeChart[] createCharts(String[] dimensions, String quantity, String time, List rows, boolean displaychart) { + public LinkedHashMap createCharts(String[] dimensions, String quantity, String time, List rows, boolean displaychart) { if (dimensions==null) dimensions=new String[0]; @@ -74,8 +76,19 @@ public class QuantitiesAttributesChartsTransducerer extends AbstractChartsProduc } - List meanvar = DatabaseFactory.executeSQLQuery("select avg("+quantity+"), variance("+quantity+") from "+IOHelper.getInputParameter(config, inputTableParameter), connection); - Object[] meanvarsrow = (Object[]) meanvar.get(0); +// List meanvar = DatabaseFactory.executeSQLQuery("select avg("+"( CAST ( " + quantity + " as real))"+"), variance("+"( CAST ( " + quantity + " as real))"+") from "+IOHelper.getInputParameter(config, inputTableParameter), connection); + String selectMeanVar = "select avg(( CAST ( "+quantity+" as real))), variance(( CAST ( "+quantity+" as real))) from (select "+quantity+" from "+IOHelper.getInputParameter(config, inputTableParameter)+" where "+quantity+" IS NOT NULL and CAST("+quantity+" as character varying) <> '' ) as a"; + AnalysisLogger.getLogger().debug("QuantitiesAttributesCharts: select for mean and variance: "+selectMeanVar); + List meanvar = DatabaseFactory.executeSQLQuery(selectMeanVar, connection); + + + Object[] meanvarsrow = {0,0.1}; + + try{ + meanvarsrow = (Object[]) meanvar.get(0);}catch(Exception e){ + AnalysisLogger.getLogger().debug("QuantitiesAttributesCharts: cannot detect mean and variance for "+quantity); + } + double mean = MathFunctions.roundDecimal(Double.parseDouble(""+meanvarsrow[0]),2); double variance = MathFunctions.roundDecimal(Math.sqrt(Double.parseDouble(""+meanvarsrow[1])),2); @@ -86,17 +99,17 @@ public class QuantitiesAttributesChartsTransducerer extends AbstractChartsProduc XYSeriesCollection gaussianxyseriescollection = new XYSeriesCollection(); gaussianxyseriescollection .addSeries(gaussianxyseries); - JFreeChart charthisto = null; - JFreeChart chartscattering = null; - JFreeChart chartradar = null; + Image charthisto = null; + Image chartscattering = null; + Image chartradar = null; if (dimensions.length>0){ - charthisto = HistogramGraph.createStaticChart(datasetHisto); - chartscattering = ScatterGraphGeneric.createStaticChart(datasetHisto); - chartradar = RadarGraph.createStaticChart(datasetHisto); + charthisto = ImageTools.toImage(HistogramGraph.createStaticChart(datasetHisto).createBufferedImage(1200, 960)); + chartscattering = ImageTools.toImage(ScatterGraphGeneric.createStaticChart(datasetHisto).createBufferedImage(1200, 960)); + chartradar = ImageTools.toImage(RadarGraph.createStaticChart(datasetHisto).createBufferedImage(1200, 960)); } - JFreeChart chartgaussian = GaussianDistributionGraph.createStaticChart(gaussianxyseriescollection, mean, variance); + Image chartgaussian = ImageTools.toImage(GaussianDistributionGraph.createStaticChart(gaussianxyseriescollection, mean, variance).createBufferedImage(1200, 960)); if (displaychart){ HistogramGraph tsg = new HistogramGraph("QuantitiesAttributesHistogram"); @@ -115,11 +128,12 @@ public class QuantitiesAttributesChartsTransducerer extends AbstractChartsProduc } - JFreeChart [] charts = new JFreeChart[4]; - charts [0] = charthisto; - charts [1] = chartscattering; - charts [2] = chartradar; - charts [3] = chartgaussian; + LinkedHashMap charts = new LinkedHashMap(); + charts.put("Histogram of the top ten quantities over the dimensions", charthisto); + charts.put("Scattering of the top ten quantities over the dimensions", chartscattering); + charts.put("Radar chart of the top ten quantities over the dimensions", chartradar); + charts.put("Overall mean and standard deviation of the quantity", chartgaussian); + return charts; } diff --git a/src/main/java/org/gcube/dataanalysis/ecoengine/transducers/charts/TimeSeriesChartsTransducerer.java b/src/main/java/org/gcube/dataanalysis/ecoengine/transducers/charts/TimeSeriesChartsTransducerer.java index f880bfc..783571c 100644 --- a/src/main/java/org/gcube/dataanalysis/ecoengine/transducers/charts/TimeSeriesChartsTransducerer.java +++ b/src/main/java/org/gcube/dataanalysis/ecoengine/transducers/charts/TimeSeriesChartsTransducerer.java @@ -1,57 +1,72 @@ package org.gcube.dataanalysis.ecoengine.transducers.charts; +import java.awt.Image; import java.text.ParseException; import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.Arrays; import java.util.Date; +import java.util.LinkedHashMap; import java.util.List; -import org.gcube.contentmanagement.graphtools.plotting.graphs.LineGraph; +import org.gcube.contentmanagement.graphtools.data.conversions.ImageTools; import org.gcube.contentmanagement.graphtools.plotting.graphs.TimeSeriesGraph; import org.gcube.contentmanagement.graphtools.plotting.graphs.TransectLineGraph; import org.gcube.contentmanagement.graphtools.utils.DateGuesser; import org.gcube.contentmanagement.lexicalmatcher.utils.AnalysisLogger; import org.gcube.dataanalysis.ecoengine.datatypes.ColumnType; -import org.jfree.chart.JFreeChart; +import org.gcube.dataanalysis.ecoengine.datatypes.ColumnTypesList; +import org.gcube.dataanalysis.ecoengine.datatypes.DatabaseType; +import org.gcube.dataanalysis.ecoengine.datatypes.InputTable; +import org.gcube.dataanalysis.ecoengine.datatypes.enumtypes.TableTemplates; +import org.gcube.dataanalysis.ecoengine.utils.Operations; +import org.gcube.dataanalysis.ecoengine.utils.TimeAnalyzer; import org.jfree.data.category.DefaultCategoryDataset; import org.jfree.data.time.FixedMillisecond; import org.jfree.data.time.TimeSeries; import org.jfree.data.time.TimeSeriesCollection; - -import com.sun.org.apache.bcel.internal.generic.LNEG; +import org.jfree.data.time.TimeSeriesDataItem; public class TimeSeriesChartsTransducerer extends QuantitiesAttributesChartsTransducerer { @Override protected void setInputParameters() { - super.setInputParameters(); - ColumnType p = new ColumnType(inputTableParameter, timeParameter, "The column containing time information", "year", false); - inputs.add(p); + List templates = new ArrayList(); + templates.add(TableTemplates.GENERIC); + InputTable tinput = new InputTable(templates, inputTableParameter, "The input table"); + inputs.add(tinput); + ColumnTypesList p1 = new ColumnTypesList(inputTableParameter, attributesParameter, "The dimensions to consider in the charts", true); + ColumnTypesList p2 = new ColumnTypesList(inputTableParameter, quantitiesParameter, "The numeric quantities to visualize ", false); + inputs.add(p1); + inputs.add(p2); + ColumnType p3 = new ColumnType(inputTableParameter, timeParameter, "The column containing time information", "year", false); + inputs.add(p3); + DatabaseType.addDefaultDBPars(inputs); } @Override public String getDescription() { - return "An algorithm producing time series charts of attributes vs. quantities. Charts are displayed per quantity column and only the top ten quantities are reported."; + return "An algorithm producing time series charts of attributes vs. quantities. Charts are displayed per quantity column and superposing quantities are summed."; } - String timepattern = ""; - SimpleDateFormat formatter = null; - Date sampleTime = null; + protected String timepattern = ""; + protected SimpleDateFormat formatter = null; + protected Date sampleTime = null; + protected int maxvisualizable = 100; public Date getTime(String timel) { - timel = timel.replace("time:", ""); try { - if (formatter == null) { - timepattern = DateGuesser.getPattern(timel); - AnalysisLogger.getLogger().debug("Time pattern: " + timepattern); + TimeAnalyzer analyzer = new TimeAnalyzer(); + sampleTime = analyzer.string2Date(timel); + timepattern = analyzer.getPattern(); + AnalysisLogger.getLogger().debug("TimeSeriesChart: Time pattern: " + timepattern); formatter = new SimpleDateFormat(timepattern); - sampleTime = formatter.parse(timel); } return formatter.parse(timel); } catch (ParseException e) { - e.printStackTrace(); + AnalysisLogger.getLogger().debug("Error parsing date " + timel + " using pattern " + timepattern); return null; } } @@ -69,14 +84,16 @@ public class TimeSeriesChartsTransducerer extends QuantitiesAttributesChartsTran } @Override - public JFreeChart[] createCharts(String[] dimensions, String quantity, String time, List rows, boolean displaychart) { + public LinkedHashMap createCharts(String[] dimensions, String quantity, String time, List rows, boolean displaychart) { - if (dimensions==null) + if (dimensions == null) dimensions = new String[0]; - + + LinkedHashMap charts = new LinkedHashMap(); + TimeSeriesCollection dataset = new TimeSeriesCollection(); TimeSeries series = null; - if (dimensions.length>0) + if (dimensions.length > 0) series = new TimeSeries("Trend of " + quantity + " for " + Arrays.toString(dimensions).replace("[", "").replace("]", "")); else series = new TimeSeries("Trend of " + quantity); @@ -84,8 +101,19 @@ public class TimeSeriesChartsTransducerer extends QuantitiesAttributesChartsTran DefaultCategoryDataset[] linedatasets = new DefaultCategoryDataset[dimensions.length]; - for (Object row : rows) { + int nrows = rows.size(); + int[] indicesToTake = null; + if (nrows > maxvisualizable) + indicesToTake = Operations.uniformIntegerSampling(0, nrows - 1, maxvisualizable); + else + indicesToTake = Operations.uniformIntegerSampling(0, nrows - 1, nrows); + + AnalysisLogger.getLogger().debug("TimeSeriesChartsTransducerer: uniform sampling - taking " + indicesToTake.length + " over " + nrows); + + for (int i = 0; i < indicesToTake.length; i++) { + Object row = rows.get(indicesToTake[i]); Object[] array = (Object[]) row; + // AnalysisLogger.getLogger().debug("TimeSeriesChartsTransducerer: "+Arrays.toString(array)); Double q = null; Date timeD = null; String timel = "" + array[array.length - 1]; @@ -93,45 +121,54 @@ public class TimeSeriesChartsTransducerer extends QuantitiesAttributesChartsTran q = Double.parseDouble("" + array[array.length - 2]); timeD = getTime(timel); } catch (Exception e) { + AnalysisLogger.getLogger().debug("TimeSeriesChartsTransducerer: warning skipping value " + q + "," + timel); } if (q != null && timeD != null) { FixedMillisecond ms = new FixedMillisecond(timeD); - series.add(ms, q); + TimeSeriesDataItem item = series.getDataItem(ms); + if (item != null) { + double prevquant = (Double) item.getValue(); + q = prevquant + q; + AnalysisLogger.getLogger().debug("TimeSeriesChartsTransducerer: a previous quantity was found for time " + timel + " : " + prevquant + " setting to " + (prevquant + q)); + item.setValue(q); + } else + series.add(ms, q); - for (int dimIdx=0;dimIdx 0) { DefaultCategoryDataset lineds = linedatasets[dimIdx]; - if (lineds == null){ + if (lineds == null) { lineds = new DefaultCategoryDataset(); - linedatasets[dimIdx]=lineds; + linedatasets[dimIdx] = lineds; } lineds.addValue(q, "singlets", timel + ";[" + dimensionValue + "]"); } } } } + if (sampleTime != null) { + Image chartTS = ImageTools.toImage(TimeSeriesGraph.createStaticChart(dataset, getChartPattern(sampleTime), "Variation of " + quantity).createBufferedImage(1200, 960)); - JFreeChart chartTS = TimeSeriesGraph.createStaticChart(dataset, getChartPattern(sampleTime), "Variations of " + quantity); - - if (displaychart) { - TimeSeriesGraph tsg = new TimeSeriesGraph("Variations of " + quantity); - tsg.timeseriesformat = getChartPattern(sampleTime); - tsg.render(dataset); - for (int i = 0; i < dimensions.length; i++) { - TransectLineGraph tlg = new TransectLineGraph("Variations of " + dimensions[i]); - tlg.render(linedatasets[i]); + if (displaychart) { + TimeSeriesGraph tsg = new TimeSeriesGraph("Variation of " + quantity); + tsg.timeseriesformat = getChartPattern(sampleTime); + tsg.render(dataset); + for (int i = 0; i < dimensions.length; i++) { + TransectLineGraph tlg = new TransectLineGraph("Variation of " + dimensions[i]); + tlg.render(TransectLineGraph.orderByTime(linedatasets[i], timepattern)); + } } - } - JFreeChart[] charts = new JFreeChart[1 + dimensions.length]; - charts[0] = chartTS; - for (int i = 0; i < dimensions.length; i++) { - JFreeChart linechartTS = LineGraph.createStaticChart(linedatasets[i], "Variations of " + dimensions[i]); - charts[i+1] = linechartTS; + charts.put("Time trend of " + quantity, chartTS); + + for (int i = 0; i < dimensions.length; i++) { + Image linechartTS = ImageTools.toImage(TransectLineGraph.createStaticChart(TransectLineGraph.orderByTime(linedatasets[i], timepattern)).createBufferedImage(1200, 960)); + charts.put("Annotated chart of " + quantity + " for " + dimensions[i], linechartTS); + } } return charts; } diff --git a/src/main/java/org/gcube/dataanalysis/ecoengine/utils/GifSequenceWriter.java b/src/main/java/org/gcube/dataanalysis/ecoengine/utils/GifSequenceWriter.java new file mode 100644 index 0000000..53ac2f6 --- /dev/null +++ b/src/main/java/org/gcube/dataanalysis/ecoengine/utils/GifSequenceWriter.java @@ -0,0 +1,191 @@ +package org.gcube.dataanalysis.ecoengine.utils; +// +// GifSequenceWriter.java +// +// Created by Elliot Kroo on 2009-04-25. +// +// This work is licensed under the Creative Commons Attribution 3.0 Unported +// License. To view a copy of this license, visit +// http://creativecommons.org/licenses/by/3.0/ or send a letter to Creative +// Commons, 171 Second Street, Suite 300, San Francisco, California, 94105, USA. + + +import java.awt.image.BufferedImage; +import java.awt.image.RenderedImage; +import java.io.File; +import java.io.IOException; +import java.util.Iterator; +import java.util.List; + +import javax.imageio.IIOException; +import javax.imageio.IIOImage; +import javax.imageio.ImageIO; +import javax.imageio.ImageTypeSpecifier; +import javax.imageio.ImageWriteParam; +import javax.imageio.ImageWriter; +import javax.imageio.metadata.IIOMetadata; +import javax.imageio.metadata.IIOMetadataNode; +import javax.imageio.stream.FileImageOutputStream; +import javax.imageio.stream.ImageOutputStream; + +public class GifSequenceWriter { + protected ImageWriter gifWriter; + protected ImageWriteParam imageWriteParam; + protected IIOMetadata imageMetaData; + + /** + * Creates a new GifSequenceWriter + * + * @param outputStream the ImageOutputStream to be written to + * @param imageType one of the imageTypes specified in BufferedImage + * @param timeBetweenFramesMS the time between frames in miliseconds + * @param loopContinuously wether the gif should loop repeatedly + * @throws IIOException if no gif ImageWriters are found + * + * @author Elliot Kroo (elliot[at]kroo[dot]net) + */ + public GifSequenceWriter( + ImageOutputStream outputStream, + int imageType, + int timeBetweenFramesMS, + boolean loopContinuously) throws IIOException, IOException { + // my method to create a writer + gifWriter = getWriter(); + imageWriteParam = gifWriter.getDefaultWriteParam(); + ImageTypeSpecifier imageTypeSpecifier = + ImageTypeSpecifier.createFromBufferedImageType(imageType); + + imageMetaData = + gifWriter.getDefaultImageMetadata(imageTypeSpecifier, + imageWriteParam); + + String metaFormatName = imageMetaData.getNativeMetadataFormatName(); + + IIOMetadataNode root = (IIOMetadataNode) + imageMetaData.getAsTree(metaFormatName); + + IIOMetadataNode graphicsControlExtensionNode = getNode( + root, + "GraphicControlExtension"); + + graphicsControlExtensionNode.setAttribute("disposalMethod", "none"); + graphicsControlExtensionNode.setAttribute("userInputFlag", "FALSE"); + graphicsControlExtensionNode.setAttribute( + "transparentColorFlag", + "FALSE"); + graphicsControlExtensionNode.setAttribute( + "delayTime", + Integer.toString(timeBetweenFramesMS / 10)); + graphicsControlExtensionNode.setAttribute( + "transparentColorIndex", + "0"); + + IIOMetadataNode commentsNode = getNode(root, "CommentExtensions"); + commentsNode.setAttribute("CommentExtension", "Created by MAH"); + + IIOMetadataNode appEntensionsNode = getNode( + root, + "ApplicationExtensions"); + + IIOMetadataNode child = new IIOMetadataNode("ApplicationExtension"); + + child.setAttribute("applicationID", "NETSCAPE"); + child.setAttribute("authenticationCode", "2.0"); + + int loop = loopContinuously ? 0 : 1; + + child.setUserObject(new byte[]{ 0x1, (byte) (loop & 0xFF), (byte) + ((loop >> 8) & 0xFF)}); + appEntensionsNode.appendChild(child); + + imageMetaData.setFromTree(metaFormatName, root); + + gifWriter.setOutput(outputStream); + + gifWriter.prepareWriteSequence(null); + } + + public void writeToSequence(RenderedImage img) throws IOException { + gifWriter.writeToSequence( + new IIOImage( + img, + null, + imageMetaData), + imageWriteParam); + } + + /** + * Close this GifSequenceWriter object. This does not close the underlying + * stream, just finishes off the GIF. + */ + public void close() throws IOException { + gifWriter.endWriteSequence(); + } + + /** + * Returns the first available GIF ImageWriter using + * ImageIO.getImageWritersBySuffix("gif"). + * + * @return a GIF ImageWriter object + * @throws IIOException if no GIF image writers are returned + */ + private static ImageWriter getWriter() throws IIOException { + Iterator iter = ImageIO.getImageWritersBySuffix("gif"); + if(!iter.hasNext()) { + throw new IIOException("No GIF Image Writers Exist"); + } else { + return iter.next(); + } + } + + /** + * Returns an existing child node, or creates and returns a new child node (if + * the requested node does not exist). + * + * @param rootNode the IIOMetadataNode to search for the child node. + * @param nodeName the name of the child node. + * + * @return the child node, if found or a new node created with the given name. + */ + private static IIOMetadataNode getNode( + IIOMetadataNode rootNode, + String nodeName) { + int nNodes = rootNode.getLength(); + for (int i = 0; i < nNodes; i++) { + if (rootNode.item(i).getNodeName().compareToIgnoreCase(nodeName) + == 0) { + return((IIOMetadataNode) rootNode.item(i)); + } + } + IIOMetadataNode node = new IIOMetadataNode(nodeName); + rootNode.appendChild(node); + return(node); + } + + public static void writeGif(String outputgifpath, List imagefilespaths, int secondsdelay) throws Exception { + + // grab the output image type from the first image in the sequence + BufferedImage firstImage = ImageIO.read(new File(imagefilespaths.get(0))); + + // create a new BufferedOutputStream with the last argument + ImageOutputStream output = + new FileImageOutputStream(new File(outputgifpath)); + + // create a gif sequence with the type of the first image, 1 second + // between frames, which loops continuously + GifSequenceWriter writer = + new GifSequenceWriter(output, firstImage.getType(), secondsdelay, false); + + firstImage.flush(); + // write out the first image to our sequence... + writer.writeToSequence(firstImage); + for(String image:imagefilespaths) { + BufferedImage nextImage = ImageIO.read(new File(image)); + writer.writeToSequence(nextImage); + } + + writer.close(); + output.close(); + + } +} diff --git a/src/main/java/org/gcube/dataanalysis/ecoengine/utils/Operations.java b/src/main/java/org/gcube/dataanalysis/ecoengine/utils/Operations.java index 46a5911..084e0c0 100644 --- a/src/main/java/org/gcube/dataanalysis/ecoengine/utils/Operations.java +++ b/src/main/java/org/gcube/dataanalysis/ecoengine/utils/Operations.java @@ -348,7 +348,7 @@ public class Operations { } } - public static void main(String[] args) { + public static void main2(String[] args) { /* * System.out.println("numbers to take: " + calcNumOfRepresentativeElements(100, 100)); double[] interp = linearInterpolation(27.27, 28.28, 3); double[] parabinterp = parabolicInterpolation(1, 10, 9); System.out.println(""); */ @@ -402,4 +402,37 @@ public class Operations { return chunksize; } + + public static double[] uniformSampling(double min, double max, int maxElementsToTake){ + double step = (max-min)/(double)(maxElementsToTake-1); + double [] samples = new double [maxElementsToTake]; + + for (int i=0;imax) + value=max; + samples [i] = value; + } + + return samples; + } + + public static int[] uniformIntegerSampling(double min, double max, int maxElementsToTake){ + double step = (max-min)/(double)(maxElementsToTake-1); + int [] samples = new int [maxElementsToTake]; + + for (int i=0;imax) + value=max; + samples [i] = (int)value; + } + + return samples; + } + + public static void main(String[] args) { + double [] samples = uniformSampling(0, 9, 10); + System.out.println("OK"); + } } diff --git a/src/main/java/org/gcube/dataanalysis/ecoengine/utils/TimeAnalyzer.java b/src/main/java/org/gcube/dataanalysis/ecoengine/utils/TimeAnalyzer.java new file mode 100644 index 0000000..44b9ce2 --- /dev/null +++ b/src/main/java/org/gcube/dataanalysis/ecoengine/utils/TimeAnalyzer.java @@ -0,0 +1,48 @@ +package org.gcube.dataanalysis.ecoengine.utils; + +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.Locale; + +import org.gcube.contentmanagement.graphtools.utils.DateGuesser; + +public class TimeAnalyzer { + + + private String pattern = ""; + + public String getPattern(){ + return pattern; + } + + public Date string2Date(String time) { + try { + time = time.replace("time:", ""); + String timepattern = DateGuesser.getPattern(time); + SimpleDateFormat sdf = new SimpleDateFormat(timepattern, Locale.ENGLISH); + Date timedate = (Date) sdf.parse(time); + + if (timepattern.equals("s")) { + timepattern = "HH:mm:ss:SS"; + sdf = new SimpleDateFormat(timepattern, Locale.ENGLISH); + timedate = (Date) sdf.parse(time); + } + pattern=timepattern; + return timedate; + } catch (Exception e) { + return new Date(System.currentTimeMillis()); + } + } + + public static int getTimeIndexInTimeRange(Date maxdate,Date mindate,Date currentdate, int chunks){ + + long timemax = maxdate.getTime(); + long timemin = mindate.getTime(); + long timecurr = currentdate.getTime(); + + return (int)Math.round((double)(timecurr-timemin)*(double)chunks/(double)(timemax-timemin)); + + } + + +}