Skip to content

Commit 35a595b

Browse files
authored
fix: move emission tests to core (#211)
1 parent f525dc3 commit 35a595b

File tree

4 files changed

+320
-15
lines changed

4 files changed

+320
-15
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
package org.eqasim.core.components.emissions;
2+
3+
import org.apache.commons.lang3.ArrayUtils;
4+
import org.apache.commons.lang3.StringUtils;
5+
import org.eqasim.core.misc.ClassUtils;
6+
import org.eqasim.core.simulation.EqasimConfigurator;
7+
import org.matsim.api.core.v01.Scenario;
8+
import org.matsim.api.core.v01.network.Link;
9+
import org.matsim.api.core.v01.network.Network;
10+
import org.matsim.contrib.emissions.EmissionModule;
11+
import org.matsim.contrib.emissions.OsmHbefaMapping;
12+
import org.matsim.contrib.emissions.utils.EmissionsConfigGroup;
13+
import org.matsim.core.api.experimental.events.EventsManager;
14+
import org.matsim.core.config.CommandLine;
15+
import org.matsim.core.config.Config;
16+
import org.matsim.core.config.ConfigGroup;
17+
import org.matsim.core.config.ConfigUtils;
18+
import org.matsim.core.controler.AbstractModule;
19+
import org.matsim.core.controler.Injector;
20+
import org.matsim.core.events.EventsUtils;
21+
import org.matsim.core.events.MatsimEventsReader;
22+
import org.matsim.core.events.algorithms.EventWriterXML;
23+
import org.matsim.core.network.NetworkUtils;
24+
import org.matsim.core.scenario.ScenarioUtils;
25+
26+
public class RunComputeEmissionsEvents {
27+
28+
public static void main(String[] args) throws CommandLine.ConfigurationException {
29+
30+
CommandLine cmd = new CommandLine.Builder(args) //
31+
.requireOptions("config-path", "hbefa-cold-avg", "hbefa-hot-avg") //
32+
.allowOptions("hbefa-cold-detailed", "hbefa-hot-detailed", "configurator-class")
33+
.build();
34+
35+
EqasimConfigurator configurator;
36+
if(cmd.hasOption("configurator-class")) {
37+
configurator = ClassUtils.getInstanceOfClassExtendingOtherClass(cmd.getOptionStrict("configurator-class"), EqasimConfigurator.class);
38+
} else {
39+
configurator = new EqasimConfigurator();
40+
}
41+
42+
ConfigGroup[] configGroups = ArrayUtils.addAll(configurator.getConfigGroups(), new EmissionsConfigGroup());
43+
44+
Config config = ConfigUtils.loadConfig(cmd.getOptionStrict("config-path"), configGroups);
45+
cmd.applyConfiguration(config);
46+
47+
EmissionsConfigGroup emissionsConfig = (EmissionsConfigGroup) config.getModules().get("emissions");
48+
emissionsConfig.setHbefaVehicleDescriptionSource(EmissionsConfigGroup.HbefaVehicleDescriptionSource.asEngineInformationAttributes);
49+
emissionsConfig.setDetailedVsAverageLookupBehavior(
50+
EmissionsConfigGroup.DetailedVsAverageLookupBehavior.tryDetailedThenTechnologyAverageThenAverageTable);
51+
emissionsConfig.setNonScenarioVehicles(EmissionsConfigGroup.NonScenarioVehicles.abort);
52+
emissionsConfig.setHbefaTableConsistencyCheckingLevel(EmissionsConfigGroup.HbefaTableConsistencyCheckingLevel.consistent);
53+
54+
emissionsConfig.setAverageColdEmissionFactorsFile(cmd.getOptionStrict("hbefa-cold-avg"));
55+
emissionsConfig.setAverageWarmEmissionFactorsFile(cmd.getOptionStrict("hbefa-hot-avg"));
56+
57+
if (cmd.hasOption("hbefa-cold-detailed") && cmd.hasOption("hbefa-hot-detailed")) {
58+
emissionsConfig.setDetailedColdEmissionFactorsFile(cmd.getOptionStrict("hbefa-cold-detailed"));
59+
emissionsConfig.setDetailedWarmEmissionFactorsFile(cmd.getOptionStrict("hbefa-hot-detailed"));
60+
}
61+
62+
Scenario scenario = ScenarioUtils.createScenario(config);
63+
ScenarioUtils.loadScenario(scenario);
64+
65+
OsmHbefaMapping osmHbefaMapping = OsmHbefaMapping.build();
66+
Network network = scenario.getNetwork();
67+
// if the network is from pt2matsim it might not have "type" but "osm:way:highway" attribute instead
68+
for (Link link: network.getLinks().values()) {
69+
String roadTypeAttribute = NetworkUtils.getType(link);
70+
String osmRoadTypeAttribute = (String) link.getAttributes().getAttribute("osm:way:highway");
71+
if (StringUtils.isBlank(roadTypeAttribute)) {
72+
if (!StringUtils.isBlank(osmRoadTypeAttribute)) {
73+
NetworkUtils.setType(link, osmRoadTypeAttribute);
74+
}
75+
else { // not a road (railway for example)
76+
NetworkUtils.setType(link, "unclassified");
77+
}
78+
}
79+
// '_link' types are not defined in the OSM mapping, set t undefined
80+
if (NetworkUtils.getType(link).contains("_link")) {
81+
NetworkUtils.setType(link, "unclassified");
82+
}
83+
if (NetworkUtils.getType(link).equals("living_street")) {
84+
NetworkUtils.setType(link, "living");
85+
}
86+
}
87+
osmHbefaMapping.addHbefaMappings(network);
88+
89+
EventsManager eventsManager = EventsUtils.createEventsManager();
90+
AbstractModule module = new AbstractModule(){
91+
@Override
92+
public void install(){
93+
bind( Scenario.class ).toInstance( scenario );
94+
bind( EventsManager.class ).toInstance( eventsManager );
95+
bind( EmissionModule.class ) ;
96+
}
97+
};
98+
99+
com.google.inject.Injector injector = Injector.createInjector(config, module );
100+
EmissionModule emissionModule = injector.getInstance(EmissionModule.class);
101+
102+
final String outputDirectory = scenario.getConfig().controler().getOutputDirectory() + "/";
103+
EventWriterXML emissionEventWriter = new EventWriterXML( outputDirectory + "output_emissions_events.xml.gz" ) ;
104+
emissionModule.getEmissionEventsManager().addHandler(emissionEventWriter);
105+
106+
eventsManager.initProcessing();
107+
MatsimEventsReader matsimEventsReader = new MatsimEventsReader(eventsManager);
108+
matsimEventsReader.readFile( outputDirectory + "./output_events.xml.gz" );
109+
eventsManager.finishProcessing();
110+
111+
emissionEventWriter.closeFile();
112+
}
113+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
package org.eqasim.core.components.emissions;
2+
3+
import org.apache.commons.lang3.ArrayUtils;
4+
import org.eqasim.core.misc.ClassUtils;
5+
import org.eqasim.core.simulation.EqasimConfigurator;
6+
import org.locationtech.jts.geom.Geometry;
7+
import org.matsim.api.core.v01.network.Network;
8+
import org.matsim.contrib.emissions.analysis.EmissionGridAnalyzer;
9+
import org.matsim.contrib.emissions.utils.EmissionsConfigGroup;
10+
import org.matsim.core.config.CommandLine;
11+
import org.matsim.core.config.Config;
12+
import org.matsim.core.config.ConfigGroup;
13+
import org.matsim.core.config.ConfigUtils;
14+
import org.matsim.core.network.NetworkUtils;
15+
import org.matsim.core.network.io.MatsimNetworkReader;
16+
import org.matsim.core.utils.gis.ShapeFileReader;
17+
import org.opengis.feature.simple.SimpleFeature;
18+
19+
public class RunComputeEmissionsGrid {
20+
21+
public static void main(String[] args) throws CommandLine.ConfigurationException {
22+
23+
CommandLine cmd = new CommandLine.Builder(args) //
24+
.requireOptions("config-path", "domain-shp-path") //
25+
.allowOptions("scale-factor", "grid-size", "smooth-radius", "time-bin-size", "configurator-class")
26+
.build();
27+
28+
EqasimConfigurator configurator;
29+
if(cmd.hasOption("configurator-class")) {
30+
configurator = ClassUtils.getInstanceOfClassExtendingOtherClass(cmd.getOptionStrict("configurator-class"), EqasimConfigurator.class);
31+
} else {
32+
configurator = new EqasimConfigurator();
33+
}
34+
35+
ConfigGroup[] configGroups = ArrayUtils.addAll(configurator.getConfigGroups(), new EmissionsConfigGroup());
36+
37+
Config config = ConfigUtils.loadConfig(cmd.getOptionStrict("config-path"), configGroups);
38+
cmd.applyConfiguration(config);
39+
final String outputDirectory = config.controler().getOutputDirectory() + "/";
40+
41+
Network network = NetworkUtils.createNetwork();
42+
new MatsimNetworkReader(network).readFile(outputDirectory + "output_network.xml.gz");
43+
44+
SimpleFeature analysisFeature = ShapeFileReader.getAllFeatures(cmd.getOptionStrict("domain-shp-path")).iterator().next();
45+
Geometry analysisGeometry = (Geometry) analysisFeature.getDefaultGeometry();
46+
47+
double scaleFactor = Double.parseDouble(cmd.getOption("scale-factor").orElse("1.0"));
48+
int gridSize = Integer.parseInt(cmd.getOption("grid-size").orElse("25"));
49+
int smoothRadius = Integer.parseInt(cmd.getOption("smooth-radius").orElse("50"));
50+
int timeBinSize = Integer.parseInt(cmd.getOption("time-bin-size").orElse("3600"));
51+
52+
new EmissionGridAnalyzer.Builder() //
53+
.withBounds(analysisGeometry) //
54+
.withNetwork(network) //
55+
.withCountScaleFactor(scaleFactor) //
56+
.withGridSize(gridSize) //
57+
.withSmoothingRadius(smoothRadius) //
58+
.withTimeBinSize(timeBinSize) //
59+
.withGridType(EmissionGridAnalyzer.GridType.Square) //
60+
.build() //
61+
.processToJsonFile(outputDirectory + "output_emissions_events.xml.gz", outputDirectory + "output_emissions.json");
62+
}
63+
64+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
package org.eqasim.core.components.emissions;
2+
3+
import java.util.ArrayList;
4+
import java.util.Collection;
5+
import java.util.LinkedList;
6+
import java.util.List;
7+
import java.util.Map;
8+
9+
import org.apache.commons.lang3.ArrayUtils;
10+
import org.eqasim.core.misc.ClassUtils;
11+
import org.eqasim.core.simulation.EqasimConfigurator;
12+
import org.locationtech.jts.geom.Coordinate;
13+
import org.matsim.api.core.v01.Id;
14+
import org.matsim.api.core.v01.network.Link;
15+
import org.matsim.api.core.v01.network.Network;
16+
import org.matsim.contrib.analysis.time.TimeBinMap;
17+
import org.matsim.contrib.emissions.Pollutant;
18+
import org.matsim.contrib.emissions.analysis.EmissionsByPollutant;
19+
import org.matsim.contrib.emissions.analysis.EmissionsOnLinkEventHandler;
20+
import org.matsim.contrib.emissions.events.EmissionEventsReader;
21+
import org.matsim.contrib.emissions.utils.EmissionsConfigGroup;
22+
import org.matsim.core.api.experimental.events.EventsManager;
23+
import org.matsim.core.config.CommandLine;
24+
import org.matsim.core.config.Config;
25+
import org.matsim.core.config.ConfigGroup;
26+
import org.matsim.core.config.ConfigUtils;
27+
import org.matsim.core.events.EventsUtils;
28+
import org.matsim.core.network.NetworkUtils;
29+
import org.matsim.core.network.io.MatsimNetworkReader;
30+
import org.matsim.core.utils.geometry.geotools.MGC;
31+
import org.matsim.core.utils.gis.PolylineFeatureFactory;
32+
import org.matsim.core.utils.gis.ShapeFileWriter;
33+
import org.opengis.feature.simple.SimpleFeature;
34+
35+
public class RunExportEmissionsNetwork {
36+
37+
public static void main(String[] args) throws CommandLine.ConfigurationException {
38+
39+
CommandLine cmd = new CommandLine.Builder(args) //
40+
.requireOptions("config-path") //
41+
.allowOptions("time-bin-size")
42+
.allowOptions("pollutants", "configurator-class")
43+
.build();
44+
45+
EqasimConfigurator configurator;
46+
if(cmd.hasOption("configurator-class")) {
47+
configurator = ClassUtils.getInstanceOfClassExtendingOtherClass(cmd.getOptionStrict("configurator-class"), EqasimConfigurator.class);
48+
} else {
49+
configurator = new EqasimConfigurator();
50+
}
51+
52+
ConfigGroup[] configGroups = ArrayUtils.addAll(configurator.getConfigGroups(), new EmissionsConfigGroup());
53+
54+
Config config = ConfigUtils.loadConfig(cmd.getOptionStrict("config-path"), configGroups);
55+
cmd.applyConfiguration(config);
56+
final String outputDirectory = config.controler().getOutputDirectory() + "/";
57+
58+
int timeBinSize = Integer.parseInt(cmd.getOption("time-bin-size").orElse("3600"));
59+
60+
String[] wanted_pollutants = cmd.getOption("pollutants").orElse("PM,CO,NOx").split(",");
61+
62+
EventsManager eventsManager = EventsUtils.createEventsManager();
63+
EmissionsOnLinkEventHandler handler = new EmissionsOnLinkEventHandler(timeBinSize);
64+
65+
EmissionEventsReader eventsReader = new EmissionEventsReader(eventsManager);
66+
67+
eventsManager.addHandler(handler);
68+
eventsManager.initProcessing();
69+
eventsReader.readFile(outputDirectory + "output_emissions_events.xml.gz");
70+
eventsManager.finishProcessing();
71+
72+
Network network = NetworkUtils.createNetwork();
73+
new MatsimNetworkReader(network).readFile(outputDirectory + "output_network.xml.gz");
74+
Map<Id<Link>, ? extends Link> links = network.getLinks();
75+
TimeBinMap<Map<Id<Link>, EmissionsByPollutant>> res = handler.getTimeBins();
76+
Collection<SimpleFeature> features = new LinkedList<>();
77+
PolylineFeatureFactory.Builder builder = new PolylineFeatureFactory.Builder() //
78+
.setCrs(MGC.getCRS("epsg:2154")).setName("Emissions") //
79+
.addAttribute("link", String.class) //
80+
.addAttribute("time", Integer.class);
81+
for (String pollutant: wanted_pollutants) {
82+
builder.addAttribute(pollutant, Double.class);
83+
}
84+
PolylineFeatureFactory linkFactory = builder.create();
85+
86+
for (TimeBinMap.TimeBin<Map<Id<Link>, EmissionsByPollutant>> timeBin : res.getTimeBins()) {
87+
int startTime = (int) timeBin.getStartTime();
88+
Map<Id<Link>, EmissionsByPollutant> map = timeBin.getValue();
89+
for (Map.Entry<Id<Link>, EmissionsByPollutant> entry : map.entrySet()) {
90+
Id<Link> link_id = entry.getKey();
91+
Link link = links.get(link_id);
92+
Coordinate fromCoordinate = new Coordinate(link.getFromNode().getCoord().getX(),
93+
link.getFromNode().getCoord().getY());
94+
Coordinate toCoordinate = new Coordinate(link.getToNode().getCoord().getX(),
95+
link.getToNode().getCoord().getY());
96+
97+
List<Object> attributes = new ArrayList<>();
98+
99+
attributes.add(link_id.toString());
100+
attributes.add(startTime);
101+
EmissionsByPollutant emissions = entry.getValue();
102+
Map<Pollutant, Double> pollutants = emissions.getEmissions();
103+
for (String pollutant: wanted_pollutants) {
104+
try {
105+
Pollutant pollutant_key = Pollutant.valueOf(pollutant);
106+
attributes.add(pollutants.getOrDefault(pollutant_key, Double.NaN));
107+
}
108+
catch (IllegalArgumentException e) {
109+
attributes.add(Double.NaN);
110+
}
111+
112+
}
113+
114+
SimpleFeature feature = linkFactory.createPolyline( //
115+
new Coordinate[] { fromCoordinate, toCoordinate }, //
116+
attributes.toArray(),
117+
null);
118+
119+
features.add(feature);
120+
}
121+
}
122+
ShapeFileWriter.writeGeometries(features, outputDirectory + "emissions_network.shp");
123+
}
124+
}

ile_de_france/src/test/java/org/eqasim/ile_de_france/TestEmissions.java renamed to core/src/test/java/org/eqasim/TestEmissions.java

+19-15
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,24 @@
1-
package org.eqasim.ile_de_france;
1+
package org.eqasim;
2+
3+
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
4+
5+
import java.io.File;
6+
import java.io.IOException;
7+
import java.net.URL;
8+
import java.nio.file.Files;
9+
import java.nio.file.Paths;
10+
import java.util.Collection;
11+
import java.util.HashSet;
12+
import java.util.Set;
213

314
import org.apache.commons.io.FileUtils;
15+
import org.eqasim.core.components.emissions.RunComputeEmissionsEvents;
16+
import org.eqasim.core.components.emissions.RunExportEmissionsNetwork;
417
import org.eqasim.core.simulation.EqasimConfigurator;
518
import org.eqasim.core.simulation.analysis.EqasimAnalysisModule;
619
import org.eqasim.core.simulation.mode_choice.AbstractEqasimExtension;
720
import org.eqasim.core.simulation.mode_choice.EqasimModeChoiceModule;
821
import org.eqasim.core.simulation.mode_choice.parameters.ModeParameters;
9-
import org.eqasim.ile_de_france.emissions.RunComputeEmissionsEvents;
10-
import org.eqasim.ile_de_france.emissions.RunExportEmissionsNetwork;
1122
import org.junit.After;
1223
import org.junit.Before;
1324
import org.junit.Test;
@@ -28,20 +39,13 @@
2839
import org.matsim.core.utils.gis.ShapeFileReader;
2940
import org.matsim.examples.ExamplesUtils;
3041
import org.matsim.utils.objectattributes.attributable.Attributes;
31-
import org.matsim.vehicles.*;
42+
import org.matsim.vehicles.MatsimVehicleWriter;
43+
import org.matsim.vehicles.Vehicle;
44+
import org.matsim.vehicles.VehicleType;
45+
import org.matsim.vehicles.VehicleUtils;
46+
import org.matsim.vehicles.Vehicles;
3247
import org.opengis.feature.simple.SimpleFeature;
3348

34-
import java.io.File;
35-
import java.io.IOException;
36-
import java.net.URL;
37-
import java.nio.file.Files;
38-
import java.nio.file.Paths;
39-
import java.util.Collection;
40-
import java.util.HashSet;
41-
import java.util.Set;
42-
43-
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
44-
4549
public class TestEmissions {
4650

4751
@Before

0 commit comments

Comments
 (0)