diff --git a/hub/catalog_factories/cost/montreal_complete_cost_catalog.py b/hub/catalog_factories/cost/montreal_complete_cost_catalog.py new file mode 100644 index 00000000..c66668ca --- /dev/null +++ b/hub/catalog_factories/cost/montreal_complete_cost_catalog.py @@ -0,0 +1,196 @@ +""" +Cost catalog +SPDX - License - Identifier: LGPL - 3.0 - or -later +Copyright © 2023 Concordia CERC group +Project Coder Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concordia.ca +""" + +import xmltodict +from hub.catalog_factories.catalog import Catalog +from hub.catalog_factories.data_models.cost.archetype import Archetype +from hub.catalog_factories.data_models.cost.content import Content +from hub.catalog_factories.data_models.cost.capital_cost import CapitalCost +from hub.catalog_factories.data_models.cost.chapter import Chapter +from hub.catalog_factories.data_models.cost.item_description import ItemDescription +from hub.catalog_factories.data_models.cost.operational_cost import OperationalCost +from hub.catalog_factories.data_models.cost.fuel import Fuel +from hub.catalog_factories.data_models.cost.income import Income + + +class MontrealNewCatalog(Catalog): + """ + Montreal custom catalog class + """ + + def __init__(self, path): + path = (path / 'montreal_costs_completed.xml').resolve() + with open(path, 'r', encoding='utf-8') as xml: + self._archetypes = xmltodict.parse(xml.read(), force_list='archetype') + + # store the full catalog data model in self._content + self._content = Content(self._load_archetypes()) + + def _load_archetypes(self): + _catalog_archetypes = [] + archetypes = self._archetypes['archetypes']['archetype'] + for archetype in archetypes: + lod = float(archetype['@lod']) + function = archetype['@function'] + municipality = archetype['@municipality'] + country = archetype['@country'] + currency = archetype['currency'] + capital_cost = self.load_capital_costs(archetype) + operational_cost = self._get_operational_costs(archetype['operational_cost']) + end_of_life_cost = float(archetype['end_of_life_cost']['#text']) + construction = float(archetype['incomes']['subsidies']['construction']['#text']) + hvac = float(archetype['incomes']['subsidies']['hvac']['#text']) + photovoltaic_system = float(archetype['incomes']['subsidies']['photovoltaic']['#text']) + electricity_exports = float(archetype['incomes']['electricity_export']['#text']) / 1000 / 3600 + reduction_tax = float(archetype['incomes']['tax_reduction']['#text']) / 100 + income = Income(construction_subsidy=construction, + hvac_subsidy=hvac, + photovoltaic_subsidy=photovoltaic_system, + electricity_export=electricity_exports, + reductions_tax=reduction_tax) + _catalog_archetypes.append(Archetype(lod, + function, + municipality, + country, + currency, + capital_cost, + operational_cost, + end_of_life_cost, + income)) + return _catalog_archetypes + + @staticmethod + def item_description(item_type, item): + if 'refurbishment_cost' in item.keys(): + _refurbishment = float(item['refurbishment_cost']['#text']) + _refurbishment_unit = item['refurbishment_cost']['@cost_unit'] + _item_description = ItemDescription(item_type, + initial_investment=None, + initial_investment_unit=None, + refurbishment=_refurbishment, + refurbishment_unit=_refurbishment_unit, + reposition=None, + reposition_unit=None, + lifetime=None) + else: + _reposition = float(item['reposition']['#text']) + _reposition_unit = item['reposition']['@cost_unit'] + _investment = float(item['investment_cost']['#text']) + _investment_unit = item['investment_cost']['@cost_unit'] + _lifetime = float(item['lifetime_equipment']['#text']) + _item_description = ItemDescription(item_type, + initial_investment=_investment, + initial_investment_unit=_investment_unit, + refurbishment=None, + refurbishment_unit=None, + reposition=_reposition, + reposition_unit=_reposition_unit, + lifetime=_lifetime) + + return _item_description + + def load_capital_costs(self, archetype): + archetype_capital_costs = archetype['capital_cost'] + design_allowance = float( + archetype_capital_costs['Z_allowances_overhead_profit']['Z10_design_allowance']['#text']) / 100 + overhead_and_profit = float( + archetype_capital_costs['Z_allowances_overhead_profit']['Z20_overhead_profit']['#text']) / 100 + general_chapters = [] + shell_items = [] + service_items = [] + for category in archetype_capital_costs: + if category == 'B_shell': + items = archetype_capital_costs[category] + for item in items: + components = items[item] + for component in components: + building_item = components[component] + shell_items.append(self.item_description(component, building_item)) + general_chapters.append(Chapter(chapter_type=category, items=shell_items)) + elif category == 'D_services': + services = archetype_capital_costs[category] + for service in services: + components = services[service] + if len(components.keys()) == 1: + for component in components: + service_item = components[component] + service_items.append(self.item_description(component, service_item)) + else: + for component in components: + items = components[component] + if 'investment_cost' in items.keys(): + service_item = components[component] + service_items.append(self.item_description(component, service_item)) + else: + for item in items: + service_item = items[item] + service_items.append(self.item_description(item, service_item)) + + general_chapters.append(Chapter(chapter_type=category, items=service_items)) + capital_costs = CapitalCost(general_chapters=general_chapters, + design_allowance=design_allowance, + overhead_and_profit=overhead_and_profit) + + return capital_costs + + @staticmethod + def _get_operational_costs(entry): + fuels = [] + for item in entry['fuels']['fuel']: + fuel_type = item['@fuel_type'] + fuel_variable = float(item['variable']['#text']) + fuel_variable_units = item['variable']['@cost_unit'] + fuel_fixed_monthly = None + fuel_fixed_peak = None + if fuel_type == 'electricity': + fuel_fixed_monthly = float(item['fixed_monthly']['#text']) + fuel_fixed_peak = float(item['fixed_power']['#text']) / 1000 + elif fuel_type == 'gas': + fuel_fixed_monthly = float(item['fixed_monthly']['#text']) + fuel = Fuel(fuel_type, + fixed_monthly=fuel_fixed_monthly, + fixed_power=fuel_fixed_peak, + variable=fuel_variable, + variable_units=fuel_variable_units) + fuels.append(fuel) + heating_equipment_maintenance = float(entry['maintenance']['heating_equipment']['#text']) / 1000 + cooling_equipment_maintenance = float(entry['maintenance']['cooling_equipment']['#text']) / 1000 + photovoltaic_system_maintenance = float(entry['maintenance']['photovoltaic_system']['#text']) + co2_emissions = float(entry['co2_cost']['#text']) + _operational_cost = OperationalCost(fuels, + heating_equipment_maintenance, + cooling_equipment_maintenance, + photovoltaic_system_maintenance, + co2_emissions) + return _operational_cost + + def names(self, category=None): + """ + Get the catalog elements names + :parm: for costs catalog category filter does nothing as there is only one category (archetypes) + """ + _names = {'archetypes': []} + for archetype in self._content.archetypes: + _names['archetypes'].append(archetype.name) + return _names + + def entries(self, category=None): + """ + Get the catalog elements + :parm: for costs catalog category filter does nothing as there is only one category (archetypes) + """ + return self._content + + def get_entry(self, name): + """ + Get one catalog element by names + :parm: entry name + """ + for entry in self._content.archetypes: + if entry.name.lower() == name.lower(): + return entry + raise IndexError(f"{name} doesn't exists in the catalog") diff --git a/hub/catalog_factories/costs_catalog_factory.py b/hub/catalog_factories/costs_catalog_factory.py index de341991..898773b8 100644 --- a/hub/catalog_factories/costs_catalog_factory.py +++ b/hub/catalog_factories/costs_catalog_factory.py @@ -9,6 +9,7 @@ Code contributors: Pilar Monsalvete Alvarez de Uribarri pilar.monsalvete@concord from pathlib import Path from typing import TypeVar from hub.catalog_factories.cost.montreal_custom_catalog import MontrealCustomCatalog +from hub.catalog_factories.cost.montreal_complete_cost_catalog import MontrealNewCatalog Catalog = TypeVar('Catalog') @@ -30,6 +31,13 @@ class CostsCatalogFactory: """ return MontrealCustomCatalog(self._path) + @property + def _montreal_new(self): + """ + Retrieve Montreal Custom catalog + """ + return MontrealNewCatalog(self._path) + @property def catalog(self) -> Catalog: """ @@ -37,3 +45,7 @@ class CostsCatalogFactory: :return: CostCatalog """ return getattr(self, self._catalog_type, lambda: None) + + @property + def catalog_debug(self): + return MontrealNewCatalog(self._path) diff --git a/hub/catalog_factories/data_models/cost/operational_cost.py b/hub/catalog_factories/data_models/cost/operational_cost.py index 9b20466e..1275830a 100644 --- a/hub/catalog_factories/data_models/cost/operational_cost.py +++ b/hub/catalog_factories/data_models/cost/operational_cost.py @@ -20,6 +20,7 @@ class OperationalCost: self._maintenance_pv = maintenance_pv self._co2 = co2 + @property def fuels(self) -> List[Fuel]: """ diff --git a/hub/catalog_factories/usage/__pycache__/eilat_catalog.cpython-39.pyc b/hub/catalog_factories/usage/__pycache__/eilat_catalog.cpython-39.pyc index 6f94f311..c8495890 100644 Binary files a/hub/catalog_factories/usage/__pycache__/eilat_catalog.cpython-39.pyc and b/hub/catalog_factories/usage/__pycache__/eilat_catalog.cpython-39.pyc differ diff --git a/hub/catalog_factories/usage/__pycache__/nrcan_catalog.cpython-39.pyc b/hub/catalog_factories/usage/__pycache__/nrcan_catalog.cpython-39.pyc index f31ba86c..3b8d6019 100644 Binary files a/hub/catalog_factories/usage/__pycache__/nrcan_catalog.cpython-39.pyc and b/hub/catalog_factories/usage/__pycache__/nrcan_catalog.cpython-39.pyc differ diff --git a/hub/city_model_structure/building_demand/__pycache__/layer.cpython-39.pyc b/hub/city_model_structure/building_demand/__pycache__/layer.cpython-39.pyc index fcb9d3af..15f06888 100644 Binary files a/hub/city_model_structure/building_demand/__pycache__/layer.cpython-39.pyc and b/hub/city_model_structure/building_demand/__pycache__/layer.cpython-39.pyc differ diff --git a/hub/city_model_structure/building_demand/__pycache__/surface.cpython-39.pyc b/hub/city_model_structure/building_demand/__pycache__/surface.cpython-39.pyc index 3b6aaf92..3950b16c 100644 Binary files a/hub/city_model_structure/building_demand/__pycache__/surface.cpython-39.pyc and b/hub/city_model_structure/building_demand/__pycache__/surface.cpython-39.pyc differ diff --git a/hub/city_model_structure/energy_systems/__pycache__/distribution_system.cpython-39.pyc b/hub/city_model_structure/energy_systems/__pycache__/distribution_system.cpython-39.pyc index 54356ab7..cd5e5f80 100644 Binary files a/hub/city_model_structure/energy_systems/__pycache__/distribution_system.cpython-39.pyc and b/hub/city_model_structure/energy_systems/__pycache__/distribution_system.cpython-39.pyc differ diff --git a/hub/city_model_structure/energy_systems/__pycache__/emission_system.cpython-39.pyc b/hub/city_model_structure/energy_systems/__pycache__/emission_system.cpython-39.pyc index 77b78e11..64aabbfc 100644 Binary files a/hub/city_model_structure/energy_systems/__pycache__/emission_system.cpython-39.pyc and b/hub/city_model_structure/energy_systems/__pycache__/emission_system.cpython-39.pyc differ diff --git a/hub/city_model_structure/energy_systems/__pycache__/energy_storage_system.cpython-39.pyc b/hub/city_model_structure/energy_systems/__pycache__/energy_storage_system.cpython-39.pyc index 2abd5948..a55e1c85 100644 Binary files a/hub/city_model_structure/energy_systems/__pycache__/energy_storage_system.cpython-39.pyc and b/hub/city_model_structure/energy_systems/__pycache__/energy_storage_system.cpython-39.pyc differ diff --git a/hub/city_model_structure/energy_systems/__pycache__/energy_system.cpython-39.pyc b/hub/city_model_structure/energy_systems/__pycache__/energy_system.cpython-39.pyc index 259e97f4..82059b31 100644 Binary files a/hub/city_model_structure/energy_systems/__pycache__/energy_system.cpython-39.pyc and b/hub/city_model_structure/energy_systems/__pycache__/energy_system.cpython-39.pyc differ diff --git a/hub/city_model_structure/energy_systems/__pycache__/generation_system.cpython-39.pyc b/hub/city_model_structure/energy_systems/__pycache__/generation_system.cpython-39.pyc index a96f6789..77a7095c 100644 Binary files a/hub/city_model_structure/energy_systems/__pycache__/generation_system.cpython-39.pyc and b/hub/city_model_structure/energy_systems/__pycache__/generation_system.cpython-39.pyc differ diff --git a/hub/city_model_structure/energy_systems/__pycache__/non_pv_generation_system.cpython-39.pyc b/hub/city_model_structure/energy_systems/__pycache__/non_pv_generation_system.cpython-39.pyc index 32f7c26b..2f955954 100644 Binary files a/hub/city_model_structure/energy_systems/__pycache__/non_pv_generation_system.cpython-39.pyc and b/hub/city_model_structure/energy_systems/__pycache__/non_pv_generation_system.cpython-39.pyc differ diff --git a/hub/city_model_structure/energy_systems/__pycache__/performance_curve.cpython-39.pyc b/hub/city_model_structure/energy_systems/__pycache__/performance_curve.cpython-39.pyc index e33db28d..a6ead2dd 100644 Binary files a/hub/city_model_structure/energy_systems/__pycache__/performance_curve.cpython-39.pyc and b/hub/city_model_structure/energy_systems/__pycache__/performance_curve.cpython-39.pyc differ diff --git a/hub/city_model_structure/energy_systems/__pycache__/pv_generation_system.cpython-39.pyc b/hub/city_model_structure/energy_systems/__pycache__/pv_generation_system.cpython-39.pyc index 47de2346..637183ed 100644 Binary files a/hub/city_model_structure/energy_systems/__pycache__/pv_generation_system.cpython-39.pyc and b/hub/city_model_structure/energy_systems/__pycache__/pv_generation_system.cpython-39.pyc differ diff --git a/hub/data/costs/montreal_costs_completed.xml b/hub/data/costs/montreal_costs_completed.xml new file mode 100644 index 00000000..64be368c --- /dev/null +++ b/hub/data/costs/montreal_costs_completed.xml @@ -0,0 +1,328 @@ + + + CAD + + + + + 0 + + + + + 304 + + + 857.14 + + + + + 118 + + + + + + + 800 + 800 + 25 + + + + + + 622.86 + 622.86 + 25 + + + 47.62 + 47.62 + 15 + + + 47.62 + 47.62 + 15 + + + 47.62 + 47.62 + 15 + + + 47.62 + 47.62 + 15 + + + 47.62 + 47.62 + 15 + + + 47.62 + 47.62 + 15 + + + 47.62 + 47.62 + 15 + + + 622.86 + 622.86 + 15 + + + + 0 + 0 + 15 + + + 47.62 + 47.62 + 15 + + + + 47.62 + 47.62 + 15 + + + 47.62 + 47.62 + 15 + + + + + + 47.62 + 47.62 + 15 + + + 47.62 + 47.62 + 15 + + + + + 139 + 139 + 20 + + + + + 2.5 + 14 + + + + + + 12.27 + 0 + 0.075 + + + 17.71 + 0.0640 + + + 1.2 + + + 0.04 + + + + 40 + 40 + 1 + + 30 + + 6.3 + + + 20 + 1.5 + 3.6 + + 0.07 + 5 + + + + CAD + + + + + 0 + + + + + 304 + + + 857.14 + + + + + 118 + + + + + + + 800 + 800 + 25 + + + + + + 622.86 + 622.86 + 25 + + + 47.62 + 47.62 + 15 + + + 47.62 + 47.62 + 15 + + + 47.62 + 47.62 + 15 + + + 47.62 + 47.62 + 15 + + + 47.62 + 47.62 + 15 + + + 47.62 + 47.62 + 15 + + + 47.62 + 47.62 + 15 + + + 622.86 + 622.86 + 15 + + + + 0 + 0 + 15 + + + 47.62 + 47.62 + 15 + + + + 47.62 + 47.62 + 15 + + + 47.62 + 47.62 + 15 + + + + + + 47.62 + 47.62 + 15 + + + 47.62 + 47.62 + 15 + + + + + 139 + 139 + 20 + + + + + 6 + 14 + + + + + + 12.27 + 0 + 0.075 + + + 17.71 + 0.0640 + + + 1.2 + + + 0.04 + + + + 40 + 40 + 1 + + 30 + + 6.3 + + + 20 + 1.5 + 3.6 + + 0.05 + 5 + + + \ No newline at end of file diff --git a/hub/exports/building_energy/__pycache__/idf.cpython-39.pyc b/hub/exports/building_energy/__pycache__/idf.cpython-39.pyc index 6286a2fd..a5f54a2f 100644 Binary files a/hub/exports/building_energy/__pycache__/idf.cpython-39.pyc and b/hub/exports/building_energy/__pycache__/idf.cpython-39.pyc differ diff --git a/hub/helpers/data/__pycache__/montreal_generation_system_to_hub_energy_generation_system.cpython-39.pyc b/hub/helpers/data/__pycache__/montreal_generation_system_to_hub_energy_generation_system.cpython-39.pyc index de2ff300..225e6bc3 100644 Binary files a/hub/helpers/data/__pycache__/montreal_generation_system_to_hub_energy_generation_system.cpython-39.pyc and b/hub/helpers/data/__pycache__/montreal_generation_system_to_hub_energy_generation_system.cpython-39.pyc differ diff --git a/hub/helpers/data/__pycache__/north_america_custom_fuel_to_hub_fuel.cpython-39.pyc b/hub/helpers/data/__pycache__/north_america_custom_fuel_to_hub_fuel.cpython-39.pyc index bc03122b..4a7f2d2a 100644 Binary files a/hub/helpers/data/__pycache__/north_america_custom_fuel_to_hub_fuel.cpython-39.pyc and b/hub/helpers/data/__pycache__/north_america_custom_fuel_to_hub_fuel.cpython-39.pyc differ diff --git a/hub/helpers/data/__pycache__/north_america_demand_type_to_hub_energy_demand_type.cpython-39.pyc b/hub/helpers/data/__pycache__/north_america_demand_type_to_hub_energy_demand_type.cpython-39.pyc index 0a15aabb..0b4f8e04 100644 Binary files a/hub/helpers/data/__pycache__/north_america_demand_type_to_hub_energy_demand_type.cpython-39.pyc and b/hub/helpers/data/__pycache__/north_america_demand_type_to_hub_energy_demand_type.cpython-39.pyc differ diff --git a/hub/helpers/data/__pycache__/north_america_storage_system_to_hub_storage.cpython-39.pyc b/hub/helpers/data/__pycache__/north_america_storage_system_to_hub_storage.cpython-39.pyc index b50b0108..975b3af0 100644 Binary files a/hub/helpers/data/__pycache__/north_america_storage_system_to_hub_storage.cpython-39.pyc and b/hub/helpers/data/__pycache__/north_america_storage_system_to_hub_storage.cpython-39.pyc differ diff --git a/hub/helpers/data/__pycache__/north_america_system_to_hub_energy_generation_system.cpython-39.pyc b/hub/helpers/data/__pycache__/north_america_system_to_hub_energy_generation_system.cpython-39.pyc index 3079abd1..70757d92 100644 Binary files a/hub/helpers/data/__pycache__/north_america_system_to_hub_energy_generation_system.cpython-39.pyc and b/hub/helpers/data/__pycache__/north_america_system_to_hub_energy_generation_system.cpython-39.pyc differ diff --git a/hub/imports/construction/__pycache__/eilat_physics_parameters.cpython-39.pyc b/hub/imports/construction/__pycache__/eilat_physics_parameters.cpython-39.pyc index bb658e26..93856512 100644 Binary files a/hub/imports/construction/__pycache__/eilat_physics_parameters.cpython-39.pyc and b/hub/imports/construction/__pycache__/eilat_physics_parameters.cpython-39.pyc differ diff --git a/hub/imports/construction/__pycache__/nrcan_physics_parameters.cpython-39.pyc b/hub/imports/construction/__pycache__/nrcan_physics_parameters.cpython-39.pyc index 4f79b767..981665a8 100644 Binary files a/hub/imports/construction/__pycache__/nrcan_physics_parameters.cpython-39.pyc and b/hub/imports/construction/__pycache__/nrcan_physics_parameters.cpython-39.pyc differ diff --git a/hub/imports/construction/__pycache__/nrel_physics_parameters.cpython-39.pyc b/hub/imports/construction/__pycache__/nrel_physics_parameters.cpython-39.pyc index 69de5f7e..422e1c19 100644 Binary files a/hub/imports/construction/__pycache__/nrel_physics_parameters.cpython-39.pyc and b/hub/imports/construction/__pycache__/nrel_physics_parameters.cpython-39.pyc differ diff --git a/hub/imports/geometry/__pycache__/citygml.cpython-39.pyc b/hub/imports/geometry/__pycache__/citygml.cpython-39.pyc index 027b10be..eb8a59b0 100644 Binary files a/hub/imports/geometry/__pycache__/citygml.cpython-39.pyc and b/hub/imports/geometry/__pycache__/citygml.cpython-39.pyc differ diff --git a/hub/imports/geometry/__pycache__/geojson.cpython-39.pyc b/hub/imports/geometry/__pycache__/geojson.cpython-39.pyc index 8010f6fa..fecd484e 100644 Binary files a/hub/imports/geometry/__pycache__/geojson.cpython-39.pyc and b/hub/imports/geometry/__pycache__/geojson.cpython-39.pyc differ diff --git a/hub/imports/geometry/citygml_classes/__pycache__/citygml_lod2.cpython-39.pyc b/hub/imports/geometry/citygml_classes/__pycache__/citygml_lod2.cpython-39.pyc index 1d503b9c..cb0038c4 100644 Binary files a/hub/imports/geometry/citygml_classes/__pycache__/citygml_lod2.cpython-39.pyc and b/hub/imports/geometry/citygml_classes/__pycache__/citygml_lod2.cpython-39.pyc differ diff --git a/hub/imports/results/__pycache__/energy_plus_single_building.cpython-39.pyc b/hub/imports/results/__pycache__/energy_plus_single_building.cpython-39.pyc index afb0019d..2e825741 100644 Binary files a/hub/imports/results/__pycache__/energy_plus_single_building.cpython-39.pyc and b/hub/imports/results/__pycache__/energy_plus_single_building.cpython-39.pyc differ diff --git a/hub/imports/results/__pycache__/ep_multiple_buildings.cpython-39.pyc b/hub/imports/results/__pycache__/ep_multiple_buildings.cpython-39.pyc index f39e2667..941073e5 100644 Binary files a/hub/imports/results/__pycache__/ep_multiple_buildings.cpython-39.pyc and b/hub/imports/results/__pycache__/ep_multiple_buildings.cpython-39.pyc differ diff --git a/hub/imports/results/__pycache__/insel_monthly_energry_balance.cpython-39.pyc b/hub/imports/results/__pycache__/insel_monthly_energry_balance.cpython-39.pyc index 790ad3be..96200b03 100644 Binary files a/hub/imports/results/__pycache__/insel_monthly_energry_balance.cpython-39.pyc and b/hub/imports/results/__pycache__/insel_monthly_energry_balance.cpython-39.pyc differ diff --git a/hub/imports/weather/helpers/__pycache__/weather.cpython-39.pyc b/hub/imports/weather/helpers/__pycache__/weather.cpython-39.pyc index 989715d0..53a78479 100644 Binary files a/hub/imports/weather/helpers/__pycache__/weather.cpython-39.pyc and b/hub/imports/weather/helpers/__pycache__/weather.cpython-39.pyc differ diff --git a/tests/test_costs_catalog.py b/tests/test_costs_catalog.py index 8f873850..27b88264 100644 --- a/tests/test_costs_catalog.py +++ b/tests/test_costs_catalog.py @@ -26,3 +26,22 @@ class TestCostsCatalog(TestCase): with self.assertRaises(IndexError): catalog.get_entry('unknown') + print(catalog.entries()) + + def test_new_costs_catalog(self): + catalog = CostsCatalogFactory('montreal_complete').catalog_debug + catalog_categories = catalog.names() + self.assertIsNotNone(catalog, 'catalog is none') + content = catalog.entries() + self.assertTrue(len(content.archetypes) == 2) + + # retrieving all the entries should not raise any exceptions + for category in catalog_categories: + for value in catalog_categories[category]: + catalog.get_entry(value) + + with self.assertRaises(IndexError): + catalog.get_entry('unknown') + print(catalog.entries()) + +