MATSIM
FacilitiesFromPopulation.java
Go to the documentation of this file.
1 /* *********************************************************************** *
2  * project: org.matsim.*
3  * *
4  * *********************************************************************** *
5  * *
6  * copyright : (C) 2013 by the members listed in the COPYING, *
7  * LICENSE and WARRANTY file. *
8  * email : info at matsim dot org *
9  * *
10  * *********************************************************************** *
11  * *
12  * This program is free software; you can redistribute it and/or modify *
13  * it under the terms of the GNU General Public License as published by *
14  * the Free Software Foundation; either version 2 of the License, or *
15  * (at your option) any later version. *
16  * See also COPYING, LICENSE and WARRANTY file *
17  * *
18  * *********************************************************************** */
19 
20 package org.matsim.facilities;
21 
23 
24 import java.util.HashMap;
25 import java.util.HashSet;
26 import java.util.Map;
27 import java.util.Objects;
28 import java.util.Set;
29 
30 import org.apache.logging.log4j.LogManager;
31 import org.apache.logging.log4j.Logger;
32 import org.matsim.api.core.v01.Coord;
33 import org.matsim.api.core.v01.Id;
34 import org.matsim.api.core.v01.IdMap;
35 import org.matsim.api.core.v01.Scenario;
46 import org.matsim.core.gbl.Gbl;
49 
60 public final class FacilitiesFromPopulation {
61 
62  private final static Logger log = LogManager.getLogger(FacilitiesFromPopulation.class);
63 
65  private Scenario scenario;
67  private String idPrefix = "";
68  private Network network = null;
69  private boolean removeLinksAndCoordinates = true;
71  private boolean addEmptyActivityOptions = false;
72 
73  public FacilitiesFromPopulation(final ActivityFacilities facilities) {
74  // minimalistic constructor, to configure via external setters
75  this.facilities = facilities;
76  }
77 
78  public FacilitiesFromPopulation( Scenario scenario ) {
79  // "fat" constructor, to configure via config etc.
80  this(scenario.getActivityFacilities());
81  FacilitiesConfigGroup facilityConfigGroup = scenario.getConfig().facilities();
82  this.idPrefix = facilityConfigGroup.getIdPrefix();
83 // this.removeLinksAndCoordinates = facilityConfigGroup.isRemovingLinksAndCoordinates();
84  this.removeLinksAndCoordinates = false ;
85 // this.addEmptyActivityOptions = facilityConfigGroup.isAddEmptyActivityOption();
86  this.addEmptyActivityOptions = true ;
87  this.facilitiesSource = facilityConfigGroup.getFacilitiesSource();
88  this.network = scenario.getNetwork() ;
89  this.scoringConfigGroup = scenario.getConfig().scoring() ;
90  this.scenario = scenario;
91  }
92  public void setFacilitiesSource( final FacilitiesSource facilitiesSource ) {
93  this.facilitiesSource = facilitiesSource;
94  }
104  public void setOneFacilityPerLink(final boolean oneFacilityPerLink) {
105  if ( oneFacilityPerLink ) {
106  this.facilitiesSource = FacilitiesSource.onePerActivityLinkInPlansFile;
107  } else{
108  this.facilitiesSource = FacilitiesSource.onePerActivityLocationInPlansFile;
109  }
110  }
111 
112  public void setIdPrefix(final String prefix) {
113  this.idPrefix = prefix;
114  }
115 
125  public void setAssignLinksToFacilitiesIfMissing( final Network network ) {
126  Gbl.assertNotNull( network );
127  this.network = network ;
128  }
129 
136  public void setRemoveLinksAndCoordinates(final boolean doRemoval) {
137  this.removeLinksAndCoordinates = doRemoval;
138  }
139 
140  public void assignOpeningTimes( final ScoringConfigGroup calcScoreConfigGroup ) {
141  Gbl.assertNotNull( calcScoreConfigGroup );
142  this.scoringConfigGroup = calcScoreConfigGroup ;
143  }
144 
145  public void run(final Population population) {
146  handleActivities(population);
147  if (this.scoringConfigGroup != null ) {
148  if (this.addEmptyActivityOptions) {
149  this.assignOpeningTimes();
150  } else{
151  log.error("Cannot assign opening times to activity facilities because switch to add empty activity option to activity facilities is set to false.");
152  }
153  }
154  }
155 
156  private void handleActivities(final Population population) {
157  Gbl.assertNotNull( network ) ;
158 
159  int idxCounter = 0;
160  ActivityFacilitiesFactory factory = this.facilities.getFactory();
161  IdMap<Link, ActivityFacility> facilitiesPerLinkId = new IdMap<>(Link.class);
162  Map<Coord, ActivityFacility> facilitiesPerCoordinate = new HashMap<>();
163 
164  for (Person person : population.getPersons().values()) {
165  for (Plan plan : person.getPlans()) {
166  for (PlanElement pe : plan.getPlanElements()) {
167  if (pe instanceof Activity) {
168  Activity activity = (Activity) pe;
169 
170  Coord coord = activity.getCoord();
171  // (may be null, and we are not fixing it at this point)
172 
173  Id<Link> linkId = activity.getLinkId();
174  // (may be null, and we are not fixing it at this point)
175 
176  Gbl.assertIf( coord!=null || linkId!=null );
177  // (need one of them non-null!)
178 
179  ActivityFacility facility ;
180 
181  if ( linkId == null ) {
182  linkId = NetworkUtils.getNearestLinkExactly(this.network, coord).getId();
183  // yyyy we have been using the non-exact version in other parts of the project. kai, mar'19
184  }
185  if ( coord==null ) {
186  coord = PopulationUtils.decideOnCoordForActivity( activity, scenario );
187  }
188 
189  Gbl.assertNotNull( linkId );
190 
191  if ( this.facilitiesSource==FacilitiesSource.onePerActivityLinkInPlansFile
192  || ( this.facilitiesSource==FacilitiesSource.onePerActivityLinkInPlansFileExceptWhenCoordinatesAreGiven && coord==null )
193  ) {
194  facility = facilitiesPerLinkId.get(linkId);
195  if (facility == null) {
196  final Id<ActivityFacility> facilityId = Id.create( this.idPrefix + linkId.toString() , ActivityFacility.class );
197  final ActivityFacility preExistingFacilityIfAny = this.facilities.getFacilities().get( facilityId );
198  if ( preExistingFacilityIfAny == null ){
199  facility = factory.createActivityFacility( facilityId , coord , linkId );
200  facilitiesPerLinkId.put( linkId , facility );
201  this.facilities.addActivityFacility( facility );
202  } else {
203  if ( Objects.equals( preExistingFacilityIfAny.getLinkId() ,
204  linkId ) && Objects.equals( preExistingFacilityIfAny.getCoord() , coord ) ) {
205  // do nothing; presumably, same auto-generation has been run before
206  facility = preExistingFacilityIfAny;
207  } else {
208  throw new RuntimeException( "Facility with id=" + facilityId + " but different in coordinates and/or linkId already exists." ) ;
209  }
210  }
211  // above code is a duplicate, but they are difficult to merge because facilitiesPerLinkId is an IdMap while facilitiesPerCoord is a normal Map. kai, feb'20
212  }
213  } else if ( this.facilitiesSource==FacilitiesSource.onePerActivityLocationInPlansFile
214  || ( this.facilitiesSource==FacilitiesSource.onePerActivityLinkInPlansFileExceptWhenCoordinatesAreGiven && coord!=null )
215  ) {
216  if (coord == null) {
217  throw new RuntimeException("Coordinate for the activity "+activity+" is null, cannot collect facilities per coordinate. " +
218  "Possibly use " + FacilitiesSource.onePerActivityLinkInPlansFile + " " +
219  "instead and collect facilities per link.");
220  }
221 
222  facility = facilitiesPerCoordinate.get(coord);
223  if (facility == null) {
224  final Id<ActivityFacility> facilityId = Id.create( this.idPrefix + idxCounter++ , ActivityFacility.class );
225  final ActivityFacility preExistingFacilityIfAny = this.facilities.getFacilities().get( facilityId );
226  if ( preExistingFacilityIfAny == null ){
227  facility = factory.createActivityFacility( facilityId , coord , linkId );
228  facilitiesPerCoordinate.put( coord , facility );
229  this.facilities.addActivityFacility( facility );
230  } else {
231  if ( Objects.equals( preExistingFacilityIfAny.getLinkId() , linkId ) && Objects.equals( preExistingFacilityIfAny.getCoord() , coord ) ) {
232  // do nothing; presumably, same auto-generation has been run before
233  facility = preExistingFacilityIfAny;
234  } else {
235  throw new RuntimeException( "Facility with id=" + facilityId + " but different in coordinates and/or linkId already exists." ) ;
236  }
237  }
238  // above code is a duplicate, but they are difficult to merge because facilitiesPerLinkId is an IdMap while facilitiesPerCoord is a normal Map. kai, feb'20
239  }
240  } else {
241  throw new RuntimeException( "should never get to this location; either class/method used with invalid" +
242  " setting of facilitiesSource, or something there is " +
243  "something that was not understood while implementing " +
244  "this." );
245  }
246 
247  if (this.addEmptyActivityOptions) {
248  String actType = activity.getType();
249  ActivityOption option = facility.getActivityOptions().get(actType);
250  if (option == null) {
251  option = factory.createActivityOption(actType);
252  facility.addActivityOption(option);
253  }
254  }
255 
256  activity.setFacilityId(facility.getId());
257  if (this.removeLinksAndCoordinates) {
258  activity.setLinkId(null);
259  activity.setCoord(null);
260  }
261  }
262  }
263  }
264  }
265  }
266 
267  private void assignOpeningTimes() {
268  Set<String> missingActTypes = new HashSet<>();
269  for (ActivityFacility af : this.facilities.getFacilities().values()) {
270  for (ActivityOption ao : af.getActivityOptions().values()) {
271  String actType = ao.getType();
272  ActivityParams params = this.scoringConfigGroup.getActivityParams(actType);
273  if (params == null) {
274  if (missingActTypes.add(actType)) {
275  log.error("No information for activity type " + actType + " found in given configuration.");
276  }
277  } else {
278  ao.addOpeningTime(OpeningTimeImpl.createFromOptionalTimes(params.getOpeningTime(),
279  params.getClosingTime()));
280  }
281  }
282  }
283  }
284 
285  public void setAddEmptyActivityOptions(boolean addEmptyActivityOptions) {
286  this.addEmptyActivityOptions = addEmptyActivityOptions;
287  }
288 }
Map< Id< ActivityFacility >, ? extends ActivityFacility > getFacilities()
static void assertIf(boolean flag)
Definition: Gbl.java:207
void addActivityOption(ActivityOption option)
void addActivityFacility(ActivityFacility facility)
void setFacilitiesSource(final FacilitiesSource facilitiesSource)
void setOneFacilityPerLink(final boolean oneFacilityPerLink)
FacilitiesFromPopulation(final ActivityFacilities facilities)
Map< Id< Person >,? extends Person > getPersons()
final ScoringConfigGroup scoring()
Definition: Config.java:407
ActivityOption createActivityOption(String type)
static< T > Id< T > create(final long key, final Class< T > type)
Definition: Id.java:68
ActivityFacilitiesFactory getFactory()
static Link getNearestLinkExactly(Network network, Coord coord)
final FacilitiesConfigGroup facilities()
Definition: Config.java:423
ActivityFacility createActivityFacility(Id< ActivityFacility > id, Coord coord)
static void assertNotNull(Object obj)
Definition: Gbl.java:212
void setAddEmptyActivityOptions(boolean addEmptyActivityOptions)
void assignOpeningTimes(final ScoringConfigGroup calcScoreConfigGroup)
ActivityFacilities getActivityFacilities()
static Coord decideOnCoordForActivity(Activity act, Scenario sc)
Map< String, ActivityOption > getActivityOptions()
V put(Id< T > key, V value)
Definition: IdMap.java:141
void setFacilityId(final Id< ActivityFacility > id)
static OpeningTime createFromOptionalTimes(OptionalTime start, OptionalTime end)