From f14515fd56c2986aa1dcafad9086b9d3515a46ac Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 18 Jan 2023 15:14:32 +0100 Subject: [PATCH 01/11] Bump jackson-databind from 2.12.6.1 to 2.12.7.1 (#151) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Bumps [jackson-databind](https://github.com/FasterXML/jackson) from 2.12.6.1 to 2.12.7.1. - [Release notes](https://github.com/FasterXML/jackson/releases) - [Commits](https://github.com/FasterXML/jackson/commits) --- updated-dependencies: - dependency-name: com.fasterxml.jackson.core:jackson-databind dependency-type: direct:production ... Signed-off-by: dependabot[bot] Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> Co-authored-by: Sebastian Hörl --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index a9880e017..a54ca2860 100644 --- a/pom.xml +++ b/pom.xml @@ -67,7 +67,7 @@ com.fasterxml.jackson.core jackson-databind - 2.12.6.1 + 2.12.7.1 From e7805213796d8f6f423b982979a40150af2420e2 Mon Sep 17 00:00:00 2001 From: tkchouaki Date: Mon, 13 Mar 2023 09:03:29 +0100 Subject: [PATCH 02/11] LegIndex fix (#159) Co-authored-by: Tarek Chouaki --- .../src/main/java/org/eqasim/core/analysis/legs/LegListener.java | 1 + 1 file changed, 1 insertion(+) diff --git a/core/src/main/java/org/eqasim/core/analysis/legs/LegListener.java b/core/src/main/java/org/eqasim/core/analysis/legs/LegListener.java index ebef0073f..c92addd14 100644 --- a/core/src/main/java/org/eqasim/core/analysis/legs/LegListener.java +++ b/core/src/main/java/org/eqasim/core/analysis/legs/LegListener.java @@ -64,6 +64,7 @@ public void reset(int iteration) { ongoing.clear(); passengers.clear(); tripIndex.clear(); + legIndex.clear(); } @Override From 77bd90be512591ae204ca9b6659e6fa300467738 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Thu, 20 Apr 2023 11:22:05 +0200 Subject: [PATCH 03/11] feat: Optionally write out paths when batch routing (#160) * feat: Optionally write out paths when batch routing * fix --- .../core/tools/routing/BatchRoadRouter.java | 12 +++++- .../tools/routing/RunBatchRoadRouter.java | 37 +++++++++++++++---- 2 files changed, 40 insertions(+), 9 deletions(-) diff --git a/core/src/main/java/org/eqasim/core/tools/routing/BatchRoadRouter.java b/core/src/main/java/org/eqasim/core/tools/routing/BatchRoadRouter.java index 6ed4f91ff..2d04d60c9 100644 --- a/core/src/main/java/org/eqasim/core/tools/routing/BatchRoadRouter.java +++ b/core/src/main/java/org/eqasim/core/tools/routing/BatchRoadRouter.java @@ -3,6 +3,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; +import java.util.LinkedList; import java.util.List; import org.eqasim.core.misc.ParallelProgress; @@ -28,13 +29,15 @@ public class BatchRoadRouter { private final int batchSize; private final int numberOfThreads; + private final boolean writePaths; public BatchRoadRouter(Provider routerFactoryProvider, Network network, - int batchSize, int numberOfThreads) { + int batchSize, int numberOfThreads, boolean writePaths) { this.routerFactoryProvider = routerFactoryProvider; this.batchSize = batchSize; this.numberOfThreads = numberOfThreads; this.network = network; + this.writePaths = writePaths; } public Collection run(Collection tasks) throws InterruptedException { @@ -115,6 +118,10 @@ public void run() { result.egressEuclideanDistance_km = CoordUtils.calcEuclideanDistance(toCoord, toLink.getFromNode().getCoord()) * 1e-3; + if (writePaths) { + path.links.forEach(link -> result.path.add(link.getId().toString())); + } + localResults.add(result); progress.update(); } @@ -162,6 +169,9 @@ static public class Result { @JsonProperty("in_vehicle_distance_km") public double inVehicleDistance_km; + @JsonProperty("path") + public List path = new LinkedList<>(); + Result(Task task) { this.identifier = task.identifier; } diff --git a/core/src/main/java/org/eqasim/core/tools/routing/RunBatchRoadRouter.java b/core/src/main/java/org/eqasim/core/tools/routing/RunBatchRoadRouter.java index 4fa8736ee..ce38ba146 100644 --- a/core/src/main/java/org/eqasim/core/tools/routing/RunBatchRoadRouter.java +++ b/core/src/main/java/org/eqasim/core/tools/routing/RunBatchRoadRouter.java @@ -25,6 +25,7 @@ import org.matsim.core.scenario.ScenarioUtils; import com.fasterxml.jackson.core.JsonGenerationException; +import com.fasterxml.jackson.core.JsonGenerator; import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.MappingIterator; import com.fasterxml.jackson.databind.SequenceWriter; @@ -42,7 +43,7 @@ static public void main(String[] args) throws ConfigurationException, JsonGenera IOException, InterruptedException { CommandLine cmd = new CommandLine.Builder(args) // .requireOptions("config-path", "input-path", "output-path") // - .allowOptions("threads", "batch-size", "modes") // + .allowOptions("threads", "batch-size", "modes", "write-paths") // .build(); EqasimConfigurator configurator = new EqasimConfigurator(); @@ -57,6 +58,8 @@ static public void main(String[] args) throws ConfigurationException, JsonGenera .orElse(Runtime.getRuntime().availableProcessors()); int batchSize = cmd.getOption("batch-size").map(Integer::parseInt).orElse(100); + boolean writePaths = cmd.getOption("write-paths").map(Boolean::parseBoolean).orElse(false); + Set modes = new HashSet<>(); for (String mode : cmd.getOption("modes").orElse("car").split(",")) { modes.add(mode); @@ -83,25 +86,43 @@ public Network provideCarNetwork(Network network) { Network network = injector.getInstance(Key.get(Network.class, Names.named("car"))); BatchRoadRouter batchRouter = new BatchRoadRouter(injector.getProvider(LeastCostPathCalculatorFactory.class), - network, batchSize, numberOfThreads); + network, batchSize, numberOfThreads, writePaths); - CsvMapper mapper = new CsvMapper(); + CsvMapper taskMapper = new CsvMapper(); File inputFile = new File(cmd.getOptionStrict("input-path")); - CsvSchema taskSchema = mapper.typedSchemaFor(Task.class).withHeader().withColumnSeparator(',').withComments() - .withColumnReordering(true); + CsvSchema taskSchema = taskMapper.typedSchemaFor(Task.class).withHeader().withColumnSeparator(',') + .withComments().withColumnReordering(true); - MappingIterator taskIterator = mapper.readerWithTypedSchemaFor(Task.class).with(taskSchema) + MappingIterator taskIterator = taskMapper.readerWithTypedSchemaFor(Task.class).with(taskSchema) .readValues(inputFile); List tasks = taskIterator.readAll(); Collection results = batchRouter.run(tasks); + CsvSchema.Builder builder = new CsvSchema.Builder() // + .setColumnSeparator(',') // + .setArrayElementSeparator(" ") // + .setUseHeader(true) // + .addColumn("identifier") // + .addColumn("access_euclidean_distance_km") // + .addColumn("egress_euclidean_distance_km") // + .addColumn("in_vehicle_time_min") // + .addColumn("in_vehicle_distance_km"); + + if (writePaths) { + builder.addArrayColumn("path"); + } + + CsvSchema schema = builder.build(); + File outputFile = new File(cmd.getOptionStrict("output-path")); - CsvSchema resultSchema = mapper.typedSchemaFor(Result.class).withHeader().withColumnSeparator(','); - SequenceWriter writer = mapper.writerWithTypedSchemaFor(Result.class).with(resultSchema) + CsvMapper resultMapper = new CsvMapper(); + resultMapper.configure(JsonGenerator.Feature.IGNORE_UNKNOWN, true); + SequenceWriter writer = resultMapper.writerWithTypedSchemaFor(Result.class).with(schema) .writeValues(outputFile); + writer.writeAll(results); } } From 1a10b832c08605f9041d45bc3637a6cba158bdb8 Mon Sep 17 00:00:00 2001 From: tkchouaki Date: Tue, 23 May 2023 10:46:43 +0200 Subject: [PATCH 04/11] Isolated mode choice (#161) Co-authored-by: Tarek Chouaki --- .../eqasim/ile_de_france/RunModeChoice.java | 156 ++++++++++++++++++ 1 file changed, 156 insertions(+) create mode 100644 ile_de_france/src/main/java/org/eqasim/ile_de_france/RunModeChoice.java diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunModeChoice.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunModeChoice.java new file mode 100644 index 000000000..c8c8c91b2 --- /dev/null +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunModeChoice.java @@ -0,0 +1,156 @@ +package org.eqasim.ile_de_france; + +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.name.Names; +import org.eqasim.core.analysis.PersonAnalysisFilter; +import org.eqasim.core.analysis.trips.TripItem; +import org.eqasim.core.analysis.trips.TripReaderFromPopulation; +import org.eqasim.core.misc.InjectorBuilder; +import org.eqasim.core.scenario.validation.ScenarioValidator; +import org.eqasim.core.simulation.analysis.EqasimAnalysisModule; +import org.eqasim.core.simulation.mode_choice.EqasimModeChoiceModule; +import org.eqasim.ile_de_france.mode_choice.IDFModeChoiceModule; +import org.matsim.api.core.v01.Scenario; +import org.matsim.api.core.v01.population.Person; +import org.matsim.api.core.v01.population.Population; +import org.matsim.api.core.v01.population.PopulationWriter; +import org.matsim.contribs.discrete_mode_choice.modules.DiscreteModeChoiceModule; +import org.matsim.contribs.discrete_mode_choice.modules.ModelModule; +import org.matsim.core.config.CommandLine; +import org.matsim.core.config.Config; +import org.matsim.core.config.ConfigGroup; +import org.matsim.core.config.ConfigUtils; +import org.matsim.core.config.groups.StrategyConfigGroup; +import org.matsim.core.controler.AbstractModule; +import org.matsim.core.controler.ControlerDefaultsModule; +import org.matsim.core.controler.NewControlerModule; +import org.matsim.core.controler.corelisteners.ControlerDefaultCoreListenersModule; +import org.matsim.core.replanning.PlanStrategy; +import org.matsim.core.replanning.ReplanningContext; +import org.matsim.core.router.MainModeIdentifier; +import org.matsim.core.scenario.ScenarioUtils; + +import java.io.BufferedWriter; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.util.*; + + +/** + * This class isolates the discrete mode choice model component of Eqasim and performs the mode choice on all the agents of a provided population + * It is meant to be ran from the command line with the following arguments + * - config-path: mandatory, the path of the MATSim config file indicating the population on which the mode choice model should be performed. This configuration also specifies the parameters of the mode choice model and other parameters. + * - output-plans-path: optional, when used, writes a plans file containing the new agent plans resulting from the mode choice + * - output-csv-path: optional, when used, writes a csv file with the header personId;tripId;mode indicating the new modes of agent trips + * - base-csv-path: optional, when used, writes a csv file containing the base modes of agent trips before performing the mode choice + * At least one of the arguments output-plans-path and output-csv-path should be used. + * Parameters in the configuration file can be overridden in the command line by using an argument of the form config:arg=value. + * E.g. --config-path=config.xml --output-plans-path=plans_out.xml.gz --output-csv-path=trip_modes_out.csv --base-csv-path=trip_modes_in.csv --config:global.numberOfThreads=10 + */ +public class RunModeChoice { + + public static void main(String[] args) throws CommandLine.ConfigurationException { + CommandLine cmd = new CommandLine.Builder(args) // + .requireOptions("config-path") + .allowOptions("output-plans-path", "output-csv-path", "base-csv-path") + .build(); + + Config config = ConfigUtils.loadConfig(cmd.getOptionStrict("config-path")); + Optional outputPlansPath = cmd.getOption("output-plans-path"); + Optional outputCsvPath = cmd.getOption("output-csv-path"); + + if(outputPlansPath.isEmpty() && outputCsvPath.isEmpty()) { + throw new IllegalStateException("At least one of output-plans-path and output-csv-path should be provided"); + } + + IDFConfigurator configurator = new IDFConfigurator(); + for(ConfigGroup configGroup : configurator.getConfigGroups()) { + config.addModule(configGroup); + } + cmd.applyConfiguration(config); + + // We make sure the config is set to use DiscreteModeChoice, i.e. contains a DiscreteModeChoice module and a DiscreteModeChoice strategy settings + boolean containsDiscreteModeChoiceStrategy = false; + for(StrategyConfigGroup.StrategySettings strategySettings: config.strategy().getStrategySettings()) { + if(strategySettings.getStrategyName().equals("DiscreteModeChoice")) { + containsDiscreteModeChoiceStrategy = true; + break; + } + } + if(!containsDiscreteModeChoiceStrategy || !config.getModules().containsKey("DiscreteModeChoice")) { + throw new IllegalStateException("The config file is not set to use DiscreteModeChoice"); + } + + Scenario scenario = ScenarioUtils.createScenario(config); + ScenarioUtils.loadScenario(scenario); + + ScenarioValidator scenarioValidator = new ScenarioValidator(); + scenarioValidator.checkScenario(scenario); + + InjectorBuilder injectorBuilder = new InjectorBuilder(scenario) + .addOverridingModule(new NewControlerModule()) + .addOverridingModule(new ControlerDefaultCoreListenersModule()) + .addOverridingModule(new ControlerDefaultsModule()) + .addOverridingModule(new IDFModeChoiceModule(cmd)) + .addOverridingModule(new EqasimModeChoiceModule()) + .addOverridingModule(new EqasimAnalysisModule()) + .addOverridingModule(new ModelModule()) + .addOverridingModule(new DiscreteModeChoiceModule()); + + for(AbstractModule module: configurator.getModules()) { + injectorBuilder.addOverridingModule(module); + } + Injector injector = injectorBuilder.build(); + + + Population population = injector.getInstance(Population.class); + // We init the TripReaderFromPopulation here as we might need it just below + TripReaderFromPopulation tripReader = new TripReaderFromPopulation(Arrays.asList("car,pt".split(",")), injector.getInstance(MainModeIdentifier.class), injector.getInstance(PersonAnalysisFilter.class), Optional.empty(), Optional.empty()); + cmd.getOption("base-csv-path").ifPresent(s -> { + //We write the initial trip modes + Collection trips = tripReader.readTrips(population); + writeTripModesToCsv(trips, s); + }); + + // We retrieve the DiscreteModeChoice Strategy here + PlanStrategy strategy = injector.getInstance(Key.get(PlanStrategy.class, Names.named("DiscreteModeChoice"))); + /* + * Depending on the configuration, the strategy can be set to use multiple threads or not. + * In the former case, the threads need to be created before running the strategy. + */ + strategy.init(injector.getInstance(ReplanningContext.class)); + for(Person person: population.getPersons().values()) { + strategy.run(person); + } + /* + * In the multithreaded case, the run method only adds the person to the queue of a given thread. + * We need to call the finish method to actually perform the mode choice. + */ + strategy.finish(); + outputPlansPath.ifPresent(s -> new PopulationWriter(population).write(s)); + outputCsvPath.ifPresent(s -> { + Collection trips = tripReader.readTrips(population); + writeTripModesToCsv(trips, s); + }); + } + + public static void writeTripModesToCsv(Collection trips, String outputPath) { + try { + BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outputPath))); + + writer.write( "personId;tripId;mode\n"); + writer.flush(); + + for (TripItem trip : trips) { + writer.write( String.join(";", trip.personId.toString(), trip.personTripId+"", trip.mode) + "\n"); + writer.flush(); + } + writer.flush(); + writer.close(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } +} From 7d18076feda74a5784069f8c1f66e37f795bba34 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?N=C3=A9da?= <79261451+neda-git@users.noreply.github.com> Date: Mon, 19 Jun 2023 10:59:56 +0200 Subject: [PATCH 05/11] Update RunExportEmissionsNetwork.java (#163) Adding other polluants like NO2,SO2,PM2_5 --- .../ile_de_france/emissions/RunExportEmissionsNetwork.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/emissions/RunExportEmissionsNetwork.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/emissions/RunExportEmissionsNetwork.java index c543f01a8..82ba51c46 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/emissions/RunExportEmissionsNetwork.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/emissions/RunExportEmissionsNetwork.java @@ -71,6 +71,9 @@ public static void main(String[] args) throws CommandLine.ConfigurationException .addAttribute("HC", Double.class) // .addAttribute("NOx", Double.class) // .addAttribute("CO2_rep", Double.class) // + .addAttribute("NO2", Double.class) // + .addAttribute("PM2_5", Double.class) // + .addAttribute("SO2", Double.class) // .create(); for (TimeBinMap.TimeBin, EmissionsByPollutant>> timeBin : res.getTimeBins()) { From 43fe9846f8b54bb400ef260916e62221417bba6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Tue, 20 Jun 2023 11:00:56 +0200 Subject: [PATCH 06/11] fix: revert untested changes in emissions (#166) --- .../ile_de_france/emissions/RunExportEmissionsNetwork.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/emissions/RunExportEmissionsNetwork.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/emissions/RunExportEmissionsNetwork.java index 82ba51c46..c543f01a8 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/emissions/RunExportEmissionsNetwork.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/emissions/RunExportEmissionsNetwork.java @@ -71,9 +71,6 @@ public static void main(String[] args) throws CommandLine.ConfigurationException .addAttribute("HC", Double.class) // .addAttribute("NOx", Double.class) // .addAttribute("CO2_rep", Double.class) // - .addAttribute("NO2", Double.class) // - .addAttribute("PM2_5", Double.class) // - .addAttribute("SO2", Double.class) // .create(); for (TimeBinMap.TimeBin, EmissionsByPollutant>> timeBin : res.getTimeBins()) { From 21dabcaa03c4010c36d996a242e70821936bf132 Mon Sep 17 00:00:00 2001 From: tkchouaki Date: Wed, 21 Jun 2023 12:33:24 +0200 Subject: [PATCH 07/11] Isolated mode choice (#165) * Isolated mode choice * Ability to provide travel time delay factors --------- Co-authored-by: Tarek Chouaki --- .../eqasim/ile_de_france/RunModeChoice.java | 88 +++++++++++++++++-- 1 file changed, 79 insertions(+), 9 deletions(-) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunModeChoice.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunModeChoice.java index c8c8c91b2..012d77e89 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunModeChoice.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunModeChoice.java @@ -12,6 +12,7 @@ import org.eqasim.core.simulation.mode_choice.EqasimModeChoiceModule; import org.eqasim.ile_de_france.mode_choice.IDFModeChoiceModule; import org.matsim.api.core.v01.Scenario; +import org.matsim.api.core.v01.network.Link; import org.matsim.api.core.v01.population.Person; import org.matsim.api.core.v01.population.Population; import org.matsim.api.core.v01.population.PopulationWriter; @@ -29,12 +30,12 @@ import org.matsim.core.replanning.PlanStrategy; import org.matsim.core.replanning.ReplanningContext; import org.matsim.core.router.MainModeIdentifier; +import org.matsim.core.router.util.TravelTime; import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.core.trafficmonitoring.FreeSpeedTravelTime; +import org.matsim.vehicles.Vehicle; -import java.io.BufferedWriter; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.OutputStreamWriter; +import java.io.*; import java.util.*; @@ -51,10 +52,67 @@ */ public class RunModeChoice { + public static class TravelTimeFactors implements TravelTime { + + private final String filePath; + private final FreeSpeedTravelTime freeSpeedTravelTime; + private List congestionSlotUpperBounds; + private List congestionSlotSpeedFactor; + private static final String CSV_SEPARATOR = ";"; + private static final String TIME_UPPER_BOUND_COLUMN = "timeUpperBound"; + private static final String CONGESTION_FACTOR_COLUMN = "travelTimeFactor"; + + public TravelTimeFactors(String filePath) { + this.filePath = filePath; + this.freeSpeedTravelTime = new FreeSpeedTravelTime(); + try { + this.readFile(); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private void readFile() throws IOException { + this.congestionSlotSpeedFactor = new ArrayList<>(); + this.congestionSlotUpperBounds = new ArrayList<>(); + BufferedReader reader = new BufferedReader( + new InputStreamReader(new FileInputStream(this.filePath))); + String line; + List header = null; + while ((line = reader.readLine()) != null) { + List row = Arrays.asList(line.split(CSV_SEPARATOR)); + + if (header == null) { + header = row; + } else { + double timeUpperBound = Double.parseDouble(row.get(header.indexOf(TIME_UPPER_BOUND_COLUMN))); + double speedFactor = Double.parseDouble(row.get(header.indexOf(CONGESTION_FACTOR_COLUMN))); + if(this.congestionSlotUpperBounds.size() > 0 && this.congestionSlotUpperBounds.get(this.congestionSlotUpperBounds.size()-1) >= timeUpperBound) { + throw new IllegalStateException(); + } + this.congestionSlotUpperBounds.add(timeUpperBound); + this.congestionSlotSpeedFactor.add(speedFactor); + } + } + reader.close(); + } + + @Override + public double getLinkTravelTime(Link link, double time, Person person, Vehicle vehicle) { + int slotIndex; + for(slotIndex=this.congestionSlotSpeedFactor.size()-1; slotIndex>0 && congestionSlotUpperBounds.get(slotIndex)>time; slotIndex--); + if(slotIndex < 0) { + slotIndex=0; + } + return this.freeSpeedTravelTime.getLinkTravelTime(link, time, person, vehicle) * congestionSlotSpeedFactor.get(slotIndex); + } + } + public static void main(String[] args) throws CommandLine.ConfigurationException { CommandLine cmd = new CommandLine.Builder(args) // .requireOptions("config-path") .allowOptions("output-plans-path", "output-csv-path", "base-csv-path") + .allowOptions("travel-times-factors-path") .build(); Config config = ConfigUtils.loadConfig(cmd.getOptionStrict("config-path")); @@ -98,6 +156,15 @@ public static void main(String[] args) throws CommandLine.ConfigurationException .addOverridingModule(new EqasimAnalysisModule()) .addOverridingModule(new ModelModule()) .addOverridingModule(new DiscreteModeChoiceModule()); + if(cmd.hasOption("travel-times-factors-path")) { + String travelTimesFactorsPath = cmd.getOptionStrict("travel-times-factors-path"); + injectorBuilder.addOverridingModule(new AbstractModule() { + @Override + public void install() { + addTravelTimeBinding("car").toInstance(new TravelTimeFactors(travelTimesFactorsPath)); + } + }); + } for(AbstractModule module: configurator.getModules()) { injectorBuilder.addOverridingModule(module); @@ -107,6 +174,12 @@ public static void main(String[] args) throws CommandLine.ConfigurationException Population population = injector.getInstance(Population.class); // We init the TripReaderFromPopulation here as we might need it just below + // We retrieve the DiscreteModeChoice Strategy here + /* + * Depending on the configuration, the strategy can be set to use multiple threads or not. + * In the former case, the threads need to be created before running the strategy. + */ + TripReaderFromPopulation tripReader = new TripReaderFromPopulation(Arrays.asList("car,pt".split(",")), injector.getInstance(MainModeIdentifier.class), injector.getInstance(PersonAnalysisFilter.class), Optional.empty(), Optional.empty()); cmd.getOption("base-csv-path").ifPresent(s -> { //We write the initial trip modes @@ -114,12 +187,9 @@ public static void main(String[] args) throws CommandLine.ConfigurationException writeTripModesToCsv(trips, s); }); - // We retrieve the DiscreteModeChoice Strategy here + PlanStrategy strategy = injector.getInstance(Key.get(PlanStrategy.class, Names.named("DiscreteModeChoice"))); - /* - * Depending on the configuration, the strategy can be set to use multiple threads or not. - * In the former case, the threads need to be created before running the strategy. - */ + strategy.init(injector.getInstance(ReplanningContext.class)); for(Person person: population.getPersons().values()) { strategy.run(person); From 9574f3cacba2de634cbb7ffaa95b4d3565444692 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Tue, 27 Jun 2023 16:36:13 +0200 Subject: [PATCH 08/11] fix: Make batch routing more flexible wrt transit modes (#167) --- .../routing/BatchPublicTransportRouter.java | 20 ++++++++----------- .../RunBatchPublicTransportRouter.java | 2 +- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/core/src/main/java/org/eqasim/core/tools/routing/BatchPublicTransportRouter.java b/core/src/main/java/org/eqasim/core/tools/routing/BatchPublicTransportRouter.java index 879609679..96aecd4dd 100644 --- a/core/src/main/java/org/eqasim/core/tools/routing/BatchPublicTransportRouter.java +++ b/core/src/main/java/org/eqasim/core/tools/routing/BatchPublicTransportRouter.java @@ -4,7 +4,6 @@ import java.util.Collection; import java.util.Iterator; import java.util.List; -import java.util.Set; import java.util.stream.Collectors; import org.apache.commons.lang3.tuple.Pair; @@ -36,11 +35,9 @@ public class BatchPublicTransportRouter { private final int numberOfThreads; private final double interval; - private final Set transitModes; - public BatchPublicTransportRouter(Provider routerProvider, Provider headwayCalculatorProvider, TransitSchedule schedule, Network network, - int batchSize, int numberOfThreads, double interval, Set transitModes) { + int batchSize, int numberOfThreads, double interval) { this.routerProvider = routerProvider; this.headwayCalculatorProvider = headwayCalculatorProvider; this.batchSize = batchSize; @@ -48,7 +45,6 @@ public BatchPublicTransportRouter(Provider routerProvider, this.schedule = schedule; this.network = network; this.interval = interval; - this.transitModes = transitModes; } public Pair, Collection> run(Collection tasks) @@ -146,12 +142,16 @@ public void run() { } else if (leg.getMode().contains("walk") && isLastLeg) { tripInformation.egressTravelTime_min += leg.getTravelTime().seconds() / 60.0; tripInformation.egressDistance_km += leg.getRoute().getDistance() * 1e-3; - } else if (leg.getMode().contains("walk") && !isFirstLeg && !isLastLeg) { + } else if (leg.getMode().contains("walk")) { tripInformation.transferTravelTime_min += leg.getTravelTime().seconds() / 60.0; tripInformation.transferDistance_km += leg.getRoute().getDistance() * 1e-3; - } else if (transitModes.contains(leg.getMode())) { + } else if (leg.getRoute() instanceof TransitPassengerRoute) { TransitPassengerRoute route = (TransitPassengerRoute) leg.getRoute(); + TransitLine transitLine = schedule.getTransitLines().get(route.getLineId()); + TransitRoute transitRoute = transitLine.getRoutes().get(route.getRouteId()); + String transitMode = transitRoute.getTransportMode(); + double waitingTime = route.getBoardingTime().seconds() - leg.getDepartureTime().seconds(); @@ -163,10 +163,6 @@ public void run() { tripInformation.transferWaitingTime_min += waitingTime / 60.0; } - TransitLine transitLine = schedule.getTransitLines().get(route.getLineId()); - TransitRoute transitRoute = transitLine.getRoutes().get(route.getRouteId()); - String transitMode = transitRoute.getTransportMode(); - double inVehicleTime = route.getTravelTime().seconds() - waitingTime; switch (transitMode) { @@ -210,7 +206,7 @@ public void run() { localLegResults.add(legInformation); } } else { - throw new IllegalStateException(); + throw new IllegalStateException("Don't know what to do with mode: " + leg.getMode()); } currentIndex++; diff --git a/core/src/main/java/org/eqasim/core/tools/routing/RunBatchPublicTransportRouter.java b/core/src/main/java/org/eqasim/core/tools/routing/RunBatchPublicTransportRouter.java index fc39573c3..410382945 100644 --- a/core/src/main/java/org/eqasim/core/tools/routing/RunBatchPublicTransportRouter.java +++ b/core/src/main/java/org/eqasim/core/tools/routing/RunBatchPublicTransportRouter.java @@ -270,7 +270,7 @@ static public void main(String[] args) throws ConfigurationException, JsonGenera Network network = injector.getInstance(Network.class); BatchPublicTransportRouter batchRouter = new BatchPublicTransportRouter(routerProvider, - headwayCalculatorProvider, schedule, network, batchSize, numberOfThreads, interval, transitModes); + headwayCalculatorProvider, schedule, network, batchSize, numberOfThreads, interval); CsvMapper mapper = new CsvMapper(); From 582f4015f9c09b99e431dc8b19c75233729a0e0d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20H=C3=B6rl?= Date: Sun, 9 Jul 2023 23:18:37 +0200 Subject: [PATCH 09/11] Update to MATSim 14 (#132) * Update to MATSim 14 * Fixed BatchPublicTransportRouter * updated CHANGELOG.md --------- Co-authored-by: Tarek Chouaki --- CHANGELOG.md | 8 +++++++- .../core/components/headway/HeadwayCalculator.java | 3 ++- .../core/scenario/cutter/RunScenarioCutter.java | 3 +++ .../eqasim/core/scenario/routing/PlanRouter.java | 2 +- .../mode_choice/EqasimModeChoiceModule.java | 6 +++--- .../utilities/ModalUtilityEstimator.java | 6 +++--- .../tools/routing/BatchPublicTransportRouter.java | 14 ++++++++++---- .../mode_choice/TestSpecialModeChoiceCases.java | 10 ++++++---- .../corsica_drt/RunCorsicaDrtSimulation.java | 2 +- .../org/eqasim/ile_de_france/TestCorisica.java | 4 ++-- pom.xml | 2 +- 11 files changed, 39 insertions(+), 21 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e6c9d1ff4..b151a0381 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,13 @@ This change log is written in descending order. Changes that happen after versio included in the (note yet determined) next version number. **Development version** - + +- Updated to MATSim 14 +- Isolated the mode choice model in a standalone runnable script +- Fixed LegIndex count between iterations in legs analysis +- Improved batch routing tools +- Allow boolean values in parameter definition +- Added stop area to transit leg analysis output - Improve functionality of routing tools to set utilities in detail - Fix bug in EqasimTransitQSimModule: first check if EqasimConfigGroup has TransitEngineModule before removing it - Updated config option from `eqasim.tripAnalysisInterval` to `eqasim.analysisInterval` diff --git a/core/src/main/java/org/eqasim/core/components/headway/HeadwayCalculator.java b/core/src/main/java/org/eqasim/core/components/headway/HeadwayCalculator.java index a4a66b2f6..94ee33343 100644 --- a/core/src/main/java/org/eqasim/core/components/headway/HeadwayCalculator.java +++ b/core/src/main/java/org/eqasim/core/components/headway/HeadwayCalculator.java @@ -3,6 +3,7 @@ import java.util.List; import org.matsim.facilities.Facility; +import org.matsim.utils.objectattributes.attributable.Attributes; import ch.sbb.matsim.routing.pt.raptor.RaptorRoute; import ch.sbb.matsim.routing.pt.raptor.RaptorRoute.RoutePart; @@ -25,7 +26,7 @@ public double calculateHeadway_min(Facility originFacility, Facility destination double latestDepartureTime = departureTime + afterDepartureOffset; List routes = raptor.calcRoutes(originFacility, destinationFacilty, earliestDepartureTime, - departureTime, latestDepartureTime, null); + departureTime, latestDepartureTime, null, new Attributes()); int numberOfPtRoutes = 0; diff --git a/core/src/main/java/org/eqasim/core/scenario/cutter/RunScenarioCutter.java b/core/src/main/java/org/eqasim/core/scenario/cutter/RunScenarioCutter.java index 7e62bc30e..e78006028 100644 --- a/core/src/main/java/org/eqasim/core/scenario/cutter/RunScenarioCutter.java +++ b/core/src/main/java/org/eqasim/core/scenario/cutter/RunScenarioCutter.java @@ -33,6 +33,7 @@ import org.matsim.core.config.Config; import org.matsim.core.config.ConfigUtils; import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.core.utils.timing.TimeInterpretationModule; import com.google.inject.Injector; @@ -100,6 +101,7 @@ static public void main(String[] args) .addOverridingModule( new PopulationCutterModule(extent, numberOfThreads, 40, cmd.getOption("events-path"))) // .addOverridingModule(new CutterTravelTimeModule(travelTime)) // + .addOverridingModule(new TimeInterpretationModule()) // .build(); PopulationCutter populationCutter = populationCutterInjector.getInstance(PopulationCutter.class); @@ -151,6 +153,7 @@ static public void main(String[] args) .addOverridingModules(configurator.getModules()) // .addOverridingModule(new PopulationRouterModule(numberOfThreads, 100, false)) // .addOverridingModule(new CutterTravelTimeModule(travelTime)) // + .addOverridingModule(new TimeInterpretationModule()) // .build(); PopulationRouter router = routingInjector.getInstance(PopulationRouter.class); diff --git a/core/src/main/java/org/eqasim/core/scenario/routing/PlanRouter.java b/core/src/main/java/org/eqasim/core/scenario/routing/PlanRouter.java index 343d0cfda..bff821f49 100644 --- a/core/src/main/java/org/eqasim/core/scenario/routing/PlanRouter.java +++ b/core/src/main/java/org/eqasim/core/scenario/routing/PlanRouter.java @@ -53,7 +53,7 @@ public void run(Plan plan, boolean replaceExistingRoutes, Set modes) { Facility toFacility = FacilitiesUtils.toFacility(trip.getDestinationActivity(), facilities); List newElements = tripRouter.calcRoute(mainMode, fromFacility, toFacility, - departureTime.seconds(), plan.getPerson()); + departureTime.seconds(), plan.getPerson(), trip.getTripAttributes()); TripRouter.insertTrip(plan, trip.getOriginActivity(), newElements, trip.getDestinationActivity()); } diff --git a/core/src/main/java/org/eqasim/core/simulation/mode_choice/EqasimModeChoiceModule.java b/core/src/main/java/org/eqasim/core/simulation/mode_choice/EqasimModeChoiceModule.java index b9a63e941..b6bdf3773 100644 --- a/core/src/main/java/org/eqasim/core/simulation/mode_choice/EqasimModeChoiceModule.java +++ b/core/src/main/java/org/eqasim/core/simulation/mode_choice/EqasimModeChoiceModule.java @@ -27,8 +27,8 @@ import org.matsim.contribs.discrete_mode_choice.components.utils.home_finder.HomeFinder; import org.matsim.contribs.discrete_mode_choice.modules.config.DiscreteModeChoiceConfigGroup; import org.matsim.contribs.discrete_mode_choice.modules.config.VehicleTourConstraintConfigGroup; -import org.matsim.contribs.discrete_mode_choice.replanning.time_interpreter.TimeInterpreter; import org.matsim.core.router.TripRouter; +import org.matsim.core.utils.timing.TimeInterpretation; import org.matsim.facilities.ActivityFacilities; import com.google.inject.Provider; @@ -87,7 +87,7 @@ protected void installEqasimExtension() { @Provides public ModalUtilityEstimator provideModularUtilityEstimator(TripRouter tripRouter, ActivityFacilities facilities, Map> factory, EqasimConfigGroup config, - TimeInterpreter.Factory timeInterpreterFactory, DiscreteModeChoiceConfigGroup dmcConfig) { + TimeInterpretation timeInterpretation, DiscreteModeChoiceConfigGroup dmcConfig) { Map estimators = new HashMap<>(); for (Map.Entry entry : config.getEstimators().entrySet()) { @@ -101,7 +101,7 @@ public ModalUtilityEstimator provideModularUtilityEstimator(TripRouter tripRoute } } - return new ModalUtilityEstimator(tripRouter, facilities, estimators, timeInterpreterFactory, + return new ModalUtilityEstimator(tripRouter, facilities, estimators, timeInterpretation, Collections.emptySet()); // Here we may add "pt" etc. as pre-routed modes. } diff --git a/core/src/main/java/org/eqasim/core/simulation/mode_choice/utilities/ModalUtilityEstimator.java b/core/src/main/java/org/eqasim/core/simulation/mode_choice/utilities/ModalUtilityEstimator.java index 47e910758..35819e3fa 100644 --- a/core/src/main/java/org/eqasim/core/simulation/mode_choice/utilities/ModalUtilityEstimator.java +++ b/core/src/main/java/org/eqasim/core/simulation/mode_choice/utilities/ModalUtilityEstimator.java @@ -9,17 +9,17 @@ import org.matsim.contribs.discrete_mode_choice.components.estimators.AbstractTripRouterEstimator; import org.matsim.contribs.discrete_mode_choice.model.DiscreteModeChoiceTrip; import org.matsim.contribs.discrete_mode_choice.model.trip_based.candidates.TripCandidate; -import org.matsim.contribs.discrete_mode_choice.replanning.time_interpreter.TimeInterpreter; import org.matsim.core.router.TripRouter; +import org.matsim.core.utils.timing.TimeInterpretation; import org.matsim.facilities.ActivityFacilities; public class ModalUtilityEstimator extends AbstractTripRouterEstimator { private final Map estimators; public ModalUtilityEstimator(TripRouter tripRouter, ActivityFacilities facilities, - Map estimators, TimeInterpreter.Factory timeInterpreterFactory, + Map estimators, TimeInterpretation timeInterpretation, Collection preroutedModes) { - super(tripRouter, facilities, timeInterpreterFactory, preroutedModes); + super(tripRouter, facilities, timeInterpretation, preroutedModes); this.estimators = estimators; } diff --git a/core/src/main/java/org/eqasim/core/tools/routing/BatchPublicTransportRouter.java b/core/src/main/java/org/eqasim/core/tools/routing/BatchPublicTransportRouter.java index 96aecd4dd..90b667c1f 100644 --- a/core/src/main/java/org/eqasim/core/tools/routing/BatchPublicTransportRouter.java +++ b/core/src/main/java/org/eqasim/core/tools/routing/BatchPublicTransportRouter.java @@ -12,7 +12,9 @@ import org.matsim.api.core.v01.Coord; import org.matsim.api.core.v01.network.Network; import org.matsim.api.core.v01.population.Leg; +import org.matsim.api.core.v01.population.PlanElement; import org.matsim.core.network.NetworkUtils; +import org.matsim.core.router.DefaultRoutingRequest; import org.matsim.core.router.LinkWrapperFacility; import org.matsim.facilities.Facility; import org.matsim.pt.router.TransitRouter; @@ -117,9 +119,9 @@ public void run() { Facility fromFacility = new LinkWrapperFacility(NetworkUtils.getNearestLink(network, fromCoord)); Facility toFacility = new LinkWrapperFacility(NetworkUtils.getNearestLink(network, toCoord)); - List legs = router.calcRoute(fromFacility, toFacility, task.departureTime, null); + List planElements = router.calcRoute(DefaultRoutingRequest.withoutAttributes(fromFacility, toFacility, task.departureTime, null)); - if (legs != null) { + if (planElements != null) { boolean isFirstVehicularLeg = true; tripInformation.isOnlyWalk = 1; @@ -132,9 +134,13 @@ public void run() { int currentIndex = 0; - for (Leg leg : legs) { + for (PlanElement planElement : planElements) { + if(!(planElement instanceof Leg)) { + continue; + } + Leg leg = (Leg) planElement; boolean isFirstLeg = currentIndex == 0; - boolean isLastLeg = currentIndex == legs.size() - 1; + boolean isLastLeg = currentIndex == planElements.size() - 1; if (leg.getMode().contains("walk") && isFirstLeg) { tripInformation.accessTravelTime_min += leg.getTravelTime().seconds() / 60.0; diff --git a/core/src/test/java/org/eqasim/mode_choice/TestSpecialModeChoiceCases.java b/core/src/test/java/org/eqasim/mode_choice/TestSpecialModeChoiceCases.java index 84012b03d..167023d44 100644 --- a/core/src/test/java/org/eqasim/mode_choice/TestSpecialModeChoiceCases.java +++ b/core/src/test/java/org/eqasim/mode_choice/TestSpecialModeChoiceCases.java @@ -39,8 +39,10 @@ import org.matsim.core.config.ConfigUtils; import org.matsim.core.population.PopulationUtils; import org.matsim.core.router.RoutingModule; +import org.matsim.core.router.RoutingRequest; import org.matsim.core.scenario.ScenarioUtils; -import org.matsim.facilities.Facility; +import org.matsim.core.utils.timing.TimeInterpretationModule; +import org.matsim.utils.objectattributes.attributable.Attributes; import com.google.inject.Inject; import com.google.inject.Injector; @@ -152,6 +154,7 @@ static private Set findChains(List trips, int sa .addOverridingModules(configurator.getModules()) // .addOverridingModule(new EqasimModeChoiceModule()) // .addOverridingModule(new StaticModeAvailabilityModule()) // + .addOverridingModule(new TimeInterpretationModule()) // .build(); DiscreteModeChoiceModel model = injector.getInstance(DiscreteModeChoiceModel.class); @@ -185,7 +188,7 @@ static private void appendTrip(List trips, String preced destinationActivity.setMaximumDuration(3600.0); DiscreteModeChoiceTrip trip = new DiscreteModeChoiceTrip(originActivity, destinationActivity, "walk", - Collections.emptyList(), 0, trips.size(), trips.size()); + Collections.emptyList(), 0, trips.size(), trips.size(), new Attributes()); trips.add(trip); } @@ -210,8 +213,7 @@ public StaticRoutingModule(PopulationFactory populationFactory) { } @Override - public List calcRoute(Facility fromFacility, Facility toFacility, double departureTime, - Person person) { + public List calcRoute(RoutingRequest request) { Leg leg = populationFactory.createLeg("doesn't matter"); leg.setTravelTime(3600.0); diff --git a/examples/src/main/java/org/eqasim/examples/corsica_drt/RunCorsicaDrtSimulation.java b/examples/src/main/java/org/eqasim/examples/corsica_drt/RunCorsicaDrtSimulation.java index 10e6b70d8..38a7d840d 100644 --- a/examples/src/main/java/org/eqasim/examples/corsica_drt/RunCorsicaDrtSimulation.java +++ b/examples/src/main/java/org/eqasim/examples/corsica_drt/RunCorsicaDrtSimulation.java @@ -17,7 +17,7 @@ import org.eqasim.ile_de_france.mode_choice.IDFModeChoiceModule; import org.matsim.api.core.v01.Scenario; import org.matsim.contrib.drt.optimizer.insertion.DrtInsertionSearchParams; -import org.matsim.contrib.drt.optimizer.insertion.SelectiveInsertionSearchParams; +import org.matsim.contrib.drt.optimizer.insertion.selective.SelectiveInsertionSearchParams; import org.matsim.contrib.drt.routing.DrtRoute; import org.matsim.contrib.drt.routing.DrtRouteFactory; import org.matsim.contrib.drt.run.DrtConfigGroup; diff --git a/ile_de_france/src/test/java/org/eqasim/ile_de_france/TestCorisica.java b/ile_de_france/src/test/java/org/eqasim/ile_de_france/TestCorisica.java index 20ddd697f..a6b7ae128 100644 --- a/ile_de_france/src/test/java/org/eqasim/ile_de_france/TestCorisica.java +++ b/ile_de_france/src/test/java/org/eqasim/ile_de_france/TestCorisica.java @@ -52,7 +52,7 @@ public void testCorsicaPipeline() Assert.assertEquals(3162, countPersons("corsica_test/simulation_output/output_plans.xml.gz")); Map counts = countLegs("corsica_test/simulation_output/output_events.xml.gz"); - Assert.assertEquals(7782, (long) counts.get("car")); + Assert.assertEquals(7781, (long) counts.get("car")); Assert.assertEquals(894, (long) counts.get("car_passenger")); Assert.assertEquals(2091, (long) counts.get("walk")); Assert.assertEquals(2, (long) counts.get("bike")); @@ -86,7 +86,7 @@ public void testCorsicaPipeline() Map counts = countLegs("corsica_test/cut_output/output_events.xml.gz"); Assert.assertEquals(3001, (long) counts.get("car")); Assert.assertEquals(387, (long) counts.get("car_passenger")); - Assert.assertEquals(845, (long) counts.get("walk")); + Assert.assertEquals(847, (long) counts.get("walk")); Assert.assertEquals(0, (long) counts.getOrDefault("bike", 0L)); Assert.assertEquals(6, (long) counts.get("pt")); Assert.assertEquals(95, (long) counts.get("outside")); diff --git a/pom.xml b/pom.xml index a54ca2860..392b6d3bb 100644 --- a/pom.xml +++ b/pom.xml @@ -22,7 +22,7 @@ 11 11 - 13.0 + 14.0 From 7cbe85b251f8adf9dacc29adc7e386abb853b614 Mon Sep 17 00:00:00 2001 From: tkchouaki Date: Tue, 29 Aug 2023 13:58:40 +0200 Subject: [PATCH 10/11] Fixed Missing TimeInterpretationModule (#169) Co-authored-by: Tarek Chouaki --- .../org/eqasim/core/scenario/routing/RunPopulationRouting.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/src/main/java/org/eqasim/core/scenario/routing/RunPopulationRouting.java b/core/src/main/java/org/eqasim/core/scenario/routing/RunPopulationRouting.java index d2d36d414..7a6b3d16e 100644 --- a/core/src/main/java/org/eqasim/core/scenario/routing/RunPopulationRouting.java +++ b/core/src/main/java/org/eqasim/core/scenario/routing/RunPopulationRouting.java @@ -12,6 +12,7 @@ import org.matsim.core.config.ConfigUtils; import org.matsim.core.population.io.PopulationWriter; import org.matsim.core.scenario.ScenarioUtils; +import org.matsim.core.utils.timing.TimeInterpretationModule; import org.matsim.facilities.ActivityFacility; import com.google.inject.Injector; @@ -53,6 +54,7 @@ static public void main(String[] args) throws ConfigurationException, Interrupte Injector injector = new InjectorBuilder(scenario) // .addOverridingModules(configurator.getModules()) // .addOverridingModule(new PopulationRouterModule(numberOfThreads, batchSize, true, modes)) // + .addOverridingModule(new TimeInterpretationModule()) .build(); PopulationRouter populationRouter = injector.getInstance(PopulationRouter.class); From 71b8e4722fb5d43164d62d7da7e97a95759a6ae3 Mon Sep 17 00:00:00 2001 From: tkchouaki Date: Tue, 5 Dec 2023 07:47:51 +0100 Subject: [PATCH 11/11] feat: extensive csv trip outputs (#172) Co-authored-by: Tarek Chouaki --- .../eqasim/ile_de_france/RunModeChoice.java | 32 +++++++------------ 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunModeChoice.java b/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunModeChoice.java index 012d77e89..9c97acb12 100644 --- a/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunModeChoice.java +++ b/ile_de_france/src/main/java/org/eqasim/ile_de_france/RunModeChoice.java @@ -3,9 +3,11 @@ import com.google.inject.Injector; import com.google.inject.Key; import com.google.inject.name.Names; +import org.eqasim.core.analysis.DistanceUnit; import org.eqasim.core.analysis.PersonAnalysisFilter; import org.eqasim.core.analysis.trips.TripItem; import org.eqasim.core.analysis.trips.TripReaderFromPopulation; +import org.eqasim.core.analysis.trips.TripWriter; import org.eqasim.core.misc.InjectorBuilder; import org.eqasim.core.scenario.validation.ScenarioValidator; import org.eqasim.core.simulation.analysis.EqasimAnalysisModule; @@ -184,7 +186,11 @@ public void install() { cmd.getOption("base-csv-path").ifPresent(s -> { //We write the initial trip modes Collection trips = tripReader.readTrips(population); - writeTripModesToCsv(trips, s); + try { + new TripWriter(trips, DistanceUnit.meter, DistanceUnit.meter).write(s); + } catch (IOException e) { + throw new RuntimeException(e); + } }); @@ -202,25 +208,11 @@ public void install() { outputPlansPath.ifPresent(s -> new PopulationWriter(population).write(s)); outputCsvPath.ifPresent(s -> { Collection trips = tripReader.readTrips(population); - writeTripModesToCsv(trips, s); - }); - } - - public static void writeTripModesToCsv(Collection trips, String outputPath) { - try { - BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outputPath))); - - writer.write( "personId;tripId;mode\n"); - writer.flush(); - - for (TripItem trip : trips) { - writer.write( String.join(";", trip.personId.toString(), trip.personTripId+"", trip.mode) + "\n"); - writer.flush(); + try { + new TripWriter(trips, DistanceUnit.meter, DistanceUnit.meter).write(s); + } catch (IOException e) { + throw new RuntimeException(e); } - writer.flush(); - writer.close(); - } catch (IOException e) { - throw new RuntimeException(e); - } + }); } }