Skip to content

Commit 0597c86

Browse files
authored
feat: separate travel time recording from general analysis (#271)
* feat: separate travel time recording from general analysis * add changelog * fix problem in unit tests
1 parent cd8c1dd commit 0597c86

File tree

6 files changed

+46
-9
lines changed

6 files changed

+46
-9
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ included in the (note yet determined) next version number.
66

77
**Development version**
88

9+
- Introduce `travelTimeRecordingInterval` config option that decouples travel time writing from general analysis
910
- Add eqasim_activities.csv for analysis
1011
- The cutters now take a GeoPackage file as an alterative to a ShapeFile
1112
- Emissions tools have been moved to core package (from ile_de_france)

core/src/main/java/org/eqasim/core/components/config/EqasimConfigGroup.java

+14
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,8 @@ public class EqasimConfigGroup extends ReflectiveConfigGroup {
2222

2323
private final static String ANALYSIS_INTERVAL = "analysisInterval";
2424
private final static String ANALYSIS_DISTANCE_UNIT = "analysisDistanceUnit";
25+
26+
private final static String TRAVEL_TIME_RECORDING_INTERVAL = "travelTimeRecordingInterval";
2527

2628
private final static String USE_SCHEDULE_BASED_TRANSPORT = "useScheduleBasedTransport";
2729

@@ -35,6 +37,8 @@ public class EqasimConfigGroup extends ReflectiveConfigGroup {
3537

3638
private int analysisInterval = 0;
3739
private DistanceUnit analysisDistanceUnit = DistanceUnit.meter;
40+
41+
private int travelTimeRecordingInterval = 0;
3842

3943
private boolean useScheduleBasedTransport = true;
4044

@@ -208,6 +212,16 @@ public void setAnalysisInterval(int analysisInterval) {
208212
this.analysisInterval = analysisInterval;
209213
}
210214

215+
@StringGetter(TRAVEL_TIME_RECORDING_INTERVAL)
216+
public int getTravelTimeRecordingInterval() {
217+
return travelTimeRecordingInterval;
218+
}
219+
220+
@StringSetter(TRAVEL_TIME_RECORDING_INTERVAL)
221+
public void setTravelTimeRecordingInterval(int travelTimeRecordingInterval) {
222+
this.travelTimeRecordingInterval = travelTimeRecordingInterval;
223+
}
224+
211225
@StringGetter(DISTANCE_UNIT)
212226
public DistanceUnit getDistanceUnit() {
213227
return distanceUnit;

core/src/main/java/org/eqasim/core/simulation/analysis/AnalysisOutputListener.java

+24-9
Original file line numberDiff line numberDiff line change
@@ -44,21 +44,25 @@ public class AnalysisOutputListener implements IterationStartsListener, Iteratio
4444
private final TravelTimeRecorder travelTimeRecorder;
4545

4646
private final int analysisInterval;
47+
private final int travelTimeInterval;
48+
4749
private boolean isAnalysisActive = false;
50+
private boolean isTravelTimeActive = false;
4851

4952
private final DistanceUnit scenarioDistanceUnit;
5053
private final DistanceUnit analysisDistanceUnit;
5154

5255
@Inject
5356
public AnalysisOutputListener(EqasimConfigGroup config, OutputDirectoryHierarchy outputDirectory,
54-
TripListener tripListener, LegListener legListener, PublicTransportLegListener ptListener,
55-
ActivityListener activityAnalysisListener, TravelTimeRecorder travelTimeRecorder) {
57+
TripListener tripListener, LegListener legListener, PublicTransportLegListener ptListener,
58+
ActivityListener activityAnalysisListener, TravelTimeRecorder travelTimeRecorder) {
5659
this.outputDirectory = outputDirectory;
5760

5861
this.scenarioDistanceUnit = config.getDistanceUnit();
5962
this.analysisDistanceUnit = config.getAnalysisDistanceUnit();
6063

6164
this.analysisInterval = config.getAnalysisInterval();
65+
this.travelTimeInterval = config.getTravelTimeRecordingInterval();
6266

6367
this.tripAnalysisListener = tripListener;
6468
this.legAnalysisListener = legListener;
@@ -70,15 +74,21 @@ public AnalysisOutputListener(EqasimConfigGroup config, OutputDirectoryHierarchy
7074
@Override
7175
public void notifyIterationStarts(IterationStartsEvent event) {
7276
isAnalysisActive = false;
77+
isTravelTimeActive = false;
7378

7479
if (analysisInterval > 0) {
7580
if (event.getIteration() % analysisInterval == 0 || event.isLastIteration()) {
7681
isAnalysisActive = true;
7782
event.getServices().getEvents().addHandler(tripAnalysisListener);
7883
event.getServices().getEvents().addHandler(legAnalysisListener);
7984
event.getServices().getEvents().addHandler(ptAnalysisListener);
85+
}
86+
}
87+
88+
if (travelTimeInterval > 0) {
89+
if (event.getIteration() % travelTimeInterval == 0 || event.isLastIteration()) {
90+
isTravelTimeActive = true;
8091
event.getServices().getEvents().addHandler(activityAnalysisListener);
81-
event.getServices().getEvents().addHandler(travelTimeRecorder);
8292
}
8393
}
8494
}
@@ -91,7 +101,6 @@ public void notifyIterationEnds(IterationEndsEvent event) {
91101
event.getServices().getEvents().removeHandler(legAnalysisListener);
92102
event.getServices().getEvents().removeHandler(ptAnalysisListener);
93103
event.getServices().getEvents().removeHandler(activityAnalysisListener);
94-
event.getServices().getEvents().removeHandler(travelTimeRecorder);
95104

96105
new TripWriter(tripAnalysisListener.getTripItems(), scenarioDistanceUnit, analysisDistanceUnit)
97106
.write(outputDirectory.getIterationFilename(event.getIteration(), TRIPS_FILE_NAME));
@@ -101,11 +110,16 @@ public void notifyIterationEnds(IterationEndsEvent event) {
101110

102111
new ActivityWriter(activityAnalysisListener.getActivityItems())
103112
.write(outputDirectory.getIterationFilename(event.getIteration(), ACTIVITIES_FILE_NAME));
104-
113+
105114
new PublicTransportLegWriter(ptAnalysisListener.getTripItems())
106115
.write(outputDirectory.getIterationFilename(event.getIteration(), PT_FILE_NAME));
116+
}
117+
118+
if (isTravelTimeActive) {
119+
event.getServices().getEvents().removeHandler(travelTimeRecorder);
107120

108-
RecordedTravelTime.writeBinary(outputDirectory.getIterationFilename(event.getIteration(), TRAVEL_TIMES_FILE_NAME),
121+
RecordedTravelTime.writeBinary(
122+
outputDirectory.getIterationFilename(event.getIteration(), TRAVEL_TIMES_FILE_NAME),
109123
this.travelTimeRecorder.getTravelTime());
110124
}
111125
} catch (IOException | InterruptedException e) {
@@ -122,10 +136,11 @@ public void notifyShutdown(ShutdownEvent event) {
122136
new File(outputDirectory.getOutputFilename(LEGS_FILE_NAME)).toPath());
123137
Files.copy(new File(outputDirectory.getIterationFilename(event.getIteration(), PT_FILE_NAME)).toPath(),
124138
new File(outputDirectory.getOutputFilename(PT_FILE_NAME)).toPath());
125-
Files.copy(new File(outputDirectory.getIterationFilename(event.getIteration(), ACTIVITIES_FILE_NAME)).toPath(),
139+
Files.copy(
140+
new File(outputDirectory.getIterationFilename(event.getIteration(), ACTIVITIES_FILE_NAME)).toPath(),
126141
new File(outputDirectory.getOutputFilename(ACTIVITIES_FILE_NAME)).toPath());
127-
Files.copy(new File(outputDirectory.getIterationFilename(event.getIteration(), TRAVEL_TIMES_FILE_NAME)).toPath(),
128-
new File(outputDirectory.getOutputFilename(TRAVEL_TIMES_FILE_NAME)).toPath());
142+
Files.copy(new File(outputDirectory.getIterationFilename(event.getIteration(), TRAVEL_TIMES_FILE_NAME))
143+
.toPath(), new File(outputDirectory.getOutputFilename(TRAVEL_TIMES_FILE_NAME)).toPath());
129144
} catch (IOException e) {
130145
}
131146
}

core/src/main/java/org/eqasim/core/standalone_mode_choice/RunStandaloneModeChoice.java

+3
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
import java.io.BufferedReader;
55
import java.io.FileInputStream;
6+
import java.io.FileNotFoundException;
67
import java.io.IOException;
78
import java.io.InputStream;
89
import java.io.InputStreamReader;
@@ -219,6 +220,8 @@ RecordedTravelTime provideRecordedTravelTime() {
219220
RecordedTravelTime recordedTravelTime = RecordedTravelTime.readBinary(inputStream);
220221
inputStream.close();
221222
return recordedTravelTime;
223+
} catch (FileNotFoundException e) {
224+
throw new IllegalStateException("Travel time input file not found: " + path);
222225
} catch (IOException e) {
223226
throw new RuntimeException(e);
224227
}

core/src/test/java/org/eqasim/TestSimulationPipeline.java

+2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import org.eqasim.core.analysis.run.RunLegAnalysis;
1414
import org.eqasim.core.analysis.run.RunPublicTransportLegAnalysis;
1515
import org.eqasim.core.analysis.run.RunTripAnalysis;
16+
import org.eqasim.core.components.config.EqasimConfigGroup;
1617
import org.eqasim.core.scenario.cutter.RunScenarioCutter;
1718
import org.eqasim.core.scenario.cutter.RunScenarioCutterV2;
1819
import org.eqasim.core.scenario.routing.RunPopulationRouting;
@@ -90,6 +91,7 @@ private void runMelunSimulation(String configPath, String outputPath, String inp
9091
if(lastIteration != null) {
9192
config.controller().setLastIteration(lastIteration);
9293
}
94+
EqasimConfigGroup.get(config).setTravelTimeRecordingInterval(1000);
9395

9496
Scenario scenario = ScenarioUtils.createScenario(config);
9597
eqasimConfigurator.configureScenario(scenario);

ile_de_france/src/test/java/org/eqasim/ile_de_france/TestCorisica.java

+2
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ public void testCorsicaPipeline()
7070
"--config-path", "corsica_test/corsica_config.xml", //
7171
"--config:controler.lastIteration", "2", // ,
7272
"--config:controler.outputDirectory", "corsica_test/simulation_output", //
73+
"--config:eqasim.travelTimeRecordingInterval", "1000", //
7374
});
7475

7576
Assert.assertEquals(389, countPersons("corsica_test/simulation_output/output_plans.xml.gz"));
@@ -115,6 +116,7 @@ public void testCorsicaPipeline()
115116
"--config-path", "corsica_test/cut_config.xml", //
116117
"--config:controler.lastIteration", "2", // ,
117118
"--config:controler.outputDirectory", "corsica_test/cut_output", //
119+
"--config:eqasim.travelTimeRecordingInterval", "1000", //
118120
});
119121

120122
Map<String, Long> counts = countLegs("corsica_test/cut_output/output_events.xml.gz");

0 commit comments

Comments
 (0)