Skip to content

Commit

Permalink
Merge pull request #2 from arup-group/michael-refactoring
Browse files Browse the repository at this point in the history
Michael refactoring
  • Loading branch information
mfitz authored Jan 29, 2024
2 parents 2f7c52b + 45eb4a8 commit b431a0b
Show file tree
Hide file tree
Showing 32 changed files with 2,079 additions and 99 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,4 @@ hs_err_pid*
replay_pid*

target/
*.iml
2 changes: 1 addition & 1 deletion dependency-reduced-pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@
</dependencies>
<properties>
<maven.compiler.release>17</maven.compiler.release>
<main.class>com.arup.cml.kpi.matsim.run.KpiGenerator</main.class>
<main.class>com.arup.cml.abm.kpi.matsim.run.MatsimKpiGenerator</main.class>
<maven.compiler.source>17</maven.compiler.source>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.target>17</maven.compiler.target>
Expand Down
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<maven.compiler.release>17</maven.compiler.release>
<main.class>com.arup.cml.kpi.matsim.run.KpiGenerator</main.class>
<main.class>com.arup.cml.abm.kpi.matsim.run.MatsimKpiGenerator</main.class>
<maven.compiler.source>17</maven.compiler.source>
<maven.compiler.target>17</maven.compiler.target>
</properties>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.arup.cml.kpi;
package com.arup.cml.abm.kpi;

import tech.tablesaw.api.Table;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
package com.arup.cml.kpi;
package com.arup.cml.abm.kpi;

import tech.tablesaw.api.StringColumn;
import tech.tablesaw.api.IntColumn;
import tech.tablesaw.api.Table;

import static tech.tablesaw.aggregate.AggregateFunctions.mean;
Expand Down Expand Up @@ -47,10 +47,10 @@ public Table congestion() {
);

// put in hour bins
StringColumn hour = StringColumn.create("hour");
IntColumn hour = IntColumn.create("hour");
linkLog.doubleColumn("endTime")
.forEach(time -> hour.append(
String.valueOf((int) Math.floor(time / (60 * 60)))
(int) Math.floor(time / (60 * 60))
));
linkLog.addColumns(hour);

