ContourPlotDelay.java

  1. package org.opentrafficsim.draw.graphs.road;

  2. import java.awt.Color;
  3. import java.util.List;

  4. import org.djunits.unit.DurationUnit;
  5. import org.djunits.unit.LinearDensityUnit;
  6. import org.djunits.value.ValueRuntimeException;
  7. import org.djunits.value.storage.StorageType;
  8. import org.djunits.value.vdouble.matrix.DurationMatrix;
  9. import org.djunits.value.vdouble.matrix.base.DoubleMatrix;
  10. import org.djunits.value.vdouble.scalar.Duration;
  11. import org.djunits.value.vdouble.scalar.Length;
  12. import org.djunits.value.vdouble.scalar.Time;
  13. import org.djunits.value.vfloat.vector.FloatSpeedVector;
  14. import org.opentrafficsim.core.dsol.OTSSimulatorInterface;
  15. import org.opentrafficsim.core.egtf.Converter;
  16. import org.opentrafficsim.core.egtf.Quantity;
  17. import org.opentrafficsim.draw.core.BoundsPaintScale;
  18. import org.opentrafficsim.draw.graphs.AbstractContourPlot;
  19. import org.opentrafficsim.draw.graphs.ContourDataSource;
  20. import org.opentrafficsim.draw.graphs.ContourDataSource.ContourDataType;
  21. import org.opentrafficsim.draw.graphs.GraphType;
  22. import org.opentrafficsim.draw.graphs.GraphUtil;
  23. import org.opentrafficsim.kpi.sampling.SamplingException;
  24. import org.opentrafficsim.kpi.sampling.Trajectory;
  25. import org.opentrafficsim.kpi.sampling.TrajectoryGroup;
  26. import org.opentrafficsim.road.network.sampling.GtuData;
  27. import org.opentrafficsim.road.network.sampling.data.ReferenceSpeed;

  28. /**
  29.  * Contour plot for delay.
  30.  * <p>
  31.  * <i>A note on the unit "/km"</i>. This unit is derived by measuring the total delay over a cell in space-time, which gives an
  32.  * SI value in [s]. With varying granularity, the value needs to be normalized to space-time. Hence, the value is divided by the
  33.  * length of the cell [m], and divided by the duration of the cell [s]. This gives a unit of [s/s/m] = [1/m]. This means that a
  34.  * traffic state represented by a value of D/km, gives a total amount of delay equal to D * x * t, where x * t is the size of
  35.  * the cell, and the resulting value is in the same unit as t. So if D = 50/km, then measuring this state over 2km and during 3
  36.  * hours gives 50 * 2 * 3 = 300h of delay.
  37.  * <p>
  38.  * Copyright (c) 2013-2019 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
  39.  * BSD-style license. See <a href="http://opentrafficsim.org/node/13">OpenTrafficSim License</a>.
  40.  * <p>
  41.  * @version $Revision$, $LastChangedDate$, by $Author$, initial version 10 okt. 2018 <br>
  42.  * @author <a href="http://www.tbm.tudelft.nl/averbraeck">Alexander Verbraeck</a>
  43.  * @author <a href="http://www.tudelft.nl/pknoppers">Peter Knoppers</a>
  44.  * @author <a href="http://www.transport.citg.tudelft.nl">Wouter Schakel</a>
  45.  */
  46. public class ContourPlotDelay extends AbstractContourPlot<Duration>
  47. {
  48.     /** */
  49.     private static final long serialVersionUID = 20181010L;

  50.     /** Quantity for the EGTF. */
  51.     private static final Quantity<Duration, DurationMatrix> QUANTITY = new Quantity<>("delay", new Converter<DurationMatrix>()
  52.     {
  53.         /** {@inheritDoc} */
  54.         @Override
  55.         public DurationMatrix convert(final double[][] filteredData)
  56.         {
  57.             try
  58.             {
  59.                 return DoubleMatrix.instantiate(filteredData, DurationUnit.SI, StorageType.DENSE);
  60.             }
  61.             catch (ValueRuntimeException exception)
  62.             {
  63.                 // should not happen as filtered data comes from the EGTF
  64.                 throw new RuntimeException("Unexpected exception while converting duration to output format.", exception);
  65.             }
  66.         }
  67.     });

  68.     /** Contour data type. */
  69.     private static final ContourDataType<Duration, Duration> CONTOUR_DATA_TYPE = new ContourDataType<Duration, Duration>()
  70.     {
  71.         /** {@inheritDoc} */
  72.         @Override
  73.         public Duration identity()
  74.         {
  75.             return Duration.ZERO;
  76.         }

  77.         /** {@inheritDoc} */
  78.         @Override
  79.         public Duration processSeries(final Duration intermediate, final List<TrajectoryGroup<?>> trajectories,
  80.                 final List<Length> xFrom, final List<Length> xTo, final Time tFrom, final Time tTo)
  81.         {
  82.             double sumActualTime = 0.0;
  83.             double sumRefTime = 0.0;
  84.             for (int i = 0; i < trajectories.size(); i++)
  85.             {
  86.                 TrajectoryGroup<?> trajectoryGroup = trajectories.get(i);
  87.                 for (Trajectory<?> trajectory : trajectoryGroup.getTrajectories())
  88.                 {
  89.                     if (GraphUtil.considerTrajectory(trajectory, tFrom, tTo))
  90.                     {
  91.                         trajectory = trajectory.subSet(xFrom.get(i), xTo.get(i), tFrom, tTo);
  92.                         try
  93.                         {
  94.                             FloatSpeedVector ref = trajectory.getExtendedData(ReferenceSpeed.INSTANCE);
  95.                             float[] v = trajectory.getV();
  96.                             float[] x = trajectory.getX();
  97.                             for (int j = 0; j < v.length - 1; j++)
  98.                             {
  99.                                 sumRefTime += (x[j + 1] - x[j]) / ref.get(j).si;
  100.                             }
  101.                         }
  102.                         catch (SamplingException | ValueRuntimeException exception)
  103.                         {
  104.                             throw new RuntimeException("Unexpected exception while calculating delay.", exception);
  105.                         }
  106.                         sumActualTime += trajectory.getTotalDuration().si;
  107.                     }
  108.                 }
  109.             }
  110.             return Duration.instantiateSI(intermediate.si + sumActualTime - sumRefTime);
  111.         }

  112.         /** {@inheritDoc} */
  113.         @Override
  114.         public Duration finalize(final Duration intermediate)
  115.         {
  116.             return intermediate;
  117.         }

  118.         /** {@inheritDoc} */
  119.         @SuppressWarnings("synthetic-access")
  120.         @Override
  121.         public Quantity<Duration, ?> getQuantity()
  122.         {
  123.             return QUANTITY;
  124.         }

  125.     };

  126.     /**
  127.      * Constructor.
  128.      * @param caption String; caption
  129.      * @param simulator OTSSimulatorInterface; simulator
  130.      * @param dataPool ContourDataSource&lt;GtuData&gt;; data pool
  131.      */
  132.     public ContourPlotDelay(final String caption, final OTSSimulatorInterface simulator,
  133.             final ContourDataSource<GtuData> dataPool)
  134.     {
  135.         super(caption, simulator, dataPool, createPaintScale(), new Duration(0.05, DurationUnit.SI), "%.1f/km",
  136.                 "delay %.1f /km");
  137.         dataPool.getSampler().registerExtendedDataType(ReferenceSpeed.INSTANCE);
  138.     }

  139.     /**
  140.      * Creates a paint scale from red, via yellow to green.
  141.      * @return ContinuousColorPaintScale; paint scale
  142.      */
  143.     private static BoundsPaintScale createPaintScale()
  144.     {
  145.         double[] boundaries = {0.0, 0.05, 0.2};
  146.         Color[] colorValues = BoundsPaintScale.GREEN_RED;
  147.         return new BoundsPaintScale(boundaries, colorValues);
  148.     }

  149.     /** {@inheritDoc} */
  150.     @Override
  151.     public GraphType getGraphType()
  152.     {
  153.         return GraphType.DELAY_CONTOUR;
  154.     }

  155.     /** {@inheritDoc} */
  156.     @Override
  157.     protected double scale(final double si)
  158.     {
  159.         return LinearDensityUnit.PER_KILOMETER.getScale().fromStandardUnit(si);
  160.     }

  161.     /** {@inheritDoc} */
  162.     @Override
  163.     protected double getValue(final int item, final double cellLength, final double cellSpan)
  164.     {
  165.         return getDataPool().get(item, CONTOUR_DATA_TYPE) / (cellLength * cellSpan);
  166.     }

  167.     /** {@inheritDoc} */
  168.     @Override
  169.     protected ContourDataType<Duration, Duration> getContourDataType()
  170.     {
  171.         return CONTOUR_DATA_TYPE;
  172.     }

  173. }