def test__save_geography(self, world_h5): areas = world_h5.areas super_areas = world_h5.super_areas geography = Geography(areas, super_areas) save_geography_to_hdf5(geography, "test.hdf5") geography_recovered = load_geography_from_hdf5("test.hdf5") for area, area2 in zip(areas, geography_recovered.areas): for attribute_name in ["id", "name"]: attribute = getattr(area, attribute_name) attribute2 = getattr(area2, attribute_name) if attribute is None: assert attribute2 == None else: assert attribute == attribute2 if area.super_area is not None: assert area.super_area.id == area2.super_area else: assert area2.super_area is None assert area.coordinates[0] == area2.coordinates[0] assert area.coordinates[1] == area2.coordinates[1] for super_area, super_area2 in zip( super_areas, geography_recovered.super_areas ): for attribute_name in ["id", "name"]: attribute = getattr(super_area, attribute_name) attribute2 = getattr(super_area2, attribute_name) if attribute is None: assert attribute2 == None else: assert attribute == attribute2 assert super_area.coordinates[0] == super_area2.coordinates[0] assert super_area.coordinates[1] == super_area2.coordinates[1]
def to_hdf5(self, file_path: str, chunk_size=100000): """ Saves the world to an hdf5 file. All supergroups and geography are stored as groups. Class instances are substituted by ids of the instances. To load the world back, one needs to call the generate_world_from_hdf5 function. Parameters ---------- file_path path of the hdf5 file chunk_size how many units of supergroups to process at a time. It is advise to keep it around 1e5 """ # empty file with h5py.File(file_path, "w"): pass geo = Geography(self.areas, self.super_areas) save_geography_to_hdf5(geo, file_path) save_population_to_hdf5(self.people, file_path, chunk_size) if self.hospitals is not None: save_hospitals_to_hdf5(self.hospitals, file_path, chunk_size) if self.schools is not None: save_schools_to_hdf5(self.schools, file_path, chunk_size) if self.companies is not None: save_companies_to_hdf5(self.companies, file_path, chunk_size) if self.households is not None: save_households_to_hdf5(self.households, file_path, chunk_size) if self.care_homes is not None: save_care_homes_to_hdf5(self.care_homes, file_path, chunk_size) if self.commutecities is not None: save_commute_cities_to_hdf5(self.commutecities, file_path) if self.commutehubs is not None: save_commute_hubs_to_hdf5(self.commutehubs, file_path) if self.universities is not None: save_universities_to_hdf5(self.universities, file_path) if self.pubs is not None: save_pubs_to_hdf5(self.pubs, file_path) if self.cinemas is not None: save_cinemas_to_hdf5(self.cinemas, file_path) if self.groceries is not None: save_groceries_to_hdf5(self.groceries, file_path)
def load_geography_from_hdf5(file_path: str, chunk_size=50000): """ Loads geography from an hdf5 file located at ``file_path``. Note that this object will not be ready to use, as the links to object instances of other classes need to be restored first. This function should be rarely be called oustide world.py """ with h5py.File(file_path, "r", libver="latest", swmr=True) as f: geography = f["geography"] n_areas = geography.attrs["n_areas"] area_list = [] n_super_areas = geography.attrs["n_super_areas"] # areas n_chunks = int(np.ceil(n_areas / chunk_size)) for chunk in range(n_chunks): idx1 = chunk * chunk_size idx2 = min((chunk + 1) * chunk_size, n_areas) ids = geography["area_id"][idx1:idx2] names = geography["area_name"][idx1:idx2] super_areas = geography["area_super_area"][idx1:idx2] area_coordinates = geography["area_coordinates"][idx1:idx2] for k in range(idx2 - idx1): area = Area(names[k].decode(), super_areas[k], area_coordinates[k]) area.id = ids[k] area_list.append(area) # super areas super_area_list = [] n_chunks = int(np.ceil(n_super_areas / chunk_size)) for chunk in range(n_chunks): idx1 = chunk * chunk_size idx2 = min((chunk + 1) * chunk_size, n_super_areas) ids = geography["super_area_id"][idx1:idx2] names = geography["super_area_name"][idx1:idx2] super_area_coordinates = geography["super_area_coordinates"][idx1:idx2] for k in range(idx2 - idx1): super_area = SuperArea( names[k].decode(), None, super_area_coordinates[k] ) super_area.id = ids[k] super_area_list.append(super_area) areas = Areas(area_list) super_areas = SuperAreas(super_area_list) return Geography(areas, super_areas)