Stride Reference Manual  1.0
ClusterSaver.cpp
Go to the documentation of this file.
1 
2 
3 #include <boost/property_tree/xml_parser.hpp>
4 #include <boost/property_tree/ptree.hpp>
5 #include <boost/property_tree/json_parser.hpp>
6 #include <boost/filesystem.hpp>
7 #include <string>
8 #include <utility>
9 #include <iostream>
10 #include <sstream>
11 #include <iomanip>
12 #include <fstream>
13 #include <map>
14 
15 #include "vis/ClusterSaver.h"
16 #include "util/InstallDirs.h"
18 #include "core/ClusterType.h"
19 
20 using boost::property_tree::ptree;
21 using boost::property_tree::write_json;
22 using std::map;
23 using std::ofstream;
24 using std::setw;
25 using std::setfill;
26 using std::string;
27 using std::stringstream;
28 using std::vector;
29 using std::to_string;
30 
31 
32 namespace stride {
33 
34 ClusterSaver::ClusterSaver(string file_name, string pop_file_name, string facility_file_name, string output_dir) :
35  m_sim_day(0), m_file_name(file_name), m_pop_file_name(pop_file_name), m_facility_file_name(facility_file_name) {
36 
37  /*#if defined(__linux__)
38  m_file_dir = "vis/resources/app/data";
39  #elif defined(__APPLE__)
40  m_file_dir = "vis/visualization.app/Contents/Resources/app/data";
41  #endif
42  // Sorry windows*/
43 
44  m_file_dir = output_dir;
45 
46  boost::filesystem::create_directory(boost::filesystem::path(m_file_dir));
47 
48  m_pop_file_dir = m_file_dir + "/populationData";
49  m_facility_file_dir = m_file_dir + "/transportFacilityData";
50  m_file_dir = m_file_dir + "/clusterData";
51  // Create the subdirectory if it does not exist.
52  if (!boost::filesystem::exists(boost::filesystem::path(m_file_dir))) {
53  boost::filesystem::create_directory(boost::filesystem::path(m_file_dir));
54  }
55 
56  // Create the subdirectory if it does not exist.
57  if (!boost::filesystem::exists(boost::filesystem::path(m_pop_file_dir))) {
58  boost::filesystem::create_directory(boost::filesystem::path(m_pop_file_dir));
59  }
60 
61  // Create the subdirectory if it does not exist.
62  if (!boost::filesystem::exists(boost::filesystem::path(m_facility_file_dir))) {
63  boost::filesystem::create_directory(boost::filesystem::path(m_facility_file_dir));
64  }
65 }
66 
67 
68 void ClusterSaver::saveClustersCSV(const Simulator& sim) const {
69  ofstream csv_file;
70  stringstream ss;
71  ss << setfill('0') << setw(5) << m_sim_day;
72  string file_name = m_file_dir + "/" + m_file_name + "_" + ss.str() + ".csv";
73  csv_file.open(file_name.c_str());
74 
75  // Format of the csv file
76  csv_file << "id,size,infected,infected_percent,lat,lon,type" << endl;
77 
78  for (const auto& cluster : sim.getPrimaryCommunities()) {
79  this->saveClusterCSV(cluster, csv_file);
80  }
81  for (const auto& cluster : sim.getSecondaryCommunities()) {
82  this->saveClusterCSV(cluster, csv_file);
83  }
84 
85  this->saveAggrClustersCSV(sim.getHouseholds(), csv_file);
86  this->saveAggrClustersCSV(sim.getWorkClusters(), csv_file);
87  this->saveAggrClustersCSV(sim.getSchoolClusters(), csv_file);
88 
89  csv_file.close();
90 }
91 
92 inline void ClusterSaver::saveClusterCSV(const Cluster& cluster, ofstream& csv_file) const {
93  size_t size = cluster.getSize();
94  if (size == 0) {
95  return;
96  }
97  size_t infected_count = cluster.getInfectedCount();
98  double ratio = (infected_count == 0 ? -1 : (double) infected_count / size);
99  GeoCoordinate coords = cluster.getLocation();
100 
101  csv_file << cluster.getId() << ',' <<
102  size << ',' <<
103  infected_count << ',' <<
104  ratio << ',' <<
105  coords.m_latitude << ',' <<
106  coords.m_longitude << ',' <<
107  toString(cluster.getClusterType()) << "\n";
108 }
109 
110 void ClusterSaver::saveAggrClustersCSV(const vector<Cluster>& households, ofstream& csv_file) const {
111  map<GeoCoordinate, vector<unsigned int>> aggregation_mapping;
112 
113  for (unsigned int i = 1; i < households.size(); i++) {
114  aggregation_mapping[households[i].getLocation()].push_back(i);
115  }
116 
117  for (auto entry : aggregation_mapping) {
118  this->saveClusterGroup(households, entry.second, csv_file);
119  }
120 }
121 
122 void ClusterSaver::saveClusterGroup(const vector<Cluster>& households, const vector<unsigned int> indices,
123  ofstream& csv_file) const {
124  // Use the first id as cluster id
125  unsigned int id = households[indices[0]].getId();
126  GeoCoordinate coords = households[indices[0]].getLocation();
127  string cluster_type = toString(households[indices[0]].getClusterType());
128 
129  unsigned int total_size = 0;
130  unsigned int total_infected = 0;
131  for (auto index : indices) {
132  total_size += households[index].getSize();
133  total_infected += households[index].getInfectedCount();
134  }
135  double ratio = (total_infected == 0 ? -1 : (double) total_infected / total_size);
136 
137  csv_file << id << ',' <<
138  total_size << ',' <<
139  total_infected << ',' <<
140  ratio << ',' <<
141  coords.m_latitude << ',' <<
142  coords.m_longitude << ',' <<
143  cluster_type << "\n";
144 }
145 
146 
148  // ptree clusters;
149  // clusters.put("type", "FeatureCollection");
150  // {
151  // ptree clusters_primaries;
152  // // First cluster is always empty
153  // for (unsigned int i = 1; i < sim.m_primary_community.size(); i++) {
154  // pair<ptree, ptree> cluster_pair = this->getClusterJSON(sim.m_primary_community.at(i));
155  // ptree cluster_primary;
156  // cluster_primary.put("type", "Feature");
157  // cluster_primary.push_back(std::make_pair("geometry", cluster_pair.first));
158  // cluster_primary.push_back(std::make_pair("properties", cluster_pair.second));
159  //
160  // clusters_primaries.push_back(std::make_pair("", cluster_primary));
161  // }
162  // clusters.add_child("features", clusters_primaries);
163  // }
164  // {
165  // ptree clusters_secondaries;
166  // for (unsigned int i = 0; i < sim.m_secondary_community.size(); i++) {
167  // pair<ptree, ptree> cluster_pair = this->getClusterJSON(sim.m_secondary_community.at(i), i);
168  // ptree cluster_secondary;
169  // cluster_secondary.put("type", "Feature");
170  // cluster_secondary.push_back(std::make_pair("geometry", cluster_pair.first));m_pop_file_name
171  // cluster_secondary.push_back(std::make_pair("properties", cluster_pair.second));
172  //
173  // clusters_secondaries.push_back(std::make_pair("", cluster_secondary));
174  // }
175  // clusters.add_child("Secondary_communities", clusters_secondaries);
176  // }
177  // stringstream ss;
178  // ss << setfill('0') << setw(5) << m_sim_day;
179  // write_json(util::InstallDirs::getOutputDir().string() + "/" + m_file_name + "_" + ss.str() + ".json", clusters);
180 }
181 
182 pair<ptree, ptree> ClusterSaver::getClusterJSON(const Cluster& cluster) const {
183 
184  ptree cluster_geometry;
185  ptree cluster_properties;
186 
187  cluster_geometry.put("type", "Point");
188  ptree coordinates;
189 
190  GeoCoordinate coords = cluster.getLocation();
191  ptree lat;
192  ptree lon;
193  lat.put("", coords.m_latitude);
194  lon.put("", coords.m_longitude);
195  coordinates.push_back(std::make_pair("", lon));
196  coordinates.push_back(std::make_pair("", lat));
197  cluster_geometry.add_child("coordinates", coordinates);
198 
199  size_t id = cluster.getId();
200  size_t size = cluster.getSize();
201  size_t infected_count = cluster.getInfectedCount();
202  double ratio = (size == 0 ? 0 : (double) infected_count / size);
203  if (infected_count == 0) {
204  ratio = -1;
205  }
206  string cluster_type = toString(cluster.getClusterType());
207 
208  cluster_properties.put("id", id);
209  cluster_properties.put("size", size);
210  cluster_properties.put("infected", infected_count);
211  cluster_properties.put("infected_percent", ratio);
212  cluster_properties.put("type", cluster_type);
213 
214  return std::make_pair(cluster_geometry, cluster_properties);
215 }
216 
217 #define SET_CLUSTER_SURFACE(cluster_type) \
218 { \
219  surface = ClusterCalculator<cluster_type>::calculateSurface(local_sim); \
220  if (surface == 0.0) \
221  densities.put(toString(cluster_type), 0.0); \
222  else \
223  densities.put(toString(cluster_type), double(pop_count) / surface); \
224 }
225 
226 #define SET_CLUSTER_MAP(cluster_type) \
227 { \
228  ptree specific_cluster_map; \
229  auto cluster_map = ClusterCalculator<cluster_type>::getClusterMap(local_sim); \
230  for (auto it = cluster_map.begin(); it != cluster_map.end(); ++it) { \
231  if (it->first != 0) { \
232  specific_cluster_map.put(to_string(it->first), it->second); \
233  } \
234  } \
235  cluster_sizes.add_child(toString(cluster_type), specific_cluster_map); \
236 }
237 
238 void ClusterSaver::savePopDataJSON(const Simulator& local_sim) const {
239  stringstream ss;
240  ss << setfill('0') << setw(5) << m_sim_day;
241  string file_name = m_pop_file_dir + "/" + m_pop_file_name + "_" + ss.str() + ".json";
242 
243  ptree pop_data;
244  {
245  uint pop_count = getPopCount(local_sim);
246 
247  ptree densities;
248 
249  // Set population densities
250  double surface;
256 
257  pop_data.add_child("densities", densities);
258 
259  ptree ages;
260  // Set ages
261  auto age_map = getAgeMap(local_sim);
262  for (auto it = age_map.begin(); it != age_map.end(); ++it) {
263  ages.put(to_string(it->first), it->second);
264  }
265 
266  pop_data.add_child("age_map", ages);
267 
268  ptree cluster_sizes;
269 
270  // Set cluster sizes
276 
277  pop_data.add_child("cluster_sizes", cluster_sizes);
278  }
279 
280  write_json(file_name.c_str(), pop_data);
281 }
282 
283 double ClusterSaver::getPopCount(const Simulator& local_sim) const {
284  // TODO only people that are not on vacation
285  uint total = 0;
286 
287  for (const auto& cluster: local_sim.getPrimaryCommunities()) {
288  total += cluster.getSize();
289  }
290 
291  return total;
292 }
293 
294 map<uint, uint> ClusterSaver::getAgeMap(const Simulator& local_sim) const {
295  map<uint, uint> result;
296 
297  for (const auto& cluster: local_sim.getPrimaryCommunities()) {
298  for (const auto& person: cluster.getMembers()) {
299  if (result.find(person.first->getAge()) == result.end()) {
300  result[person.first->getAge()] = 0;
301  } else {
302  ++result[person.first->getAge()];
303  }
304  }
305  }
306 
307  return result;
308 }
309 
311  ptree result;
312  ptree children;
313 
314  for (const auto& district: local_sim.getDistricts()) {
315  for (const auto& facility: district.m_transportations_facilities) {
316  ptree facility_config;
317  facility_config.put("city", district.getName());
318  facility_config.put("name", facility.first);
319  facility_config.put("location.lat", district.getLocation().m_latitude);
320  facility_config.put("location.lon", district.getLocation().m_longitude);
321  facility_config.put("influence", facility.second.getInfluence());
322  facility_config.put("passengers_today", facility.second.m_deque.front());
323  facility_config.put("passengers_x_days", facility.second.getScore());
324  facility_config.put("x_days", facility.second.m_deque.size());
325 
326  children.push_back(make_pair("", facility_config));
327  }
328  }
329 
330  result.add_child("facilities", children);
331 
332  stringstream ss;
333  ss << setfill('0') << setw(5) << m_sim_day;
334  string file_name = m_facility_file_dir + "/" + m_facility_file_name + "_" + ss.str() + ".json";
335  write_json(file_name.c_str(), result);
336 }
337 
338 }
const std::vector< Cluster > & getPrimaryCommunities() const
Definition: Simulator.h:143
GeoCoordinate getLocation() const
Return the geo coordinates (latitude-longitude) of the cluster.
Definition: Cluster.h:70
unsigned int uint
Definition: ClusterSaver.h:38
Interface for install directory queries.
string toString(ClusterType c)
Converts a ClusterType value to corresponding name.
Definition: ClusterType.cpp:54
double getPopCount(const Simulator &local_sim) const
#define SET_CLUSTER_SURFACE(cluster_type)
void saveClustersCSV(const Simulator &sim) const
Saves cluster information for Households (aggregated), Primary Communities and Secondary Communities...
ClusterType getClusterType() const
Return the type of this cluster.
Definition: Cluster.h:67
std::size_t getInfectedCount() const
Return the amount of infected people in this cluster.
Definition: Cluster.cpp:50
#define SET_CLUSTER_MAP(cluster_type)
Time Dependent Person DataType.
Definition: NoBehaviour.h:17
void saveClustersJSON(const Simulator &sim) const
pair< ptree, ptree > getClusterJSON(const Cluster &cluster) const
void saveTransportationFacilities(const Simulator &local_sim) const
ClusterSaver(string file_name, string pop_file_name, string facility_file_name, string output_dir)
map< uint, uint > getAgeMap(const Simulator &local_sim) const
void saveClusterGroup(const vector< Cluster > &households, const vector< uint > indices, ofstream &csv_file) const
Saves an aggregated cluster. The clusters that need to be aggregated are given by the indices...
std::size_t getSize() const
Return number of persons in this cluster.
Definition: Cluster.h:58
const std::vector< Cluster > & getSchoolClusters() const
Definition: Simulator.h:139
Definition of ClusterType.
Main class that contains and direct the virtual world.
Definition: Simulator.h:64
std::size_t getId() const
Get the ID of this cluster.
Definition: Cluster.h:78
const std::vector< Cluster > & getWorkClusters() const
Definition: Simulator.h:141
const std::vector< Cluster > & getSecondaryCommunities() const
Definition: Simulator.h:145
void savePopDataJSON(const Simulator &local_sim) const
Represents a location for social contacts, an group of people.
Definition: Cluster.h:46
void saveClusterCSV(const Cluster &cluster, ofstream &csv_file) const
Saves a single cluster.
const std::vector< Cluster > & getHouseholds() const
Definition: Simulator.h:137
void saveAggrClustersCSV(const vector< Cluster > &households, ofstream &csv_file) const
Aggregates the vector of given clusters according to their GeoLocation, and saves them...
const std::vector< District > & getDistricts() const
Definition: Simulator.h:147