diff --git a/core/src/main/java/org/eqasim/core/analysis/activities/ActivityListener.java b/core/src/main/java/org/eqasim/core/analysis/activities/ActivityListener.java index f09e8b42f..f514fb121 100644 --- a/core/src/main/java/org/eqasim/core/analysis/activities/ActivityListener.java +++ b/core/src/main/java/org/eqasim/core/analysis/activities/ActivityListener.java @@ -10,14 +10,18 @@ import org.matsim.api.core.v01.Id; import org.matsim.api.core.v01.events.ActivityEndEvent; import org.matsim.api.core.v01.events.ActivityStartEvent; +import org.matsim.api.core.v01.events.PersonInitializedEvent; import org.matsim.api.core.v01.events.handler.ActivityEndEventHandler; import org.matsim.api.core.v01.events.handler.ActivityStartEventHandler; +import org.matsim.api.core.v01.events.handler.PersonInitializedEventHandler; import org.matsim.api.core.v01.population.Person; +import org.matsim.contrib.dvrp.vrpagent.VrpAgentLogic; import org.matsim.core.router.TripStructureUtils; import com.google.common.base.Verify; -public class ActivityListener implements ActivityStartEventHandler, ActivityEndEventHandler { +public class ActivityListener + implements PersonInitializedEventHandler, ActivityStartEventHandler, ActivityEndEventHandler { final private Collection activities = new LinkedList<>(); final private Map, ActivityItem> ongoing = new HashMap<>(); final private Map, Integer> activityIndex = new HashMap<>(); @@ -39,48 +43,49 @@ public void reset(int iteration) { activityIndex.clear(); } + @Override + public void handleEvent(PersonInitializedEvent event) { + if (personFilter.analyzePerson(event.getPersonId())) { + ActivityItem activity = new ActivityItem(event.getPersonId(), 0, event.getActivityType(), + Double.NEGATIVE_INFINITY, + Double.POSITIVE_INFINITY, event.getCoord().getX(), event.getCoord().getY(), event.getFacilityId(), + event.getLinkId()); + + activities.add(activity); + ongoing.put(event.getPersonId(), activity); + } + } + @Override public void handleEvent(ActivityStartEvent event) { if (personFilter.analyzePerson(event.getPersonId())) { if (!TripStructureUtils.isStageActivityType(event.getActType())) { - int personActivityIndex = Objects.requireNonNull(activityIndex.get(event.getPersonId())) + 1; - activityIndex.put(event.getPersonId(), personActivityIndex); + int personActivityIndex = activityIndex.compute(event.getPersonId(), + (id, val) -> val == null ? 1 : val + 1); - // this is not the first one ActivityItem activity = new ActivityItem(event.getPersonId(), personActivityIndex, event.getActType(), event.getTime(), Double.POSITIVE_INFINITY, event.getCoord().getX(), event.getCoord().getY(), event.getFacilityId(), event.getLinkId()); activities.add(activity); - ongoing.put(event.getPersonId(), activity); + Verify.verify(ongoing.put(event.getPersonId(), activity) == null); } } } @Override public void handleEvent(ActivityEndEvent event) { + if (event.getActType().startsWith(VrpAgentLogic.BEFORE_SCHEDULE_ACTIVITY_TYPE)) { + // special case that can not be covered by the person filter (event comes too + // early) + return; + } + if (personFilter.analyzePerson(event.getPersonId())) { if (!TripStructureUtils.isStageActivityType(event.getActType())) { - ActivityItem activity = ongoing.remove(event.getPersonId()); - - if (activity == null) { - if (event.getCoord() == null) { - // can happen for BeforeVrpSchedule activities of DRT vehicles - return; - } - - // this is the first one - activity = new ActivityItem(event.getPersonId(), 0, event.getActType(), Double.NEGATIVE_INFINITY, - event.getTime(), event.getCoord().getX(), event.getCoord().getY(), event.getFacilityId(), - event.getLinkId()); - - Verify.verify(activityIndex.put(event.getPersonId(), 0) == null); - - activities.add(activity); - ongoing.put(event.getPersonId(), activity); - } else { - activity.endTime = event.getTime(); - } + ActivityItem activity = Objects.requireNonNull(ongoing.remove(event.getPersonId()), + "Are you running activity analysis on an instance without qsim.personInitializedEvents = 'all'?"); + activity.endTime = event.getTime(); } } } diff --git a/core/src/main/java/org/eqasim/core/scenario/config/GenerateConfig.java b/core/src/main/java/org/eqasim/core/scenario/config/GenerateConfig.java index 043acb645..d87e93468 100644 --- a/core/src/main/java/org/eqasim/core/scenario/config/GenerateConfig.java +++ b/core/src/main/java/org/eqasim/core/scenario/config/GenerateConfig.java @@ -16,6 +16,7 @@ import org.matsim.core.config.CommandLine.ConfigurationException; import org.matsim.core.config.Config; import org.matsim.core.config.groups.ControllerConfigGroup.RoutingAlgorithmType; +import org.matsim.core.config.groups.QSimConfigGroup.PersonInitializedEventsSetting; import org.matsim.core.config.groups.PlansConfigGroup; import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.config.groups.RoutingConfigGroup.AccessEgressType; @@ -77,6 +78,7 @@ protected void adaptConfiguration(Config config) { config.qsim().setNumberOfThreads(Math.min(12, threads)); config.qsim().setFlowCapFactor(sampleSize); config.qsim().setStorageCapFactor(sampleSize); + config.qsim().setPersonInitializedEventsSetting(PersonInitializedEventsSetting.all); // Eqasim settings EqasimConfigGroup eqasimConfig = EqasimConfigGroup.get(config); diff --git a/core/src/main/java/org/eqasim/core/simulation/analysis/EqasimAnalysisModule.java b/core/src/main/java/org/eqasim/core/simulation/analysis/EqasimAnalysisModule.java index 0450fad7f..fcb34b2cf 100644 --- a/core/src/main/java/org/eqasim/core/simulation/analysis/EqasimAnalysisModule.java +++ b/core/src/main/java/org/eqasim/core/simulation/analysis/EqasimAnalysisModule.java @@ -20,6 +20,8 @@ import org.matsim.core.api.experimental.events.EventsManager; import org.matsim.core.config.Config; import org.matsim.core.config.groups.ControllerConfigGroup; +import org.matsim.core.config.groups.QSimConfigGroup; +import org.matsim.core.config.groups.QSimConfigGroup.PersonInitializedEventsSetting; import org.matsim.core.config.groups.RoutingConfigGroup; import org.matsim.core.controler.AbstractModule; import org.matsim.core.controler.OutputDirectoryHierarchy; @@ -28,6 +30,7 @@ import org.matsim.core.utils.timing.TimeInterpretation; import org.matsim.pt.transitSchedule.api.TransitSchedule; +import com.google.common.base.Preconditions; import com.google.inject.Provides; import com.google.inject.Singleton; @@ -73,7 +76,10 @@ public PublicTransportLegListener providePublicTransportListener(Network network @Provides @Singleton - public ActivityListener provideActivityListener(PersonAnalysisFilter personFilter) { + public ActivityListener provideActivityListener(PersonAnalysisFilter personFilter, QSimConfigGroup qsimConfig) { + Preconditions.checkState( + qsimConfig.getPersonInitializedEventsSetting().equals(PersonInitializedEventsSetting.all), + "We now require to have qsim.personInitializedEvents to be set to 'all'."); return new ActivityListener(personFilter); } diff --git a/core/src/main/resources/melun/config.xml b/core/src/main/resources/melun/config.xml index 57ba7d3aa..7c2995003 100644 --- a/core/src/main/resources/melun/config.xml +++ b/core/src/main/resources/melun/config.xml @@ -390,6 +390,7 @@ + diff --git a/core/src/test/java/org/eqasim/TestEmissions.java b/core/src/test/java/org/eqasim/TestEmissions.java index f5481eb9f..79218af6f 100644 --- a/core/src/test/java/org/eqasim/TestEmissions.java +++ b/core/src/test/java/org/eqasim/TestEmissions.java @@ -165,7 +165,7 @@ private void runMelunEmissions() throws CommandLine.ConfigurationException, IOEx "sample_41_EFA_HOT_SubSegm_2020detailed.csv", "--eqasim-configurator", TestConfigurator.class.getName() }); - assertEquals(634526, countLines(new File("melun_test/output/output_emissions_events.xml.gz"))); + assertEquals(640230, countLines(new File("melun_test/output/output_emissions_events.xml.gz"))); RunExportEmissionsNetwork.main(new String[] { "--config-path", "melun_test/input/config.xml", "--pollutants", "PM,CO,NOx,Unknown", "--time-bin-size", "3600", diff --git a/ile_de_france/src/main/resources/corsica/corsica_config.xml b/ile_de_france/src/main/resources/corsica/corsica_config.xml index 435c2e328..49583dc1f 100644 --- a/ile_de_france/src/main/resources/corsica/corsica_config.xml +++ b/ile_de_france/src/main/resources/corsica/corsica_config.xml @@ -706,6 +706,7 @@ +