MATSIM
PKMbyModeCalculator.java
Go to the documentation of this file.
1 /* *********************************************************************** *
2  * project: org.matsim.*
3  * PKMbyModeCalculator.java
4  * *
5  * *********************************************************************** *
6  * *
7  * copyright : (C) 2008 by the members listed in the COPYING, *
8  * LICENSE and WARRANTY file. *
9  * email : info at matsim dot org *
10  * *
11  * *********************************************************************** *
12  * *
13  * This program is free software; you can redistribute it and/or modify *
14  * it under the terms of the GNU General Public License as published by *
15  * the Free Software Foundation; either version 2 of the License, or *
16  * (at your option) any later version. *
17  * See also COPYING, LICENSE and WARRANTY file *
18  * *
19  * *********************************************************************** */
20 
21 package org.matsim.analysis;
22 
23 import java.io.BufferedWriter;
24 import java.io.IOException;
25 import java.nio.file.Files;
26 import java.nio.file.Paths;
27 import java.util.AbstractMap;
28 import java.util.Map;
29 import java.util.TreeMap;
30 import java.util.TreeSet;
31 import java.util.stream.Collectors;
32 import jakarta.inject.Inject;
33 import org.apache.commons.csv.CSVFormat;
34 import org.apache.commons.csv.CSVPrinter;
35 import org.apache.logging.log4j.LogManager;
36 import org.jfree.chart.axis.CategoryLabelPositions;
37 import org.matsim.api.core.v01.IdMap;
44 
49 public class PKMbyModeCalculator {
50 
51  private final Map<Integer,Map<String,Double>> pmtPerIteration = new TreeMap<>();
53  private final String delimiter;
54  private final static String FILENAME = "pkm_modestats";
55 
56  @Inject
58  this.controllerIO = controllerIO;
59  this.delimiter = globalConfig.getDefaultDelimiter();
60  }
61 
62  void addIteration(int iteration, IdMap<Person, Plan> map) {
63  Map<String,Double> pmtbyMode = map.values()
64  .parallelStream()
65  .flatMap(plan -> plan.getPlanElements().stream())
66  .filter(Leg.class::isInstance)
67  .map(l->{
68  Leg leg = (Leg) l;
69  double dist = leg.getRoute()!=null?leg.getRoute().getDistance():0;
70  if (Double.isNaN(dist)) {dist = 0.0; }
71  return new AbstractMap.SimpleEntry<>(leg.getMode(),dist);
72  })
73  .collect(Collectors.toMap(AbstractMap.SimpleEntry::getKey, AbstractMap.SimpleEntry::getValue, Double::sum));
74  pmtPerIteration.put(iteration,pmtbyMode);
75  }
76 
77  void writeOutput(boolean writePng) {
78  writeCsv();
79  if (writePng){
80  new Thread(this::writePng).start();
81  }
82  }
83 
84  private void writeCsv() {
85  TreeSet<String> allModes = getAllModes();
86 
87  try {
88  BufferedWriter writer = Files.newBufferedWriter(Paths.get(controllerIO.getOutputFilename(FILENAME + ".csv")));
89  CSVPrinter csvPrinter = new CSVPrinter(writer, CSVFormat.Builder.create().setDelimiter((this.delimiter.charAt(0))).build());
90  writeHeader(csvPrinter, allModes);
91  writeValues(csvPrinter, allModes);
92  csvPrinter.close();
93  } catch (IOException e) {
94  LogManager.getLogger(getClass()).error("Could not write PKM Modestats.");
95  }
96  }
97 
98  private void writeHeader(CSVPrinter csvPrinter, TreeSet<String> allModes) throws IOException {
99  csvPrinter.print("Iteration");
100  csvPrinter.printRecord(allModes);
101  }
102 
103  private void writeValues(CSVPrinter csvPrinter, TreeSet<String> allModes) throws IOException {
104  for (Map.Entry<Integer,Map<String,Double>> e : pmtPerIteration.entrySet()){
105  csvPrinter.print(e.getKey());
106  for (String mode : allModes){
107  csvPrinter.print((int) Math.round(e.getValue().getOrDefault(mode, 0.0) / 1000.0));
108  }
109  csvPrinter.println();
110  }
111  }
112 
113  private void writePng() {
114  String[] categories = new String[pmtPerIteration.size()];
115  int i = 0;
116  for (Integer it : pmtPerIteration.keySet()){
117  categories[i++] = it.toString();
118  }
119 
120  StackedBarChart chart = new StackedBarChart("Passenger kilometers traveled per Mode","Iteration","pkm",categories);
121  //rotate x-axis by 90degrees
122  chart.getChart().getCategoryPlot().getDomainAxis().setCategoryLabelPositions(CategoryLabelPositions.UP_90);
123 
124  for (String mode : getAllModes()){
125  double[] value = pmtPerIteration.values().stream()
126  .mapToDouble(k->k.getOrDefault(mode,0.0)/1000.0)
127  .toArray();
128  chart.addSeries(mode, value);
129  }
130  chart.addMatsimLogo();
131 
132  synchronized (controllerIO) {
133  chart.saveAsPng(controllerIO.getOutputFilename(FILENAME+ ".png"), 1024, 768);
134  }
135  }
136 
137  private TreeSet<String> getAllModes() {
138  return this.pmtPerIteration.values()
139  .stream()
140  .flatMap(i -> i.keySet().stream())
141  .collect(Collectors.toCollection(TreeSet::new));
142  }
143 }
144 
Collection< V > values()
Definition: IdMap.java:204
void writeValues(CSVPrinter csvPrinter, TreeSet< String > allModes)
void addSeries(final String title, final double[] values)
final Map< Integer, Map< String, Double > > pmtPerIteration
final OutputDirectoryHierarchy controllerIO
void saveAsPng(final String filename, final int width, final int height)
Definition: ChartUtil.java:65
void writeHeader(CSVPrinter csvPrinter, TreeSet< String > allModes)