diff --git a/city_model_structure/city.py b/city_model_structure/city.py index 9f6b0e0a..9465f368 100644 --- a/city_model_structure/city.py +++ b/city_model_structure/city.py @@ -2,7 +2,6 @@ City module SPDX - License - Identifier: LGPL - 3.0 - or -later Copyright © 2020 Project Author Guille Gutierrez guillermo.gutierrezmorote@concordia.ca -Contributor Peter Yefi peteryefi@gmail.com """ from __future__ import annotations import sys @@ -19,361 +18,372 @@ from city_model_structure.city_objects_cluster import CityObjectsCluster from city_model_structure.buildings_cluster import BuildingsCluster from city_model_structure.parts_consisting_building import PartsConsistingBuilding from city_model_structure.subway_entrance import SubwayEntrance +from city_model_structure.fuel import Fuel from helpers.geometry_helper import GeometryHelper from helpers.location import Location from city_model_structure.energy_system import EnergySystem class City: - """ + """ City class """ - def __init__(self, lower_corner, upper_corner, srs_name): - self._name = None - self._lower_corner = lower_corner - self._upper_corner = upper_corner - self._buildings = None - self._subway_entrances = None - self._srs_name = srs_name - self._geometry = GeometryHelper() - # todo: right now extracted at city level, in the future should be extracted also at building level if exist - self._location = None - self._country_code = None - self._climate_reference_city = None - self._climate_file = None - self._latitude = None - self._longitude = None - self._time_zone = None - self._buildings_clusters = None - self._parts_consisting_buildings = None - self._city_objects_clusters = None - self._city_objects = None - self._energy_systems = None + def __init__(self, lower_corner, upper_corner, srs_name): + self._name = None + self._lower_corner = lower_corner + self._upper_corner = upper_corner + self._buildings = None + self._subway_entrances = None + self._srs_name = srs_name + self._geometry = GeometryHelper() + # todo: right now extracted at city level, in the future should be extracted also at building level if exist + self._location = None + self._country_code = None + self._climate_reference_city = None + self._climate_file = None + self._latitude = None + self._longitude = None + self._time_zone = None + self._buildings_clusters = None + self._parts_consisting_buildings = None + self._city_objects_clusters = None + self._city_objects = None + self._energy_systems = None + self._fuels = None - def _get_location(self) -> Location: - if self._location is None: - gps = pyproj.CRS('EPSG:4326') # LatLon with WGS84 datum used by GPS units and Google Earth - try: - input_reference = pyproj.CRS(self.srs_name) # Projected coordinate system from input data - except pyproj.exceptions.CRSError: - sys.stderr.write('Invalid projection reference system, please check the input data. ' - '(e.g. in CityGML files: srs_name)\n') - sys.exit() - transformer = Transformer.from_crs(input_reference, gps) - coordinates = transformer.transform(self.lower_corner[0], self.lower_corner[1]) - self._location = GeometryHelper.get_location(coordinates[0], coordinates[1]) - return self._location + @property + def fuels(self) -> [Fuel]: + return self._fuels - @property - def country_code(self): - """ + @fuels.setter + def fuels(self, value): + self._fuels = value + + + def _get_location(self) -> Location: + if self._location is None: + gps = pyproj.CRS('EPSG:4326') # LatLon with WGS84 datum used by GPS units and Google Earth + try: + input_reference = pyproj.CRS(self.srs_name) # Projected coordinate system from input data + except pyproj.exceptions.CRSError: + sys.stderr.write('Invalid projection reference system, please check the input data. ' + '(e.g. in CityGML files: srs_name)\n') + sys.exit() + transformer = Transformer.from_crs(input_reference, gps) + coordinates = transformer.transform(self.lower_corner[0], self.lower_corner[1]) + self._location = GeometryHelper.get_location(coordinates[0], coordinates[1]) + return self._location + + @property + def country_code(self): + """ Get city country code :return: str """ - return self._get_location().country + return self._get_location().country - @property - def name(self): - """ + @property + def name(self): + """ Get city name :return: str """ - return self._get_location().city + return self._get_location().city - @property - def climate_reference_city(self) -> Union[None, str]: - """ + @property + def climate_reference_city(self) -> Union[None, str]: + """ Get the name for the climatic information reference city :return: None or str """ - return self._climate_reference_city + return self._climate_reference_city - @climate_reference_city.setter - def climate_reference_city(self, value): - """ + @climate_reference_city.setter + def climate_reference_city(self, value): + """ Set the name for the climatic information reference city :param value: str """ - if value is not None: - self._climate_reference_city = str(value) + if value is not None: + self._climate_reference_city = str(value) - @property - def climate_file(self) -> Union[None, Path]: - """ + @property + def climate_file(self) -> Union[None, Path]: + """ Get the climate file full path :return: None or Path """ - return self._climate_file + return self._climate_file - @climate_file.setter - def climate_file(self, value): - """ + @climate_file.setter + def climate_file(self, value): + """ Set the climate file full path :param value: Path """ - if value is not None: - self._climate_file = Path(value) + if value is not None: + self._climate_file = Path(value) - @property - def city_objects(self) -> Union[List[CityObject], None]: - """ + @property + def city_objects(self) -> Union[List[CityObject], None]: + """ Get the city objects belonging to the city :return: None or [CityObject] """ - if self._city_objects is None: - if self.city_objects_clusters is None: - self._city_objects = [] - else: - self._city_objects = self.city_objects_clusters - if self.buildings is not None: - for building in self.buildings: - self._city_objects.append(building) - if self.subway_entrances is not None: - for subway_entrance in self.subway_entrances: - self._city_objects.append(subway_entrance) - if self.energy_systems is not None: - for energy_system in self.energy_systems: - self._city_objects.append(energy_system) - return self._city_objects + if self._city_objects is None: + if self.city_objects_clusters is None: + self._city_objects = [] + else: + self._city_objects = self.city_objects_clusters + if self.buildings is not None: + for building in self.buildings: + self._city_objects.append(building) + if self.subway_entrances is not None: + for subway_entrance in self.subway_entrances: + self._city_objects.append(subway_entrance) + if self.energy_systems is not None: + for energy_system in self.energy_systems: + self._city_objects.append(energy_system) + return self._city_objects - @property - def buildings(self) -> Union[List[Building], None]: - """ + @property + def buildings(self) -> Union[List[Building], None]: + """ Get the buildings belonging to the city :return: None or [Building] """ - return self._buildings + return self._buildings - @property - def subway_entrances(self) -> Union[List[SubwayEntrance], None]: - """ + @property + def subway_entrances(self) -> Union[List[SubwayEntrance], None]: + """ Get the subway entrances belonging to the city :return: a list of subway entrances objects or none """ - return self._subway_entrances + return self._subway_entrances - @property - def lower_corner(self) -> List[float]: - """ + @property + def lower_corner(self) -> List[float]: + """ Get city lower corner :return: [x,y,z] """ - return self._lower_corner + return self._lower_corner - @property - def upper_corner(self) -> List[float]: - """ + @property + def upper_corner(self) -> List[float]: + """ Get city upper corner :return: [x,y,z] """ - return self._upper_corner + return self._upper_corner - def city_object(self, name) -> Union[CityObject, None]: - """ + def city_object(self, name) -> Union[CityObject, None]: + """ Retrieve the city CityObject with the given name :param name:str :return: None or CityObject """ - for city_object in self.buildings: - if city_object.name == name: - return city_object - return None + for city_object in self.buildings: + if city_object.name == name: + return city_object + return None - def add_city_object(self, new_city_object): - """ + def add_city_object(self, new_city_object): + """ Add a CityObject to the city :param new_city_object:CityObject :return: None or not implemented error """ - if new_city_object.type == 'building': - if self._buildings is None: - self._buildings = [] - self._buildings.append(new_city_object) - elif new_city_object.type == 'subway_entrance': - if self._subway_entrances is None: - self._subway_entrances = [] - self._subway_entrances.append(new_city_object) - elif new_city_object.type == 'energy_system': - if self._energy_systems is None: - self._energy_systems = [] - self._energy_systems.append(new_city_object) - else: - raise NotImplementedError(new_city_object.type) + if new_city_object.type == 'building': + if self._buildings is None: + self._buildings = [] + self._buildings.append(new_city_object) + elif new_city_object.type == 'subway_entrance': + if self._subway_entrances is None: + self._subway_entrances = [] + self._subway_entrances.append(new_city_object) + elif new_city_object.type == 'energy_system': + if self._energy_systems is None: + self._energy_systems = [] + self._energy_systems.append(new_city_object) + else: + raise NotImplementedError(new_city_object.type) - def remove_city_object(self, city_object): - """ + def remove_city_object(self, city_object): + """ Remove a CityObject from the city :param city_object:CityObject :return: None """ - if city_object.type != 'building': - raise NotImplementedError(city_object.type) - if self._buildings is None or self._buildings == []: - sys.stderr.write('Warning: impossible to remove city_object, the city is empty\n') - else: - if city_object in self._buildings: - self._buildings.remove(city_object) + if city_object.type != 'building': + raise NotImplementedError(city_object.type) + if self._buildings is None or self._buildings == []: + sys.stderr.write('Warning: impossible to remove city_object, the city is empty\n') + else: + if city_object in self._buildings: + self._buildings.remove(city_object) - @property - def srs_name(self) -> Union[None, str]: - """ + @property + def srs_name(self) -> Union[None, str]: + """ Get city srs name :return: None or str """ - return self._srs_name + return self._srs_name - @name.setter - def name(self, value): - """ + @name.setter + def name(self, value): + """ Set city name :param value:str """ - if value is not None: - self._name = str(value) + if value is not None: + self._name = str(value) - @staticmethod - def load(city_filename) -> City: - """ + @staticmethod + def load(city_filename) -> City: + """ Load a city saved with city.save(city_filename) :param city_filename: city filename :return: City """ - with open(city_filename, 'rb') as file: - return pickle.load(file) + with open(city_filename, 'rb') as file: + return pickle.load(file) - def save(self, city_filename): - """ + def save(self, city_filename): + """ Save a city into the given filename :param city_filename: destination city filename :return: None """ - with open(city_filename, 'wb') as file: - pickle.dump(self, file) + with open(city_filename, 'wb') as file: + pickle.dump(self, file) - def region(self, center, radius) -> City: - """ + def region(self, center, radius) -> City: + """ Get a region from the city :param center: specific point in space [x, y, z] :param radius: distance to center of the sphere selected in meters :return: selected_region_city """ - selected_region_lower_corner = [center[0] - radius, center[1] - radius, center[2] - radius] - selected_region_upper_corner = [center[0] + radius, center[1] + radius, center[2] + radius] - selected_region_city = City(selected_region_lower_corner, selected_region_upper_corner, srs_name=self.srs_name) - selected_region_city.climate_file = self.climate_file - # selected_region_city.climate_reference_city = self.climate_reference_city - for city_object in self.city_objects: - location = city_object.centroid - if location is not None: - distance = math.sqrt(math.pow(location[0] - center[0], 2) + math.pow(location[1] - center[1], 2) - + math.pow(location[2] - center[2], 2)) - if distance < radius: - selected_region_city.add_city_object(city_object) - return selected_region_city + selected_region_lower_corner = [center[0] - radius, center[1] - radius, center[2] - radius] + selected_region_upper_corner = [center[0] + radius, center[1] + radius, center[2] + radius] + selected_region_city = City(selected_region_lower_corner, selected_region_upper_corner, srs_name=self.srs_name) + selected_region_city.climate_file = self.climate_file +# selected_region_city.climate_reference_city = self.climate_reference_city + for city_object in self.city_objects: + location = city_object.centroid + if location is not None: + distance = math.sqrt(math.pow(location[0]-center[0], 2) + math.pow(location[1]-center[1], 2) + + math.pow(location[2]-center[2], 2)) + if distance < radius: + selected_region_city.add_city_object(city_object) + return selected_region_city - @property - def latitude(self) -> Union[None, float]: - """ + @property + def latitude(self) -> Union[None, float]: + """ Get city latitude in degrees :return: None or float """ - return self._latitude + return self._latitude - @latitude.setter - def latitude(self, value): - """ + @latitude.setter + def latitude(self, value): + """ Set city latitude in degrees :parameter value: float """ - if value is not None: - self._latitude = float(value) + if value is not None: + self._latitude = float(value) - @property - def longitude(self) -> Union[None, float]: - """ + @property + def longitude(self) -> Union[None, float]: + """ Get city longitude in degrees :return: None or float """ - return self._longitude + return self._longitude - @longitude.setter - def longitude(self, value): - """ + @longitude.setter + def longitude(self, value): + """ Set city longitude in degrees :parameter value: float """ - if value is not None: - self._longitude = float(value) + if value is not None: + self._longitude = float(value) - @property - def time_zone(self) -> Union[None, float]: - """ + @property + def time_zone(self) -> Union[None, float]: + """ Get city time_zone :return: None or float """ - return self._time_zone + return self._time_zone - @time_zone.setter - def time_zone(self, value): - """ + @time_zone.setter + def time_zone(self, value): + """ Set city time_zone :parameter value: float """ - if value is not None: - self._time_zone = float(value) + if value is not None: + self._time_zone = float(value) - @property - def buildings_clusters(self) -> Union[List[BuildingsCluster], None]: - """ + @property + def buildings_clusters(self) -> Union[List[BuildingsCluster], None]: + """ Get buildings clusters belonging to the city :return: None or [BuildingsCluster] """ - return self._buildings_clusters + return self._buildings_clusters - @property - def parts_consisting_buildings(self) -> Union[List[PartsConsistingBuilding], None]: - """ + @property + def parts_consisting_buildings(self) -> Union[List[PartsConsistingBuilding], None]: + """ Get parts consisting buildings belonging to the city :return: None or [PartsConsistingBuilding] """ - return self._parts_consisting_buildings + return self._parts_consisting_buildings - @property - def energy_systems(self) -> Union[List[EnergySystem], None]: - """ - Get energy systems belonging to the city - :return: None or [EnergySystem] - """ - return self._energy_systems + @property + def energy_systems(self) -> Union[List[EnergySystem], None]: + """ + Get energy systems belonging to the city + :return: None or [EnergySystem] + """ + return self._energy_systems - @property - def city_objects_clusters(self) -> Union[List[CityObjectsCluster], None]: - """ + @property + def city_objects_clusters(self) -> Union[List[CityObjectsCluster], None]: + """ Get city objects clusters belonging to the city :return: None or [CityObjectsCluster] """ - if self.buildings_clusters is None: - self._city_objects_clusters = [] - else: - self._city_objects_clusters = self.buildings_clusters - if self.parts_consisting_buildings is not None: - self._city_objects_clusters.append(self.parts_consisting_buildings) - return self._city_objects_clusters + if self.buildings_clusters is None: + self._city_objects_clusters = [] + else: + self._city_objects_clusters = self.buildings_clusters + if self.parts_consisting_buildings is not None: + self._city_objects_clusters.append(self.parts_consisting_buildings) + return self._city_objects_clusters - def add_city_objects_cluster(self, new_city_objects_cluster): - """ + def add_city_objects_cluster(self, new_city_objects_cluster): + """ Add a CityObject to the city :param new_city_objects_cluster:CityObjectsCluster :return: None or NotImplementedError """ - if new_city_objects_cluster.type == 'buildings': - if self._buildings_clusters is None: - self._buildings_clusters = [] - self._buildings_clusters.append(new_city_objects_cluster) - elif new_city_objects_cluster.type == 'building_parts': - if self._parts_consisting_buildings is None: - self._parts_consisting_buildings = [] - self._parts_consisting_buildings.append(new_city_objects_cluster) - else: - raise NotImplementedError + if new_city_objects_cluster.type == 'buildings': + if self._buildings_clusters is None: + self._buildings_clusters = [] + self._buildings_clusters.append(new_city_objects_cluster) + elif new_city_objects_cluster.type == 'building_parts': + if self._parts_consisting_buildings is None: + self._parts_consisting_buildings = [] + self._parts_consisting_buildings.append(new_city_objects_cluster) + else: + raise NotImplementedError diff --git a/city_model_structure/fuel.py b/city_model_structure/fuel.py new file mode 100644 index 00000000..e78a9f76 --- /dev/null +++ b/city_model_structure/fuel.py @@ -0,0 +1,41 @@ +""" +ConstructionFactory (before PhysicsFactory) retrieve the specific construction module for the given region +SPDX - License - Identifier: LGPL - 3.0 - or -later +Copyright © 2020 Project Author Atiya +""" + +class Fuel: + def __init__(self, fuel_id, name, carbon_emission_factor, unit): + self._fuel_id = fuel_id + self._name = name + self._carbon_emission_factor = carbon_emission_factor + self._unit = unit + + @property + def id(self): + """ + Get fuel id + """ + return self._fuel_id + + @property + def name(self): + """ + Get fuel name + """ + return self._name + + @property + def carbon_emission_factor(self): + """ + Get fuel carbon emission factor + """ + return self._carbon_emission_factor + + @property + def unit(self): + """ + Get fuel units + """ + return self._unit + diff --git a/data/life_cicle_analize/lca_data.xml b/data/life_cicle_analize/lca_data.xml new file mode 100644 index 00000000..bc3ab8ee --- /dev/null +++ b/data/life_cicle_analize/lca_data.xml @@ -0,0 +1,573 @@ + + + + + 0.32 + + + 0.4 + + + 0.4 + + + 0.5 + + + 0.18 + + + 0.39 + + + 0.27 + + + 4.16 + + + 2.24 + + + 0.2 + + + 3.19 + + + 3.53 + + + 0.27 + + + 0.21 + + + 1.69 + + + 0.21 + + + 0.35 + + + 0.18 + + + 0.81 + + + 1.21 + + + 1.61 + + + 0.11 + + + 0.3 + + + 1.16 + + + 0.61 + + + + + 0.347 + 16.5 + 0.918 + + + 0.033 + 25.2 + 4.16 + + + 0.027 + 16.8 + 2.239 + + + 0.023 + 16.8 + 2.239 + + + 0.109 + 25.2 + 2.239 + + + 0.003 + 16.4 + 4.16 + + + 0.002 + 11 + 0.918 + + + 0.002 + 90 + 0.918 + + + 0.002 + 10 + 0.918 + + + 0.002 + 11 + 0.918 + + + 0.002 + 132 + 0.918 + + + 0.002 + 15 + 0.918 + + + 0.002 + 5.5 + 0.918 + + + 0.002 + 22.5 + 0.918 + + + + + 0.0123 + 2.239 + + + 0.042 + 0.918 + + + 0.01 + 1.00000 + + + 1.3 + 1.00000 + + + + + + 1.8 + 560 + 0.8 + 0.3 + 0.7 + 0.2 + .... + + + 1.2 + 310 + 0.8 + 0.3 + 0.7 + 0.2 + .... + + + 2 + 3080 + 0.8 + 0.3 + 0.7 + 0.2 + .... + + + 1.4 + 300 + 0.8 + 0.3 + 0.7 + 0.2 + .... + + + + + 1.6 + 900 + 0.8 + 0 + 1 + 0.2 + .... + + + 1.6 + 2340 + 0.8 + 0 + 1 + 0.2 + .... + + + 1.6 + 1570 + 0.8 + 0 + 1 + 0.2 + .... + + + 1.4 + 1840 + 0.8 + 0 + 1 + 0.2 + .... + + + 1.3 + 410 + 0.8 + 0 + 1 + 0.2 + .... + + + 2.3 + 160 + 0.8 + 0 + 1 + 0.2 + .... + + + 2.3 + 170 + 0.8 + 0 + 1 + 0.2 + .... + + + 2.3 + 230 + 0.8 + 0 + 1 + 0.2 + .... + + + 2.4 + 240 + 0.8 + 0 + 1 + 0.2 + .... + + + 2.4 + 280 + 0.8 + 0 + 1 + 0.2 + .... + + + 2.3 + 170 + 0.8 + 0 + 1 + 0.2 + .... + + + 1.2 + 440 + 0.8 + 0 + 1 + 0.2 + .... + + + + + 2.58 + 2660 + 0.95 + 0 + 1 + 0.05 + .... + + + 2.58 + 5260 + 0.95 + 0 + 1 + 0.05 + .... + + + + + 0.06 + 1760 + 0.9 + 0 + 1 + 0.1 + .... + + + 0.122 + 3080 + 0.9 + 0 + 1 + 0.1 + .... + + + 0.028 + 3180 + 0.9 + 0 + 1 + 0.1 + .... + + + 0.024 + 5140 + 0.9 + 0 + 1 + 0.1 + .... + + + 0.1 + 6040 + 0.9 + 0 + 1 + 0.1 + .... + + + 0.3 + 5380 + 0.9 + 0 + 1 + 0.1 + .... + + + 0.032 + 2150 + 0.9 + 0 + 1 + 0.1 + .... + + + + + 0.9 + 3420 + 0.6 + 0 + 1 + 0.4 + .... + + + 0.7 + 1430 + 0.6 + 0 + 1 + 0.4 + .... + + + 0.65 + 2780 + 0.6 + 0 + 1 + 0.4 + .... + + + 0.72 + 2190 + 0.6 + 0 + 1 + 0.4 + .... + + + + + 1.43 + 1070 + 0 + 0 + 0 + 1 + .... + + + 1.43 + 240 + 0 + 0 + 0 + 1 + .... + + + 1.43 + 430 + 0 + 0 + 0 + 1 + .... + + + 1.43 + 340 + 0 + 0 + 0 + 1 + .... + + + 1.2 + 440 + 0.8 + 0 + 1 + 0.2 + .... + + + 2.1 + 1410 + 0.8 + 0 + 1 + 0.2 + .... + + + 1.43 + 250 + 0 + 0 + 0 + 1 + .... + + + 1.44 + 1480 + 0.8 + 0 + 1 + 0.2 + .... + + + 1.44 + 2220 + 0.8 + 0 + 1 + 0.2 + .... + + + 1.27 + 3960 + 0.8 + 0 + 1 + 0.2 + .... + + + 1.15 + 760 + 0.8 + 0 + 1 + 0.2 + .... + + + + + 8 + 3160 + 0.98 + 0 + 1 + 0.02 + .... + + + 2.7 + 5370 + 0.98 + 0 + 1 + 0.02 + .... + + + 7.85 + 3910 + 0.98 + 0 + 1 + 0.02 + .... + + + + \ No newline at end of file diff --git a/imports/life_cicle_analize/lca_fuel.py b/imports/life_cicle_analize/lca_fuel.py new file mode 100644 index 00000000..c35e0749 --- /dev/null +++ b/imports/life_cicle_analize/lca_fuel.py @@ -0,0 +1,24 @@ +""" +CityGml module parses citygml_classes files and import the geometry into the city model structure +SPDX - License - Identifier: LGPL - 3.0 - or -later +Copyright © 2020 Project Author Atiya +""" +import xmltodict +from pathlib import Path +from city_model_structure.fuel import Fuel + +class LcaFuel: + def __init__(self, city, base_path): + self._city = city + self._base_path = base_path + self._lca = None + + def enrich(self): + self._city.fuels = [] + path = Path(self._base_path / 'lca_data.xml').resolve() + + with open(path) as xml: + self._lca = xmltodict.parse(xml.read()) + for fuel in self._lca["library"]["Fuels"]['fuel']: + self._city.fuels.append(Fuel(fuel['@id'], fuel['@name'], fuel['carbon_emission_factor']['#text'], + fuel['carbon_emission_factor']['@unit'])) diff --git a/imports/life_cicle_analyze_factory.py b/imports/life_cicle_analyze_factory.py new file mode 100644 index 00000000..7a09097a --- /dev/null +++ b/imports/life_cicle_analyze_factory.py @@ -0,0 +1,33 @@ +""" +ConstructionFactory (before PhysicsFactory) retrieve the specific construction module for the given region +SPDX - License - Identifier: LGPL - 3.0 - or -later +Copyright © 2020 Project Author Atiya +""" + +from pathlib import Path +from imports.life_cicle_analize.lca_fuel import LcaFuel + + +class LifeCicleAnalizeFactory: + """ + Life cicle analize factory class + """ + def __init__(self, handler, city, base_path=None): + if base_path is None: + base_path = Path(Path(__file__).parent.parent / 'data/construction') + self._handler = '_' + handler.lower().replace(' ', '_') + self._city = city + self._base_path = base_path + + def _fuel(self): + """ + Enrich the city by adding the fuel carbon information + """ + LcaFuel(self._city, self._base_path).enrich() + + def enrich(self): + """ + Enrich the city given to the class using the class given handler + :return: None + """ + getattr(self, self._handler, lambda: None)() diff --git a/unittests/tests_data/lca_data.xml b/unittests/tests_data/lca_data.xml new file mode 100644 index 00000000..bc3ab8ee --- /dev/null +++ b/unittests/tests_data/lca_data.xml @@ -0,0 +1,573 @@ + + + + + 0.32 + + + 0.4 + + + 0.4 + + + 0.5 + + + 0.18 + + + 0.39 + + + 0.27 + + + 4.16 + + + 2.24 + + + 0.2 + + + 3.19 + + + 3.53 + + + 0.27 + + + 0.21 + + + 1.69 + + + 0.21 + + + 0.35 + + + 0.18 + + + 0.81 + + + 1.21 + + + 1.61 + + + 0.11 + + + 0.3 + + + 1.16 + + + 0.61 + + + + + 0.347 + 16.5 + 0.918 + + + 0.033 + 25.2 + 4.16 + + + 0.027 + 16.8 + 2.239 + + + 0.023 + 16.8 + 2.239 + + + 0.109 + 25.2 + 2.239 + + + 0.003 + 16.4 + 4.16 + + + 0.002 + 11 + 0.918 + + + 0.002 + 90 + 0.918 + + + 0.002 + 10 + 0.918 + + + 0.002 + 11 + 0.918 + + + 0.002 + 132 + 0.918 + + + 0.002 + 15 + 0.918 + + + 0.002 + 5.5 + 0.918 + + + 0.002 + 22.5 + 0.918 + + + + + 0.0123 + 2.239 + + + 0.042 + 0.918 + + + 0.01 + 1.00000 + + + 1.3 + 1.00000 + + + + + + 1.8 + 560 + 0.8 + 0.3 + 0.7 + 0.2 + .... + + + 1.2 + 310 + 0.8 + 0.3 + 0.7 + 0.2 + .... + + + 2 + 3080 + 0.8 + 0.3 + 0.7 + 0.2 + .... + + + 1.4 + 300 + 0.8 + 0.3 + 0.7 + 0.2 + .... + + + + + 1.6 + 900 + 0.8 + 0 + 1 + 0.2 + .... + + + 1.6 + 2340 + 0.8 + 0 + 1 + 0.2 + .... + + + 1.6 + 1570 + 0.8 + 0 + 1 + 0.2 + .... + + + 1.4 + 1840 + 0.8 + 0 + 1 + 0.2 + .... + + + 1.3 + 410 + 0.8 + 0 + 1 + 0.2 + .... + + + 2.3 + 160 + 0.8 + 0 + 1 + 0.2 + .... + + + 2.3 + 170 + 0.8 + 0 + 1 + 0.2 + .... + + + 2.3 + 230 + 0.8 + 0 + 1 + 0.2 + .... + + + 2.4 + 240 + 0.8 + 0 + 1 + 0.2 + .... + + + 2.4 + 280 + 0.8 + 0 + 1 + 0.2 + .... + + + 2.3 + 170 + 0.8 + 0 + 1 + 0.2 + .... + + + 1.2 + 440 + 0.8 + 0 + 1 + 0.2 + .... + + + + + 2.58 + 2660 + 0.95 + 0 + 1 + 0.05 + .... + + + 2.58 + 5260 + 0.95 + 0 + 1 + 0.05 + .... + + + + + 0.06 + 1760 + 0.9 + 0 + 1 + 0.1 + .... + + + 0.122 + 3080 + 0.9 + 0 + 1 + 0.1 + .... + + + 0.028 + 3180 + 0.9 + 0 + 1 + 0.1 + .... + + + 0.024 + 5140 + 0.9 + 0 + 1 + 0.1 + .... + + + 0.1 + 6040 + 0.9 + 0 + 1 + 0.1 + .... + + + 0.3 + 5380 + 0.9 + 0 + 1 + 0.1 + .... + + + 0.032 + 2150 + 0.9 + 0 + 1 + 0.1 + .... + + + + + 0.9 + 3420 + 0.6 + 0 + 1 + 0.4 + .... + + + 0.7 + 1430 + 0.6 + 0 + 1 + 0.4 + .... + + + 0.65 + 2780 + 0.6 + 0 + 1 + 0.4 + .... + + + 0.72 + 2190 + 0.6 + 0 + 1 + 0.4 + .... + + + + + 1.43 + 1070 + 0 + 0 + 0 + 1 + .... + + + 1.43 + 240 + 0 + 0 + 0 + 1 + .... + + + 1.43 + 430 + 0 + 0 + 0 + 1 + .... + + + 1.43 + 340 + 0 + 0 + 0 + 1 + .... + + + 1.2 + 440 + 0.8 + 0 + 1 + 0.2 + .... + + + 2.1 + 1410 + 0.8 + 0 + 1 + 0.2 + .... + + + 1.43 + 250 + 0 + 0 + 0 + 1 + .... + + + 1.44 + 1480 + 0.8 + 0 + 1 + 0.2 + .... + + + 1.44 + 2220 + 0.8 + 0 + 1 + 0.2 + .... + + + 1.27 + 3960 + 0.8 + 0 + 1 + 0.2 + .... + + + 1.15 + 760 + 0.8 + 0 + 1 + 0.2 + .... + + + + + 8 + 3160 + 0.98 + 0 + 1 + 0.02 + .... + + + 2.7 + 5370 + 0.98 + 0 + 1 + 0.02 + .... + + + 7.85 + 3910 + 0.98 + 0 + 1 + 0.02 + .... + + + + \ No newline at end of file