MATSIM
VolumesAnalyzer.java
Go to the documentation of this file.
1 /* *********************************************************************** *
2  * project: org.matsim.*
3  * VolumesAnalyzer.java
4  * *
5  * *********************************************************************** *
6  * *
7  * copyright : (C) 2007 by the members listed in the COPYING, *
8  * LICENSE and WARRANTY file. *
9  * email : info at matsim dot org *
10  * *
11  * *********************************************************************** *
12  * *
13  * This program is free software; you can redistribute it and/or modify *
14  * it under the terms of the GNU General Public License as published by *
15  * the Free Software Foundation; either version 2 of the License, or *
16  * (at your option) any later version. *
17  * See also COPYING, LICENSE and WARRANTY file *
18  * *
19  * *********************************************************************** */
20 
21 package org.matsim.analysis;
22 
23 import org.apache.logging.log4j.LogManager;
24 import org.apache.logging.log4j.Logger;
25 import org.matsim.api.core.v01.Id;
26 import org.matsim.api.core.v01.IdMap;
34 import org.matsim.vehicles.Vehicle;
35 
36 import jakarta.inject.Inject;
37 import java.util.HashMap;
38 import java.util.Map;
39 import java.util.Set;
40 import java.util.TreeSet;
41 
48 
49  private final static Logger log = LogManager.getLogger(VolumesAnalyzer.class);
50  private final int timeBinSize;
51  private final int maxTime;
52  private final int maxSlotIndex;
53  private final IdMap<Link, int[]> links;
54 
55  // for multi-modal support
56  private final boolean observeModes;
59 
60  @Inject
61  VolumesAnalyzer(Network network, EventsManager eventsManager) {
62  this(3600, 24 * 3600 - 1, network);
63  eventsManager.addHandler(this);
64  }
65 
66  public VolumesAnalyzer(final int timeBinSize, final int maxTime, final Network network) {
67  this(timeBinSize, maxTime, network, true);
68  }
69 
70  public VolumesAnalyzer(final int timeBinSize, final int maxTime, final Network network, boolean observeModes) {
71  this.timeBinSize = timeBinSize;
72  this.maxTime = maxTime;
73  this.maxSlotIndex = (this.maxTime / this.timeBinSize) + 1;
74  this.links = new IdMap<>(Link.class);
75 
76  this.observeModes = observeModes;
77  if (this.observeModes) {
78  this.enRouteModes = new IdMap<>(Vehicle.class);
79  this.linksPerMode = new IdMap<>(Link.class);
80  } else {
81  this.enRouteModes = null;
82  this.linksPerMode = null;
83  }
84  }
85 
86  @Override
88  if (this.observeModes) {
89  this.enRouteModes.put(event.getVehicleId(), event.getNetworkMode());
90  }
91  }
92 
93  @Override
94  public void handleEvent(final LinkLeaveEvent event) {
95  int[] volumes = this.links.get(event.getLinkId());
96  if (volumes == null) {
97  volumes = new int[this.maxSlotIndex + 1]; // initialized to 0 by default, according to JVM specs
98  this.links.put(event.getLinkId(), volumes);
99  }
100  int timeslot = getTimeSlotIndex(event.getTime());
101  volumes[timeslot]++;
102 
103  if (this.observeModes) {
104  Map<String, int[]> modeVolumes = this.linksPerMode.get(event.getLinkId());
105  if (modeVolumes == null) {
106  modeVolumes = new HashMap<>();
107  this.linksPerMode.put(event.getLinkId(), modeVolumes);
108  }
109  String mode = this.enRouteModes.get(event.getVehicleId());
110  volumes = modeVolumes.get(mode);
111  if (volumes == null) {
112  volumes = new int[this.maxSlotIndex + 1]; // initialized to 0 by default, according to JVM specs
113  modeVolumes.put(mode, volumes);
114  }
115  volumes[timeslot]++;
116  }
117  }
118 
119  private int getTimeSlotIndex(final double time) {
120  if (time > this.maxTime) {
121  return this.maxSlotIndex;
122  }
123  return ((int) time / this.timeBinSize);
124  }
125 
131  public int[] getVolumesForLink(final Id<Link> linkId) {
132  return this.links.get(linkId);
133  }
134 
141  public int[] getVolumesForLink(final Id<Link> linkId, String mode) {
142  if (observeModes) {
143  Map<String, int[]> modeVolumes = this.linksPerMode.get(linkId);
144  if (modeVolumes != null) return modeVolumes.get(mode);
145  }
146  return null;
147  }
148 
153  public int getVolumesArraySize() {
154  return this.maxSlotIndex + 1;
155  }
156 
157  /*
158  * This procedure is only working if (hour % timeBinSize == 0)
159  *
160  * Example: 15 minutes bins
161  * ___________________
162  * | 0 | 1 | 2 | 3 |
163  * |____|____|____|____|
164  * 0 900 1800 2700 3600
165  ___________________
166  * | hour 0 |
167  * |___________________|
168  * 0 3600
169  *
170  * hour 0 = bins 0,1,2,3
171  * hour 1 = bins 4,5,6,7
172  * ...
173  *
174  * getTimeSlotIndex = (int)time / this.timeBinSize => jumps at 3600.0!
175  * Thus, starting time = (hour = 0) * 3600.0
176  */
177  public double[] getVolumesPerHourForLink(final Id<Link> linkId) {
178  if (3600.0 % this.timeBinSize != 0) log.error("Volumes per hour and per link probably not correct!");
179 
180  double[] volumes = new double[24];
181 
182  int[] volumesForLink = this.getVolumesForLink(linkId);
183  if (volumesForLink == null) return volumes;
184 
185  int slotsPerHour = (int) (3600.0 / this.timeBinSize);
186  for (int hour = 0; hour < 24; hour++) {
187  double time = hour * 3600.0;
188  for (int i = 0; i < slotsPerHour; i++) {
189  volumes[hour] += volumesForLink[this.getTimeSlotIndex(time)];
190  time += this.timeBinSize;
191  }
192  }
193  return volumes;
194  }
195 
196  public double[] getVolumesPerHourForLink(final Id<Link> linkId, String mode) {
197  if (observeModes) {
198  if (3600.0 % this.timeBinSize != 0) log.error("Volumes per hour and per link probably not correct!");
199 
200  double[] volumes = new double[24];
201  for (int hour = 0; hour < 24; hour++) {
202  volumes[hour] = 0.0;
203  }
204 
205  int[] volumesForLink = this.getVolumesForLink(linkId, mode);
206  if (volumesForLink == null) return volumes;
207 
208  int slotsPerHour = (int) (3600.0 / this.timeBinSize);
209  for (int hour = 0; hour < 24; hour++) {
210  double time = hour * 3600.0;
211  for (int i = 0; i < slotsPerHour; i++) {
212  volumes[hour] += volumesForLink[this.getTimeSlotIndex(time)];
213  time += this.timeBinSize;
214  }
215  }
216  return volumes;
217  }
218  return null;
219  }
220 
224  public Set<String> getModes() {
225  Set<String> modes = new TreeSet<>();
226 
227  for (Map<String, int[]> map : this.linksPerMode.values()) {
228  try {
229  modes.addAll(map.keySet());
230  } catch (NullPointerException ex) {
231  // Fails on initialized entries, which can happen during tests
232  // will just be ignored here
233  }
234  }
235 
236  return modes;
237  }
238 
242  public Set<Id<Link>> getLinkIds() {
243  return this.links.keySet();
244  }
245 
246  @Override
247  public void reset(final int iteration) {
248  this.links.clear();
249  if (observeModes) {
250  this.linksPerMode.clear();
251  this.enRouteModes.clear();
252  }
253  }
254 }
int [] getVolumesForLink(final Id< Link > linkId)
VolumesAnalyzer(final int timeBinSize, final int maxTime, final Network network, boolean observeModes)
double [] getVolumesPerHourForLink(final Id< Link > linkId)
double [] getVolumesPerHourForLink(final Id< Link > linkId, String mode)
Set< Id< T > > keySet()
Definition: IdMap.java:189
Collection< V > values()
Definition: IdMap.java:204
void handleEvent(final LinkLeaveEvent event)
final IdMap< Link, Map< String, int[]> > linksPerMode
void handleEvent(VehicleEntersTrafficEvent event)
void addHandler(final EventHandler handler)
final IdMap< Vehicle, String > enRouteModes
int getTimeSlotIndex(final double time)
V put(Id< T > key, V value)
Definition: IdMap.java:141
final IdMap< Link, int[]> links
VolumesAnalyzer(final int timeBinSize, final int maxTime, final Network network)
int [] getVolumesForLink(final Id< Link > linkId, String mode)