Expand All @@ -61,16 +61,11 @@ public Table congestion() {
.by("linkID", "mode", "hour");
intermediate.write().csv(String.format("%s/congestion.csv", outputDir));

linkLog.where(
linkLog.stringColumn("hour").asDoubleColumn().isGreaterThanOrEqualTo(7)
.and(linkLog.stringColumn("hour").asDoubleColumn().isLessThanOrEqualTo(9))
);

// kpi output
Table kpi =
linkLog
.where(linkLog.stringColumn("hour").asDoubleColumn().isGreaterThanOrEqualTo(7)
.and(linkLog.stringColumn("hour").asDoubleColumn().isLessThanOrEqualTo(9)))
.where(linkLog.intColumn("hour").isGreaterThanOrEqualTo(7)
.and(linkLog.intColumn("hour").isLessThanOrEqualTo(9)))
.summarize("delayRatio", mean)
.by("mode")
.setName("Congestion KPI");
Expand Down
12 changes: 12 additions & 0 deletions src/main/java/com/arup/cml/abm/kpi/KpiCalculator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.arup.cml.abm.kpi;

import java.nio.file.Path;

public interface KpiCalculator {
void linkEntered(String vehicleId, String linkId, double timestamp);
void linkExited(String vehicleId, String linkId, double timestamp);
void vehicleEntered(String vehicleId, String personId);
void vehicleExited(String vehicleId, String personId);
void recordVehicleMode(String vehicleId, String mode);
void writeCongestionKpi(Path directory);
}
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
package com.arup.cml.kpi.matsim;
package com.arup.cml.abm.kpi.matsim;

import com.arup.cml.kpi.DataModel;
import com.arup.cml.kpi.matsim.handlers.LinkLogHandler;
import com.arup.cml.abm.kpi.matsim.handlers.LinkLogHandler;
import com.arup.cml.abm.kpi.DataModel;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.matsim.api.core.v01.Scenario;
import org.matsim.api.core.v01.network.Network;
import org.matsim.core.api.experimental.events.EventsManager;
import org.matsim.core.config.Config;
import org.matsim.core.config.ConfigGroup;
import org.matsim.core.config.ConfigUtils;
import org.matsim.core.config.ReflectiveConfigGroup;
import org.matsim.core.config.groups.*;
import org.matsim.core.events.EventsUtils;
import org.matsim.core.events.MatsimEventsReader;
Expand All @@ -18,8 +20,7 @@
import tech.tablesaw.api.StringColumn;
import tech.tablesaw.api.Table;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.*;


public class MATSimModel implements DataModel {
Expand All @@ -28,16 +29,15 @@ public class MATSimModel implements DataModel {
private final String matsimOutputDir;
private final Scenario scenario;
private final EventsManager eventsManager;

private final String[] necessaryConfigGroups = new String[]{
GlobalConfigGroup.GROUP_NAME,
PlansConfigGroup.GROUP_NAME,
FacilitiesConfigGroup.GROUP_NAME,
HouseholdsConfigGroup.GROUP_NAME,
TransitConfigGroup.GROUP_NAME,
VehiclesConfigGroup.GROUP_NAME,
NetworkConfigGroup.GROUP_NAME
};
private final Set<String> necessaryConfigGroups = new HashSet<>(Arrays.asList(
GlobalConfigGroup.GROUP_NAME,
PlansConfigGroup.GROUP_NAME,
FacilitiesConfigGroup.GROUP_NAME,
HouseholdsConfigGroup.GROUP_NAME,
TransitConfigGroup.GROUP_NAME,
VehiclesConfigGroup.GROUP_NAME,
NetworkConfigGroup.GROUP_NAME
));

private final Table linkLog;
private final Table vehicleOccupancy;
Expand Down Expand Up @@ -65,18 +65,25 @@ public MATSimModel(String matsimInputConfig, String matsimOutputDir) {

private Config getConfig(String matsimInputConfig) {
Config config = ConfigUtils.createConfig();
ArrayList<String> configGroups = new ArrayList<>(config.getModules().keySet());
for (String module : configGroups) {
if (Arrays.asList(necessaryConfigGroups).contains(module)) {
// TreeMap<String, ConfigGroup> configuredModules = config.getModules();
// for (ConfigGroup module : configuredModules.values().stream().toList()){
// for (Map.Entry<String, String> entry : module.getParams().entrySet()) {
// System.out.println((entry.getKey() + "," + entry.getValue()));
// }
// }

TreeMap<String, ConfigGroup> configuredModules = config.getModules();
for (ConfigGroup module : configuredModules.values().stream().toList()) {
if (necessaryConfigGroups.contains(module.getName())) {
System.out.println("Config group " + module + " is read as is");
} else {
config.removeModule(module);
config.addModule(new RelaxedReflectiveConfigGroup(module));
ReflectiveConfigGroup relaxedModule =
new ReflectiveConfigGroup(module.getName(), true) {};
config.removeModule(module.getName());
config.addModule(relaxedModule);
}
}
ConfigUtils.loadConfig(
config, String.format(matsimInputConfig)
);
ConfigUtils.loadConfig(config, String.format(matsimInputConfig));
setOutputFilePaths(config);
return config;
}
Expand Down
85 changes: 85 additions & 0 deletions src/main/java/com/arup/cml/abm/kpi/matsim/MatsimUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
package com.arup.cml.abm.kpi.matsim;

import org.matsim.api.core.v01.network.Network;
import org.matsim.core.config.Config;
import org.matsim.core.config.ConfigGroup;
import org.matsim.core.config.ConfigUtils;
import org.matsim.core.config.ReflectiveConfigGroup;
import org.matsim.core.config.groups.*;
import org.matsim.core.scenario.ScenarioUtils;
import org.matsim.pt.config.TransitConfigGroup;

import java.nio.file.Path;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.TreeMap;

public class MatsimUtils {
private Path matsimOutputDir;
private Network matsimNetwork;
private Config matsimConfig;

private final Set<String> necessaryConfigGroups = new HashSet<>(Arrays.asList(
GlobalConfigGroup.GROUP_NAME,
PlansConfigGroup.GROUP_NAME,
FacilitiesConfigGroup.GROUP_NAME,
HouseholdsConfigGroup.GROUP_NAME,
TransitConfigGroup.GROUP_NAME,
VehiclesConfigGroup.GROUP_NAME,
NetworkConfigGroup.GROUP_NAME
));

public MatsimUtils(Path matsimOutputDir, Path matsimConfigFile) {
this.matsimOutputDir = matsimOutputDir;
this.matsimConfig = getConfig(matsimConfigFile.toString());
this.matsimNetwork = ScenarioUtils.loadScenario(matsimConfig).getNetwork();
}

private Config getConfig(String matsimInputConfig) {
Config config = ConfigUtils.createConfig();
TreeMap<String, ConfigGroup> configuredModules = config.getModules();
for (ConfigGroup module : configuredModules.values().stream().toList()) {
if (necessaryConfigGroups.contains(module.getName())) {
System.out.println("Config group " + module + " is read as is");
} else {
ReflectiveConfigGroup relaxedModule =
new ReflectiveConfigGroup(module.getName(), true) {};
config.removeModule(module.getName());
config.addModule(relaxedModule);
}
}
ConfigUtils.loadConfig(config, String.format(matsimInputConfig));
setOutputFilePaths(config);
return config;
}

private void setOutputFilePaths(Config config) {
TreeMap<String, ConfigGroup> modules = config.getModules();
modules.get("network")
.addParam("inputNetworkFile",
String.format("%s/output_network.xml.gz", this.matsimOutputDir));
modules.get("transit")
.addParam("transitScheduleFile",
String.format("%s/output_transitSchedule.xml.gz", this.matsimOutputDir));
modules.get("transit")
.addParam("vehiclesFile",
String.format("%s/output_transitVehicles.xml.gz", this.matsimOutputDir));
modules.get("plans")
.addParam("inputPlansFile",
String.format("%s/output_plans.xml.gz", this.matsimOutputDir));
modules.get("households")
.addParam("inputFile",
String.format("%s/output_households.xml.gz", this.matsimOutputDir));
modules.get("facilities")
.addParam("inputFacilitiesFile",
String.format("%s/output_facilities.xml.gz", this.matsimOutputDir));
modules.get("vehicles")
.addParam("vehiclesFile",
String.format("%s/output_vehicles.xml.gz", this.matsimOutputDir));
}

public Network getMatsimNetwork() {
return matsimNetwork;
}
}
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
package com.arup.cml.kpi.matsim.handlers;
package com.arup.cml.abm.kpi.matsim.handlers;

import org.matsim.api.core.v01.Id;
import org.matsim.api.core.v01.events.*;
Expand All @@ -11,9 +11,13 @@
import java.util.*;
import java.util.stream.LongStream;

public class LinkLogHandler implements VehicleEntersTrafficEventHandler, VehicleLeavesTrafficEventHandler,
PersonEntersVehicleEventHandler, PersonLeavesVehicleEventHandler,
LinkEnterEventHandler, LinkLeaveEventHandler {
public class LinkLogHandler implements
VehicleEntersTrafficEventHandler,
VehicleLeavesTrafficEventHandler,
PersonEntersVehicleEventHandler,
PersonLeavesVehicleEventHandler,
LinkEnterEventHandler,
LinkLeaveEventHandler {

// arrays to collect Link Log data, each will form a column of the Link Log
private final ArrayList<String> vehicleIDColumn = new ArrayList<>();
Expand Down Expand Up @@ -91,10 +95,10 @@ public Table getVehicleOccupancy() {
);
}

public void write(String outputDir) {
getLinkLog().write().csv(String.format("%s/linkLog.csv", outputDir));
getVehicleOccupancy().write().csv(String.format("%s/vehicleOccupancy.csv", outputDir));
}
// public void write(String outputDir) {
// getLinkLog().write().csv(String.format("%s/linkLog.csv", outputDir));
// getVehicleOccupancy().write().csv(String.format("%s/vehicleOccupancy.csv", outputDir));
// }

@Override
public void handleEvent(VehicleEntersTrafficEvent event) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package com.arup.cml.abm.kpi.matsim.handlers;

import com.arup.cml.abm.kpi.KpiCalculator;
import org.matsim.api.core.v01.events.*;
import org.matsim.api.core.v01.events.handler.*;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

public class MatsimLinkLogHandler implements
VehicleEntersTrafficEventHandler,
VehicleLeavesTrafficEventHandler,
PersonEntersVehicleEventHandler,
PersonLeavesVehicleEventHandler,
LinkEnterEventHandler,
LinkLeaveEventHandler {

private KpiCalculator kpiCalculator;
private final Map<String, AtomicInteger> eventCounts = new HashMap<>();

public MatsimLinkLogHandler(KpiCalculator kpiCalculator) {
this.kpiCalculator = kpiCalculator;
}

@Override
public void handleEvent(LinkEnterEvent event) {
incrementEventCount(event);
kpiCalculator.linkEntered(
event.getVehicleId().toString(),
event.getLinkId().toString(),
event.getTime()
);
}

@Override
public void handleEvent(LinkLeaveEvent event) {
incrementEventCount(event);
kpiCalculator.linkExited(
event.getVehicleId().toString(),
event.getLinkId().toString(),
event.getTime()
);
}

@Override
public void handleEvent(PersonEntersVehicleEvent event) {
incrementEventCount(event);
kpiCalculator.vehicleEntered(
event.getVehicleId().toString(),
event.getPersonId().toString()
);
}

@Override
public void handleEvent(PersonLeavesVehicleEvent event) {
incrementEventCount(event);
kpiCalculator.vehicleExited(
event.getVehicleId().toString(),
event.getPersonId().toString()
);
}

@Override
public void handleEvent(VehicleEntersTrafficEvent event) {
incrementEventCount(event);
// this is the earliest event we will see for this vehicle, and includes the
// mode, which is missing from subsequent link events, so we must grab it now
kpiCalculator.recordVehicleMode(event.getVehicleId().toString(), event.getNetworkMode());
kpiCalculator.linkEntered(
event.getVehicleId().toString(),
event.getLinkId().toString(),
event.getTime()
);
}

@Override
public void handleEvent(VehicleLeavesTrafficEvent event) {
incrementEventCount(event);
kpiCalculator.linkExited(
event.getVehicleId().toString(),
event.getLinkId().toString(),
event.getTime()
);
}

public Map<String, AtomicInteger> getEventCounts() {
return this.eventCounts;
}

private void incrementEventCount(Event e) {
eventCounts.putIfAbsent(e.getEventType(), new AtomicInteger(0));
eventCounts.get(e.getEventType()).incrementAndGet();
}
}
Loading

0 comments on commit b431a0b

Please sign in to comment.