source: ether_megapoli/trunk/service/implementation/com/ether/EtherPlotContentServiceImpl.java @ 189

Last change on this file since 189 was 189, checked in by vmipsl, 13 years ago

Servlet _ TimeSerie? :

  • 1 paramètre ok
  • même paramètre sur différentes plateformes ok
  • plusieurs paramètres sur même ou différentes plateformes ok
File size: 16.7 KB
Line 
1package com.ether;
2
3import com.medias.database.objects.Parametre;
4import com.medias.database.objects.Plateforme;
5import gov.noaa.pmel.sgt.Axis;
6import gov.noaa.pmel.sgt.CartesianGraph;
7import gov.noaa.pmel.sgt.Graph;
8import gov.noaa.pmel.sgt.JPane;
9import gov.noaa.pmel.sgt.Layer;
10import gov.noaa.pmel.sgt.LineAttribute;
11import gov.noaa.pmel.sgt.LineCartesianRenderer;
12import gov.noaa.pmel.sgt.LineKey;
13import gov.noaa.pmel.sgt.LinearTransform;
14import gov.noaa.pmel.sgt.PlainAxis;
15import gov.noaa.pmel.sgt.SGLabel;
16import gov.noaa.pmel.sgt.StackedLayout;
17import gov.noaa.pmel.sgt.TimeAxis;
18import gov.noaa.pmel.sgt.dm.SGTMetaData;
19import gov.noaa.pmel.sgt.dm.SimpleLine;
20import gov.noaa.pmel.util.Dimension2D;
21import gov.noaa.pmel.util.GeoDateArray;
22import gov.noaa.pmel.util.Point2D;
23import gov.noaa.pmel.util.Range2D;
24import gov.noaa.pmel.util.SoTPoint;
25import gov.noaa.pmel.util.SoTRange;
26import org.jetbrains.annotations.NotNull;
27import org.jetbrains.annotations.Nullable;
28import org.springframework.beans.factory.annotation.Required;
29
30import java.awt.*;
31import java.util.ArrayList;
32import java.util.Date;
33import java.util.List;
34import java.util.Locale;
35import java.util.Random;
36import java.util.ResourceBundle;
37
38/**
39 * @author vmipsl
40 * @date 05 sept. 2011
41 */
42public class EtherPlotContentServiceImpl
43{
44    /**
45     * First layer contains axes, labels and the first set of data
46     * Others layers contains only the other sets of data
47     *
48     * @param megapoliPlot
49     * @return
50     */
51    @NotNull
52    public JPane createTimeSeriePlot( @NotNull final MegapoliPlot megapoliPlot, @NotNull final Integer plotWidth, @NotNull final Integer plotHeight )
53            throws ServiceException
54    {
55        final JPane mainPane = new JPane( "Time Serie Pane", new Dimension( plotWidth, plotHeight ) );
56        mainPane.setLayout( new StackedLayout() );
57
58        // TODO : revoir les tailles ! mettre en automatique par rapport à plotWidth et plotHeight
59        /*
60        * xsize, ysize are the width and height in physical units
61        * of the Layer graphics region.
62        *
63        * xstart, xend are the start and end points for the TimeAxis
64        * ystart, yend are the start and end points for the Y axis
65        */
66        final double xsize = 5.0;
67        final double ysize = 3.5;
68        final double xstart = 0.3;
69        final double xend = xsize - xstart;
70        final double ystart = 0.5;
71        final double yend = ysize - ystart;
72
73        final Layer layer = new Layer( "First Layer", new Dimension2D( xsize, ysize ) );
74        mainPane.add( layer );
75
76        final Pair<List, List> listPairOfPIdPIdForTwoAxes = extractListPairForAxes( megapoliPlot.getpIdPIdList() );
77        final List<Pair> pIdPIdListForFirstAxis = listPairOfPIdPIdForTwoAxes.getFirstValue();
78        final List<Pair> pIdPIdListForSecondAxis = listPairOfPIdPIdForTwoAxes.getSecondValue();
79
80        final List<SimpleLine> lines = createLines( pIdPIdListForFirstAxis, megapoliPlot.getBeginDate(), megapoliPlot.getEndDate(), 1, layer );
81        final List<SimpleLine> linesForSecondAxis = createLines( pIdPIdListForSecondAxis, megapoliPlot.getBeginDate(), megapoliPlot.getEndDate(), 10, layer );
82        final SimpleLine firstLine = lines.get( 0 );
83
84        /** ********** AXIS RANGES ********* **/
85        final SoTRange xnRange = firstLine.getXRange();
86        final SoTRange yRange = firstLine.getYRange();
87        for( final SimpleLine line : lines )
88        {
89            yRange.add( line.getYRange() );
90            xnRange.add( line.getXRange() );
91        }
92
93        for( final SimpleLine line : linesForSecondAxis )
94            xnRange.add( line.getXRange() );
95
96        final SoTRange ynRange = Graph.computeRange( yRange, _intervalsNumber );
97
98        // Origin point
99        final SoTPoint originPoint = new SoTPoint( ynRange.getStart(), xnRange.getStart() );
100
101
102        /** ************ AXIS ********** **/
103        // Time axis is the same for the two y-axis
104        final TimeAxis xTimeAxis = createXTimeAxis( xnRange, originPoint );
105        final PlainAxis yLeftAxis = createYAxis( firstLine, ynRange, originPoint, null );
106
107        /** ************ GRAPH ********** **/
108        final CartesianGraph graph = new CartesianGraph( "First Graph" );
109        layer.setGraph( graph );
110
111        final LinearTransform xt = new LinearTransform( new Range2D( xstart, xend ), xnRange );
112        graph.setXTransform( xt );
113        final LinearTransform yt = new LinearTransform( new Range2D( ystart, yend ), ynRange );
114        graph.setYTransform( yt );
115
116        graph.addXAxis( xTimeAxis );
117        graph.addYAxis( yLeftAxis );
118
119        final LineAttribute lineAttribute = createRandomLineAttribute( megapoliPlot.getAxeType() );
120        graph.setData( firstLine, lineAttribute );
121
122        /** *********** LEGEND ********* **/
123        final LineKey lkey = createLineKey( megapoliPlot, ysize, layer, firstLine, graph );
124
125        /** *********** OTHER LAYERS ********* **/
126        // First axis
127        addOtherLinesForOneAxis( megapoliPlot.getAxeType(), mainPane, xsize, ysize, lines, xt, yt, lkey, 1 );
128
129        // Second axis
130        if( !pIdPIdListForSecondAxis.isEmpty() )
131        {
132            final SimpleLine firstLineForSecondAxis = linesForSecondAxis.get( 0 );
133
134            final SoTRange yRangeForSecondAxis = firstLineForSecondAxis.getYRange();
135            for( final SimpleLine line : linesForSecondAxis )
136                yRangeForSecondAxis.add( line.getYRange() );
137
138            final SoTRange ynRangeForSecondAxis = Graph.computeRange( yRangeForSecondAxis, _intervalsNumber );
139            final SoTPoint endPointForSecondAxis = new SoTPoint( ynRangeForSecondAxis.getStart(), xnRange.getEnd() );
140
141            final PlainAxis yRightAxis = createYAxis( firstLineForSecondAxis, ynRangeForSecondAxis, endPointForSecondAxis, Axis.POSITIVE_SIDE );
142
143            final LinearTransform ytForSecondAxis = new LinearTransform( new Range2D( ystart, yend ), ynRangeForSecondAxis );
144
145            // It transforms the graph with the maximum yAxis
146            if( ytForSecondAxis.getRangeU().end > yt.getRangeU().end )
147                graph.setYTransform( ytForSecondAxis );
148            graph.addYAxis( yRightAxis );
149
150            addOtherLinesForOneAxis( megapoliPlot.getAxeType(), mainPane, xsize, ysize, linesForSecondAxis, xt, ytForSecondAxis, lkey, 0 );
151        }
152
153        return mainPane;
154    }
155
156    @NotNull
157    public JPane create2DPlot( @NotNull final MegapoliPlot megapoliPlot, @NotNull final Integer plotWidth, @NotNull final Integer plotHeight, @Nullable final Locale locale )
158    {
159        final JPane mainPane = new JPane( "2D Pane", new Dimension( plotWidth, plotHeight ) );
160
161        final ResourceBundle bundle = WebHelper.getBundle( locale );
162
163        final Data realValuesFor2D = BouchonHelper.createRealValuesFor2D();
164//        final double[] parameterValues = (double[]) megapoliPlot.getData().getFirstArray();
165//        final double[] latitudeValues = (double[]) megapoliPlot.getData().getSecondArray();
166//        final double[] longitudeValues = (double[]) megapoliPlot.getData().getThirdArray();
167
168        final double[] parameterValues = (double[]) realValuesFor2D.getFirstArray();
169        final double[] latitudeValues = (double[]) realValuesFor2D.getSecondArray();
170        final double[] longitudeValues = (double[]) realValuesFor2D.getThirdArray();
171
172        return mainPane;
173    }
174
175    @NotNull
176    protected String formatTitle( @Nullable final String title )
177    {
178        if( null == title )
179            return "";
180        else
181        {
182            final String formatTitle = title.replaceAll( "\\n", "<br>" );
183            return "<html>" + formatTitle + "</html>";
184        }
185    }
186
187    /**
188     * This method creates a legend
189     *
190     * @param megapoliPlot
191     * @param ysize
192     * @param layer
193     * @param firstLine
194     * @param graph
195     * @return
196     */
197    @NotNull
198    private LineKey createLineKey( final MegapoliPlot megapoliPlot, final double ysize, final Layer layer, final SimpleLine firstLine, final CartesianGraph graph )
199    {
200        final LineKey lkey = new LineKey();
201        if( !megapoliPlot.isLegendToHide() )
202        {
203            lkey.setId( "Legend" );
204            lkey.setLocationP( new Point2D.Double( 0.1, ysize - 0.1 ) );
205            lkey.setBorderStyle( LineKey.NO_BORDER );
206            lkey.setVAlign( LineKey.TOP );
207            lkey.setHAlign( LineKey.LEFT );
208            layer.addChild( lkey );
209            lkey.addLineGraph( (LineCartesianRenderer) graph.getRenderer(), firstLine.getKeyTitle() );
210        }
211        return lkey;
212    }
213
214    /**
215     * This method creates a x-axis for time serie
216     *
217     * @param xnRange
218     * @param originPoint
219     * @return
220     */
221    @NotNull
222    private TimeAxis createXTimeAxis( final SoTRange xnRange, final SoTPoint originPoint )
223    {
224        final TimeAxis xbot = new TimeAxis( "X-Axis", TimeAxis.AUTO );
225        xbot.setRangeU( xnRange );
226        xbot.setLocationU( originPoint );
227        xbot.setLabelFont( _axisFont );
228        xbot.setLabelHeightP( _heightAxisFont );
229        xbot.setMajorLabelFormat( "yyyy-MM-dd HH:mm:ss" );
230        return xbot;
231    }
232
233    /**
234     * This method adds layers corresponding to the other lines to display
235     *
236     * @param axeType
237     * @param mainPane
238     * @param xsize
239     * @param ysize
240     * @param lines
241     * @param xt
242     * @param yt
243     * @param lkey
244     * @param indexLineToBegin
245     */
246    private void addOtherLinesForOneAxis( @NotNull final String axeType, @NotNull final JPane mainPane, final double xsize, final double ysize, @NotNull final List<SimpleLine> lines, @NotNull final LinearTransform xt, @NotNull final LinearTransform yt, @NotNull final LineKey lkey, @NotNull final Integer indexLineToBegin )
247    {
248        for( final SimpleLine line : lines.subList( indexLineToBegin, lines.size() ) )
249        {
250            final Layer otherLayer = new Layer( "Other Layer", new Dimension2D( xsize, ysize ) );
251            mainPane.add( otherLayer );
252            final CartesianGraph otherGraph = new CartesianGraph( "Other Graph", xt, yt );
253            otherLayer.setGraph( otherGraph );
254
255            final LineAttribute otherLineAttribute = createRandomLineAttribute( axeType );
256            otherGraph.setData( line, otherLineAttribute );
257            lkey.addLineGraph( (LineCartesianRenderer) otherGraph.getRenderer(), line.getKeyTitle() );
258        }
259    }
260
261    /**
262     * This method creates a vertical axis, set its range in user units and its origin and creates the axis title
263     *
264     * @param line
265     * @param ynRange
266     * @param originPoint
267     * @param labelPosition
268     * @return
269     */
270    @NotNull
271    private PlainAxis createYAxis( final SimpleLine line, final SoTRange ynRange, final SoTPoint originPoint, @Nullable final Integer labelPosition )
272    {
273        final PlainAxis yAxis = new PlainAxis( "Y-Axis" );
274        yAxis.setRangeU( ynRange );
275        yAxis.setLocationU( originPoint );
276        yAxis.setLabelFont( _axisFont );
277        if( null != labelPosition )
278            yAxis.setLabelPosition( labelPosition );
279
280        final String yLabel = line.getYMetaData().getName() + " (" + line.getYMetaData().getUnits() + ")";
281        final SGLabel ytitle = new SGLabel( "Y-Axis Title", yLabel, new Point2D.Double( 0.0, 0.0 ) );
282        ytitle.setFont( _axisFont );
283        ytitle.setHeightP( _heightAxisFont );
284        yAxis.setTitle( ytitle );
285        return yAxis;
286    }
287
288    /**
289     * This method returns a new LineAttribute with a random color
290     *
291     * @param axeType
292     * @return
293     */
294    @NotNull
295    private LineAttribute createRandomLineAttribute( @NotNull final String axeType )
296    {
297        final LineAttribute attr;
298        final Color color = new Color( new Random().nextInt( 256 ), new Random().nextInt( 256 ), new Random().nextInt( 256 ) );
299
300        if( axeType.equals( AxeTypeForFixedPlateform.TIME_POINTS.toString() ) )
301            attr = new LineAttribute( LineAttribute.MARK, 1, color );
302        else
303            attr = new LineAttribute( LineAttribute.SOLID, 1, color );
304
305        attr.setMarkHeightP( _markHeight );
306
307        return attr;
308    }
309
310    /**
311     * This method extracts from a list of <plateformId, parameterId> two lists of <plateformId, parameterId> corresponding for the 2 axes needed for the graph
312     * The second list can be empty, in this case, only one axis is needed
313     *
314     * @param pIdPIdList
315     * @return
316     */
317    @NotNull
318    private Pair<List, List> extractListPairForAxes( @NotNull final List<Pair> pIdPIdList )
319    {
320        final List<Pair<Integer, Integer>> pIdPIdListForFirstAxis = new ArrayList<Pair<Integer, Integer>>();
321        final List<Pair<Integer, Integer>> pIdPIdListForSecondAxis = new ArrayList<Pair<Integer, Integer>>();
322
323        for( final Pair pIdPId : pIdPIdList )
324        {
325            final List<Integer> secondValuesForFirstAxis = EtherHelper.getSecondValues( pIdPIdListForFirstAxis );
326            final Integer parameterId = (Integer) pIdPId.getSecondValue();
327
328            if( pIdPIdListForFirstAxis.isEmpty() || secondValuesForFirstAxis.contains( parameterId ) )
329                pIdPIdListForFirstAxis.add( pIdPId );
330            else
331                pIdPIdListForSecondAxis.add( pIdPId );
332        }
333
334        return new Pair( pIdPIdListForFirstAxis, pIdPIdListForSecondAxis );
335    }
336
337    /**
338     * This method extracts data from BD for the plateform and parameter given as parameters
339     * and creates the corresponded simpleLine
340     *
341     * @param pIdPIdList
342     * @param beginDate
343     * @param endDate
344     * @return
345     * @throws ServiceException
346     */
347    @NotNull
348    private List<SimpleLine> createLines( @NotNull final List<Pair> pIdPIdList, @Nullable final Date beginDate, @Nullable final Date endDate, final Integer delta, @NotNull final Layer layer )
349            throws ServiceException
350    {
351        final List<SimpleLine> lines = new ArrayList<SimpleLine>( pIdPIdList.size() );
352        boolean isFirstLine = true;
353
354        for( final Pair<Integer, Integer> pIdPId : pIdPIdList )
355        {
356            final Integer plateformId = pIdPId.getFirstValue();
357            final Integer parameterId = pIdPId.getSecondValue();
358
359//            final Plateforme plateform = _etherService.getPlateformById( plateformId );
360            final Plateforme plateform = BouchonHelper.getPlateformById( plateformId );
361            if( null == plateform )
362                throw new ServiceException( ServiceException.ServiceCode.PLATEFORM_IS_NULL, new Throwable( ServiceException.ServiceCode.PLATEFORM_IS_NULL.toString() ) );
363
364//            final Parametre parametre = _etherService.getParameterById( parameterId );
365            final Parametre parametre = BouchonHelper.getParameterById( parameterId );
366            if( null == parametre )
367                throw new ServiceException( ServiceException.ServiceCode.PARAMETER_IS_NULL, new Throwable( ServiceException.ServiceCode.PARAMETER_IS_NULL.toString() ) );
368
369//            final Data valuesLists = _etherService.getListsByPlateformByParameterByPeriodForTimeSerie( plateformId, parameterId, beginDate, endDate );
370            final Data valuesLists = BouchonHelper.createValuesForTimeSerie( 50, delta );
371
372            final double[] dataArray = (double[]) valuesLists.getFirstArray();
373            final Date[] dateValues = (Date[]) valuesLists.getSecondArray();
374
375            final SimpleLine line = new SimpleLine( new GeoDateArray( dateValues ), dataArray, "legend" );
376            SGTMetaData meta = new SGTMetaData( "", "", false, false );
377            line.setXMetaData( meta );
378            final SGLabel sgLabel = new SGLabel( "Line", plateform.getPlateformeNom() + "-" + parametre.getParametreNom(), new Point2D.Double( 0.0, 0.0 ) );
379            line.setKeyTitle( sgLabel );
380
381            if( isFirstLine )
382                meta = new SGTMetaData( parametre.getParametreNom(), parametre.getUnite().getUniteCode(), false, false );
383            else
384                meta = new SGTMetaData( "", "", false, false );
385            line.setYMetaData( meta );
386
387            lines.add( line );
388            isFirstLine = false;
389        }
390        return lines;
391    }
392
393
394    public EtherService getEtherService()
395    {
396        return _etherService;
397    }
398
399    @Required
400    public void setEtherService( final EtherService etherService )
401    {
402        _etherService = etherService;
403    }
404
405    // Dimensions of the jPanes
406    protected static final int MAX_WIDTH = 800;
407    protected static final int MAX_HEIGHT = 700;
408    protected static final int MARGIN_LEFT_RIGHT = 50;
409
410    protected static final int TITLE_FONT_SIZE = 20;
411    protected static final int FONT_SIZE = 12;
412    protected static final int ERROR_FONT_SIZE = 10;
413
414    protected static final Font _axisFont = new Font( "Helvetica", Font.PLAIN, 15 );
415    protected static final double _heightAxisFont = 0.14;
416    protected static final double _markHeight = 0.1;
417    // Number of intervals on a Y-Axis
418    protected Integer _intervalsNumber = 10;
419
420    private EtherService _etherService;
421}
Note: See TracBrowser for help on using the repository browser.