From 16269297b48583141dbc277be1087fc40d737832 Mon Sep 17 00:00:00 2001 From: louispt1 Date: Wed, 23 Jul 2025 16:28:09 +0200 Subject: [PATCH 01/19] Cleaning up tests and adjusting them based on new implementation of serialization --- tests/models/test_inputs.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tests/models/test_inputs.py b/tests/models/test_inputs.py index cb3af91..2875047 100644 --- a/tests/models/test_inputs.py +++ b/tests/models/test_inputs.py @@ -27,6 +27,7 @@ def test_to_dataframe(inputs_json): assert df_with_non_existing["foo"].isnull().all() + def test_valid_update(inputs_json): input_collection = Inputs.from_json(inputs_json) @@ -38,7 +39,9 @@ def test_valid_update(inputs_json): warnings = input_collection.is_valid_update({"investment_costs_co2_ccs": "hello"}) assert len(warnings) > 0 assert "investment_costs_co2_ccs" in warnings - assert warnings["investment_costs_co2_ccs"]["user"] == ["Input should be a valid number, unable to parse string as a number"] + assert warnings["investment_costs_co2_ccs"]["user"] == [ + "Input should be a valid number, unable to parse string as a number" + ] # An update of a non existent key warnings = input_collection.is_valid_update({"hello": "hello"}) From 4c341f3a1164552fa4c45be12852b4a90a541d28 Mon Sep 17 00:00:00 2001 From: Nora Schinkel Date: Fri, 25 Jul 2025 17:05:12 +0200 Subject: [PATCH 02/19] Setting inputs form dict and from df --- src/pyetm/models/inputs.py | 22 +++++++++++++--------- src/pyetm/models/scenario.py | 16 +++++++--------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/src/pyetm/models/inputs.py b/src/pyetm/models/inputs.py index 33dde63..8fa5737 100644 --- a/src/pyetm/models/inputs.py +++ b/src/pyetm/models/inputs.py @@ -85,6 +85,9 @@ def is_bool_float(cls, value: float) -> float: f"{value} should be 1.0 or 0.0 representing True/False, or On/Off" ) + # NOTE: I need a lot of validation, and I need my own update method that + # will cast true/false into 1.0 and 0.0 + class EnumInput(Input): """Input representing an enumeration""" @@ -106,12 +109,13 @@ def check_permitted(self) -> EnumInput: if self.user is None or self.user in self.permitted_values: return self self._raise_exception_on_loc( - 'ValueError', - type='inclusion', - loc='user', - msg=f"Value error, {self.user} should be in {self.permitted_values}" + "ValueError", + type="inclusion", + loc="user", + msg=f"Value error, {self.user} should be in {self.permitted_values}", ) + class FloatInput(Input): """Input representing a float""" @@ -138,10 +142,10 @@ def check_min_max(self) -> FloatInput: if self.user is None or (self.user <= self.max and self.user >= self.min): return self self._raise_exception_on_loc( - 'ValueError', - type='out_of_bounds', - loc='user', - msg=f"Value error, {self.user} should be between {self.min} and {self.max}" + "ValueError", + type="out_of_bounds", + loc="user", + msg=f"Value error, {self.user} should be between {self.min} and {self.max}", ) @@ -207,6 +211,6 @@ def from_json(cls, data) -> Inputs: inputs = [Input.from_json(item) for item in data.items()] collection = cls.model_validate({"inputs": inputs}) - collection._merge_submodel_warnings(*inputs, key_attr='key') + collection._merge_submodel_warnings(*inputs, key_attr="key") return collection diff --git a/src/pyetm/models/scenario.py b/src/pyetm/models/scenario.py index 879ad89..9da114a 100644 --- a/src/pyetm/models/scenario.py +++ b/src/pyetm/models/scenario.py @@ -71,7 +71,7 @@ def new(cls, area_code: str, end_year: int, **kwargs) -> "Scenario": # parse into a Scenario scenario = cls.model_validate(result.data) for warning in result.errors: - scenario.add_warning('base', warning) + scenario.add_warning("base", warning) return scenario @@ -91,7 +91,7 @@ def load(cls, scenario_id: int) -> Scenario: # parse into a Scenario scenario = cls.model_validate(result.data) for w in result.errors: - scenario.add_warning('metadata', w) + scenario.add_warning("metadata", w) return scenario def update_metadata(self, **kwargs) -> Dict[str, Any]: @@ -105,7 +105,7 @@ def update_metadata(self, **kwargs) -> Dict[str, Any]: # Add any warnings from the update for w in result.errors: - self.add_warning('metadata', w) + self.add_warning("metadata", w) # Update the current scenario object with the server response if result.data and "scenario" in result.data: @@ -163,7 +163,7 @@ def inputs(self) -> Inputs: coll = Inputs.from_json(result.data) # merge runner warnings and any item‐level warnings for w in result.errors: - self.add_warning('inputs', w) + self.add_warning("inputs", w) self._merge_submodel_warnings(coll) self._inputs = coll @@ -175,7 +175,7 @@ def set_user_values_from_dataframe(self, dataframe: pd.DataFrame) -> None: This ensures the dataframe exactly represents the inputs. """ self.update_user_values( - dataframe['user'].droplevel('unit').fillna("reset").to_dict() + dataframe["user"].droplevel("unit").fillna("reset").to_dict() ) def update_user_values(self, update_inputs: Dict[str, Any]) -> None: @@ -195,7 +195,6 @@ def update_user_values(self, update_inputs: Dict[str, Any]) -> None: self.inputs.update(update_inputs) - def remove_user_values(self, input_keys: Union[List[str], Set[str]]) -> None: """ Remove user values for specified inputs, resetting them to default values. @@ -212,7 +211,6 @@ def remove_user_values(self, input_keys: Union[List[str], Set[str]]) -> None: # Update them in the Inputs object self.inputs.update(reset_inputs) - @property def sortables(self) -> Sortables: if self._sortables is not None: @@ -224,7 +222,7 @@ def sortables(self) -> Sortables: coll = Sortables.from_json(result.data) for w in result.errors: - self.add_warning('sortables', w) + self.add_warning("sortables", w) self._merge_submodel_warnings(coll) self._sortables = coll @@ -241,7 +239,7 @@ def custom_curves(self) -> CustomCurves: coll = CustomCurves.from_json(result.data) for w in result.errors: - self.add_warning('custom_curves', w) + self.add_warning("custom_curves", w) self._merge_submodel_warnings(coll) self._custom_curves = coll From fdfca9c862e646cd135ed2cf7e2d1ff1c72a8d28 Mon Sep 17 00:00:00 2001 From: louispt1 Date: Wed, 30 Jul 2025 10:35:21 +0200 Subject: [PATCH 03/19] First implementation of sortables, update controller and scenario methods --- src/pyetm/models/scenario.py | 85 ++++++++++ src/pyetm/models/sortables.py | 145 +++++++++++++++++- .../scenario_runners/update_sortables.py | 47 ++++++ 3 files changed, 276 insertions(+), 1 deletion(-) create mode 100644 src/pyetm/services/scenario_runners/update_sortables.py diff --git a/src/pyetm/models/scenario.py b/src/pyetm/models/scenario.py index 9da114a..4dbcf3e 100644 --- a/src/pyetm/models/scenario.py +++ b/src/pyetm/models/scenario.py @@ -18,6 +18,7 @@ FetchAllCustomCurveDataRunner, ) from pyetm.services.scenario_runners.update_inputs import UpdateInputsRunner +from pyetm.services.scenario_runners.update_sortables import UpdateSortablesRunner from pyetm.services.scenario_runners.create_scenario import CreateScenarioRunner from pyetm.services.scenario_runners.update_metadata import UpdateMetadataRunner @@ -228,6 +229,90 @@ def sortables(self) -> Sortables: self._sortables = coll return coll + def sortable_values(self) -> Dict[str, List[Any]]: + """ + Returns the current orders for all sortables + """ + return {sortable.name(): sortable.order for sortable in self.sortables} + + def set_sortables_from_dataframe(self, dataframe: pd.DataFrame) -> None: + """ + Extract sortables from dataframe and update them. + The dataframe should have sortable names as columns and orders as rows. + + Args: + dataframe: DataFrame with sortable names as columns and order values as rows + """ + # Convert DataFrame to dict of lists, handling NaN/None values + sortables_dict = {} + for column in dataframe.columns: + # Filter out NaN/None values and convert to list + order_values = dataframe[column].dropna().tolist() + if order_values: # Only include if there are actual values + sortables_dict[column] = order_values + + self.update_sortables(sortables_dict) + + def update_sortables(self, update_sortables: Dict[str, List[Any]]) -> None: + """ + Update the order of specified sortables. + + Args: + update_sortables: Dictionary mapping sortable names to their new orders + """ + # Validate the updates first + validity_errors = self.sortables.is_valid_update(update_sortables) + if validity_errors: + raise ScenarioError(f"Could not update sortables: {validity_errors}") + + # Make individual API calls for each sortable + for name, order in update_sortables.items(): + if name.startswith("heat_network_"): + # Handle heat_network with subtype + subtype = name.replace("heat_network_", "") + result = UpdateSortablesRunner.run( + BaseClient(), self, "heat_network", order, subtype=subtype + ) + else: + # Handle simple sortables + result = UpdateSortablesRunner.run(BaseClient(), self, name, order) + + if not result.success: + raise ScenarioError( + f"Could not update sortable '{name}': {result.errors}" + ) + + # Update the local sortables object + self.sortables.update(update_sortables) + + def remove_sortables(self, sortable_names: Union[List[str], Set[str]]) -> None: + """ + Reset specified sortables to their default/empty orders. + + Args: + sortable_names: List or set of sortable names to reset + """ + # Make individual API calls to reset each sortable + for name in sortable_names: + if name.startswith("heat_network_"): + # Handle heat_network with subtype + subtype = name.replace("heat_network_", "") + result = UpdateSortablesRunner.run( + BaseClient(), self, "heat_network", [], subtype=subtype + ) + else: + # Handle simple sortables + result = UpdateSortablesRunner.run(BaseClient(), self, name, []) + + if not result.success: + raise ScenarioError( + f"Could not remove sortable '{name}': {result.errors}" + ) + + # Update the local sortables object + reset_sortables = {name: [] for name in sortable_names} + self.sortables.update(reset_sortables) + @property def custom_curves(self) -> CustomCurves: if self._custom_curves is not None: diff --git a/src/pyetm/models/sortables.py b/src/pyetm/models/sortables.py index ecc9225..e26f08e 100644 --- a/src/pyetm/models/sortables.py +++ b/src/pyetm/models/sortables.py @@ -2,6 +2,7 @@ from typing import Any, Dict, Iterator, List, Optional, Tuple, Union import pandas as pd +from pydantic import field_validator, model_validator from pyetm.models.base import Base @@ -30,6 +31,66 @@ def name(self): else: return self.type + def is_valid_update(self, new_order: list[Any]) -> list[str]: + """ + Returns a list of validation warnings without updating the current object + """ + new_obj_dict = self.model_dump() + new_obj_dict["order"] = new_order + + warnings_obj = self.__class__(**new_obj_dict) + return warnings_obj.warnings + + @field_validator("type") + @classmethod + def validate_type(cls, value: str) -> str: + """Validate that type is a non-empty string""" + if not isinstance(value, str) or not value.strip(): + raise ValueError("Type must be a non-empty string") + return value.strip() + + @field_validator("subtype") + @classmethod + def validate_subtype(cls, value: Optional[str]) -> Optional[str]: + """Validate subtype if provided""" + if value is not None: + if not isinstance(value, str) or not value.strip(): + raise ValueError("Subtype must be a non-empty string or None") + return value.strip() + return value + + @field_validator("order") + @classmethod + def validate_order(cls, value: list[Any]) -> list[Any]: + """Validate that order is a list and check for duplicates""" + if not isinstance(value, list): + raise ValueError("Order must be a list") + + # Check for duplicates + seen = set() + duplicates = [] + for item in value: + if item in seen: + duplicates.append(item) + seen.add(item) + + if duplicates: + raise ValueError(f"Order contains duplicate items: {duplicates}") + + return value + + @model_validator(mode="after") + def validate_sortable_consistency(self) -> "Sortable": + """Additional validation for the entire sortable""" + if self.type == "heat_network" and self.subtype is None: + raise ValueError("heat_network type requires a subtype") + + # TODO: check how long these actually ought to be + if len(self.order) > 10: + raise ValueError("Order cannot contain more than 10 items") + + return self + @classmethod def from_json( cls, data: Tuple[str, Union[list[Any], Dict[str, list[Any]]]] @@ -93,6 +154,85 @@ def keys(self) -> List[str]: # will repeat 'heat_network' for each subtype return [s.type for s in self.sortables] + def names(self) -> List[str]: + """Get all sortable names (including subtype suffixes)""" + return [s.name() for s in self.sortables] + + def is_valid_update(self, updates: Dict[str, list[Any]]) -> Dict[str, list[str]]: + """ + Returns a dict of sortable names and their validation warnings + + :param updates: Dict mapping sortable names to new orders + :return: Dict mapping sortable names to list of validation warnings + """ + warnings = {} + + # Check each sortable that has an update + sortable_by_name = {s.name(): s for s in self.sortables} + + for name, new_order in updates.items(): + if name in sortable_by_name: + sortable = sortable_by_name[name] + sortable_warnings = sortable.is_valid_update(new_order) + if sortable_warnings: + warnings[name] = sortable_warnings + else: + warnings[name] = ["Sortable does not exist"] + + # Check for non-existent sortables + non_existent_names = set(updates.keys()) - set(self.names()) + for name in non_existent_names: + if name not in warnings: + warnings[name] = [f"Sortable {name} does not exist"] + + return warnings + + def update(self, updates: Dict[str, list[Any]]): + """ + Update the orders of specified sortables + + :param updates: Dict mapping sortable names to new orders + """ + sortable_by_name = {s.name(): s for s in self.sortables} + + for name, new_order in updates.items(): + if name in sortable_by_name: + sortable_by_name[name].order = new_order + + @field_validator("sortables") + @classmethod + def validate_sortables_list(cls, value: List[Sortable]) -> List[Sortable]: + """Validate the list of sortables""" + if not isinstance(value, list): + raise ValueError("Sortables must be a list") + + # Check for duplicate names + names = [s.name() for s in value if isinstance(s, Sortable)] + duplicates = [] + seen = set() + for name in names: + if name in seen: + duplicates.append(name) + seen.add(name) + + if duplicates: + raise ValueError(f"Duplicate sortable names found: {duplicates}") + + return value + + @model_validator(mode="after") + def validate_sortables_consistency(self) -> "Sortables": + """Additional validation for the entire sortables collection""" + # Example: Ensure we don't have conflicting heat_network configurations + heat_network_types = [s for s in self.sortables if s.type == "heat_network"] + if len(heat_network_types) > 0: + # All heat_network sortables should have subtypes + without_subtypes = [s for s in heat_network_types if s.subtype is None] + if without_subtypes: + raise ValueError("All heat_network sortables must have subtypes") + + return self + @classmethod def from_json(cls, data: Dict[str, Any]) -> "Sortables": """ @@ -125,7 +265,10 @@ def as_dict(self) -> Dict[str, Any]: result[s.type] = s.order return result - def to_dataframe(self) -> pd.DataFrame: + def _to_dataframe(self, **kwargs) -> pd.DataFrame: + """ + Serialize the Sortables collection to DataFrame. + """ return pd.DataFrame.from_dict( {s.name(): s.order for s in self.sortables}, orient="index" ).T diff --git a/src/pyetm/services/scenario_runners/update_sortables.py b/src/pyetm/services/scenario_runners/update_sortables.py new file mode 100644 index 0000000..59679b4 --- /dev/null +++ b/src/pyetm/services/scenario_runners/update_sortables.py @@ -0,0 +1,47 @@ +from typing import Any, Dict, List +from pyetm.services.scenario_runners.base_runner import BaseRunner +from ..service_result import ServiceResult +from pyetm.clients.base_client import BaseClient + + +class UpdateSortablesRunner(BaseRunner[Dict[str, Any]]): + """ + Runner for updating a single user sortable on a scenario. + + PUT /api/v3/scenarios/{scenario_id}/user_sortables/{sortable_type} + PUT /api/v3/scenarios/{scenario_id}/user_sortables/{sortable_type}?subtype={subtype} + + Args: + client: The HTTP client to use + scenario: The scenario object (must have an 'id' attribute) + sortable_type: The type of sortable (e.g., "demand", "heat_network") + order: The new order for the sortable + subtype: Optional subtype for heat_network (e.g., "lt", "mt", "ht") + **kwargs: Additional arguments passed to the request + """ + + @staticmethod + def run( + client: BaseClient, + scenario: Any, + sortable_type: str, + order: List[Any], + subtype: str = None, + **kwargs, + ) -> ServiceResult[Dict[str, Any]]: + """ + Update a single sortable for a scenario - the endpoint doesn't handle bulk updates. + + """ + path = f"/scenarios/{scenario.id}/user_sortables/{sortable_type}" + if subtype: + path += f"?subtype={subtype}" + + payload = {"order": order} + + return UpdateSortablesRunner._make_request( + client=client, + method="put", + path=path, + payload=payload, + ) From e4c31981393dcb476454ab2d4f69802770e93ef5 Mon Sep 17 00:00:00 2001 From: louispt1 Date: Wed, 30 Jul 2025 12:06:29 +0200 Subject: [PATCH 04/19] sortables update, validation and tests implemented --- src/pyetm/models/base.py | 15 +++-- src/pyetm/models/scenario.py | 13 +--- src/pyetm/models/sortables.py | 49 +++++--------- tests/models/conftest.py | 22 +++++++ tests/models/test_scenario.py | 71 +++++++++++++++++++- tests/models/test_sortable.py | 116 +++++++++++++++++++++++++++++++-- tests/models/test_sortables.py | 103 ++++++++++++++++++++++++++--- 7 files changed, 324 insertions(+), 65 deletions(-) diff --git a/src/pyetm/models/base.py b/src/pyetm/models/base.py index 335a47f..df6f045 100644 --- a/src/pyetm/models/base.py +++ b/src/pyetm/models/base.py @@ -43,14 +43,14 @@ def __init__(self, **data: Any) -> None: self.add_warning(loc, msg) def __setattr__(self, name: str, value: Any) -> None: - """ Abuses the fact that init does not return on valdiation errors""" + """Abuses the fact that init does not return on valdiation errors""" # Intercept assignment-time validation errors if name in self.__class__.model_fields: try: self._clear_warnings_for_attr(name) current_data = self.model_dump() current_data[name] = value - obj =self.__class__.model_validate(current_data) + obj = self.__class__.model_validate(current_data) if name in obj.warnings: self.add_warning(name, obj.warnings[name]) # Do not assign invalid value @@ -73,7 +73,7 @@ def add_warning(self, key: str, message: str) -> None: if isinstance(message, dict): self._warnings[key].update(message) else: - self._warnings[key].update({'base', message}) + self._warnings[key].update({"base", message}) elif isinstance(message, list): self._warnings[key].extend(message) else: @@ -114,11 +114,12 @@ def _merge_submodel_warnings(self, *submodels: Base, key_attr=None) -> None: from typing import Iterable def _collect(wm: Base): - if not wm.warnings: return + if not wm.warnings: + return key = wm.__class__.__name__ if not key_attr is None: - key += f'({key_attr}={getattr(wm, key_attr)})' + key += f"({key_attr}={getattr(wm, key_attr)})" self.add_warning(key, wm.warnings) for item in submodels: @@ -191,7 +192,9 @@ def to_dataframe(self, **kwargs) -> pd.DataFrame: if not isinstance(df, pd.DataFrame): raise ValueError(f"Expected DataFrame, got {type(df)}") except Exception as e: - self.add_warning(f"{self.__class__.__name__}._to_dataframe()", f"failed: {e}") + self.add_warning( + f"{self.__class__.__name__}._to_dataframe()", f"failed: {e}" + ) df = pd.DataFrame() # Set index name if not already set diff --git a/src/pyetm/models/scenario.py b/src/pyetm/models/scenario.py index 4dbcf3e..47c09db 100644 --- a/src/pyetm/models/scenario.py +++ b/src/pyetm/models/scenario.py @@ -229,12 +229,6 @@ def sortables(self) -> Sortables: self._sortables = coll return coll - def sortable_values(self) -> Dict[str, List[Any]]: - """ - Returns the current orders for all sortables - """ - return {sortable.name(): sortable.order for sortable in self.sortables} - def set_sortables_from_dataframe(self, dataframe: pd.DataFrame) -> None: """ Extract sortables from dataframe and update them. @@ -265,16 +259,14 @@ def update_sortables(self, update_sortables: Dict[str, List[Any]]) -> None: if validity_errors: raise ScenarioError(f"Could not update sortables: {validity_errors}") - # Make individual API calls for each sortable + # Make individual API calls for each sortable as there is no bulk endpoint for name, order in update_sortables.items(): if name.startswith("heat_network_"): - # Handle heat_network with subtype subtype = name.replace("heat_network_", "") result = UpdateSortablesRunner.run( BaseClient(), self, "heat_network", order, subtype=subtype ) else: - # Handle simple sortables result = UpdateSortablesRunner.run(BaseClient(), self, name, order) if not result.success: @@ -282,7 +274,6 @@ def update_sortables(self, update_sortables: Dict[str, List[Any]]) -> None: f"Could not update sortable '{name}': {result.errors}" ) - # Update the local sortables object self.sortables.update(update_sortables) def remove_sortables(self, sortable_names: Union[List[str], Set[str]]) -> None: @@ -301,7 +292,6 @@ def remove_sortables(self, sortable_names: Union[List[str], Set[str]]) -> None: BaseClient(), self, "heat_network", [], subtype=subtype ) else: - # Handle simple sortables result = UpdateSortablesRunner.run(BaseClient(), self, name, []) if not result.success: @@ -309,7 +299,6 @@ def remove_sortables(self, sortable_names: Union[List[str], Set[str]]) -> None: f"Could not remove sortable '{name}': {result.errors}" ) - # Update the local sortables object reset_sortables = {name: [] for name in sortable_names} self.sortables.update(reset_sortables) diff --git a/src/pyetm/models/sortables.py b/src/pyetm/models/sortables.py index e26f08e..e275df6 100644 --- a/src/pyetm/models/sortables.py +++ b/src/pyetm/models/sortables.py @@ -31,9 +31,9 @@ def name(self): else: return self.type - def is_valid_update(self, new_order: list[Any]) -> list[str]: + def is_valid_update(self, new_order: list[Any]) -> dict[str, list[str]]: """ - Returns a list of validation warnings without updating the current object + Returns a dict of validation warnings without updating the current object """ new_obj_dict = self.model_dump() new_obj_dict["order"] = new_order @@ -82,6 +82,7 @@ def validate_order(cls, value: list[Any]) -> list[Any]: @model_validator(mode="after") def validate_sortable_consistency(self) -> "Sortable": """Additional validation for the entire sortable""" + # Example: validate that certain types require subtypes if self.type == "heat_network" and self.subtype is None: raise ValueError("heat_network type requires a subtype") @@ -103,36 +104,20 @@ def from_json( sort_type, payload = data if isinstance(payload, list): - try: - sortable = cls.model_validate({"type": sort_type, "order": payload}) - yield sortable - except Exception as e: - # Create basic sortable with warning - sortable = cls.model_validate({"type": sort_type, "order": []}) - sortable.add_warning('base', f"Failed to create sortable for {sort_type}: {e}") - yield sortable + sortable = cls(type=sort_type, order=payload) + yield sortable elif isinstance(payload, dict): for sub, order in payload.items(): - try: - sortable = cls.model_validate( - {"type": sort_type, "subtype": sub, "order": order} - ) - yield sortable - except Exception as e: - # Create basic sortable with warning - sortable = cls.model_validate( - {"type": sort_type, "subtype": sub, "order": []} - ) - sortable.add_warning( - 'base', f"Failed to create sortable for {sort_type}.{sub}: {e}" - ) - yield sortable + sortable = cls(type=sort_type, subtype=sub, order=order) + yield sortable else: # Create basic sortable with warning for unexpected payload - sortable = cls.model_validate({"type": sort_type, "order": []}) - sortable.add_warning('type', f"Unexpected payload for '{sort_type}': {payload!r}") + sortable = cls(type=sort_type, order=[]) + sortable.add_warning( + "payload", f"Unexpected payload for '{sort_type}': {payload!r}" + ) yield sortable @@ -182,8 +167,8 @@ def is_valid_update(self, updates: Dict[str, list[Any]]) -> Dict[str, list[str]] # Check for non-existent sortables non_existent_names = set(updates.keys()) - set(self.names()) for name in non_existent_names: - if name not in warnings: - warnings[name] = [f"Sortable {name} does not exist"] + if name not in warnings: # Don't overwrite existing warnings + warnings[name] = ["Sortable does not exist"] return warnings @@ -243,13 +228,15 @@ def from_json(cls, data: Dict[str, Any]) -> "Sortables": for pair in data.items(): items.extend(Sortable.from_json(pair)) - collection = cls.model_validate({"sortables": items}) + # Use Base class constructor that handles validation gracefully + collection = cls(sortables=items) # Merge any warnings from individual sortables for sortable in items: if hasattr(sortable, "warnings") and sortable.warnings: - for warning in sortable.warnings: - collection.add_warning(warning) + for warning_key, warning_list in sortable.warnings.items(): + for warning in warning_list: + collection.add_warning(f"Sortable.{warning_key}", warning) return collection diff --git a/tests/models/conftest.py b/tests/models/conftest.py index 7149d98..abdc464 100644 --- a/tests/models/conftest.py +++ b/tests/models/conftest.py @@ -10,6 +10,7 @@ import pytest from datetime import datetime from pathlib import Path +from pyetm.models.sortables import Sortables from pyetm.models.scenario import Scenario @@ -154,6 +155,13 @@ def multiple_scenarios(): return scenarios +@pytest.fixture(autouse=True) +def patch_sortables_from_json(monkeypatch): + dummy = object() + monkeypatch.setattr(Sortables, "from_json", staticmethod(lambda data: dummy)) + return dummy + + # --- Input Fixtures --- # @@ -244,6 +252,20 @@ def sortable_collection_json(): } +@pytest.fixture +def valid_sortable_collection_json(): + """Fixture with valid data that won't trigger validation warnings""" + return { + "forecast_storage": ["fs1", "fs2"], + "heat_network": { + "lt": ["hn1", "hn2"], + "mt": ["hn3"], + "ht": ["hn4", "hn5", "hn6"], + }, + "hydrogen_supply": ["hs1", "hs2", "hs3"], + } + + # --- Curve Fixtures --- # diff --git a/tests/models/test_scenario.py b/tests/models/test_scenario.py index e72607b..cd54a63 100644 --- a/tests/models/test_scenario.py +++ b/tests/models/test_scenario.py @@ -1,3 +1,4 @@ +from unittest.mock import Mock import pytest from pyetm.clients.base_client import BaseClient from pyetm.models.inputs import Inputs @@ -13,6 +14,7 @@ from pyetm.services.scenario_runners.create_scenario import CreateScenarioRunner from pyetm.services.scenario_runners.update_metadata import UpdateMetadataRunner from pyetm.services.scenario_runners.update_inputs import UpdateInputsRunner +from pyetm.services.scenario_runners.update_sortables import UpdateSortablesRunner # ------ New scenario ------ # @@ -486,7 +488,7 @@ def test_sortables_with_warnings( coll = scenario.sortables assert coll is patch_sortables_from_json - assert scenario.warnings["sortables"] == warns + assert len(scenario.warnings) > 0 def test_sortables_failure(monkeypatch, scenario, fail_service_result): @@ -500,6 +502,73 @@ def test_sortables_failure(monkeypatch, scenario, fail_service_result): _ = scenario.sortables +def test_set_sortables_from_dataframe(monkeypatch, scenario): + import pandas as pd + + df = pd.DataFrame({"forecast_storage": [1, 2, 3], "heat_network_lt": [4, 5, None]}) + + update_calls = [] + + def mock_update_sortables(self, updates): + update_calls.append(updates) + + monkeypatch.setattr(scenario.__class__, "update_sortables", mock_update_sortables) + + scenario.set_sortables_from_dataframe(df) + + expected = { + "forecast_storage": [1, 2, 3], + "heat_network_lt": [4, 5], + } + assert update_calls[0] == expected + + +def test_update_sortables(monkeypatch, scenario, ok_service_result): + updates = {"forecast_storage": [1, 2, 3]} + + mock_sortables = Mock() + mock_sortables.is_valid_update.return_value = {} + mock_sortables.update = Mock() + scenario._sortables = mock_sortables + + monkeypatch.setattr( + UpdateSortablesRunner, "run", lambda *args, **kwargs: ok_service_result({}) + ) + + scenario.update_sortables(updates) + + mock_sortables.is_valid_update.assert_called_once_with(updates) + mock_sortables.update.assert_called_once_with(updates) + + +def test_update_sortables_validation_error(scenario): + updates = {"nonexistent": [1, 2, 3]} + + mock_sortables = Mock() + mock_sortables.is_valid_update.return_value = {"nonexistent": ["error"]} + scenario._sortables = mock_sortables + + with pytest.raises(ScenarioError): + scenario.update_sortables(updates) + + +def test_remove_sortables(monkeypatch, scenario, ok_service_result): + sortable_names = ["forecast_storage", "hydrogen_supply"] + + mock_sortables = Mock() + mock_sortables.update = Mock() + scenario._sortables = mock_sortables + + monkeypatch.setattr( + UpdateSortablesRunner, "run", lambda *args, **kwargs: ok_service_result({}) + ) + + scenario.remove_sortables(sortable_names) + + expected_updates = {"forecast_storage": [], "hydrogen_supply": []} + mock_sortables.update.assert_called_once_with(expected_updates) + + # ------ custom_curves ------ # diff --git a/tests/models/test_sortable.py b/tests/models/test_sortable.py index 184b2e2..da15c87 100644 --- a/tests/models/test_sortable.py +++ b/tests/models/test_sortable.py @@ -12,8 +12,7 @@ ["a", "b", "c"], None, ), - # flat list for heat_network treated the same - (("heat_network", ["x", "y"]), "heat_network", ["x", "y"], None), + (("hydrogen_supply", ["x", "y"]), "hydrogen_supply", ["x", "y"], None), ], ) def test_from_json_with_list(payload, expected_type, expected_order, expected_subtype): @@ -25,6 +24,26 @@ def test_from_json_with_list(payload, expected_type, expected_order, expected_su assert sortable.subtype is expected_subtype +def test_from_json_with_list_heat_network_generates_warning(): + """heat_network without subtype should generate a validation warning""" + payload = ("heat_network", ["x", "y"]) + result = list(Sortable.from_json(payload)) + + assert len(result) == 1 + sortable = result[0] + assert sortable.type == "heat_network" + assert sortable.order == ["x", "y"] + assert sortable.subtype is None # No subtype provided + + # Should have validation warning about missing subtype + assert len(sortable.warnings) > 0 + all_warnings = [] + for warning_list in sortable.warnings.values(): + all_warnings.extend(warning_list) + warning_text = " ".join(all_warnings) + assert "heat_network type requires a subtype" in warning_text + + def test_from_json_with_dict(): # nested dict → one Sortable per subtype payload = ("heat_network", {"lt": [1, 2], "mt": [3, 4], "ht": []}) @@ -40,6 +59,49 @@ def test_from_json_with_dict(): } assert got == expected + # These should not have warnings since they have proper subtypes + for sortable in result: + assert len(sortable.warnings) == 0 + + +def test_validation_duplicate_order_items(): + """Test that duplicate items in order generate warnings""" + payload = ("forecast_storage", [1, 2, 2, 3]) + result = list(Sortable.from_json(payload)) + + assert len(result) == 1 + sortable = result[0] + assert sortable.type == "forecast_storage" + assert sortable.order == [1, 2, 2, 3] + + # Should have validation warning about duplicates + assert len(sortable.warnings) > 0 + all_warnings = [] + for warning_list in sortable.warnings.values(): + all_warnings.extend(warning_list) + warning_text = " ".join(all_warnings) + assert "duplicate" in warning_text.lower() + + +def test_validation_order_too_long(): + """Test that orders with too many items generate warnings""" + long_order = list(range(15)) # More than 10 items + payload = ("forecast_storage", long_order) + result = list(Sortable.from_json(payload)) + + assert len(result) == 1 + sortable = result[0] + assert sortable.type == "forecast_storage" + assert sortable.order == long_order + + # Should have validation warning about length + assert len(sortable.warnings) > 0 + all_warnings = [] + for warning_list in sortable.warnings.values(): + all_warnings.extend(warning_list) + warning_text = " ".join(all_warnings) + assert "more than 10 items" in warning_text + @pytest.mark.parametrize( "payload", @@ -62,8 +124,50 @@ def test_from_json_creates_warning_on_invalid(payload): assert sortable.order == [] assert sortable.subtype is None - # Should have a warning about the unexpected payload assert hasattr(sortable, "warnings") - assert 'type' in sortable.warnings - assert "Unexpected payload" in sortable.warnings['type'][0] - assert str(payload[1]) in sortable.warnings['type'][0] + assert len(sortable.warnings) > 0 + all_warnings = [] + for warning_list in sortable.warnings.values(): + all_warnings.extend(warning_list) + warning_text = " ".join(all_warnings) + # Could be either unexpected payload warning or validation warning + assert ( + "Unexpected payload" in warning_text + or "heat_network type requires a subtype" in warning_text + ) + assert str(payload[1]) in warning_text + + +def test_is_valid_update(): + """Test the is_valid_update method""" + sortable = Sortable(type="forecast_storage", order=[1, 2, 3]) + + # Valid update - no warnings + warnings = sortable.is_valid_update([4, 5, 6]) + assert warnings == {} + + # Invalid update - duplicates + warnings = sortable.is_valid_update([1, 2, 2]) + assert len(warnings) > 0 + all_warnings = [] + for warning_list in warnings.values(): + all_warnings.extend(warning_list) + warning_text = " ".join(all_warnings) + assert "duplicate" in warning_text.lower() + + # Invalid update - too long + warnings = sortable.is_valid_update(list(range(15))) + assert len(warnings) > 0 + all_warnings = [] + for warning_list in warnings.values(): + all_warnings.extend(warning_list) + warning_text = " ".join(all_warnings) + assert "more than 10 items" in warning_text + + +def test_name_method(): + sortable1 = Sortable(type="forecast_storage", order=[1, 2]) + assert sortable1.name() == "forecast_storage" + + sortable2 = Sortable(type="heat_network", subtype="lt", order=[3, 4]) + assert sortable2.name() == "heat_network_lt" diff --git a/tests/models/test_sortables.py b/tests/models/test_sortables.py index b631369..13b85ae 100644 --- a/tests/models/test_sortables.py +++ b/tests/models/test_sortables.py @@ -1,9 +1,8 @@ -import pytest from pyetm.models.sortables import Sortable, Sortables -def test_collection_from_json(sortable_collection_json): - coll = Sortables.from_json(sortable_collection_json) +def test_collection_from_json(valid_sortable_collection_json): + coll = Sortables.from_json(valid_sortable_collection_json) assert coll # 1 (forecast_storage) + 3 (heat_network subtypes) + 1 (hydrogen_supply) = 5 @@ -24,14 +23,100 @@ def test_collection_from_json(sortable_collection_json): ] -def test_as_dict_roundtrip(sortable_collection_json): - coll = Sortables.from_json(sortable_collection_json) +def test_names_method(valid_sortable_collection_json): + coll = Sortables.from_json(valid_sortable_collection_json) + + names = coll.names() + expected_names = [ + "forecast_storage", + "heat_network_lt", + "heat_network_mt", + "heat_network_ht", + "hydrogen_supply", + ] + assert set(names) == set(expected_names) + + +def test_as_dict_roundtrip(valid_sortable_collection_json): + coll = Sortables.from_json(valid_sortable_collection_json) rebuilt = coll.as_dict() - assert rebuilt == sortable_collection_json + assert rebuilt == valid_sortable_collection_json + + +def test_to_dataframe(valid_sortable_collection_json): + coll = Sortables.from_json(valid_sortable_collection_json) + + df = coll._to_dataframe() + assert df["forecast_storage"][0] == "fs1" + assert df["heat_network_lt"][0] == "hn1" + + +def test_is_valid_update(): + """Test the is_valid_update method""" + coll = Sortables.from_json( + {"forecast_storage": ["a", "b"], "heat_network": {"lt": ["c", "d"]}} + ) + + # Valid updates + valid_updates = {"forecast_storage": ["x", "y"], "heat_network_lt": ["z"]} + warnings = coll.is_valid_update(valid_updates) + assert warnings == {} + + # Invalid updates - non-existent sortable + invalid_updates = {"nonexistent": ["a", "b"], "forecast_storage": ["valid"]} + warnings = coll.is_valid_update(invalid_updates) + assert "forecast_storage" not in warnings + + # Invalid updates - validation errors + invalid_order_updates = {"forecast_storage": [1, 2, 2]} + warnings = coll.is_valid_update(invalid_order_updates) + assert "forecast_storage" in warnings + assert len(warnings["forecast_storage"]) > 0 + + +def test_update_method(): + coll = Sortables.from_json( + {"forecast_storage": ["a", "b"], "heat_network": {"lt": ["c", "d"]}} + ) + + updates = {"forecast_storage": ["x", "y", "z"], "heat_network_lt": ["w"]} + coll.update(updates) + + sortable_by_name = {s.name(): s for s in coll.sortables} + assert sortable_by_name["forecast_storage"].order == ["x", "y", "z"] + assert sortable_by_name["heat_network_lt"].order == ["w"] + + +def test_validation_duplicate_sortable_names(): + sortables_list = [ + Sortable(type="forecast_storage", order=["a"]), + Sortable(type="forecast_storage", order=["b"]), # Duplicate name + ] + + # This should create warnings about duplicate names + coll = Sortables(sortables=sortables_list) + assert len(coll.warnings) > 0 + # Flatten all warning messages to search + all_warnings = [] + for warning_list in coll.warnings.values(): + all_warnings.extend(warning_list) + warning_text = " ".join(all_warnings) + assert "duplicate" in warning_text.lower() + + +def test_validation_heat_network_consistency(): + sortables_list = [ + Sortable(type="heat_network", order=["a"], subtype="lt"), # Valid + Sortable(type="heat_network", order=["b"]), # Invalid - no subtype + ] + + coll = Sortables(sortables=sortables_list) + assert len(coll.warnings) > 0 -def test_to_dataframe(sortable_collection_json): - coll = Sortables.from_json(sortable_collection_json) +def test_collection_merges_individual_warnings(): + data_with_issues = {"heat_network": ["no_subtype"]} # This will cause warnings - assert coll.to_dataframe()["forecast_storage"][0] == "fs1" + coll = Sortables.from_json(data_with_issues) + assert len(coll.warnings) > 0 From 45fc1d344be56d12a1160c31927ae7894a978397 Mon Sep 17 00:00:00 2001 From: louispt1 Date: Thu, 31 Jul 2025 11:14:12 +0200 Subject: [PATCH 05/19] Warnings implementented as separate model with repr --- src/pyetm/models/base.py | 182 ++++++++++---------- src/pyetm/models/warnings.py | 209 +++++++++++++++++++++++ tests/models/test_base.py | 299 ++++++++++++++++++++++++++++----- tests/models/test_warnings.py | 302 ++++++++++++++++++++++++++++++++++ 4 files changed, 858 insertions(+), 134 deletions(-) create mode 100644 src/pyetm/models/warnings.py create mode 100644 tests/models/test_warnings.py diff --git a/src/pyetm/models/base.py b/src/pyetm/models/base.py index df6f045..0f1d022 100644 --- a/src/pyetm/models/base.py +++ b/src/pyetm/models/base.py @@ -1,8 +1,9 @@ from __future__ import annotations -from typing import Any, Type, TypeVar +from typing import Any, Type, TypeVar, Union, List, Dict from pydantic import BaseModel, PrivateAttr, ValidationError, ConfigDict from pydantic_core import InitErrorDetails, PydanticCustomError import pandas as pd +from pyetm.models.warnings import WarningCollector T = TypeVar("T", bound="Base") @@ -10,7 +11,7 @@ class Base(BaseModel): """ Custom base model that: - - Collects non-breaking validation or runtime warnings + - Collects non-breaking validation or runtime warnings using WarningCollector - Fails fast on critical errors - Catches validation errors and converts them into warnings - Validates on assignment, converting assignment errors into warnings @@ -20,111 +21,101 @@ class Base(BaseModel): # Enable assignment validation model_config = ConfigDict(validate_assignment=True) - # Internal list of warnings (not part of serialized schema) - _warnings: dict[str, list[str]] = PrivateAttr(default_factory=dict) + _warning_collector: WarningCollector = PrivateAttr(default_factory=WarningCollector) def __init__(self, **data: Any) -> None: - # Ensure private warnings list exists before any validation - object.__setattr__(self, "_warnings", {}) + """ + Initialize the model, converting validation errors to warnings. + """ + object.__setattr__(self, "_warning_collector", WarningCollector()) + try: super().__init__(**data) except ValidationError as e: - # Construct without validation to preserve fields - inst = self.__class__.model_construct(**data) - # Copy field data - object.__setattr__(self, "__dict__", inst.__dict__.copy()) - # Ensure warnings list on this instance - if not hasattr(self, "_warnings"): - object.__setattr__(self, "_warnings", {}) - # Convert each validation error into a warning - for err in e.errors(): - loc = ".".join(str(x) for x in err.get("loc", [])) - msg = err.get("msg", "") - self.add_warning(loc, msg) + # If validation fails, create model without validation and collect warnings + # Use model_construct to bypass validation + temp_instance = self.__class__.model_construct(**data) + + # Copy the constructed data to this instance + for field_name, field_value in temp_instance.__dict__.items(): + if not field_name.startswith("_"): + object.__setattr__(self, field_name, field_value) + + # Convert validation errors to warnings + for error in e.errors(): + field_path = ".".join(str(part) for part in error.get("loc", [])) + message = error.get("msg", "Validation failed") + self._warning_collector.add(field_path, message, "error") def __setattr__(self, name: str, value: Any) -> None: - """Abuses the fact that init does not return on valdiation errors""" - # Intercept assignment-time validation errors - if name in self.__class__.model_fields: - try: - self._clear_warnings_for_attr(name) - current_data = self.model_dump() - current_data[name] = value - obj = self.__class__.model_validate(current_data) - if name in obj.warnings: - self.add_warning(name, obj.warnings[name]) - # Do not assign invalid value - return - except ValidationError as e: - for err in e.errors(): - if err.get("loc") == (name,): - msg = err.get("msg", "") - self.add_warning(name, msg) - # Do not assign invalid value - return - - super().__setattr__(name, value) - - def add_warning(self, key: str, message: str) -> None: - """Append a warning message to this model.""" - # TODO: this is horrible. we need a struct for it!! - if key in self._warnings: - if isinstance(self._warnings[key], dict): - if isinstance(message, dict): - self._warnings[key].update(message) - else: - self._warnings[key].update({"base", message}) - elif isinstance(message, list): - self._warnings[key].extend(message) - else: - self._warnings[key].append(message) - else: - # TODO: this is horrible. we need a struct for it - if isinstance(message, list) or isinstance(message, dict): - self._warnings[key] = message - else: - self._warnings[key] = [message] + """ + Handle assignment with validation error capture. + Simplified from the original complex implementation. + """ + # Skip validation for private attributes + if name.startswith("_") or name not in self.__class__.model_fields: + super().__setattr__(name, value) + return - @property - def warnings(self) -> dict[str, list[str]]: - """Return a copy of the warnings list.""" - return self._warnings + # Clear existing warnings for this field + self._warning_collector.clear(name) - def show_warnings(self) -> None: - """Print all warnings to the console.""" - if not self._warnings: - print("No warnings.") + try: + # Try to validate the new value by creating a copy with the update + current_data = self.model_dump() + current_data[name] = value + + # Test validation with a temporary instance + test_instance = self.__class__.model_validate(current_data) + + # If validation succeeds, set the value + super().__setattr__(name, value) + + except ValidationError as e: + # If validation fails, add warnings but don't set the value + for error in e.errors(): + if error.get("loc") == (name,): + message = error.get("msg", "Validation failed") + self._warning_collector.add(name, message, "warning") return - print("Warnings:") - # TODO: use prettyprint - for i, w in enumerate(self._warnings, start=1): - print(f" {i}. {w}") - def _clear_warnings_for_attr(self, key): - """ - Remove a key from the warnings. - """ - self._warnings.pop(key, None) + def add_warning( + self, + field: str, + message: Union[str, List[str], Dict[str, Any]], + severity: str = "warning", + ) -> None: + """Add a warning to this model instance.""" + self._warning_collector.add(field, message, severity) - def _merge_submodel_warnings(self, *submodels: Base, key_attr=None) -> None: + @property + def warnings(self) -> Union[WarningCollector, Dict[str, List[str]]]: """ - Bring warnings from a nested Base (or list thereof) - into this model's warnings list. + Return warnings. + + For backward compatibility, this can return either the new WarningCollector + or the legacy dict format. The implementation can be switched based on needs. """ - from typing import Iterable + # Return the new collector (recommended) + return self._warning_collector + + # OR return legacy format for backward compatibility: + # return self._warning_collector.to_legacy_dict() - def _collect(wm: Base): - if not wm.warnings: - return + def show_warnings(self) -> None: + """Print all warnings to the console.""" + self._warning_collector.show_warnings() - key = wm.__class__.__name__ - if not key_attr is None: - key += f"({key_attr}={getattr(wm, key_attr)})" - self.add_warning(key, wm.warnings) + def _clear_warnings_for_attr(self, field: str) -> None: + """Remove warnings for a specific field.""" + self._warning_collector.clear(field) - for item in submodels: - if isinstance(item, Base): - _collect(item) + def _merge_submodel_warnings(self, *submodels: Base, key_attr: str = None) -> None: + """ + Merge warnings from nested Base models. + Maintains compatibility with existing code while using the new system. + """ + self._warning_collector.merge_submodel_warnings(*submodels, key_attr=key_attr) @classmethod def load_safe(cls: Type[T], **data: Any) -> T: @@ -134,7 +125,7 @@ def load_safe(cls: Type[T], **data: Any) -> T: """ return cls(**data) - def _get_serializable_fields(self) -> list[str]: + def _get_serializable_fields(self) -> List[str]: """ Parse and return column names for serialization. Override this method in subclasses if you need custom field selection logic. @@ -147,17 +138,14 @@ def _get_serializable_fields(self) -> list[str]: def _raise_exception_on_loc(self, err: str, type: str, loc: str, msg: str): """ - Nice and convoluted way to raise validation errors on custom locs. - Used in model validators + Raise validation errors on custom locations. + Used in model validators. """ raise ValidationError.from_exception_data( err, [ InitErrorDetails( - type=PydanticCustomError( - type, - msg, - ), + type=PydanticCustomError(type, msg), loc=(loc,), input=self, ), diff --git a/src/pyetm/models/warnings.py b/src/pyetm/models/warnings.py new file mode 100644 index 0000000..52a3d19 --- /dev/null +++ b/src/pyetm/models/warnings.py @@ -0,0 +1,209 @@ +from __future__ import annotations +from typing import Any, Optional, Dict, List, Union, Literal +from dataclasses import dataclass, field +from datetime import datetime + + +@dataclass +class ModelWarning: + """Individual warning with context and metadata.""" + + field: str + message: str + severity: Literal["info", "warning", "error"] = "warning" + timestamp: datetime = field(default_factory=datetime.now) + + def __str__(self) -> str: + return f"{self.field}: {self.message}" + + def __repr__(self) -> str: + return f"ModelWarning(field='{self.field}', message='{self.message}', severity='{self.severity}')" + + def to_dict(self) -> Dict[str, Any]: + """Convert to dictionary for serialization.""" + return { + "field": self.field, + "message": self.message, + "severity": self.severity, + "timestamp": self.timestamp.isoformat(), + } + + +class WarningCollector: + """Manages warnings for a model instance with a clean API.""" + + def __init__(self): + self._warnings: List[ModelWarning] = [] + + def add( + self, + field: str, + message: Union[str, List[str], Dict[str, Any]], + severity: str = "warning", + ) -> None: + """ + Add warning(s) to the collection. + + Handles the complex legacy patterns from the original system: + - Single string messages + - Lists of messages + - Nested dictionaries of warnings + """ + if isinstance(message, str): + self._warnings.append(ModelWarning(field, message, severity)) + + elif isinstance(message, list): + for msg in message: + if isinstance(msg, str): + self._warnings.append(ModelWarning(field, msg, severity)) + else: + # Handle nested structures + self._warnings.append(ModelWarning(field, str(msg), severity)) + + elif isinstance(message, dict): + # Handle nested warning dictionaries (like from submodels) + for sub_field, sub_messages in message.items(): + nested_field = f"{field}.{sub_field}" + self.add(nested_field, sub_messages, severity) + else: + # Fallback for any other type + self._warnings.append(ModelWarning(field, str(message), severity)) + + def clear(self, field: Optional[str] = None) -> None: + """Clear warnings. If field is specified, clear only that field.""" + if field is None: + self._warnings.clear() + else: + self._warnings = [w for w in self._warnings if w.field != field] + + def get_by_field(self, field: str) -> List[ModelWarning]: + """Get all warnings for a specific field.""" + return [w for w in self._warnings if w.field == field] + + def has_warnings(self, field: Optional[str] = None) -> bool: + """Check if warnings exist. If field specified, check only that field.""" + if field is None: + return len(self._warnings) > 0 + return any(w.field == field for w in self._warnings) + + def get_fields_with_warnings(self) -> List[str]: + """Get list of all fields that have warnings.""" + return list(set(w.field for w in self._warnings)) + + def to_dict(self) -> Dict[str, List[Dict[str, Any]]]: + """Convert to dictionary grouped by field.""" + result = {} + for warning in self._warnings: + if warning.field not in result: + result[warning.field] = [] + result[warning.field].append(warning.to_dict()) + return result + + def to_legacy_dict(self) -> Dict[str, List[str]]: + """ + Convert to the old warning format for backward compatibility. + Groups warnings by field and returns just the messages. + """ + result = {} + for warning in self._warnings: + if warning.field not in result: + result[warning.field] = [] + result[warning.field].append(warning.message) + return result + + def merge_from(self, other: "WarningCollector", prefix: str = "") -> None: + """ + Merge warnings from another collector, optionally with a field prefix. + This replaces the complex _merge_submodel_warnings logic. + """ + for warning in other._warnings: + field = f"{prefix}.{warning.field}" if prefix else warning.field + self._warnings.append( + ModelWarning( + field=field, + message=warning.message, + severity=warning.severity, + timestamp=warning.timestamp, + ) + ) + + def merge_submodel_warnings( + self, *submodels, key_attr: Optional[str] = None + ) -> None: + """ + Merge warnings from Base model instances. + Maintains compatibility with the original _merge_submodel_warnings method. + """ + for submodel in submodels: + if hasattr(submodel, "_warning_collector"): + # Determine prefix for nested warnings + prefix = submodel.__class__.__name__ + if key_attr and hasattr(submodel, key_attr): + key_value = getattr(submodel, key_attr) + prefix = f"{prefix}({key_attr}={key_value})" + + self.merge_from(submodel._warning_collector, prefix) + + def show_warnings(self) -> None: + """Print all warnings to console in a readable format.""" + if not self._warnings: + print("No warnings.") + return + + print("Warnings:") + grouped = {} + for warning in self._warnings: + if warning.field not in grouped: + grouped[warning.field] = [] + grouped[warning.field].append(warning) + + for field, warnings in grouped.items(): + print(f" {field}:") + for warning in warnings: + severity_indicator = ( + "[WARNING]" + if warning.severity == "warning" + else "[ERROR]" if warning.severity == "error" else "[INFO]" + ) + print(f" {severity_indicator} {warning.message}") + + def __len__(self) -> int: + """Return number of warnings.""" + return len(self._warnings) + + def __bool__(self) -> bool: + """Return True if there are warnings.""" + return len(self._warnings) > 0 + + def __iter__(self): + """Iterate over warnings.""" + return iter(self._warnings) + + def __repr__(self) -> str: + """Nice string representation showing warning summary.""" + if not self._warnings: + return "WarningCollector(no warnings)" + + # Group by field for summary + field_counts = {} + severity_counts = {"error": 0, "warning": 0, "info": 0} + + for warning in self._warnings: + field_counts[warning.field] = field_counts.get(warning.field, 0) + 1 + severity_counts[warning.severity] += 1 + + # Build summary string + total = len(self._warnings) + severity_parts = [] + for sev, count in severity_counts.items(): + if count > 0: + severity_parts.append(f"{count} {sev}") + + severity_str = ", ".join(severity_parts) + field_summary = ( + f"{len(field_counts)} fields" if len(field_counts) != 1 else "1 field" + ) + + return ( + f"WarningCollector({total} warnings: {severity_str} across {field_summary})" + ) diff --git a/tests/models/test_base.py b/tests/models/test_base.py index 06a6545..deebc14 100644 --- a/tests/models/test_base.py +++ b/tests/models/test_base.py @@ -2,99 +2,324 @@ def test_valid_initialization_has_no_warnings(dummy_base_model): + """Test that valid initialization produces no warnings.""" d = dummy_base_model(a=10, b="string", c=3.14) + assert d.a == 10 assert d.b == "string" assert d.c == 3.14 - assert d.warnings == {} + assert len(d.warnings) == 0 # New: check length instead of empty dict + assert not d.warnings.has_warnings() # New: use has_warnings method def test_invalid_initialization_becomes_warning_not_exception(dummy_base_model): + """Test that invalid initialization creates warnings instead of exceptions.""" d = dummy_base_model(a="not-an-int", b="hi") + assert isinstance(d, dummy_base_model) - assert any("valid integer" in w.lower() for w_list in d.warnings.values() for w in w_list) + assert len(d.warnings) > 0 # New: check that warnings exist + + # Check warning content using new API + all_warnings = list(d.warnings) # Get all ModelWarning objects + warning_messages = [w.message.lower() for w in all_warnings] + assert any("valid integer" in msg for msg in warning_messages) def test_missing_required_field_becomes_warning(dummy_base_model): + """Test that missing required fields become warnings.""" d = dummy_base_model(a=5) + assert isinstance(d, dummy_base_model) - assert any("field required" in w.lower() for w_list in d.warnings.values() for w in w_list) + assert len(d.warnings) > 0 + + # Check for field required warning + all_warnings = list(d.warnings) + warning_messages = [w.message.lower() for w in all_warnings] + assert any("field required" in msg for msg in warning_messages) def test_assignment_validation_generates_warning_and_skips_assignment(dummy_base_model): + """Test that invalid assignments generate warnings and don't change the value.""" d = dummy_base_model(a=1, b="foo") - d.warnings.clear() + d.warnings.clear() # Clear any initialization warnings - # good assignment + # Good assignment should work d.a = 42 assert d.a == 42 - assert d.warnings == {} + assert len(d.warnings) == 0 - # bad assignment - d.b = 123 - assert d.b == "foo" + # Bad assignment should generate warning and not change value + original_b = d.b + d.b = 123 # Invalid: should be string + + assert d.b == original_b # Value should not change assert len(d.warnings) == 1 - # actual message contains "valid string" - assert any("valid string" in w.lower() for w_list in d.warnings.values() for w in w_list) + + # Check warning content + b_warnings = d.warnings.get_by_field("b") + assert len(b_warnings) > 0 + assert any("valid string" in w.message.lower() for w in b_warnings) def test_merge_submodel_warnings_brings_them_up(dummy_base_model): + """Test that submodel warnings are properly merged with key attributes.""" + class Child(Base): x: int - child = Child(x="warning") - assert child.warnings, "child should have at least one warning" + def _to_dataframe(self, **kwargs): + import pandas as pd + + return pd.DataFrame({"x": [self.x]}) + + child = Child(x="warning") # Invalid value will create warnings + assert len(child.warnings) > 0, "child should have at least one warning" parent = dummy_base_model(a=0, b="string") parent.warnings.clear() - parent._merge_submodel_warnings(child, key_attr='x') + parent._merge_submodel_warnings(child, key_attr="x") - assert parent.warnings[f'Child(x=warning)'] == child.warnings + # Check that warnings were merged with proper prefix + parent_fields = parent.warnings.get_fields_with_warnings() + assert any("Child(x=warning)" in field for field in parent_fields) + + # Check that the actual warning content is preserved + assert len(parent.warnings) > 0 def test_show_warnings_no_warnings_prints_no_warnings(capsys, dummy_base_model): + """Test show_warnings output when no warnings exist.""" d = dummy_base_model(a=3, b="string") - # ensure no warnings - d.warnings.clear() + d.warnings.clear() # Ensure no warnings + d.show_warnings() + captured = capsys.readouterr() assert "No warnings." in captured.out.strip() -def test_merge_submodel_warnings_with_list(dummy_base_model): - # Create two children +def test_show_warnings_with_warnings_prints_formatted_output(capsys, dummy_base_model): + """Test show_warnings output when warnings exist.""" + d = dummy_base_model(a="invalid", b="string") + + d.show_warnings() + + captured = capsys.readouterr() + assert "Warnings:" in captured.out + # Should contain field name and warning indicator + assert "a:" in captured.out + assert "[WARNING]" in captured.out or "[ERROR]" in captured.out + + +def test_merge_submodel_warnings_with_multiple_submodels(dummy_base_model): + """Test merging warnings from multiple submodels.""" + class Child(Base): x: int + def _to_dataframe(self, **kwargs): + import pandas as pd + + return pd.DataFrame({"x": [self.x]}) + c1 = Child(x="bad1") c2 = Child(x="bad2") - # both have warnings - assert c1.warnings and c2.warnings + + # Both should have warnings + assert len(c1.warnings) > 0 and len(c2.warnings) > 0 parent = dummy_base_model(a=1, b="string") parent.warnings.clear() - # pass list of submodels - parent._merge_submodel_warnings(c1, c2, key_attr='x') - # expect two warnings, in order - expected = { - 'Child(x=bad1)': { - 'x': ['Input should be a valid integer, unable to parse string as an integer'] - }, - 'Child(x=bad2)': { - 'x': ['Input should be a valid integer, unable to parse string as an integer'] - } - } - assert parent.warnings == expected + # Merge warnings from both children + parent._merge_submodel_warnings(c1, c2, key_attr="x") + + # Check that both were merged with proper prefixes + parent_fields = parent.warnings.get_fields_with_warnings() + assert any("Child(x=bad1)" in field for field in parent_fields) + assert any("Child(x=bad2)" in field for field in parent_fields) + + # Should have warnings from both children + assert len(parent.warnings) >= 2 def test_load_safe_always_constructs_and_warns(dummy_base_model): + """Test that load_safe never raises exceptions and creates warnings.""" # load_safe should never raise, even if data is invalid data = {"a": "not-int", "b": 123} d = dummy_base_model.load_safe(**data) + + assert isinstance(d, dummy_base_model) + assert len(d.warnings) > 0 + + # Check that warnings contain expected validation messages + all_warnings = list(d.warnings) + warning_messages = [w.message.lower() for w in all_warnings] + + assert any("valid integer" in msg for msg in warning_messages) + # Should have warning about b being invalid (number instead of string) or missing + assert any( + "valid string" in msg or "field required" in msg for msg in warning_messages + ) + + +def test_add_warning_manually(dummy_base_model): + """Test manually adding warnings to a model.""" + d = dummy_base_model(a=1, b="string") + d.warnings.clear() + + d.add_warning("custom_field", "Custom warning message") + + assert d.warnings.has_warnings("custom_field") + custom_warnings = d.warnings.get_by_field("custom_field") + assert len(custom_warnings) == 1 + assert custom_warnings[0].message == "Custom warning message" + + +def test_add_warning_with_severity(dummy_base_model): + """Test adding warnings with different severity levels.""" + d = dummy_base_model(a=1, b="string") + d.warnings.clear() + + d.add_warning("error_field", "Critical error", "error") + d.add_warning("info_field", "Information", "info") + + error_warnings = d.warnings.get_by_field("error_field") + info_warnings = d.warnings.get_by_field("info_field") + + assert error_warnings[0].severity == "error" + assert info_warnings[0].severity == "info" + + +def test_clear_warnings_for_specific_field(dummy_base_model): + """Test clearing warnings for a specific field.""" + d = dummy_base_model(a="invalid", b=123) # Both invalid + + # Should have warnings for both fields + assert d.warnings.has_warnings("a") + assert d.warnings.has_warnings("b") + + # Clear warnings for field 'a' only + d._clear_warnings_for_attr("a") + + assert not d.warnings.has_warnings("a") + assert d.warnings.has_warnings("b") # Should still have warnings for b + + +def test_warnings_property_returns_collector(dummy_base_model): + """Test that the warnings property returns a WarningCollector.""" + d = dummy_base_model(a=1, b="string") + + from pyetm.models.warnings import WarningCollector + + assert isinstance(d.warnings, WarningCollector) + + +def test_assignment_clears_previous_warnings(dummy_base_model): + """Test that valid assignment clears previous warnings for that field.""" + d = dummy_base_model(a=1, b="string") + + # Make invalid assignment to create warning + d.a = "invalid" # Should create warning + assert d.warnings.has_warnings("a") + + # Make valid assignment - should clear warnings + d.a = 42 + assert d.a == 42 + assert not d.warnings.has_warnings("a") + + +def test_get_serializable_fields(dummy_base_model): + """Test _get_serializable_fields method.""" + d = dummy_base_model(a=1, b="string") + + fields = d._get_serializable_fields() + + assert "a" in fields + assert "b" in fields + # Should not include private fields + assert all(not field.startswith("_") for field in fields) + + +def test_warning_collector_legacy_compatibility(dummy_base_model): + """Test that we can still get legacy dict format if needed.""" + d = dummy_base_model(a="invalid", b="string") + + # New API + assert len(d.warnings) > 0 + assert d.warnings.has_warnings("a") + + # Legacy format available through to_legacy_dict() + legacy_dict = d.warnings.to_legacy_dict() + assert isinstance(legacy_dict, dict) + assert "a" in legacy_dict + assert isinstance(legacy_dict["a"], list) + + +def test_model_construction_with_partial_data(dummy_base_model): + """Test model construction with missing optional fields.""" + # Assuming 'c' is optional in dummy_base_model + d = dummy_base_model(a=1, b="string") + + assert d.a == 1 + assert d.b == "string" + # Optional field 'c' should have default or None + + +def test_multiple_validation_errors_all_become_warnings(dummy_base_model): + """Test that multiple validation errors all become warnings.""" + # Create model with multiple invalid fields + d = dummy_base_model(a="not-int", b=123) # Both invalid + assert isinstance(d, dummy_base_model) - # Contains both warnings - msgs = [w.lower() for w_list in d.warnings.values() for w in w_list] - assert any("valid integer" in m for m in msgs) - assert any("valid string" in m or "field required" in m for m in msgs) + assert len(d.warnings) >= 2 # Should have at least 2 warnings + + # Should have warnings for both fields + assert d.warnings.has_warnings("a") + assert d.warnings.has_warnings("b") + + +# Additional helper test for complex warning merging +def test_nested_warning_merging_preserves_structure(dummy_base_model): + """Test that nested warning structures are preserved during merging.""" + d = dummy_base_model(a=1, b="string") + d.warnings.clear() + + # Add complex nested warning structure (simulating legacy behavior) + complex_warnings = {"sub1": ["Warning 1", "Warning 2"], "sub2": ["Warning 3"]} + d.add_warning("parent", complex_warnings) + + # Should create nested field names + fields = d.warnings.get_fields_with_warnings() + assert "parent.sub1" in fields + assert "parent.sub2" in fields + + # Check warning counts + sub1_warnings = d.warnings.get_by_field("parent.sub1") + sub2_warnings = d.warnings.get_by_field("parent.sub2") + + assert len(sub1_warnings) == 2 + assert len(sub2_warnings) == 1 + + +def test_show_warnings_different_severities(capsys, dummy_base_model): + """Test show_warnings output with different severity levels.""" + d = dummy_base_model(a=1, b="string") + d.warnings.clear() + + # Add warnings with different severities + d.add_warning("field1", "Information message", "info") + d.add_warning("field2", "Warning message", "warning") + d.add_warning("field3", "Error message", "error") + + d.show_warnings() + + captured = capsys.readouterr() + assert "Warnings:" in captured.out + assert "[INFO]" in captured.out + assert "[WARNING]" in captured.out + assert "[ERROR]" in captured.out + assert "Information message" in captured.out + assert "Warning message" in captured.out + assert "Error message" in captured.out diff --git a/tests/models/test_warnings.py b/tests/models/test_warnings.py new file mode 100644 index 0000000..486390c --- /dev/null +++ b/tests/models/test_warnings.py @@ -0,0 +1,302 @@ +from datetime import datetime +from pyetm.models.warnings import ModelWarning, WarningCollector + +# ----------------ModelWarning---------------- + + +def test_warning_creation(): + """Test basic ModelWarning object creation.""" + warning = ModelWarning(field="test_field", message="Test message") + + assert warning.field == "test_field" + assert warning.message == "Test message" + assert warning.severity == "warning" + assert isinstance(warning.timestamp, datetime) + + +def test_warning_with_custom_severity(): + """Test ModelWarning creation with custom severity.""" + warning = ModelWarning( + field="error_field", message="Error message", severity="error" + ) + + assert warning.field == "error_field" + assert warning.message == "Error message" + assert warning.severity == "error" + + +def test_warning_string_representation(): + """Test ModelWarning __str__ method.""" + warning = ModelWarning(field="field1", message="Test message") + + assert str(warning) == "field1: Test message" + + +def test_warning_repr(): + """Test ModelWarning __repr__ method.""" + warning = ModelWarning(field="field1", message="Test message", severity="error") + + repr_str = repr(warning) + assert "ModelWarning(" in repr_str + assert "field='field1'" in repr_str + assert "message='Test message'" in repr_str + assert "severity='error'" in repr_str + + +def test_warning_to_dict(): + """Test ModelWarning serialization to dictionary.""" + warning = ModelWarning(field="field1", message="Test message", severity="info") + result = warning.to_dict() + + assert result["field"] == "field1" + assert result["message"] == "Test message" + assert result["severity"] == "info" + assert "timestamp" in result + + +# ----------------WarningCollector---------------- + + +def test_warning_collector_creation(): + """Test basic WarningCollector creation.""" + collector = WarningCollector() + + assert len(collector) == 0 + assert not collector.has_warnings() + assert collector.get_fields_with_warnings() == [] + + +def test_add_simple_warning(): + """Test adding a simple string warning.""" + collector = WarningCollector() + collector.add("field1", "Simple warning") + + assert len(collector) == 1 + assert collector.has_warnings("field1") + assert not collector.has_warnings("field2") + + warnings = collector.get_by_field("field1") + assert len(warnings) == 1 + assert warnings[0].message == "Simple warning" + + +def test_add_multiple_warnings_same_field(): + """Test adding multiple warnings to the same field.""" + collector = WarningCollector() + + collector.add("field1", "Warning 1") + collector.add("field1", "Warning 2") + + assert len(collector) == 2 + warnings = collector.get_by_field("field1") + assert len(warnings) == 2 + messages = [w.message for w in warnings] + assert "Warning 1" in messages + assert "Warning 2" in messages + + +def test_add_list_of_warnings(): + """Test adding a list of warning messages.""" + collector = WarningCollector() + collector.add("field1", ["Warning 1", "Warning 2", "Warning 3"]) + + assert len(collector) == 3 + warnings = collector.get_by_field("field1") + messages = [w.message for w in warnings] + assert "Warning 1" in messages + assert "Warning 2" in messages + assert "Warning 3" in messages + + +def test_add_nested_dict_warnings(): + """Test adding nested dictionary warnings (legacy pattern).""" + collector = WarningCollector() + nested_warnings = { + "subfield1": ["Sub warning 1"], + "subfield2": ["Sub warning 2", "Sub warning 3"], + } + collector.add("parent", nested_warnings) + + assert len(collector) == 3 + assert collector.has_warnings("parent.subfield1") + assert collector.has_warnings("parent.subfield2") + + sub1_warnings = collector.get_by_field("parent.subfield1") + assert len(sub1_warnings) == 1 + assert sub1_warnings[0].message == "Sub warning 1" + + sub2_warnings = collector.get_by_field("parent.subfield2") + assert len(sub2_warnings) == 2 + + +def test_add_warning_with_severity(): + """Test adding warnings with different severities.""" + collector = WarningCollector() + + collector.add("field1", "Info message", "info") + collector.add("field2", "Warning message", "warning") + collector.add("field3", "Error message", "error") + + assert len(collector) == 3 + + info_warning = collector.get_by_field("field1")[0] + assert info_warning.severity == "info" + + warning_warning = collector.get_by_field("field2")[0] + assert warning_warning.severity == "warning" + + error_warning = collector.get_by_field("field3")[0] + assert error_warning.severity == "error" + + +def test_clear_all_warnings(): + """Test clearing all warnings.""" + collector = WarningCollector() + collector.add("field1", "Warning 1") + collector.add("field2", "Warning 2") + + assert len(collector) == 2 + + collector.clear() + + assert len(collector) == 0 + assert not collector.has_warnings() + + +def test_clear_specific_field(): + """Test clearing warnings for a specific field.""" + collector = WarningCollector() + collector.add("field1", "Warning 1") + collector.add("field2", "Warning 2") + collector.add("field1", "Warning 3") + + assert len(collector) == 3 + + collector.clear("field1") + + assert len(collector) == 1 + assert not collector.has_warnings("field1") + assert collector.has_warnings("field2") + + +def test_get_fields_with_warnings(): + """Test getting list of fields that have warnings.""" + collector = WarningCollector() + collector.add("field1", "Warning 1") + collector.add("field2", "Warning 2") + collector.add("field1", "Warning 3") + + fields = collector.get_fields_with_warnings() + + assert len(fields) == 2 + assert "field1" in fields + assert "field2" in fields + + +def test_to_legacy_dict(): + """Test conversion to legacy dictionary format.""" + collector = WarningCollector() + collector.add("field1", "Warning 1") + collector.add("field1", "Warning 2") + collector.add("field2", "Warning 3") + + legacy_dict = collector.to_legacy_dict() + + expected = {"field1": ["Warning 1", "Warning 2"], "field2": ["Warning 3"]} + assert legacy_dict == expected + + +def test_to_dict(): + """Test conversion to detailed dictionary format.""" + collector = WarningCollector() + collector.add("field1", "Warning 1", "error") + + result = collector.to_dict() + + assert "field1" in result + assert len(result["field1"]) == 1 + warning_dict = result["field1"][0] + assert warning_dict["field"] == "field1" + assert warning_dict["message"] == "Warning 1" + assert warning_dict["severity"] == "error" + assert "timestamp" in warning_dict + + +def test_merge_from_another_collector(): + """Test merging warnings from another collector.""" + collector1 = WarningCollector() + collector1.add("field1", "Main warning") + + collector2 = WarningCollector() + collector2.add("sub_field", "Sub warning") + + collector1.merge_from(collector2, "SubModel") + + assert len(collector1) == 2 + assert collector1.has_warnings("field1") + assert collector1.has_warnings("SubModel.sub_field") + + +def test_merge_from_without_prefix(): + """Test merging warnings without prefix.""" + collector1 = WarningCollector() + collector1.add("field1", "Warning 1") + + collector2 = WarningCollector() + collector2.add("field2", "Warning 2") + + collector1.merge_from(collector2) + + assert len(collector1) == 2 + assert collector1.has_warnings("field1") + assert collector1.has_warnings("field2") + + +def test_collector_bool_evaluation(): + """Test WarningCollector boolean evaluation.""" + collector = WarningCollector() + + assert not collector # Empty collector is falsy + + collector.add("field1", "Warning") + + assert collector # Non-empty collector is truthy + + +def test_collector_iteration(): + """Test iterating over WarningCollector.""" + collector = WarningCollector() + collector.add("field1", "Warning 1") + collector.add("field2", "Warning 2") + + warnings = list(collector) + + assert len(warnings) == 2 + assert all(isinstance(w, ModelWarning) for w in warnings) + messages = [w.message for w in warnings] + assert "Warning 1" in messages + assert "Warning 2" in messages + + +def test_collector_repr_empty(): + """Test WarningCollector __repr__ when empty.""" + collector = WarningCollector() + + repr_str = repr(collector) + + assert "no warnings" in repr_str + + +def test_collector_repr_with_warnings(): + """Test WarningCollector __repr__ with warnings.""" + collector = WarningCollector() + collector.add("field1", "Warning", "warning") + collector.add("field2", "Error", "error") + collector.add("field3", "Info", "info") + + repr_str = repr(collector) + + assert "3 warnings" in repr_str + assert "1 warning" in repr_str + assert "1 error" in repr_str + assert "1 info" in repr_str From bfe2ca8332e9424a3d7f8ed1f9c4b1cdeb0aba84 Mon Sep 17 00:00:00 2001 From: louispt1 Date: Mon, 4 Aug 2025 08:30:15 +0200 Subject: [PATCH 06/19] Update inputs to new warnings model --- src/pyetm/models/inputs.py | 49 +++-- tests/models/test_input.py | 100 ---------- tests/models/test_inputs.py | 359 +++++++++++++++++++++++++++++++++++- 3 files changed, 380 insertions(+), 128 deletions(-) delete mode 100644 tests/models/test_input.py diff --git a/src/pyetm/models/inputs.py b/src/pyetm/models/inputs.py index 8fa5737..4183544 100644 --- a/src/pyetm/models/inputs.py +++ b/src/pyetm/models/inputs.py @@ -1,7 +1,8 @@ from __future__ import annotations -from typing import Any, Optional, Union -from pydantic import field_validator, model_validator, ValidationInfo +from typing import Optional, Union +from pydantic import field_validator, model_validator import pandas as pd +from pyetm.models.warnings import WarningCollector from pyetm.models.base import Base @@ -19,9 +20,9 @@ class Input(Base): coupling_groups: Optional[list[str]] = [] disabled_by: Optional[str] = None - def is_valid_update(self, value) -> list[str]: + def is_valid_update(self, value) -> WarningCollector: """ - Returns a list of validation warnings without updating the current object + Returns a WarningCollector with validation warnings without updating the current object. """ new_obj_dict = self.model_dump() new_obj_dict["user"] = value @@ -30,7 +31,7 @@ def is_valid_update(self, value) -> list[str]: return warnings_obj.warnings @classmethod - def from_json(cls, data: tuple[str, dict]) -> Input: + def from_json(cls, data: tuple[str, dict]) -> "Input": """ Initialize an Input from a JSON-like tuple coming from .items() """ @@ -43,7 +44,8 @@ def from_json(cls, data: tuple[str, dict]) -> Input: return input_instance except Exception as e: # Create a basic Input with warning attached - basic_input = cls.model_validate(payload) + basic_input = cls.model_construct(**payload) # Bypass validation + basic_input._warning_collector = WarningCollector() basic_input.add_warning(key, f"Failed to create specialized input: {e}") return basic_input @@ -78,7 +80,7 @@ class BoolInput(Input): @field_validator("user", mode="after") @classmethod - def is_bool_float(cls, value: float) -> float: + def is_bool_float(cls, value: Optional[float]) -> Optional[float]: if value == 1.0 or value == 0.0 or value is None: return value raise ValueError( @@ -161,30 +163,39 @@ def __iter__(self): def keys(self): return [input.key for input in self.inputs] - def is_valid_update(self, key_vals: dict) -> dict: + # TODO: Check the efficiency of doing this in a loop + def is_valid_update(self, key_vals: dict) -> dict[str, WarningCollector]: """ - Returns a dict of input keys and errors when errors were found + Returns a dict mapping input keys to their WarningCollectors when errors were found. """ warnings = {} - for input in self.inputs: - if input.key in key_vals: - input_warn = input.is_valid_update(key_vals[input.key]) - if len(input_warn) > 0: - warnings[input.key] = input_warn + # Check each input that has an update + for input_obj in self.inputs: + if input_obj.key in key_vals: + input_warnings = input_obj.is_valid_update(key_vals[input_obj.key]) + if len(input_warnings) > 0: + warnings[input_obj.key] = input_warnings + + # Check for non-existent keys non_existent_keys = set(key_vals.keys()) - set(self.keys()) for key in non_existent_keys: - warnings[key] = "Key does not exist" + # Create a warning collector for non-existent keys + warning_collector = WarningCollector() + warning_collector.add(key, "Key does not exist") + warnings[key] = warning_collector return warnings def update(self, key_vals: dict): """ - Update the values of certain inputs + Update the values of certain inputs. + Uses the new warning system for validation. """ - for input in self.inputs: - if input.key in key_vals: - input.user = key_vals[input.key] + for input_obj in self.inputs: + if input_obj.key in key_vals: + # Use assignment which goes through __setattr__ validation + input_obj.user = key_vals[input_obj.key] def _to_dataframe(self, columns="user", **kwargs) -> pd.DataFrame: """ diff --git a/tests/models/test_input.py b/tests/models/test_input.py deleted file mode 100644 index 25de8b5..0000000 --- a/tests/models/test_input.py +++ /dev/null @@ -1,100 +0,0 @@ -import pytest -from pyetm.models import Input -from pyetm.models.inputs import BoolInput, EnumInput, FloatInput - - -@pytest.mark.parametrize( - "json_fixture", - ["float_input_json", "enum_input_json", "bool_input_json", "disabled_input_json"], -) -def test_input_from_json(json_fixture, request): - input_json = request.getfixturevalue(json_fixture) - input = Input.from_json(next(iter(input_json.items()))) - - # Assert valid input - assert input - - -def test_bool_input(): - input = BoolInput(key='my_bool', unit='bool', default=0.0) - - # Setting the input - input.user = 0.0 - assert input.user == 0.0 - - # Is it valid to update to string? - validity_errors = input.is_valid_update('true') - assert 'user' in validity_errors - assert 'Input should be a valid number, unable to parse string as a number' in validity_errors['user'] - - # Is it valid to update to 0.5? - validity_errors = input.is_valid_update(0.5) - assert 'user' in validity_errors - assert 'Value error, 0.5 should be 1.0 or 0.0 representing True/False, or On/Off' in validity_errors['user'] - - # Try to update to 0.5 - input.user = 0.5 - assert input.user == 0.0 - - # Reset the input - input.user = "reset" - assert input.user is None - assert 'user' not in input.warnings - -def test_enum_input(): - input = EnumInput( - key='my_enum', - unit='enum', - default='diesel', - permitted_values=['diesel', 'gasoline'] - ) - - # Setting the input - input.user = 'gasoline' - assert input.user == 'gasoline' - # Is it valid to update to kerosene? - validity_errors = input.is_valid_update('kerosene') - assert 'user' in validity_errors - assert "Value error, kerosene should be in ['diesel', 'gasoline']" in validity_errors['user'] - - # Try to update to 0.5 - input.user = 0.5 - assert 'user' in input.warnings - assert input.user == 'gasoline' - - # Try to update to kerosene - input.user = 'kerosene' - assert 'user' in input.warnings - assert input.user == 'gasoline' - - # Reset the input - input.user = "reset" - assert input.user is None - assert 'user' not in input.warnings - -def test_float_input(): - input = FloatInput( - key='my_float', - unit='euro', - min=0.0, - max=20.0 - ) - - # Setting the input - input.user = 2.0 - assert input.user == 2.0 - - # Is it valid to update to -1.0? - validity_errors = input.is_valid_update(-1.0) - assert 'user' in validity_errors - assert "Value error, -1.0 should be between 0.0 and 20.0" in validity_errors['user'] - - # Try to update to 30 - input.user = 30.0 - assert 'user' in input.warnings - assert "Value error, 30.0 should be between 0.0 and 20.0" in input.warnings['user'] - assert input.user == 2.0 - - # Reset the input - input.user = "reset" - assert input.user is None diff --git a/tests/models/test_inputs.py b/tests/models/test_inputs.py index 2875047..2883e92 100644 --- a/tests/models/test_inputs.py +++ b/tests/models/test_inputs.py @@ -1,7 +1,10 @@ -from pyetm.models import Inputs +import pytest +from pyetm.models import Inputs, Input +from pyetm.models.inputs import BoolInput, EnumInput, FloatInput def test_collection_from_json(inputs_json): + """Test creating Inputs collection from JSON data.""" input_collection = Inputs.from_json(inputs_json) # Check if valid! @@ -19,7 +22,6 @@ def test_to_dataframe(inputs_json): assert "user" in df_standard.columns assert "user" in df_with_defaults.columns - assert "default" not in df_standard.columns assert "default" in df_with_defaults.columns @@ -29,22 +31,361 @@ def test_to_dataframe(inputs_json): def test_valid_update(inputs_json): + """Test validation of updates using new WarningCollector system.""" input_collection = Inputs.from_json(inputs_json) - # A good update + # A good update - should return empty dict warnings = input_collection.is_valid_update({"investment_costs_co2_ccs": 50.0}) assert len(warnings) == 0 - # An update that will trigger validation + # An update that will trigger validation - returns WarningCollector objects warnings = input_collection.is_valid_update({"investment_costs_co2_ccs": "hello"}) assert len(warnings) > 0 assert "investment_costs_co2_ccs" in warnings - assert warnings["investment_costs_co2_ccs"]["user"] == [ - "Input should be a valid number, unable to parse string as a number" - ] - # An update of a non existent key + # Check the WarningCollector object + warning_collector = warnings["investment_costs_co2_ccs"] + assert warning_collector.has_warnings("user") + + user_warnings = warning_collector.get_by_field("user") + assert len(user_warnings) > 0 + assert "unable to parse string as a number" in user_warnings[0].message.lower() + + # An update of a non-existent key warnings = input_collection.is_valid_update({"hello": "hello"}) assert len(warnings) > 0 assert "hello" in warnings - assert warnings["hello"] == "Key does not exist" + + # Check non-existent key warning + hello_warnings = warnings["hello"] + assert hello_warnings.has_warnings("hello") + hello_warning_msgs = [w.message for w in hello_warnings.get_by_field("hello")] + assert "Key does not exist" in hello_warning_msgs + + +def test_collection_update_method(inputs_json): + """Test the update method applies changes correctly.""" + input_collection = Inputs.from_json(inputs_json) + + # Get original value + original_input = next( + inp for inp in input_collection if inp.key == "investment_costs_co2_ccs" + ) + original_value = original_input.user + + # Update with valid value + input_collection.update({"investment_costs_co2_ccs": 75.0}) + assert original_input.user == 75.0 + + # Update with invalid value - should not change and add warning + input_collection.update({"investment_costs_co2_ccs": "invalid"}) + assert original_input.user == 75.0 # Should not change + assert original_input.warnings.has_warnings("user") + + +def test_collection_with_invalid_inputs(): + """Test collection creation when individual inputs have issues.""" + # Create data that will cause some inputs to have warnings + problematic_data = { + "good_input": {"unit": "float", "min": 0, "max": 100, "user": 50}, + "bad_input": {"unit": "float"}, # Missing required min/max + "unknown_unit": {"unit": "weird_unit", "min": 0, "max": 100}, + } + + collection = Inputs.from_json(problematic_data) + + # Collection should be created + assert len(collection) == 3 + + # Collection should have warnings merged from problematic inputs + assert len(collection.warnings) > 0 + + +@pytest.mark.parametrize( + "json_fixture", + ["float_input_json", "enum_input_json", "bool_input_json", "disabled_input_json"], +) +def test_input_from_json(json_fixture, request): + """Test Input creation from JSON data.""" + input_json = request.getfixturevalue(json_fixture) + input_obj = Input.from_json(next(iter(input_json.items()))) + + # Assert valid input + assert input_obj + + +def test_bool_input(): + """Test BoolInput validation and warning behavior.""" + input_obj = BoolInput(key="my_bool", unit="bool", default=0.0) + + # Setting the input + input_obj.user = 0.0 + assert input_obj.user == 0.0 + + # Is it valid to update to string? - should return WarningCollector + validity_warnings = input_obj.is_valid_update("true") + assert validity_warnings.has_warnings("user") + + user_warnings = validity_warnings.get_by_field("user") + assert any( + "unable to parse string as a number" in w.message.lower() for w in user_warnings + ) + + # Is it valid to update to 0.5? + validity_warnings = input_obj.is_valid_update(0.5) + assert validity_warnings.has_warnings("user") + + user_warnings = validity_warnings.get_by_field("user") + assert any("0.5 should be 1.0 or 0.0" in w.message for w in user_warnings) + + # Try to update to 0.5 - should not change value but add warning + input_obj.user = 0.5 + assert input_obj.user == 0.0 # Should not change + assert input_obj.warnings.has_warnings("user") # Should have warning + + # Reset the input + input_obj.user = "reset" + assert input_obj.user is None + assert not input_obj.warnings.has_warnings("user") # Warnings should be cleared + + +def test_enum_input(): + """Test EnumInput validation and warning behavior.""" + input_obj = EnumInput( + key="my_enum", + unit="enum", + default="diesel", + permitted_values=["diesel", "gasoline"], + ) + + # Setting the input + input_obj.user = "gasoline" + assert input_obj.user == "gasoline" + + # Is it valid to update to kerosene? + validity_warnings = input_obj.is_valid_update("kerosene") + assert validity_warnings.has_warnings("user") + + user_warnings = validity_warnings.get_by_field("user") + assert any( + "kerosene should be in ['diesel', 'gasoline']" in w.message + for w in user_warnings + ) + + # Try to update to invalid number - should not change value but add warning + input_obj.user = 0.5 + assert input_obj.warnings.has_warnings("user") + assert input_obj.user == "gasoline" # Should not change + + # Try to update to kerosene - should not change value but add warning + input_obj.warnings.clear() # Clear previous warnings + input_obj.user = "kerosene" + assert input_obj.warnings.has_warnings("user") + assert input_obj.user == "gasoline" # Should not change + + # Reset the input + input_obj.user = "reset" + assert input_obj.user is None + assert not input_obj.warnings.has_warnings("user") + + +def test_float_input(): + """Test FloatInput validation and warning behavior.""" + input_obj = FloatInput(key="my_float", unit="euro", min=0.0, max=20.0) + + # Setting the input + input_obj.user = 2.0 + assert input_obj.user == 2.0 + + # Is it valid to update to -1.0? + validity_warnings = input_obj.is_valid_update(-1.0) + assert validity_warnings.has_warnings("user") + + user_warnings = validity_warnings.get_by_field("user") + assert any( + "-1.0 should be between 0.0 and 20.0" in w.message for w in user_warnings + ) + + # Try to update to 30 - should not change value but add warning + input_obj.user = 30.0 + assert input_obj.warnings.has_warnings("user") + + # Check the warning message + user_warnings = input_obj.warnings.get_by_field("user") + assert any( + "30.0 should be between 0.0 and 20.0" in w.message for w in user_warnings + ) + assert input_obj.user == 2.0 # Should not change + + # Reset the input + input_obj.user = "reset" + assert input_obj.user is None + assert not input_obj.warnings.has_warnings("user") + + +def test_input_warning_severity_levels(): + """Test that different validation failures can have different severity levels.""" + input_obj = FloatInput(key="test", unit="float", min=0, max=100) + + # Create input with validation error (should be 'error' severity from __init__) + bad_input = FloatInput( + key="test", unit="float", min=0, max=100, user="not_a_number" + ) + + # Check that initialization warnings exist + if len(bad_input.warnings) > 0: + warnings = list(bad_input.warnings) + # Should have error-level warnings from failed initialization + assert any(w.severity == "error" for w in warnings) + + +def test_input_warning_timestamps(): + """Test that warnings have timestamps.""" + input_obj = BoolInput(key="test", unit="bool") + + # Create a warning + input_obj.user = 0.5 # Invalid value + + if len(input_obj.warnings) > 0: + warnings = list(input_obj.warnings) + for warning in warnings: + assert hasattr(warning, "timestamp") + assert warning.timestamp is not None + + +def test_warning_collector_methods(): + """Test WarningCollector methods work correctly with Input objects.""" + input_obj = FloatInput(key="test", unit="float", min=0, max=100) + + # Add some warnings + input_obj.user = -5 # Out of bounds + input_obj.add_warning("custom_field", "Custom warning", "info") + + warnings = input_obj.warnings + + # Test various methods + assert len(warnings) > 0 + assert warnings.has_warnings() + assert warnings.has_warnings("user") + assert warnings.has_warnings("custom_field") + + fields_with_warnings = warnings.get_fields_with_warnings() + assert "user" in fields_with_warnings + assert "custom_field" in fields_with_warnings + + # Test clearing specific field + warnings.clear("custom_field") + assert not warnings.has_warnings("custom_field") + assert warnings.has_warnings("user") # Should still have user warnings + + +def test_inputs_collection_warning_aggregation(): + """Test that Inputs collection properly aggregates warnings from individual inputs.""" + # Create inputs with various issues + inputs_data = { + "good_input": {"unit": "float", "min": 0, "max": 100, "user": 50}, + "bad_float": { + "unit": "float", + "min": 0, + "max": 100, + "user": 150, + }, # Out of bounds + "bad_bool": {"unit": "bool", "user": 0.5}, # Invalid bool value + "missing_data": {"unit": "enum"}, # Missing required permitted_values + } + + collection = Inputs.from_json(inputs_data) + + # Collection should exist + assert len(collection) == 4 + + # Should have aggregated warnings + assert len(collection.warnings) > 0 + + # Check that warnings from individual inputs are properly prefixed + warning_fields = collection.warnings.get_fields_with_warnings() + + # Should have warnings with input key prefixes + assert any("Input(key=" in field for field in warning_fields) + + +def test_input_serializable_fields(): + """Test that different input types return correct serializable fields.""" + # Test base Input + base_input = Input(key="test", unit="simple") + base_fields = base_input._get_serializable_fields() + expected_base = [ + "key", + "unit", + "default", + "user", + "disabled", + "coupling_disabled", + "coupling_groups", + "disabled_by", + ] + for field in expected_base: + assert field in base_fields + + # Test EnumInput includes permitted_values + enum_input = EnumInput(key="test", unit="enum", permitted_values=["a", "b"]) + enum_fields = enum_input._get_serializable_fields() + assert "permitted_values" in enum_fields + + # Test FloatInput includes min/max + float_input = FloatInput(key="test", unit="float", min=0, max=100) + float_fields = float_input._get_serializable_fields() + assert "min" in float_fields + assert "max" in float_fields + assert "step" in float_fields + assert "share_group" in float_fields + + +def test_input_reset_functionality(): + """Test that 'reset' string properly clears user values across all input types.""" + # Test FloatInput + float_input = FloatInput(key="test_float", unit="float", min=0, max=100, user=50.0) + assert float_input.user == 50.0 + float_input.user = "reset" + assert float_input.user is None + + # Test BoolInput + bool_input = BoolInput(key="test_bool", unit="bool", user=1.0) + assert bool_input.user == 1.0 + bool_input.user = "reset" + assert bool_input.user is None + + # Test EnumInput + enum_input = EnumInput( + key="test_enum", unit="enum", permitted_values=["a", "b"], user="a" + ) + assert enum_input.user == "a" + enum_input.user = "reset" + assert enum_input.user is None + + +def test_collection_iteration_and_access(): + """Test that Inputs collection supports proper iteration and key access.""" + inputs_data = { + "input1": {"unit": "float", "min": 0, "max": 100}, + "input2": {"unit": "bool"}, + "input3": {"unit": "enum", "permitted_values": ["a", "b"]}, + } + + collection = Inputs.from_json(inputs_data) + + # Test length + assert len(collection) == 3 + + # Test iteration + input_keys = [inp.key for inp in collection] + assert "input1" in input_keys + assert "input2" in input_keys + assert "input3" in input_keys + + # Test keys() method + keys = collection.keys() + assert len(keys) == 3 + assert "input1" in keys + assert "input2" in keys + assert "input3" in keys From 56222fe9b174200cb9a861a5ec2a90af2e9bd0ce Mon Sep 17 00:00:00 2001 From: louispt1 Date: Mon, 4 Aug 2025 10:10:14 +0200 Subject: [PATCH 07/19] Update all models to use Warnings --- src/pyetm/models/base.py | 7 -- src/pyetm/models/custom_curves.py | 37 +++--- src/pyetm/models/gqueries.py | 11 +- src/pyetm/models/inputs.py | 6 +- src/pyetm/models/output_curves.py | 68 ++++++----- src/pyetm/models/scenario.py | 47 +++++++- src/pyetm/models/scenario_packer.py | 6 +- src/pyetm/models/sortables.py | 30 ++--- src/pyetm/models/warnings.py | 12 ++ tests/models/conftest.py | 2 +- tests/models/test_custom_curves.py | 35 ++++-- tests/models/test_output_curves.py | 42 +++++-- tests/models/test_scenario.py | 120 ++++++++++++++----- tests/models/test_sortable.py | 173 ---------------------------- tests/models/test_sortables.py | 166 +++++++++++++++++++++++++- 15 files changed, 446 insertions(+), 316 deletions(-) delete mode 100644 tests/models/test_sortable.py diff --git a/src/pyetm/models/base.py b/src/pyetm/models/base.py index 0f1d022..fd7b593 100644 --- a/src/pyetm/models/base.py +++ b/src/pyetm/models/base.py @@ -92,16 +92,9 @@ def add_warning( def warnings(self) -> Union[WarningCollector, Dict[str, List[str]]]: """ Return warnings. - - For backward compatibility, this can return either the new WarningCollector - or the legacy dict format. The implementation can be switched based on needs. """ - # Return the new collector (recommended) return self._warning_collector - # OR return legacy format for backward compatibility: - # return self._warning_collector.to_legacy_dict() - def show_warnings(self) -> None: """Print all warnings to the console.""" self._warning_collector.show_warnings() diff --git a/src/pyetm/models/custom_curves.py b/src/pyetm/models/custom_curves.py index 8f2bf2c..b60ea51 100644 --- a/src/pyetm/models/custom_curves.py +++ b/src/pyetm/models/custom_curves.py @@ -4,6 +4,7 @@ from typing import Optional from pyetm.clients import BaseClient from pyetm.models.base import Base +from pyetm.models.warnings import WarningCollector from pyetm.services.scenario_runners.fetch_custom_curves import ( DownloadCustomCurveRunner, ) @@ -59,10 +60,7 @@ def retrieve(self, client, scenario) -> Optional[pd.DataFrame]: return curve.rename(self.key) except Exception as e: # File processing error - add warning and return None - self.add_warning( - self.key, - f"Failed to process curve data: {e}" - ) + self.add_warning(self.key, f"Failed to process curve data: {e}") return None else: # API call failed - add warning for each error @@ -119,8 +117,8 @@ def from_json(cls, data: dict) -> CustomCurve: "key": data.get("key", "unknown"), "type": data.get("type", "unknown"), } - curve = cls.model_validate(basic_data) - curve.add_warning(basic_data["key"], f"Failed to create curve from data: {e}") + curve = cls.model_construct(**basic_data) + curve.add_warning("base", f"Failed to create curve from data: {e}") return curve @@ -147,19 +145,17 @@ def get_contents( curve = self._find(curve_name) if not curve: - self.add_warning('curves', f"Curve {curve_name} not found in collection") + self.add_warning("curves", f"Curve {curve_name} not found in collection") return None if not curve.available(): # Try to retrieve it result = curve.retrieve(BaseClient(), scenario) - # Merge any warnings from the curve retrieval - self._merge_submodel_warnings(curve) + self._merge_submodel_warnings(curve, key_attr="key") return result else: contents = curve.contents() - # Merge any warnings from reading contents - self._merge_submodel_warnings(curve) + self._merge_submodel_warnings(curve, key_attr="key") return contents def _find(self, curve_name: str) -> Optional[CustomCurve]: @@ -171,24 +167,23 @@ def from_json(cls, data: list[dict]) -> CustomCurves: Initialize CustomCurves collection from JSON data """ curves = [] - collection_warnings = {} for curve_data in data: try: - key = curve_data['key'] curve = CustomCurve.from_json(curve_data) curves.append(curve) except Exception as e: - # Log the problematic curve but continue processing - collection_warnings[f"CustomCurve(key={key})"] = f"Skipped invalid curve data: {e}" + # Create a basic curve and continue processing + key = curve_data.get("key", "unknown") + basic_curve = CustomCurve.model_construct(key=key, type="unknown") + basic_curve.add_warning(key, f"Skipped invalid curve data: {e}") + curves.append(basic_curve) collection = cls.model_validate({"curves": curves}) - # Add any collection-level warnings - for loc, msg in collection_warnings.items(): - collection.add_warning(loc, msg) - - # Merge warnings from individual curves - collection._merge_submodel_warnings(*curves, key_attr='key') + # Merge warnings from individual curves using new system + collection._merge_submodel_warnings(*curves, key_attr="key") return collection + + # TODO: _to_dataframe diff --git a/src/pyetm/models/gqueries.py b/src/pyetm/models/gqueries.py index 4fe802c..948dce6 100644 --- a/src/pyetm/models/gqueries.py +++ b/src/pyetm/models/gqueries.py @@ -10,7 +10,7 @@ class Gqueries(Base): """ - We cannot validat yet - as we'd need a servcie connected to the main + We cannot validate yet - as we'd need a service connected to the main gquery endpoint """ @@ -48,7 +48,7 @@ def execute(self, client, scenario): if result.success: self.update(result.data) else: - self.add_warning('results', f"Error retrieving queries: {result.errors}") + self.add_warning("results", f"Error retrieving queries: {result.errors}") def to_dataframe(self, columns="future"): if not self.is_ready(): @@ -58,6 +58,13 @@ def to_dataframe(self, columns="future"): df.index.name = "gquery" return df.set_index("unit", append=True) + def _to_dataframe(self, **kwargs) -> pd.DataFrame: + """ + Implementation required by Base class. + Uses to_dataframe with default parameters. + """ + return self.to_dataframe() + @classmethod def from_list(cls, query_list: list[str]): return cls(query_dict={q: None for q in query_list}) diff --git a/src/pyetm/models/inputs.py b/src/pyetm/models/inputs.py index 4183544..a8ee2f1 100644 --- a/src/pyetm/models/inputs.py +++ b/src/pyetm/models/inputs.py @@ -45,7 +45,6 @@ def from_json(cls, data: tuple[str, dict]) -> "Input": except Exception as e: # Create a basic Input with warning attached basic_input = cls.model_construct(**payload) # Bypass validation - basic_input._warning_collector = WarningCollector() basic_input.add_warning(key, f"Failed to create specialized input: {e}") return basic_input @@ -180,10 +179,7 @@ def is_valid_update(self, key_vals: dict) -> dict[str, WarningCollector]: # Check for non-existent keys non_existent_keys = set(key_vals.keys()) - set(self.keys()) for key in non_existent_keys: - # Create a warning collector for non-existent keys - warning_collector = WarningCollector() - warning_collector.add(key, "Key does not exist") - warnings[key] = warning_collector + warnings[key] = WarningCollector.with_warning(key, "Key does not exist") return warnings diff --git a/src/pyetm/models/output_curves.py b/src/pyetm/models/output_curves.py index 83a1a14..540bb27 100644 --- a/src/pyetm/models/output_curves.py +++ b/src/pyetm/models/output_curves.py @@ -7,6 +7,7 @@ import yaml from pyetm.clients import BaseClient from pyetm.models.base import Base +from pyetm.models.warnings import WarningCollector from pyetm.config.settings import get_settings from pyetm.services.scenario_runners.fetch_output_curves import ( DownloadOutputCurveRunner, @@ -59,27 +60,32 @@ def retrieve(self, client, scenario) -> Optional[pd.DataFrame]: except Exception as e: self.add_warning( - 'data', - f"Failed to process curve data for {self.key}: {e}" + "data", f"Failed to process curve data for {self.key}: {e}" ) return None except Exception as e: # Unexpected error - add warning - self.add_warning('base', f"Unexpected error retrieving curve {self.key}: {e}") + self.add_warning( + "base", f"Unexpected error retrieving curve {self.key}: {e}" + ) return None def contents(self) -> Optional[pd.DataFrame]: """Open file from path and return contents""" if not self.available(): - self.add_warning('file_path', f"Curve {self.key} not available - no file path set") + self.add_warning( + "file_path", f"Curve {self.key} not available - no file path set" + ) return None try: df = pd.read_csv(self.file_path, index_col=0) return df.dropna(how="all") except Exception as e: - self.add_warning('file_path', f"Failed to read curve file for {self.key}: {e}") + self.add_warning( + "file_path", f"Failed to read curve file for {self.key}: {e}" + ) return None def remove(self) -> bool: @@ -92,7 +98,9 @@ def remove(self) -> bool: self.file_path = None return True except Exception as e: - self.add_warning('file_path', f"Failed to remove curve file for {self.key}: {e}") + self.add_warning( + "file_path", f"Failed to remove curve file for {self.key}: {e}" + ) return False @classmethod @@ -109,8 +117,8 @@ def from_json(cls, data: dict) -> OutputCurve: "key": data.get("key", "unknown"), "type": data.get("type", "unknown"), } - curve = cls.model_validate(basic_data) - curve.add_warning('base', f"Failed to create curve from data: {e}") + curve = cls.model_construct(**basic_data) + curve.add_warning("base", f"Failed to create curve from data: {e}") return curve @@ -135,19 +143,19 @@ def get_contents(self, scenario, curve_name: str) -> Optional[pd.DataFrame]: curve = self._find(curve_name) if not curve: - self.add_warning('curves', f"Curve {curve_name} not found in collection") + self.add_warning("curves", f"Curve {curve_name} not found in collection") return None if not curve.available(): # Try to retrieve it result = curve.retrieve(BaseClient(), scenario) - # Merge any warnings from the curve retrieval - self._merge_submodel_warnings(curve) + # Merge any warnings from the curve retrieval using new system + self._merge_submodel_warnings(curve, key_attr="key") return result else: contents = curve.contents() - # Merge any warnings from reading contents - self._merge_submodel_warnings(curve) + # Merge any warnings from reading contents using new system + self._merge_submodel_warnings(curve, key_attr="key") return contents @staticmethod @@ -203,8 +211,8 @@ def get_curves_by_carrier_type( if carrier_type not in carrier_mapping: valid_types = ", ".join(carrier_mapping.keys()) self.add_warning( - 'carrier_type', - f"Invalid carrier type '{carrier_type}'. Valid types: {valid_types}" + "carrier_type", + f"Invalid carrier type '{carrier_type}'. Valid types: {valid_types}", ) return {} @@ -225,25 +233,22 @@ def from_json(cls, data: list[dict]) -> OutputCurves: Initialize OutputCurves collection from JSON data """ curves = [] - collection_warnings = {} for curve_data in data: try: - key = curve_data['key'] curve = OutputCurve.from_json(curve_data) curves.append(curve) except Exception as e: - # Log the problematic curve but continue processing - collection_warnings[f"OutputCurve(key={key})"] = f"Skipped invalid curve data: {e}" + # Create a basic curve and continue processing + key = curve_data.get("key", "unknown") + basic_curve = OutputCurve.model_construct(key=key, type="unknown") + basic_curve.add_warning(key, f"Skipped invalid curve data: {e}") + curves.append(basic_curve) collection = cls.model_validate({"curves": curves}) - # Add any collection-level warnings - for loc, msg in collection_warnings.items(): - collection.add_warning(loc, msg) - - # Merge warnings from individual curves - collection._merge_submodel_warnings(*curves, key_attr='key') + # Merge warnings from individual curves using new system + collection._merge_submodel_warnings(*curves, key_attr="key") return collection @@ -255,7 +260,7 @@ def from_service_result( if not service_result.success or not service_result.data: empty_curves = cls(curves=[]) for error in service_result.errors: - empty_curves.add_warning('base', f"Service error: {error}") + empty_curves.add_warning("base", f"Service error: {error}") return empty_curves curves_list = [] @@ -281,17 +286,18 @@ def from_service_result( curves_list.append(curve) except Exception as e: - curves_list.append( - OutputCurve.model_validate({"key": curve_name, "type": "unknown"}) + basic_curve = OutputCurve.model_construct( + key=curve_name, type="unknown" ) - curves_list[-1].add_warning('base', f"Failed to process curve data: {e}") + basic_curve.add_warning("base", f"Failed to process curve data: {e}") + curves_list.append(basic_curve) curves_collection = cls(curves=curves_list) for error in service_result.errors: - curves_collection.add_warning('base', f"Download warning: {error}") + curves_collection.add_warning("base", f"Download warning: {error}") - curves_collection._merge_submodel_warnings(curves_list, key_attr='key') + curves_collection._merge_submodel_warnings(*curves_list, key_attr="key") return curves_collection diff --git a/src/pyetm/models/scenario.py b/src/pyetm/models/scenario.py index 47c09db..4277906 100644 --- a/src/pyetm/models/scenario.py +++ b/src/pyetm/models/scenario.py @@ -3,7 +3,7 @@ from datetime import datetime from typing import Any, Dict, List, Optional, Set, Union from urllib.parse import urlparse -from pydantic import Field, PrivateAttr, model_validator +from pydantic import Field, PrivateAttr from pyetm.models.inputs import Inputs from pyetm.models.output_curves import OutputCurves from pyetm.clients import BaseClient @@ -165,7 +165,7 @@ def inputs(self) -> Inputs: # merge runner warnings and any item‐level warnings for w in result.errors: self.add_warning("inputs", w) - self._merge_submodel_warnings(coll) + self._merge_submodel_warnings(coll, key_attr="inputs") self._inputs = coll return coll @@ -174,6 +174,7 @@ def set_user_values_from_dataframe(self, dataframe: pd.DataFrame) -> None: """ Extract df to dict, set None/NaN sliders to reset, and call update_inputs. This ensures the dataframe exactly represents the inputs. + # TODO: Add validation for the dataframe structure """ self.update_user_values( dataframe["user"].droplevel("unit").fillna("reset").to_dict() @@ -187,7 +188,11 @@ def update_user_values(self, update_inputs: Dict[str, Any]) -> None: # Update them in the Inputs object, and check validation validity_errors = self.inputs.is_valid_update(update_inputs) if validity_errors: - raise ScenarioError(f"Could not update user values: {validity_errors}") + error_summary = [] + for key, warning_collector in validity_errors.items(): + warnings_list = [w.message for w in warning_collector] + error_summary.append(f"{key}: {warnings_list}") + raise ScenarioError(f"Could not update user values: {error_summary}") result = UpdateInputsRunner.run(BaseClient(), self, update_inputs) @@ -224,7 +229,7 @@ def sortables(self) -> Sortables: coll = Sortables.from_json(result.data) for w in result.errors: self.add_warning("sortables", w) - self._merge_submodel_warnings(coll) + self._merge_submodel_warnings(coll, key_attr="sortables") self._sortables = coll return coll @@ -257,7 +262,11 @@ def update_sortables(self, update_sortables: Dict[str, List[Any]]) -> None: # Validate the updates first validity_errors = self.sortables.is_valid_update(update_sortables) if validity_errors: - raise ScenarioError(f"Could not update sortables: {validity_errors}") + error_summary = [] + for key, warning_collector in validity_errors.items(): + warnings_list = [w.message for w in warning_collector] + error_summary.append(f"{key}: {warnings_list}") + raise ScenarioError(f"Could not update sortables: {error_summary}") # Make individual API calls for each sortable as there is no bulk endpoint for name, order in update_sortables.items(): @@ -314,7 +323,7 @@ def custom_curves(self) -> CustomCurves: coll = CustomCurves.from_json(result.data) for w in result.errors: self.add_warning("custom_curves", w) - self._merge_submodel_warnings(coll) + self._merge_submodel_warnings(coll, key_attr="custom_curves") self._custom_curves = coll return coll @@ -358,6 +367,7 @@ def execute_queries(self): ready collecting all of them """ self._queries.execute(BaseClient(), self) + self._merge_submodel_warnings(self._queries, key_attr="queries") def results(self, columns="future") -> pd.DataFrame: """ @@ -380,3 +390,28 @@ def queries_requested(self): return False return len(self._queries.query_keys()) > 0 + + def show_all_warnings(self) -> None: + """ + Display all warnings from the scenario and its submodels in a organized way. + """ + print(f"=== Warnings for Scenario {self.id} ===") + + # Show scenario-level warnings + if len(self.warnings) > 0: + print("\nScenario warnings:") + self.show_warnings() + + # Show submodel warnings if they exist and are loaded + submodels = [ + ("Inputs", self._inputs), + ("Sortables", self._sortables), + ("Custom Curves", self._custom_curves), + ("Output Curves", self._output_curves), + ("Queries", self._queries), + ] + + for name, submodel in submodels: + if submodel is not None and len(submodel.warnings) > 0: + print(f"\n{name} warnings:") + submodel.show_warnings() diff --git a/src/pyetm/models/scenario_packer.py b/src/pyetm/models/scenario_packer.py index cf5c74d..92b9e44 100644 --- a/src/pyetm/models/scenario_packer.py +++ b/src/pyetm/models/scenario_packer.py @@ -102,7 +102,11 @@ def _to_dataframe(self, columns="", **kwargs) -> pd.DataFrame: class ScenarioPacker(BaseModel): - """Packs one or multiple scenarios for export to dataframes or excel""" + """ + Packs one or multiple scenarios for export to dataframes or excel + + TODO: This class doesn't inherit from Base so it doesn't use the warning system yet - consider this further. + """ # To avoid keeping all in memory, the packer only remembers which scenarios # to pack what info for later diff --git a/src/pyetm/models/sortables.py b/src/pyetm/models/sortables.py index e275df6..9e1c559 100644 --- a/src/pyetm/models/sortables.py +++ b/src/pyetm/models/sortables.py @@ -3,6 +3,7 @@ import pandas as pd from pydantic import field_validator, model_validator +from pyetm.models.warnings import WarningCollector from pyetm.models.base import Base @@ -31,9 +32,9 @@ def name(self): else: return self.type - def is_valid_update(self, new_order: list[Any]) -> dict[str, list[str]]: + def is_valid_update(self, new_order: list[Any]) -> WarningCollector: """ - Returns a dict of validation warnings without updating the current object + Returns a WarningCollector with validation warnings without updating the current object """ new_obj_dict = self.model_dump() new_obj_dict["order"] = new_order @@ -143,12 +144,14 @@ def names(self) -> List[str]: """Get all sortable names (including subtype suffixes)""" return [s.name() for s in self.sortables] - def is_valid_update(self, updates: Dict[str, list[Any]]) -> Dict[str, list[str]]: + def is_valid_update( + self, updates: Dict[str, list[Any]] + ) -> Dict[str, WarningCollector]: """ - Returns a dict of sortable names and their validation warnings + Returns a dict mapping sortable names to their WarningCollectors when errors were found :param updates: Dict mapping sortable names to new orders - :return: Dict mapping sortable names to list of validation warnings + :return: Dict mapping sortable names to WarningCollectors """ warnings = {} @@ -159,16 +162,20 @@ def is_valid_update(self, updates: Dict[str, list[Any]]) -> Dict[str, list[str]] if name in sortable_by_name: sortable = sortable_by_name[name] sortable_warnings = sortable.is_valid_update(new_order) - if sortable_warnings: + if len(sortable_warnings) > 0: warnings[name] = sortable_warnings else: - warnings[name] = ["Sortable does not exist"] + warnings[name] = WarningCollector.with_warning( + name, "Sortable does not exist" + ) # Check for non-existent sortables non_existent_names = set(updates.keys()) - set(self.names()) for name in non_existent_names: if name not in warnings: # Don't overwrite existing warnings - warnings[name] = ["Sortable does not exist"] + warnings[name] = WarningCollector.with_warning( + name, "Sortable does not exist" + ) return warnings @@ -231,12 +238,7 @@ def from_json(cls, data: Dict[str, Any]) -> "Sortables": # Use Base class constructor that handles validation gracefully collection = cls(sortables=items) - # Merge any warnings from individual sortables - for sortable in items: - if hasattr(sortable, "warnings") and sortable.warnings: - for warning_key, warning_list in sortable.warnings.items(): - for warning in warning_list: - collection.add_warning(f"Sortable.{warning_key}", warning) + collection._merge_submodel_warnings(*items, key_attr="type") return collection diff --git a/src/pyetm/models/warnings.py b/src/pyetm/models/warnings.py index 52a3d19..574c9b6 100644 --- a/src/pyetm/models/warnings.py +++ b/src/pyetm/models/warnings.py @@ -35,6 +35,18 @@ class WarningCollector: def __init__(self): self._warnings: List[ModelWarning] = [] + @classmethod + def with_warning( + cls, field: str, message: str, severity: str = "warning" + ) -> "WarningCollector": + """ + Convenience method to create a WarningCollector with a single warning. + E.g: WarningCollector.with_warning("field", "message") + """ + collector = cls() + collector.add(field, message, severity) + return collector + def add( self, field: str, diff --git a/tests/models/conftest.py b/tests/models/conftest.py index abdc464..cf58d3a 100644 --- a/tests/models/conftest.py +++ b/tests/models/conftest.py @@ -155,7 +155,7 @@ def multiple_scenarios(): return scenarios -@pytest.fixture(autouse=True) +@pytest.fixture def patch_sortables_from_json(monkeypatch): dummy = object() monkeypatch.setattr(Sortables, "from_json", staticmethod(lambda data: dummy)) diff --git a/tests/models/test_custom_curves.py b/tests/models/test_custom_curves.py index 8587a29..e96edad 100644 --- a/tests/models/test_custom_curves.py +++ b/tests/models/test_custom_curves.py @@ -60,7 +60,9 @@ def test_custom_curve_retrieve_processing_error(): assert result is None assert len(curve.warnings) > 0 - assert "Failed to process curve data" in curve.warnings[curve.key][0] + key_warnings = curve.warnings.get_by_field(curve.key) + assert len(key_warnings) > 0 + assert "Failed to process curve data" in key_warnings[0].message def test_custom_curve_retrieve_service_error(): @@ -81,7 +83,9 @@ def test_custom_curve_retrieve_service_error(): assert result is None assert len(curve.warnings) > 0 - assert "Failed to retrieve curve: API error" in curve.warnings[curve.key][0] + key_warnings = curve.warnings.get_by_field(curve.key) + assert len(key_warnings) > 0 + assert "Failed to retrieve curve: API error" in key_warnings[0].message def test_custom_curve_retrieve_unexpected_error(): @@ -99,9 +103,10 @@ def test_custom_curve_retrieve_unexpected_error(): assert result is None assert len(curve.warnings) > 0 + key_warnings = curve.warnings.get_by_field(curve.key) + assert len(key_warnings) > 0 assert ( - "Unexpected error retrieving curve: Unexpected" - in curve.warnings[curve.key][0] + "Unexpected error retrieving curve: Unexpected" in key_warnings[0].message ) @@ -112,7 +117,9 @@ def test_custom_curve_contents_not_available(): assert result is None assert len(curve.warnings) > 0 - assert "not available - no file path set" in curve.warnings[curve.key][0] + key_warnings = curve.warnings.get_by_field(curve.key) + assert len(key_warnings) > 0 + assert "not available - no file path set" in key_warnings[0].message def test_custom_curve_contents_file_error(): @@ -124,7 +131,9 @@ def test_custom_curve_contents_file_error(): assert result is None assert len(curve.warnings) > 0 - assert "Failed to read curve file" in curve.warnings[curve.key][0] + key_warnings = curve.warnings.get_by_field(curve.key) + assert len(key_warnings) > 0 + assert "Failed to read curve file" in key_warnings[0].message def test_custom_curve_remove_not_available(): @@ -145,7 +154,9 @@ def test_custom_curve_remove_file_error(): assert result is False assert len(curve.warnings) > 0 - assert "Failed to remove curve file" in curve.warnings[curve.key][0] + key_warnings = curve.warnings.get_by_field(curve.key) + assert len(key_warnings) > 0 + assert "Failed to remove curve file" in key_warnings[0].message def test_custom_curves_from_json_with_invalid_curve(): @@ -162,6 +173,12 @@ def test_custom_curves_from_json_with_invalid_curve(): ): curves = CustomCurves.from_json(data) - assert len(curves.curves) == 1 + assert len(curves.curves) == 2 # 1 valid curve + 1 fallback curve assert len(curves.warnings) > 0 - assert "Skipped invalid curve data" in curves.warnings['CustomCurve(key=valid_curve)'][0] + # The key for the warnings appears to be based on the fallback curve that was created + fallback_curve_key = ( + "CustomCurve(key=unknown).unknown" # This is the actual key generated + ) + fallback_curve_warnings = curves.warnings.get_by_field(fallback_curve_key) + assert len(fallback_curve_warnings) > 0 + assert "Skipped invalid curve data" in fallback_curve_warnings[0].message diff --git a/tests/models/test_output_curves.py b/tests/models/test_output_curves.py index c9fccb7..f43a003 100644 --- a/tests/models/test_output_curves.py +++ b/tests/models/test_output_curves.py @@ -61,7 +61,9 @@ def test_output_curve_retrieve_processing_error(): assert result is None assert len(curve.warnings) > 0 - assert "Failed to process curve data" in curve.warnings['data'][0] + data_warnings = curve.warnings.get_by_field("data") + assert len(data_warnings) > 0 + assert "Failed to process curve data" in data_warnings[0].message def test_output_curve_retrieve_unexpected_error(): @@ -79,9 +81,11 @@ def test_output_curve_retrieve_unexpected_error(): assert result is None assert len(curve.warnings) > 0 + base_warnings = curve.warnings.get_by_field("base") + assert len(base_warnings) > 0 assert ( "Unexpected error retrieving curve test_curve: Unexpected" - in curve.warnings['base'][0] + in base_warnings[0].message ) @@ -92,7 +96,9 @@ def test_output_curve_contents_not_available(): assert result is None assert len(curve.warnings) > 0 - assert "not available - no file path set" in curve.warnings['file_path'][0] + file_path_warnings = curve.warnings.get_by_field("file_path") + assert len(file_path_warnings) > 0 + assert "not available - no file path set" in file_path_warnings[0].message def test_output_curve_contents_file_error(): @@ -104,7 +110,9 @@ def test_output_curve_contents_file_error(): assert result is None assert len(curve.warnings) > 0 - assert "Failed to read curve file" in curve.warnings['file_path'][0] + file_path_warnings = curve.warnings.get_by_field("file_path") + assert len(file_path_warnings) > 0 + assert "Failed to read curve file" in file_path_warnings[0].message def test_output_curve_remove_not_available(): @@ -125,7 +133,9 @@ def test_output_curve_remove_file_error(): assert result is False assert len(curve.warnings) > 0 - assert "Failed to remove curve file" in curve.warnings['file_path'][0] + file_path_warnings = curve.warnings.get_by_field("file_path") + assert len(file_path_warnings) > 0 + assert "Failed to remove curve file" in file_path_warnings[0].message def test_output_curves_from_json_with_invalid_curve(): @@ -142,9 +152,15 @@ def test_output_curves_from_json_with_invalid_curve(): ): curves = OutputCurves.from_json(data) - assert len(curves.curves) == 1 + assert len(curves.curves) == 2 # 1 valid curve + 1 fallback curve assert len(curves.warnings) > 0 - assert "Skipped invalid curve data" in curves.warnings['OutputCurve(key=valid_curve)'][0] + # The key for the warnings appears to be based on the fallback curve that was created + fallback_curve_key = ( + "OutputCurve(key=unknown).unknown" # This is the actual key generated + ) + fallback_curve_warnings = curves.warnings.get_by_field(fallback_curve_key) + assert len(fallback_curve_warnings) > 0 + assert "Skipped invalid curve data" in fallback_curve_warnings[0].message def test_output_curves_from_service_result_failure(): @@ -157,9 +173,11 @@ def test_output_curves_from_service_result_failure(): curves = OutputCurves.from_service_result(failed_result, mock_scenario) assert len(curves.curves) == 0 - assert len(curves.warnings['base']) == 2 - assert "Service error: API error" in curves.warnings['base'][0] - assert "Service error: Network error" in curves.warnings['base'][1] + base_warnings = curves.warnings.get_by_field("base") + assert len(base_warnings) == 2 + warning_messages = [w.message for w in base_warnings] + assert "Service error: API error" in warning_messages + assert "Service error: Network error" in warning_messages def test_output_curves_from_service_result_no_data(): @@ -196,7 +214,9 @@ def test_output_curves_from_service_result_processing_error(): assert curves.curves[0].key == "test_curve" assert curves.curves[0].type == "unknown" assert len(curves.curves[0].warnings) > 0 - assert "Failed to process curve data" in curves.curves[0].warnings['base'][0] + base_warnings = curves.curves[0].warnings.get_by_field("base") + assert len(base_warnings) > 0 + assert "Failed to process curve data" in base_warnings[0].message def test_output_curves_from_service_result_no_caching(): diff --git a/tests/models/test_scenario.py b/tests/models/test_scenario.py index cd54a63..e9d70b5 100644 --- a/tests/models/test_scenario.py +++ b/tests/models/test_scenario.py @@ -1,6 +1,5 @@ from unittest.mock import Mock import pytest -from pyetm.clients.base_client import BaseClient from pyetm.models.inputs import Inputs from pyetm.models.custom_curves import CustomCurves from pyetm.models.scenario import Scenario, ScenarioError @@ -40,7 +39,7 @@ def test_new_scenario_success_minimal(monkeypatch, ok_service_result): assert scenario.area_code == "nl" assert scenario.end_year == 2050 assert scenario.private is False - assert scenario.warnings == {} + assert len(scenario.warnings) == 0 def test_new_scenario_success_with_kwargs(monkeypatch, ok_service_result): @@ -74,7 +73,7 @@ def test_new_scenario_success_with_kwargs(monkeypatch, ok_service_result): assert scenario.private is True assert scenario.start_year == 2019 assert scenario.source == "pyetm" - assert scenario.warnings == {} + assert len(scenario.warnings) == 0 def test_new_scenario_with_warnings(monkeypatch, ok_service_result): @@ -90,7 +89,9 @@ def test_new_scenario_with_warnings(monkeypatch, ok_service_result): scenario = Scenario.new("nl", 2050, invalid_field="should_be_ignored") assert scenario.id == 12347 - assert scenario.warnings["base"] == warnings + base_warnings = scenario.warnings.get_by_field("base") + assert len(base_warnings) == 1 + assert base_warnings[0].message == warnings[0] def test_new_scenario_failure(monkeypatch, fail_service_result): @@ -121,7 +122,7 @@ def test_update_metadata_success(monkeypatch, scenario, ok_service_result): result = scenario.update_metadata(end_year=2050, private=True, custom_field="value") assert result == updated_data - assert scenario.warnings == {} + assert len(scenario.warnings) == 0 def test_update_metadata_with_warnings(monkeypatch, scenario, ok_service_result): @@ -138,7 +139,9 @@ def test_update_metadata_with_warnings(monkeypatch, scenario, ok_service_result) result = scenario.update_metadata(private=True, id=999) assert result == updated_data - assert scenario.warnings["metadata"] == warnings + metadata_warnings = scenario.warnings.get_by_field("metadata") + assert len(metadata_warnings) == 1 + assert metadata_warnings[0].message == warnings[0] def test_update_metadata_failure(monkeypatch, scenario, fail_service_result): @@ -165,7 +168,7 @@ def test_update_metadata_empty_kwargs(monkeypatch, scenario, ok_service_result): result = scenario.update_metadata() assert result == updated_data - assert scenario.warnings == {} + assert len(scenario.warnings) == 0 # ------ Load ------ # @@ -182,7 +185,7 @@ def test_load_success(monkeypatch, full_scenario_metadata, ok_service_result): scenario = Scenario.load(1) for key, val in full_scenario_metadata.items(): assert getattr(scenario, key) == val - assert scenario.warnings == {} + assert len(scenario.warnings) == 0 def test_load_with_warnings(monkeypatch, minimal_scenario_metadata, ok_service_result): @@ -199,7 +202,9 @@ def test_load_with_warnings(monkeypatch, minimal_scenario_metadata, ok_service_r assert scenario.id == 2 assert scenario.end_year == 2040 assert scenario.area_code == "NL" - assert scenario.warnings["metadata"] == warns + metadata_warnings = scenario.warnings.get_by_field("metadata") + assert len(metadata_warnings) == 1 + assert metadata_warnings[0].message == warns[0] def test_load_failure(monkeypatch, fail_service_result): @@ -223,8 +228,11 @@ def test_load_missing_required_field(monkeypatch, ok_service_result): "run", lambda client, stub: ok_service_result(incomplete_data), ) - print(Scenario.load(4).warnings) - assert "Field required" in Scenario.load(4).warnings["end_year"] + + scenario = Scenario.load(4) + end_year_warnings = scenario.warnings.get_by_field("end_year") + assert len(end_year_warnings) > 0 + assert any("Field required" in w.message for w in end_year_warnings) # ------ version ------- # @@ -236,7 +244,10 @@ def test_version_when_no_url_set(scenario): def test_version_when_url_stable(): scenario = Scenario( - id=4, url="https://2025-01.engine.energytransitionmodel.com/api/v3/scenarios/4" + id=4, + area_code="nl", + end_year=2050, + url="https://2025-01.engine.energytransitionmodel.com/api/v3/scenarios/4", ) assert scenario.version == "2025-01" @@ -244,7 +255,10 @@ def test_version_when_url_stable(): def test_version_when_url_latest(): scenario = Scenario( - id=4, url="https://engine.energytransitionmodel.com/api/v3/scenarios/4" + id=4, + area_code="nl", + end_year=2050, + url="https://engine.energytransitionmodel.com/api/v3/scenarios/4", ) assert scenario.version == "latest" @@ -260,7 +274,7 @@ def test_inputs_success(monkeypatch, scenario, inputs_json, ok_service_result): coll = scenario.inputs assert scenario._inputs is coll - assert scenario.warnings == {} + assert len(scenario.warnings) == 0 def test_inputs_with_warnings(monkeypatch, inputs_json, scenario, ok_service_result): @@ -275,7 +289,9 @@ def test_inputs_with_warnings(monkeypatch, inputs_json, scenario, ok_service_res coll = scenario.inputs assert coll assert next(iter(coll)).key in inputs_json.keys() - assert scenario.warnings["inputs"] == warns + inputs_warnings = scenario.warnings.get_by_field("inputs") + assert len(inputs_warnings) == 1 + assert inputs_warnings[0].message == warns[0] def test_inputs_failure(monkeypatch, scenario, fail_service_result): @@ -317,8 +333,7 @@ def test_update_inputs_success(monkeypatch, inputs_json, scenario, ok_service_re # Should not return anything (returns None) assert result is None - # No warnings - assert scenario.warnings == {} + assert len(scenario.warnings) == 0 # Inputs were updated assert targeted_input.user == 42.5 @@ -351,7 +366,7 @@ def test_update_inputs_single_input( # Cache should be invalidated assert targeted_input.user == new_value - assert scenario.warnings == {} + assert len(scenario.warnings) == 0 def test_update_inputs_with_warnings( @@ -372,7 +387,7 @@ def test_update_inputs_with_warnings( scenario.update_user_values({"investment_costs_co2_ccs": 42.5}) # This is not likely to occur so we don't log them - assert scenario.warnings == {} + assert len(scenario.warnings) == 0 assert scenario._inputs @@ -405,7 +420,7 @@ def test_update_inputs_empty_dict( ) scenario.update_user_values({}) - assert scenario.warnings == {} + assert len(scenario.warnings) == 0 assert not scenario.user_values() @@ -435,13 +450,14 @@ def mock_runner_run(client, scen, inputs): try: scenario.update_user_values({"investment_costs_co2_ccs": 42}) - # Should have both existing and new warnings [for now we ignore new warnings] - expected_warnings = [ - "Existing warning 1", - "Existing warning 2", - # "New warning from update", - ] - assert scenario.warnings["queries"] == expected_warnings + queries_warnings = scenario.warnings.get_by_field("queries") + expected_messages = ["Existing warning 1", "Existing warning 2"] + + assert len(queries_warnings) == 2 + warning_messages = [w.message for w in queries_warnings] + for expected_msg in expected_messages: + assert expected_msg in warning_messages + finally: # Restore original method pyetm.services.scenario_runners.update_inputs.UpdateInputsRunner.run = ( @@ -471,7 +487,7 @@ def test_sortables_success( coll = scenario.sortables assert coll is patch_sortables_from_json assert scenario._sortables is coll - assert scenario.warnings == {} + assert len(scenario.warnings) == 0 def test_sortables_with_warnings( @@ -542,10 +558,15 @@ def test_update_sortables(monkeypatch, scenario, ok_service_result): def test_update_sortables_validation_error(scenario): + from pyetm.models.warnings import WarningCollector + updates = {"nonexistent": [1, 2, 3]} mock_sortables = Mock() - mock_sortables.is_valid_update.return_value = {"nonexistent": ["error"]} + error_collector = WarningCollector.with_warning( + "nonexistent", "Sortable does not exist" + ) + mock_sortables.is_valid_update.return_value = {"nonexistent": error_collector} scenario._sortables = mock_sortables with pytest.raises(ScenarioError): @@ -597,7 +618,7 @@ def test_custom_curves_success( coll = scenario.custom_curves assert coll is patch_custom_curves_from_json assert scenario._custom_curves is coll - assert scenario.warnings == {} + assert len(scenario.warnings) == 0 def test_custom_curves_with_warnings( @@ -614,7 +635,9 @@ def test_custom_curves_with_warnings( coll = scenario.custom_curves assert coll is patch_custom_curves_from_json - assert scenario.warnings["custom_curves"] == warns + custom_curves_warnings = scenario.warnings.get_by_field("custom_curves") + assert len(custom_curves_warnings) == 1 + assert custom_curves_warnings[0].message == warns[0] def test_custom_curves_failure(monkeypatch, scenario, fail_service_result): @@ -633,3 +656,38 @@ def test_to_dataframe(scenario): dataframe = scenario.to_dataframe() assert dataframe[scenario.id]["end_year"] == 2050 + + +# ------ Warnings tests ------ # + + +def test_scenario_warning_system_integration(scenario): + """Test that the scenario properly integrates with the new warning system""" + # Add some warnings + scenario.add_warning("test_field", "Test warning message") + scenario.add_warning("test_field", "Another warning") + scenario.add_warning("other_field", "Different field warning", "error") + + # Check warning collector functionality + assert len(scenario.warnings) == 3 + assert scenario.warnings.has_warnings("test_field") + assert scenario.warnings.has_warnings("other_field") + + test_warnings = scenario.warnings.get_by_field("test_field") + assert len(test_warnings) == 2 + + other_warnings = scenario.warnings.get_by_field("other_field") + assert len(other_warnings) == 1 + assert other_warnings[0].severity == "error" + + +def test_scenario_show_all_warnings(scenario, capsys): + """Test the show_all_warnings method""" + scenario.add_warning("test_field", "Test warning") + + scenario.show_all_warnings() + + captured = capsys.readouterr() + assert f"Warnings for Scenario {scenario.id}" in captured.out + assert "Scenario warnings:" in captured.out + assert "Test warning" in captured.out diff --git a/tests/models/test_sortable.py b/tests/models/test_sortable.py deleted file mode 100644 index da15c87..0000000 --- a/tests/models/test_sortable.py +++ /dev/null @@ -1,173 +0,0 @@ -import pytest -from pyetm.models.sortables import Sortable - - -@pytest.mark.parametrize( - "payload, expected_type, expected_order, expected_subtype", - [ - # flat list → one Sortable, no subtype - ( - ("forecast_storage", ["a", "b", "c"]), - "forecast_storage", - ["a", "b", "c"], - None, - ), - (("hydrogen_supply", ["x", "y"]), "hydrogen_supply", ["x", "y"], None), - ], -) -def test_from_json_with_list(payload, expected_type, expected_order, expected_subtype): - result = list(Sortable.from_json(payload)) - assert isinstance(result, list) and len(result) == 1 - sortable = result[0] - assert sortable.type == expected_type - assert sortable.order == expected_order - assert sortable.subtype is expected_subtype - - -def test_from_json_with_list_heat_network_generates_warning(): - """heat_network without subtype should generate a validation warning""" - payload = ("heat_network", ["x", "y"]) - result = list(Sortable.from_json(payload)) - - assert len(result) == 1 - sortable = result[0] - assert sortable.type == "heat_network" - assert sortable.order == ["x", "y"] - assert sortable.subtype is None # No subtype provided - - # Should have validation warning about missing subtype - assert len(sortable.warnings) > 0 - all_warnings = [] - for warning_list in sortable.warnings.values(): - all_warnings.extend(warning_list) - warning_text = " ".join(all_warnings) - assert "heat_network type requires a subtype" in warning_text - - -def test_from_json_with_dict(): - # nested dict → one Sortable per subtype - payload = ("heat_network", {"lt": [1, 2], "mt": [3, 4], "ht": []}) - result = list(Sortable.from_json(payload)) - - assert isinstance(result, list) and len(result) == 3 - - got = {(s.type, s.subtype, tuple(s.order)) for s in result} - expected = { - ("heat_network", "lt", (1, 2)), - ("heat_network", "mt", (3, 4)), - ("heat_network", "ht", ()), - } - assert got == expected - - # These should not have warnings since they have proper subtypes - for sortable in result: - assert len(sortable.warnings) == 0 - - -def test_validation_duplicate_order_items(): - """Test that duplicate items in order generate warnings""" - payload = ("forecast_storage", [1, 2, 2, 3]) - result = list(Sortable.from_json(payload)) - - assert len(result) == 1 - sortable = result[0] - assert sortable.type == "forecast_storage" - assert sortable.order == [1, 2, 2, 3] - - # Should have validation warning about duplicates - assert len(sortable.warnings) > 0 - all_warnings = [] - for warning_list in sortable.warnings.values(): - all_warnings.extend(warning_list) - warning_text = " ".join(all_warnings) - assert "duplicate" in warning_text.lower() - - -def test_validation_order_too_long(): - """Test that orders with too many items generate warnings""" - long_order = list(range(15)) # More than 10 items - payload = ("forecast_storage", long_order) - result = list(Sortable.from_json(payload)) - - assert len(result) == 1 - sortable = result[0] - assert sortable.type == "forecast_storage" - assert sortable.order == long_order - - # Should have validation warning about length - assert len(sortable.warnings) > 0 - all_warnings = [] - for warning_list in sortable.warnings.values(): - all_warnings.extend(warning_list) - warning_text = " ".join(all_warnings) - assert "more than 10 items" in warning_text - - -@pytest.mark.parametrize( - "payload", - [ - ("forecast_storage", None), - ("heat_network", 123), - ("foo", object()), - ], -) -def test_from_json_creates_warning_on_invalid(payload): - """Test that invalid payloads create sortables with warnings instead of raising exceptions""" - result = list(Sortable.from_json(payload)) - - # Should always yield exactly one sortable - assert len(result) == 1 - sortable = result[0] - - # Should have the correct type and empty order - assert sortable.type == payload[0] - assert sortable.order == [] - assert sortable.subtype is None - - assert hasattr(sortable, "warnings") - assert len(sortable.warnings) > 0 - all_warnings = [] - for warning_list in sortable.warnings.values(): - all_warnings.extend(warning_list) - warning_text = " ".join(all_warnings) - # Could be either unexpected payload warning or validation warning - assert ( - "Unexpected payload" in warning_text - or "heat_network type requires a subtype" in warning_text - ) - assert str(payload[1]) in warning_text - - -def test_is_valid_update(): - """Test the is_valid_update method""" - sortable = Sortable(type="forecast_storage", order=[1, 2, 3]) - - # Valid update - no warnings - warnings = sortable.is_valid_update([4, 5, 6]) - assert warnings == {} - - # Invalid update - duplicates - warnings = sortable.is_valid_update([1, 2, 2]) - assert len(warnings) > 0 - all_warnings = [] - for warning_list in warnings.values(): - all_warnings.extend(warning_list) - warning_text = " ".join(all_warnings) - assert "duplicate" in warning_text.lower() - - # Invalid update - too long - warnings = sortable.is_valid_update(list(range(15))) - assert len(warnings) > 0 - all_warnings = [] - for warning_list in warnings.values(): - all_warnings.extend(warning_list) - warning_text = " ".join(all_warnings) - assert "more than 10 items" in warning_text - - -def test_name_method(): - sortable1 = Sortable(type="forecast_storage", order=[1, 2]) - assert sortable1.name() == "forecast_storage" - - sortable2 = Sortable(type="heat_network", subtype="lt", order=[3, 4]) - assert sortable2.name() == "heat_network_lt" diff --git a/tests/models/test_sortables.py b/tests/models/test_sortables.py index 13b85ae..21f399f 100644 --- a/tests/models/test_sortables.py +++ b/tests/models/test_sortables.py @@ -1,3 +1,4 @@ +import pytest from pyetm.models.sortables import Sortable, Sortables @@ -61,7 +62,7 @@ def test_is_valid_update(): # Valid updates valid_updates = {"forecast_storage": ["x", "y"], "heat_network_lt": ["z"]} warnings = coll.is_valid_update(valid_updates) - assert warnings == {} + assert len(warnings) == 0 # Invalid updates - non-existent sortable invalid_updates = {"nonexistent": ["a", "b"], "forecast_storage": ["valid"]} @@ -98,9 +99,7 @@ def test_validation_duplicate_sortable_names(): coll = Sortables(sortables=sortables_list) assert len(coll.warnings) > 0 # Flatten all warning messages to search - all_warnings = [] - for warning_list in coll.warnings.values(): - all_warnings.extend(warning_list) + all_warnings = [w.message for w in coll.warnings] warning_text = " ".join(all_warnings) assert "duplicate" in warning_text.lower() @@ -120,3 +119,162 @@ def test_collection_merges_individual_warnings(): coll = Sortables.from_json(data_with_issues) assert len(coll.warnings) > 0 + + +@pytest.mark.parametrize( + "payload, expected_type, expected_order, expected_subtype", + [ + # flat list → one Sortable, no subtype + ( + ("forecast_storage", ["a", "b", "c"]), + "forecast_storage", + ["a", "b", "c"], + None, + ), + (("hydrogen_supply", ["x", "y"]), "hydrogen_supply", ["x", "y"], None), + ], +) +def test_from_json_with_list(payload, expected_type, expected_order, expected_subtype): + result = list(Sortable.from_json(payload)) + assert isinstance(result, list) and len(result) == 1 + sortable = result[0] + assert sortable.type == expected_type + assert sortable.order == expected_order + assert sortable.subtype is expected_subtype + + +def test_from_json_with_list_heat_network_generates_warning(): + """heat_network without subtype should generate a validation warning""" + payload = ("heat_network", ["x", "y"]) + result = list(Sortable.from_json(payload)) + + assert len(result) == 1 + sortable = result[0] + assert sortable.type == "heat_network" + assert sortable.order == ["x", "y"] + assert sortable.subtype is None # No subtype provided + + # Should have validation warning about missing subtype + assert len(sortable.warnings) > 0 + all_warnings = [w.message for w in sortable.warnings] + warning_text = " ".join(all_warnings) + assert "heat_network type requires a subtype" in warning_text + + +def test_from_json_with_dict(): + # nested dict → one Sortable per subtype + payload = ("heat_network", {"lt": [1, 2], "mt": [3, 4], "ht": []}) + result = list(Sortable.from_json(payload)) + + assert isinstance(result, list) and len(result) == 3 + + got = {(s.type, s.subtype, tuple(s.order)) for s in result} + expected = { + ("heat_network", "lt", (1, 2)), + ("heat_network", "mt", (3, 4)), + ("heat_network", "ht", ()), + } + assert got == expected + + # These should not have warnings since they have proper subtypes + for sortable in result: + assert len(sortable.warnings) == 0 + + +def test_validation_duplicate_order_items(): + """Test that duplicate items in order generate warnings""" + payload = ("forecast_storage", [1, 2, 2, 3]) + result = list(Sortable.from_json(payload)) + + assert len(result) == 1 + sortable = result[0] + assert sortable.type == "forecast_storage" + assert sortable.order == [1, 2, 2, 3] + + # Should have validation warning about duplicates + assert len(sortable.warnings) > 0 + all_warnings = [w.message for w in sortable.warnings] + warning_text = " ".join(all_warnings) + assert "duplicate" in warning_text.lower() + + +def test_validation_order_too_long(): + """Test that orders with too many items generate warnings""" + long_order = list(range(15)) # More than 10 items + payload = ("forecast_storage", long_order) + result = list(Sortable.from_json(payload)) + + assert len(result) == 1 + sortable = result[0] + assert sortable.type == "forecast_storage" + assert sortable.order == long_order + + # Should have validation warning about length + assert len(sortable.warnings) > 0 + all_warnings = [w.message for w in sortable.warnings] + warning_text = " ".join(all_warnings) + assert "more than 10 items" in warning_text + + +@pytest.mark.parametrize( + "payload", + [ + ("forecast_storage", None), + ("heat_network", 123), + ("foo", object()), + ], +) +def test_from_json_creates_warning_on_invalid(payload): + """Test that invalid payloads create sortables with warnings instead of raising exceptions""" + result = list(Sortable.from_json(payload)) + + # Should always yield exactly one sortable + assert len(result) == 1 + sortable = result[0] + + # Should have the correct type and empty order + assert sortable.type == payload[0] + assert sortable.order == [] + assert sortable.subtype is None + + assert hasattr(sortable, "warnings") + assert len(sortable.warnings) > 0 + all_warnings = [w.message for w in sortable.warnings] + warning_text = " ".join(all_warnings) + # Could be either unexpected payload warning or validation warning + assert ( + "Unexpected payload" in warning_text + or "heat_network type requires a subtype" in warning_text + ) + assert str(payload[1]) in warning_text + + +def test_sortable_is_valid_update(): + """Test the is_valid_update method""" + sortable = Sortable(type="forecast_storage", order=[1, 2, 3]) + + # Valid update - no warnings + warnings = sortable.is_valid_update([4, 5, 6]) + assert len(warnings) == 0 + + # Invalid update - duplicates + warnings = sortable.is_valid_update([1, 2, 2]) + assert len(warnings) > 0 + all_warnings = [w.message for w in warnings] + warning_text = " ".join(all_warnings) + assert "duplicate" in warning_text.lower() + + # Invalid update - too long + warnings = sortable.is_valid_update(list(range(15))) + assert len(warnings) > 0 + all_warnings = [w.message for w in warnings] + warning_text = " ".join(all_warnings) + assert "more than 10 items" in warning_text + + +def test_name_method(): + sortable1 = Sortable(type="forecast_storage", order=[1, 2]) + assert sortable1.name() == "forecast_storage" + + sortable2 = Sortable(type="heat_network", subtype="lt", order=[3, 4]) + assert sortable2.name() == "heat_network_lt" From 0f06ad28ff68a6e16365b59493d9b3486b058c8e Mon Sep 17 00:00:00 2001 From: louispt1 <81332401+louispt1@users.noreply.github.com> Date: Thu, 7 Aug 2025 09:46:37 +0200 Subject: [PATCH 08/19] Custom curves upload, validation and to/from df (#68) * Custom curves to and from dataframe * Upload custom curves runner, scenario methods and validation on the model * Custom curves: tests for runner, scenario and validation --- .../agriculture_electricity_curve.csv | 8760 +++++++++++++++++ .../electric_vehicle_profile_5_curve.csv | 8760 +++++++++++++++++ .../interconnector_8_price_curve.csv | 8760 +++++++++++++++++ examples/excel_to_scenario.ipynb | 196 + src/pyetm/models/base.py | 38 +- src/pyetm/models/custom_curves.py | 194 +- src/pyetm/models/scenario.py | 37 +- src/pyetm/models/warnings.py | 20 - .../scenario_runners/update_custom_curves.py | 82 + tests/models/test_base.py | 140 +- tests/models/test_custom_curves.py | 482 + tests/models/test_scenario.py | 228 +- tests/models/test_warnings.py | 13 - tests/services/conftest.py | 1 - .../test_update_custom_curves.py | 302 + .../scenario_runners/test_update_sortables.py | 445 + 16 files changed, 28347 insertions(+), 111 deletions(-) create mode 100644 examples/curve_examples/agriculture_electricity_curve.csv create mode 100644 examples/curve_examples/electric_vehicle_profile_5_curve.csv create mode 100644 examples/curve_examples/interconnector_8_price_curve.csv create mode 100644 examples/excel_to_scenario.ipynb create mode 100644 src/pyetm/services/scenario_runners/update_custom_curves.py create mode 100644 tests/services/scenario_runners/test_update_custom_curves.py create mode 100644 tests/services/scenario_runners/test_update_sortables.py diff --git a/examples/curve_examples/agriculture_electricity_curve.csv b/examples/curve_examples/agriculture_electricity_curve.csv new file mode 100644 index 0000000..8c5c7b9 --- /dev/null +++ b/examples/curve_examples/agriculture_electricity_curve.csv @@ -0,0 +1,8760 @@ +3.083099492094933e-08 +3.2365569328779384e-08 +3.1947049035734825e-08 +3.2365569328779384e-08 +3.278408962182394e-08 +3.292359638617213e-08 +3.3063103150520315e-08 +3.390014373660944e-08 +3.390014373660944e-08 +3.2365569328779384e-08 +3.348162344356488e-08 +3.362113020791307e-08 +3.348162344356488e-08 +3.320260991486851e-08 +3.278408962182394e-08 +3.348162344356488e-08 +3.417915726530581e-08 +3.613225196618043e-08 +3.5713731673135874e-08 +3.557422490878769e-08 +3.5713731673135874e-08 +3.627175873052862e-08 +3.5713731673135874e-08 +3.557422490878769e-08 +3.180754227138664e-08 +3.2644582857475756e-08 +3.22260625644312e-08 +3.22260625644312e-08 +3.250507609312757e-08 +3.3342116679216694e-08 +3.724830608096593e-08 +3.027296786355658e-08 +4.199153606880429e-08 +4.478167135576803e-08 +4.631624576359808e-08 +4.687427282099083e-08 +4.366561724098254e-08 +4.492117812011622e-08 +4.492117812011622e-08 +4.310759018358978e-08 +3.8085346667055053e-08 +3.027296786355658e-08 +2.6227271697459155e-08 +2.5808751404414597e-08 +2.4971710818325472e-08 +2.2739602588754482e-08 +2.0367987594835303e-08 +3.487669108704675e-08 +3.2644582857475756e-08 +3.3063103150520315e-08 +3.22260625644312e-08 +3.1947049035734825e-08 +3.292359638617213e-08 +3.417915726530581e-08 +3.892238725314418e-08 +3.22260625644312e-08 +4.575821870620534e-08 +4.840884722882089e-08 +4.93853945792582e-08 +5.008292840099913e-08 +4.6595259292294455e-08 +4.8548353993169076e-08 +4.812983370012452e-08 +4.5897725470553524e-08 +3.961992107488511e-08 +3.083099492094933e-08 +2.6645791990503717e-08 +2.5808751404414597e-08 +2.4413683760932724e-08 +2.2600095824406296e-08 +2.0367987594835303e-08 +3.5295211380091315e-08 +3.2644582857475756e-08 +3.3342116679216694e-08 +3.250507609312757e-08 +3.292359638617213e-08 +3.4039650500957626e-08 +3.5992745201832246e-08 +4.115449548271517e-08 +3.320260991486851e-08 +4.729279311403539e-08 +5.008292840099913e-08 +5.0919968987088255e-08 +5.175700957317738e-08 +4.910638105056182e-08 +5.0919968987088255e-08 +5.147799604448101e-08 +4.966440810795457e-08 +4.394463076967891e-08 +3.5016197851394936e-08 +3.0970501685297515e-08 +2.9993954334860204e-08 +2.8877900220074708e-08 +2.6924805519200093e-08 +2.385565670353998e-08 +4.031745489662604e-08 +3.6550772259225e-08 +3.696929255226956e-08 +3.627175873052862e-08 +3.613225196618043e-08 +3.5713731673135874e-08 +3.627175873052862e-08 +4.045696166097423e-08 +3.069148815660114e-08 +4.1852029304456096e-08 +4.408413753402709e-08 +4.492117812011622e-08 +4.520019164881259e-08 +4.213104283315248e-08 +4.2689069890545226e-08 +4.1712522540107916e-08 +3.892238725314418e-08 +3.417915726530581e-08 +2.9017406984422894e-08 +2.5250724347021848e-08 +2.4274176996584538e-08 +2.3297629646147227e-08 +2.1902562002665358e-08 +2.008897406613893e-08 +3.459767755835038e-08 +3.208655580008301e-08 +3.2644582857475756e-08 +3.152852874269026e-08 +3.152852874269026e-08 +3.1947049035734825e-08 +3.2365569328779384e-08 +3.278408962182394e-08 +3.54347181444395e-08 +3.948041431053692e-08 +4.1712522540107916e-08 +4.408413753402709e-08 +4.478167135576803e-08 +4.3526110476634344e-08 +4.2410056361848854e-08 +4.213104283315248e-08 +4.101498871836698e-08 +4.0735975189670606e-08 +3.9759427839233295e-08 +3.822485343140324e-08 +3.7387812845314116e-08 +3.682978578792137e-08 +3.5713731673135874e-08 +3.417915726530581e-08 +3.362113020791307e-08 +3.124951521399389e-08 +3.1947049035734825e-08 +3.069148815660114e-08 +3.0970501685297515e-08 +3.11100084496457e-08 +3.152852874269026e-08 +3.1389021978342073e-08 +3.208655580008301e-08 +3.208655580008301e-08 +3.1947049035734825e-08 +3.320260991486851e-08 +3.4039650500957626e-08 +3.417915726530581e-08 +3.4318664029654005e-08 +3.417915726530581e-08 +3.417915726530581e-08 +3.417915726530581e-08 +3.6550772259225e-08 +3.627175873052862e-08 +3.557422490878769e-08 +3.515570461574312e-08 +3.4737184322698563e-08 +3.390014373660944e-08 +3.3342116679216694e-08 +3.180754227138664e-08 +3.250507609312757e-08 +3.124951521399389e-08 +3.180754227138664e-08 +3.208655580008301e-08 +3.376063697226125e-08 +3.948041431053692e-08 +3.278408962182394e-08 +4.631624576359808e-08 +4.9245887814910014e-08 +5.036194192969551e-08 +5.1338489280132814e-08 +4.785082017142814e-08 +4.966440810795457e-08 +4.9943421636650945e-08 +4.771131340707996e-08 +4.0735975189670606e-08 +3.1389021978342073e-08 +2.7482832576592838e-08 +2.6645791990503717e-08 +2.5250724347021848e-08 +2.3018616117450855e-08 +2.008897406613893e-08 +3.515570461574312e-08 +3.250507609312757e-08 +3.348162344356488e-08 +3.250507609312757e-08 +3.278408962182394e-08 +3.3063103150520315e-08 +3.459767755835038e-08 +3.9759427839233295e-08 +3.348162344356488e-08 +4.7432299878383586e-08 +5.064095545839188e-08 +5.203602310187375e-08 +5.273355692361469e-08 +4.896687428621364e-08 +5.064095545839188e-08 +5.064095545839188e-08 +4.82693404644727e-08 +4.1433509011411543e-08 +3.1947049035734825e-08 +2.7482832576592838e-08 +2.6785298754851907e-08 +2.5808751404414597e-08 +2.3297629646147227e-08 +2.0228480830487117e-08 +3.4318664029654005e-08 +3.22260625644312e-08 +3.2644582857475756e-08 +3.1668035507038446e-08 +3.1668035507038446e-08 +3.2644582857475756e-08 +3.4039650500957626e-08 +3.961992107488511e-08 +3.376063697226125e-08 +4.799032693577633e-08 +5.0919968987088255e-08 +5.217552986622194e-08 +5.315207721665925e-08 +4.9524901343606386e-08 +5.1338489280132814e-08 +5.119898251578463e-08 +4.896687428621364e-08 +4.213104283315248e-08 +3.2644582857475756e-08 +2.845937992703015e-08 +2.7482832576592838e-08 +2.5948258168762783e-08 +2.413467023223635e-08 +2.14840417096208e-08 +3.710879931661774e-08 +3.459767755835038e-08 +3.487669108704675e-08 +3.376063697226125e-08 +3.417915726530581e-08 +3.487669108704675e-08 +3.6550772259225e-08 +4.2549563126197034e-08 +3.515570461574312e-08 +4.980391487230276e-08 +5.273355692361469e-08 +5.3849611038400187e-08 +5.48261583888375e-08 +5.147799604448101e-08 +5.343109074535562e-08 +5.3989117802748366e-08 +5.1338489280132814e-08 +4.464216459141985e-08 +3.515570461574312e-08 +3.11100084496457e-08 +2.9993954334860204e-08 +2.873839345572652e-08 +2.650628522615553e-08 +2.315812288179904e-08 +3.948041431053692e-08 +3.710879931661774e-08 +3.7666826374010495e-08 +3.682978578792137e-08 +3.6690279023573184e-08 +3.6550772259225e-08 +3.7387812845314116e-08 +4.29680834192416e-08 +3.459767755835038e-08 +4.8548353993169076e-08 +5.161750280882919e-08 +5.2873063687962876e-08 +5.315207721665925e-08 +4.93853945792582e-08 +5.008292840099913e-08 +4.896687428621364e-08 +4.50606848844644e-08 +3.86433737244478e-08 +3.180754227138664e-08 +2.7482832576592838e-08 +2.650628522615553e-08 +2.5390231111370035e-08 +2.3716149939191793e-08 +2.14840417096208e-08 +3.724830608096593e-08 +3.4737184322698563e-08 +3.5016197851394936e-08 +3.376063697226125e-08 +3.4039650500957626e-08 +3.417915726530581e-08 +3.459767755835038e-08 +3.54347181444395e-08 +3.8364360195751426e-08 +4.366561724098254e-08 +4.687427282099083e-08 +4.93853945792582e-08 +4.9943421636650945e-08 +4.785082017142814e-08 +4.673476605664265e-08 +4.603723223490171e-08 +4.50606848844644e-08 +4.408413753402709e-08 +4.2828576654893406e-08 +4.087548195401879e-08 +4.045696166097423e-08 +3.989893460358149e-08 +3.86433737244478e-08 +3.7666826374010495e-08 +3.710879931661774e-08 +3.515570461574312e-08 +3.5713731673135874e-08 +3.445817079400219e-08 +3.445817079400219e-08 +3.445817079400219e-08 +3.5016197851394936e-08 +3.4318664029654005e-08 +3.487669108704675e-08 +3.487669108704675e-08 +3.5016197851394936e-08 +3.613225196618043e-08 +3.682978578792137e-08 +3.710879931661774e-08 +3.724830608096593e-08 +3.710879931661774e-08 +3.627175873052862e-08 +3.585323843748406e-08 +3.75273196096623e-08 +3.696929255226956e-08 +3.627175873052862e-08 +3.5713731673135874e-08 +3.487669108704675e-08 +3.390014373660944e-08 +3.362113020791307e-08 +3.208655580008301e-08 +3.292359638617213e-08 +3.152852874269026e-08 +3.208655580008301e-08 +3.292359638617213e-08 +3.459767755835038e-08 +4.0735975189670606e-08 +3.445817079400219e-08 +4.896687428621364e-08 +5.1896516337525566e-08 +5.343109074535562e-08 +5.440763809579293e-08 +5.078046222274007e-08 +5.245454339491831e-08 +5.273355692361469e-08 +5.0222435165347324e-08 +4.2549563126197034e-08 +3.250507609312757e-08 +2.8877900220074708e-08 +2.804085963398559e-08 +2.6785298754851907e-08 +2.4413683760932724e-08 +2.0926014652228048e-08 +3.627175873052862e-08 +3.4039650500957626e-08 +3.54347181444395e-08 +3.487669108704675e-08 +3.5016197851394936e-08 +3.5295211380091315e-08 +3.710879931661774e-08 +4.29680834192416e-08 +3.557422490878769e-08 +5.036194192969551e-08 +5.343109074535562e-08 +5.48261583888375e-08 +5.5663198974926615e-08 +5.175700957317738e-08 +5.3849611038400187e-08 +5.3710104274051994e-08 +5.0919968987088255e-08 +4.310759018358978e-08 +3.3342116679216694e-08 +2.9017406984422894e-08 +2.8319873162681962e-08 +2.706431228354828e-08 +2.4274176996584538e-08 +2.0647001123531675e-08 +3.5016197851394936e-08 +3.278408962182394e-08 +3.3342116679216694e-08 +3.22260625644312e-08 +3.250507609312757e-08 +3.292359638617213e-08 +3.459767755835038e-08 +4.045696166097423e-08 +3.459767755835038e-08 +4.896687428621364e-08 +5.1896516337525566e-08 +5.301257045231106e-08 +5.4268131331444745e-08 +5.0222435165347324e-08 +5.1896516337525566e-08 +5.2315036630570125e-08 +5.0222435165347324e-08 +4.324709694793797e-08 +3.376063697226125e-08 +2.9575434041815645e-08 +2.8598886691378335e-08 +2.6924805519200093e-08 +2.46926972896291e-08 +2.14840417096208e-08 +3.682978578792137e-08 +3.459767755835038e-08 +3.4737184322698563e-08 +3.362113020791307e-08 +3.390014373660944e-08 +3.417915726530581e-08 +3.5713731673135874e-08 +4.227054959750066e-08 +3.585323843748406e-08 +5.036194192969551e-08 +5.343109074535562e-08 +5.4686651624489304e-08 +5.5663198974926615e-08 +5.1896516337525566e-08 +5.3570597509703814e-08 +5.3570597509703814e-08 +5.078046222274007e-08 +4.3386603712286164e-08 +3.390014373660944e-08 +3.027296786355658e-08 +2.943592727746746e-08 +2.8180366398333776e-08 +2.552973787571822e-08 +2.1902562002665358e-08 +3.696929255226956e-08 +3.487669108704675e-08 +3.54347181444395e-08 +3.459767755835038e-08 +3.487669108704675e-08 +3.515570461574312e-08 +3.627175873052862e-08 +4.2549563126197034e-08 +3.515570461574312e-08 +4.910638105056182e-08 +5.203602310187375e-08 +5.343109074535562e-08 +5.3849611038400187e-08 +5.008292840099913e-08 +5.064095545839188e-08 +4.966440810795457e-08 +4.5897725470553524e-08 +3.892238725314418e-08 +3.1947049035734825e-08 +2.7901352869637404e-08 +2.6785298754851907e-08 +2.552973787571822e-08 +2.385565670353998e-08 +2.1623548473968986e-08 +3.7387812845314116e-08 +3.459767755835038e-08 +3.459767755835038e-08 +3.348162344356488e-08 +3.3342116679216694e-08 +3.320260991486851e-08 +3.376063697226125e-08 +3.487669108704675e-08 +3.850386696009961e-08 +4.3805124005330716e-08 +4.701377958533902e-08 +4.966440810795457e-08 +5.008292840099913e-08 +4.82693404644727e-08 +4.701377958533902e-08 +4.61767389992499e-08 +4.520019164881259e-08 +4.366561724098254e-08 +4.2549563126197034e-08 +4.059646842532242e-08 +4.045696166097423e-08 +3.948041431053692e-08 +3.86433737244478e-08 +3.7666826374010495e-08 +3.6690279023573184e-08 +3.515570461574312e-08 +3.557422490878769e-08 +3.417915726530581e-08 +3.4039650500957626e-08 +3.4039650500957626e-08 +3.4737184322698563e-08 +3.4039650500957626e-08 +3.459767755835038e-08 +3.4737184322698563e-08 +3.487669108704675e-08 +3.6411265494876805e-08 +3.7666826374010495e-08 +3.8782880488795985e-08 +3.906189401749236e-08 +3.920140078184055e-08 +3.822485343140324e-08 +3.7387812845314116e-08 +3.8364360195751426e-08 +3.7666826374010495e-08 +3.6690279023573184e-08 +3.585323843748406e-08 +3.5295211380091315e-08 +3.4039650500957626e-08 +3.362113020791307e-08 +3.1947049035734825e-08 +3.278408962182394e-08 +3.1947049035734825e-08 +3.180754227138664e-08 +3.278408962182394e-08 +3.4318664029654005e-08 +4.059646842532242e-08 +3.417915726530581e-08 +4.868786075751727e-08 +5.175700957317738e-08 +5.3291583981007435e-08 +5.4268131331444745e-08 +5.0501448694043697e-08 +5.245454339491831e-08 +5.203602310187375e-08 +4.966440810795457e-08 +4.213104283315248e-08 +3.22260625644312e-08 +2.9156913748771087e-08 +2.8319873162681962e-08 +2.6785298754851907e-08 +2.413467023223635e-08 +2.0647001123531675e-08 +3.54347181444395e-08 +3.320260991486851e-08 +3.4039650500957626e-08 +3.376063697226125e-08 +3.348162344356488e-08 +3.390014373660944e-08 +3.5713731673135874e-08 +4.213104283315248e-08 +3.557422490878769e-08 +5.036194192969551e-08 +5.3570597509703814e-08 +5.510517191753387e-08 +5.580270573927481e-08 +5.217552986622194e-08 +5.4268131331444745e-08 +5.412862456709656e-08 +5.147799604448101e-08 +4.366561724098254e-08 +3.4318664029654005e-08 +3.069148815660114e-08 +3.027296786355658e-08 +2.873839345572652e-08 +2.5390231111370035e-08 +2.1344534945272613e-08 +3.5992745201832246e-08 +3.4039650500957626e-08 +3.445817079400219e-08 +3.348162344356488e-08 +3.376063697226125e-08 +3.390014373660944e-08 +3.5016197851394936e-08 +4.087548195401879e-08 +3.487669108704675e-08 +4.9245887814910014e-08 +5.217552986622194e-08 +5.3849611038400187e-08 +5.4686651624489304e-08 +5.0222435165347324e-08 +5.1896516337525566e-08 +5.245454339491831e-08 +4.980391487230276e-08 +4.2689069890545226e-08 +3.3342116679216694e-08 +2.985444757051202e-08 +2.8877900220074708e-08 +2.6924805519200093e-08 +2.4274176996584538e-08 +2.050749435918349e-08 +3.4318664029654005e-08 +3.208655580008301e-08 +3.250507609312757e-08 +3.1389021978342073e-08 +3.1668035507038446e-08 +3.1947049035734825e-08 +3.3342116679216694e-08 +3.989893460358149e-08 +3.445817079400219e-08 +4.82693404644727e-08 +5.147799604448101e-08 +5.2873063687962876e-08 +5.3710104274051994e-08 +5.008292840099913e-08 +5.147799604448101e-08 +5.1338489280132814e-08 +4.896687428621364e-08 +4.157301577575972e-08 +3.2644582857475756e-08 +3.013346109920839e-08 +2.9575434041815645e-08 +2.7901352869637404e-08 +2.5111217582673662e-08 +2.1344534945272613e-08 +3.4737184322698563e-08 +3.292359638617213e-08 +3.3063103150520315e-08 +3.2365569328779384e-08 +3.250507609312757e-08 +3.250507609312757e-08 +3.390014373660944e-08 +4.045696166097423e-08 +3.390014373660944e-08 +4.7432299878383586e-08 +5.008292840099913e-08 +5.147799604448101e-08 +5.203602310187375e-08 +4.812983370012452e-08 +4.868786075751727e-08 +4.82693404644727e-08 +4.436315106272346e-08 +3.7387812845314116e-08 +3.0970501685297515e-08 +2.7482832576592838e-08 +2.6227271697459155e-08 +2.4832204053977286e-08 +2.287910935310267e-08 +2.050749435918349e-08 +3.5016197851394936e-08 +3.250507609312757e-08 +3.348162344356488e-08 +3.292359638617213e-08 +3.278408962182394e-08 +3.22260625644312e-08 +3.3063103150520315e-08 +3.4737184322698563e-08 +3.794583990270687e-08 +4.324709694793797e-08 +4.7432299878383586e-08 +5.0501448694043697e-08 +5.0919968987088255e-08 +4.896687428621364e-08 +4.701377958533902e-08 +4.6455752527946275e-08 +4.492117812011622e-08 +4.324709694793797e-08 +4.1433509011411543e-08 +3.961992107488511e-08 +3.892238725314418e-08 +3.7666826374010495e-08 +3.6550772259225e-08 +3.5713731673135874e-08 +3.445817079400219e-08 +3.3063103150520315e-08 +3.362113020791307e-08 +3.320260991486851e-08 +3.22260625644312e-08 +3.152852874269026e-08 +3.180754227138664e-08 +3.1947049035734825e-08 +3.250507609312757e-08 +3.2365569328779384e-08 +3.320260991486851e-08 +3.4737184322698563e-08 +3.6550772259225e-08 +3.7666826374010495e-08 +3.7666826374010495e-08 +3.7806333138358674e-08 +3.724830608096593e-08 +3.682978578792137e-08 +3.8085346667055053e-08 +3.7806333138358674e-08 +3.6690279023573184e-08 +3.585323843748406e-08 +3.557422490878769e-08 +3.445817079400219e-08 +3.362113020791307e-08 +3.180754227138664e-08 +3.250507609312757e-08 +3.1668035507038446e-08 +3.1668035507038446e-08 +3.2365569328779384e-08 +3.362113020791307e-08 +4.003844136792967e-08 +3.390014373660944e-08 +4.82693404644727e-08 +5.119898251578463e-08 +5.2594050159266504e-08 +5.343109074535562e-08 +4.980391487230276e-08 +5.1896516337525566e-08 +5.1338489280132814e-08 +4.868786075751727e-08 +4.1433509011411543e-08 +3.22260625644312e-08 +2.9296420513119273e-08 +2.8319873162681962e-08 +2.6645791990503717e-08 +2.3576643174843603e-08 +2.0367987594835303e-08 +3.445817079400219e-08 +3.2365569328779384e-08 +3.2644582857475756e-08 +3.180754227138664e-08 +3.180754227138664e-08 +3.2365569328779384e-08 +3.417915726530581e-08 +4.087548195401879e-08 +3.54347181444395e-08 +4.93853945792582e-08 +5.245454339491831e-08 +5.412862456709656e-08 +5.454714486014112e-08 +5.0919968987088255e-08 +5.2873063687962876e-08 +5.2873063687962876e-08 +5.0222435165347324e-08 +4.2689069890545226e-08 +3.3342116679216694e-08 +3.0551981392252956e-08 +2.985444757051202e-08 +2.873839345572652e-08 +2.552973787571822e-08 +2.1623548473968986e-08 +3.5992745201832246e-08 +3.417915726530581e-08 +3.445817079400219e-08 +3.348162344356488e-08 +3.376063697226125e-08 +3.4039650500957626e-08 +3.4737184322698563e-08 +4.087548195401879e-08 +3.487669108704675e-08 +4.882736752186545e-08 +5.1896516337525566e-08 +5.3710104274051994e-08 +5.440763809579293e-08 +5.0222435165347324e-08 +5.1896516337525566e-08 +5.175700957317738e-08 +4.93853945792582e-08 +4.199153606880429e-08 +3.250507609312757e-08 +2.985444757051202e-08 +2.9017406984422894e-08 +2.6924805519200093e-08 +2.413467023223635e-08 +2.050749435918349e-08 +3.417915726530581e-08 +3.208655580008301e-08 +3.250507609312757e-08 +3.180754227138664e-08 +3.1947049035734825e-08 +3.208655580008301e-08 +3.348162344356488e-08 +3.9340907546188736e-08 +3.376063697226125e-08 +4.701377958533902e-08 +5.0222435165347324e-08 +5.175700957317738e-08 +5.273355692361469e-08 +4.93853945792582e-08 +5.0919968987088255e-08 +5.105947575143644e-08 +4.8548353993169076e-08 +4.101498871836698e-08 +3.1947049035734825e-08 +3.013346109920839e-08 +2.9296420513119273e-08 +2.7901352869637404e-08 +2.4971710818325472e-08 +2.106552141657624e-08 +3.417915726530581e-08 +3.278408962182394e-08 +3.320260991486851e-08 +3.320260991486851e-08 +3.3342116679216694e-08 +3.320260991486851e-08 +3.4737184322698563e-08 +4.059646842532242e-08 +3.362113020791307e-08 +4.673476605664265e-08 +4.966440810795457e-08 +5.0501448694043697e-08 +5.1338489280132814e-08 +4.785082017142814e-08 +4.8548353993169076e-08 +4.812983370012452e-08 +4.4502657827071654e-08 +3.75273196096623e-08 +3.083099492094933e-08 +2.7622339340941025e-08 +2.6366778461807345e-08 +2.5111217582673662e-08 +2.315812288179904e-08 +2.106552141657624e-08 +3.613225196618043e-08 +3.376063697226125e-08 +3.54347181444395e-08 +3.5016197851394936e-08 +3.4318664029654005e-08 +3.362113020791307e-08 +3.4318664029654005e-08 +3.585323843748406e-08 +3.86433737244478e-08 +4.366561724098254e-08 +4.882736752186545e-08 +5.1338489280132814e-08 +5.175700957317738e-08 +4.9943421636650945e-08 +4.799032693577633e-08 +4.7153286349687207e-08 +4.533969841316077e-08 +4.3386603712286164e-08 +4.1712522540107916e-08 +4.059646842532242e-08 +3.961992107488511e-08 +3.794583990270687e-08 +3.627175873052862e-08 +3.54347181444395e-08 +3.4318664029654005e-08 +3.3063103150520315e-08 +3.4318664029654005e-08 +3.4039650500957626e-08 +3.320260991486851e-08 +3.1947049035734825e-08 +3.22260625644312e-08 +3.22260625644312e-08 +3.278408962182394e-08 +3.180754227138664e-08 +3.278408962182394e-08 +3.445817079400219e-08 +3.5713731673135874e-08 +3.6690279023573184e-08 +3.710879931661774e-08 +3.696929255226956e-08 +3.682978578792137e-08 +3.627175873052862e-08 +3.7806333138358674e-08 +3.8085346667055053e-08 +3.6411265494876805e-08 +3.5713731673135874e-08 +3.5295211380091315e-08 +3.417915726530581e-08 +3.3342116679216694e-08 +3.1668035507038446e-08 +3.278408962182394e-08 +3.1668035507038446e-08 +3.180754227138664e-08 +3.250507609312757e-08 +3.4039650500957626e-08 +4.031745489662604e-08 +3.4039650500957626e-08 +4.729279311403539e-08 +5.036194192969551e-08 +5.217552986622194e-08 +5.343109074535562e-08 +4.9943421636650945e-08 +5.161750280882919e-08 +5.147799604448101e-08 +4.8548353993169076e-08 +4.1433509011411543e-08 +3.208655580008301e-08 +2.9714940806163832e-08 +2.873839345572652e-08 +2.6924805519200093e-08 +2.3995163467888165e-08 +2.078650788787986e-08 +3.4737184322698563e-08 +3.278408962182394e-08 +3.320260991486851e-08 +3.2365569328779384e-08 +3.2644582857475756e-08 +3.320260991486851e-08 +3.4737184322698563e-08 +4.087548195401879e-08 +3.515570461574312e-08 +4.8548353993169076e-08 +5.175700957317738e-08 +5.315207721665925e-08 +5.412862456709656e-08 +5.036194192969551e-08 +5.175700957317738e-08 +5.147799604448101e-08 +4.882736752186545e-08 +4.157301577575972e-08 +3.1947049035734825e-08 +2.985444757051202e-08 +2.9296420513119273e-08 +2.845937992703015e-08 +2.5669244640066407e-08 +2.218157553136173e-08 +3.682978578792137e-08 +3.4737184322698563e-08 +3.5295211380091315e-08 +3.4318664029654005e-08 +3.417915726530581e-08 +3.390014373660944e-08 +3.487669108704675e-08 +4.087548195401879e-08 +3.4737184322698563e-08 +4.785082017142814e-08 +5.105947575143644e-08 +5.245454339491831e-08 +5.3570597509703814e-08 +4.9524901343606386e-08 +5.078046222274007e-08 +5.0501448694043697e-08 +4.840884722882089e-08 +4.101498871836698e-08 +3.1389021978342073e-08 +2.943592727746746e-08 +2.8598886691378335e-08 +2.6785298754851907e-08 +2.3995163467888165e-08 +2.0926014652228048e-08 +3.5016197851394936e-08 +3.292359638617213e-08 +3.348162344356488e-08 +3.3063103150520315e-08 +3.3063103150520315e-08 +3.3342116679216694e-08 +3.487669108704675e-08 +4.059646842532242e-08 +3.4318664029654005e-08 +4.729279311403539e-08 +5.0919968987088255e-08 +5.2315036630570125e-08 +5.301257045231106e-08 +4.9524901343606386e-08 +5.105947575143644e-08 +5.1338489280132814e-08 +4.868786075751727e-08 +4.129400224706335e-08 +3.152852874269026e-08 +2.9714940806163832e-08 +2.8877900220074708e-08 +2.7482832576592838e-08 +2.4832204053977286e-08 +2.14840417096208e-08 +3.5713731673135874e-08 +3.459767755835038e-08 +3.5295211380091315e-08 +3.5016197851394936e-08 +3.515570461574312e-08 +3.515570461574312e-08 +3.6411265494876805e-08 +4.199153606880429e-08 +3.4318664029654005e-08 +4.701377958533902e-08 +4.9943421636650945e-08 +5.0919968987088255e-08 +5.161750280882919e-08 +4.799032693577633e-08 +4.840884722882089e-08 +4.771131340707996e-08 +4.422364429837528e-08 +3.7387812845314116e-08 +2.9993954334860204e-08 +2.706431228354828e-08 +2.5808751404414597e-08 +2.4832204053977286e-08 +2.3018616117450855e-08 +2.106552141657624e-08 +3.627175873052862e-08 +3.417915726530581e-08 +3.487669108704675e-08 +3.417915726530581e-08 +3.390014373660944e-08 +3.4318664029654005e-08 +3.459767755835038e-08 +3.5713731673135874e-08 +3.892238725314418e-08 +4.3805124005330716e-08 +4.910638105056182e-08 +5.2594050159266504e-08 +5.3291583981007435e-08 +5.161750280882919e-08 +4.966440810795457e-08 +4.771131340707996e-08 +4.5897725470553524e-08 +4.366561724098254e-08 +4.213104283315248e-08 +4.1852029304456096e-08 +4.087548195401879e-08 +3.948041431053692e-08 +3.8085346667055053e-08 +3.696929255226956e-08 +3.5713731673135874e-08 +3.445817079400219e-08 +3.613225196618043e-08 +3.5016197851394936e-08 +3.4737184322698563e-08 +3.376063697226125e-08 +3.4039650500957626e-08 +3.320260991486851e-08 +3.3342116679216694e-08 +3.1668035507038446e-08 +3.292359638617213e-08 +3.459767755835038e-08 +3.6411265494876805e-08 +3.710879931661774e-08 +3.7666826374010495e-08 +3.724830608096593e-08 +3.724830608096593e-08 +3.627175873052862e-08 +3.7387812845314116e-08 +3.850386696009961e-08 +3.682978578792137e-08 +3.627175873052862e-08 +3.515570461574312e-08 +3.445817079400219e-08 +3.320260991486851e-08 +3.1947049035734825e-08 +3.3063103150520315e-08 +3.208655580008301e-08 +3.1668035507038446e-08 +3.1947049035734825e-08 +3.376063697226125e-08 +4.003844136792967e-08 +3.348162344356488e-08 +4.5897725470553524e-08 +4.93853945792582e-08 +5.147799604448101e-08 +5.2594050159266504e-08 +4.93853945792582e-08 +5.105947575143644e-08 +5.105947575143644e-08 +4.868786075751727e-08 +4.115449548271517e-08 +3.083099492094933e-08 +2.9575434041815645e-08 +2.8877900220074708e-08 +2.7482832576592838e-08 +2.413467023223635e-08 +2.0926014652228048e-08 +3.5713731673135874e-08 +3.348162344356488e-08 +3.4039650500957626e-08 +3.292359638617213e-08 +3.278408962182394e-08 +3.3063103150520315e-08 +3.4318664029654005e-08 +4.031745489662604e-08 +3.4039650500957626e-08 +4.729279311403539e-08 +5.078046222274007e-08 +5.217552986622194e-08 +5.301257045231106e-08 +4.910638105056182e-08 +5.064095545839188e-08 +5.008292840099913e-08 +4.7571806642731765e-08 +4.031745489662604e-08 +3.041247462790477e-08 +2.9017406984422894e-08 +2.8598886691378335e-08 +2.7901352869637404e-08 +2.5111217582673662e-08 +2.1344534945272613e-08 +3.5295211380091315e-08 +3.3342116679216694e-08 +3.376063697226125e-08 +3.292359638617213e-08 +3.2644582857475756e-08 +3.2644582857475756e-08 +3.376063697226125e-08 +3.9759427839233295e-08 +3.376063697226125e-08 +4.6455752527946275e-08 +4.9943421636650945e-08 +5.147799604448101e-08 +5.273355692361469e-08 +4.8548353993169076e-08 +4.9943421636650945e-08 +4.980391487230276e-08 +4.7571806642731765e-08 +4.003844136792967e-08 +2.9993954334860204e-08 +2.9017406984422894e-08 +2.845937992703015e-08 +2.706431228354828e-08 +2.4413683760932724e-08 +2.078650788787986e-08 +3.4737184322698563e-08 +3.250507609312757e-08 +3.348162344356488e-08 +3.278408962182394e-08 +3.250507609312757e-08 +3.292359638617213e-08 +3.4318664029654005e-08 +4.003844136792967e-08 +3.348162344356488e-08 +4.6455752527946275e-08 +5.0222435165347324e-08 +5.147799604448101e-08 +5.217552986622194e-08 +4.868786075751727e-08 +5.036194192969551e-08 +5.036194192969551e-08 +4.785082017142814e-08 +4.045696166097423e-08 +3.041247462790477e-08 +2.9156913748771087e-08 +2.8598886691378335e-08 +2.706431228354828e-08 +2.4274176996584538e-08 +2.0926014652228048e-08 +3.4737184322698563e-08 +3.278408962182394e-08 +3.3063103150520315e-08 +3.250507609312757e-08 +3.250507609312757e-08 +3.2365569328779384e-08 +3.390014373660944e-08 +3.9759427839233295e-08 +3.3063103150520315e-08 +4.5618711941857144e-08 +4.896687428621364e-08 +5.036194192969551e-08 +5.064095545839188e-08 +4.687427282099083e-08 +4.7153286349687207e-08 +4.631624576359808e-08 +4.2828576654893406e-08 +3.5992745201832246e-08 +2.8598886691378335e-08 +2.6366778461807345e-08 +2.5250724347021848e-08 +2.4413683760932724e-08 +2.2321082295709924e-08 +2.008897406613893e-08 +3.417915726530581e-08 +3.208655580008301e-08 +3.1947049035734825e-08 +3.1389021978342073e-08 +3.152852874269026e-08 +3.22260625644312e-08 +3.250507609312757e-08 +3.362113020791307e-08 +3.6690279023573184e-08 +4.087548195401879e-08 +4.575821870620534e-08 +4.966440810795457e-08 +5.078046222274007e-08 +4.868786075751727e-08 +4.729279311403539e-08 +4.533969841316077e-08 +4.3805124005330716e-08 +4.115449548271517e-08 +3.906189401749236e-08 +3.892238725314418e-08 +3.8364360195751426e-08 +3.7806333138358674e-08 +3.710879931661774e-08 +3.682978578792137e-08 +3.557422490878769e-08 +3.390014373660944e-08 +3.487669108704675e-08 +3.376063697226125e-08 +3.362113020791307e-08 +3.320260991486851e-08 +3.348162344356488e-08 +3.2644582857475756e-08 +3.2365569328779384e-08 +3.0970501685297515e-08 +3.2644582857475756e-08 +3.417915726530581e-08 +3.5016197851394936e-08 +3.515570461574312e-08 +3.557422490878769e-08 +3.487669108704675e-08 +3.459767755835038e-08 +3.376063697226125e-08 +3.4039650500957626e-08 +3.5992745201832246e-08 +3.54347181444395e-08 +3.5016197851394936e-08 +3.390014373660944e-08 +3.3342116679216694e-08 +3.250507609312757e-08 +3.11100084496457e-08 +3.1947049035734825e-08 +3.1389021978342073e-08 +3.11100084496457e-08 +3.11100084496457e-08 +3.3063103150520315e-08 +3.906189401749236e-08 +3.2365569328779384e-08 +4.464216459141985e-08 +4.785082017142814e-08 +4.980391487230276e-08 +5.064095545839188e-08 +4.729279311403539e-08 +4.910638105056182e-08 +4.9245887814910014e-08 +4.7153286349687207e-08 +3.961992107488511e-08 +2.9296420513119273e-08 +2.873839345572652e-08 +2.845937992703015e-08 +2.6785298754851907e-08 +2.3576643174843603e-08 +2.0228480830487117e-08 +3.4737184322698563e-08 +3.208655580008301e-08 +3.2644582857475756e-08 +3.1668035507038446e-08 +3.1389021978342073e-08 +3.1389021978342073e-08 +3.278408962182394e-08 +3.8782880488795985e-08 +3.278408962182394e-08 +4.5479205177508965e-08 +4.8548353993169076e-08 +4.9943421636650945e-08 +5.078046222274007e-08 +4.687427282099083e-08 +4.882736752186545e-08 +4.868786075751727e-08 +4.61767389992499e-08 +3.8782880488795985e-08 +2.8319873162681962e-08 +2.7761846105289214e-08 +2.804085963398559e-08 +2.7343325812244652e-08 +2.413467023223635e-08 +1.9670453773094368e-08 +3.250507609312757e-08 +3.0551981392252956e-08 +3.11100084496457e-08 +3.013346109920839e-08 +3.027296786355658e-08 +3.069148815660114e-08 +3.250507609312757e-08 +3.8364360195751426e-08 +3.2644582857475756e-08 +4.50606848844644e-08 +4.812983370012452e-08 +4.966440810795457e-08 +5.078046222274007e-08 +4.687427282099083e-08 +4.868786075751727e-08 +4.868786075751727e-08 +4.631624576359808e-08 +3.9340907546188736e-08 +2.9017406984422894e-08 +2.845937992703015e-08 +2.845937992703015e-08 +2.706431228354828e-08 +2.413467023223635e-08 +2.008897406613893e-08 +3.3063103150520315e-08 +3.11100084496457e-08 +3.180754227138664e-08 +3.11100084496457e-08 +3.069148815660114e-08 +3.11100084496457e-08 +3.250507609312757e-08 +3.7806333138358674e-08 +3.208655580008301e-08 +4.4502657827071654e-08 +4.799032693577633e-08 +4.9524901343606386e-08 +5.0501448694043697e-08 +4.701377958533902e-08 +4.8548353993169076e-08 +4.8548353993169076e-08 +4.61767389992499e-08 +3.906189401749236e-08 +2.873839345572652e-08 +2.8180366398333776e-08 +2.845937992703015e-08 +2.706431228354828e-08 +2.3995163467888165e-08 +1.9809960537442554e-08 +3.208655580008301e-08 +2.9575434041815645e-08 +2.943592727746746e-08 +2.873839345572652e-08 +2.8598886691378335e-08 +2.9017406984422894e-08 +3.0970501685297515e-08 +3.6550772259225e-08 +3.083099492094933e-08 +4.2689069890545226e-08 +4.61767389992499e-08 +4.729279311403539e-08 +4.799032693577633e-08 +4.436315106272346e-08 +4.520019164881259e-08 +4.436315106272346e-08 +4.087548195401879e-08 +3.445817079400219e-08 +2.706431228354828e-08 +2.5111217582673662e-08 +2.4413683760932724e-08 +2.3437136410495414e-08 +2.14840417096208e-08 +1.8972919951353434e-08 +3.180754227138664e-08 +2.943592727746746e-08 +2.9575434041815645e-08 +2.873839345572652e-08 +2.873839345572652e-08 +2.873839345572652e-08 +2.9296420513119273e-08 +3.013346109920839e-08 +3.292359638617213e-08 +3.6411265494876805e-08 +4.087548195401879e-08 +4.394463076967891e-08 +4.492117812011622e-08 +4.2410056361848854e-08 +4.157301577575972e-08 +4.087548195401879e-08 +3.9759427839233295e-08 +3.7666826374010495e-08 +3.5016197851394936e-08 +3.487669108704675e-08 +3.5016197851394936e-08 +3.3342116679216694e-08 +3.3063103150520315e-08 +3.292359638617213e-08 +3.1668035507038446e-08 +2.985444757051202e-08 +3.027296786355658e-08 +2.9296420513119273e-08 +2.943592727746746e-08 +2.9156913748771087e-08 +2.9575434041815645e-08 +2.9575434041815645e-08 +2.9156913748771087e-08 +2.845937992703015e-08 +3.041247462790477e-08 +3.2644582857475756e-08 +3.348162344356488e-08 +3.362113020791307e-08 +3.390014373660944e-08 +3.390014373660944e-08 +3.4737184322698563e-08 +3.417915726530581e-08 +3.3342116679216694e-08 +3.5295211380091315e-08 +3.5713731673135874e-08 +3.4737184322698563e-08 +3.4318664029654005e-08 +3.362113020791307e-08 +3.320260991486851e-08 +3.11100084496457e-08 +3.152852874269026e-08 +3.0970501685297515e-08 +3.11100084496457e-08 +3.11100084496457e-08 +3.292359638617213e-08 +3.850386696009961e-08 +3.152852874269026e-08 +4.366561724098254e-08 +4.701377958533902e-08 +4.882736752186545e-08 +4.9524901343606386e-08 +4.575821870620534e-08 +4.771131340707996e-08 +4.771131340707996e-08 +4.5479205177508965e-08 +3.822485343140324e-08 +2.804085963398559e-08 +2.7482832576592838e-08 +2.845937992703015e-08 +2.6366778461807345e-08 +2.3018616117450855e-08 +1.9251933480049806e-08 +3.208655580008301e-08 +2.943592727746746e-08 +2.985444757051202e-08 +2.943592727746746e-08 +2.9714940806163832e-08 +2.9714940806163832e-08 +3.1389021978342073e-08 +3.7387812845314116e-08 +3.152852874269026e-08 +4.394463076967891e-08 +4.701377958533902e-08 +4.868786075751727e-08 +4.966440810795457e-08 +4.5479205177508965e-08 +4.7432299878383586e-08 +4.729279311403539e-08 +4.492117812011622e-08 +3.7387812845314116e-08 +2.6924805519200093e-08 +2.6785298754851907e-08 +2.845937992703015e-08 +2.7343325812244652e-08 +2.413467023223635e-08 +1.9251933480049806e-08 +3.124951521399389e-08 +2.943592727746746e-08 +3.027296786355658e-08 +2.985444757051202e-08 +3.027296786355658e-08 +3.069148815660114e-08 +3.2644582857475756e-08 +3.850386696009961e-08 +3.208655580008301e-08 +4.4502657827071654e-08 +4.7571806642731765e-08 +4.868786075751727e-08 +4.9524901343606386e-08 +4.5479205177508965e-08 +4.7432299878383586e-08 +4.729279311403539e-08 +4.492117812011622e-08 +3.7806333138358674e-08 +2.7343325812244652e-08 +2.706431228354828e-08 +2.8598886691378335e-08 +2.6924805519200093e-08 +2.4274176996584538e-08 +1.9949467301790744e-08 +3.22260625644312e-08 +2.9993954334860204e-08 +3.069148815660114e-08 +2.985444757051202e-08 +3.013346109920839e-08 +3.027296786355658e-08 +3.22260625644312e-08 +3.8364360195751426e-08 +3.152852874269026e-08 +4.3386603712286164e-08 +4.7153286349687207e-08 +4.882736752186545e-08 +4.9943421636650945e-08 +4.61767389992499e-08 +4.785082017142814e-08 +4.785082017142814e-08 +4.5479205177508965e-08 +3.8364360195751426e-08 +2.7901352869637404e-08 +2.7482832576592838e-08 +2.9156913748771087e-08 +2.804085963398559e-08 +2.4832204053977286e-08 +2.0228480830487117e-08 +3.22260625644312e-08 +3.013346109920839e-08 +3.027296786355658e-08 +2.9714940806163832e-08 +2.985444757051202e-08 +3.0551981392252956e-08 +3.124951521399389e-08 +3.75273196096623e-08 +3.027296786355658e-08 +4.213104283315248e-08 +4.5618711941857144e-08 +4.6595259292294455e-08 +4.7432299878383586e-08 +4.366561724098254e-08 +4.436315106272346e-08 +4.310759018358978e-08 +3.948041431053692e-08 +3.3342116679216694e-08 +2.5390231111370035e-08 +2.3995163467888165e-08 +2.4274176996584538e-08 +2.3018616117450855e-08 +2.078650788787986e-08 +1.82753861296125e-08 +3.083099492094933e-08 +2.845937992703015e-08 +2.9017406984422894e-08 +2.845937992703015e-08 +2.873839345572652e-08 +2.873839345572652e-08 +2.9017406984422894e-08 +2.9714940806163832e-08 +3.208655580008301e-08 +3.6411265494876805e-08 +4.101498871836698e-08 +4.422364429837528e-08 +4.478167135576803e-08 +4.227054959750066e-08 +4.1433509011411543e-08 +4.059646842532242e-08 +3.989893460358149e-08 +3.8085346667055053e-08 +3.5713731673135874e-08 +3.515570461574312e-08 +3.54347181444395e-08 +3.320260991486851e-08 +3.278408962182394e-08 +3.1668035507038446e-08 +3.0551981392252956e-08 +2.8877900220074708e-08 +2.943592727746746e-08 +2.873839345572652e-08 +2.873839345572652e-08 +2.845937992703015e-08 +2.873839345572652e-08 +2.9017406984422894e-08 +2.804085963398559e-08 +2.804085963398559e-08 +2.985444757051202e-08 +3.1947049035734825e-08 +3.320260991486851e-08 +3.3342116679216694e-08 +3.3342116679216694e-08 +3.362113020791307e-08 +3.445817079400219e-08 +3.3342116679216694e-08 +3.208655580008301e-08 +3.376063697226125e-08 +3.515570461574312e-08 +3.4318664029654005e-08 +3.4039650500957626e-08 +3.362113020791307e-08 +3.3063103150520315e-08 +3.124951521399389e-08 +3.1668035507038446e-08 +3.083099492094933e-08 +3.11100084496457e-08 +3.11100084496457e-08 +3.278408962182394e-08 +3.8364360195751426e-08 +3.11100084496457e-08 +4.3526110476634344e-08 +4.687427282099083e-08 +4.882736752186545e-08 +4.966440810795457e-08 +4.5897725470553524e-08 +4.799032693577633e-08 +4.771131340707996e-08 +4.520019164881259e-08 +3.794583990270687e-08 +2.7203819047896466e-08 +2.650628522615553e-08 +2.873839345572652e-08 +2.650628522615553e-08 +2.315812288179904e-08 +1.9391440244397992e-08 +3.1947049035734825e-08 +2.9575434041815645e-08 +2.9993954334860204e-08 +2.9575434041815645e-08 +2.985444757051202e-08 +3.013346109920839e-08 +3.180754227138664e-08 +3.822485343140324e-08 +3.1389021978342073e-08 +4.394463076967891e-08 +4.7153286349687207e-08 +4.882736752186545e-08 +4.966440810795457e-08 +4.5897725470553524e-08 +4.771131340707996e-08 +4.7432299878383586e-08 +4.464216459141985e-08 +3.696929255226956e-08 +2.6366778461807345e-08 +2.552973787571822e-08 +2.8319873162681962e-08 +2.7343325812244652e-08 +2.3995163467888165e-08 +1.953094700874618e-08 +3.180754227138664e-08 +2.9296420513119273e-08 +2.9714940806163832e-08 +2.9575434041815645e-08 +3.027296786355658e-08 +3.013346109920839e-08 +3.208655580008301e-08 +3.8085346667055053e-08 +3.0970501685297515e-08 +4.3526110476634344e-08 +4.729279311403539e-08 +4.8548353993169076e-08 +4.9245887814910014e-08 +4.520019164881259e-08 +4.701377958533902e-08 +4.673476605664265e-08 +4.4502657827071654e-08 +3.710879931661774e-08 +2.6785298754851907e-08 +2.608776493311097e-08 +2.9156913748771087e-08 +2.7482832576592838e-08 +2.4832204053977286e-08 +1.9949467301790744e-08 +3.208655580008301e-08 +2.9575434041815645e-08 +3.041247462790477e-08 +2.9575434041815645e-08 +2.985444757051202e-08 +3.013346109920839e-08 +3.208655580008301e-08 +3.8085346667055053e-08 +3.083099492094933e-08 +4.310759018358978e-08 +4.687427282099083e-08 +4.882736752186545e-08 +4.9943421636650945e-08 +4.603723223490171e-08 +4.7571806642731765e-08 +4.785082017142814e-08 +4.50606848844644e-08 +3.794583990270687e-08 +2.7482832576592838e-08 +2.6227271697459155e-08 +2.9575434041815645e-08 +2.873839345572652e-08 +2.5948258168762783e-08 +2.078650788787986e-08 +3.2644582857475756e-08 +3.041247462790477e-08 +3.083099492094933e-08 +3.027296786355658e-08 +3.0551981392252956e-08 +3.0970501685297515e-08 +3.180754227138664e-08 +3.8085346667055053e-08 +3.041247462790477e-08 +4.2549563126197034e-08 +4.5897725470553524e-08 +4.7153286349687207e-08 +4.7571806642731765e-08 +4.366561724098254e-08 +4.422364429837528e-08 +4.324709694793797e-08 +3.961992107488511e-08 +3.3063103150520315e-08 +2.5111217582673662e-08 +2.3716149939191793e-08 +2.455319052528091e-08 +2.3437136410495414e-08 +2.0926014652228048e-08 +1.82753861296125e-08 +3.0551981392252956e-08 +2.8180366398333776e-08 +2.8877900220074708e-08 +2.8180366398333776e-08 +2.8598886691378335e-08 +2.8319873162681962e-08 +2.8598886691378335e-08 +2.943592727746746e-08 +3.124951521399389e-08 +3.6550772259225e-08 +4.157301577575972e-08 +4.478167135576803e-08 +4.533969841316077e-08 +4.2549563126197034e-08 +4.115449548271517e-08 +4.031745489662604e-08 +3.920140078184055e-08 +3.696929255226956e-08 +3.5016197851394936e-08 +3.390014373660944e-08 +3.459767755835038e-08 +3.278408962182394e-08 +3.22260625644312e-08 +3.0970501685297515e-08 +2.9993954334860204e-08 +2.8180366398333776e-08 +2.8877900220074708e-08 +2.8180366398333776e-08 +2.8319873162681962e-08 +2.8180366398333776e-08 +2.804085963398559e-08 +2.7761846105289214e-08 +2.706431228354828e-08 +2.7622339340941025e-08 +2.9575434041815645e-08 +3.083099492094933e-08 +3.069148815660114e-08 +3.0970501685297515e-08 +3.0970501685297515e-08 +3.069148815660114e-08 +3.041247462790477e-08 +2.9296420513119273e-08 +2.8598886691378335e-08 +2.9993954334860204e-08 +3.1668035507038446e-08 +3.0970501685297515e-08 +3.027296786355658e-08 +2.985444757051202e-08 +2.943592727746746e-08 +2.7901352869637404e-08 +2.9156913748771087e-08 +2.8598886691378335e-08 +2.8877900220074708e-08 +2.9575434041815645e-08 +3.0970501685297515e-08 +3.682978578792137e-08 +3.027296786355658e-08 +4.310759018358978e-08 +4.6595259292294455e-08 +4.82693404644727e-08 +4.910638105056182e-08 +4.520019164881259e-08 +4.701377958533902e-08 +4.7153286349687207e-08 +4.4502657827071654e-08 +3.724830608096593e-08 +2.6366778461807345e-08 +2.552973787571822e-08 +2.8319873162681962e-08 +2.650628522615553e-08 +2.287910935310267e-08 +1.9391440244397992e-08 +3.22260625644312e-08 +2.9714940806163832e-08 +3.027296786355658e-08 +2.9575434041815645e-08 +2.985444757051202e-08 +3.0551981392252956e-08 +3.250507609312757e-08 +3.906189401749236e-08 +3.1668035507038446e-08 +4.436315106272346e-08 +4.785082017142814e-08 +4.9245887814910014e-08 +4.9943421636650945e-08 +4.61767389992499e-08 +4.82693404644727e-08 +4.799032693577633e-08 +4.50606848844644e-08 +3.7387812845314116e-08 +2.706431228354828e-08 +2.5669244640066407e-08 +2.9296420513119273e-08 +2.8877900220074708e-08 +2.5111217582673662e-08 +2.0228480830487117e-08 +3.278408962182394e-08 +2.9993954334860204e-08 +3.013346109920839e-08 +2.9156913748771087e-08 +2.9714940806163832e-08 +2.9714940806163832e-08 +3.124951521399389e-08 +3.724830608096593e-08 +3.027296786355658e-08 +4.29680834192416e-08 +4.6595259292294455e-08 +4.840884722882089e-08 +4.9245887814910014e-08 +4.5479205177508965e-08 +4.7153286349687207e-08 +4.701377958533902e-08 +4.492117812011622e-08 +3.7666826374010495e-08 +2.7203819047896466e-08 +2.552973787571822e-08 +2.9714940806163832e-08 +2.8319873162681962e-08 +2.5111217582673662e-08 +1.9809960537442554e-08 +3.1947049035734825e-08 +2.9156913748771087e-08 +2.9575434041815645e-08 +2.8180366398333776e-08 +2.845937992703015e-08 +2.873839345572652e-08 +3.013346109920839e-08 +3.557422490878769e-08 +2.9993954334860204e-08 +4.2689069890545226e-08 +4.6455752527946275e-08 +4.840884722882089e-08 +4.910638105056182e-08 +4.5479205177508965e-08 +4.6455752527946275e-08 +4.687427282099083e-08 +4.422364429837528e-08 +3.710879931661774e-08 +2.6645791990503717e-08 +2.4832204053977286e-08 +2.8877900220074708e-08 +2.8180366398333776e-08 +2.4971710818325472e-08 +1.9670453773094368e-08 +3.083099492094933e-08 +2.7901352869637404e-08 +2.8180366398333776e-08 +2.7343325812244652e-08 +2.7482832576592838e-08 +2.7761846105289214e-08 +2.943592727746746e-08 +3.5016197851394936e-08 +2.8877900220074708e-08 +4.087548195401879e-08 +4.408413753402709e-08 +4.5618711941857144e-08 +4.6455752527946275e-08 +4.2410056361848854e-08 +4.3386603712286164e-08 +4.29680834192416e-08 +3.948041431053692e-08 +3.320260991486851e-08 +2.5808751404414597e-08 +2.3995163467888165e-08 +2.5669244640066407e-08 +2.46926972896291e-08 +2.1902562002665358e-08 +1.911242671570162e-08 +3.11100084496457e-08 +2.804085963398559e-08 +2.8319873162681962e-08 +2.706431228354828e-08 +2.7343325812244652e-08 +2.7343325812244652e-08 +2.804085963398559e-08 +2.8319873162681962e-08 +2.9575434041815645e-08 +3.54347181444395e-08 +4.017794813227786e-08 +4.310759018358978e-08 +4.408413753402709e-08 +4.129400224706335e-08 +3.989893460358149e-08 +3.961992107488511e-08 +3.822485343140324e-08 +3.5713731673135874e-08 +3.348162344356488e-08 +3.2365569328779384e-08 +3.390014373660944e-08 +3.278408962182394e-08 +3.1947049035734825e-08 +3.069148815660114e-08 +2.9714940806163832e-08 +2.7761846105289214e-08 +2.845937992703015e-08 +2.7203819047896466e-08 +2.7622339340941025e-08 +2.7203819047896466e-08 +2.706431228354828e-08 +2.6227271697459155e-08 +2.552973787571822e-08 +2.5808751404414597e-08 +2.8319873162681962e-08 +2.9575434041815645e-08 +2.9993954334860204e-08 +3.027296786355658e-08 +3.0551981392252956e-08 +2.985444757051202e-08 +2.985444757051202e-08 +2.9714940806163832e-08 +2.9714940806163832e-08 +2.985444757051202e-08 +3.1947049035734825e-08 +3.124951521399389e-08 +2.9993954334860204e-08 +2.9156913748771087e-08 +2.8877900220074708e-08 +2.7482832576592838e-08 +2.873839345572652e-08 +2.8180366398333776e-08 +2.845937992703015e-08 +2.9714940806163832e-08 +3.041247462790477e-08 +3.515570461574312e-08 +2.9296420513119273e-08 +4.213104283315248e-08 +4.603723223490171e-08 +4.729279311403539e-08 +4.785082017142814e-08 +4.3805124005330716e-08 +4.5618711941857144e-08 +4.603723223490171e-08 +4.366561724098254e-08 +3.613225196618043e-08 +2.5390231111370035e-08 +2.3437136410495414e-08 +2.8180366398333776e-08 +2.6924805519200093e-08 +2.2739602588754482e-08 +1.8972919951353434e-08 +3.083099492094933e-08 +2.845937992703015e-08 +2.873839345572652e-08 +2.7901352869637404e-08 +2.8319873162681962e-08 +2.9017406984422894e-08 +3.083099492094933e-08 +3.627175873052862e-08 +2.9993954334860204e-08 +4.310759018358978e-08 +4.701377958533902e-08 +4.8548353993169076e-08 +4.896687428621364e-08 +4.478167135576803e-08 +4.687427282099083e-08 +4.687427282099083e-08 +4.4502657827071654e-08 +3.682978578792137e-08 +2.6227271697459155e-08 +2.3995163467888165e-08 +2.9296420513119273e-08 +2.9156913748771087e-08 +2.5250724347021848e-08 +1.953094700874618e-08 +3.11100084496457e-08 +2.873839345572652e-08 +2.9017406984422894e-08 +2.873839345572652e-08 +2.8598886691378335e-08 +2.9156913748771087e-08 +3.0551981392252956e-08 +3.557422490878769e-08 +2.9575434041815645e-08 +4.227054959750066e-08 +4.603723223490171e-08 +4.7571806642731765e-08 +4.840884722882089e-08 +4.478167135576803e-08 +4.6455752527946275e-08 +4.6595259292294455e-08 +4.422364429837528e-08 +3.696929255226956e-08 +2.6227271697459155e-08 +2.3716149939191793e-08 +2.8877900220074708e-08 +2.7901352869637404e-08 +2.4413683760932724e-08 +1.9251933480049806e-08 +3.027296786355658e-08 +2.7622339340941025e-08 +2.8180366398333776e-08 +2.6924805519200093e-08 +2.7203819047896466e-08 +2.7343325812244652e-08 +2.9017406984422894e-08 +3.390014373660944e-08 +2.873839345572652e-08 +4.101498871836698e-08 +4.478167135576803e-08 +4.6455752527946275e-08 +4.701377958533902e-08 +4.3386603712286164e-08 +4.50606848844644e-08 +4.520019164881259e-08 +4.2828576654893406e-08 +3.5992745201832246e-08 +2.552973787571822e-08 +2.3297629646147227e-08 +2.804085963398559e-08 +2.7761846105289214e-08 +2.413467023223635e-08 +1.8833413187005247e-08 +2.9156913748771087e-08 +2.6366778461807345e-08 +2.6924805519200093e-08 +2.5948258168762783e-08 +2.6366778461807345e-08 +2.650628522615553e-08 +2.8180366398333776e-08 +3.3063103150520315e-08 +2.7343325812244652e-08 +3.906189401749236e-08 +4.29680834192416e-08 +4.4502657827071654e-08 +4.5479205177508965e-08 +4.1433509011411543e-08 +4.227054959750066e-08 +4.1852029304456096e-08 +3.8085346667055053e-08 +3.208655580008301e-08 +2.4971710818325472e-08 +2.2739602588754482e-08 +2.4971710818325472e-08 +2.4274176996584538e-08 +2.1623548473968986e-08 +1.8693906422657058e-08 +3.069148815660114e-08 +2.7482832576592838e-08 +2.7901352869637404e-08 +2.6785298754851907e-08 +2.6785298754851907e-08 +2.6924805519200093e-08 +2.7482832576592838e-08 +2.706431228354828e-08 +2.873839345572652e-08 +3.4737184322698563e-08 +3.9759427839233295e-08 +4.2828576654893406e-08 +4.29680834192416e-08 +4.003844136792967e-08 +3.920140078184055e-08 +3.822485343140324e-08 +3.724830608096593e-08 +3.515570461574312e-08 +3.278408962182394e-08 +3.124951521399389e-08 +3.3342116679216694e-08 +3.250507609312757e-08 +3.180754227138664e-08 +3.0551981392252956e-08 +2.943592727746746e-08 +2.7761846105289214e-08 +2.8598886691378335e-08 +2.7761846105289214e-08 +2.7761846105289214e-08 +2.7622339340941025e-08 +2.804085963398559e-08 +2.6785298754851907e-08 +2.6227271697459155e-08 +2.706431228354828e-08 +2.9017406984422894e-08 +2.9993954334860204e-08 +3.1389021978342073e-08 +3.152852874269026e-08 +3.0970501685297515e-08 +2.9714940806163832e-08 +2.9156913748771087e-08 +2.845937992703015e-08 +2.8319873162681962e-08 +2.804085963398559e-08 +3.041247462790477e-08 +3.027296786355658e-08 +2.9017406984422894e-08 +2.8180366398333776e-08 +2.7761846105289214e-08 +2.7482832576592838e-08 +2.8598886691378335e-08 +2.8319873162681962e-08 +2.8877900220074708e-08 +3.0970501685297515e-08 +3.320260991486851e-08 +4.115449548271517e-08 +3.348162344356488e-08 +4.2689069890545226e-08 +4.5897725470553524e-08 +4.7153286349687207e-08 +4.5897725470553524e-08 +4.422364429837528e-08 +4.5479205177508965e-08 +4.478167135576803e-08 +4.059646842532242e-08 +3.180754227138664e-08 +2.3576643174843603e-08 +2.1623548473968986e-08 +2.7203819047896466e-08 +2.5808751404414597e-08 +2.1344534945272613e-08 +1.7996372600916123e-08 +2.8319873162681962e-08 +2.7622339340941025e-08 +2.7343325812244652e-08 +2.6924805519200093e-08 +2.7482832576592838e-08 +2.9017406984422894e-08 +3.2365569328779384e-08 +4.366561724098254e-08 +3.557422490878769e-08 +4.366561724098254e-08 +4.6455752527946275e-08 +4.7432299878383586e-08 +4.5618711941857144e-08 +4.464216459141985e-08 +4.575821870620534e-08 +4.4502657827071654e-08 +3.9759427839233295e-08 +3.083099492094933e-08 +2.2739602588754482e-08 +2.106552141657624e-08 +2.6785298754851907e-08 +2.5948258168762783e-08 +2.1205028180924427e-08 +1.757785230787156e-08 +2.845937992703015e-08 +2.7622339340941025e-08 +2.804085963398559e-08 +2.8180366398333776e-08 +2.804085963398559e-08 +2.8877900220074708e-08 +3.208655580008301e-08 +4.324709694793797e-08 +3.515570461574312e-08 +4.3386603712286164e-08 +4.603723223490171e-08 +4.687427282099083e-08 +4.50606848844644e-08 +4.422364429837528e-08 +4.520019164881259e-08 +4.408413753402709e-08 +3.948041431053692e-08 +3.0551981392252956e-08 +2.3018616117450855e-08 +2.1763055238317172e-08 +2.6785298754851907e-08 +2.5669244640066407e-08 +2.1205028180924427e-08 +1.729883877917519e-08 +2.8319873162681962e-08 +2.650628522615553e-08 +2.6366778461807345e-08 +2.608776493311097e-08 +2.608776493311097e-08 +2.6645791990503717e-08 +3.069148815660114e-08 +4.1852029304456096e-08 +3.4039650500957626e-08 +4.199153606880429e-08 +4.492117812011622e-08 +4.61767389992499e-08 +4.50606848844644e-08 +4.422364429837528e-08 +4.5479205177508965e-08 +4.394463076967891e-08 +3.906189401749236e-08 +3.013346109920839e-08 +2.2600095824406296e-08 +2.1623548473968986e-08 +2.6645791990503717e-08 +2.5808751404414597e-08 +2.14840417096208e-08 +1.7438345543523375e-08 +2.7203819047896466e-08 +2.608776493311097e-08 +2.5948258168762783e-08 +2.5390231111370035e-08 +2.5808751404414597e-08 +2.6645791990503717e-08 +3.013346109920839e-08 +4.017794813227786e-08 +3.208655580008301e-08 +3.948041431053692e-08 +4.2549563126197034e-08 +4.3805124005330716e-08 +4.227054959750066e-08 +4.059646842532242e-08 +4.059646842532242e-08 +3.850386696009961e-08 +3.3342116679216694e-08 +2.6785298754851907e-08 +2.14840417096208e-08 +1.9949467301790744e-08 +2.246058906005811e-08 +2.1623548473968986e-08 +1.8972919951353434e-08 +1.6601304957434254e-08 +2.7343325812244652e-08 +2.5948258168762783e-08 +2.5948258168762783e-08 +2.5250724347021848e-08 +2.5390231111370035e-08 +2.5390231111370035e-08 +2.5948258168762783e-08 +2.6366778461807345e-08 +2.9714940806163832e-08 +3.515570461574312e-08 +3.961992107488511e-08 +4.1852029304456096e-08 +4.059646842532242e-08 +3.850386696009961e-08 +3.7666826374010495e-08 +3.6550772259225e-08 +3.487669108704675e-08 +3.320260991486851e-08 +3.11100084496457e-08 +2.9993954334860204e-08 +3.1668035507038446e-08 +3.11100084496457e-08 +2.9575434041815645e-08 +2.8598886691378335e-08 +2.7343325812244652e-08 +2.706431228354828e-08 +2.7622339340941025e-08 +2.706431228354828e-08 +2.6924805519200093e-08 +2.7482832576592838e-08 +2.7482832576592838e-08 +2.608776493311097e-08 +2.5669244640066407e-08 +2.7622339340941025e-08 +2.9017406984422894e-08 +2.985444757051202e-08 +3.069148815660114e-08 +3.069148815660114e-08 +2.943592727746746e-08 +2.8598886691378335e-08 +2.706431228354828e-08 +2.5808751404414597e-08 +2.4971710818325472e-08 +2.5111217582673662e-08 +2.706431228354828e-08 +2.804085963398559e-08 +2.6785298754851907e-08 +2.608776493311097e-08 +2.7343325812244652e-08 +2.706431228354828e-08 +2.7622339340941025e-08 +2.706431228354828e-08 +2.6924805519200093e-08 +2.7482832576592838e-08 +2.7482832576592838e-08 +2.608776493311097e-08 +2.5669244640066407e-08 +2.7622339340941025e-08 +2.9017406984422894e-08 +2.985444757051202e-08 +3.069148815660114e-08 +3.069148815660114e-08 +2.943592727746746e-08 +2.8598886691378335e-08 +2.706431228354828e-08 +2.5808751404414597e-08 +2.4971710818325472e-08 +2.5111217582673662e-08 +2.706431228354828e-08 +2.804085963398559e-08 +2.6785298754851907e-08 +2.608776493311097e-08 +2.6645791990503717e-08 +2.7343325812244652e-08 +2.650628522615553e-08 +2.6785298754851907e-08 +2.7343325812244652e-08 +2.9296420513119273e-08 +3.4737184322698563e-08 +2.9156913748771087e-08 +4.1852029304456096e-08 +4.50606848844644e-08 +4.6455752527946275e-08 +4.673476605664265e-08 +4.2828576654893406e-08 +4.464216459141985e-08 +4.533969841316077e-08 +4.310759018358978e-08 +3.585323843748406e-08 +2.5669244640066407e-08 +2.106552141657624e-08 +2.1344534945272613e-08 +2.6227271697459155e-08 +2.4413683760932724e-08 +1.8414892893960685e-08 +2.8180366398333776e-08 +2.5669244640066407e-08 +2.608776493311097e-08 +2.6645791990503717e-08 +2.6227271697459155e-08 +2.650628522615553e-08 +2.7482832576592838e-08 +3.292359638617213e-08 +2.804085963398559e-08 +4.059646842532242e-08 +4.408413753402709e-08 +4.5897725470553524e-08 +4.673476605664265e-08 +4.2689069890545226e-08 +4.464216459141985e-08 +4.492117812011622e-08 +4.2689069890545226e-08 +3.613225196618043e-08 +2.5250724347021848e-08 +2.106552141657624e-08 +2.1344534945272613e-08 +2.5948258168762783e-08 +2.4413683760932724e-08 +1.855439965830887e-08 +2.8598886691378335e-08 +2.6785298754851907e-08 +2.5948258168762783e-08 +2.4832204053977286e-08 +2.552973787571822e-08 +2.5948258168762783e-08 +2.706431228354828e-08 +3.292359638617213e-08 +2.7901352869637404e-08 +4.031745489662604e-08 +4.394463076967891e-08 +4.575821870620534e-08 +4.673476605664265e-08 +4.3386603712286164e-08 +4.533969841316077e-08 +4.5618711941857144e-08 +4.29680834192416e-08 +3.5713731673135874e-08 +2.4971710818325472e-08 +2.0367987594835303e-08 +2.078650788787986e-08 +2.552973787571822e-08 +2.46926972896291e-08 +1.9391440244397992e-08 +2.8877900220074708e-08 +2.6227271697459155e-08 +2.6366778461807345e-08 +2.5669244640066407e-08 +2.608776493311097e-08 +2.6785298754851907e-08 +2.845937992703015e-08 +3.362113020791307e-08 +2.7343325812244652e-08 +3.86433737244478e-08 +4.1852029304456096e-08 +4.324709694793797e-08 +4.3805124005330716e-08 +3.989893460358149e-08 +4.045696166097423e-08 +3.948041431053692e-08 +3.5713731673135874e-08 +2.985444757051202e-08 +2.246058906005811e-08 +1.9251933480049806e-08 +1.8972919951353434e-08 +2.1763055238317172e-08 +2.106552141657624e-08 +1.771735907221975e-08 +2.845937992703015e-08 +2.5390231111370035e-08 +2.5669244640066407e-08 +2.5250724347021848e-08 +2.5390231111370035e-08 +2.608776493311097e-08 +2.5808751404414597e-08 +2.5808751404414597e-08 +2.7622339340941025e-08 +3.3063103150520315e-08 +3.682978578792137e-08 +3.948041431053692e-08 +4.003844136792967e-08 +3.822485343140324e-08 +3.710879931661774e-08 +3.6411265494876805e-08 +3.54347181444395e-08 +3.348162344356488e-08 +3.11100084496457e-08 +2.9575434041815645e-08 +2.943592727746746e-08 +3.0551981392252956e-08 +3.0970501685297515e-08 +2.9296420513119273e-08 +2.873839345572652e-08 +2.706431228354828e-08 +2.804085963398559e-08 +2.7482832576592838e-08 +2.706431228354828e-08 +2.6785298754851907e-08 +2.7343325812244652e-08 +2.650628522615553e-08 +2.4971710818325472e-08 +2.5669244640066407e-08 +2.7482832576592838e-08 +2.8877900220074708e-08 +2.9575434041815645e-08 +2.9714940806163832e-08 +2.9575434041815645e-08 +2.845937992703015e-08 +2.7761846105289214e-08 +2.6366778461807345e-08 +2.552973787571822e-08 +2.4832204053977286e-08 +2.455319052528091e-08 +2.6227271697459155e-08 +2.7343325812244652e-08 +2.5948258168762783e-08 +2.5111217582673662e-08 +2.2739602588754482e-08 +2.385565670353998e-08 +2.3437136410495414e-08 +2.3716149939191793e-08 +2.455319052528091e-08 +2.6366778461807345e-08 +3.152852874269026e-08 +2.6785298754851907e-08 +3.9759427839233295e-08 +4.366561724098254e-08 +4.5618711941857144e-08 +4.631624576359808e-08 +4.324709694793797e-08 +4.50606848844644e-08 +4.4502657827071654e-08 +4.227054959750066e-08 +3.4737184322698563e-08 +2.3576643174843603e-08 +1.9391440244397992e-08 +1.911242671570162e-08 +2.3018616117450855e-08 +2.287910935310267e-08 +1.8414892893960685e-08 +2.8598886691378335e-08 +2.4971710818325472e-08 +2.5669244640066407e-08 +2.5111217582673662e-08 +2.5390231111370035e-08 +2.552973787571822e-08 +2.6785298754851907e-08 +3.208655580008301e-08 +2.7203819047896466e-08 +3.9759427839233295e-08 +4.324709694793797e-08 +4.478167135576803e-08 +4.5618711941857144e-08 +4.199153606880429e-08 +4.3805124005330716e-08 +4.4502657827071654e-08 +4.227054959750066e-08 +3.5295211380091315e-08 +2.455319052528091e-08 +2.050749435918349e-08 +2.106552141657624e-08 +2.5390231111370035e-08 +2.46926972896291e-08 +1.855439965830887e-08 +2.706431228354828e-08 +2.4413683760932724e-08 +2.455319052528091e-08 +2.455319052528091e-08 +2.3995163467888165e-08 +2.4413683760932724e-08 +2.608776493311097e-08 +3.11100084496457e-08 +2.6785298754851907e-08 +3.920140078184055e-08 +4.2689069890545226e-08 +4.436315106272346e-08 +4.5618711941857144e-08 +4.199153606880429e-08 +4.408413753402709e-08 +4.464216459141985e-08 +4.2410056361848854e-08 +3.5713731673135874e-08 +2.4832204053977286e-08 +2.0926014652228048e-08 +2.0926014652228048e-08 +2.5111217582673662e-08 +2.5111217582673662e-08 +1.9251933480049806e-08 +2.8877900220074708e-08 +2.6227271697459155e-08 +2.6366778461807345e-08 +2.5669244640066407e-08 +2.6645791990503717e-08 +2.6645791990503717e-08 +2.8180366398333776e-08 +3.362113020791307e-08 +2.804085963398559e-08 +4.031745489662604e-08 +4.394463076967891e-08 +4.5479205177508965e-08 +4.631624576359808e-08 +4.2689069890545226e-08 +4.492117812011622e-08 +4.492117812011622e-08 +4.199153606880429e-08 +3.5295211380091315e-08 +2.5111217582673662e-08 +2.0926014652228048e-08 +2.106552141657624e-08 +2.5111217582673662e-08 +2.5669244640066407e-08 +2.008897406613893e-08 +2.943592727746746e-08 +2.650628522615553e-08 +2.6785298754851907e-08 +2.6227271697459155e-08 +2.6785298754851907e-08 +2.7343325812244652e-08 +2.9017406984422894e-08 +3.417915726530581e-08 +2.7622339340941025e-08 +3.961992107488511e-08 +4.2689069890545226e-08 +4.422364429837528e-08 +4.478167135576803e-08 +4.087548195401879e-08 +4.129400224706335e-08 +4.017794813227786e-08 +3.6550772259225e-08 +3.069148815660114e-08 +2.287910935310267e-08 +1.9391440244397992e-08 +1.9251933480049806e-08 +2.1902562002665358e-08 +2.2321082295709924e-08 +1.911242671570162e-08 +2.9993954334860204e-08 +2.706431228354828e-08 +2.7482832576592838e-08 +2.7343325812244652e-08 +2.7622339340941025e-08 +2.8598886691378335e-08 +2.7901352869637404e-08 +2.706431228354828e-08 +2.9156913748771087e-08 +3.459767755835038e-08 +3.822485343140324e-08 +4.0735975189670606e-08 +4.115449548271517e-08 +3.9759427839233295e-08 +3.794583990270687e-08 +3.724830608096593e-08 +3.5016197851394936e-08 +3.320260991486851e-08 +2.985444757051202e-08 +2.8180366398333776e-08 +2.845937992703015e-08 +2.985444757051202e-08 +3.11100084496457e-08 +3.027296786355658e-08 +2.873839345572652e-08 +2.706431228354828e-08 +2.7901352869637404e-08 +2.6645791990503717e-08 +2.6785298754851907e-08 +2.6366778461807345e-08 +2.6645791990503717e-08 +2.5669244640066407e-08 +2.385565670353998e-08 +2.5390231111370035e-08 +2.7343325812244652e-08 +2.8877900220074708e-08 +2.9714940806163832e-08 +2.985444757051202e-08 +2.943592727746746e-08 +2.8319873162681962e-08 +2.6924805519200093e-08 +2.5808751404414597e-08 +2.4971710818325472e-08 +2.413467023223635e-08 +2.385565670353998e-08 +2.4971710818325472e-08 +2.6366778461807345e-08 +2.5111217582673662e-08 +2.3995163467888165e-08 +2.246058906005811e-08 +2.3437136410495414e-08 +2.315812288179904e-08 +2.3576643174843603e-08 +2.455319052528091e-08 +2.5808751404414597e-08 +3.041247462790477e-08 +2.5948258168762783e-08 +3.8364360195751426e-08 +4.227054959750066e-08 +4.366561724098254e-08 +4.464216459141985e-08 +4.115449548271517e-08 +4.310759018358978e-08 +4.2689069890545226e-08 +4.101498871836698e-08 +3.376063697226125e-08 +2.2739602588754482e-08 +1.8693906422657058e-08 +1.855439965830887e-08 +2.1344534945272613e-08 +2.246058906005811e-08 +1.7856865836567937e-08 +2.8180366398333776e-08 +2.455319052528091e-08 +2.5390231111370035e-08 +2.4274176996584538e-08 +2.46926972896291e-08 +2.455319052528091e-08 +2.552973787571822e-08 +3.027296786355658e-08 +2.5948258168762783e-08 +3.8364360195751426e-08 +4.199153606880429e-08 +4.394463076967891e-08 +4.533969841316077e-08 +4.157301577575972e-08 +4.324709694793797e-08 +4.366561724098254e-08 +4.1433509011411543e-08 +3.487669108704675e-08 +2.3995163467888165e-08 +1.9391440244397992e-08 +1.9391440244397992e-08 +2.246058906005811e-08 +2.3576643174843603e-08 +1.813587936526431e-08 +2.650628522615553e-08 +2.3716149939191793e-08 +2.413467023223635e-08 +2.315812288179904e-08 +2.3297629646147227e-08 +2.3716149939191793e-08 +2.552973787571822e-08 +3.013346109920839e-08 +2.5948258168762783e-08 +3.8085346667055053e-08 +4.1712522540107916e-08 +4.3526110476634344e-08 +4.464216459141985e-08 +4.115449548271517e-08 +4.310759018358978e-08 +4.3805124005330716e-08 +4.157301577575972e-08 +3.459767755835038e-08 +2.4274176996584538e-08 +1.9949467301790744e-08 +1.9670453773094368e-08 +2.2600095824406296e-08 +2.4413683760932724e-08 +1.8972919951353434e-08 +2.7901352869637404e-08 +2.5111217582673662e-08 +2.5669244640066407e-08 +2.4971710818325472e-08 +2.552973787571822e-08 +2.5250724347021848e-08 +2.7203819047896466e-08 +3.22260625644312e-08 +2.7343325812244652e-08 +3.9759427839233295e-08 +4.3386603712286164e-08 +4.520019164881259e-08 +4.61767389992499e-08 +4.2689069890545226e-08 +4.464216459141985e-08 +4.492117812011622e-08 +4.199153606880429e-08 +3.5295211380091315e-08 +2.5111217582673662e-08 +2.106552141657624e-08 +2.050749435918349e-08 +2.287910935310267e-08 +2.4971710818325472e-08 +1.953094700874618e-08 +2.9017406984422894e-08 +2.5669244640066407e-08 +2.552973787571822e-08 +2.4832204053977286e-08 +2.5390231111370035e-08 +2.5808751404414597e-08 +2.706431228354828e-08 +3.180754227138664e-08 +2.608776493311097e-08 +3.794583990270687e-08 +4.129400224706335e-08 +4.324709694793797e-08 +4.4502657827071654e-08 +4.115449548271517e-08 +4.157301577575972e-08 +4.101498871836698e-08 +3.724830608096593e-08 +3.11100084496457e-08 +2.3437136410495414e-08 +1.953094700874618e-08 +1.9251933480049806e-08 +2.1344534945272613e-08 +2.218157553136173e-08 +1.911242671570162e-08 +3.013346109920839e-08 +2.706431228354828e-08 +2.7203819047896466e-08 +2.650628522615553e-08 +2.6645791990503717e-08 +2.6645791990503717e-08 +2.650628522615553e-08 +2.5808751404414597e-08 +2.804085963398559e-08 +3.3342116679216694e-08 +3.794583990270687e-08 +4.059646842532242e-08 +4.101498871836698e-08 +3.961992107488511e-08 +3.8085346667055053e-08 +3.75273196096623e-08 +3.54347181444395e-08 +3.3342116679216694e-08 +3.013346109920839e-08 +2.8598886691378335e-08 +2.873839345572652e-08 +2.9156913748771087e-08 +3.083099492094933e-08 +2.9575434041815645e-08 +2.7482832576592838e-08 +2.552973787571822e-08 +2.5948258168762783e-08 +2.4832204053977286e-08 +2.46926972896291e-08 +2.455319052528091e-08 +2.455319052528091e-08 +2.315812288179904e-08 +2.1902562002665358e-08 +2.3716149939191793e-08 +2.650628522615553e-08 +2.7901352869637404e-08 +2.8598886691378335e-08 +2.8877900220074708e-08 +2.8877900220074708e-08 +2.8180366398333776e-08 +2.7343325812244652e-08 +2.6785298754851907e-08 +2.552973787571822e-08 +2.3995163467888165e-08 +2.385565670353998e-08 +2.413467023223635e-08 +2.6366778461807345e-08 +2.4971710818325472e-08 +2.413467023223635e-08 +2.2042068767013544e-08 +2.315812288179904e-08 +2.2321082295709924e-08 +2.3018616117450855e-08 +2.3716149939191793e-08 +2.4832204053977286e-08 +2.943592727746746e-08 +2.4971710818325472e-08 +3.682978578792137e-08 +4.0735975189670606e-08 +4.2689069890545226e-08 +4.3805124005330716e-08 +3.989893460358149e-08 +4.1712522540107916e-08 +4.157301577575972e-08 +4.003844136792967e-08 +3.320260991486851e-08 +2.2739602588754482e-08 +1.8693906422657058e-08 +1.8414892893960685e-08 +2.008897406613893e-08 +2.1623548473968986e-08 +1.757785230787156e-08 +2.7203819047896466e-08 +2.46926972896291e-08 +2.5250724347021848e-08 +2.413467023223635e-08 +2.4971710818325472e-08 +2.5250724347021848e-08 +2.6227271697459155e-08 +2.9575434041815645e-08 +2.4274176996584538e-08 +3.5295211380091315e-08 +3.8782880488795985e-08 +4.059646842532242e-08 +4.1712522540107916e-08 +3.8364360195751426e-08 +4.003844136792967e-08 +3.989893460358149e-08 +3.8085346667055053e-08 +3.22260625644312e-08 +2.287910935310267e-08 +1.82753861296125e-08 +1.7856865836567937e-08 +1.9809960537442554e-08 +2.14840417096208e-08 +1.7159332014827002e-08 +2.5948258168762783e-08 +2.385565670353998e-08 +2.4413683760932724e-08 +2.315812288179904e-08 +2.3297629646147227e-08 +2.3716149939191793e-08 +2.5111217582673662e-08 +2.943592727746746e-08 +2.5250724347021848e-08 +3.7666826374010495e-08 +4.087548195401879e-08 +4.2828576654893406e-08 +4.408413753402709e-08 +4.0735975189670606e-08 +4.29680834192416e-08 +4.310759018358978e-08 +4.115449548271517e-08 +3.417915726530581e-08 +2.3995163467888165e-08 +1.9391440244397992e-08 +1.855439965830887e-08 +2.050749435918349e-08 +2.2739602588754482e-08 +1.82753861296125e-08 +2.6366778461807345e-08 +2.3297629646147227e-08 +2.3576643174843603e-08 +2.2600095824406296e-08 +2.287910935310267e-08 +2.3576643174843603e-08 +2.4971710818325472e-08 +2.9296420513119273e-08 +2.552973787571822e-08 +3.7806333138358674e-08 +4.115449548271517e-08 +4.3526110476634344e-08 +4.478167135576803e-08 +4.1433509011411543e-08 +4.310759018358978e-08 +4.3526110476634344e-08 +4.1433509011411543e-08 +3.445817079400219e-08 +2.4274176996584538e-08 +2.0367987594835303e-08 +1.953094700874618e-08 +2.0647001123531675e-08 +2.3437136410495414e-08 +1.8693906422657058e-08 +2.7622339340941025e-08 +2.455319052528091e-08 +2.4413683760932724e-08 +2.4274176996584538e-08 +2.455319052528091e-08 +2.455319052528091e-08 +2.4971710818325472e-08 +2.8319873162681962e-08 +2.3018616117450855e-08 +3.3063103150520315e-08 +3.613225196618043e-08 +3.794583990270687e-08 +3.892238725314418e-08 +3.613225196618043e-08 +3.682978578792137e-08 +3.6550772259225e-08 +3.348162344356488e-08 +2.7901352869637404e-08 +2.14840417096208e-08 +1.7996372600916123e-08 +1.7438345543523375e-08 +1.8833413187005247e-08 +1.953094700874618e-08 +1.7019825250478813e-08 +2.7203819047896466e-08 +2.315812288179904e-08 +2.3297629646147227e-08 +2.315812288179904e-08 +2.2739602588754482e-08 +2.2739602588754482e-08 +2.3576643174843603e-08 +2.455319052528091e-08 +2.9714940806163832e-08 +4.157301577575972e-08 +4.82693404644727e-08 +5.105947575143644e-08 +5.2873063687962876e-08 +5.105947575143644e-08 +5.064095545839188e-08 +5.175700957317738e-08 +5.036194192969551e-08 +4.6455752527946275e-08 +3.557422490878769e-08 +3.027296786355658e-08 +2.9017406984422894e-08 +2.9575434041815645e-08 +3.3063103150520315e-08 +2.985444757051202e-08 +2.6645791990503717e-08 +2.3576643174843603e-08 +2.3995163467888165e-08 +2.3297629646147227e-08 +2.246058906005811e-08 +2.2600095824406296e-08 +2.2321082295709924e-08 +2.050749435918349e-08 +1.9949467301790744e-08 +2.1763055238317172e-08 +2.455319052528091e-08 +2.6924805519200093e-08 +2.7343325812244652e-08 +2.845937992703015e-08 +2.8180366398333776e-08 +2.804085963398559e-08 +2.8180366398333776e-08 +2.804085963398559e-08 +2.6645791990503717e-08 +2.5390231111370035e-08 +2.4971710818325472e-08 +2.4971710818325472e-08 +2.6785298754851907e-08 +2.5948258168762783e-08 +2.5111217582673662e-08 +2.315812288179904e-08 +2.3716149939191793e-08 +2.287910935310267e-08 +2.3297629646147227e-08 +2.3716149939191793e-08 +2.4832204053977286e-08 +2.7901352869637404e-08 +2.2739602588754482e-08 +3.3063103150520315e-08 +3.557422490878769e-08 +3.75273196096623e-08 +3.8364360195751426e-08 +3.557422490878769e-08 +3.724830608096593e-08 +3.724830608096593e-08 +3.515570461574312e-08 +2.9575434041815645e-08 +2.106552141657624e-08 +1.757785230787156e-08 +1.7019825250478813e-08 +1.729883877917519e-08 +1.855439965830887e-08 +1.6043277900041506e-08 +2.5250724347021848e-08 +2.3018616117450855e-08 +2.3576643174843603e-08 +2.246058906005811e-08 +2.2600095824406296e-08 +2.287910935310267e-08 +2.3995163467888165e-08 +2.6645791990503717e-08 +2.3018616117450855e-08 +3.362113020791307e-08 +3.682978578792137e-08 +3.822485343140324e-08 +3.892238725314418e-08 +3.6690279023573184e-08 +3.850386696009961e-08 +3.86433737244478e-08 +3.682978578792137e-08 +3.069148815660114e-08 +2.2042068767013544e-08 +1.7996372600916123e-08 +1.7159332014827002e-08 +1.82753861296125e-08 +2.050749435918349e-08 +1.7019825250478813e-08 +2.5948258168762783e-08 +2.455319052528091e-08 +2.5250724347021848e-08 +2.3995163467888165e-08 +2.4274176996584538e-08 +2.455319052528091e-08 +2.5390231111370035e-08 +2.8319873162681962e-08 +2.455319052528091e-08 +3.5713731673135874e-08 +3.822485343140324e-08 +4.017794813227786e-08 +4.1433509011411543e-08 +3.822485343140324e-08 +3.961992107488511e-08 +3.948041431053692e-08 +3.75273196096623e-08 +3.180754227138664e-08 +2.246058906005811e-08 +1.82753861296125e-08 +1.7438345543523375e-08 +1.7996372600916123e-08 +2.0228480830487117e-08 +1.7159332014827002e-08 +2.650628522615553e-08 +2.3297629646147227e-08 +2.385565670353998e-08 +2.3297629646147227e-08 +2.3716149939191793e-08 +2.4413683760932724e-08 +2.5111217582673662e-08 +2.8319873162681962e-08 +2.46926972896291e-08 +3.6550772259225e-08 +3.961992107488511e-08 +4.1852029304456096e-08 +4.310759018358978e-08 +3.989893460358149e-08 +4.1712522540107916e-08 +4.213104283315248e-08 +3.989893460358149e-08 +3.3342116679216694e-08 +2.3437136410495414e-08 +1.9949467301790744e-08 +1.9251933480049806e-08 +2.0367987594835303e-08 +2.2600095824406296e-08 +1.8414892893960685e-08 +2.7203819047896466e-08 +2.455319052528091e-08 +2.46926972896291e-08 +2.3995163467888165e-08 +2.3576643174843603e-08 +2.3576643174843603e-08 +2.3576643174843603e-08 +2.5808751404414597e-08 +2.1205028180924427e-08 +3.041247462790477e-08 +3.3063103150520315e-08 +3.459767755835038e-08 +3.54347181444395e-08 +3.278408962182394e-08 +3.376063697226125e-08 +3.3342116679216694e-08 +3.0970501685297515e-08 +2.650628522615553e-08 +2.050749435918349e-08 +1.771735907221975e-08 +1.6880318486130626e-08 +1.771735907221975e-08 +1.8414892893960685e-08 +1.6880318486130626e-08 +2.6785298754851907e-08 +2.46926972896291e-08 +2.46926972896291e-08 +2.3576643174843603e-08 +2.3437136410495414e-08 +2.3297629646147227e-08 +2.315812288179904e-08 +2.1902562002665358e-08 +2.3995163467888165e-08 +2.8877900220074708e-08 +3.2644582857475756e-08 +3.5295211380091315e-08 +3.5992745201832246e-08 +3.487669108704675e-08 +3.417915726530581e-08 +3.3342116679216694e-08 +3.22260625644312e-08 +3.0970501685297515e-08 +2.8877900220074708e-08 +2.6785298754851907e-08 +2.6645791990503717e-08 +2.5948258168762783e-08 +2.7622339340941025e-08 +2.7622339340941025e-08 +2.5669244640066407e-08 +2.3437136410495414e-08 +2.3995163467888165e-08 +2.3437136410495414e-08 +2.3018616117450855e-08 +2.315812288179904e-08 +2.246058906005811e-08 +2.0228480830487117e-08 +1.9949467301790744e-08 +2.078650788787986e-08 +2.3018616117450855e-08 +2.5669244640066407e-08 +2.6366778461807345e-08 +2.804085963398559e-08 +2.8319873162681962e-08 +2.7482832576592838e-08 +2.7761846105289214e-08 +2.6785298754851907e-08 +2.608776493311097e-08 +2.552973787571822e-08 +2.4832204053977286e-08 +2.455319052528091e-08 +2.6227271697459155e-08 +2.6366778461807345e-08 +2.5669244640066407e-08 +2.4274176996584538e-08 +2.5111217582673662e-08 +2.46926972896291e-08 +2.4971710818325472e-08 +2.4971710818325472e-08 +2.6227271697459155e-08 +2.9017406984422894e-08 +2.4413683760932724e-08 +3.487669108704675e-08 +3.75273196096623e-08 +3.906189401749236e-08 +4.017794813227786e-08 +3.7666826374010495e-08 +3.948041431053692e-08 +3.920140078184055e-08 +3.724830608096593e-08 +3.124951521399389e-08 +2.218157553136173e-08 +1.82753861296125e-08 +1.7159332014827002e-08 +1.729883877917519e-08 +1.8693906422657058e-08 +1.6182784664389692e-08 +2.552973787571822e-08 +2.3018616117450855e-08 +2.3437136410495414e-08 +2.2739602588754482e-08 +2.2739602588754482e-08 +2.287910935310267e-08 +2.3995163467888165e-08 +2.7482832576592838e-08 +2.455319052528091e-08 +3.627175873052862e-08 +3.9759427839233295e-08 +4.1433509011411543e-08 +4.2549563126197034e-08 +3.9759427839233295e-08 +4.199153606880429e-08 +4.2410056361848854e-08 +4.017794813227786e-08 +3.3342116679216694e-08 +2.3297629646147227e-08 +1.9251933480049806e-08 +1.8693906422657058e-08 +1.9391440244397992e-08 +2.1623548473968986e-08 +1.813587936526431e-08 +2.804085963398559e-08 +2.5250724347021848e-08 +2.5808751404414597e-08 +2.455319052528091e-08 +2.4971710818325472e-08 +2.5250724347021848e-08 +2.6227271697459155e-08 +2.9156913748771087e-08 +2.552973787571822e-08 +3.6690279023573184e-08 +3.9759427839233295e-08 +4.1433509011411543e-08 +4.2549563126197034e-08 +3.892238725314418e-08 +4.017794813227786e-08 +4.045696166097423e-08 +3.822485343140324e-08 +3.208655580008301e-08 +2.2739602588754482e-08 +1.855439965830887e-08 +1.7856865836567937e-08 +1.8414892893960685e-08 +2.008897406613893e-08 +1.729883877917519e-08 +2.7482832576592838e-08 +2.4413683760932724e-08 +2.4832204053977286e-08 +2.455319052528091e-08 +2.4413683760932724e-08 +2.4413683760932724e-08 +2.4832204053977286e-08 +2.46926972896291e-08 +2.9993954334860204e-08 +4.031745489662604e-08 +4.533969841316077e-08 +4.729279311403539e-08 +4.93853945792582e-08 +4.82693404644727e-08 +4.8548353993169076e-08 +4.9245887814910014e-08 +4.701377958533902e-08 +4.29680834192416e-08 +3.4039650500957626e-08 +2.9156913748771087e-08 +2.7482832576592838e-08 +2.6924805519200093e-08 +2.9017406984422894e-08 +2.7901352869637404e-08 +2.552973787571822e-08 +2.4832204053977286e-08 +2.4832204053977286e-08 +2.455319052528091e-08 +2.4274176996584538e-08 +2.4413683760932724e-08 +2.46926972896291e-08 +2.4971710818325472e-08 +1.771735907221975e-08 +2.4971710818325472e-08 +2.8598886691378335e-08 +2.9714940806163832e-08 +3.0970501685297515e-08 +2.9993954334860204e-08 +2.985444757051202e-08 +3.027296786355658e-08 +2.873839345572652e-08 +2.5948258168762783e-08 +2.050749435918349e-08 +1.7438345543523375e-08 +1.6322291428737878e-08 +1.6182784664389692e-08 +1.729883877917519e-08 +1.6601304957434254e-08 +2.6645791990503717e-08 +2.5390231111370035e-08 +2.5390231111370035e-08 +2.455319052528091e-08 +2.46926972896291e-08 +2.4413683760932724e-08 +2.3995163467888165e-08 +2.246058906005811e-08 +2.455319052528091e-08 +3.013346109920839e-08 +3.4318664029654005e-08 +3.710879931661774e-08 +3.7666826374010495e-08 +3.6550772259225e-08 +3.557422490878769e-08 +3.487669108704675e-08 +3.348162344356488e-08 +3.1947049035734825e-08 +2.9296420513119273e-08 +2.706431228354828e-08 +2.6924805519200093e-08 +2.6645791990503717e-08 +2.7482832576592838e-08 +2.7622339340941025e-08 +2.6366778461807345e-08 +2.3995163467888165e-08 +2.4832204053977286e-08 +2.3995163467888165e-08 +2.413467023223635e-08 +2.3995163467888165e-08 +2.315812288179904e-08 +2.14840417096208e-08 +2.0926014652228048e-08 +2.1763055238317172e-08 +2.3995163467888165e-08 +2.5948258168762783e-08 +2.6645791990503717e-08 +2.7343325812244652e-08 +2.7901352869637404e-08 +2.6785298754851907e-08 +2.6366778461807345e-08 +2.5390231111370035e-08 +2.46926972896291e-08 +2.3995163467888165e-08 +2.3437136410495414e-08 +2.3297629646147227e-08 +2.4971710818325472e-08 +2.5111217582673662e-08 +2.46926972896291e-08 +2.2739602588754482e-08 +2.385565670353998e-08 +2.3437136410495414e-08 +2.3995163467888165e-08 +2.3995163467888165e-08 +2.4971710818325472e-08 +2.8598886691378335e-08 +2.552973787571822e-08 +3.7806333138358674e-08 +4.087548195401879e-08 +4.2828576654893406e-08 +4.436315106272346e-08 +4.115449548271517e-08 +4.310759018358978e-08 +4.310759018358978e-08 +4.087548195401879e-08 +3.390014373660944e-08 +2.3576643174843603e-08 +1.8972919951353434e-08 +1.7996372600916123e-08 +1.813587936526431e-08 +1.9949467301790744e-08 +1.7019825250478813e-08 +2.650628522615553e-08 +2.3716149939191793e-08 +2.385565670353998e-08 +2.385565670353998e-08 +2.3995163467888165e-08 +2.3716149939191793e-08 +2.4274176996584538e-08 +2.804085963398559e-08 +2.5390231111370035e-08 +3.724830608096593e-08 +4.087548195401879e-08 +4.2828576654893406e-08 +4.436315106272346e-08 +4.101498871836698e-08 +4.324709694793797e-08 +4.3386603712286164e-08 +4.115449548271517e-08 +3.445817079400219e-08 +2.3716149939191793e-08 +1.9949467301790744e-08 +1.953094700874618e-08 +1.9670453773094368e-08 +2.1344534945272613e-08 +1.813587936526431e-08 +2.845937992703015e-08 +2.4832204053977286e-08 +2.4971710818325472e-08 +2.385565670353998e-08 +2.3995163467888165e-08 +2.4274176996584538e-08 +2.5250724347021848e-08 +2.873839345572652e-08 +2.5808751404414597e-08 +3.8085346667055053e-08 +4.157301577575972e-08 +4.310759018358978e-08 +4.436315106272346e-08 +4.0735975189670606e-08 +4.2410056361848854e-08 +4.29680834192416e-08 +4.045696166097423e-08 +3.362113020791307e-08 +2.3716149939191793e-08 +1.9251933480049806e-08 +1.855439965830887e-08 +1.8833413187005247e-08 +2.0367987594835303e-08 +1.82753861296125e-08 +2.7761846105289214e-08 +2.413467023223635e-08 +2.4413683760932724e-08 +2.3437136410495414e-08 +2.3995163467888165e-08 +2.3437136410495414e-08 +2.385565670353998e-08 +2.7622339340941025e-08 +2.5111217582673662e-08 +3.682978578792137e-08 +4.059646842532242e-08 +4.2689069890545226e-08 +4.422364429837528e-08 +4.129400224706335e-08 +4.3526110476634344e-08 +4.3805124005330716e-08 +4.1433509011411543e-08 +3.5295211380091315e-08 +2.46926972896291e-08 +2.0228480830487117e-08 +1.9670453773094368e-08 +1.9809960537442554e-08 +2.1344534945272613e-08 +1.911242671570162e-08 +2.8180366398333776e-08 +2.4971710818325472e-08 +2.4971710818325472e-08 +2.413467023223635e-08 +2.3995163467888165e-08 +2.4274176996584538e-08 +2.4413683760932724e-08 +2.6785298754851907e-08 +2.3018616117450855e-08 +3.320260991486851e-08 +3.6690279023573184e-08 +3.822485343140324e-08 +3.8782880488795985e-08 +3.5713731673135874e-08 +3.6550772259225e-08 +3.5992745201832246e-08 +3.362113020791307e-08 +2.845937992703015e-08 +2.2321082295709924e-08 +1.8972919951353434e-08 +1.82753861296125e-08 +1.8414892893960685e-08 +1.9670453773094368e-08 +1.82753861296125e-08 +2.8877900220074708e-08 +2.5669244640066407e-08 +2.5111217582673662e-08 +2.385565670353998e-08 +2.3995163467888165e-08 +2.413467023223635e-08 +2.3018616117450855e-08 +2.2042068767013544e-08 +2.4274176996584538e-08 +2.985444757051202e-08 +3.4318664029654005e-08 +3.696929255226956e-08 +3.794583990270687e-08 +3.6550772259225e-08 +3.515570461574312e-08 +3.487669108704675e-08 +3.362113020791307e-08 +3.1947049035734825e-08 +2.9017406984422894e-08 +2.7482832576592838e-08 +2.7203819047896466e-08 +2.650628522615553e-08 +2.6924805519200093e-08 +2.706431228354828e-08 +2.608776493311097e-08 +2.413467023223635e-08 +2.4832204053977286e-08 +2.3995163467888165e-08 +2.3576643174843603e-08 +2.3716149939191793e-08 +2.3297629646147227e-08 +2.246058906005811e-08 +2.2739602588754482e-08 +2.3995163467888165e-08 +2.5808751404414597e-08 +2.7761846105289214e-08 +2.845937992703015e-08 +2.8598886691378335e-08 +2.804085963398559e-08 +2.6924805519200093e-08 +2.5808751404414597e-08 +2.552973787571822e-08 +2.5250724347021848e-08 +2.4274176996584538e-08 +2.4413683760932724e-08 +2.4413683760932724e-08 +2.5111217582673662e-08 +2.5390231111370035e-08 +2.4413683760932724e-08 +2.413467023223635e-08 +2.4832204053977286e-08 +2.3995163467888165e-08 +2.3576643174843603e-08 +2.3716149939191793e-08 +2.3297629646147227e-08 +2.246058906005811e-08 +2.2739602588754482e-08 +2.3995163467888165e-08 +2.5808751404414597e-08 +2.7761846105289214e-08 +2.845937992703015e-08 +2.8598886691378335e-08 +2.804085963398559e-08 +2.6924805519200093e-08 +2.5808751404414597e-08 +2.552973787571822e-08 +2.5250724347021848e-08 +2.4274176996584538e-08 +2.4413683760932724e-08 +2.4413683760932724e-08 +2.5111217582673662e-08 +2.5390231111370035e-08 +2.4413683760932724e-08 +2.315812288179904e-08 +2.3576643174843603e-08 +2.3297629646147227e-08 +2.3716149939191793e-08 +2.3018616117450855e-08 +2.3576643174843603e-08 +2.7343325812244652e-08 +2.5111217582673662e-08 +3.710879931661774e-08 +4.0735975189670606e-08 +4.2828576654893406e-08 +4.408413753402709e-08 +4.0735975189670606e-08 +4.324709694793797e-08 +4.324709694793797e-08 +4.129400224706335e-08 +3.4318664029654005e-08 +2.385565670353998e-08 +1.9391440244397992e-08 +1.855439965830887e-08 +1.8414892893960685e-08 +1.953094700874618e-08 +1.7438345543523375e-08 +2.650628522615553e-08 +2.315812288179904e-08 +2.3437136410495414e-08 +2.2739602588754482e-08 +2.2739602588754482e-08 +2.3437136410495414e-08 +2.3297629646147227e-08 +2.7203819047896466e-08 +2.5390231111370035e-08 +3.794583990270687e-08 +4.157301577575972e-08 +4.366561724098254e-08 +4.533969841316077e-08 +4.1712522540107916e-08 +4.3386603712286164e-08 +4.366561724098254e-08 +4.1433509011411543e-08 +3.459767755835038e-08 +2.455319052528091e-08 +2.0647001123531675e-08 +1.9809960537442554e-08 +1.8833413187005247e-08 +2.0228480830487117e-08 +1.8414892893960685e-08 +2.804085963398559e-08 +2.6924805519200093e-08 +2.6785298754851907e-08 +2.5669244640066407e-08 +2.650628522615553e-08 +2.6645791990503717e-08 +2.4971710818325472e-08 +2.8180366398333776e-08 +2.552973787571822e-08 +3.7666826374010495e-08 +4.1433509011411543e-08 +4.3386603712286164e-08 +4.50606848844644e-08 +4.1852029304456096e-08 +4.394463076967891e-08 +4.408413753402709e-08 +4.1852029304456096e-08 +3.54347181444395e-08 +2.4971710818325472e-08 +2.0228480830487117e-08 +1.911242671570162e-08 +1.9251933480049806e-08 +2.0228480830487117e-08 +1.8414892893960685e-08 +2.7343325812244652e-08 +2.385565670353998e-08 +2.413467023223635e-08 +2.3297629646147227e-08 +2.3437136410495414e-08 +2.385565670353998e-08 +2.3576643174843603e-08 +2.6227271697459155e-08 +2.3437136410495414e-08 +3.4318664029654005e-08 +3.7806333138358674e-08 +3.948041431053692e-08 +4.031745489662604e-08 +3.682978578792137e-08 +3.7806333138358674e-08 +3.710879931661774e-08 +3.417915726530581e-08 +2.873839345572652e-08 +2.2042068767013544e-08 +1.8693906422657058e-08 +1.7996372600916123e-08 +1.7856865836567937e-08 +1.8833413187005247e-08 +1.82753861296125e-08 +2.9017406984422894e-08 +2.5808751404414597e-08 +2.5111217582673662e-08 +2.3297629646147227e-08 +2.2739602588754482e-08 +2.2739602588754482e-08 +2.14840417096208e-08 +2.0926014652228048e-08 +2.3576643174843603e-08 +2.9156913748771087e-08 +3.390014373660944e-08 +3.6411265494876805e-08 +3.7666826374010495e-08 +3.627175873052862e-08 +3.557422490878769e-08 +3.5295211380091315e-08 +3.417915726530581e-08 +3.208655580008301e-08 +2.9575434041815645e-08 +2.7901352869637404e-08 +2.7761846105289214e-08 +2.6785298754851907e-08 +2.6645791990503717e-08 +2.706431228354828e-08 +2.5808751404414597e-08 +2.3576643174843603e-08 +2.385565670353998e-08 +2.315812288179904e-08 +2.287910935310267e-08 +2.3018616117450855e-08 +2.2042068767013544e-08 +2.1344534945272613e-08 +2.287910935310267e-08 +2.455319052528091e-08 +2.608776493311097e-08 +2.8180366398333776e-08 +2.8877900220074708e-08 +2.873839345572652e-08 +2.7901352869637404e-08 +2.6785298754851907e-08 +2.5948258168762783e-08 +2.5111217582673662e-08 +2.5250724347021848e-08 +2.4832204053977286e-08 +2.4971710818325472e-08 +2.455319052528091e-08 +2.4274176996584538e-08 +2.5111217582673662e-08 +2.4274176996584538e-08 +2.2739602588754482e-08 +2.3995163467888165e-08 +2.3297629646147227e-08 +2.3716149939191793e-08 +2.3995163467888165e-08 +2.2739602588754482e-08 +2.650628522615553e-08 +2.4413683760932724e-08 +3.6690279023573184e-08 +4.017794813227786e-08 +4.115449548271517e-08 +4.2689069890545226e-08 +3.920140078184055e-08 +4.1433509011411543e-08 +4.1433509011411543e-08 +3.9759427839233295e-08 +3.348162344356488e-08 +2.287910935310267e-08 +1.8833413187005247e-08 +1.7996372600916123e-08 +1.7019825250478813e-08 +1.7159332014827002e-08 +1.6182784664389692e-08 +2.5250724347021848e-08 +2.3716149939191793e-08 +2.3995163467888165e-08 +2.315812288179904e-08 +2.3716149939191793e-08 +2.413467023223635e-08 +2.385565670353998e-08 +2.7482832576592838e-08 +2.4971710818325472e-08 +3.710879931661774e-08 +4.115449548271517e-08 +4.29680834192416e-08 +4.422364429837528e-08 +4.087548195401879e-08 +4.29680834192416e-08 +4.324709694793797e-08 +4.101498871836698e-08 +3.417915726530581e-08 +2.3437136410495414e-08 +1.8833413187005247e-08 +1.7856865836567937e-08 +1.729883877917519e-08 +1.813587936526431e-08 +1.7438345543523375e-08 +2.6785298754851907e-08 +2.413467023223635e-08 +2.4971710818325472e-08 +2.4274176996584538e-08 +2.413467023223635e-08 +2.4832204053977286e-08 +2.385565670353998e-08 +2.804085963398559e-08 +2.5808751404414597e-08 +3.8085346667055053e-08 +4.1852029304456096e-08 +4.408413753402709e-08 +4.5618711941857144e-08 +4.2549563126197034e-08 +4.408413753402709e-08 +4.408413753402709e-08 +4.227054959750066e-08 +3.5295211380091315e-08 +2.4971710818325472e-08 +2.0926014652228048e-08 +2.008897406613893e-08 +1.8972919951353434e-08 +1.9391440244397992e-08 +1.8833413187005247e-08 +2.8877900220074708e-08 +2.5808751404414597e-08 +2.5111217582673662e-08 +2.4832204053977286e-08 +2.5390231111370035e-08 +2.5669244640066407e-08 +2.4413683760932724e-08 +2.804085963398559e-08 +2.5250724347021848e-08 +3.75273196096623e-08 +4.115449548271517e-08 +4.2828576654893406e-08 +4.422364429837528e-08 +4.101498871836698e-08 +4.29680834192416e-08 +4.310759018358978e-08 +4.087548195401879e-08 +3.445817079400219e-08 +2.413467023223635e-08 +1.9670453773094368e-08 +1.8693906422657058e-08 +1.8972919951353434e-08 +1.8972919951353434e-08 +1.757785230787156e-08 +2.650628522615553e-08 +2.3437136410495414e-08 +2.385565670353998e-08 +2.287910935310267e-08 +2.3018616117450855e-08 +2.287910935310267e-08 +2.2600095824406296e-08 +2.5948258168762783e-08 +2.315812288179904e-08 +3.390014373660944e-08 +3.7387812845314116e-08 +3.9340907546188736e-08 +4.059646842532242e-08 +3.724830608096593e-08 +3.8085346667055053e-08 +3.724830608096593e-08 +3.4039650500957626e-08 +2.8598886691378335e-08 +2.1902562002665358e-08 +1.8414892893960685e-08 +1.757785230787156e-08 +1.6880318486130626e-08 +1.6880318486130626e-08 +1.7159332014827002e-08 +2.7761846105289214e-08 +2.4832204053977286e-08 +2.455319052528091e-08 +2.2600095824406296e-08 +2.2042068767013544e-08 +2.1902562002665358e-08 +2.0647001123531675e-08 +2.078650788787986e-08 +2.3995163467888165e-08 +2.9156913748771087e-08 +3.362113020791307e-08 +3.6411265494876805e-08 +3.75273196096623e-08 +3.613225196618043e-08 +3.557422490878769e-08 +3.4737184322698563e-08 +3.376063697226125e-08 +3.152852874269026e-08 +2.9296420513119273e-08 +2.7343325812244652e-08 +2.7761846105289214e-08 +2.6785298754851907e-08 +2.6227271697459155e-08 +2.6924805519200093e-08 +2.608776493311097e-08 +2.385565670353998e-08 +2.413467023223635e-08 +2.3297629646147227e-08 +2.315812288179904e-08 +2.315812288179904e-08 +2.1623548473968986e-08 +2.0367987594835303e-08 +2.1623548473968986e-08 +2.3576643174843603e-08 +2.5948258168762783e-08 +2.8180366398333776e-08 +2.943592727746746e-08 +2.9575434041815645e-08 +2.845937992703015e-08 +2.7622339340941025e-08 +2.7203819047896466e-08 +2.608776493311097e-08 +2.6227271697459155e-08 +2.5948258168762783e-08 +2.552973787571822e-08 +2.5390231111370035e-08 +2.5390231111370035e-08 +2.6227271697459155e-08 +2.4971710818325472e-08 +2.4413683760932724e-08 +2.5111217582673662e-08 +2.46926972896291e-08 +2.4832204053977286e-08 +2.5111217582673662e-08 +2.4971710818325472e-08 +2.873839345572652e-08 +2.552973787571822e-08 +3.7666826374010495e-08 +4.129400224706335e-08 +4.310759018358978e-08 +4.422364429837528e-08 +4.101498871836698e-08 +4.324709694793797e-08 +4.3526110476634344e-08 +4.1433509011411543e-08 +3.5016197851394936e-08 +2.455319052528091e-08 +2.0367987594835303e-08 +1.9251933480049806e-08 +1.82753861296125e-08 +1.771735907221975e-08 +1.674081172178244e-08 +2.6645791990503717e-08 +2.46926972896291e-08 +2.4971710818325472e-08 +2.413467023223635e-08 +2.4274176996584538e-08 +2.4832204053977286e-08 +2.46926972896291e-08 +2.7901352869637404e-08 +2.5390231111370035e-08 +3.7666826374010495e-08 +4.1712522540107916e-08 +4.3805124005330716e-08 +4.5479205177508965e-08 +4.1852029304456096e-08 +4.3526110476634344e-08 +4.422364429837528e-08 +4.213104283315248e-08 +3.5295211380091315e-08 +2.455319052528091e-08 +1.9949467301790744e-08 +1.855439965830887e-08 +1.7996372600916123e-08 +1.855439965830887e-08 +1.757785230787156e-08 +2.7482832576592838e-08 +2.46926972896291e-08 +2.552973787571822e-08 +2.4832204053977286e-08 +2.4971710818325472e-08 +2.4971710818325472e-08 +2.4832204053977286e-08 +2.8877900220074708e-08 +2.5669244640066407e-08 +3.75273196096623e-08 +4.129400224706335e-08 +4.324709694793797e-08 +4.464216459141985e-08 +4.1712522540107916e-08 +4.310759018358978e-08 +4.3386603712286164e-08 +4.129400224706335e-08 +3.445817079400219e-08 +2.4413683760932724e-08 +1.953094700874618e-08 +1.8414892893960685e-08 +1.82753861296125e-08 +1.855439965830887e-08 +1.771735907221975e-08 +2.7203819047896466e-08 +2.4274176996584538e-08 +2.4274176996584538e-08 +2.3297629646147227e-08 +2.3437136410495414e-08 +2.3576643174843603e-08 +2.3437136410495414e-08 +2.7761846105289214e-08 +2.4971710818325472e-08 +3.710879931661774e-08 +4.0735975189670606e-08 +4.29680834192416e-08 +4.422364429837528e-08 +4.101498871836698e-08 +4.2828576654893406e-08 +4.310759018358978e-08 +4.087548195401879e-08 +3.417915726530581e-08 +2.3995163467888165e-08 +1.9251933480049806e-08 +1.82753861296125e-08 +1.813587936526431e-08 +1.7856865836567937e-08 +1.7438345543523375e-08 +2.7343325812244652e-08 +2.3716149939191793e-08 +2.3995163467888165e-08 +2.2321082295709924e-08 +2.287910935310267e-08 +2.246058906005811e-08 +2.1902562002665358e-08 +2.5111217582673662e-08 +2.2600095824406296e-08 +3.362113020791307e-08 +3.724830608096593e-08 +3.920140078184055e-08 +4.045696166097423e-08 +3.724830608096593e-08 +3.794583990270687e-08 +3.696929255226956e-08 +3.4039650500957626e-08 +2.8598886691378335e-08 +2.1623548473968986e-08 +1.82753861296125e-08 +1.729883877917519e-08 +1.6322291428737878e-08 +1.6043277900041506e-08 +1.6182784664389692e-08 +2.6924805519200093e-08 +2.3995163467888165e-08 +2.3716149939191793e-08 +2.2321082295709924e-08 +2.1763055238317172e-08 +2.1763055238317172e-08 +2.008897406613893e-08 +2.050749435918349e-08 +2.3716149939191793e-08 +2.845937992703015e-08 +3.2644582857475756e-08 +3.5713731673135874e-08 +3.696929255226956e-08 +3.557422490878769e-08 +3.445817079400219e-08 +3.348162344356488e-08 +3.320260991486851e-08 +3.069148815660114e-08 +2.804085963398559e-08 +2.5948258168762783e-08 +2.6366778461807345e-08 +2.552973787571822e-08 +2.5111217582673662e-08 +2.6227271697459155e-08 +2.5808751404414597e-08 +2.3716149939191793e-08 +2.4274176996584538e-08 +2.2739602588754482e-08 +2.2739602588754482e-08 +2.2600095824406296e-08 +2.0647001123531675e-08 +1.9670453773094368e-08 +2.078650788787986e-08 +2.2321082295709924e-08 +2.5111217582673662e-08 +2.7203819047896466e-08 +2.8598886691378335e-08 +2.9017406984422894e-08 +2.873839345572652e-08 +2.804085963398559e-08 +2.8319873162681962e-08 +2.7622339340941025e-08 +2.6924805519200093e-08 +2.6366778461807345e-08 +2.608776493311097e-08 +2.5948258168762783e-08 +2.608776493311097e-08 +2.650628522615553e-08 +2.5390231111370035e-08 +2.3716149939191793e-08 +2.4413683760932724e-08 +2.3716149939191793e-08 +2.3716149939191793e-08 +2.3995163467888165e-08 +2.3716149939191793e-08 +2.7901352869637404e-08 +2.46926972896291e-08 +3.710879931661774e-08 +4.087548195401879e-08 +4.324709694793797e-08 +4.478167135576803e-08 +4.199153606880429e-08 +4.3386603712286164e-08 +4.310759018358978e-08 +4.087548195401879e-08 +3.4039650500957626e-08 +2.385565670353998e-08 +2.008897406613893e-08 +1.953094700874618e-08 +1.813587936526431e-08 +1.757785230787156e-08 +1.674081172178244e-08 +2.6366778461807345e-08 +2.3297629646147227e-08 +2.385565670353998e-08 +2.3018616117450855e-08 +2.3297629646147227e-08 +2.315812288179904e-08 +2.3437136410495414e-08 +2.6645791990503717e-08 +2.455319052528091e-08 +3.682978578792137e-08 +4.059646842532242e-08 +4.310759018358978e-08 +4.464216459141985e-08 +4.115449548271517e-08 +4.2828576654893406e-08 +4.366561724098254e-08 +4.1712522540107916e-08 +3.5016197851394936e-08 +2.455319052528091e-08 +2.008897406613893e-08 +1.8414892893960685e-08 +1.7856865836567937e-08 +1.813587936526431e-08 +1.7159332014827002e-08 +2.6645791990503717e-08 +2.385565670353998e-08 +2.4274176996584538e-08 +2.3576643174843603e-08 +2.3716149939191793e-08 +2.3576643174843603e-08 +2.3716149939191793e-08 +2.7622339340941025e-08 +2.5250724347021848e-08 +3.710879931661774e-08 +4.115449548271517e-08 +4.29680834192416e-08 +4.4502657827071654e-08 +4.129400224706335e-08 +4.2549563126197034e-08 +4.29680834192416e-08 +4.1433509011411543e-08 +3.459767755835038e-08 +2.4274176996584538e-08 +1.9251933480049806e-08 +1.771735907221975e-08 +1.729883877917519e-08 +1.729883877917519e-08 +1.6601304957434254e-08 +2.6645791990503717e-08 +2.4274176996584538e-08 +2.455319052528091e-08 +2.2739602588754482e-08 +2.2739602588754482e-08 +2.3437136410495414e-08 +2.3576643174843603e-08 +2.7482832576592838e-08 +2.4971710818325472e-08 +3.7387812845314116e-08 +4.129400224706335e-08 +4.394463076967891e-08 +4.5479205177508965e-08 +4.2689069890545226e-08 +4.464216459141985e-08 +4.50606848844644e-08 +4.310759018358978e-08 +3.613225196618043e-08 +2.5669244640066407e-08 +2.050749435918349e-08 +1.911242671570162e-08 +1.8693906422657058e-08 +1.813587936526431e-08 +1.7438345543523375e-08 +2.7482832576592838e-08 +2.4413683760932724e-08 +2.455319052528091e-08 +2.2739602588754482e-08 +2.3297629646147227e-08 +2.3018616117450855e-08 +2.246058906005811e-08 +2.5808751404414597e-08 +2.3576643174843603e-08 +3.5295211380091315e-08 +3.906189401749236e-08 +4.129400224706335e-08 +4.213104283315248e-08 +3.86433737244478e-08 +3.948041431053692e-08 +3.8782880488795985e-08 +3.557422490878769e-08 +2.943592727746746e-08 +2.1902562002665358e-08 +1.855439965830887e-08 +1.729883877917519e-08 +1.6601304957434254e-08 +1.6322291428737878e-08 +1.576426437134513e-08 +2.650628522615553e-08 +2.3437136410495414e-08 +2.315812288179904e-08 +2.1902562002665358e-08 +2.14840417096208e-08 +2.1344534945272613e-08 +1.9670453773094368e-08 +1.9670453773094368e-08 +2.246058906005811e-08 +2.7761846105289214e-08 +3.1668035507038446e-08 +3.445817079400219e-08 +3.54347181444395e-08 +3.390014373660944e-08 +3.278408962182394e-08 +3.1947049035734825e-08 +3.152852874269026e-08 +2.9575434041815645e-08 +2.706431228354828e-08 +2.4971710818325472e-08 +2.455319052528091e-08 +2.3995163467888165e-08 +2.3716149939191793e-08 +2.5390231111370035e-08 +2.4971710818325472e-08 +2.287910935310267e-08 +2.3297629646147227e-08 +2.2042068767013544e-08 +2.1902562002665358e-08 +2.14840417096208e-08 +1.9809960537442554e-08 +1.8693906422657058e-08 +1.9391440244397992e-08 +2.078650788787986e-08 +2.315812288179904e-08 +2.4971710818325472e-08 +2.608776493311097e-08 +2.6645791990503717e-08 +2.7203819047896466e-08 +2.6645791990503717e-08 +2.706431228354828e-08 +2.650628522615553e-08 +2.5250724347021848e-08 +2.4832204053977286e-08 +2.4274176996584538e-08 +2.46926972896291e-08 +2.4832204053977286e-08 +2.5808751404414597e-08 +2.5250724347021848e-08 +2.2042068767013544e-08 +2.246058906005811e-08 +2.14840417096208e-08 +2.1623548473968986e-08 +2.1902562002665358e-08 +2.106552141657624e-08 +2.552973787571822e-08 +2.3576643174843603e-08 +3.613225196618043e-08 +3.948041431053692e-08 +4.199153606880429e-08 +4.3805124005330716e-08 +4.0735975189670606e-08 +4.2410056361848854e-08 +4.213104283315248e-08 +4.017794813227786e-08 +3.362113020791307e-08 +2.3297629646147227e-08 +1.911242671570162e-08 +1.855439965830887e-08 +1.7159332014827002e-08 +1.7019825250478813e-08 +1.6601304957434254e-08 +2.7203819047896466e-08 +2.455319052528091e-08 +2.4413683760932724e-08 +2.3995163467888165e-08 +2.4832204053977286e-08 +2.46926972896291e-08 +2.413467023223635e-08 +2.7622339340941025e-08 +2.4971710818325472e-08 +3.7387812845314116e-08 +4.101498871836698e-08 +4.29680834192416e-08 +4.436315106272346e-08 +4.115449548271517e-08 +4.310759018358978e-08 +4.366561724098254e-08 +4.157301577575972e-08 +3.5016197851394936e-08 +2.4413683760932724e-08 +2.008897406613893e-08 +1.8414892893960685e-08 +1.7019825250478813e-08 +1.6880318486130626e-08 +1.7159332014827002e-08 +2.6924805519200093e-08 +2.4274176996584538e-08 +2.3995163467888165e-08 +2.287910935310267e-08 +2.3018616117450855e-08 +2.3018616117450855e-08 +2.2321082295709924e-08 +2.650628522615553e-08 +2.46926972896291e-08 +3.6690279023573184e-08 +4.059646842532242e-08 +4.2549563126197034e-08 +4.394463076967891e-08 +4.0735975189670606e-08 +4.2410056361848854e-08 +4.310759018358978e-08 +4.157301577575972e-08 +3.5016197851394936e-08 +2.455319052528091e-08 +1.9391440244397992e-08 +1.7856865836567937e-08 +1.7019825250478813e-08 +1.674081172178244e-08 +1.7159332014827002e-08 +2.7761846105289214e-08 +2.5111217582673662e-08 +2.4971710818325472e-08 +2.3716149939191793e-08 +2.3716149939191793e-08 +2.4274176996584538e-08 +2.3716149939191793e-08 +2.7343325812244652e-08 +2.4832204053977286e-08 +3.696929255226956e-08 +4.101498871836698e-08 +4.3386603712286164e-08 +4.50606848844644e-08 +4.2828576654893406e-08 +4.4502657827071654e-08 +4.478167135576803e-08 +4.29680834192416e-08 +3.6411265494876805e-08 +2.5669244640066407e-08 +2.078650788787986e-08 +1.9251933480049806e-08 +1.8693906422657058e-08 +1.82753861296125e-08 +1.7996372600916123e-08 +2.8180366398333776e-08 +2.455319052528091e-08 +2.455319052528091e-08 +2.3437136410495414e-08 +2.385565670353998e-08 +2.385565670353998e-08 +2.385565670353998e-08 +2.7622339340941025e-08 +2.4274176996584538e-08 +3.585323843748406e-08 +3.948041431053692e-08 +4.1712522540107916e-08 +4.310759018358978e-08 +3.9759427839233295e-08 +4.045696166097423e-08 +3.9759427839233295e-08 +3.627175873052862e-08 +2.9993954334860204e-08 +2.2321082295709924e-08 +1.8833413187005247e-08 +1.757785230787156e-08 +1.7019825250478813e-08 +1.6461798193086064e-08 +1.6043277900041506e-08 +2.6785298754851907e-08 +2.3995163467888165e-08 +2.3995163467888165e-08 +2.3018616117450855e-08 +2.2739602588754482e-08 +2.218157553136173e-08 +2.0926014652228048e-08 +2.0367987594835303e-08 +2.3576643174843603e-08 +2.9017406984422894e-08 +3.3342116679216694e-08 +3.5713731673135874e-08 +3.682978578792137e-08 +3.487669108704675e-08 +3.376063697226125e-08 +3.278408962182394e-08 +3.1668035507038446e-08 +3.013346109920839e-08 +2.7482832576592838e-08 +2.5808751404414597e-08 +2.5390231111370035e-08 +2.5669244640066407e-08 +2.4832204053977286e-08 +2.5808751404414597e-08 +2.4832204053977286e-08 +2.2739602588754482e-08 +2.315812288179904e-08 +2.218157553136173e-08 +2.2042068767013544e-08 +2.1763055238317172e-08 +2.050749435918349e-08 +1.9251933480049806e-08 +2.050749435918349e-08 +2.2042068767013544e-08 +2.385565670353998e-08 +2.5808751404414597e-08 +2.7343325812244652e-08 +2.804085963398559e-08 +2.8180366398333776e-08 +2.7761846105289214e-08 +2.7761846105289214e-08 +2.650628522615553e-08 +2.5390231111370035e-08 +2.46926972896291e-08 +2.3995163467888165e-08 +2.4413683760932724e-08 +2.413467023223635e-08 +2.5250724347021848e-08 +2.4971710818325472e-08 +2.218157553136173e-08 +2.2739602588754482e-08 +2.2042068767013544e-08 +2.2321082295709924e-08 +2.2600095824406296e-08 +2.1763055238317172e-08 +2.5669244640066407e-08 +2.3995163467888165e-08 +3.6411265494876805e-08 +4.003844136792967e-08 +4.2549563126197034e-08 +4.436315106272346e-08 +4.129400224706335e-08 +4.3526110476634344e-08 +4.366561724098254e-08 +4.115449548271517e-08 +3.4318664029654005e-08 +2.3995163467888165e-08 +1.8972919951353434e-08 +1.82753861296125e-08 +1.7438345543523375e-08 +1.7019825250478813e-08 +1.6880318486130626e-08 +2.7622339340941025e-08 +2.5250724347021848e-08 +2.5390231111370035e-08 +2.5390231111370035e-08 +2.5669244640066407e-08 +2.5669244640066407e-08 +2.4832204053977286e-08 +2.873839345572652e-08 +2.5948258168762783e-08 +3.8364360195751426e-08 +4.227054959750066e-08 +4.4502657827071654e-08 +4.575821870620534e-08 +4.2410056361848854e-08 +4.436315106272346e-08 +4.478167135576803e-08 +4.29680834192416e-08 +3.6411265494876805e-08 +2.6227271697459155e-08 +2.1344534945272613e-08 +2.008897406613893e-08 +1.8833413187005247e-08 +1.82753861296125e-08 +1.813587936526431e-08 +2.9575434041815645e-08 +2.6785298754851907e-08 +2.706431228354828e-08 +2.6366778461807345e-08 +2.6924805519200093e-08 +2.608776493311097e-08 +2.5111217582673662e-08 +2.8877900220074708e-08 +2.552973787571822e-08 +3.8085346667055053e-08 +4.157301577575972e-08 +4.3805124005330716e-08 +4.520019164881259e-08 +4.1852029304456096e-08 +4.3805124005330716e-08 +4.408413753402709e-08 +4.199153606880429e-08 +3.5295211380091315e-08 +2.5111217582673662e-08 +2.0228480830487117e-08 +1.8972919951353434e-08 +1.855439965830887e-08 +1.855439965830887e-08 +1.82753861296125e-08 +2.9296420513119273e-08 +2.6227271697459155e-08 +2.650628522615553e-08 +2.5669244640066407e-08 +2.4971710818325472e-08 +2.552973787571822e-08 +2.413467023223635e-08 +2.7901352869637404e-08 +2.5111217582673662e-08 +3.724830608096593e-08 +4.087548195401879e-08 +4.2689069890545226e-08 +4.422364429837528e-08 +4.1852029304456096e-08 +4.3386603712286164e-08 +4.366561724098254e-08 +4.199153606880429e-08 +3.5713731673135874e-08 +2.5250724347021848e-08 +2.078650788787986e-08 +1.9251933480049806e-08 +1.911242671570162e-08 +1.855439965830887e-08 +1.7996372600916123e-08 +2.7901352869637404e-08 +2.4413683760932724e-08 +2.4274176996584538e-08 +2.3576643174843603e-08 +2.3995163467888165e-08 +2.385565670353998e-08 +2.4274176996584538e-08 +2.8319873162681962e-08 +2.455319052528091e-08 +3.5992745201832246e-08 +3.961992107488511e-08 +4.213104283315248e-08 +4.3386603712286164e-08 +4.003844136792967e-08 +4.059646842532242e-08 +3.961992107488511e-08 +3.5992745201832246e-08 +2.985444757051202e-08 +2.246058906005811e-08 +1.8972919951353434e-08 +1.7856865836567937e-08 +1.7159332014827002e-08 +1.6322291428737878e-08 +1.6043277900041506e-08 +2.6924805519200093e-08 +2.4274176996584538e-08 +2.455319052528091e-08 +2.385565670353998e-08 +2.3018616117450855e-08 +2.2739602588754482e-08 +2.1205028180924427e-08 +2.0926014652228048e-08 +2.385565670353998e-08 +2.9017406984422894e-08 +3.3342116679216694e-08 +3.613225196618043e-08 +3.710879931661774e-08 +3.557422490878769e-08 +3.4318664029654005e-08 +3.320260991486851e-08 +3.250507609312757e-08 +3.0551981392252956e-08 +2.7901352869637404e-08 +2.6645791990503717e-08 +2.5948258168762783e-08 +2.7203819047896466e-08 +2.5808751404414597e-08 +2.608776493311097e-08 +2.5390231111370035e-08 +2.3018616117450855e-08 +2.3995163467888165e-08 +2.3018616117450855e-08 +2.2600095824406296e-08 +2.14840417096208e-08 +2.050749435918349e-08 +1.953094700874618e-08 +2.0926014652228048e-08 +2.246058906005811e-08 +2.3995163467888165e-08 +2.608776493311097e-08 +2.7622339340941025e-08 +2.8319873162681962e-08 +2.8319873162681962e-08 +2.7622339340941025e-08 +2.706431228354828e-08 +2.608776493311097e-08 +2.4971710818325472e-08 +2.3995163467888165e-08 +2.3576643174843603e-08 +2.287910935310267e-08 +2.218157553136173e-08 +2.315812288179904e-08 +2.3297629646147227e-08 +2.1623548473968986e-08 +2.287910935310267e-08 +2.2321082295709924e-08 +2.2739602588754482e-08 +2.3018616117450855e-08 +2.218157553136173e-08 +2.6227271697459155e-08 +2.3995163467888165e-08 +3.5992745201832246e-08 +3.9759427839233295e-08 +4.1852029304456096e-08 +4.3386603712286164e-08 +4.101498871836698e-08 +4.3526110476634344e-08 +4.394463076967891e-08 +4.129400224706335e-08 +3.487669108704675e-08 +2.4971710818325472e-08 +1.953094700874618e-08 +1.855439965830887e-08 +1.7438345543523375e-08 +1.6601304957434254e-08 +1.6322291428737878e-08 +2.6227271697459155e-08 +2.3576643174843603e-08 +2.413467023223635e-08 +2.3576643174843603e-08 +2.3716149939191793e-08 +2.385565670353998e-08 +2.315812288179904e-08 +2.706431228354828e-08 +2.4971710818325472e-08 +3.724830608096593e-08 +4.115449548271517e-08 +4.3526110476634344e-08 +4.492117812011622e-08 +4.157301577575972e-08 +4.3805124005330716e-08 +4.3805124005330716e-08 +4.227054959750066e-08 +3.613225196618043e-08 +2.6227271697459155e-08 +2.106552141657624e-08 +2.008897406613893e-08 +1.9391440244397992e-08 +1.8693906422657058e-08 +1.82753861296125e-08 +3.0551981392252956e-08 +2.7761846105289214e-08 +2.845937992703015e-08 +2.7622339340941025e-08 +2.8180366398333776e-08 +2.6785298754851907e-08 +2.552973787571822e-08 +2.9296420513119273e-08 +2.5390231111370035e-08 +3.7806333138358674e-08 +4.157301577575972e-08 +4.366561724098254e-08 +4.520019164881259e-08 +4.1852029304456096e-08 +4.366561724098254e-08 +4.422364429837528e-08 +4.2410056361848854e-08 +3.5713731673135874e-08 +2.552973787571822e-08 +2.0647001123531675e-08 +1.953094700874618e-08 +1.8972919951353434e-08 +1.8414892893960685e-08 +1.7856865836567937e-08 +2.873839345572652e-08 +2.5669244640066407e-08 +2.5808751404414597e-08 +2.4971710818325472e-08 +2.4832204053977286e-08 +2.552973787571822e-08 +2.4413683760932724e-08 +2.7901352869637404e-08 +2.5111217582673662e-08 +3.7806333138358674e-08 +4.1852029304456096e-08 +4.3805124005330716e-08 +4.520019164881259e-08 +4.2549563126197034e-08 +4.4502657827071654e-08 +4.4502657827071654e-08 +4.29680834192416e-08 +3.6690279023573184e-08 +2.608776493311097e-08 +2.1344534945272613e-08 +1.9670453773094368e-08 +1.9251933480049806e-08 +1.855439965830887e-08 +1.757785230787156e-08 +2.7761846105289214e-08 +2.4274176996584538e-08 +2.413467023223635e-08 +2.3437136410495414e-08 +2.385565670353998e-08 +2.3995163467888165e-08 +2.385565670353998e-08 +2.7482832576592838e-08 +2.4274176996584538e-08 +3.5992745201832246e-08 +3.961992107488511e-08 +4.213104283315248e-08 +4.2828576654893406e-08 +3.989893460358149e-08 +4.017794813227786e-08 +3.9340907546188736e-08 +3.557422490878769e-08 +3.013346109920839e-08 +2.315812288179904e-08 +1.953094700874618e-08 +1.8833413187005247e-08 +1.82753861296125e-08 +1.7019825250478813e-08 +1.6043277900041506e-08 +2.706431228354828e-08 +2.4413683760932724e-08 +2.4832204053977286e-08 +2.385565670353998e-08 +2.315812288179904e-08 +2.287910935310267e-08 +2.14840417096208e-08 +2.1205028180924427e-08 +2.3995163467888165e-08 +2.943592727746746e-08 +3.4318664029654005e-08 +3.682978578792137e-08 +3.6690279023573184e-08 +3.5713731673135874e-08 +3.487669108704675e-08 +3.390014373660944e-08 +3.292359638617213e-08 +3.124951521399389e-08 +2.8319873162681962e-08 +2.7203819047896466e-08 +2.650628522615553e-08 +2.6785298754851907e-08 +2.650628522615553e-08 +2.7482832576592838e-08 +2.7203819047896466e-08 +2.4971710818325472e-08 +2.5948258168762783e-08 +2.4971710818325472e-08 +2.46926972896291e-08 +2.2321082295709924e-08 +2.106552141657624e-08 +1.9949467301790744e-08 +2.0228480830487117e-08 +2.3018616117450855e-08 +2.455319052528091e-08 +2.7343325812244652e-08 +2.873839345572652e-08 +2.943592727746746e-08 +2.8319873162681962e-08 +2.7901352869637404e-08 +2.706431228354828e-08 +2.6645791990503717e-08 +2.46926972896291e-08 +2.3995163467888165e-08 +2.3995163467888165e-08 +2.315812288179904e-08 +2.3297629646147227e-08 +2.4413683760932724e-08 +2.413467023223635e-08 +2.2600095824406296e-08 +2.3576643174843603e-08 +2.3297629646147227e-08 +2.3018616117450855e-08 +2.315812288179904e-08 +2.2600095824406296e-08 +2.608776493311097e-08 +2.3437136410495414e-08 +3.5016197851394936e-08 +3.8782880488795985e-08 +4.115449548271517e-08 +4.2689069890545226e-08 +4.017794813227786e-08 +4.2549563126197034e-08 +4.2828576654893406e-08 +4.101498871836698e-08 +3.487669108704675e-08 +2.455319052528091e-08 +1.9391440244397992e-08 +1.7856865836567937e-08 +1.674081172178244e-08 +1.590377113569332e-08 +1.5485250842648757e-08 +2.5808751404414597e-08 +2.3297629646147227e-08 +2.3995163467888165e-08 +2.287910935310267e-08 +2.287910935310267e-08 +2.3297629646147227e-08 +2.3018616117450855e-08 +2.650628522615553e-08 +2.3995163467888165e-08 +3.5713731673135874e-08 +3.906189401749236e-08 +4.1433509011411543e-08 +4.310759018358978e-08 +4.031745489662604e-08 +4.2689069890545226e-08 +4.29680834192416e-08 +4.1433509011411543e-08 +3.5295211380091315e-08 +2.4971710818325472e-08 +2.008897406613893e-08 +1.8693906422657058e-08 +1.8414892893960685e-08 +1.771735907221975e-08 +1.7438345543523375e-08 +2.943592727746746e-08 +2.6924805519200093e-08 +2.7482832576592838e-08 +2.650628522615553e-08 +2.6227271697459155e-08 +2.5808751404414597e-08 +2.5111217582673662e-08 +2.8598886691378335e-08 +2.4413683760932724e-08 +3.6550772259225e-08 +4.017794813227786e-08 +4.227054959750066e-08 +4.3526110476634344e-08 +4.045696166097423e-08 +4.227054959750066e-08 +4.310759018358978e-08 +4.157301577575972e-08 +3.54347181444395e-08 +2.552973787571822e-08 +2.0367987594835303e-08 +1.911242671570162e-08 +1.8414892893960685e-08 +1.771735907221975e-08 +1.6461798193086064e-08 +2.6924805519200093e-08 +2.413467023223635e-08 +2.413467023223635e-08 +2.3297629646147227e-08 +2.3995163467888165e-08 +2.413467023223635e-08 +2.413467023223635e-08 +2.7761846105289214e-08 +2.4413683760932724e-08 +3.6550772259225e-08 +4.017794813227786e-08 +4.2410056361848854e-08 +4.366561724098254e-08 +4.101498871836698e-08 +4.2689069890545226e-08 +4.2549563126197034e-08 +4.115449548271517e-08 +3.515570461574312e-08 +2.552973787571822e-08 +2.106552141657624e-08 +1.953094700874618e-08 +1.9251933480049806e-08 +1.953094700874618e-08 +1.8833413187005247e-08 +3.041247462790477e-08 +2.6645791990503717e-08 +2.6227271697459155e-08 +2.5250724347021848e-08 +2.552973787571822e-08 +2.5948258168762783e-08 +2.5250724347021848e-08 +2.8319873162681962e-08 +2.413467023223635e-08 +3.5295211380091315e-08 +3.850386696009961e-08 +4.031745489662604e-08 +4.101498871836698e-08 +3.850386696009961e-08 +3.8782880488795985e-08 +3.794583990270687e-08 +3.487669108704675e-08 +2.985444757051202e-08 +2.315812288179904e-08 +1.9251933480049806e-08 +1.8693906422657058e-08 +1.7996372600916123e-08 +1.7159332014827002e-08 +1.674081172178244e-08 +2.845937992703015e-08 +2.5111217582673662e-08 +2.4971710818325472e-08 +2.3576643174843603e-08 +2.315812288179904e-08 +2.3018616117450855e-08 +2.218157553136173e-08 +2.1344534945272613e-08 +2.413467023223635e-08 +2.943592727746746e-08 +3.4039650500957626e-08 +3.5992745201832246e-08 +3.585323843748406e-08 +3.487669108704675e-08 +3.4039650500957626e-08 +3.3342116679216694e-08 +3.22260625644312e-08 +3.1668035507038446e-08 +2.8598886691378335e-08 +2.7482832576592838e-08 +2.7622339340941025e-08 +2.6924805519200093e-08 +2.7203819047896466e-08 +2.9156913748771087e-08 +2.8319873162681962e-08 +2.6645791990503717e-08 +2.7203819047896466e-08 +2.6227271697459155e-08 +2.5808751404414597e-08 +2.3995163467888165e-08 +2.287910935310267e-08 +2.1344534945272613e-08 +2.1902562002665358e-08 +2.5808751404414597e-08 +2.6645791990503717e-08 +2.9156913748771087e-08 +3.013346109920839e-08 +3.013346109920839e-08 +2.845937992703015e-08 +2.7901352869637404e-08 +2.804085963398559e-08 +2.7482832576592838e-08 +2.5669244640066407e-08 +2.5111217582673662e-08 +2.552973787571822e-08 +2.46926972896291e-08 +2.46926972896291e-08 +2.608776493311097e-08 +2.5390231111370035e-08 +2.3576643174843603e-08 +2.4274176996584538e-08 +2.3995163467888165e-08 +2.3297629646147227e-08 +2.315812288179904e-08 +2.3297629646147227e-08 +2.5808751404414597e-08 +2.246058906005811e-08 +3.3342116679216694e-08 +3.696929255226956e-08 +3.920140078184055e-08 +4.0735975189670606e-08 +3.8782880488795985e-08 +4.031745489662604e-08 +4.045696166097423e-08 +3.906189401749236e-08 +3.348162344356488e-08 +2.385565670353998e-08 +1.9391440244397992e-08 +1.7856865836567937e-08 +1.7019825250478813e-08 +1.6322291428737878e-08 +1.576426437134513e-08 +2.6924805519200093e-08 +2.455319052528091e-08 +2.5111217582673662e-08 +2.413467023223635e-08 +2.413467023223635e-08 +2.46926972896291e-08 +2.455319052528091e-08 +2.706431228354828e-08 +2.385565670353998e-08 +3.417915726530581e-08 +3.7387812845314116e-08 +3.948041431053692e-08 +4.087548195401879e-08 +3.892238725314418e-08 +4.045696166097423e-08 +4.059646842532242e-08 +3.9340907546188736e-08 +3.376063697226125e-08 +2.385565670353998e-08 +1.9670453773094368e-08 +1.7996372600916123e-08 +1.757785230787156e-08 +1.771735907221975e-08 +1.6880318486130626e-08 +2.804085963398559e-08 +2.5669244640066407e-08 +2.6227271697459155e-08 +2.5948258168762783e-08 +2.5250724347021848e-08 +2.5390231111370035e-08 +2.5390231111370035e-08 +2.8180366398333776e-08 +2.3576643174843603e-08 +3.445817079400219e-08 +3.7806333138358674e-08 +3.9759427839233295e-08 +4.087548195401879e-08 +3.8364360195751426e-08 +3.989893460358149e-08 +3.989893460358149e-08 +3.850386696009961e-08 +3.348162344356488e-08 +2.46926972896291e-08 +1.9670453773094368e-08 +1.8414892893960685e-08 +1.7996372600916123e-08 +1.771735907221975e-08 +1.6322291428737878e-08 +2.650628522615553e-08 +2.3995163467888165e-08 +2.4274176996584538e-08 +2.3716149939191793e-08 +2.385565670353998e-08 +2.413467023223635e-08 +2.413467023223635e-08 +2.7482832576592838e-08 +2.3018616117450855e-08 +3.348162344356488e-08 +3.6411265494876805e-08 +3.850386696009961e-08 +3.948041431053692e-08 +3.7666826374010495e-08 +3.892238725314418e-08 +3.906189401749236e-08 +3.7387812845314116e-08 +3.208655580008301e-08 +2.3995163467888165e-08 +2.008897406613893e-08 +1.8833413187005247e-08 +1.7996372600916123e-08 +1.8414892893960685e-08 +1.8414892893960685e-08 +2.985444757051202e-08 +2.706431228354828e-08 +2.6645791990503717e-08 +2.5808751404414597e-08 +2.5669244640066407e-08 +2.608776493311097e-08 +2.5669244640066407e-08 +2.7761846105289214e-08 +2.2739602588754482e-08 +3.22260625644312e-08 +3.557422490878769e-08 +3.710879931661774e-08 +3.7806333138358674e-08 +3.5713731673135874e-08 +3.585323843748406e-08 +3.5295211380091315e-08 +3.208655580008301e-08 +2.7761846105289214e-08 +2.1902562002665358e-08 +1.813587936526431e-08 +1.674081172178244e-08 +1.6182784664389692e-08 +1.590377113569332e-08 +1.6043277900041506e-08 +2.7343325812244652e-08 +2.4413683760932724e-08 +2.4413683760932724e-08 +2.3576643174843603e-08 +2.287910935310267e-08 +2.2600095824406296e-08 +2.218157553136173e-08 +2.1205028180924427e-08 +2.2600095824406296e-08 +2.7203819047896466e-08 +3.0970501685297515e-08 +3.3063103150520315e-08 +3.376063697226125e-08 +3.362113020791307e-08 +3.2644582857475756e-08 +3.208655580008301e-08 +3.1389021978342073e-08 +3.069148815660114e-08 +2.845937992703015e-08 +2.6924805519200093e-08 +2.7203819047896466e-08 +2.6227271697459155e-08 +2.6645791990503717e-08 +2.7901352869637404e-08 +2.8180366398333776e-08 +2.7343325812244652e-08 +2.8598886691378335e-08 +2.8598886691378335e-08 +2.8319873162681962e-08 +2.7622339340941025e-08 +2.6366778461807345e-08 +2.46926972896291e-08 +2.4832204053977286e-08 +2.706431228354828e-08 +2.804085963398559e-08 +2.9156913748771087e-08 +2.985444757051202e-08 +2.9993954334860204e-08 +2.943592727746746e-08 +2.804085963398559e-08 +2.8598886691378335e-08 +2.8598886691378335e-08 +2.7622339340941025e-08 +2.7622339340941025e-08 +2.7622339340941025e-08 +2.6785298754851907e-08 +2.608776493311097e-08 +2.706431228354828e-08 +2.6366778461807345e-08 +2.4274176996584538e-08 +2.46926972896291e-08 +2.3716149939191793e-08 +2.3437136410495414e-08 +2.3297629646147227e-08 +2.385565670353998e-08 +2.5390231111370035e-08 +2.0926014652228048e-08 +3.041247462790477e-08 +3.390014373660944e-08 +3.5016197851394936e-08 +3.6411265494876805e-08 +3.515570461574312e-08 +3.627175873052862e-08 +3.613225196618043e-08 +3.515570461574312e-08 +3.069148815660114e-08 +2.287910935310267e-08 +1.8972919951353434e-08 +1.7996372600916123e-08 +1.729883877917519e-08 +1.674081172178244e-08 +1.6182784664389692e-08 +2.7622339340941025e-08 +2.5250724347021848e-08 +2.5250724347021848e-08 +2.46926972896291e-08 +2.5111217582673662e-08 +2.552973787571822e-08 +2.5669244640066407e-08 +2.7343325812244652e-08 +2.2739602588754482e-08 +3.208655580008301e-08 +3.5295211380091315e-08 +3.696929255226956e-08 +3.794583990270687e-08 +3.6411265494876805e-08 +3.710879931661774e-08 +3.696929255226956e-08 +3.5713731673135874e-08 +3.1389021978342073e-08 +2.3297629646147227e-08 +1.9391440244397992e-08 +1.813587936526431e-08 +1.7856865836567937e-08 +1.813587936526431e-08 +1.6880318486130626e-08 +2.7901352869637404e-08 +2.5250724347021848e-08 +2.5808751404414597e-08 +2.5250724347021848e-08 +2.5111217582673662e-08 +2.552973787571822e-08 +2.5948258168762783e-08 +2.7622339340941025e-08 +2.2042068767013544e-08 +3.124951521399389e-08 +3.445817079400219e-08 +3.585323843748406e-08 +3.696929255226956e-08 +3.515570461574312e-08 +3.585323843748406e-08 +3.5295211380091315e-08 +3.4039650500957626e-08 +3.013346109920839e-08 +2.246058906005811e-08 +1.82753861296125e-08 +1.7438345543523375e-08 +1.674081172178244e-08 +1.7159332014827002e-08 +1.6043277900041506e-08 +2.6924805519200093e-08 +2.413467023223635e-08 +2.4274176996584538e-08 +2.385565670353998e-08 +2.3576643174843603e-08 +2.3995163467888165e-08 +2.3995163467888165e-08 +2.5808751404414597e-08 +2.078650788787986e-08 +2.9714940806163832e-08 +3.3063103150520315e-08 +3.5016197851394936e-08 +3.585323843748406e-08 +3.487669108704675e-08 +3.613225196618043e-08 +3.5713731673135874e-08 +3.4318664029654005e-08 +2.9993954334860204e-08 +2.2600095824406296e-08 +1.8693906422657058e-08 +1.729883877917519e-08 +1.6322291428737878e-08 +1.674081172178244e-08 +1.6461798193086064e-08 +2.6785298754851907e-08 +2.4274176996584538e-08 +2.4413683760932724e-08 +2.385565670353998e-08 +2.3995163467888165e-08 +2.413467023223635e-08 +2.385565670353998e-08 +2.5250724347021848e-08 +2.008897406613893e-08 +2.845937992703015e-08 +3.250507609312757e-08 +3.417915726530581e-08 +3.4737184322698563e-08 +3.348162344356488e-08 +3.376063697226125e-08 +3.3342116679216694e-08 +3.0551981392252956e-08 +2.6924805519200093e-08 +2.2042068767013544e-08 +1.813587936526431e-08 +1.6880318486130626e-08 +1.6182784664389692e-08 +1.6043277900041506e-08 +1.5485250842648757e-08 +2.6645791990503717e-08 +2.455319052528091e-08 +2.455319052528091e-08 +2.3716149939191793e-08 +2.287910935310267e-08 +2.287910935310267e-08 +2.287910935310267e-08 +2.1763055238317172e-08 +2.246058906005811e-08 +2.7203819047896466e-08 +3.027296786355658e-08 +3.180754227138664e-08 +3.3063103150520315e-08 +3.362113020791307e-08 +3.390014373660944e-08 +3.2644582857475756e-08 +3.22260625644312e-08 +3.083099492094933e-08 +2.8877900220074708e-08 +2.650628522615553e-08 +2.5390231111370035e-08 +2.455319052528091e-08 +2.5669244640066407e-08 +2.6924805519200093e-08 +2.7482832576592838e-08 +2.6366778461807345e-08 +2.7203819047896466e-08 +2.7203819047896466e-08 +2.7203819047896466e-08 +2.6366778461807345e-08 +2.5390231111370035e-08 +2.3716149939191793e-08 +2.3437136410495414e-08 +2.4832204053977286e-08 +2.6227271697459155e-08 +2.8180366398333776e-08 +2.943592727746746e-08 +2.9993954334860204e-08 +2.943592727746746e-08 +2.8319873162681962e-08 +2.845937992703015e-08 +2.8319873162681962e-08 +2.7203819047896466e-08 +2.6785298754851907e-08 +2.6645791990503717e-08 +2.6924805519200093e-08 +2.7343325812244652e-08 +2.7482832576592838e-08 +2.7343325812244652e-08 +2.46926972896291e-08 +2.4971710818325472e-08 +2.4274176996584538e-08 +2.3576643174843603e-08 +2.413467023223635e-08 +2.455319052528091e-08 +2.5390231111370035e-08 +1.9251933480049806e-08 +2.7622339340941025e-08 +3.1389021978342073e-08 +3.2644582857475756e-08 +3.362113020791307e-08 +3.22260625644312e-08 +3.320260991486851e-08 +3.3342116679216694e-08 +3.208655580008301e-08 +2.8319873162681962e-08 +2.14840417096208e-08 +1.7856865836567937e-08 +1.7159332014827002e-08 +1.6880318486130626e-08 +1.7019825250478813e-08 +1.6182784664389692e-08 +2.7343325812244652e-08 +2.3995163467888165e-08 +2.3716149939191793e-08 +2.3716149939191793e-08 +2.3995163467888165e-08 +2.4274176996584538e-08 +2.4413683760932724e-08 +2.4971710818325472e-08 +1.9809960537442554e-08 +2.873839345572652e-08 +3.22260625644312e-08 +3.390014373660944e-08 +3.4737184322698563e-08 +3.320260991486851e-08 +3.362113020791307e-08 +3.362113020791307e-08 +3.250507609312757e-08 +2.9017406984422894e-08 +2.2042068767013544e-08 +1.8414892893960685e-08 +1.771735907221975e-08 +1.771735907221975e-08 +1.8693906422657058e-08 +1.7019825250478813e-08 +2.7761846105289214e-08 +2.5111217582673662e-08 +2.5250724347021848e-08 +2.4274176996584538e-08 +2.413467023223635e-08 +2.455319052528091e-08 +2.5250724347021848e-08 +2.5808751404414597e-08 +1.9949467301790744e-08 +2.8319873162681962e-08 +3.1668035507038446e-08 +3.3063103150520315e-08 +3.390014373660944e-08 +3.2644582857475756e-08 +3.320260991486851e-08 +3.3063103150520315e-08 +3.1947049035734825e-08 +2.8180366398333776e-08 +2.14840417096208e-08 +1.82753861296125e-08 +1.7856865836567937e-08 +1.7019825250478813e-08 +1.757785230787156e-08 +1.6601304957434254e-08 +2.7901352869637404e-08 +2.5669244640066407e-08 +2.6645791990503717e-08 +2.5948258168762783e-08 +2.5390231111370035e-08 +2.4971710818325472e-08 +2.5111217582673662e-08 +2.5948258168762783e-08 +1.9391440244397992e-08 +2.7203819047896466e-08 +3.069148815660114e-08 +3.2365569328779384e-08 +3.320260991486851e-08 +3.22260625644312e-08 +3.320260991486851e-08 +3.2644582857475756e-08 +3.152852874269026e-08 +2.804085963398559e-08 +2.1205028180924427e-08 +1.757785230787156e-08 +1.6880318486130626e-08 +1.6182784664389692e-08 +1.7438345543523375e-08 +1.6601304957434254e-08 +2.7343325812244652e-08 +2.4274176996584538e-08 +2.3995163467888165e-08 +2.315812288179904e-08 +2.315812288179904e-08 +2.287910935310267e-08 +2.315812288179904e-08 +2.5390231111370035e-08 +1.8972919951353434e-08 +2.6785298754851907e-08 +3.013346109920839e-08 +3.1389021978342073e-08 +3.208655580008301e-08 +3.11100084496457e-08 +3.1668035507038446e-08 +3.124951521399389e-08 +2.9714940806163832e-08 +2.650628522615553e-08 +2.1763055238317172e-08 +1.8833413187005247e-08 +1.7996372600916123e-08 +1.7438345543523375e-08 +1.6880318486130626e-08 +1.6182784664389692e-08 +2.7343325812244652e-08 +2.413467023223635e-08 +2.3576643174843603e-08 +2.246058906005811e-08 +2.1902562002665358e-08 +2.1902562002665358e-08 +2.246058906005811e-08 +2.078650788787986e-08 +2.1902562002665358e-08 +2.650628522615553e-08 +2.9156913748771087e-08 +3.1668035507038446e-08 +3.2365569328779384e-08 +3.208655580008301e-08 +3.22260625644312e-08 +3.1668035507038446e-08 +3.1947049035734825e-08 +3.069148815660114e-08 +2.9017406984422894e-08 +2.7622339340941025e-08 +2.608776493311097e-08 +2.6227271697459155e-08 +2.7343325812244652e-08 +2.8877900220074708e-08 +2.8598886691378335e-08 +2.552973787571822e-08 +2.5111217582673662e-08 +2.3995163467888165e-08 +2.3576643174843603e-08 +2.315812288179904e-08 +2.3576643174843603e-08 +2.1205028180924427e-08 +2.1344534945272613e-08 +2.3297629646147227e-08 +2.4274176996584538e-08 +2.6227271697459155e-08 +2.7343325812244652e-08 +2.7901352869637404e-08 +2.7343325812244652e-08 +2.6645791990503717e-08 +2.608776493311097e-08 +2.5808751404414597e-08 +2.46926972896291e-08 +2.413467023223635e-08 +2.4274176996584538e-08 +2.4832204053977286e-08 +2.650628522615553e-08 +2.6645791990503717e-08 +2.6785298754851907e-08 +2.413467023223635e-08 +2.4274176996584538e-08 +2.413467023223635e-08 +2.3437136410495414e-08 +2.385565670353998e-08 +2.4274176996584538e-08 +2.5669244640066407e-08 +1.9391440244397992e-08 +2.804085963398559e-08 +3.1947049035734825e-08 +3.362113020791307e-08 +3.445817079400219e-08 +3.292359638617213e-08 +3.4039650500957626e-08 +3.445817079400219e-08 +3.3342116679216694e-08 +2.9017406984422894e-08 +2.1623548473968986e-08 +1.7856865836567937e-08 +1.674081172178244e-08 +1.674081172178244e-08 +1.771735907221975e-08 +1.6043277900041506e-08 +2.6785298754851907e-08 +2.315812288179904e-08 +2.3437136410495414e-08 +2.3297629646147227e-08 +2.3437136410495414e-08 +2.315812288179904e-08 +2.3437136410495414e-08 +2.3437136410495414e-08 +1.8972919951353434e-08 +2.804085963398559e-08 +3.1389021978342073e-08 +3.292359638617213e-08 +3.376063697226125e-08 +3.208655580008301e-08 +3.278408962182394e-08 +3.292359638617213e-08 +3.1947049035734825e-08 +2.8180366398333776e-08 +2.078650788787986e-08 +1.7159332014827002e-08 +1.6322291428737878e-08 +1.6182784664389692e-08 +1.8414892893960685e-08 +1.6182784664389692e-08 +2.608776493311097e-08 +2.287910935310267e-08 +2.2739602588754482e-08 +2.1902562002665358e-08 +2.1623548473968986e-08 +2.2042068767013544e-08 +2.246058906005811e-08 +2.3576643174843603e-08 +1.9251933480049806e-08 +2.804085963398559e-08 +3.152852874269026e-08 +3.3063103150520315e-08 +3.376063697226125e-08 +3.2365569328779384e-08 +3.3342116679216694e-08 +3.348162344356488e-08 +3.250507609312757e-08 +2.8598886691378335e-08 +2.14840417096208e-08 +1.8693906422657058e-08 +1.855439965830887e-08 +1.813587936526431e-08 +1.9391440244397992e-08 +1.757785230787156e-08 +2.8180366398333776e-08 +2.5669244640066407e-08 +2.7343325812244652e-08 +2.6645791990503717e-08 +2.5948258168762783e-08 +2.5948258168762783e-08 +2.5669244640066407e-08 +2.608776493311097e-08 +1.9949467301790744e-08 +2.8598886691378335e-08 +3.180754227138664e-08 +3.3063103150520315e-08 +3.376063697226125e-08 +3.2365569328779384e-08 +3.3063103150520315e-08 +3.3063103150520315e-08 +3.1947049035734825e-08 +2.7901352869637404e-08 +2.0926014652228048e-08 +1.7159332014827002e-08 +1.7019825250478813e-08 +1.6601304957434254e-08 +1.8972919951353434e-08 +1.7159332014827002e-08 +2.7901352869637404e-08 +2.5390231111370035e-08 +2.5250724347021848e-08 +2.413467023223635e-08 +2.3995163467888165e-08 +2.3716149939191793e-08 +2.4413683760932724e-08 +2.6785298754851907e-08 +2.008897406613893e-08 +2.8319873162681962e-08 +3.124951521399389e-08 +3.2365569328779384e-08 +3.3342116679216694e-08 +3.1947049035734825e-08 +3.278408962182394e-08 +3.278408962182394e-08 +3.069148815660114e-08 +2.706431228354828e-08 +2.1763055238317172e-08 +1.8693906422657058e-08 +1.7856865836567937e-08 +1.771735907221975e-08 +1.757785230787156e-08 +1.674081172178244e-08 +2.804085963398559e-08 +2.4832204053977286e-08 +2.5250724347021848e-08 +2.4413683760932724e-08 +2.4274176996584538e-08 +2.3576643174843603e-08 +2.385565670353998e-08 +2.218157553136173e-08 +2.3018616117450855e-08 +2.6924805519200093e-08 +3.041247462790477e-08 +3.3063103150520315e-08 +3.3342116679216694e-08 +3.320260991486851e-08 +3.208655580008301e-08 +3.1668035507038446e-08 +3.11100084496457e-08 +2.9714940806163832e-08 +2.7901352869637404e-08 +2.7343325812244652e-08 +2.608776493311097e-08 +2.6366778461807345e-08 +2.7761846105289214e-08 +2.804085963398559e-08 +2.706431228354828e-08 +2.385565670353998e-08 +2.3716149939191793e-08 +2.287910935310267e-08 +2.246058906005811e-08 +2.218157553136173e-08 +2.3297629646147227e-08 +2.1763055238317172e-08 +2.2042068767013544e-08 +2.3995163467888165e-08 +2.5111217582673662e-08 +2.6366778461807345e-08 +2.7203819047896466e-08 +2.7622339340941025e-08 +2.7622339340941025e-08 +2.6924805519200093e-08 +2.6227271697459155e-08 +2.5948258168762783e-08 +2.4832204053977286e-08 +2.4274176996584538e-08 +2.4413683760932724e-08 +2.4413683760932724e-08 +2.5808751404414597e-08 +2.552973787571822e-08 +2.4832204053977286e-08 +2.3018616117450855e-08 +2.3297629646147227e-08 +2.3018616117450855e-08 +2.3018616117450855e-08 +2.3297629646147227e-08 +2.4274176996584538e-08 +2.6366778461807345e-08 +2.14840417096208e-08 +3.1389021978342073e-08 +3.5016197851394936e-08 +3.6690279023573184e-08 +3.7666826374010495e-08 +3.627175873052862e-08 +3.8085346667055053e-08 +3.822485343140324e-08 +3.696929255226956e-08 +3.180754227138664e-08 +2.315812288179904e-08 +1.911242671570162e-08 +1.771735907221975e-08 +1.7856865836567937e-08 +1.9949467301790744e-08 +1.757785230787156e-08 +2.7622339340941025e-08 +2.455319052528091e-08 +2.5111217582673662e-08 +2.4413683760932724e-08 +2.4832204053977286e-08 +2.4413683760932724e-08 +2.4832204053977286e-08 +2.6366778461807345e-08 +2.14840417096208e-08 +3.1668035507038446e-08 +3.487669108704675e-08 +3.6690279023573184e-08 +3.794583990270687e-08 +3.5992745201832246e-08 +3.724830608096593e-08 +3.7387812845314116e-08 +3.613225196618043e-08 +3.041247462790477e-08 +2.2042068767013544e-08 +1.7856865836567937e-08 +1.7159332014827002e-08 +1.7856865836567937e-08 +2.0228480830487117e-08 +1.729883877917519e-08 +2.7343325812244652e-08 +2.413467023223635e-08 +2.413467023223635e-08 +2.3297629646147227e-08 +2.315812288179904e-08 +2.287910935310267e-08 +2.3297629646147227e-08 +2.5250724347021848e-08 +2.1205028180924427e-08 +3.0970501685297515e-08 +3.459767755835038e-08 +3.6550772259225e-08 +3.7666826374010495e-08 +3.557422490878769e-08 +3.6690279023573184e-08 +3.6690279023573184e-08 +3.515570461574312e-08 +3.041247462790477e-08 +2.1623548473968986e-08 +1.7996372600916123e-08 +1.7438345543523375e-08 +1.813587936526431e-08 +2.078650788787986e-08 +1.7438345543523375e-08 +2.6924805519200093e-08 +2.3995163467888165e-08 +2.46926972896291e-08 +2.4413683760932724e-08 +2.3995163467888165e-08 +2.4413683760932724e-08 +2.46926972896291e-08 +2.5948258168762783e-08 +2.14840417096208e-08 +3.1947049035734825e-08 +3.54347181444395e-08 +3.682978578792137e-08 +3.7666826374010495e-08 +3.5295211380091315e-08 +3.6690279023573184e-08 +3.682978578792137e-08 +3.557422490878769e-08 +3.027296786355658e-08 +2.1902562002665358e-08 +1.82753861296125e-08 +1.8414892893960685e-08 +1.9391440244397992e-08 +2.218157553136173e-08 +1.855439965830887e-08 +2.8180366398333776e-08 +2.552973787571822e-08 +2.552973787571822e-08 +2.4274176996584538e-08 +2.4413683760932724e-08 +2.413467023223635e-08 +2.46926972896291e-08 +2.7482832576592838e-08 +2.1623548473968986e-08 +3.124951521399389e-08 +3.459767755835038e-08 +3.6411265494876805e-08 +3.724830608096593e-08 +3.54347181444395e-08 +3.627175873052862e-08 +3.585323843748406e-08 +3.3063103150520315e-08 +2.845937992703015e-08 +2.218157553136173e-08 +1.8414892893960685e-08 +1.7159332014827002e-08 +1.729883877917519e-08 +1.855439965830887e-08 +1.7159332014827002e-08 +2.7622339340941025e-08 +2.5111217582673662e-08 +2.552973787571822e-08 +2.4832204053977286e-08 +2.455319052528091e-08 +2.385565670353998e-08 +2.413467023223635e-08 +2.287910935310267e-08 +2.3716149939191793e-08 +2.7622339340941025e-08 +3.1947049035734825e-08 +3.376063697226125e-08 +3.4737184322698563e-08 +3.4039650500957626e-08 +3.320260991486851e-08 +3.22260625644312e-08 +3.124951521399389e-08 +2.9993954334860204e-08 +2.7622339340941025e-08 +2.7343325812244652e-08 +2.7343325812244652e-08 +2.7622339340941025e-08 +2.873839345572652e-08 +2.7901352869637404e-08 +2.608776493311097e-08 +2.385565670353998e-08 +2.4274176996584538e-08 +2.3576643174843603e-08 +2.3018616117450855e-08 +2.2600095824406296e-08 +2.2600095824406296e-08 +2.1344534945272613e-08 +2.078650788787986e-08 +2.2600095824406296e-08 +2.455319052528091e-08 +2.650628522615553e-08 +2.706431228354828e-08 +2.7761846105289214e-08 +2.7482832576592838e-08 +2.6366778461807345e-08 +2.6227271697459155e-08 +2.6645791990503717e-08 +2.5948258168762783e-08 +2.5808751404414597e-08 +2.6924805519200093e-08 +2.7203819047896466e-08 +2.845937992703015e-08 +2.706431228354828e-08 +2.552973787571822e-08 +2.3716149939191793e-08 +2.413467023223635e-08 +2.3576643174843603e-08 +2.315812288179904e-08 +2.3995163467888165e-08 +2.5111217582673662e-08 +2.7622339340941025e-08 +2.315812288179904e-08 +3.4318664029654005e-08 +3.8364360195751426e-08 +4.031745489662604e-08 +4.129400224706335e-08 +3.906189401749236e-08 +4.115449548271517e-08 +4.1433509011411543e-08 +3.9340907546188736e-08 +3.362113020791307e-08 +2.385565670353998e-08 +2.008897406613893e-08 +1.9391440244397992e-08 +2.0228480830487117e-08 +2.2042068767013544e-08 +1.8833413187005247e-08 +2.9156913748771087e-08 +2.6227271697459155e-08 +2.6645791990503717e-08 +2.5948258168762783e-08 +2.650628522615553e-08 +2.6366778461807345e-08 +2.7203819047896466e-08 +2.985444757051202e-08 +2.4274176996584538e-08 +3.557422490878769e-08 +3.948041431053692e-08 +4.157301577575972e-08 +4.3386603712286164e-08 +4.0735975189670606e-08 +4.2828576654893406e-08 +4.324709694793797e-08 +4.129400224706335e-08 +3.445817079400219e-08 +2.455319052528091e-08 +1.9809960537442554e-08 +1.9251933480049806e-08 +2.1344534945272613e-08 +2.3018616117450855e-08 +1.8693906422657058e-08 +2.8319873162681962e-08 +2.5390231111370035e-08 +2.5111217582673662e-08 +2.385565670353998e-08 +2.3576643174843603e-08 +2.3437136410495414e-08 +2.385565670353998e-08 +2.706431228354828e-08 +2.315812288179904e-08 +3.4318664029654005e-08 +3.7806333138358674e-08 +4.017794813227786e-08 +4.1712522540107916e-08 +3.892238725314418e-08 +4.059646842532242e-08 +4.059646842532242e-08 +3.906189401749236e-08 +3.3063103150520315e-08 +2.3018616117450855e-08 +1.8833413187005247e-08 +1.7856865836567937e-08 +2.0228480830487117e-08 +2.246058906005811e-08 +1.7996372600916123e-08 +2.7482832576592838e-08 +2.4413683760932724e-08 +2.455319052528091e-08 +2.385565670353998e-08 +2.3576643174843603e-08 +2.3297629646147227e-08 +2.4413683760932724e-08 +2.7343325812244652e-08 +2.3576643174843603e-08 +3.459767755835038e-08 +3.8364360195751426e-08 +4.059646842532242e-08 +4.213104283315248e-08 +3.906189401749236e-08 +4.0735975189670606e-08 +4.115449548271517e-08 +3.9759427839233295e-08 +3.390014373660944e-08 +2.4274176996584538e-08 +1.9949467301790744e-08 +1.9670453773094368e-08 +2.2321082295709924e-08 +2.4971710818325472e-08 +2.008897406613893e-08 +3.027296786355658e-08 +2.650628522615553e-08 +2.6227271697459155e-08 +2.4832204053977286e-08 +2.4413683760932724e-08 +2.46926972896291e-08 +2.5948258168762783e-08 +2.943592727746746e-08 +2.385565670353998e-08 +3.445817079400219e-08 +3.8085346667055053e-08 +4.031745489662604e-08 +4.101498871836698e-08 +3.850386696009961e-08 +3.948041431053692e-08 +3.892238725314418e-08 +3.613225196618043e-08 +3.041247462790477e-08 +2.315812288179904e-08 +1.953094700874618e-08 +1.855439965830887e-08 +1.9391440244397992e-08 +2.0228480830487117e-08 +1.771735907221975e-08 +2.7482832576592838e-08 +2.4413683760932724e-08 +2.3995163467888165e-08 +2.287910935310267e-08 +2.2321082295709924e-08 +2.218157553136173e-08 +2.2600095824406296e-08 +2.1763055238317172e-08 +2.3018616117450855e-08 +2.7482832576592838e-08 +3.1947049035734825e-08 +3.445817079400219e-08 +3.5713731673135874e-08 +3.417915726530581e-08 +3.348162344356488e-08 +3.3063103150520315e-08 +3.1668035507038446e-08 +3.027296786355658e-08 +2.804085963398559e-08 +2.7622339340941025e-08 +2.7761846105289214e-08 +2.8877900220074708e-08 +2.9296420513119273e-08 +2.8319873162681962e-08 +2.6227271697459155e-08 +2.4413683760932724e-08 +2.4832204053977286e-08 +2.413467023223635e-08 +2.3437136410495414e-08 +2.3018616117450855e-08 +2.2739602588754482e-08 +2.14840417096208e-08 +2.0228480830487117e-08 +2.1623548473968986e-08 +2.3576643174843603e-08 +2.5948258168762783e-08 +2.6366778461807345e-08 +2.7622339340941025e-08 +2.7203819047896466e-08 +2.6645791990503717e-08 +2.6645791990503717e-08 +2.7343325812244652e-08 +2.6785298754851907e-08 +2.6785298754851907e-08 +2.7761846105289214e-08 +2.8598886691378335e-08 +2.985444757051202e-08 +2.8319873162681962e-08 +2.6227271697459155e-08 +2.46926972896291e-08 +2.5250724347021848e-08 +2.46926972896291e-08 +2.413467023223635e-08 +2.46926972896291e-08 +2.5948258168762783e-08 +2.9017406984422894e-08 +2.413467023223635e-08 +3.5713731673135874e-08 +3.948041431053692e-08 +4.1433509011411543e-08 +4.2549563126197034e-08 +3.961992107488511e-08 +4.157301577575972e-08 +4.1852029304456096e-08 +3.989893460358149e-08 +3.3342116679216694e-08 +2.315812288179904e-08 +1.9251933480049806e-08 +1.8972919951353434e-08 +2.1205028180924427e-08 +2.1763055238317172e-08 +1.7856865836567937e-08 +2.7343325812244652e-08 +2.455319052528091e-08 +2.4971710818325472e-08 +2.4413683760932724e-08 +2.4971710818325472e-08 +2.4971710818325472e-08 +2.650628522615553e-08 +2.985444757051202e-08 +2.4971710818325472e-08 +3.682978578792137e-08 +4.0735975189670606e-08 +4.2828576654893406e-08 +4.478167135576803e-08 +4.1712522540107916e-08 +4.3805124005330716e-08 +4.464216459141985e-08 +4.227054959750066e-08 +3.515570461574312e-08 +2.455319052528091e-08 +1.9670453773094368e-08 +1.8833413187005247e-08 +2.2739602588754482e-08 +2.4413683760932724e-08 +1.9391440244397992e-08 +2.8877900220074708e-08 +2.4971710818325472e-08 +2.46926972896291e-08 +2.3576643174843603e-08 +2.3297629646147227e-08 +2.3437136410495414e-08 +2.455319052528091e-08 +2.873839345572652e-08 +2.4832204053977286e-08 +3.627175873052862e-08 +3.9759427839233295e-08 +4.2410056361848854e-08 +4.3805124005330716e-08 +4.059646842532242e-08 +4.2410056361848854e-08 +4.2689069890545226e-08 +4.101498871836698e-08 +3.4318664029654005e-08 +2.385565670353998e-08 +1.953094700874618e-08 +1.8693906422657058e-08 +2.2739602588754482e-08 +2.3716149939191793e-08 +1.8833413187005247e-08 +2.845937992703015e-08 +2.5669244640066407e-08 +2.552973787571822e-08 +2.4832204053977286e-08 +2.4413683760932724e-08 +2.413467023223635e-08 +2.5390231111370035e-08 +2.9156913748771087e-08 +2.5111217582673662e-08 +3.6550772259225e-08 +4.003844136792967e-08 +4.227054959750066e-08 +4.3805124005330716e-08 +4.087548195401879e-08 +4.2410056361848854e-08 +4.29680834192416e-08 +4.157301577575972e-08 +3.557422490878769e-08 +2.5111217582673662e-08 +2.050749435918349e-08 +2.008897406613893e-08 +2.3995163467888165e-08 +2.5250724347021848e-08 +2.008897406613893e-08 +3.027296786355658e-08 +2.6924805519200093e-08 +2.6924805519200093e-08 +2.5390231111370035e-08 +2.4832204053977286e-08 +2.5808751404414597e-08 +2.7203819047896466e-08 +3.083099492094933e-08 +2.5390231111370035e-08 +3.6411265494876805e-08 +3.989893460358149e-08 +4.213104283315248e-08 +4.29680834192416e-08 +4.003844136792967e-08 +4.115449548271517e-08 +4.0735975189670606e-08 +3.7806333138358674e-08 +3.1389021978342073e-08 +2.3576643174843603e-08 +1.9809960537442554e-08 +1.8972919951353434e-08 +2.14840417096208e-08 +2.1205028180924427e-08 +1.82753861296125e-08 +2.845937992703015e-08 +2.5250724347021848e-08 +2.5250724347021848e-08 +2.385565670353998e-08 +2.3576643174843603e-08 +2.3716149939191793e-08 +2.413467023223635e-08 +2.3716149939191793e-08 +2.455319052528091e-08 +2.9993954334860204e-08 +3.5016197851394936e-08 +3.724830608096593e-08 +3.822485343140324e-08 +3.682978578792137e-08 +3.5713731673135874e-08 +3.487669108704675e-08 +3.278408962182394e-08 +3.11100084496457e-08 +2.845937992703015e-08 +2.706431228354828e-08 +2.650628522615553e-08 +2.7901352869637404e-08 +2.7622339340941025e-08 +2.6227271697459155e-08 +2.46926972896291e-08 +2.2600095824406296e-08 +2.3297629646147227e-08 +2.2600095824406296e-08 +2.315812288179904e-08 +2.246058906005811e-08 +2.3018616117450855e-08 +2.246058906005811e-08 +2.1623548473968986e-08 +2.2739602588754482e-08 +2.455319052528091e-08 +2.6645791990503717e-08 +2.7203819047896466e-08 +2.804085963398559e-08 +2.845937992703015e-08 +2.7761846105289214e-08 +2.7761846105289214e-08 +2.7343325812244652e-08 +2.6785298754851907e-08 +2.608776493311097e-08 +2.5808751404414597e-08 +2.8180366398333776e-08 +2.8598886691378335e-08 +2.6924805519200093e-08 +2.5111217582673662e-08 +2.4413683760932724e-08 +2.5111217582673662e-08 +2.455319052528091e-08 +2.455319052528091e-08 +2.4274176996584538e-08 +2.552973787571822e-08 +2.943592727746746e-08 +2.455319052528091e-08 +3.613225196618043e-08 +3.920140078184055e-08 +4.101498871836698e-08 +4.2549563126197034e-08 +3.961992107488511e-08 +4.1852029304456096e-08 +4.1852029304456096e-08 +4.031745489662604e-08 +3.348162344356488e-08 +2.3297629646147227e-08 +1.9251933480049806e-08 +1.9251933480049806e-08 +2.3018616117450855e-08 +2.246058906005811e-08 +1.813587936526431e-08 +2.7761846105289214e-08 +2.4971710818325472e-08 +2.5111217582673662e-08 +2.4274176996584538e-08 +2.46926972896291e-08 +2.4832204053977286e-08 +2.5669244640066407e-08 +2.985444757051202e-08 +2.5669244640066407e-08 +3.724830608096593e-08 +4.0735975189670606e-08 +4.2549563126197034e-08 +4.394463076967891e-08 +4.0735975189670606e-08 +4.2828576654893406e-08 +4.3386603712286164e-08 +4.1433509011411543e-08 +3.4318664029654005e-08 +2.3995163467888165e-08 +1.9670453773094368e-08 +2.008897406613893e-08 +2.455319052528091e-08 +2.455319052528091e-08 +2.008897406613893e-08 +3.0970501685297515e-08 +2.7761846105289214e-08 +2.7901352869637404e-08 +2.7343325812244652e-08 +2.7622339340941025e-08 +2.6924805519200093e-08 +2.8180366398333776e-08 +3.320260991486851e-08 +2.7343325812244652e-08 +3.8782880488795985e-08 +4.1852029304456096e-08 +4.3805124005330716e-08 +4.492117812011622e-08 +4.157301577575972e-08 +4.310759018358978e-08 +4.3386603712286164e-08 +4.157301577575972e-08 +3.487669108704675e-08 +2.4413683760932724e-08 +1.9809960537442554e-08 +1.9809960537442554e-08 +2.4832204053977286e-08 +2.4274176996584538e-08 +1.911242671570162e-08 +2.8877900220074708e-08 +2.6366778461807345e-08 +2.650628522615553e-08 +2.6366778461807345e-08 +2.6227271697459155e-08 +2.6924805519200093e-08 +2.8180366398333776e-08 +3.2644582857475756e-08 +2.6785298754851907e-08 +3.86433737244478e-08 +4.1852029304456096e-08 +4.3386603712286164e-08 +4.464216459141985e-08 +4.199153606880429e-08 +4.366561724098254e-08 +4.366561724098254e-08 +4.1712522540107916e-08 +3.54347181444395e-08 +2.4832204053977286e-08 +2.0647001123531675e-08 +2.078650788787986e-08 +2.608776493311097e-08 +2.5390231111370035e-08 +1.9949467301790744e-08 +2.9156913748771087e-08 +2.5808751404414597e-08 +2.608776493311097e-08 +2.455319052528091e-08 +2.455319052528091e-08 +2.4832204053977286e-08 +2.5948258168762783e-08 +3.041247462790477e-08 +2.5250724347021848e-08 +3.613225196618043e-08 +3.948041431053692e-08 +4.115449548271517e-08 +4.199153606880429e-08 +3.906189401749236e-08 +4.003844136792967e-08 +3.948041431053692e-08 +3.627175873052862e-08 +2.9993954334860204e-08 +2.287910935310267e-08 +1.9251933480049806e-08 +1.9251933480049806e-08 +2.2321082295709924e-08 +2.1344534945272613e-08 +1.813587936526431e-08 +2.8877900220074708e-08 +2.5669244640066407e-08 +2.5808751404414597e-08 +2.4413683760932724e-08 +2.385565670353998e-08 +2.385565670353998e-08 +2.413467023223635e-08 +2.4274176996584538e-08 +2.5948258168762783e-08 +3.1947049035734825e-08 +3.75273196096623e-08 +3.989893460358149e-08 +4.059646842532242e-08 +3.892238725314418e-08 +3.7806333138358674e-08 +3.6411265494876805e-08 +3.5295211380091315e-08 +3.320260991486851e-08 +3.083099492094933e-08 +2.8877900220074708e-08 +2.873839345572652e-08 +3.069148815660114e-08 +3.027296786355658e-08 +2.873839345572652e-08 +2.6785298754851907e-08 +2.46926972896291e-08 +2.4971710818325472e-08 +2.3995163467888165e-08 +2.4971710818325472e-08 +2.3995163467888165e-08 +2.455319052528091e-08 +2.4274176996584538e-08 +2.287910935310267e-08 +2.3576643174843603e-08 +2.6227271697459155e-08 +2.7901352869637404e-08 +2.845937992703015e-08 +2.9296420513119273e-08 +2.943592727746746e-08 +2.9017406984422894e-08 +2.7761846105289214e-08 +2.706431228354828e-08 +2.6645791990503717e-08 +2.608776493311097e-08 +2.552973787571822e-08 +2.804085963398559e-08 +2.7761846105289214e-08 +2.608776493311097e-08 +2.4832204053977286e-08 +2.3716149939191793e-08 +2.455319052528091e-08 +2.3995163467888165e-08 +2.385565670353998e-08 +2.3716149939191793e-08 +2.4971710818325472e-08 +2.943592727746746e-08 +2.5111217582673662e-08 +3.682978578792137e-08 +3.989893460358149e-08 +4.199153606880429e-08 +4.3386603712286164e-08 +4.017794813227786e-08 +4.213104283315248e-08 +4.199153606880429e-08 +4.017794813227786e-08 +3.3342116679216694e-08 +2.315812288179904e-08 +1.9251933480049806e-08 +2.008897406613893e-08 +2.4971710818325472e-08 +2.3018616117450855e-08 +1.7996372600916123e-08 +2.7761846105289214e-08 +2.5111217582673662e-08 +2.5250724347021848e-08 +2.4274176996584538e-08 +2.4274176996584538e-08 +2.455319052528091e-08 +2.5390231111370035e-08 +2.9993954334860204e-08 +2.5948258168762783e-08 +3.7387812845314116e-08 +4.0735975189670606e-08 +4.227054959750066e-08 +4.3386603712286164e-08 +4.031745489662604e-08 +4.2410056361848854e-08 +4.29680834192416e-08 +4.0735975189670606e-08 +3.390014373660944e-08 +2.3437136410495414e-08 +1.9670453773094368e-08 +2.1205028180924427e-08 +2.5250724347021848e-08 +2.3297629646147227e-08 +1.8693906422657058e-08 +2.9575434041815645e-08 +2.7761846105289214e-08 +2.8180366398333776e-08 +2.7622339340941025e-08 +2.7482832576592838e-08 +2.706431228354828e-08 +2.7482832576592838e-08 +3.3342116679216694e-08 +2.7622339340941025e-08 +3.9340907546188736e-08 +4.1712522540107916e-08 +4.310759018358978e-08 +4.408413753402709e-08 +4.0735975189670606e-08 +4.2410056361848854e-08 +4.2549563126197034e-08 +4.087548195401879e-08 +3.417915726530581e-08 +2.3995163467888165e-08 +1.953094700874618e-08 +2.078650788787986e-08 +2.5808751404414597e-08 +2.3576643174843603e-08 +1.82753861296125e-08 +2.7761846105289214e-08 +2.5250724347021848e-08 +2.650628522615553e-08 +2.6366778461807345e-08 +2.6785298754851907e-08 +2.7482832576592838e-08 +2.8319873162681962e-08 +3.348162344356488e-08 +2.7622339340941025e-08 +3.906189401749236e-08 +4.2549563126197034e-08 +4.3805124005330716e-08 +4.492117812011622e-08 +4.199153606880429e-08 +4.408413753402709e-08 +4.366561724098254e-08 +4.157301577575972e-08 +3.5016197851394936e-08 +2.5250724347021848e-08 +2.078650788787986e-08 +2.1623548473968986e-08 +2.6924805519200093e-08 +2.4971710818325472e-08 +1.9251933480049806e-08 +2.8180366398333776e-08 +2.455319052528091e-08 +2.4971710818325472e-08 +2.3576643174843603e-08 +2.3716149939191793e-08 +2.3716149939191793e-08 +2.46926972896291e-08 +2.985444757051202e-08 +2.5390231111370035e-08 +3.6411265494876805e-08 +3.948041431053692e-08 +4.101498871836698e-08 +4.199153606880429e-08 +3.850386696009961e-08 +3.961992107488511e-08 +3.8782880488795985e-08 +3.54347181444395e-08 +2.9156913748771087e-08 +2.218157553136173e-08 +1.8693906422657058e-08 +1.9809960537442554e-08 +2.2739602588754482e-08 +2.0926014652228048e-08 +1.771735907221975e-08 +2.804085963398559e-08 +2.4971710818325472e-08 +2.4832204053977286e-08 +2.3437136410495414e-08 +2.3018616117450855e-08 +2.3018616117450855e-08 +2.3297629646147227e-08 +2.3576643174843603e-08 +2.552973787571822e-08 +3.124951521399389e-08 +3.54347181444395e-08 +3.8364360195751426e-08 +3.948041431053692e-08 +3.794583990270687e-08 +3.6550772259225e-08 +3.54347181444395e-08 +3.487669108704675e-08 +3.2644582857475756e-08 +3.041247462790477e-08 +2.9017406984422894e-08 +2.9017406984422894e-08 +3.11100084496457e-08 +3.013346109920839e-08 +2.8598886691378335e-08 +2.6785298754851907e-08 +2.4971710818325472e-08 +2.5250724347021848e-08 +2.455319052528091e-08 +2.46926972896291e-08 +2.413467023223635e-08 +2.4274176996584538e-08 +2.385565670353998e-08 +2.218157553136173e-08 +2.2321082295709924e-08 +2.4832204053977286e-08 +2.650628522615553e-08 +2.7343325812244652e-08 +2.8319873162681962e-08 +2.8319873162681962e-08 +2.8180366398333776e-08 +2.6924805519200093e-08 +2.6227271697459155e-08 +2.5808751404414597e-08 +2.552973787571822e-08 +2.5111217582673662e-08 +2.650628522615553e-08 +2.608776493311097e-08 +2.455319052528091e-08 +2.3437136410495414e-08 +2.1902562002665358e-08 +2.287910935310267e-08 +2.246058906005811e-08 +2.2321082295709924e-08 +2.2321082295709924e-08 +2.3716149939191793e-08 +2.8598886691378335e-08 +2.5250724347021848e-08 +3.710879931661774e-08 +4.017794813227786e-08 +4.199153606880429e-08 +4.29680834192416e-08 +3.9759427839233295e-08 +4.1712522540107916e-08 +4.1852029304456096e-08 +3.989893460358149e-08 +3.278408962182394e-08 +2.2600095824406296e-08 +1.855439965830887e-08 +2.0367987594835303e-08 +2.5111217582673662e-08 +2.2042068767013544e-08 +1.674081172178244e-08 +2.5250724347021848e-08 +2.2600095824406296e-08 +2.3018616117450855e-08 +2.246058906005811e-08 +2.2600095824406296e-08 +2.3297629646147227e-08 +2.4413683760932724e-08 +2.9575434041815645e-08 +2.6227271697459155e-08 +3.7666826374010495e-08 +4.101498871836698e-08 +4.2410056361848854e-08 +4.366561724098254e-08 +4.045696166097423e-08 +4.227054959750066e-08 +4.2549563126197034e-08 +4.059646842532242e-08 +3.348162344356488e-08 +2.315812288179904e-08 +1.9391440244397992e-08 +2.14840417096208e-08 +2.5808751404414597e-08 +2.3018616117450855e-08 +1.7856865836567937e-08 +2.6645791990503717e-08 +2.46926972896291e-08 +2.4413683760932724e-08 +2.3716149939191793e-08 +2.3716149939191793e-08 +2.385565670353998e-08 +2.455319052528091e-08 +2.9993954334860204e-08 +2.6227271697459155e-08 +3.850386696009961e-08 +4.0735975189670606e-08 +4.2410056361848854e-08 +4.3526110476634344e-08 +4.059646842532242e-08 +4.213104283315248e-08 +4.2410056361848854e-08 +4.031745489662604e-08 +3.362113020791307e-08 +2.3437136410495414e-08 +1.953094700874618e-08 +2.218157553136173e-08 +2.6227271697459155e-08 +2.315812288179904e-08 +1.771735907221975e-08 +2.608776493311097e-08 +2.3297629646147227e-08 +2.4274176996584538e-08 +2.3716149939191793e-08 +2.385565670353998e-08 +2.3995163467888165e-08 +2.5250724347021848e-08 +3.041247462790477e-08 +2.6227271697459155e-08 +3.7666826374010495e-08 +4.115449548271517e-08 +4.2549563126197034e-08 +4.3805124005330716e-08 +4.115449548271517e-08 +4.310759018358978e-08 +4.310759018358978e-08 +4.129400224706335e-08 +3.445817079400219e-08 +2.46926972896291e-08 +2.050749435918349e-08 +2.315812288179904e-08 +2.706431228354828e-08 +2.4413683760932724e-08 +1.855439965830887e-08 +2.7482832576592838e-08 +2.385565670353998e-08 +2.413467023223635e-08 +2.287910935310267e-08 +2.287910935310267e-08 +2.3018616117450855e-08 +2.4274176996584538e-08 +2.9575434041815645e-08 +2.5808751404414597e-08 +3.6690279023573184e-08 +3.9759427839233295e-08 +4.1433509011411543e-08 +4.2410056361848854e-08 +3.8782880488795985e-08 +4.003844136792967e-08 +3.892238725314418e-08 +3.5713731673135874e-08 +2.985444757051202e-08 +2.2739602588754482e-08 +1.911242671570162e-08 +2.0647001123531675e-08 +2.3297629646147227e-08 +2.0647001123531675e-08 +1.7438345543523375e-08 +2.7203819047896466e-08 +2.4274176996584538e-08 +2.46926972896291e-08 +2.3576643174843603e-08 +2.3576643174843603e-08 +2.287910935310267e-08 +2.315812288179904e-08 +2.3576643174843603e-08 +2.5390231111370035e-08 +3.083099492094933e-08 +3.4039650500957626e-08 +3.6690279023573184e-08 +3.794583990270687e-08 +3.627175873052862e-08 +3.5016197851394936e-08 +3.445817079400219e-08 +3.3342116679216694e-08 +3.1947049035734825e-08 +2.9296420513119273e-08 +2.8319873162681962e-08 +2.8877900220074708e-08 +3.0551981392252956e-08 +2.9714940806163832e-08 +2.8877900220074708e-08 +2.7343325812244652e-08 +2.5390231111370035e-08 +2.6366778461807345e-08 +2.5808751404414597e-08 +2.5390231111370035e-08 +2.5250724347021848e-08 +2.5390231111370035e-08 +2.5111217582673662e-08 +2.385565670353998e-08 +2.3297629646147227e-08 +2.4971710818325472e-08 +2.6924805519200093e-08 +2.7901352869637404e-08 +2.8319873162681962e-08 +2.8319873162681962e-08 +2.7761846105289214e-08 +2.7203819047896466e-08 +2.650628522615553e-08 +2.5948258168762783e-08 +2.552973787571822e-08 +2.6227271697459155e-08 +2.7761846105289214e-08 +2.6924805519200093e-08 +2.552973787571822e-08 +2.4274176996584538e-08 +2.2321082295709924e-08 +2.3297629646147227e-08 +2.2739602588754482e-08 +2.3297629646147227e-08 +2.3576643174843603e-08 +2.4971710818325472e-08 +3.013346109920839e-08 +2.6366778461807345e-08 +3.7806333138358674e-08 +4.087548195401879e-08 +4.2549563126197034e-08 +4.366561724098254e-08 +4.045696166097423e-08 +4.2410056361848854e-08 +4.2549563126197034e-08 +4.059646842532242e-08 +3.362113020791307e-08 +2.3437136410495414e-08 +1.9809960537442554e-08 +2.3018616117450855e-08 +2.608776493311097e-08 +2.218157553136173e-08 +1.7159332014827002e-08 +2.5808751404414597e-08 +2.287910935310267e-08 +2.3716149939191793e-08 +2.315812288179904e-08 +2.413467023223635e-08 +2.4971710818325472e-08 +2.5808751404414597e-08 +3.11100084496457e-08 +2.7761846105289214e-08 +3.920140078184055e-08 +4.2549563126197034e-08 +4.394463076967891e-08 +4.520019164881259e-08 +4.1852029304456096e-08 +4.366561724098254e-08 +4.366561724098254e-08 +4.199153606880429e-08 +3.487669108704675e-08 +2.455319052528091e-08 +2.050749435918349e-08 +2.3995163467888165e-08 +2.7622339340941025e-08 +2.4274176996584538e-08 +1.8414892893960685e-08 +2.650628522615553e-08 +2.413467023223635e-08 +2.413467023223635e-08 +2.3576643174843603e-08 +2.413467023223635e-08 +2.385565670353998e-08 +2.5808751404414597e-08 +3.11100084496457e-08 +2.706431228354828e-08 +3.8782880488795985e-08 +4.1712522540107916e-08 +4.366561724098254e-08 +4.492117812011622e-08 +4.157301577575972e-08 +4.324709694793797e-08 +4.324709694793797e-08 +4.1433509011411543e-08 +3.487669108704675e-08 +2.4274176996584538e-08 +2.008897406613893e-08 +2.413467023223635e-08 +2.6924805519200093e-08 +2.385565670353998e-08 +1.813587936526431e-08 +2.5948258168762783e-08 +2.3018616117450855e-08 +2.3576643174843603e-08 +2.246058906005811e-08 +2.2600095824406296e-08 +2.2600095824406296e-08 +2.4413683760932724e-08 +2.985444757051202e-08 +2.6785298754851907e-08 +3.8085346667055053e-08 +4.1433509011411543e-08 +4.324709694793797e-08 +4.464216459141985e-08 +4.1852029304456096e-08 +4.366561724098254e-08 +4.3805124005330716e-08 +4.1852029304456096e-08 +3.5016197851394936e-08 +2.46926972896291e-08 +2.106552141657624e-08 +2.5390231111370035e-08 +2.7761846105289214e-08 +2.46926972896291e-08 +1.8833413187005247e-08 +2.7901352869637404e-08 +2.4274176996584538e-08 +2.46926972896291e-08 +2.3297629646147227e-08 +2.385565670353998e-08 +2.3716149939191793e-08 +2.4832204053977286e-08 +3.0551981392252956e-08 +2.6645791990503717e-08 +3.7387812845314116e-08 +4.059646842532242e-08 +4.227054959750066e-08 +4.29680834192416e-08 +3.961992107488511e-08 +4.087548195401879e-08 +3.989893460358149e-08 +3.6690279023573184e-08 +3.0970501685297515e-08 +2.3716149939191793e-08 +2.008897406613893e-08 +2.2739602588754482e-08 +2.413467023223635e-08 +2.106552141657624e-08 +1.7856865836567937e-08 +2.7761846105289214e-08 +2.4832204053977286e-08 +2.5390231111370035e-08 +2.455319052528091e-08 +2.4274176996584538e-08 +2.3437136410495414e-08 +2.3437136410495414e-08 +2.46926972896291e-08 +2.6924805519200093e-08 +3.152852874269026e-08 +3.54347181444395e-08 +3.822485343140324e-08 +3.8782880488795985e-08 +3.710879931661774e-08 +3.627175873052862e-08 +3.5992745201832246e-08 +3.4737184322698563e-08 +3.348162344356488e-08 +3.069148815660114e-08 +2.9156913748771087e-08 +3.0551981392252956e-08 +3.11100084496457e-08 +3.013346109920839e-08 +2.9575434041815645e-08 +2.7901352869637404e-08 +2.5669244640066407e-08 +2.6645791990503717e-08 +2.5669244640066407e-08 +2.5390231111370035e-08 +2.5390231111370035e-08 +2.552973787571822e-08 +2.552973787571822e-08 +2.4832204053977286e-08 +2.413467023223635e-08 +2.5669244640066407e-08 +2.7901352869637404e-08 +2.8598886691378335e-08 +2.8877900220074708e-08 +2.873839345572652e-08 +2.8180366398333776e-08 +2.7761846105289214e-08 +2.6785298754851907e-08 +2.6366778461807345e-08 +2.5669244640066407e-08 +2.7203819047896466e-08 +2.8180366398333776e-08 +2.7343325812244652e-08 +2.5808751404414597e-08 +2.455319052528091e-08 +2.2600095824406296e-08 +2.3716149939191793e-08 +2.3995163467888165e-08 +2.4413683760932724e-08 +2.46926972896291e-08 +2.5808751404414597e-08 +3.124951521399389e-08 +2.7203819047896466e-08 +3.822485343140324e-08 +4.129400224706335e-08 +4.29680834192416e-08 +4.436315106272346e-08 +4.087548195401879e-08 +4.2689069890545226e-08 +4.2828576654893406e-08 +4.101498871836698e-08 +3.445817079400219e-08 +2.385565670353998e-08 +2.0647001123531675e-08 +2.5250724347021848e-08 +2.6366778461807345e-08 +2.246058906005811e-08 +1.7438345543523375e-08 +2.6366778461807345e-08 +2.3297629646147227e-08 +2.385565670353998e-08 +2.3297629646147227e-08 +2.3995163467888165e-08 +2.4413683760932724e-08 +2.5250724347021848e-08 +3.0970501685297515e-08 +2.804085963398559e-08 +3.9340907546188736e-08 +4.2689069890545226e-08 +4.436315106272346e-08 +4.5479205177508965e-08 +4.199153606880429e-08 +4.3805124005330716e-08 +4.394463076967891e-08 +4.213104283315248e-08 +3.5016197851394936e-08 +2.46926972896291e-08 +2.0926014652228048e-08 +2.5948258168762783e-08 +2.7482832576592838e-08 +2.4413683760932724e-08 +1.813587936526431e-08 +2.6366778461807345e-08 +2.3576643174843603e-08 +2.413467023223635e-08 +2.3297629646147227e-08 +2.3437136410495414e-08 +2.3437136410495414e-08 +2.5250724347021848e-08 +3.11100084496457e-08 +2.7622339340941025e-08 +3.892238725314418e-08 +4.199153606880429e-08 +4.394463076967891e-08 +4.520019164881259e-08 +4.1712522540107916e-08 +4.3526110476634344e-08 +4.3526110476634344e-08 +4.1852029304456096e-08 +3.487669108704675e-08 +2.4413683760932724e-08 +2.106552141657624e-08 +2.552973787571822e-08 +2.6645791990503717e-08 +2.3576643174843603e-08 +1.7856865836567937e-08 +2.6785298754851907e-08 +2.385565670353998e-08 +2.455319052528091e-08 +2.385565670353998e-08 +2.3995163467888165e-08 +2.413467023223635e-08 +2.5390231111370035e-08 +3.1947049035734825e-08 +2.845937992703015e-08 +3.9759427839233295e-08 +4.310759018358978e-08 +4.5479205177508965e-08 +4.673476605664265e-08 +4.3386603712286164e-08 +4.50606848844644e-08 +4.478167135576803e-08 +4.2410056361848854e-08 +3.54347181444395e-08 +2.4971710818325472e-08 +2.1623548473968986e-08 +2.6924805519200093e-08 +2.7901352869637404e-08 +2.46926972896291e-08 +1.8972919951353434e-08 +2.7901352869637404e-08 +2.46926972896291e-08 +2.5250724347021848e-08 +2.385565670353998e-08 +2.455319052528091e-08 +2.46926972896291e-08 +2.5808751404414597e-08 +3.22260625644312e-08 +2.8319873162681962e-08 +3.948041431053692e-08 +4.2689069890545226e-08 +4.436315106272346e-08 +4.478167135576803e-08 +4.115449548271517e-08 +4.1852029304456096e-08 +4.1433509011411543e-08 +3.794583990270687e-08 +3.152852874269026e-08 +2.3995163467888165e-08 +2.1205028180924427e-08 +2.455319052528091e-08 +2.4413683760932724e-08 +2.1344534945272613e-08 +1.8414892893960685e-08 +2.943592727746746e-08 +2.650628522615553e-08 +2.6645791990503717e-08 +2.5390231111370035e-08 +2.552973787571822e-08 +2.5808751404414597e-08 +2.6227271697459155e-08 +2.7482832576592838e-08 +3.013346109920839e-08 +3.376063697226125e-08 +3.75273196096623e-08 +4.059646842532242e-08 +4.115449548271517e-08 +3.920140078184055e-08 +3.794583990270687e-08 +3.724830608096593e-08 +3.5992745201832246e-08 +3.459767755835038e-08 +3.2365569328779384e-08 +3.041247462790477e-08 +3.250507609312757e-08 +3.1668035507038446e-08 +3.027296786355658e-08 +2.9156913748771087e-08 +2.845937992703015e-08 +2.6366778461807345e-08 +2.6645791990503717e-08 +2.650628522615553e-08 +2.5948258168762783e-08 +2.4832204053977286e-08 +2.4971710818325472e-08 +2.46926972896291e-08 +2.4413683760932724e-08 +2.455319052528091e-08 +2.6366778461807345e-08 +2.845937992703015e-08 +2.943592727746746e-08 +3.013346109920839e-08 +2.9993954334860204e-08 +2.943592727746746e-08 +2.9017406984422894e-08 +2.845937992703015e-08 +2.804085963398559e-08 +2.7761846105289214e-08 +2.9296420513119273e-08 +2.943592727746746e-08 +2.845937992703015e-08 +2.706431228354828e-08 +2.6227271697459155e-08 +2.455319052528091e-08 +2.5808751404414597e-08 +2.5948258168762783e-08 +2.5948258168762783e-08 +2.5948258168762783e-08 +2.6924805519200093e-08 +3.208655580008301e-08 +2.8180366398333776e-08 +3.9340907546188736e-08 +4.227054959750066e-08 +4.422364429837528e-08 +4.533969841316077e-08 +4.1852029304456096e-08 +4.3526110476634344e-08 +4.394463076967891e-08 +4.199153606880429e-08 +3.54347181444395e-08 +2.455319052528091e-08 +2.2321082295709924e-08 +2.706431228354828e-08 +2.7203819047896466e-08 +2.3576643174843603e-08 +1.8414892893960685e-08 +2.8319873162681962e-08 +2.5250724347021848e-08 +2.6227271697459155e-08 +2.5808751404414597e-08 +2.5390231111370035e-08 +2.5390231111370035e-08 +2.6366778461807345e-08 +3.1947049035734825e-08 +2.873839345572652e-08 +4.045696166097423e-08 +4.3386603712286164e-08 +4.50606848844644e-08 +4.603723223490171e-08 +4.2689069890545226e-08 +4.408413753402709e-08 +4.436315106272346e-08 +4.2410056361848854e-08 +3.557422490878769e-08 +2.552973787571822e-08 +2.3018616117450855e-08 +2.8598886691378335e-08 +2.873839345572652e-08 +2.552973787571822e-08 +1.9670453773094368e-08 +2.9575434041815645e-08 +2.6785298754851907e-08 +2.7203819047896466e-08 +2.6785298754851907e-08 +2.6645791990503717e-08 +2.6366778461807345e-08 +2.8598886691378335e-08 +3.445817079400219e-08 +3.041247462790477e-08 +4.213104283315248e-08 +4.478167135576803e-08 +4.631624576359808e-08 +4.729279311403539e-08 +4.408413753402709e-08 +4.5897725470553524e-08 +4.5897725470553524e-08 +4.3805124005330716e-08 +3.682978578792137e-08 +2.6785298754851907e-08 +2.4832204053977286e-08 +2.9714940806163832e-08 +2.9017406984422894e-08 +2.5669244640066407e-08 +2.008897406613893e-08 +3.069148815660114e-08 +2.804085963398559e-08 +2.8319873162681962e-08 +2.6924805519200093e-08 +2.650628522615553e-08 +2.650628522615553e-08 +2.7343325812244652e-08 +3.362113020791307e-08 +2.9714940806163832e-08 +4.101498871836698e-08 +4.464216459141985e-08 +4.6455752527946275e-08 +4.7432299878383586e-08 +4.394463076967891e-08 +4.5897725470553524e-08 +4.5618711941857144e-08 +4.310759018358978e-08 +3.585323843748406e-08 +2.5390231111370035e-08 +2.2600095824406296e-08 +2.804085963398559e-08 +2.8180366398333776e-08 +2.4832204053977286e-08 +1.9251933480049806e-08 +2.8180366398333776e-08 +2.5390231111370035e-08 +2.5948258168762783e-08 +2.455319052528091e-08 +2.4971710818325472e-08 +2.5250724347021848e-08 +2.6785298754851907e-08 +3.376063697226125e-08 +2.9156913748771087e-08 +4.087548195401879e-08 +4.408413753402709e-08 +4.533969841316077e-08 +4.575821870620534e-08 +4.1852029304456096e-08 +4.2549563126197034e-08 +4.157301577575972e-08 +3.8085346667055053e-08 +3.1668035507038446e-08 +2.4274176996584538e-08 +2.2042068767013544e-08 +2.4971710818325472e-08 +2.413467023223635e-08 +2.1205028180924427e-08 +1.8414892893960685e-08 +2.9993954334860204e-08 +2.7343325812244652e-08 +2.7203819047896466e-08 +2.5669244640066407e-08 +2.5948258168762783e-08 +2.5948258168762783e-08 +2.650628522615553e-08 +2.7622339340941025e-08 +3.083099492094933e-08 +3.4318664029654005e-08 +3.8085346667055053e-08 +4.101498871836698e-08 +4.1712522540107916e-08 +3.961992107488511e-08 +3.850386696009961e-08 +3.794583990270687e-08 +3.627175873052862e-08 +3.487669108704675e-08 +3.2644582857475756e-08 +3.0970501685297515e-08 +3.3342116679216694e-08 +3.22260625644312e-08 +3.124951521399389e-08 +3.013346109920839e-08 +2.8877900220074708e-08 +2.7203819047896466e-08 +2.7343325812244652e-08 +2.706431228354828e-08 +2.6366778461807345e-08 +2.5111217582673662e-08 +2.5390231111370035e-08 +2.5111217582673662e-08 +2.5390231111370035e-08 +2.5390231111370035e-08 +2.6924805519200093e-08 +2.9156913748771087e-08 +3.013346109920839e-08 +3.041247462790477e-08 +3.041247462790477e-08 +3.013346109920839e-08 +2.9714940806163832e-08 +2.943592727746746e-08 +2.9017406984422894e-08 +2.9296420513119273e-08 +3.0970501685297515e-08 +3.083099492094933e-08 +2.9993954334860204e-08 +2.9017406984422894e-08 +2.8319873162681962e-08 +2.6645791990503717e-08 +2.7761846105289214e-08 +2.6924805519200093e-08 +2.706431228354828e-08 +2.7203819047896466e-08 +2.7622339340941025e-08 +3.2365569328779384e-08 +2.873839345572652e-08 +4.003844136792967e-08 +4.2689069890545226e-08 +4.478167135576803e-08 +4.5618711941857144e-08 +4.213104283315248e-08 +4.3805124005330716e-08 +4.408413753402709e-08 +4.199153606880429e-08 +3.515570461574312e-08 +2.46926972896291e-08 +2.3297629646147227e-08 +2.706431228354828e-08 +2.650628522615553e-08 +2.287910935310267e-08 +1.7996372600916123e-08 +2.8180366398333776e-08 +2.552973787571822e-08 +2.650628522615553e-08 +2.5948258168762783e-08 +2.5669244640066407e-08 +2.5808751404414597e-08 +2.7482832576592838e-08 +3.292359638617213e-08 +2.9296420513119273e-08 +4.129400224706335e-08 +4.422364429837528e-08 +4.603723223490171e-08 +4.687427282099083e-08 +4.3386603712286164e-08 +4.478167135576803e-08 +4.478167135576803e-08 +4.2828576654893406e-08 +3.613225196618043e-08 +2.5808751404414597e-08 +2.3716149939191793e-08 +2.845937992703015e-08 +2.8180366398333776e-08 +2.46926972896291e-08 +1.9809960537442554e-08 +3.11100084496457e-08 +2.9156913748771087e-08 +2.9156913748771087e-08 +2.8877900220074708e-08 +2.845937992703015e-08 +2.8319873162681962e-08 +3.013346109920839e-08 +3.585323843748406e-08 +3.1389021978342073e-08 +4.310759018358978e-08 +4.5479205177508965e-08 +4.673476605664265e-08 +4.771131340707996e-08 +4.422364429837528e-08 +4.603723223490171e-08 +4.6455752527946275e-08 +4.436315106272346e-08 +3.75273196096623e-08 +2.7343325812244652e-08 +2.552973787571822e-08 +2.9575434041815645e-08 +2.8877900220074708e-08 +2.552973787571822e-08 +2.0228480830487117e-08 +3.11100084496457e-08 +2.9017406984422894e-08 +2.9017406984422894e-08 +2.7482832576592838e-08 +2.6645791990503717e-08 +2.6645791990503717e-08 +2.7761846105289214e-08 +3.362113020791307e-08 +2.9575434041815645e-08 +4.129400224706335e-08 +4.408413753402709e-08 +4.5479205177508965e-08 +4.631624576359808e-08 +4.2828576654893406e-08 +4.492117812011622e-08 +4.50606848844644e-08 +4.29680834192416e-08 +3.585323843748406e-08 +2.6227271697459155e-08 +2.4274176996584538e-08 +2.873839345572652e-08 +2.8598886691378335e-08 +2.5250724347021848e-08 +1.9949467301790744e-08 +2.9296420513119273e-08 +2.6785298754851907e-08 +2.7901352869637404e-08 +2.6366778461807345e-08 +2.6785298754851907e-08 +2.6227271697459155e-08 +2.7901352869637404e-08 +3.417915726530581e-08 +2.9156913748771087e-08 +4.031745489662604e-08 +4.29680834192416e-08 +4.394463076967891e-08 +4.4502657827071654e-08 +4.087548195401879e-08 +4.157301577575972e-08 +4.059646842532242e-08 +3.710879931661774e-08 +3.0970501685297515e-08 +2.3576643174843603e-08 +2.1205028180924427e-08 +2.3576643174843603e-08 +2.2739602588754482e-08 +1.9809960537442554e-08 +1.7159332014827002e-08 +2.8180366398333776e-08 +2.5669244640066407e-08 +2.552973787571822e-08 +2.4413683760932724e-08 +2.4274176996584538e-08 +2.413467023223635e-08 +2.4413683760932724e-08 +2.5390231111370035e-08 +2.9017406984422894e-08 +3.2644582857475756e-08 +3.6550772259225e-08 +3.948041431053692e-08 +4.003844136792967e-08 +3.822485343140324e-08 +3.7387812845314116e-08 +3.7387812845314116e-08 +3.682978578792137e-08 +3.5295211380091315e-08 +3.2644582857475756e-08 +3.1668035507038446e-08 +3.320260991486851e-08 +3.1947049035734825e-08 +3.027296786355658e-08 +2.9156913748771087e-08 +2.7622339340941025e-08 +2.5390231111370035e-08 +2.5669244640066407e-08 +2.455319052528091e-08 +2.4413683760932724e-08 +2.385565670353998e-08 +2.385565670353998e-08 +2.385565670353998e-08 +2.4274176996584538e-08 +2.385565670353998e-08 +2.4832204053977286e-08 +2.6785298754851907e-08 +2.7901352869637404e-08 +2.8319873162681962e-08 +2.873839345572652e-08 +2.8319873162681962e-08 +2.8180366398333776e-08 +2.7901352869637404e-08 +2.7203819047896466e-08 +2.7901352869637404e-08 +2.8877900220074708e-08 +2.873839345572652e-08 +2.7901352869637404e-08 +2.7343325812244652e-08 +2.650628522615553e-08 +2.5111217582673662e-08 +2.5808751404414597e-08 +2.5669244640066407e-08 +2.650628522615553e-08 +2.6924805519200093e-08 +2.7901352869637404e-08 +3.278408962182394e-08 +2.8180366398333776e-08 +3.948041431053692e-08 +4.29680834192416e-08 +4.464216459141985e-08 +4.5618711941857144e-08 +4.2689069890545226e-08 +4.422364429837528e-08 +4.394463076967891e-08 +4.199153606880429e-08 +3.5713731673135874e-08 +2.5808751404414597e-08 +2.3297629646147227e-08 +2.608776493311097e-08 +2.5111217582673662e-08 +2.1763055238317172e-08 +1.729883877917519e-08 +2.6785298754851907e-08 +2.4413683760932724e-08 +2.455319052528091e-08 +2.4274176996584538e-08 +2.4274176996584538e-08 +2.4413683760932724e-08 +2.6227271697459155e-08 +3.083099492094933e-08 +2.7343325812244652e-08 +3.961992107488511e-08 +4.3386603712286164e-08 +4.50606848844644e-08 +4.603723223490171e-08 +4.310759018358978e-08 +4.464216459141985e-08 +4.478167135576803e-08 +4.29680834192416e-08 +3.6411265494876805e-08 +2.6366778461807345e-08 +2.3995163467888165e-08 +2.6924805519200093e-08 +2.6645791990503717e-08 +2.315812288179904e-08 +1.8693906422657058e-08 +2.8877900220074708e-08 +2.6645791990503717e-08 +2.6227271697459155e-08 +2.608776493311097e-08 +2.6366778461807345e-08 +2.6645791990503717e-08 +2.6645791990503717e-08 +3.208655580008301e-08 +2.8180366398333776e-08 +4.003844136792967e-08 +4.324709694793797e-08 +4.4502657827071654e-08 +4.61767389992499e-08 +4.2828576654893406e-08 +4.3805124005330716e-08 +4.492117812011622e-08 +4.324709694793797e-08 +3.6690279023573184e-08 +2.7343325812244652e-08 +2.5111217582673662e-08 +2.7343325812244652e-08 +2.650628522615553e-08 +2.3716149939191793e-08 +1.8972919951353434e-08 +2.943592727746746e-08 +2.7203819047896466e-08 +2.6924805519200093e-08 +2.6645791990503717e-08 +2.6227271697459155e-08 +2.6227271697459155e-08 +2.7622339340941025e-08 +3.250507609312757e-08 +2.804085963398559e-08 +4.003844136792967e-08 +4.2828576654893406e-08 +4.464216459141985e-08 +4.5897725470553524e-08 +4.2549563126197034e-08 +4.3805124005330716e-08 +4.408413753402709e-08 +4.2410056361848854e-08 +3.613225196618043e-08 +2.706431228354828e-08 +2.552973787571822e-08 +2.8180366398333776e-08 +2.7761846105289214e-08 +2.4971710818325472e-08 +2.008897406613893e-08 +2.9993954334860204e-08 +2.6645791990503717e-08 +2.6785298754851907e-08 +2.5948258168762783e-08 +2.5948258168762783e-08 +2.5390231111370035e-08 +2.6924805519200093e-08 +3.208655580008301e-08 +2.7622339340941025e-08 +3.86433737244478e-08 +4.1852029304456096e-08 +4.3386603712286164e-08 +4.436315106272346e-08 +4.129400224706335e-08 +4.1433509011411543e-08 +4.101498871836698e-08 +3.7806333138358674e-08 +3.22260625644312e-08 +2.5250724347021848e-08 +2.315812288179904e-08 +2.3995163467888165e-08 +2.3297629646147227e-08 +2.0647001123531675e-08 +1.7856865836567937e-08 +2.873839345572652e-08 +2.5948258168762783e-08 +2.5669244640066407e-08 +2.455319052528091e-08 +2.4413683760932724e-08 +2.4971710818325472e-08 +2.5390231111370035e-08 +2.6227271697459155e-08 +2.9714940806163832e-08 +3.4039650500957626e-08 +3.7387812845314116e-08 +4.087548195401879e-08 +4.115449548271517e-08 +3.920140078184055e-08 +3.7666826374010495e-08 +3.7387812845314116e-08 +3.696929255226956e-08 +3.5713731673135874e-08 +3.362113020791307e-08 +3.320260991486851e-08 +3.3342116679216694e-08 +3.124951521399389e-08 +2.9714940806163832e-08 +2.9575434041815645e-08 +2.8319873162681962e-08 +2.6227271697459155e-08 +2.6366778461807345e-08 +5.1338489280132814e-08 +2.4971710818325472e-08 +2.4832204053977286e-08 +2.5111217582673662e-08 +2.4832204053977286e-08 +2.3995163467888165e-08 +2.455319052528091e-08 +2.650628522615553e-08 +2.7482832576592838e-08 +2.8319873162681962e-08 +2.873839345572652e-08 +2.845937992703015e-08 +2.873839345572652e-08 +2.8319873162681962e-08 +2.8319873162681962e-08 +2.943592727746746e-08 +2.9156913748771087e-08 +2.8598886691378335e-08 +2.7761846105289214e-08 +2.7343325812244652e-08 +2.6227271697459155e-08 +2.552973787571822e-08 +2.5250724347021848e-08 +2.5808751404414597e-08 +2.6366778461807345e-08 +2.706431228354828e-08 +2.8877900220074708e-08 +3.208655580008301e-08 +4.3386603712286164e-08 +3.5016197851394936e-08 +4.324709694793797e-08 +4.5897725470553524e-08 +4.701377958533902e-08 +4.631624576359808e-08 +4.50606848844644e-08 +4.603723223490171e-08 +4.533969841316077e-08 +4.129400224706335e-08 +3.3063103150520315e-08 +2.7901352869637404e-08 +2.8319873162681962e-08 +2.7343325812244652e-08 +2.5111217582673662e-08 +2.1205028180924427e-08 +1.757785230787156e-08 +2.845937992703015e-08 +2.6924805519200093e-08 +2.7761846105289214e-08 +2.7761846105289214e-08 +2.7343325812244652e-08 +2.7901352869637404e-08 +2.9993954334860204e-08 +4.129400224706335e-08 +3.4737184322698563e-08 +4.2549563126197034e-08 +4.478167135576803e-08 +4.631624576359808e-08 +4.5618711941857144e-08 +4.436315106272346e-08 +4.5897725470553524e-08 +4.5618711941857144e-08 +4.1433509011411543e-08 +3.3342116679216694e-08 +2.8877900220074708e-08 +2.8877900220074708e-08 +2.8319873162681962e-08 +2.608776493311097e-08 +2.1902562002665358e-08 +1.757785230787156e-08 +2.7901352869637404e-08 +2.6366778461807345e-08 +2.6366778461807345e-08 +2.650628522615553e-08 +2.6645791990503717e-08 +2.6645791990503717e-08 +2.985444757051202e-08 +4.087548195401879e-08 +3.445817079400219e-08 +4.2549563126197034e-08 +4.464216459141985e-08 +4.61767389992499e-08 +4.520019164881259e-08 +4.3386603712286164e-08 +4.50606848844644e-08 +4.436315106272346e-08 +4.031745489662604e-08 +3.292359638617213e-08 +2.9017406984422894e-08 +2.8180366398333776e-08 +2.7482832576592838e-08 +2.5669244640066407e-08 +2.14840417096208e-08 +1.757785230787156e-08 +2.7901352869637404e-08 +2.6366778461807345e-08 +2.6227271697459155e-08 +2.5808751404414597e-08 +2.5808751404414597e-08 +2.6645791990503717e-08 +2.9296420513119273e-08 +4.101498871836698e-08 +3.417915726530581e-08 +4.213104283315248e-08 +4.464216459141985e-08 +4.631624576359808e-08 +4.533969841316077e-08 +4.3805124005330716e-08 +4.492117812011622e-08 +4.436315106272346e-08 +4.031745489662604e-08 +3.278408962182394e-08 +2.8598886691378335e-08 +2.8319873162681962e-08 +2.7761846105289214e-08 +2.608776493311097e-08 +2.2042068767013544e-08 +1.757785230787156e-08 +2.7203819047896466e-08 +2.5250724347021848e-08 +2.4971710818325472e-08 +2.46926972896291e-08 +2.4413683760932724e-08 +2.5390231111370035e-08 +2.8319873162681962e-08 +3.961992107488511e-08 +3.320260991486851e-08 +4.087548195401879e-08 +4.3386603712286164e-08 +4.478167135576803e-08 +4.394463076967891e-08 +4.1852029304456096e-08 +4.227054959750066e-08 +4.045696166097423e-08 +3.5992745201832246e-08 +3.013346109920839e-08 +2.7343325812244652e-08 +2.5948258168762783e-08 +2.4971710818325472e-08 +2.3297629646147227e-08 +2.0647001123531675e-08 +1.771735907221975e-08 +2.9156913748771087e-08 +2.7622339340941025e-08 +2.7203819047896466e-08 +2.650628522615553e-08 +2.6366778461807345e-08 +2.650628522615553e-08 +2.7203819047896466e-08 +2.9296420513119273e-08 +3.320260991486851e-08 +3.696929255226956e-08 +4.087548195401879e-08 +4.227054959750066e-08 +4.1712522540107916e-08 +4.031745489662604e-08 +4.003844136792967e-08 +3.86433737244478e-08 +3.7387812845314116e-08 +3.724830608096593e-08 +3.7387812845314116e-08 +3.5713731673135874e-08 +3.348162344356488e-08 +3.250507609312757e-08 +3.208655580008301e-08 +3.0970501685297515e-08 +2.9296420513119273e-08 +2.8180366398333776e-08 +2.8598886691378335e-08 +2.7761846105289214e-08 +2.6645791990503717e-08 +2.6227271697459155e-08 +2.6785298754851907e-08 +2.6227271697459155e-08 +2.5390231111370035e-08 +2.5808751404414597e-08 +2.8180366398333776e-08 +2.9156913748771087e-08 +2.985444757051202e-08 +3.013346109920839e-08 +3.041247462790477e-08 +3.083099492094933e-08 +3.0551981392252956e-08 +3.1389021978342073e-08 +3.292359638617213e-08 +3.1668035507038446e-08 +3.013346109920839e-08 +2.9575434041815645e-08 +2.873839345572652e-08 +2.7203819047896466e-08 +2.6645791990503717e-08 +2.5669244640066407e-08 +2.6366778461807345e-08 +2.5808751404414597e-08 +2.6366778461807345e-08 +2.7203819047896466e-08 +2.9017406984422894e-08 +3.515570461574312e-08 +2.9993954334860204e-08 +4.213104283315248e-08 +4.5479205177508965e-08 +4.729279311403539e-08 +4.82693404644727e-08 +4.520019164881259e-08 +4.673476605664265e-08 +4.7153286349687207e-08 +4.464216459141985e-08 +3.8085346667055053e-08 +3.11100084496457e-08 +2.943592727746746e-08 +2.8598886691378335e-08 +2.6924805519200093e-08 +2.3297629646147227e-08 +1.8693906422657058e-08 +2.9714940806163832e-08 +2.706431228354828e-08 +2.7901352869637404e-08 +2.7901352869637404e-08 +2.7901352869637404e-08 +2.8319873162681962e-08 +2.9156913748771087e-08 +3.515570461574312e-08 +3.069148815660114e-08 +4.2549563126197034e-08 +4.5479205177508965e-08 +4.7153286349687207e-08 +4.799032693577633e-08 +4.422364429837528e-08 +4.631624576359808e-08 +4.687427282099083e-08 +4.478167135576803e-08 +3.850386696009961e-08 +3.152852874269026e-08 +2.9017406984422894e-08 +2.8877900220074708e-08 +2.7343325812244652e-08 +2.3995163467888165e-08 +1.8972919951353434e-08 +2.9575434041815645e-08 +2.6924805519200093e-08 +2.706431228354828e-08 +2.5948258168762783e-08 +2.6227271697459155e-08 +2.6645791990503717e-08 +2.7901352869637404e-08 +3.376063697226125e-08 +2.9993954334860204e-08 +4.199153606880429e-08 +4.492117812011622e-08 +4.631624576359808e-08 +4.729279311403539e-08 +4.324709694793797e-08 +4.492117812011622e-08 +4.520019164881259e-08 +4.3386603712286164e-08 +3.7387812845314116e-08 +3.1668035507038446e-08 +2.873839345572652e-08 +2.873839345572652e-08 +2.6924805519200093e-08 +2.3576643174843603e-08 +1.82753861296125e-08 +2.8180366398333776e-08 +2.552973787571822e-08 +2.5669244640066407e-08 +2.4832204053977286e-08 +2.4832204053977286e-08 +2.5111217582673662e-08 +2.6785298754851907e-08 +3.278408962182394e-08 +2.9714940806163832e-08 +4.1852029304456096e-08 +4.492117812011622e-08 +4.6595259292294455e-08 +4.771131340707996e-08 +4.422364429837528e-08 +4.61767389992499e-08 +4.6595259292294455e-08 +4.4502657827071654e-08 +3.8364360195751426e-08 +3.152852874269026e-08 +2.873839345572652e-08 +2.8180366398333776e-08 +2.706431228354828e-08 +2.3576643174843603e-08 +1.855439965830887e-08 +2.8598886691378335e-08 +2.5948258168762783e-08 +2.6366778461807345e-08 +2.5390231111370035e-08 +2.5250724347021848e-08 +2.5390231111370035e-08 +2.6645791990503717e-08 +3.3063103150520315e-08 +2.9017406984422894e-08 +4.045696166097423e-08 +4.3386603712286164e-08 +4.492117812011622e-08 +4.5479205177508965e-08 +4.1852029304456096e-08 +4.2689069890545226e-08 +4.227054959750066e-08 +3.850386696009961e-08 +3.3063103150520315e-08 +2.9156913748771087e-08 +2.6227271697459155e-08 +2.5390231111370035e-08 +2.413467023223635e-08 +2.1623548473968986e-08 +1.8414892893960685e-08 +3.027296786355658e-08 +2.7761846105289214e-08 +2.8180366398333776e-08 +2.6785298754851907e-08 +2.6227271697459155e-08 +2.608776493311097e-08 +2.6645791990503717e-08 +2.7482832576592838e-08 +3.083099492094933e-08 +3.515570461574312e-08 +3.906189401749236e-08 +4.199153606880429e-08 +4.2828576654893406e-08 +4.1712522540107916e-08 +4.115449548271517e-08 +4.059646842532242e-08 +3.948041431053692e-08 +4.045696166097423e-08 +4.031745489662604e-08 +3.6550772259225e-08 +3.487669108704675e-08 +3.348162344356488e-08 +3.2365569328779384e-08 +3.124951521399389e-08 +2.985444757051202e-08 +2.8180366398333776e-08 +2.8598886691378335e-08 +2.7761846105289214e-08 +2.650628522615553e-08 +2.5669244640066407e-08 +2.5808751404414597e-08 +2.5808751404414597e-08 +2.5808751404414597e-08 +2.5808751404414597e-08 +2.7901352869637404e-08 +2.9575434041815645e-08 +3.013346109920839e-08 +3.083099492094933e-08 +3.0970501685297515e-08 +3.124951521399389e-08 +3.11100084496457e-08 +3.1668035507038446e-08 +3.292359638617213e-08 +3.1389021978342073e-08 +3.013346109920839e-08 +2.943592727746746e-08 +2.873839345572652e-08 +2.7482832576592838e-08 +2.6366778461807345e-08 +2.5111217582673662e-08 +2.6366778461807345e-08 +2.552973787571822e-08 +2.5808751404414597e-08 +2.6366778461807345e-08 +2.8319873162681962e-08 +3.459767755835038e-08 +3.013346109920839e-08 +4.227054959750066e-08 +4.5618711941857144e-08 +4.7432299878383586e-08 +4.812983370012452e-08 +4.533969841316077e-08 +4.7153286349687207e-08 +4.7432299878383586e-08 +4.50606848844644e-08 +3.86433737244478e-08 +3.1668035507038446e-08 +2.9296420513119273e-08 +2.8598886691378335e-08 +2.650628522615553e-08 +2.2739602588754482e-08 +1.813587936526431e-08 +2.9156913748771087e-08 +2.6785298754851907e-08 +2.7622339340941025e-08 +2.6785298754851907e-08 +2.7343325812244652e-08 +2.7622339340941025e-08 +2.9156913748771087e-08 +3.515570461574312e-08 +3.11100084496457e-08 +4.3526110476634344e-08 +4.6455752527946275e-08 +4.785082017142814e-08 +4.868786075751727e-08 +4.492117812011622e-08 +4.673476605664265e-08 +4.701377958533902e-08 +4.478167135576803e-08 +3.86433737244478e-08 +3.1947049035734825e-08 +2.8877900220074708e-08 +2.8598886691378335e-08 +2.7343325812244652e-08 +2.3995163467888165e-08 +1.8972919951353434e-08 +2.943592727746746e-08 +2.6924805519200093e-08 +2.7343325812244652e-08 +2.6366778461807345e-08 +2.6645791990503717e-08 +2.7203819047896466e-08 +2.8598886691378335e-08 +3.515570461574312e-08 +3.124951521399389e-08 +4.3386603712286164e-08 +4.631624576359808e-08 +4.799032693577633e-08 +4.9245887814910014e-08 +4.5479205177508965e-08 +4.7153286349687207e-08 +4.7153286349687207e-08 +4.50606848844644e-08 +3.9340907546188736e-08 +3.292359638617213e-08 +2.9714940806163832e-08 +2.9714940806163832e-08 +2.7761846105289214e-08 +2.455319052528091e-08 +1.911242671570162e-08 +2.985444757051202e-08 +2.7203819047896466e-08 +2.8319873162681962e-08 +2.7482832576592838e-08 +2.7622339340941025e-08 +2.8180366398333776e-08 +3.041247462790477e-08 +3.627175873052862e-08 +3.1947049035734825e-08 +4.436315106272346e-08 +4.785082017142814e-08 +4.93853945792582e-08 +5.036194192969551e-08 +4.7153286349687207e-08 +4.896687428621364e-08 +4.910638105056182e-08 +4.701377958533902e-08 +4.115449548271517e-08 +3.4039650500957626e-08 +3.083099492094933e-08 +2.9993954334860204e-08 +2.873839345572652e-08 +2.4971710818325472e-08 +1.9391440244397992e-08 +3.027296786355658e-08 +2.7622339340941025e-08 +2.873839345572652e-08 +2.7761846105289214e-08 +2.7901352869637404e-08 +2.8598886691378335e-08 +2.9575434041815645e-08 +3.557422490878769e-08 +3.0551981392252956e-08 +4.2689069890545226e-08 +4.520019164881259e-08 +4.687427282099083e-08 +4.729279311403539e-08 +4.3526110476634344e-08 +4.436315106272346e-08 +4.366561724098254e-08 +4.003844136792967e-08 +3.4737184322698563e-08 +3.027296786355658e-08 +2.6645791990503717e-08 +2.5808751404414597e-08 +2.4274176996584538e-08 +2.1623548473968986e-08 +1.855439965830887e-08 +2.9993954334860204e-08 +2.7343325812244652e-08 +2.7482832576592838e-08 +2.650628522615553e-08 +2.6785298754851907e-08 +2.6924805519200093e-08 +2.7343325812244652e-08 +2.8319873162681962e-08 +3.1947049035734825e-08 +3.613225196618043e-08 +3.989893460358149e-08 +4.29680834192416e-08 +4.3805124005330716e-08 +4.2410056361848854e-08 +4.087548195401879e-08 +4.059646842532242e-08 +3.961992107488511e-08 +4.129400224706335e-08 +4.045696166097423e-08 +3.6550772259225e-08 +3.4737184322698563e-08 +3.3063103150520315e-08 +3.180754227138664e-08 +3.027296786355658e-08 +2.9156913748771087e-08 +2.804085963398559e-08 +2.8877900220074708e-08 +2.8319873162681962e-08 +2.7761846105289214e-08 +2.706431228354828e-08 +2.6785298754851907e-08 +2.650628522615553e-08 +2.7343325812244652e-08 +2.6924805519200093e-08 +2.8180366398333776e-08 +2.9993954334860204e-08 +3.083099492094933e-08 +3.2365569328779384e-08 +3.1947049035734825e-08 +3.22260625644312e-08 +3.278408962182394e-08 +3.3342116679216694e-08 +3.4318664029654005e-08 +3.292359638617213e-08 +3.180754227138664e-08 +3.11100084496457e-08 +3.027296786355658e-08 +2.9156913748771087e-08 +2.7622339340941025e-08 +2.5669244640066407e-08 +2.6785298754851907e-08 +2.608776493311097e-08 +2.6227271697459155e-08 +2.7203819047896466e-08 +2.9017406984422894e-08 +3.5295211380091315e-08 +3.124951521399389e-08 +4.3805124005330716e-08 +4.687427282099083e-08 +4.840884722882089e-08 +4.882736752186545e-08 +4.5618711941857144e-08 +4.785082017142814e-08 +4.785082017142814e-08 +4.5618711941857144e-08 +3.961992107488511e-08 +3.2644582857475756e-08 +2.985444757051202e-08 +2.9156913748771087e-08 +2.706431228354828e-08 +2.315812288179904e-08 +1.855439965830887e-08 +2.985444757051202e-08 +2.7622339340941025e-08 +2.845937992703015e-08 +2.7761846105289214e-08 +2.7622339340941025e-08 +2.8180366398333776e-08 +2.985444757051202e-08 +3.613225196618043e-08 +3.1947049035734825e-08 +4.436315106272346e-08 +4.7153286349687207e-08 +4.8548353993169076e-08 +4.93853945792582e-08 +4.533969841316077e-08 +4.7153286349687207e-08 +4.7571806642731765e-08 +4.533969841316077e-08 +3.948041431053692e-08 +3.250507609312757e-08 +2.9296420513119273e-08 +2.8877900220074708e-08 +2.7482832576592838e-08 +2.413467023223635e-08 +1.8833413187005247e-08 +2.9714940806163832e-08 +2.7482832576592838e-08 +2.7901352869637404e-08 +2.7203819047896466e-08 +2.7482832576592838e-08 +2.804085963398559e-08 +2.943592727746746e-08 +3.585323843748406e-08 +3.208655580008301e-08 +4.4502657827071654e-08 +4.785082017142814e-08 +4.9245887814910014e-08 +5.0501448694043697e-08 +4.687427282099083e-08 +4.8548353993169076e-08 +4.8548353993169076e-08 +4.61767389992499e-08 +4.087548195401879e-08 +3.376063697226125e-08 +2.985444757051202e-08 +2.943592727746746e-08 +2.7901352869637404e-08 +2.4413683760932724e-08 +1.911242671570162e-08 +3.013346109920839e-08 +2.7622339340941025e-08 +2.8877900220074708e-08 +2.804085963398559e-08 +2.8598886691378335e-08 +2.9017406984422894e-08 +3.124951521399389e-08 +3.75273196096623e-08 +3.278408962182394e-08 +4.520019164881259e-08 +4.8548353993169076e-08 +4.9943421636650945e-08 +5.1338489280132814e-08 +4.812983370012452e-08 +4.980391487230276e-08 +4.9943421636650945e-08 +4.771131340707996e-08 +4.213104283315248e-08 +3.487669108704675e-08 +3.180754227138664e-08 +3.0551981392252956e-08 +2.9296420513119273e-08 +2.552973787571822e-08 +1.9670453773094368e-08 +3.069148815660114e-08 +2.8180366398333776e-08 +2.9017406984422894e-08 +2.845937992703015e-08 +2.9156913748771087e-08 +2.9993954334860204e-08 +3.069148815660114e-08 +3.682978578792137e-08 +3.1668035507038446e-08 +4.422364429837528e-08 +4.673476605664265e-08 +4.82693404644727e-08 +4.882736752186545e-08 +4.520019164881259e-08 +4.603723223490171e-08 +4.520019164881259e-08 +4.157301577575972e-08 +3.6550772259225e-08 +3.180754227138664e-08 +2.7622339340941025e-08 +2.6366778461807345e-08 +2.4832204053977286e-08 +2.218157553136173e-08 +1.911242671570162e-08 +3.1389021978342073e-08 +2.8877900220074708e-08 +2.8877900220074708e-08 +2.8319873162681962e-08 +2.8598886691378335e-08 +2.8877900220074708e-08 +2.9156913748771087e-08 +3.027296786355658e-08 +3.390014373660944e-08 +3.892238725314418e-08 +4.2689069890545226e-08 +4.5618711941857144e-08 +4.6595259292294455e-08 +4.520019164881259e-08 +4.3386603712286164e-08 +4.199153606880429e-08 +4.087548195401879e-08 +4.2410056361848854e-08 +4.101498871836698e-08 +3.7387812845314116e-08 +3.5713731673135874e-08 +3.362113020791307e-08 +3.250507609312757e-08 +3.083099492094933e-08 +2.985444757051202e-08 +2.8180366398333776e-08 +2.9017406984422894e-08 +2.845937992703015e-08 +2.7901352869637404e-08 +2.7482832576592838e-08 +2.7761846105289214e-08 +2.7203819047896466e-08 +2.804085963398559e-08 +2.7622339340941025e-08 +2.8877900220074708e-08 +3.069148815660114e-08 +3.152852874269026e-08 +3.2644582857475756e-08 +3.278408962182394e-08 +3.3063103150520315e-08 +3.376063697226125e-08 +3.417915726530581e-08 +3.515570461574312e-08 +3.348162344356488e-08 +3.22260625644312e-08 +3.1389021978342073e-08 +3.083099492094933e-08 +2.943592727746746e-08 +2.8319873162681962e-08 +2.6227271697459155e-08 +2.6924805519200093e-08 +2.6645791990503717e-08 +2.6645791990503717e-08 +2.7901352869637404e-08 +2.9296420513119273e-08 +3.585323843748406e-08 +3.1668035507038446e-08 +4.464216459141985e-08 +4.771131340707996e-08 +4.910638105056182e-08 +4.9943421636650945e-08 +4.631624576359808e-08 +4.82693404644727e-08 +4.812983370012452e-08 +4.5897725470553524e-08 +4.003844136792967e-08 +3.22260625644312e-08 +2.9296420513119273e-08 +2.8180366398333776e-08 +2.6366778461807345e-08 +2.287910935310267e-08 +1.8414892893960685e-08 +2.985444757051202e-08 +2.7482832576592838e-08 +2.8180366398333776e-08 +2.7761846105289214e-08 +2.7343325812244652e-08 +2.7901352869637404e-08 +2.9714940806163832e-08 +3.627175873052862e-08 +3.1947049035734825e-08 +4.478167135576803e-08 +4.785082017142814e-08 +4.9245887814910014e-08 +5.0222435165347324e-08 +4.631624576359808e-08 +4.799032693577633e-08 +4.82693404644727e-08 +4.6595259292294455e-08 +4.115449548271517e-08 +3.3342116679216694e-08 +2.9714940806163832e-08 +2.9156913748771087e-08 +2.7622339340941025e-08 +2.4274176996584538e-08 +1.9391440244397992e-08 +3.152852874269026e-08 +2.9296420513119273e-08 +2.9714940806163832e-08 +2.8598886691378335e-08 +2.845937992703015e-08 +2.9017406984422894e-08 +3.013346109920839e-08 +3.6550772259225e-08 +3.2644582857475756e-08 +4.575821870620534e-08 +4.882736752186545e-08 +5.008292840099913e-08 +5.0919968987088255e-08 +4.7153286349687207e-08 +4.896687428621364e-08 +4.896687428621364e-08 +4.701377958533902e-08 +4.199153606880429e-08 +3.348162344356488e-08 +2.943592727746746e-08 +2.8319873162681962e-08 +2.706431228354828e-08 +2.3576643174843603e-08 +1.8693906422657058e-08 +3.013346109920839e-08 +2.7901352869637404e-08 +2.845937992703015e-08 +2.7622339340941025e-08 +2.8180366398333776e-08 +2.845937992703015e-08 +2.985444757051202e-08 +3.6411265494876805e-08 +3.1947049035734825e-08 +4.478167135576803e-08 +4.785082017142814e-08 +4.93853945792582e-08 +5.078046222274007e-08 +4.729279311403539e-08 +4.896687428621364e-08 +4.9524901343606386e-08 +4.729279311403539e-08 +4.1712522540107916e-08 +3.390014373660944e-08 +3.0551981392252956e-08 +2.943592727746746e-08 +2.804085963398559e-08 +2.5390231111370035e-08 +2.1344534945272613e-08 +3.4737184322698563e-08 +3.180754227138664e-08 +3.208655580008301e-08 +3.1389021978342073e-08 +3.180754227138664e-08 +3.292359638617213e-08 +3.376063697226125e-08 +4.031745489662604e-08 +3.417915726530581e-08 +4.673476605664265e-08 +4.910638105056182e-08 +5.0222435165347324e-08 +5.064095545839188e-08 +4.687427282099083e-08 +4.7153286349687207e-08 +4.631624576359808e-08 +4.227054959750066e-08 +3.724830608096593e-08 +3.180754227138664e-08 +2.7482832576592838e-08 +2.5948258168762783e-08 +2.455319052528091e-08 +2.1902562002665358e-08 +1.9391440244397992e-08 +3.2644582857475756e-08 +3.041247462790477e-08 +3.069148815660114e-08 +2.985444757051202e-08 +2.9575434041815645e-08 +2.9575434041815645e-08 +3.027296786355658e-08 +3.1389021978342073e-08 +3.54347181444395e-08 +4.157301577575972e-08 +4.533969841316077e-08 +4.840884722882089e-08 +4.9245887814910014e-08 +4.7571806642731765e-08 +4.5897725470553524e-08 +4.422364429837528e-08 +4.324709694793797e-08 +4.310759018358978e-08 +4.115449548271517e-08 +3.75273196096623e-08 +3.585323843748406e-08 +3.4039650500957626e-08 +3.3063103150520315e-08 +3.1668035507038446e-08 +3.0551981392252956e-08 +2.873839345572652e-08 +2.9156913748771087e-08 +2.8319873162681962e-08 +2.7761846105289214e-08 +2.7901352869637404e-08 +2.8319873162681962e-08 +2.804085963398559e-08 +2.873839345572652e-08 +2.845937992703015e-08 +2.9156913748771087e-08 +3.0970501685297515e-08 +3.22260625644312e-08 +3.278408962182394e-08 +3.3063103150520315e-08 +3.292359638617213e-08 +3.278408962182394e-08 +3.3342116679216694e-08 +3.459767755835038e-08 +3.390014373660944e-08 +3.3063103150520315e-08 +3.2365569328779384e-08 +3.1947049035734825e-08 +3.069148815660114e-08 +2.943592727746746e-08 +2.7343325812244652e-08 +2.804085963398559e-08 +2.7901352869637404e-08 +2.8598886691378335e-08 +2.9296420513119273e-08 +3.069148815660114e-08 +3.7387812845314116e-08 +3.250507609312757e-08 +4.575821870620534e-08 +4.896687428621364e-08 +5.036194192969551e-08 +5.119898251578463e-08 +4.771131340707996e-08 +4.9524901343606386e-08 +4.966440810795457e-08 +4.7432299878383586e-08 +4.115449548271517e-08 +3.208655580008301e-08 +2.845937992703015e-08 +2.706431228354828e-08 +2.5390231111370035e-08 +2.246058906005811e-08 +1.8972919951353434e-08 +3.1668035507038446e-08 +2.943592727746746e-08 +3.013346109920839e-08 +2.9296420513119273e-08 +2.9296420513119273e-08 +2.985444757051202e-08 +3.152852874269026e-08 +3.822485343140324e-08 +3.320260991486851e-08 +4.6455752527946275e-08 +4.93853945792582e-08 +5.078046222274007e-08 +5.175700957317738e-08 +4.82693404644727e-08 +4.9943421636650945e-08 +5.0222435165347324e-08 +4.868786075751727e-08 +4.29680834192416e-08 +3.4318664029654005e-08 +3.013346109920839e-08 +2.943592727746746e-08 +2.7901352869637404e-08 +2.4832204053977286e-08 +2.078650788787986e-08 +3.5016197851394936e-08 +3.2365569328779384e-08 +3.278408962182394e-08 +3.152852874269026e-08 +3.0970501685297515e-08 +3.1389021978342073e-08 +3.3063103150520315e-08 +4.003844136792967e-08 +3.417915726530581e-08 +4.840884722882089e-08 +5.0919968987088255e-08 +5.203602310187375e-08 +5.2873063687962876e-08 +4.910638105056182e-08 +5.0919968987088255e-08 +5.0501448694043697e-08 +4.840884722882089e-08 +4.29680834192416e-08 +3.376063697226125e-08 +2.9296420513119273e-08 +2.7901352869637404e-08 +2.650628522615553e-08 +2.3437136410495414e-08 +1.9809960537442554e-08 +3.22260625644312e-08 +3.041247462790477e-08 +3.083099492094933e-08 +3.0551981392252956e-08 +3.041247462790477e-08 +3.11100084496457e-08 +3.22260625644312e-08 +3.892238725314418e-08 +3.3342116679216694e-08 +4.701377958533902e-08 +5.008292840099913e-08 +5.105947575143644e-08 +5.217552986622194e-08 +4.882736752186545e-08 +5.0222435165347324e-08 +5.036194192969551e-08 +4.840884722882089e-08 +4.2689069890545226e-08 +3.4039650500957626e-08 +3.027296786355658e-08 +2.9017406984422894e-08 +2.7482832576592838e-08 +2.4971710818325472e-08 +2.1902562002665358e-08 +3.7387812845314116e-08 +3.54347181444395e-08 +3.6550772259225e-08 +3.557422490878769e-08 +3.54347181444395e-08 +3.613225196618043e-08 +3.710879931661774e-08 +4.3386603712286164e-08 +3.585323843748406e-08 +4.840884722882089e-08 +5.064095545839188e-08 +5.175700957317738e-08 +5.1896516337525566e-08 +4.799032693577633e-08 +4.840884722882089e-08 +4.729279311403539e-08 +4.3386603712286164e-08 +3.822485343140324e-08 +3.152852874269026e-08 +2.7203819047896466e-08 +2.5669244640066407e-08 +2.4274176996584538e-08 +2.2042068767013544e-08 +2.008897406613893e-08 +3.445817079400219e-08 +3.180754227138664e-08 +3.22260625644312e-08 +3.11100084496457e-08 +3.083099492094933e-08 +3.180754227138664e-08 +3.278408962182394e-08 +3.376063697226125e-08 +3.7806333138358674e-08 +4.3805124005330716e-08 +4.729279311403539e-08 +5.0222435165347324e-08 +5.0501448694043697e-08 +4.799032693577633e-08 +4.631624576359808e-08 +4.50606848844644e-08 +4.3805124005330716e-08 +4.324709694793797e-08 +4.157301577575972e-08 +3.822485343140324e-08 +3.6411265494876805e-08 +3.515570461574312e-08 +3.417915726530581e-08 +3.3063103150520315e-08 +3.1668035507038446e-08 +2.985444757051202e-08 +3.041247462790477e-08 +2.9575434041815645e-08 +2.9156913748771087e-08 +2.9575434041815645e-08 +2.9714940806163832e-08 +2.9714940806163832e-08 +3.041247462790477e-08 +3.0551981392252956e-08 +3.083099492094933e-08 +3.250507609312757e-08 +3.390014373660944e-08 +3.459767755835038e-08 +3.4737184322698563e-08 +3.417915726530581e-08 +3.390014373660944e-08 +3.5016197851394936e-08 +3.627175873052862e-08 +3.5992745201832246e-08 +3.5016197851394936e-08 +3.4318664029654005e-08 +3.376063697226125e-08 +3.2644582857475756e-08 +3.152852874269026e-08 +2.9575434041815645e-08 +3.0551981392252956e-08 +3.027296786355658e-08 +3.083099492094933e-08 +3.124951521399389e-08 +3.250507609312757e-08 +3.906189401749236e-08 +3.376063697226125e-08 +4.7571806642731765e-08 +4.9943421636650945e-08 +5.119898251578463e-08 +5.203602310187375e-08 +4.840884722882089e-08 +5.0222435165347324e-08 +5.0501448694043697e-08 +4.82693404644727e-08 +4.199153606880429e-08 +3.292359638617213e-08 +2.8598886691378335e-08 +2.7482832576592838e-08 +2.5808751404414597e-08 +2.2739602588754482e-08 +1.911242671570162e-08 +3.2644582857475756e-08 +3.027296786355658e-08 +3.0970501685297515e-08 +3.013346109920839e-08 +3.083099492094933e-08 +3.22260625644312e-08 +3.4737184322698563e-08 +4.199153606880429e-08 +3.5295211380091315e-08 +4.896687428621364e-08 +5.1896516337525566e-08 +5.343109074535562e-08 +5.48261583888375e-08 +5.147799604448101e-08 +5.315207721665925e-08 +5.2594050159266504e-08 +5.008292840099913e-08 +4.436315106272346e-08 +3.5295211380091315e-08 +3.027296786355658e-08 +2.9296420513119273e-08 +2.7761846105289214e-08 +2.4832204053977286e-08 +2.0926014652228048e-08 +3.54347181444395e-08 +3.250507609312757e-08 +3.3063103150520315e-08 +3.208655580008301e-08 +3.1668035507038446e-08 +3.2365569328779384e-08 +3.417915726530581e-08 +4.129400224706335e-08 +3.5016197851394936e-08 +4.966440810795457e-08 +5.2594050159266504e-08 +5.3989117802748366e-08 +5.4965665153185677e-08 +5.0501448694043697e-08 +5.203602310187375e-08 +5.175700957317738e-08 +4.93853945792582e-08 +4.394463076967891e-08 +3.5016197851394936e-08 +3.027296786355658e-08 +2.9017406984422894e-08 +2.7482832576592838e-08 +2.46926972896291e-08 +2.078650788787986e-08 +3.417915726530581e-08 +3.208655580008301e-08 +3.208655580008301e-08 +3.152852874269026e-08 +3.1668035507038446e-08 +3.208655580008301e-08 +3.320260991486851e-08 +4.017794813227786e-08 +3.4039650500957626e-08 +4.82693404644727e-08 +5.105947575143644e-08 +5.217552986622194e-08 +5.2873063687962876e-08 +4.980391487230276e-08 +5.119898251578463e-08 +5.1338489280132814e-08 +4.9245887814910014e-08 +4.3526110476634344e-08 +3.487669108704675e-08 +3.083099492094933e-08 +2.9017406984422894e-08 +2.7761846105289214e-08 +2.46926972896291e-08 +2.1205028180924427e-08 +3.627175873052862e-08 +3.459767755835038e-08 +3.54347181444395e-08 +3.417915726530581e-08 +3.390014373660944e-08 +3.4039650500957626e-08 +3.585323843748406e-08 +4.2410056361848854e-08 +3.4737184322698563e-08 +4.812983370012452e-08 +5.105947575143644e-08 +5.217552986622194e-08 +5.245454339491831e-08 +4.882736752186545e-08 +4.910638105056182e-08 +4.771131340707996e-08 +4.436315106272346e-08 +3.9340907546188736e-08 +3.250507609312757e-08 +2.8180366398333776e-08 +2.650628522615553e-08 +2.5111217582673662e-08 +2.3297629646147227e-08 +2.1344534945272613e-08 +3.6411265494876805e-08 +3.376063697226125e-08 +3.4039650500957626e-08 +3.2644582857475756e-08 +3.22260625644312e-08 +3.3063103150520315e-08 +3.362113020791307e-08 +3.459767755835038e-08 +3.7806333138358674e-08 +4.3526110476634344e-08 +4.6455752527946275e-08 +4.93853945792582e-08 +5.008292840099913e-08 +4.771131340707996e-08 +4.603723223490171e-08 +4.4502657827071654e-08 +4.310759018358978e-08 +4.29680834192416e-08 +4.1433509011411543e-08 +3.8782880488795985e-08 +3.724830608096593e-08 +3.6690279023573184e-08 +3.5713731673135874e-08 +3.445817079400219e-08 +3.362113020791307e-08 +3.152852874269026e-08 +3.180754227138664e-08 +3.0970501685297515e-08 +3.0970501685297515e-08 +3.1389021978342073e-08 +3.1389021978342073e-08 +3.152852874269026e-08 +3.1668035507038446e-08 +3.180754227138664e-08 +3.1947049035734825e-08 +3.376063697226125e-08 +3.515570461574312e-08 +3.5992745201832246e-08 +3.613225196618043e-08 +3.585323843748406e-08 +3.5713731673135874e-08 +3.6690279023573184e-08 +3.75273196096623e-08 +3.6411265494876805e-08 +3.557422490878769e-08 +3.4737184322698563e-08 +3.376063697226125e-08 +3.250507609312757e-08 +3.22260625644312e-08 +3.069148815660114e-08 +3.22260625644312e-08 +3.250507609312757e-08 +3.208655580008301e-08 +3.1947049035734825e-08 +3.320260991486851e-08 +3.9759427839233295e-08 +3.250507609312757e-08 +4.533969841316077e-08 +4.7571806642731765e-08 +4.910638105056182e-08 +4.9943421636650945e-08 +4.673476605664265e-08 +4.799032693577633e-08 +4.840884722882089e-08 +4.6595259292294455e-08 +4.115449548271517e-08 +3.2644582857475756e-08 +2.8319873162681962e-08 +2.7203819047896466e-08 +2.552973787571822e-08 +2.287910935310267e-08 +1.9809960537442554e-08 +3.362113020791307e-08 +3.180754227138664e-08 +3.278408962182394e-08 +3.208655580008301e-08 +3.22260625644312e-08 +3.348162344356488e-08 +3.5992745201832246e-08 +4.2549563126197034e-08 +3.445817079400219e-08 +4.771131340707996e-08 +5.105947575143644e-08 +5.273355692361469e-08 +5.3989117802748366e-08 +5.0919968987088255e-08 +5.203602310187375e-08 +5.105947575143644e-08 +4.812983370012452e-08 +4.310759018358978e-08 +3.417915726530581e-08 +2.9575434041815645e-08 +2.8319873162681962e-08 +2.706431228354828e-08 +2.455319052528091e-08 +2.106552141657624e-08 +3.5713731673135874e-08 +3.250507609312757e-08 +3.320260991486851e-08 +3.22260625644312e-08 +3.22260625644312e-08 +3.3063103150520315e-08 +3.417915726530581e-08 +4.087548195401879e-08 +3.445817079400219e-08 +4.840884722882089e-08 +5.161750280882919e-08 +5.315207721665925e-08 +5.3570597509703814e-08 +4.966440810795457e-08 +5.105947575143644e-08 +5.078046222274007e-08 +4.840884722882089e-08 +4.310759018358978e-08 +3.417915726530581e-08 +2.9575434041815645e-08 +2.845937992703015e-08 +2.7203819047896466e-08 +2.4274176996584538e-08 +2.050749435918349e-08 +3.417915726530581e-08 +3.152852874269026e-08 +3.152852874269026e-08 +3.041247462790477e-08 +3.11100084496457e-08 +3.1389021978342073e-08 +3.292359638617213e-08 +3.9759427839233295e-08 +3.3342116679216694e-08 +4.687427282099083e-08 +4.93853945792582e-08 +5.078046222274007e-08 +5.1338489280132814e-08 +4.82693404644727e-08 +4.9524901343606386e-08 +4.980391487230276e-08 +4.7432299878383586e-08 +4.1852029304456096e-08 +3.362113020791307e-08 +2.9714940806163832e-08 +2.8180366398333776e-08 +2.706431228354828e-08 +2.4413683760932724e-08 +2.106552141657624e-08 +3.5713731673135874e-08 +3.292359638617213e-08 +3.3063103150520315e-08 +3.180754227138664e-08 +3.1947049035734825e-08 +3.1947049035734825e-08 +3.376063697226125e-08 +3.920140078184055e-08 +3.0970501685297515e-08 +4.2689069890545226e-08 +4.575821870620534e-08 +4.6595259292294455e-08 +4.701377958533902e-08 +4.3805124005330716e-08 +4.310759018358978e-08 +4.1712522540107916e-08 +3.86433737244478e-08 +3.487669108704675e-08 +2.9993954334860204e-08 +2.650628522615553e-08 +2.4971710818325472e-08 +2.385565670353998e-08 +2.218157553136173e-08 +2.0647001123531675e-08 +3.54347181444395e-08 +3.376063697226125e-08 +3.390014373660944e-08 +3.278408962182394e-08 +3.292359638617213e-08 +3.3063103150520315e-08 +3.3342116679216694e-08 +3.390014373660944e-08 +3.6411265494876805e-08 +4.1852029304456096e-08 +4.4502657827071654e-08 +4.729279311403539e-08 +4.868786075751727e-08 +4.673476605664265e-08 +4.533969841316077e-08 +4.394463076967891e-08 +4.2549563126197034e-08 +4.2410056361848854e-08 +4.115449548271517e-08 +3.9340907546188736e-08 +3.822485343140324e-08 +3.7666826374010495e-08 +3.682978578792137e-08 +3.54347181444395e-08 +3.5016197851394936e-08 +3.445817079400219e-08 +3.459767755835038e-08 +3.362113020791307e-08 +3.390014373660944e-08 +3.4318664029654005e-08 +3.4318664029654005e-08 +3.4318664029654005e-08 +3.4039650500957626e-08 +3.417915726530581e-08 +3.390014373660944e-08 +3.54347181444395e-08 +3.696929255226956e-08 +3.8085346667055053e-08 +3.7666826374010495e-08 +3.75273196096623e-08 +3.75273196096623e-08 +3.822485343140324e-08 +3.948041431053692e-08 +3.794583990270687e-08 +3.7387812845314116e-08 +3.682978578792137e-08 +3.5713731673135874e-08 +3.417915726530581e-08 +3.4039650500957626e-08 +3.1389021978342073e-08 +3.278408962182394e-08 +3.278408962182394e-08 +3.278408962182394e-08 +3.2365569328779384e-08 +3.362113020791307e-08 +3.906189401749236e-08 +2.9017406984422894e-08 +3.8782880488795985e-08 +4.1433509011411543e-08 +4.2549563126197034e-08 +4.2828576654893406e-08 +4.0735975189670606e-08 +4.1433509011411543e-08 +4.157301577575972e-08 +4.031745489662604e-08 +3.613225196618043e-08 +2.9575434041815645e-08 +2.5948258168762783e-08 +2.4413683760932724e-08 +2.315812288179904e-08 +2.14840417096208e-08 +1.9670453773094368e-08 +3.4039650500957626e-08 +3.124951521399389e-08 +3.22260625644312e-08 +3.11100084496457e-08 +3.11100084496457e-08 +3.152852874269026e-08 +3.292359638617213e-08 +3.75273196096623e-08 +2.9156913748771087e-08 +3.961992107488511e-08 +4.310759018358978e-08 +4.492117812011622e-08 +4.520019164881259e-08 +4.29680834192416e-08 +4.3526110476634344e-08 +4.324709694793797e-08 +4.115449548271517e-08 +3.710879931661774e-08 +3.041247462790477e-08 +2.6645791990503717e-08 +2.5390231111370035e-08 +2.4413683760932724e-08 +2.287910935310267e-08 +2.078650788787986e-08 +3.557422490878769e-08 +3.124951521399389e-08 +3.22260625644312e-08 +3.11100084496457e-08 +3.11100084496457e-08 +3.152852874269026e-08 +3.292359638617213e-08 +3.75273196096623e-08 +2.9156913748771087e-08 +3.961992107488511e-08 +4.310759018358978e-08 +4.492117812011622e-08 +4.520019164881259e-08 +4.29680834192416e-08 +4.3526110476634344e-08 +4.324709694793797e-08 +4.115449548271517e-08 +3.710879931661774e-08 +3.041247462790477e-08 +2.6645791990503717e-08 +2.5390231111370035e-08 +2.4413683760932724e-08 +2.287910935310267e-08 +2.078650788787986e-08 +3.557422490878769e-08 +3.11100084496457e-08 +3.124951521399389e-08 +3.124951521399389e-08 +3.1389021978342073e-08 +3.0551981392252956e-08 +3.1389021978342073e-08 +3.320260991486851e-08 +3.920140078184055e-08 +4.840884722882089e-08 +5.203602310187375e-08 +5.3570597509703814e-08 +5.4965665153185677e-08 +5.3710104274051994e-08 +5.3291583981007435e-08 +5.4268131331444745e-08 +5.315207721665925e-08 +5.064095545839188e-08 +4.575821870620534e-08 +4.087548195401879e-08 +3.906189401749236e-08 +3.7387812845314116e-08 +3.5713731673135874e-08 +3.348162344356488e-08 +3.22260625644312e-08 +3.1389021978342073e-08 +3.278408962182394e-08 +3.1947049035734825e-08 +3.1389021978342073e-08 +3.11100084496457e-08 +3.152852874269026e-08 +3.4737184322698563e-08 +2.4832204053977286e-08 +3.2365569328779384e-08 +3.487669108704675e-08 +3.5713731673135874e-08 +3.585323843748406e-08 +3.390014373660944e-08 +3.3063103150520315e-08 +3.22260625644312e-08 +2.9993954334860204e-08 +2.804085963398559e-08 +2.5390231111370035e-08 +2.2739602588754482e-08 +2.1763055238317172e-08 +2.0926014652228048e-08 +1.9670453773094368e-08 +1.8414892893960685e-08 +3.2365569328779384e-08 +3.11100084496457e-08 +3.1389021978342073e-08 +3.124951521399389e-08 +3.152852874269026e-08 +3.2365569328779384e-08 +3.292359638617213e-08 +3.4039650500957626e-08 +3.6550772259225e-08 +3.9759427839233295e-08 +4.129400224706335e-08 +4.29680834192416e-08 +4.3386603712286164e-08 +4.1852029304456096e-08 +4.115449548271517e-08 +4.0735975189670606e-08 +3.989893460358149e-08 +3.961992107488511e-08 +3.906189401749236e-08 +3.6690279023573184e-08 +3.5992745201832246e-08 +3.487669108704675e-08 +3.348162344356488e-08 +3.2365569328779384e-08 +3.1947049035734825e-08 +2.9993954334860204e-08 +3.041247462790477e-08 +2.9714940806163832e-08 +2.943592727746746e-08 +2.8877900220074708e-08 +2.9296420513119273e-08 +2.9714940806163832e-08 +3.041247462790477e-08 +3.069148815660114e-08 +3.027296786355658e-08 +3.1668035507038446e-08 +3.250507609312757e-08 +3.3342116679216694e-08 +3.3063103150520315e-08 +3.376063697226125e-08 +3.3063103150520315e-08 +3.417915726530581e-08 +3.5295211380091315e-08 +3.390014373660944e-08 +3.362113020791307e-08 +3.2365569328779384e-08 +3.1389021978342073e-08 +3.0551981392252956e-08 +2.9714940806163832e-08 +2.7901352869637404e-08 +2.8877900220074708e-08 +2.8319873162681962e-08 +2.845937992703015e-08 +2.845937992703015e-08 +2.9993954334860204e-08 +3.292359638617213e-08 +2.2739602588754482e-08 +2.9156913748771087e-08 +3.1389021978342073e-08 +3.208655580008301e-08 +3.180754227138664e-08 +3.0970501685297515e-08 +3.11100084496457e-08 +3.0970501685297515e-08 +2.985444757051202e-08 +2.7622339340941025e-08 +2.3995163467888165e-08 +2.0926014652228048e-08 +1.9949467301790744e-08 +1.9391440244397992e-08 +1.8414892893960685e-08 +1.7019825250478813e-08 +2.943592727746746e-08 +2.873839345572652e-08 \ No newline at end of file diff --git a/examples/curve_examples/electric_vehicle_profile_5_curve.csv b/examples/curve_examples/electric_vehicle_profile_5_curve.csv new file mode 100644 index 0000000..7e359fa --- /dev/null +++ b/examples/curve_examples/electric_vehicle_profile_5_curve.csv @@ -0,0 +1,8760 @@ +4.058029003214125e-08 +4.199957496152364e-08 +3.8220513109021064e-08 +2.9482090031937756e-08 +2.0295527943857224e-08 +1.2272828807132413e-08 +7.909041287429164e-09 +2.7023941130793784e-08 +5.623902150809556e-08 +6.116353752074473e-08 +4.788438885488115e-08 +4.177447817972987e-08 +3.70509795925161e-08 +4.020299199445773e-08 +3.430708351711257e-08 +3.320773351709241e-08 +3.342009207282629e-08 +2.01240138936186e-08 +3.3284738148177025e-08 +3.7428935087028526e-08 +3.84359945846922e-08 +3.5739353218865674e-08 +3.6394180220447543e-08 +3.901299513415333e-08 +4.3137221821827065e-08 +4.205693806984494e-08 +3.7772045369609385e-08 +3.055111483572502e-08 +2.059664317149226e-08 +1.2367913501011706e-08 +8.901061460131813e-09 +2.525332770846932e-08 +5.172262182198448e-08 +5.70589523558343e-08 +4.648310180618983e-08 +4.8967466798386086e-08 +4.7003478886262174e-08 +4.489665847806027e-08 +4.6052878493780057e-08 +4.4395429828129577e-08 +3.9255103611394826e-08 +2.356234874454507e-08 +3.4071138697641997e-08 +3.6228501099565384e-08 +3.5698755259681256e-08 +3.355322708067803e-08 +3.125812747310062e-08 +3.29047281010743e-08 +3.9551534459123965e-08 +4.324603092700959e-08 +4.066715651565933e-08 +3.5057981397817076e-08 +2.6684282496564638e-08 +1.8025411695777923e-08 +1.1288615934272923e-08 +2.2971377237469868e-08 +4.531348610758126e-08 +4.75251708799923e-08 +3.7950462716551433e-08 +4.585966836818782e-08 +5.327356248135359e-08 +5.363993029925671e-08 +4.869256766180334e-08 +4.633155800712897e-08 +3.908005573070087e-08 +2.822133438042327e-08 +2.6735892857633082e-08 +2.5060281947084308e-08 +2.5567509890578696e-08 +2.4324341209237218e-08 +2.3789417896825527e-08 +2.668937778698859e-08 +3.114709945112056e-08 +3.1219912794920955e-08 +3.0739394035100524e-08 +2.6577856672386862e-08 +2.163542496115024e-08 +1.518355455286867e-08 +1.0374175667380174e-08 +2.780919113080818e-08 +5.895653712823958e-08 +6.21563795144835e-08 +4.7528375982033175e-08 +3.9731348901827415e-08 +4.7043994663342966e-08 +4.2682426060437265e-08 +4.05751947417173e-08 +3.943450714358022e-08 +3.751366483585268e-08 +2.3015591209213225e-08 +2.769890274776063e-08 +2.9947651648900766e-08 +3.1863152119893504e-08 +3.061965471013758e-08 +2.9692065306666882e-08 +2.995233602880666e-08 +3.151248108378032e-08 +2.993474905863365e-08 +2.7434522920440244e-08 +2.1560146154241483e-08 +1.4356145133701225e-08 +8.812386970334268e-09 +6.837222292119088e-09 +2.6956962716349854e-08 +5.889276381583652e-08 +6.76377614612088e-08 +5.616719434953852e-08 +4.510145628026183e-08 +4.4312014992963216e-08 +3.50095761387895e-08 +3.052974748878585e-08 +3.835192229269694e-08 +3.675915094258924e-08 +2.383404277908694e-08 +3.586032527538281e-08 +4.2238396154620635e-08 +4.198272763028314e-08 +3.921902566790907e-08 +3.7451535165521875e-08 +3.981164081705652e-08 +3.619875117805777e-08 +3.5683551570513e-08 +3.338015157047077e-08 +2.60633967037746e-08 +1.717556656232435e-08 +1.0051693092805972e-08 +6.039316248148413e-09 +7.532811617092595e-09 +2.2363969309672232e-08 +3.0926276138714626e-08 +2.8049327237562983e-08 +1.931599945090363e-08 +2.227126789679769e-08 +2.6531095055431525e-08 +2.6586814521680586e-08 +2.9027294270547942e-08 +3.035749379961472e-08 +2.0306869074155705e-08 +2.9707515542145974e-08 +3.5981050785589104e-08 +3.72628450556283e-08 +3.3846699372677125e-08 +3.481521546374669e-08 +3.7008902355466666e-08 +4.163164568365189e-08 +4.1501387049426586e-08 +3.647866342296087e-08 +2.823842825797461e-08 +2.0044132888907563e-08 +1.2029980690958416e-08 +5.6040798274182976e-09 +8.240810439711543e-09 +2.3401354003568804e-08 +2.9870729199919766e-08 +2.69640303772605e-08 +2.38378231558531e-08 +2.3706003061659163e-08 +2.568108555777073e-08 +2.4868140188839024e-08 +3.137079913715292e-08 +3.2018969388342203e-08 +1.7453917347258807e-08 +3.014990180589035e-08 +3.440274348571715e-08 +3.507121271649864e-08 +3.248535282634133e-08 +3.372835714347558e-08 +3.622652872907869e-08 +4.058029003214125e-08 +4.199957496152364e-08 +3.8220513109021064e-08 +2.9482090031937756e-08 +2.0295527943857224e-08 +1.2272828807132413e-08 +7.909041287429164e-09 +2.7023941130793784e-08 +5.623902150809556e-08 +6.116353752074473e-08 +4.788438885488115e-08 +4.177447817972987e-08 +3.70509795925161e-08 +4.020299199445773e-08 +3.430708351711257e-08 +3.320773351709241e-08 +3.342009207282629e-08 +2.01240138936186e-08 +3.3284738148177025e-08 +3.7428935087028526e-08 +3.84359945846922e-08 +3.5739353218865674e-08 +3.6394180220447543e-08 +3.901299513415333e-08 +4.3137221821827065e-08 +4.205693806984494e-08 +3.7772045369609385e-08 +3.055111483572502e-08 +2.059664317149226e-08 +1.2367913501011706e-08 +8.901061460131813e-09 +2.525332770846932e-08 +5.172262182198448e-08 +5.70589523558343e-08 +4.648310180618983e-08 +4.8967466798386086e-08 +4.7003478886262174e-08 +4.489665847806027e-08 +4.6052878493780057e-08 +4.4395429828129577e-08 +3.9255103611394826e-08 +2.356234874454507e-08 +3.4071138697641997e-08 +3.6228501099565384e-08 +3.5698755259681256e-08 +3.355322708067803e-08 +3.125812747310062e-08 +3.29047281010743e-08 +3.9551534459123965e-08 +4.324603092700959e-08 +4.066715651565933e-08 +3.5057981397817076e-08 +2.6684282496564638e-08 +1.8025411695777923e-08 +1.1288615934272923e-08 +2.2971377237469868e-08 +4.531348610758126e-08 +4.75251708799923e-08 +3.7950462716551433e-08 +4.585966836818782e-08 +5.327356248135359e-08 +5.363993029925671e-08 +4.869256766180334e-08 +4.633155800712897e-08 +3.908005573070087e-08 +2.822133438042327e-08 +2.6735892857633082e-08 +2.5060281947084308e-08 +2.5567509890578696e-08 +2.4324341209237218e-08 +2.3789417896825527e-08 +2.668937778698859e-08 +3.114709945112056e-08 +3.1219912794920955e-08 +3.0739394035100524e-08 +2.6577856672386862e-08 +2.163542496115024e-08 +1.518355455286867e-08 +1.0374175667380174e-08 +2.780919113080818e-08 +5.895653712823958e-08 +6.21563795144835e-08 +4.7528375982033175e-08 +3.9731348901827415e-08 +4.7043994663342966e-08 +4.2682426060437265e-08 +4.05751947417173e-08 +3.943450714358022e-08 +3.751366483585268e-08 +2.3015591209213225e-08 +2.769890274776063e-08 +2.9947651648900766e-08 +3.1863152119893504e-08 +3.061965471013758e-08 +2.9692065306666882e-08 +2.995233602880666e-08 +3.151248108378032e-08 +2.993474905863365e-08 +2.7434522920440244e-08 +2.1560146154241483e-08 +1.4356145133701225e-08 +8.812386970334268e-09 +6.837222292119088e-09 +2.6956962716349854e-08 +5.889276381583652e-08 +6.76377614612088e-08 +5.616719434953852e-08 +4.510145628026183e-08 +4.4312014992963216e-08 +3.50095761387895e-08 +3.052974748878585e-08 +3.835192229269694e-08 +3.675915094258924e-08 +2.383404277908694e-08 +3.586032527538281e-08 +4.2238396154620635e-08 +4.198272763028314e-08 +3.921902566790907e-08 +3.7451535165521875e-08 +3.981164081705652e-08 +3.619875117805777e-08 +3.5683551570513e-08 +3.338015157047077e-08 +2.60633967037746e-08 +1.717556656232435e-08 +1.0051693092805972e-08 +6.039316248148413e-09 +7.532811617092595e-09 +2.2363969309672232e-08 +3.0926276138714626e-08 +2.8049327237562983e-08 +1.931599945090363e-08 +2.227126789679769e-08 +2.6531095055431525e-08 +2.6586814521680586e-08 +2.9027294270547942e-08 +3.035749379961472e-08 +2.0306869074155705e-08 +2.9707515542145974e-08 +3.5981050785589104e-08 +3.72628450556283e-08 +3.3846699372677125e-08 +3.481521546374669e-08 +3.7008902355466666e-08 +4.163164568365189e-08 +4.1501387049426586e-08 +3.647866342296087e-08 +2.823842825797461e-08 +2.0044132888907563e-08 +1.2029980690958416e-08 +5.6040798274182976e-09 +8.240810439711543e-09 +2.3401354003568804e-08 +2.9870729199919766e-08 +2.69640303772605e-08 +2.38378231558531e-08 +2.3706003061659163e-08 +2.568108555777073e-08 +2.4868140188839024e-08 +3.137079913715292e-08 +3.2018969388342203e-08 +1.7453917347258807e-08 +3.014990180589035e-08 +3.440274348571715e-08 +3.507121271649864e-08 +3.248535282634133e-08 +3.372835714347558e-08 +3.622652872907869e-08 +4.058029003214125e-08 +4.199957496152364e-08 +3.8220513109021064e-08 +2.9482090031937756e-08 +2.0295527943857224e-08 +1.2272828807132413e-08 +7.909041287429164e-09 +2.7023941130793784e-08 +5.623902150809556e-08 +6.116353752074473e-08 +4.788438885488115e-08 +4.177447817972987e-08 +3.70509795925161e-08 +4.020299199445773e-08 +3.430708351711257e-08 +3.320773351709241e-08 +3.342009207282629e-08 +2.01240138936186e-08 +3.3284738148177025e-08 +3.7428935087028526e-08 +3.84359945846922e-08 +3.5739353218865674e-08 +3.6394180220447543e-08 +3.901299513415333e-08 +4.3137221821827065e-08 +4.205693806984494e-08 +3.7772045369609385e-08 +3.055111483572502e-08 +2.059664317149226e-08 +1.2367913501011706e-08 +8.901061460131813e-09 +2.525332770846932e-08 +5.172262182198448e-08 +5.70589523558343e-08 +4.648310180618983e-08 +4.8967466798386086e-08 +4.7003478886262174e-08 +4.489665847806027e-08 +4.6052878493780057e-08 +4.4395429828129577e-08 +3.9255103611394826e-08 +2.356234874454507e-08 +3.4071138697641997e-08 +3.6228501099565384e-08 +3.5698755259681256e-08 +3.355322708067803e-08 +3.125812747310062e-08 +3.29047281010743e-08 +3.9551534459123965e-08 +4.324603092700959e-08 +4.066715651565933e-08 +3.5057981397817076e-08 +2.6684282496564638e-08 +1.8025411695777923e-08 +1.1288615934272923e-08 +2.2971377237469868e-08 +4.531348610758126e-08 +4.75251708799923e-08 +3.7950462716551433e-08 +4.585966836818782e-08 +5.327356248135359e-08 +5.363993029925671e-08 +4.869256766180334e-08 +4.633155800712897e-08 +3.908005573070087e-08 +2.822133438042327e-08 +2.6735892857633082e-08 +2.5060281947084308e-08 +2.5567509890578696e-08 +2.4324341209237218e-08 +2.3789417896825527e-08 +2.668937778698859e-08 +3.114709945112056e-08 +3.1219912794920955e-08 +3.0739394035100524e-08 +2.6577856672386862e-08 +2.163542496115024e-08 +1.518355455286867e-08 +1.0374175667380174e-08 +2.780919113080818e-08 +5.895653712823958e-08 +6.21563795144835e-08 +4.7528375982033175e-08 +3.9731348901827415e-08 +4.7043994663342966e-08 +4.2682426060437265e-08 +4.05751947417173e-08 +3.943450714358022e-08 +3.751366483585268e-08 +2.3015591209213225e-08 +2.769890274776063e-08 +2.9947651648900766e-08 +3.1863152119893504e-08 +3.061965471013758e-08 +2.9692065306666882e-08 +2.995233602880666e-08 +3.151248108378032e-08 +2.993474905863365e-08 +2.7434522920440244e-08 +2.1560146154241483e-08 +1.4356145133701225e-08 +8.812386970334268e-09 +6.837222292119088e-09 +2.6956962716349854e-08 +5.889276381583652e-08 +6.76377614612088e-08 +5.616719434953852e-08 +4.510145628026183e-08 +4.4312014992963216e-08 +3.50095761387895e-08 +3.052974748878585e-08 +3.835192229269694e-08 +3.675915094258924e-08 +2.383404277908694e-08 +3.586032527538281e-08 +4.2238396154620635e-08 +4.198272763028314e-08 +3.921902566790907e-08 +3.7451535165521875e-08 +3.981164081705652e-08 +3.619875117805777e-08 +3.5683551570513e-08 +3.338015157047077e-08 +2.60633967037746e-08 +1.717556656232435e-08 +1.0051693092805972e-08 +6.039316248148413e-09 +7.532811617092595e-09 +2.2363969309672232e-08 +3.0926276138714626e-08 +2.8049327237562983e-08 +1.931599945090363e-08 +2.227126789679769e-08 +2.6531095055431525e-08 +2.6586814521680586e-08 +2.9027294270547942e-08 +3.035749379961472e-08 +2.0306869074155705e-08 +2.9707515542145974e-08 +3.5981050785589104e-08 +3.72628450556283e-08 +3.3846699372677125e-08 +3.481521546374669e-08 +3.7008902355466666e-08 +4.163164568365189e-08 +4.1501387049426586e-08 +3.647866342296087e-08 +2.823842825797461e-08 +2.0044132888907563e-08 +1.2029980690958416e-08 +5.6040798274182976e-09 +8.240810439711543e-09 +2.3401354003568804e-08 +2.9870729199919766e-08 +2.69640303772605e-08 +2.38378231558531e-08 +2.3706003061659163e-08 +2.568108555777073e-08 +2.4868140188839024e-08 +3.137079913715292e-08 +3.2018969388342203e-08 +1.7453917347258807e-08 +3.014990180589035e-08 +3.440274348571715e-08 +3.507121271649864e-08 +3.248535282634133e-08 +3.372835714347558e-08 +3.622652872907869e-08 +4.058029003214125e-08 +4.199957496152364e-08 +3.8220513109021064e-08 +2.9482090031937756e-08 +2.0295527943857224e-08 +1.2272828807132413e-08 +7.909041287429164e-09 +2.7023941130793784e-08 +5.623902150809556e-08 +6.116353752074473e-08 +4.788438885488115e-08 +4.177447817972987e-08 +3.70509795925161e-08 +4.020299199445773e-08 +3.430708351711257e-08 +3.320773351709241e-08 +3.342009207282629e-08 +2.01240138936186e-08 +3.3284738148177025e-08 +3.7428935087028526e-08 +3.84359945846922e-08 +3.5739353218865674e-08 +3.6394180220447543e-08 +3.901299513415333e-08 +4.3137221821827065e-08 +4.205693806984494e-08 +3.7772045369609385e-08 +3.055111483572502e-08 +2.059664317149226e-08 +1.2367913501011706e-08 +8.901061460131813e-09 +2.525332770846932e-08 +5.172262182198448e-08 +5.70589523558343e-08 +4.648310180618983e-08 +4.8967466798386086e-08 +4.7003478886262174e-08 +4.489665847806027e-08 +4.6052878493780057e-08 +4.4395429828129577e-08 +3.9255103611394826e-08 +2.356234874454507e-08 +3.4071138697641997e-08 +3.6228501099565384e-08 +3.5698755259681256e-08 +3.355322708067803e-08 +3.125812747310062e-08 +3.29047281010743e-08 +3.9551534459123965e-08 +4.324603092700959e-08 +4.066715651565933e-08 +3.5057981397817076e-08 +2.6684282496564638e-08 +1.8025411695777923e-08 +1.1288615934272923e-08 +2.2971377237469868e-08 +4.531348610758126e-08 +4.75251708799923e-08 +3.7950462716551433e-08 +4.585966836818782e-08 +5.327356248135359e-08 +5.363993029925671e-08 +4.869256766180334e-08 +4.633155800712897e-08 +3.908005573070087e-08 +2.822133438042327e-08 +2.6735892857633082e-08 +2.5060281947084308e-08 +2.5567509890578696e-08 +2.4324341209237218e-08 +2.3789417896825527e-08 +2.668937778698859e-08 +3.114709945112056e-08 +3.1219912794920955e-08 +3.0739394035100524e-08 +2.6577856672386862e-08 +2.163542496115024e-08 +1.518355455286867e-08 +1.0374175667380174e-08 +2.780919113080818e-08 +5.895653712823958e-08 +6.21563795144835e-08 +4.7528375982033175e-08 +3.9731348901827415e-08 +4.7043994663342966e-08 +4.2682426060437265e-08 +4.05751947417173e-08 +3.943450714358022e-08 +3.751366483585268e-08 +2.3015591209213225e-08 +2.769890274776063e-08 +2.9947651648900766e-08 +3.1863152119893504e-08 +3.061965471013758e-08 +2.9692065306666882e-08 +2.995233602880666e-08 +3.151248108378032e-08 +2.993474905863365e-08 +2.7434522920440244e-08 +2.1560146154241483e-08 +1.4356145133701225e-08 +8.812386970334268e-09 +6.837222292119088e-09 +2.6956962716349854e-08 +5.889276381583652e-08 +6.76377614612088e-08 +5.616719434953852e-08 +4.510145628026183e-08 +4.4312014992963216e-08 +3.50095761387895e-08 +3.052974748878585e-08 +3.835192229269694e-08 +3.675915094258924e-08 +2.383404277908694e-08 +3.586032527538281e-08 +4.2238396154620635e-08 +4.198272763028314e-08 +3.921902566790907e-08 +3.7451535165521875e-08 +3.981164081705652e-08 +3.619875117805777e-08 +3.5683551570513e-08 +3.338015157047077e-08 +2.60633967037746e-08 +1.717556656232435e-08 +1.0051693092805972e-08 +6.039316248148413e-09 +7.532811617092595e-09 +2.2363969309672232e-08 +3.0926276138714626e-08 +2.8049327237562983e-08 +1.931599945090363e-08 +2.227126789679769e-08 +2.6531095055431525e-08 +2.6586814521680586e-08 +2.9027294270547942e-08 +3.035749379961472e-08 +2.0306869074155705e-08 +2.9707515542145974e-08 +3.5981050785589104e-08 +3.72628450556283e-08 +3.3846699372677125e-08 +3.481521546374669e-08 +3.7008902355466666e-08 +4.163164568365189e-08 +4.1501387049426586e-08 +3.647866342296087e-08 +2.823842825797461e-08 +2.0044132888907563e-08 +1.2029980690958416e-08 +5.6040798274182976e-09 +8.240810439711543e-09 +2.3401354003568804e-08 +2.9870729199919766e-08 +2.69640303772605e-08 +2.38378231558531e-08 +2.3706003061659163e-08 +2.568108555777073e-08 +2.4868140188839024e-08 +3.137079913715292e-08 +3.2018969388342203e-08 +1.7453917347258807e-08 +3.014990180589035e-08 +3.440274348571715e-08 +3.507121271649864e-08 +3.248535282634133e-08 +3.372835714347558e-08 +3.622652872907869e-08 +4.058029003214125e-08 +4.199957496152364e-08 +3.8220513109021064e-08 +2.9482090031937756e-08 +2.0295527943857224e-08 +1.2272828807132413e-08 +7.909041287429164e-09 +2.7023941130793784e-08 +5.623902150809556e-08 +6.116353752074473e-08 +4.788438885488115e-08 +4.177447817972987e-08 +3.70509795925161e-08 +4.020299199445773e-08 +3.430708351711257e-08 +3.320773351709241e-08 +3.342009207282629e-08 +2.01240138936186e-08 +3.3284738148177025e-08 +3.7428935087028526e-08 +3.84359945846922e-08 +3.5739353218865674e-08 +3.6394180220447543e-08 +3.901299513415333e-08 +4.3137221821827065e-08 +4.205693806984494e-08 +3.7772045369609385e-08 +3.055111483572502e-08 +2.059664317149226e-08 +1.2367913501011706e-08 +8.901061460131813e-09 +2.525332770846932e-08 +5.172262182198448e-08 +5.70589523558343e-08 +4.648310180618983e-08 +4.8967466798386086e-08 +4.7003478886262174e-08 +4.489665847806027e-08 +4.6052878493780057e-08 +4.4395429828129577e-08 +3.9255103611394826e-08 +2.356234874454507e-08 +3.4071138697641997e-08 +3.6228501099565384e-08 +3.5698755259681256e-08 +3.355322708067803e-08 +3.125812747310062e-08 +3.29047281010743e-08 +3.9551534459123965e-08 +4.324603092700959e-08 +4.066715651565933e-08 +3.5057981397817076e-08 +2.6684282496564638e-08 +1.8025411695777923e-08 +1.1288615934272923e-08 +2.2971377237469868e-08 +4.531348610758126e-08 +4.75251708799923e-08 +3.7950462716551433e-08 +4.585966836818782e-08 +5.327356248135359e-08 +5.363993029925671e-08 +4.869256766180334e-08 +4.633155800712897e-08 +3.908005573070087e-08 +2.822133438042327e-08 +2.6735892857633082e-08 +2.5060281947084308e-08 +2.5567509890578696e-08 +2.4324341209237218e-08 +2.3789417896825527e-08 +2.668937778698859e-08 +3.179732425490015e-08 +3.244039921566547e-08 +2.9594926060197282e-08 +2.5057405573457883e-08 +1.835561938809167e-08 +1.1413861460177887e-08 +1.0439510439751859e-08 +2.837501491417806e-08 +5.8732262167481936e-08 +6.109614819578273e-08 +5.122451609199106e-08 +4.024893179037693e-08 +4.422654560520654e-08 +4.245330235556649e-08 +4.453883759893283e-08 +3.766570172753522e-08 +3.298888257517317e-08 +1.915212833630094e-08 +2.8105621978537322e-08 +3.0956601334947525e-08 +3.373871208853072e-08 +3.3351387834206506e-08 +3.291598704926917e-08 +3.431415117802322e-08 +3.673885196299703e-08 +3.5738202669415105e-08 +3.249381758301339e-08 +2.4307986970618393e-08 +1.6429681789940187e-08 +9.08819011005675e-09 +5.998389560549547e-09 +2.82694109110364e-08 +6.439600620212268e-08 +7.025090580976536e-08 +5.041288563671715e-08 +4.1202655102796297e-08 +3.8288066798190274e-08 +4.2693931554942966e-08 +3.8359976138850934e-08 +4.215629623311207e-08 +3.579334686093888e-08 +2.32319766880241e-08 +3.4677560440196286e-08 +4.267313948272908e-08 +4.4177071978832014e-08 +4.041452872915548e-08 +3.828699843084332e-08 +4.076791177468786e-08 +4.5038258242584054e-08 +4.545237386268585e-08 +4.0976654317862804e-08 +3.224842182162741e-08 +2.286182849335483e-08 +1.3757366326782865e-08 +8.07685714300524e-09 +1.1919117033185581e-08 +2.7020489482442074e-08 +4.084623131943027e-08 +3.135115761438961e-08 +2.8929004474627774e-08 +2.7424743250110393e-08 +2.8382164757192317e-08 +2.9136514286248533e-08 +2.658763634271671e-08 +3.088329489852546e-08 +1.9860620251541557e-08 +3.22031394825371e-08 +3.976126318754225e-08 +3.880080094262668e-08 +3.639196130365001e-08 +3.83658110682074e-08 +4.166821671975931e-08 +4.626449741058142e-08 +4.672340227715185e-08 +4.292026106829091e-08 +3.3708140345986984e-08 +2.2013462637766273e-08 +1.2531702433510784e-08 +6.406670251294867e-09 +1.111948516503905e-08 +2.787510117790515e-08 +4.0639132418327576e-08 +3.404862080125225e-08 +2.7822668995800577e-08 +2.524954733170316e-08 +2.5566934615853412e-08 +2.6131361303461875e-08 +3.2636732261194974e-08 +3.6672695369589227e-08 +1.9600431711505388e-08 +3.141402692365293e-08 +3.863734073854205e-08 +3.93150965470317e-08 +3.854496805408196e-08 +3.995282967106224e-08 +4.449988328182066e-08 +5.040779034629319e-08 +5.090745753625525e-08 +4.6148949372902694e-08 +3.6968386578385855e-08 +2.4450572920385528e-08 +1.2553645055175237e-08 +9.292001727014961e-09 +2.992727048720495e-08 +6.589024120999936e-08 +6.97830430939012e-08 +5.239963799154164e-08 +4.500908359580174e-08 +4.229863563656836e-08 +4.218949780297138e-08 +4.255898854081177e-08 +4.1685557143621485e-08 +3.5609341130951205e-08 +2.346726405066577e-08 +3.3146507849901336e-08 +4.0237261931664005e-08 +4.3966028336755915e-08 +4.0468111460710625e-08 +3.9027952277010745e-08 +4.1176849922262086e-08 +5.138320973406618e-08 +5.478390518153827e-08 +5.0980928336884546e-08 +4.297959654709891e-08 +3.210131585616161e-08 +2.150286522802379e-08 +1.4277825588958814e-08 +2.942094654685029e-08 +5.5085595683898585e-08 +6.038576609215903e-08 +4.975575753623414e-08 +5.006558406685207e-08 +5.4034979671320446e-08 +5.425383061323969e-08 +5.4351956044952636e-08 +5.07532839098788e-08 +4.3332650864216826e-08 +2.4149704239061334e-08 +3.6544655652161444e-08 +4.182608854079831e-08 +3.9772439953633504e-08 +3.739565133506559e-08 +3.6222994898623366e-08 +3.900140745754402e-08 +4.618404113114511e-08 +5.0264793486007994e-08 +4.6846100157844835e-08 +3.808483045595735e-08 +2.848176946677028e-08 +1.6809280926524854e-08 +1.0566481789832678e-08 +2.4368472998876962e-08 +4.6795722528330575e-08 +4.502330109972665e-08 +4.0002467661643994e-08 +4.6800489090340077e-08 +4.8995983988339525e-08 +5.44245228424422e-08 +4.995233712807447e-08 +4.741595086429171e-08 +4.589434921591216e-08 +2.500300102086662e-08 +2.672964701775856e-08 +2.7953913815269234e-08 +2.5208374097793464e-08 +2.5087977316001614e-08 +2.4755879435304785e-08 +2.711688908997916e-08 +3.179732425490015e-08 +3.244039921566547e-08 +2.9594926060197282e-08 +2.5057405573457883e-08 +1.835561938809167e-08 +1.1413861460177887e-08 +1.0439510439751859e-08 +2.837501491417806e-08 +5.8732262167481936e-08 +6.109614819578273e-08 +5.122451609199106e-08 +4.024893179037693e-08 +4.422654560520654e-08 +4.245330235556649e-08 +4.453883759893283e-08 +3.766570172753522e-08 +3.298888257517317e-08 +1.915212833630094e-08 +2.8105621978537322e-08 +3.0956601334947525e-08 +3.373871208853072e-08 +3.3351387834206506e-08 +3.291598704926917e-08 +3.431415117802322e-08 +3.673885196299703e-08 +3.5738202669415105e-08 +3.249381758301339e-08 +2.4307986970618393e-08 +1.6429681789940187e-08 +9.08819011005675e-09 +5.998389560549547e-09 +2.82694109110364e-08 +6.439600620212268e-08 +7.025090580976536e-08 +5.041288563671715e-08 +4.1202655102796297e-08 +3.8288066798190274e-08 +4.2693931554942966e-08 +3.8359976138850934e-08 +4.215629623311207e-08 +3.579334686093888e-08 +2.32319766880241e-08 +3.4677560440196286e-08 +4.267313948272908e-08 +4.4177071978832014e-08 +4.041452872915548e-08 +3.828699843084332e-08 +4.076791177468786e-08 +4.5038258242584054e-08 +4.545237386268585e-08 +4.0976654317862804e-08 +3.224842182162741e-08 +2.286182849335483e-08 +1.3757366326782865e-08 +8.07685714300524e-09 +1.1919117033185581e-08 +2.7020489482442074e-08 +4.084623131943027e-08 +3.135115761438961e-08 +2.8929004474627774e-08 +2.7424743250110393e-08 +2.8382164757192317e-08 +2.9136514286248533e-08 +2.658763634271671e-08 +3.088329489852546e-08 +1.9860620251541557e-08 +3.22031394825371e-08 +3.976126318754225e-08 +3.880080094262668e-08 +3.639196130365001e-08 +3.83658110682074e-08 +4.166821671975931e-08 +4.626449741058142e-08 +4.672340227715185e-08 +4.292026106829091e-08 +3.3708140345986984e-08 +2.2013462637766273e-08 +1.2531702433510784e-08 +6.406670251294867e-09 +1.111948516503905e-08 +2.787510117790515e-08 +4.0639132418327576e-08 +3.404862080125225e-08 +2.7822668995800577e-08 +2.524954733170316e-08 +2.5566934615853412e-08 +2.6131361303461875e-08 +3.2636732261194974e-08 +3.6672695369589227e-08 +1.9600431711505388e-08 +3.141402692365293e-08 +3.863734073854205e-08 +3.93150965470317e-08 +3.854496805408196e-08 +3.995282967106224e-08 +4.449988328182066e-08 +5.040779034629319e-08 +5.090745753625525e-08 +4.6148949372902694e-08 +3.6968386578385855e-08 +2.4450572920385528e-08 +1.2553645055175237e-08 +9.292001727014961e-09 +2.992727048720495e-08 +6.589024120999936e-08 +6.97830430939012e-08 +5.239963799154164e-08 +4.500908359580174e-08 +4.229863563656836e-08 +4.218949780297138e-08 +4.255898854081177e-08 +4.1685557143621485e-08 +3.5609341130951205e-08 +2.346726405066577e-08 +3.3146507849901336e-08 +4.0237261931664005e-08 +4.3966028336755915e-08 +4.0468111460710625e-08 +3.9027952277010745e-08 +4.1176849922262086e-08 +5.138320973406618e-08 +5.478390518153827e-08 +5.0980928336884546e-08 +4.297959654709891e-08 +3.210131585616161e-08 +2.150286522802379e-08 +1.4277825588958814e-08 +2.942094654685029e-08 +5.5085595683898585e-08 +6.038576609215903e-08 +4.975575753623414e-08 +5.006558406685207e-08 +5.4034979671320446e-08 +5.425383061323969e-08 +5.4351956044952636e-08 +5.07532839098788e-08 +4.3332650864216826e-08 +2.4149704239061334e-08 +3.6544655652161444e-08 +4.182608854079831e-08 +3.9772439953633504e-08 +3.739565133506559e-08 +3.6222994898623366e-08 +3.900140745754402e-08 +4.618404113114511e-08 +5.0264793486007994e-08 +4.6846100157844835e-08 +3.808483045595735e-08 +2.848176946677028e-08 +1.6809280926524854e-08 +1.0566481789832678e-08 +2.4368472998876962e-08 +4.6795722528330575e-08 +4.502330109972665e-08 +4.0002467661643994e-08 +4.6800489090340077e-08 +4.8995983988339525e-08 +5.44245228424422e-08 +4.995233712807447e-08 +4.741595086429171e-08 +4.589434921591216e-08 +2.500300102086662e-08 +2.672964701775856e-08 +2.7953913815269234e-08 +2.5208374097793464e-08 +2.5087977316001614e-08 +2.4755879435304785e-08 +2.711688908997916e-08 +3.179732425490015e-08 +3.244039921566547e-08 +2.9594926060197282e-08 +2.5057405573457883e-08 +1.835561938809167e-08 +1.1413861460177887e-08 +1.0439510439751859e-08 +2.837501491417806e-08 +5.8732262167481936e-08 +6.109614819578273e-08 +5.122451609199106e-08 +4.024893179037693e-08 +4.422654560520654e-08 +4.245330235556649e-08 +4.453883759893283e-08 +3.766570172753522e-08 +3.298888257517317e-08 +1.915212833630094e-08 +2.8105621978537322e-08 +3.0956601334947525e-08 +3.373871208853072e-08 +3.3351387834206506e-08 +3.291598704926917e-08 +3.431415117802322e-08 +3.673885196299703e-08 +3.5738202669415105e-08 +3.249381758301339e-08 +2.4307986970618393e-08 +1.6429681789940187e-08 +9.08819011005675e-09 +5.998389560549547e-09 +2.82694109110364e-08 +6.439600620212268e-08 +7.025090580976536e-08 +5.041288563671715e-08 +4.1202655102796297e-08 +3.8288066798190274e-08 +4.2693931554942966e-08 +3.8359976138850934e-08 +4.215629623311207e-08 +3.579334686093888e-08 +2.32319766880241e-08 +3.4677560440196286e-08 +4.267313948272908e-08 +4.4177071978832014e-08 +4.041452872915548e-08 +3.828699843084332e-08 +4.076791177468786e-08 +4.5038258242584054e-08 +4.545237386268585e-08 +4.0976654317862804e-08 +3.224842182162741e-08 +2.286182849335483e-08 +1.3757366326782865e-08 +8.07685714300524e-09 +1.1919117033185581e-08 +2.7020489482442074e-08 +4.084623131943027e-08 +3.135115761438961e-08 +2.8929004474627774e-08 +2.7424743250110393e-08 +2.8382164757192317e-08 +2.9136514286248533e-08 +2.658763634271671e-08 +3.088329489852546e-08 +1.9860620251541557e-08 +3.22031394825371e-08 +3.976126318754225e-08 +3.880080094262668e-08 +3.639196130365001e-08 +3.83658110682074e-08 +4.166821671975931e-08 +4.626449741058142e-08 +4.672340227715185e-08 +4.292026106829091e-08 +3.3708140345986984e-08 +2.2013462637766273e-08 +1.2531702433510784e-08 +6.406670251294867e-09 +1.111948516503905e-08 +2.787510117790515e-08 +4.0639132418327576e-08 +3.404862080125225e-08 +2.7822668995800577e-08 +2.524954733170316e-08 +2.5566934615853412e-08 +2.6131361303461875e-08 +3.2636732261194974e-08 +3.6672695369589227e-08 +1.9600431711505388e-08 +3.141402692365293e-08 +3.863734073854205e-08 +3.93150965470317e-08 +3.854496805408196e-08 +3.995282967106224e-08 +4.449988328182066e-08 +5.040779034629319e-08 +5.090745753625525e-08 +4.6148949372902694e-08 +3.6968386578385855e-08 +2.4450572920385528e-08 +1.2553645055175237e-08 +9.292001727014961e-09 +2.992727048720495e-08 +6.589024120999936e-08 +6.97830430939012e-08 +5.239963799154164e-08 +4.500908359580174e-08 +4.229863563656836e-08 +4.218949780297138e-08 +4.255898854081177e-08 +4.1685557143621485e-08 +3.5609341130951205e-08 +2.346726405066577e-08 +3.3146507849901336e-08 +4.0237261931664005e-08 +4.3966028336755915e-08 +4.0468111460710625e-08 +3.9027952277010745e-08 +4.1176849922262086e-08 +5.138320973406618e-08 +5.478390518153827e-08 +5.0980928336884546e-08 +4.297959654709891e-08 +3.210131585616161e-08 +2.150286522802379e-08 +1.4277825588958814e-08 +2.942094654685029e-08 +5.5085595683898585e-08 +6.038576609215903e-08 +4.975575753623414e-08 +5.006558406685207e-08 +5.4034979671320446e-08 +5.425383061323969e-08 +5.4351956044952636e-08 +5.07532839098788e-08 +4.3332650864216826e-08 +2.4149704239061334e-08 +3.6544655652161444e-08 +4.182608854079831e-08 +3.9772439953633504e-08 +3.739565133506559e-08 +3.6222994898623366e-08 +3.900140745754402e-08 +4.618404113114511e-08 +5.0264793486007994e-08 +4.6846100157844835e-08 +3.808483045595735e-08 +2.848176946677028e-08 +1.6809280926524854e-08 +1.0566481789832678e-08 +2.4368472998876962e-08 +4.6795722528330575e-08 +4.502330109972665e-08 +4.0002467661643994e-08 +4.6800489090340077e-08 +4.8995983988339525e-08 +5.44245228424422e-08 +4.995233712807447e-08 +4.741595086429171e-08 +4.589434921591216e-08 +2.500300102086662e-08 +2.672964701775856e-08 +2.7953913815269234e-08 +2.5208374097793464e-08 +2.5087977316001614e-08 +2.4755879435304785e-08 +2.711688908997916e-08 +3.179732425490015e-08 +3.244039921566547e-08 +2.9594926060197282e-08 +2.5057405573457883e-08 +1.835561938809167e-08 +1.1413861460177887e-08 +1.0439510439751859e-08 +2.837501491417806e-08 +5.8732262167481936e-08 +6.109614819578273e-08 +5.122451609199106e-08 +4.024893179037693e-08 +4.422654560520654e-08 +4.245330235556649e-08 +4.453883759893283e-08 +3.766570172753522e-08 +3.298888257517317e-08 +1.915212833630094e-08 +2.8105621978537322e-08 +3.0956601334947525e-08 +3.373871208853072e-08 +3.3351387834206506e-08 +3.291598704926917e-08 +3.431415117802322e-08 +3.673885196299703e-08 +3.5738202669415105e-08 +3.249381758301339e-08 +2.4307986970618393e-08 +1.6429681789940187e-08 +9.08819011005675e-09 +5.998389560549547e-09 +2.82694109110364e-08 +6.439600620212268e-08 +7.025090580976536e-08 +5.041288563671715e-08 +4.1202655102796297e-08 +3.8288066798190274e-08 +4.2693931554942966e-08 +3.8359976138850934e-08 +4.215629623311207e-08 +3.579334686093888e-08 +2.32319766880241e-08 +3.4677560440196286e-08 +4.267313948272908e-08 +4.4177071978832014e-08 +4.041452872915548e-08 +3.828699843084332e-08 +4.076791177468786e-08 +4.5038258242584054e-08 +4.545237386268585e-08 +4.0976654317862804e-08 +3.224842182162741e-08 +2.286182849335483e-08 +1.3757366326782865e-08 +8.07685714300524e-09 +1.1919117033185581e-08 +2.7020489482442074e-08 +4.084623131943027e-08 +3.135115761438961e-08 +2.8929004474627774e-08 +2.7424743250110393e-08 +2.8382164757192317e-08 +2.9136514286248533e-08 +2.658763634271671e-08 +3.088329489852546e-08 +1.9860620251541557e-08 +3.22031394825371e-08 +3.976126318754225e-08 +3.880080094262668e-08 +3.639196130365001e-08 +3.83658110682074e-08 +4.166821671975931e-08 +4.626449741058142e-08 +4.672340227715185e-08 +4.292026106829091e-08 +3.3708140345986984e-08 +2.2013462637766273e-08 +1.2531702433510784e-08 +6.406670251294867e-09 +1.111948516503905e-08 +2.787510117790515e-08 +4.0639132418327576e-08 +3.404862080125225e-08 +2.7822668995800577e-08 +2.524954733170316e-08 +2.5566934615853412e-08 +2.6131361303461875e-08 +3.2636732261194974e-08 +3.6672695369589227e-08 +1.9600431711505388e-08 +3.141402692365293e-08 +3.863734073854205e-08 +3.93150965470317e-08 +3.854496805408196e-08 +3.995282967106224e-08 +4.449988328182066e-08 +5.040779034629319e-08 +5.090745753625525e-08 +4.6148949372902694e-08 +3.6968386578385855e-08 +2.4450572920385528e-08 +1.2553645055175237e-08 +9.292001727014961e-09 +2.992727048720495e-08 +6.589024120999936e-08 +6.97830430939012e-08 +5.239963799154164e-08 +4.500908359580174e-08 +4.229863563656836e-08 +4.218949780297138e-08 +4.255898854081177e-08 +4.1685557143621485e-08 +3.5609341130951205e-08 +2.346726405066577e-08 +3.3146507849901336e-08 +4.0237261931664005e-08 +4.3966028336755915e-08 +4.0468111460710625e-08 +3.9027952277010745e-08 +4.1176849922262086e-08 +5.138320973406618e-08 +5.478390518153827e-08 +5.0980928336884546e-08 +4.297959654709891e-08 +3.210131585616161e-08 +2.150286522802379e-08 +1.4277825588958814e-08 +2.942094654685029e-08 +5.5085595683898585e-08 +6.038576609215903e-08 +4.975575753623414e-08 +5.006558406685207e-08 +5.4034979671320446e-08 +5.425383061323969e-08 +5.4351956044952636e-08 +5.07532839098788e-08 +4.3332650864216826e-08 +2.4149704239061334e-08 +3.6544655652161444e-08 +4.182608854079831e-08 +3.9772439953633504e-08 +3.739565133506559e-08 +3.6222994898623366e-08 +3.900140745754402e-08 +4.618404113114511e-08 +5.0264793486007994e-08 +4.6846100157844835e-08 +3.808483045595735e-08 +2.848176946677028e-08 +1.6809280926524854e-08 +1.0566481789832678e-08 +2.4368472998876962e-08 +4.6795722528330575e-08 +4.502330109972665e-08 +4.0002467661643994e-08 +4.6800489090340077e-08 +4.8995983988339525e-08 +5.44245228424422e-08 +4.995233712807447e-08 +4.741595086429171e-08 +4.589434921591216e-08 +2.500300102086662e-08 +2.672964701775856e-08 +2.7953913815269234e-08 +2.5208374097793464e-08 +2.5087977316001614e-08 +2.4755879435304785e-08 +2.711688908997916e-08 +3.02656142077763e-08 +3.052284419208243e-08 +2.7446932418085685e-08 +2.387160000043771e-08 +1.9593857143216417e-08 +1.2883934929592597e-08 +1.1893311852651356e-08 +2.7653209498152262e-08 +4.491145125671046e-08 +4.409636915308485e-08 +3.6775094270690005e-08 +3.4864195997499555e-08 +4.043137606039598e-08 +4.639755023632955e-08 +3.961728014201371e-08 +3.9246967583137205e-08 +3.8794308556441316e-08 +2.3763694898394913e-08 +2.5039818603284873e-08 +2.5472096468284946e-08 +2.7543578571933603e-08 +2.6727428100961036e-08 +2.591875620141716e-08 +2.6437160911002806e-08 +2.7430085086845188e-08 +2.6277563265787942e-08 +2.2838077865410906e-08 +1.7923834615713264e-08 +1.3061530455498522e-08 +9.230282967202212e-09 +6.556241679869038e-09 +2.585958508681639e-08 +6.173536059767829e-08 +6.399380698704466e-08 +4.7220521821901936e-08 +3.499075643706231e-08 +3.611015887036384e-08 +3.3797390110509815e-08 +3.286199340719596e-08 +3.299562150766937e-08 +3.4143212402509876e-08 +2.2226232104018218e-08 +3.499749536955851e-08 +4.1857482104378166e-08 +3.6536766170214675e-08 +3.243029081692117e-08 +3.0985940345937074e-08 +3.0541335165395173e-08 +3.254066138207233e-08 +3.053237731610144e-08 +2.644159874459786e-08 +2.0239479749193717e-08 +1.425703351674493e-08 +9.071014050401804e-09 +4.974236185334536e-09 +1.1641752433494468e-08 +2.835282574620276e-08 +3.751752739472246e-08 +2.977186412927431e-08 +2.1211447488614993e-08 +2.4971936185701213e-08 +2.288270274767232e-08 +2.5643610518523573e-08 +2.3659077080496603e-08 +2.7837954867072443e-08 +1.7572834851185637e-08 +3.251247292053335e-08 +3.870941444340993e-08 +3.758590290492779e-08 +3.314404238679297e-08 +3.374068445901741e-08 +3.672562064431547e-08 +3.8947249451263593e-08 +3.639870023614621e-08 +3.137515478864437e-08 +2.2884675118159017e-08 +1.5230151805616778e-08 +8.359974489949207e-09 +5.4069249608526734e-09 +1.4843320643914238e-08 +2.7998209969116197e-08 +3.5277489796565215e-08 +2.2281705023956437e-08 +1.820037739436826e-08 +2.0462439796293565e-08 +2.226288532222925e-08 +2.3518792229630612e-08 +2.3589386656633478e-08 +2.2312030220189333e-08 +2.3926251099339808e-08 +3.261684419212082e-08 +3.673194866629361e-08 +3.657900777147134e-08 +3.223313595035555e-08 +3.2204372214091284e-08 +3.472678752025998e-08 +3.665888877618238e-08 +3.506817197866499e-08 +3.0240219937760134e-08 +2.2709051962739783e-08 +1.5849640502645406e-08 +1.1737001491580985e-08 +1.5343398744394367e-08 +3.9702174255045084e-08 +6.20640068300234e-08 +6.109154599798046e-08 +4.134121412948645e-08 +3.7827600471651216e-08 +3.6263921586222236e-08 +3.975189442773045e-08 +3.304312276355721e-08 +3.042948532237899e-08 +2.8639066013083993e-08 +2.4419918995738187e-08 +3.241032056574341e-08 +3.6295150785594865e-08 +3.457639427064969e-08 +3.2770195997461156e-08 +3.278704332870165e-08 +3.657514521260157e-08 +3.791356295202956e-08 +3.6543505102710875e-08 +3.1522260754110177e-08 +2.4686764286166943e-08 +1.6460746625105593e-08 +1.0078731004894379e-08 +1.2483708085001272e-08 +3.644340730051124e-08 +5.892218500892969e-08 +5.7337796233390434e-08 +4.618527386269929e-08 +3.8302037755804345e-08 +3.793690266945542e-08 +3.409891624866291e-08 +2.834773045577881e-08 +2.608254513391624e-08 +2.9133637912622105e-08 +1.9781643249970252e-08 +3.229049905867685e-08 +3.432286248100611e-08 +3.175171318739538e-08 +3.013050682943787e-08 +2.9372459105719103e-08 +3.101149898016046e-08 +3.460655510267536e-08 +3.5664238776164146e-08 +3.2318358791801383e-08 +2.7424743250110393e-08 +1.9851169309626152e-08 +1.3424117896635469e-08 +1.2988306201180068e-08 +2.932849168028659e-08 +4.588703500869068e-08 +4.4791629749643904e-08 +4.0026382653795145e-08 +4.478793155498136e-08 +4.496889654713538e-08 +4.3917787441935574e-08 +3.878157033038143e-08 +4.185961883907209e-08 +4.085683281079624e-08 +2.3011564286136224e-08 +2.524108257503111e-08 +2.6002746311308814e-08 +2.4038429670770438e-08 +2.480798288899491e-08 +2.3884995683326493e-08 +2.7093385008346077e-08 +3.02656142077763e-08 +3.052284419208243e-08 +2.7446932418085685e-08 +2.387160000043771e-08 +1.9593857143216417e-08 +1.2883934929592597e-08 +1.1893311852651356e-08 +2.7653209498152262e-08 +4.491145125671046e-08 +4.409636915308485e-08 +3.6775094270690005e-08 +3.4864195997499555e-08 +4.043137606039598e-08 +4.639755023632955e-08 +3.961728014201371e-08 +3.9246967583137205e-08 +3.8794308556441316e-08 +2.3763694898394913e-08 +2.5039818603284873e-08 +2.5472096468284946e-08 +2.7543578571933603e-08 +2.6727428100961036e-08 +2.591875620141716e-08 +2.6437160911002806e-08 +2.7430085086845188e-08 +2.6277563265787942e-08 +2.2838077865410906e-08 +1.7923834615713264e-08 +1.3061530455498522e-08 +9.230282967202212e-09 +6.556241679869038e-09 +2.585958508681639e-08 +6.173536059767829e-08 +6.399380698704466e-08 +4.7220521821901936e-08 +3.499075643706231e-08 +3.611015887036384e-08 +3.3797390110509815e-08 +3.286199340719596e-08 +3.299562150766937e-08 +3.4143212402509876e-08 +2.2226232104018218e-08 +3.499749536955851e-08 +4.1857482104378166e-08 +3.6536766170214675e-08 +3.243029081692117e-08 +3.0985940345937074e-08 +3.0541335165395173e-08 +3.254066138207233e-08 +3.053237731610144e-08 +2.644159874459786e-08 +2.0239479749193717e-08 +1.425703351674493e-08 +9.071014050401804e-09 +4.974236185334536e-09 +1.1641752433494468e-08 +2.835282574620276e-08 +3.751752739472246e-08 +2.977186412927431e-08 +2.1211447488614993e-08 +2.4971936185701213e-08 +2.288270274767232e-08 +2.5643610518523573e-08 +2.3659077080496603e-08 +2.7837954867072443e-08 +1.7572834851185637e-08 +3.251247292053335e-08 +3.870941444340993e-08 +3.758590290492779e-08 +3.314404238679297e-08 +3.374068445901741e-08 +3.672562064431547e-08 +3.8947249451263593e-08 +3.639870023614621e-08 +3.137515478864437e-08 +2.2884675118159017e-08 +1.5230151805616778e-08 +8.359974489949207e-09 +5.4069249608526734e-09 +1.4843320643914238e-08 +2.7998209969116197e-08 +3.5277489796565215e-08 +2.2281705023956437e-08 +1.820037739436826e-08 +2.0462439796293565e-08 +2.226288532222925e-08 +2.3518792229630612e-08 +2.3589386656633478e-08 +2.2312030220189333e-08 +2.3926251099339808e-08 +3.261684419212082e-08 +3.673194866629361e-08 +3.657900777147134e-08 +3.223313595035555e-08 +3.2204372214091284e-08 +3.472678752025998e-08 +3.665888877618238e-08 +3.506817197866499e-08 +3.0240219937760134e-08 +2.2709051962739783e-08 +1.5849640502645406e-08 +1.1737001491580985e-08 +1.5343398744394367e-08 +3.9702174255045084e-08 +6.20640068300234e-08 +6.109154599798046e-08 +4.134121412948645e-08 +3.7827600471651216e-08 +3.6263921586222236e-08 +3.975189442773045e-08 +3.304312276355721e-08 +3.042948532237899e-08 +2.8639066013083993e-08 +2.4419918995738187e-08 +3.241032056574341e-08 +3.6295150785594865e-08 +3.457639427064969e-08 +3.2770195997461156e-08 +3.278704332870165e-08 +3.657514521260157e-08 +3.791356295202956e-08 +3.6543505102710875e-08 +3.1522260754110177e-08 +2.4686764286166943e-08 +1.6460746625105593e-08 +1.0078731004894379e-08 +1.2483708085001272e-08 +3.644340730051124e-08 +5.892218500892969e-08 +5.7337796233390434e-08 +4.618527386269929e-08 +3.8302037755804345e-08 +3.793690266945542e-08 +3.409891624866291e-08 +2.834773045577881e-08 +2.608254513391624e-08 +2.9133637912622105e-08 +1.9781643249970252e-08 +3.229049905867685e-08 +3.432286248100611e-08 +3.175171318739538e-08 +3.013050682943787e-08 +2.9372459105719103e-08 +3.101149898016046e-08 +3.460655510267536e-08 +3.5664238776164146e-08 +3.2318358791801383e-08 +2.7424743250110393e-08 +1.9851169309626152e-08 +1.3424117896635469e-08 +1.2988306201180068e-08 +2.932849168028659e-08 +4.588703500869068e-08 +4.4791629749643904e-08 +4.0026382653795145e-08 +4.478793155498136e-08 +4.496889654713538e-08 +4.3917787441935574e-08 +3.878157033038143e-08 +4.185961883907209e-08 +4.085683281079624e-08 +2.3011564286136224e-08 +2.524108257503111e-08 +2.6002746311308814e-08 +2.4038429670770438e-08 +2.480798288899491e-08 +2.3884995683326493e-08 +2.7093385008346077e-08 +3.02656142077763e-08 +3.052284419208243e-08 +2.7446932418085685e-08 +2.387160000043771e-08 +1.9593857143216417e-08 +1.2883934929592597e-08 +1.1893311852651356e-08 +2.7653209498152262e-08 +4.491145125671046e-08 +4.409636915308485e-08 +3.6775094270690005e-08 +3.4864195997499555e-08 +4.043137606039598e-08 +4.639755023632955e-08 +3.961728014201371e-08 +3.9246967583137205e-08 +3.8794308556441316e-08 +2.3763694898394913e-08 +2.5039818603284873e-08 +2.5472096468284946e-08 +2.7543578571933603e-08 +2.6727428100961036e-08 +2.591875620141716e-08 +2.6437160911002806e-08 +2.7430085086845188e-08 +2.6277563265787942e-08 +2.2838077865410906e-08 +1.7923834615713264e-08 +1.3061530455498522e-08 +9.230282967202212e-09 +6.556241679869038e-09 +2.585958508681639e-08 +6.173536059767829e-08 +6.399380698704466e-08 +4.7220521821901936e-08 +3.499075643706231e-08 +3.611015887036384e-08 +3.3797390110509815e-08 +3.286199340719596e-08 +3.299562150766937e-08 +3.4143212402509876e-08 +2.2226232104018218e-08 +3.499749536955851e-08 +4.1857482104378166e-08 +3.6536766170214675e-08 +3.243029081692117e-08 +3.0985940345937074e-08 +3.0541335165395173e-08 +3.254066138207233e-08 +3.053237731610144e-08 +2.644159874459786e-08 +2.0239479749193717e-08 +1.425703351674493e-08 +9.071014050401804e-09 +4.974236185334536e-09 +1.1641752433494468e-08 +2.835282574620276e-08 +3.751752739472246e-08 +2.977186412927431e-08 +2.1211447488614993e-08 +2.4971936185701213e-08 +2.288270274767232e-08 +2.5643610518523573e-08 +2.3659077080496603e-08 +2.7837954867072443e-08 +1.7572834851185637e-08 +3.251247292053335e-08 +3.870941444340993e-08 +3.758590290492779e-08 +3.314404238679297e-08 +3.374068445901741e-08 +3.672562064431547e-08 +3.8947249451263593e-08 +3.639870023614621e-08 +3.137515478864437e-08 +2.2884675118159017e-08 +1.5230151805616778e-08 +8.359974489949207e-09 +5.4069249608526734e-09 +1.4843320643914238e-08 +2.7998209969116197e-08 +3.5277489796565215e-08 +2.2281705023956437e-08 +1.820037739436826e-08 +2.0462439796293565e-08 +2.226288532222925e-08 +2.3518792229630612e-08 +2.3589386656633478e-08 +2.2312030220189333e-08 +2.3926251099339808e-08 +3.261684419212082e-08 +3.673194866629361e-08 +3.657900777147134e-08 +3.223313595035555e-08 +3.2204372214091284e-08 +3.472678752025998e-08 +3.665888877618238e-08 +3.506817197866499e-08 +3.0240219937760134e-08 +2.2709051962739783e-08 +1.5849640502645406e-08 +1.1737001491580985e-08 +1.5343398744394367e-08 +3.9702174255045084e-08 +6.20640068300234e-08 +6.109154599798046e-08 +4.134121412948645e-08 +3.7827600471651216e-08 +3.6263921586222236e-08 +3.975189442773045e-08 +3.304312276355721e-08 +3.042948532237899e-08 +2.8639066013083993e-08 +2.4419918995738187e-08 +3.241032056574341e-08 +3.6295150785594865e-08 +3.457639427064969e-08 +3.2770195997461156e-08 +3.278704332870165e-08 +3.657514521260157e-08 +3.791356295202956e-08 +3.6543505102710875e-08 +3.1522260754110177e-08 +2.4686764286166943e-08 +1.6460746625105593e-08 +1.0078731004894379e-08 +1.2483708085001272e-08 +3.644340730051124e-08 +5.892218500892969e-08 +5.7337796233390434e-08 +4.618527386269929e-08 +3.8302037755804345e-08 +3.793690266945542e-08 +3.409891624866291e-08 +2.834773045577881e-08 +2.608254513391624e-08 +2.9133637912622105e-08 +1.9781643249970252e-08 +3.229049905867685e-08 +3.432286248100611e-08 +3.175171318739538e-08 +3.013050682943787e-08 +2.9372459105719103e-08 +3.101149898016046e-08 +3.460655510267536e-08 +3.5664238776164146e-08 +3.2318358791801383e-08 +2.7424743250110393e-08 +1.9851169309626152e-08 +1.3424117896635469e-08 +1.2988306201180068e-08 +2.932849168028659e-08 +4.588703500869068e-08 +4.4791629749643904e-08 +4.0026382653795145e-08 +4.478793155498136e-08 +4.496889654713538e-08 +4.3917787441935574e-08 +3.878157033038143e-08 +4.185961883907209e-08 +4.085683281079624e-08 +2.3011564286136224e-08 +2.524108257503111e-08 +2.6002746311308814e-08 +2.4038429670770438e-08 +2.480798288899491e-08 +2.3884995683326493e-08 +2.7093385008346077e-08 +3.02656142077763e-08 +3.052284419208243e-08 +2.7446932418085685e-08 +2.387160000043771e-08 +1.9593857143216417e-08 +1.2883934929592597e-08 +1.1893311852651356e-08 +2.7653209498152262e-08 +4.491145125671046e-08 +4.409636915308485e-08 +3.6775094270690005e-08 +3.4864195997499555e-08 +4.043137606039598e-08 +4.639755023632955e-08 +3.961728014201371e-08 +3.9246967583137205e-08 +3.8794308556441316e-08 +2.3763694898394913e-08 +2.5039818603284873e-08 +2.5472096468284946e-08 +2.7543578571933603e-08 +2.6727428100961036e-08 +2.591875620141716e-08 +2.6437160911002806e-08 +2.7430085086845188e-08 +2.6277563265787942e-08 +2.2838077865410906e-08 +1.7923834615713264e-08 +1.3061530455498522e-08 +9.230282967202212e-09 +6.556241679869038e-09 +2.585958508681639e-08 +6.173536059767829e-08 +6.399380698704466e-08 +4.7220521821901936e-08 +3.499075643706231e-08 +3.611015887036384e-08 +3.3797390110509815e-08 +3.286199340719596e-08 +3.299562150766937e-08 +3.4143212402509876e-08 +2.2226232104018218e-08 +3.499749536955851e-08 +4.1857482104378166e-08 +3.6536766170214675e-08 +3.243029081692117e-08 +3.0985940345937074e-08 +3.0541335165395173e-08 +3.254066138207233e-08 +3.053237731610144e-08 +2.644159874459786e-08 +2.0239479749193717e-08 +1.425703351674493e-08 +9.071014050401804e-09 +4.974236185334536e-09 +1.1641752433494468e-08 +2.835282574620276e-08 +3.751752739472246e-08 +2.977186412927431e-08 +2.1211447488614993e-08 +2.4971936185701213e-08 +2.288270274767232e-08 +2.5643610518523573e-08 +2.3659077080496603e-08 +2.7837954867072443e-08 +1.7572834851185637e-08 +3.251247292053335e-08 +3.870941444340993e-08 +3.758590290492779e-08 +3.314404238679297e-08 +3.374068445901741e-08 +3.672562064431547e-08 +3.8947249451263593e-08 +3.639870023614621e-08 +3.137515478864437e-08 +2.2884675118159017e-08 +1.5230151805616778e-08 +8.359974489949207e-09 +5.4069249608526734e-09 +1.4843320643914238e-08 +2.7998209969116197e-08 +3.5277489796565215e-08 +2.2281705023956437e-08 +1.820037739436826e-08 +2.0462439796293565e-08 +2.226288532222925e-08 +2.3518792229630612e-08 +2.3589386656633478e-08 +2.2312030220189333e-08 +2.3926251099339808e-08 +3.261684419212082e-08 +3.673194866629361e-08 +3.657900777147134e-08 +3.223313595035555e-08 +3.2204372214091284e-08 +3.472678752025998e-08 +3.665888877618238e-08 +3.506817197866499e-08 +3.0240219937760134e-08 +2.2709051962739783e-08 +1.5849640502645406e-08 +1.1737001491580985e-08 +1.5343398744394367e-08 +3.9702174255045084e-08 +6.20640068300234e-08 +6.109154599798046e-08 +4.134121412948645e-08 +3.7827600471651216e-08 +3.6263921586222236e-08 +3.975189442773045e-08 +3.304312276355721e-08 +3.042948532237899e-08 +2.8639066013083993e-08 +2.4419918995738187e-08 +3.241032056574341e-08 +3.6295150785594865e-08 +3.457639427064969e-08 +3.2770195997461156e-08 +3.278704332870165e-08 +3.657514521260157e-08 +3.791356295202956e-08 +3.6543505102710875e-08 +3.1522260754110177e-08 +2.4686764286166943e-08 +1.6460746625105593e-08 +1.0078731004894379e-08 +1.2483708085001272e-08 +3.644340730051124e-08 +5.892218500892969e-08 +5.7337796233390434e-08 +4.618527386269929e-08 +3.8302037755804345e-08 +3.793690266945542e-08 +3.409891624866291e-08 +2.834773045577881e-08 +2.608254513391624e-08 +2.9133637912622105e-08 +1.9781643249970252e-08 +3.229049905867685e-08 +3.432286248100611e-08 +3.175171318739538e-08 +3.013050682943787e-08 +2.9372459105719103e-08 +3.101149898016046e-08 +3.460655510267536e-08 +3.5664238776164146e-08 +3.2318358791801383e-08 +2.7424743250110393e-08 +1.9851169309626152e-08 +1.3424117896635469e-08 +1.2988306201180068e-08 +2.932849168028659e-08 +4.588703500869068e-08 +4.4791629749643904e-08 +4.0026382653795145e-08 +4.478793155498136e-08 +4.496889654713538e-08 +4.3917787441935574e-08 +3.878157033038143e-08 +4.185961883907209e-08 +4.085683281079624e-08 +2.3011564286136224e-08 +2.524108257503111e-08 +2.6002746311308814e-08 +2.4038429670770438e-08 +2.480798288899491e-08 +2.3884995683326493e-08 +2.7093385008346077e-08 +3.02656142077763e-08 +3.052284419208243e-08 +2.7446932418085685e-08 +2.387160000043771e-08 +1.9593857143216417e-08 +1.2883934929592597e-08 +1.1893311852651356e-08 +2.7653209498152262e-08 +4.491145125671046e-08 +4.409636915308485e-08 +3.6775094270690005e-08 +3.4864195997499555e-08 +4.043137606039598e-08 +4.639755023632955e-08 +3.961728014201371e-08 +3.9246967583137205e-08 +3.8794308556441316e-08 +2.3763694898394913e-08 +2.5039818603284873e-08 +2.5472096468284946e-08 +2.7543578571933603e-08 +2.6727428100961036e-08 +2.591875620141716e-08 +2.6437160911002806e-08 +2.7430085086845188e-08 +2.6277563265787942e-08 +2.2838077865410906e-08 +1.7923834615713264e-08 +1.3061530455498522e-08 +9.230282967202212e-09 +6.556241679869038e-09 +2.585958508681639e-08 +6.173536059767829e-08 +6.399380698704466e-08 +4.7220521821901936e-08 +3.499075643706231e-08 +3.611015887036384e-08 +3.3797390110509815e-08 +3.286199340719596e-08 +3.299562150766937e-08 +3.4143212402509876e-08 +2.2226232104018218e-08 +3.499749536955851e-08 +4.1857482104378166e-08 +3.6536766170214675e-08 +3.243029081692117e-08 +3.0985940345937074e-08 +3.0541335165395173e-08 +3.254066138207233e-08 +3.053237731610144e-08 +2.644159874459786e-08 +2.0239479749193717e-08 +1.425703351674493e-08 +9.071014050401804e-09 +4.974236185334536e-09 +1.1641752433494468e-08 +2.835282574620276e-08 +3.751752739472246e-08 +2.977186412927431e-08 +2.1211447488614993e-08 +2.4971936185701213e-08 +2.288270274767232e-08 +2.5643610518523573e-08 +2.3659077080496603e-08 +2.7837954867072443e-08 +1.7572834851185637e-08 +3.251247292053335e-08 +3.870941444340993e-08 +3.758590290492779e-08 +3.314404238679297e-08 +3.374068445901741e-08 +3.672562064431547e-08 +3.7325714364891624e-08 +3.167207872899518e-08 +2.406078320295295e-08 +1.5800084694167263e-08 +9.56049065951596e-09 +5.596519073885978e-09 +9.346652825917062e-09 +2.194319693917786e-08 +3.243579701786319e-08 +2.578570337566904e-08 +2.070635627981452e-08 +2.4616087677060465e-08 +2.3595139403886328e-08 +2.090145659378984e-08 +2.7129216405520988e-08 +3.158792425489631e-08 +1.704070573029676e-08 +3.400605047158115e-08 +3.777007299912269e-08 +3.6565201178064495e-08 +3.571888987506624e-08 +3.383198877613055e-08 +3.9566080691463313e-08 +4.2673386029039914e-08 +3.959131059727225e-08 +3.4407016955104984e-08 +2.5515570801095793e-08 +1.8369425981498515e-08 +1.0952819858913546e-08 +8.651227865150779e-09 +2.9775397959729636e-08 +6.173462095874578e-08 +6.557737394154779e-08 +4.779612527560166e-08 +4.20688544748687e-08 +3.827804058154959e-08 +3.9422426374349226e-08 +3.1413451648927644e-08 +3.092997433337718e-08 +2.8827180848252276e-08 +1.864112001604039e-08 +3.3595468681934686e-08 +3.6086408242419924e-08 +3.5647309262820034e-08 +3.416983940408022e-08 +3.47842328106849e-08 +3.695170361135258e-08 +4.0468029278607005e-08 +3.875740879191945e-08 +3.374084882322463e-08 +2.721920580897633e-08 +2.071202684496376e-08 +1.1522341836945966e-08 +9.784354709755546e-09 +2.9650398980135508e-08 +5.7775333753021683e-08 +6.211742519737132e-08 +4.822873186901619e-08 +3.8035767740100873e-08 +4.283725714364261e-08 +3.60714510995625e-08 +3.145059795976035e-08 +2.9009871664582158e-08 +2.812000384666945e-08 +2.142232676648385e-08 +2.8621150314496537e-08 +3.1909667190538e-08 +3.2843502433883223e-08 +3.1474512951911494e-08 +2.9804819152822796e-08 +3.118350612302076e-08 +3.568807158621167e-08 +3.618995769297127e-08 +3.4015337049289326e-08 +2.8976423548412e-08 +2.0906551884213795e-08 +1.385319065959467e-08 +8.923497174417939e-09 +2.2680288226475518e-08 +4.246004128806268e-08 +4.294779207300098e-08 +4.5546883281839853e-08 +4.601137653145591e-08 +4.722208328187057e-08 +4.455971185325033e-08 +4.071482213575439e-08 +3.919609686100126e-08 +3.429220855635876e-08 +2.1552667582812776e-08 +2.1880491994121763e-08 +2.5024779278323846e-08 +2.340957221393002e-08 +2.5545895997328686e-08 +2.139980887009411e-08 +2.387579128772193e-08 +2.838084984353452e-08 +2.9053592543703837e-08 +2.755722080113323e-08 +2.476163218255764e-08 +1.836424850897095e-08 +1.2363311303209424e-08 +7.770235714428189e-09 +2.177176507104285e-08 +4.137581279510718e-08 +4.087762488301012e-08 +3.5789155573654655e-08 +3.893122394105921e-08 +4.610629686112798e-08 +5.0537473705793214e-08 +4.701424474183537e-08 +3.453604285777611e-08 +3.2959461382080014e-08 +1.8337785871607828e-08 +2.2063840267280545e-08 +2.6118294348987537e-08 +2.9752715699132674e-08 +2.8454156279956586e-08 +2.885101365829981e-08 +2.9448559733663986e-08 +3.0920030298840104e-08 +2.9067727865525134e-08 +2.4992317347397035e-08 +1.9460475589053846e-08 +1.2290087048890972e-08 +7.487447095898671e-09 +6.9106930927483785e-09 +2.7016544741468683e-08 +5.6372403062258135e-08 +5.895826295241544e-08 +4.810595180621959e-08 +4.0753612088659346e-08 +4.026668312475717e-08 +3.558205667255196e-08 +3.137663406650939e-08 +3.199579403512357e-08 +2.896097331293291e-08 +1.9402290659696418e-08 +3.229707362696583e-08 +3.89763419159423e-08 +3.912994026759346e-08 +3.452009952967534e-08 +3.3933976766713263e-08 +3.4867318917436816e-08 +3.6627002119980855e-08 +3.439986711209072e-08 +3.037080730039989e-08 +2.4728841523216376e-08 +1.7694053454013604e-08 +1.013412174272899e-08 +4.7832449765398245e-09 +1.0727805259223392e-08 +2.404615478850998e-08 +3.262908932555904e-08 +2.8356359576658083e-08 +2.323698979634444e-08 +2.0556949215447575e-08 +2.0447811381850597e-08 +2.5025436735152743e-08 +2.3343086892107763e-08 +3.100508877607871e-08 +1.9600102983090943e-08 +3.043786789694743e-08 +3.985486860355653e-08 +3.834370408233572e-08 +3.5027163108962506e-08 +3.3358866405635216e-08 +3.327208210422075e-08 +3.7117300550131134e-08 +3.7325714364891624e-08 +3.167207872899518e-08 +2.406078320295295e-08 +1.5800084694167263e-08 +9.56049065951596e-09 +5.596519073885978e-09 +9.346652825917062e-09 +2.194319693917786e-08 +3.243579701786319e-08 +2.578570337566904e-08 +2.070635627981452e-08 +2.4616087677060465e-08 +2.3595139403886328e-08 +2.090145659378984e-08 +2.7129216405520988e-08 +3.158792425489631e-08 +1.704070573029676e-08 +3.400605047158115e-08 +3.777007299912269e-08 +3.6565201178064495e-08 +3.571888987506624e-08 +3.383198877613055e-08 +3.9566080691463313e-08 +4.2673386029039914e-08 +3.959131059727225e-08 +3.4407016955104984e-08 +2.5515570801095793e-08 +1.8369425981498515e-08 +1.0952819858913546e-08 +8.651227865150779e-09 +2.9775397959729636e-08 +6.173462095874578e-08 +6.557737394154779e-08 +4.779612527560166e-08 +4.20688544748687e-08 +3.827804058154959e-08 +3.9422426374349226e-08 +3.1413451648927644e-08 +3.092997433337718e-08 +2.8827180848252276e-08 +1.864112001604039e-08 +3.3595468681934686e-08 +3.6086408242419924e-08 +3.5647309262820034e-08 +3.416983940408022e-08 +3.47842328106849e-08 +3.695170361135258e-08 +4.0468029278607005e-08 +3.875740879191945e-08 +3.374084882322463e-08 +2.721920580897633e-08 +2.071202684496376e-08 +1.1522341836945966e-08 +9.784354709755546e-09 +2.9650398980135508e-08 +5.7775333753021683e-08 +6.211742519737132e-08 +4.822873186901619e-08 +3.8035767740100873e-08 +4.283725714364261e-08 +3.60714510995625e-08 +3.145059795976035e-08 +2.9009871664582158e-08 +2.812000384666945e-08 +2.142232676648385e-08 +2.8621150314496537e-08 +3.1909667190538e-08 +3.2843502433883223e-08 +3.1474512951911494e-08 +2.9804819152822796e-08 +3.118350612302076e-08 +3.568807158621167e-08 +3.618995769297127e-08 +3.4015337049289326e-08 +2.8976423548412e-08 +2.0906551884213795e-08 +1.385319065959467e-08 +8.923497174417939e-09 +2.2680288226475518e-08 +4.246004128806268e-08 +4.294779207300098e-08 +4.5546883281839853e-08 +4.601137653145591e-08 +4.722208328187057e-08 +4.455971185325033e-08 +4.071482213575439e-08 +3.919609686100126e-08 +3.429220855635876e-08 +2.1552667582812776e-08 +2.1880491994121763e-08 +2.5024779278323846e-08 +2.340957221393002e-08 +2.5545895997328686e-08 +2.139980887009411e-08 +2.387579128772193e-08 +2.838084984353452e-08 +2.9053592543703837e-08 +2.755722080113323e-08 +2.476163218255764e-08 +1.836424850897095e-08 +1.2363311303209424e-08 +7.770235714428189e-09 +2.177176507104285e-08 +4.137581279510718e-08 +4.087762488301012e-08 +3.5789155573654655e-08 +3.893122394105921e-08 +4.610629686112798e-08 +5.0537473705793214e-08 +4.701424474183537e-08 +3.453604285777611e-08 +3.2959461382080014e-08 +1.8337785871607828e-08 +2.2063840267280545e-08 +2.6118294348987537e-08 +2.9752715699132674e-08 +2.8454156279956586e-08 +2.885101365829981e-08 +2.9448559733663986e-08 +3.0920030298840104e-08 +2.9067727865525134e-08 +2.4992317347397035e-08 +1.9460475589053846e-08 +1.2290087048890972e-08 +7.487447095898671e-09 +6.9106930927483785e-09 +2.7016544741468683e-08 +5.6372403062258135e-08 +5.895826295241544e-08 +4.810595180621959e-08 +4.0753612088659346e-08 +4.026668312475717e-08 +3.558205667255196e-08 +3.137663406650939e-08 +3.199579403512357e-08 +2.896097331293291e-08 +1.9402290659696418e-08 +3.229707362696583e-08 +3.89763419159423e-08 +3.912994026759346e-08 +3.452009952967534e-08 +3.3933976766713263e-08 +3.4867318917436816e-08 +3.6627002119980855e-08 +3.439986711209072e-08 +3.037080730039989e-08 +2.4728841523216376e-08 +1.7694053454013604e-08 +1.013412174272899e-08 +4.7832449765398245e-09 +1.0727805259223392e-08 +2.404615478850998e-08 +3.262908932555904e-08 +2.8356359576658083e-08 +2.323698979634444e-08 +2.0556949215447575e-08 +2.0447811381850597e-08 +2.5025436735152743e-08 +2.3343086892107763e-08 +3.100508877607871e-08 +1.9600102983090943e-08 +3.043786789694743e-08 +3.985486860355653e-08 +3.834370408233572e-08 +3.5027163108962506e-08 +3.3358866405635216e-08 +3.327208210422075e-08 +3.7117300550131134e-08 +3.7325714364891624e-08 +3.167207872899518e-08 +2.406078320295295e-08 +1.5800084694167263e-08 +9.56049065951596e-09 +5.596519073885978e-09 +9.346652825917062e-09 +2.194319693917786e-08 +3.243579701786319e-08 +2.578570337566904e-08 +2.070635627981452e-08 +2.4616087677060465e-08 +2.3595139403886328e-08 +2.090145659378984e-08 +2.7129216405520988e-08 +3.158792425489631e-08 +1.704070573029676e-08 +3.400605047158115e-08 +3.777007299912269e-08 +3.6565201178064495e-08 +3.571888987506624e-08 +3.383198877613055e-08 +3.9566080691463313e-08 +4.2673386029039914e-08 +3.959131059727225e-08 +3.4407016955104984e-08 +2.5515570801095793e-08 +1.8369425981498515e-08 +1.0952819858913546e-08 +8.651227865150779e-09 +2.9775397959729636e-08 +6.173462095874578e-08 +6.557737394154779e-08 +4.779612527560166e-08 +4.20688544748687e-08 +3.827804058154959e-08 +3.9422426374349226e-08 +3.1413451648927644e-08 +3.092997433337718e-08 +2.8827180848252276e-08 +1.864112001604039e-08 +3.3595468681934686e-08 +3.6086408242419924e-08 +3.5647309262820034e-08 +3.416983940408022e-08 +3.47842328106849e-08 +3.695170361135258e-08 +4.0468029278607005e-08 +3.875740879191945e-08 +3.374084882322463e-08 +2.721920580897633e-08 +2.071202684496376e-08 +1.1522341836945966e-08 +9.784354709755546e-09 +2.9650398980135508e-08 +5.7775333753021683e-08 +6.211742519737132e-08 +4.822873186901619e-08 +3.8035767740100873e-08 +4.283725714364261e-08 +3.60714510995625e-08 +3.145059795976035e-08 +2.9009871664582158e-08 +2.812000384666945e-08 +2.142232676648385e-08 +2.8621150314496537e-08 +3.1909667190538e-08 +3.2843502433883223e-08 +3.1474512951911494e-08 +2.9804819152822796e-08 +3.118350612302076e-08 +3.568807158621167e-08 +3.618995769297127e-08 +3.4015337049289326e-08 +2.8976423548412e-08 +2.0906551884213795e-08 +1.385319065959467e-08 +8.923497174417939e-09 +2.2680288226475518e-08 +4.246004128806268e-08 +4.294779207300098e-08 +4.5546883281839853e-08 +4.601137653145591e-08 +4.722208328187057e-08 +4.455971185325033e-08 +4.071482213575439e-08 +3.919609686100126e-08 +3.429220855635876e-08 +2.1552667582812776e-08 +2.1880491994121763e-08 +2.5024779278323846e-08 +2.340957221393002e-08 +2.5545895997328686e-08 +2.139980887009411e-08 +2.387579128772193e-08 +2.838084984353452e-08 +2.9053592543703837e-08 +2.755722080113323e-08 +2.476163218255764e-08 +1.836424850897095e-08 +1.2363311303209424e-08 +7.770235714428189e-09 +2.177176507104285e-08 +4.137581279510718e-08 +4.087762488301012e-08 +3.5789155573654655e-08 +3.893122394105921e-08 +4.610629686112798e-08 +5.0537473705793214e-08 +4.701424474183537e-08 +3.453604285777611e-08 +3.2959461382080014e-08 +1.8337785871607828e-08 +2.2063840267280545e-08 +2.6118294348987537e-08 +2.9752715699132674e-08 +2.8454156279956586e-08 +2.885101365829981e-08 +2.9448559733663986e-08 +3.0920030298840104e-08 +2.9067727865525134e-08 +2.4992317347397035e-08 +1.9460475589053846e-08 +1.2290087048890972e-08 +7.487447095898671e-09 +6.9106930927483785e-09 +2.7016544741468683e-08 +5.6372403062258135e-08 +5.895826295241544e-08 +4.810595180621959e-08 +4.0753612088659346e-08 +4.026668312475717e-08 +3.558205667255196e-08 +3.137663406650939e-08 +3.199579403512357e-08 +2.896097331293291e-08 +1.9402290659696418e-08 +3.229707362696583e-08 +3.89763419159423e-08 +3.912994026759346e-08 +3.452009952967534e-08 +3.3933976766713263e-08 +3.4867318917436816e-08 +3.6627002119980855e-08 +3.439986711209072e-08 +3.037080730039989e-08 +2.4728841523216376e-08 +1.7694053454013604e-08 +1.013412174272899e-08 +4.7832449765398245e-09 +1.0727805259223392e-08 +2.404615478850998e-08 +3.262908932555904e-08 +2.8356359576658083e-08 +2.323698979634444e-08 +2.0556949215447575e-08 +2.0447811381850597e-08 +2.5025436735152743e-08 +2.3343086892107763e-08 +3.100508877607871e-08 +1.9600102983090943e-08 +3.043786789694743e-08 +3.985486860355653e-08 +3.834370408233572e-08 +3.5027163108962506e-08 +3.3358866405635216e-08 +3.327208210422075e-08 +3.7117300550131134e-08 +3.7325714364891624e-08 +3.167207872899518e-08 +2.406078320295295e-08 +1.5800084694167263e-08 +9.56049065951596e-09 +5.596519073885978e-09 +9.346652825917062e-09 +2.194319693917786e-08 +3.243579701786319e-08 +2.578570337566904e-08 +2.070635627981452e-08 +2.4616087677060465e-08 +2.3595139403886328e-08 +2.090145659378984e-08 +2.7129216405520988e-08 +3.158792425489631e-08 +1.704070573029676e-08 +3.400605047158115e-08 +3.777007299912269e-08 +3.6565201178064495e-08 +3.571888987506624e-08 +3.383198877613055e-08 +3.9566080691463313e-08 +4.2673386029039914e-08 +3.959131059727225e-08 +3.4407016955104984e-08 +2.5515570801095793e-08 +1.8369425981498515e-08 +1.0952819858913546e-08 +8.651227865150779e-09 +2.9775397959729636e-08 +6.173462095874578e-08 +6.557737394154779e-08 +4.779612527560166e-08 +4.20688544748687e-08 +3.827804058154959e-08 +3.9422426374349226e-08 +3.1413451648927644e-08 +3.092997433337718e-08 +2.8827180848252276e-08 +1.864112001604039e-08 +3.3595468681934686e-08 +3.6086408242419924e-08 +3.5647309262820034e-08 +3.416983940408022e-08 +3.47842328106849e-08 +3.695170361135258e-08 +4.0468029278607005e-08 +3.875740879191945e-08 +3.374084882322463e-08 +2.721920580897633e-08 +2.071202684496376e-08 +1.1522341836945966e-08 +9.784354709755546e-09 +2.9650398980135508e-08 +5.7775333753021683e-08 +6.211742519737132e-08 +4.822873186901619e-08 +3.8035767740100873e-08 +4.283725714364261e-08 +3.60714510995625e-08 +3.145059795976035e-08 +2.9009871664582158e-08 +2.812000384666945e-08 +2.142232676648385e-08 +2.8621150314496537e-08 +3.1909667190538e-08 +3.2843502433883223e-08 +3.1474512951911494e-08 +2.9804819152822796e-08 +3.118350612302076e-08 +3.568807158621167e-08 +3.618995769297127e-08 +3.4015337049289326e-08 +2.8976423548412e-08 +2.0906551884213795e-08 +1.385319065959467e-08 +8.923497174417939e-09 +2.2680288226475518e-08 +4.246004128806268e-08 +4.294779207300098e-08 +4.5546883281839853e-08 +4.601137653145591e-08 +4.722208328187057e-08 +4.455971185325033e-08 +4.071482213575439e-08 +3.919609686100126e-08 +3.429220855635876e-08 +2.1552667582812776e-08 +2.1880491994121763e-08 +2.5024779278323846e-08 +2.340957221393002e-08 +2.5545895997328686e-08 +2.139980887009411e-08 +2.387579128772193e-08 +2.838084984353452e-08 +2.9053592543703837e-08 +2.755722080113323e-08 +2.476163218255764e-08 +1.836424850897095e-08 +1.2363311303209424e-08 +7.770235714428189e-09 +2.177176507104285e-08 +4.137581279510718e-08 +4.087762488301012e-08 +3.5789155573654655e-08 +3.893122394105921e-08 +4.610629686112798e-08 +5.0537473705793214e-08 +4.701424474183537e-08 +3.453604285777611e-08 +3.2959461382080014e-08 +1.8337785871607828e-08 +2.2063840267280545e-08 +2.6118294348987537e-08 +2.9752715699132674e-08 +2.8454156279956586e-08 +2.885101365829981e-08 +2.9448559733663986e-08 +3.0920030298840104e-08 +2.9067727865525134e-08 +2.4992317347397035e-08 +1.9460475589053846e-08 +1.2290087048890972e-08 +7.487447095898671e-09 +6.9106930927483785e-09 +2.7016544741468683e-08 +5.6372403062258135e-08 +5.895826295241544e-08 +4.810595180621959e-08 +4.0753612088659346e-08 +4.026668312475717e-08 +3.558205667255196e-08 +3.137663406650939e-08 +3.199579403512357e-08 +2.896097331293291e-08 +1.9402290659696418e-08 +3.229707362696583e-08 +3.89763419159423e-08 +3.912994026759346e-08 +3.452009952967534e-08 +3.3933976766713263e-08 +3.4867318917436816e-08 +3.6627002119980855e-08 +3.439986711209072e-08 +3.037080730039989e-08 +2.4728841523216376e-08 +1.7694053454013604e-08 +1.013412174272899e-08 +4.7832449765398245e-09 +1.0727805259223392e-08 +2.404615478850998e-08 +3.262908932555904e-08 +2.8356359576658083e-08 +2.323698979634444e-08 +2.0556949215447575e-08 +2.0447811381850597e-08 +2.5025436735152743e-08 +2.3343086892107763e-08 +3.100508877607871e-08 +1.9600102983090943e-08 +3.043786789694743e-08 +3.985486860355653e-08 +3.834370408233572e-08 +3.5027163108962506e-08 +3.3358866405635216e-08 +3.327208210422075e-08 +3.7117300550131134e-08 +3.7325714364891624e-08 +3.167207872899518e-08 +2.406078320295295e-08 +1.5800084694167263e-08 +9.56049065951596e-09 +5.596519073885978e-09 +9.346652825917062e-09 +2.194319693917786e-08 +3.243579701786319e-08 +2.578570337566904e-08 +2.070635627981452e-08 +2.4616087677060465e-08 +2.3595139403886328e-08 +2.090145659378984e-08 +2.7129216405520988e-08 +3.158792425489631e-08 +1.704070573029676e-08 +3.400605047158115e-08 +3.777007299912269e-08 +3.6565201178064495e-08 +3.571888987506624e-08 +3.383198877613055e-08 +3.9566080691463313e-08 +4.2673386029039914e-08 +3.959131059727225e-08 +3.4407016955104984e-08 +2.5515570801095793e-08 +1.8369425981498515e-08 +1.0952819858913546e-08 +8.651227865150779e-09 +2.9775397959729636e-08 +6.173462095874578e-08 +6.557737394154779e-08 +4.779612527560166e-08 +4.20688544748687e-08 +3.827804058154959e-08 +3.9422426374349226e-08 +3.1413451648927644e-08 +3.092997433337718e-08 +2.8827180848252276e-08 +1.864112001604039e-08 +3.3595468681934686e-08 +3.6086408242419924e-08 +3.5647309262820034e-08 +3.416983940408022e-08 +3.47842328106849e-08 +3.695170361135258e-08 +4.0468029278607005e-08 +3.116452205708635e-08 +2.7712955887478314e-08 +2.2159253689574285e-08 +1.5708944741261353e-08 +9.776629592015998e-09 +7.873702982875927e-09 +2.694274521242495e-08 +5.4338560362063856e-08 +6.030646036217327e-08 +4.8049903611556076e-08 +3.6315531947290684e-08 +3.7234574411985714e-08 +3.790592001639363e-08 +2.981952974936937e-08 +3.113805941972322e-08 +2.882487974935114e-08 +1.607473728443917e-08 +2.7521800314476386e-08 +3.155768124076702e-08 +3.1090804710146216e-08 +3.0758049372620496e-08 +2.7969035322333877e-08 +2.953986405077712e-08 +3.366828202573508e-08 +3.55175437212164e-08 +3.321512990641751e-08 +2.69134062014354e-08 +1.890213037711268e-08 +1.0104536185428604e-08 +6.50849387767036e-09 +2.2574191130712194e-08 +4.336560588776533e-08 +4.536402810130275e-08 +4.481603783441672e-08 +4.3578046625602815e-08 +4.525604081715634e-08 +4.216977409810446e-08 +4.1514125275486475e-08 +4.068745549525153e-08 +3.1703225746264195e-08 +2.0617846154224202e-08 +2.7703587127666528e-08 +2.81338104400763e-08 +2.5606628571898097e-08 +2.6258168289335473e-08 +2.450752511818877e-08 +2.5191691130760187e-08 +2.994485745737795e-08 +3.177760055003322e-08 +2.9608814835707747e-08 +2.6286028022460002e-08 +2.063247456866717e-08 +1.4629236264004505e-08 +9.763727001748886e-09 +2.305298406635677e-08 +4.3068764129518125e-08 +4.19042437213335e-08 +3.822125274795357e-08 +3.5527816484167924e-08 +4.469161412954788e-08 +4.704974741059582e-08 +4.5236317112289425e-08 +4.7123711303846795e-08 +3.67669582424324e-08 +1.824072880724184e-08 +2.3120291209215144e-08 +2.4045086421163025e-08 +2.7504213344303376e-08 +2.8553267896912878e-08 +2.828247786551074e-08 +2.8571841052329234e-08 +2.793040973363615e-08 +2.7335575667691172e-08 +2.3896418995728587e-08 +1.8274670016033672e-08 +1.208701507086527e-08 +7.1074370487959426e-09 +6.188969858826196e-09 +2.7515307928291022e-08 +6.05103541612351e-08 +6.63923738630698e-08 +5.330528477334789e-08 +3.7333192936320334e-08 +3.609388681384863e-08 +3.9872537755833145e-08 +2.900420109943292e-08 +2.9491458791749545e-08 +2.7738678885908928e-08 +1.989793092658149e-08 +3.4442437441761837e-08 +4.1444845762141405e-08 +3.640650753598937e-08 +3.3007784459003975e-08 +3.2866595604998245e-08 +3.4616006044590765e-08 +3.5180761460613674e-08 +3.2131723234498114e-08 +2.876874937258402e-08 +2.292880690779876e-08 +1.5584356672185283e-08 +7.445945133574518e-09 +4.269606828963688e-09 +1.1591456986083812e-08 +2.9496800628484337e-08 +3.534101656265743e-08 +2.9187713736798922e-08 +1.875370949798908e-08 +1.8645886578049896e-08 +2.3612808556162948e-08 +1.853403673503372e-08 +2.0536650235855366e-08 +3.230734638991735e-08 +1.8447663344137313e-08 +3.3017153218815765e-08 +3.785357001639267e-08 +3.52112510210538e-08 +3.275869050295545e-08 +3.3119634302020156e-08 +3.322984050296409e-08 +3.5108934302056627e-08 +3.2724831476267236e-08 +2.8832276138676232e-08 +2.2515266562422256e-08 +1.4520509340925589e-08 +8.604219701884611e-09 +5.042693877643483e-09 +9.83275996878312e-09 +2.3222114835590635e-08 +2.8199063030344373e-08 +2.0741201491746084e-08 +1.8631093799399702e-08 +2.028073516520703e-08 +2.561550423908821e-08 +2.914349976505557e-08 +2.331736389367715e-08 +2.7749033830964064e-08 +1.7195783359812946e-08 +2.7794316170054377e-08 +2.926184199425711e-08 +2.9140705573532753e-08 +2.781231405074544e-08 +2.8889392700686698e-08 +3.1258374019411455e-08 +3.417214050298137e-08 +3.204888367405703e-08 +2.8724206672426217e-08 +2.1706430298671167e-08 +1.45853510206756e-08 +8.627559419310472e-09 +6.644340894941298e-09 +2.752064976502581e-08 +5.572069898061353e-08 +5.822207566825751e-08 +4.29937318689202e-08 +3.3939318603448055e-08 +3.6117883988103385e-08 +3.583164372122215e-08 +3.194525204140207e-08 +3.135600635850273e-08 +2.7335575667691172e-08 +2.003575031433912e-08 +2.7185675510702556e-08 +3.264404646841646e-08 +3.432064356420858e-08 +2.9538466955015714e-08 +2.8521216876504126e-08 +3.034935777135711e-08 +3.180677519681554e-08 +3.116452205708635e-08 +2.7712955887478314e-08 +2.2159253689574285e-08 +1.5708944741261353e-08 +9.776629592015998e-09 +7.873702982875927e-09 +2.694274521242495e-08 +5.4338560362063856e-08 +6.030646036217327e-08 +4.8049903611556076e-08 +3.6315531947290684e-08 +3.7234574411985714e-08 +3.790592001639363e-08 +2.981952974936937e-08 +3.113805941972322e-08 +2.882487974935114e-08 +1.607473728443917e-08 +2.7521800314476386e-08 +3.155768124076702e-08 +3.1090804710146216e-08 +3.0758049372620496e-08 +2.7969035322333877e-08 +2.953986405077712e-08 +3.366828202573508e-08 +3.55175437212164e-08 +3.321512990641751e-08 +2.69134062014354e-08 +1.890213037711268e-08 +1.0104536185428604e-08 +6.50849387767036e-09 +2.2574191130712194e-08 +4.336560588776533e-08 +4.536402810130275e-08 +4.481603783441672e-08 +4.3578046625602815e-08 +4.525604081715634e-08 +4.216977409810446e-08 +4.1514125275486475e-08 +4.068745549525153e-08 +3.1703225746264195e-08 +2.0617846154224202e-08 +2.7703587127666528e-08 +2.81338104400763e-08 +2.5606628571898097e-08 +2.6258168289335473e-08 +2.450752511818877e-08 +2.5191691130760187e-08 +2.994485745737795e-08 +3.177760055003322e-08 +2.9608814835707747e-08 +2.6286028022460002e-08 +2.063247456866717e-08 +1.4629236264004505e-08 +9.763727001748886e-09 +2.305298406635677e-08 +4.3068764129518125e-08 +4.19042437213335e-08 +3.822125274795357e-08 +3.5527816484167924e-08 +4.469161412954788e-08 +4.704974741059582e-08 +4.5236317112289425e-08 +4.7123711303846795e-08 +3.67669582424324e-08 +1.824072880724184e-08 +2.3120291209215144e-08 +2.4045086421163025e-08 +2.7504213344303376e-08 +2.8553267896912878e-08 +2.828247786551074e-08 +2.8571841052329234e-08 +2.793040973363615e-08 +2.7335575667691172e-08 +2.3896418995728587e-08 +1.8274670016033672e-08 +1.208701507086527e-08 +7.1074370487959426e-09 +6.188969858826196e-09 +2.7515307928291022e-08 +6.05103541612351e-08 +6.63923738630698e-08 +5.330528477334789e-08 +3.7333192936320334e-08 +3.609388681384863e-08 +3.9872537755833145e-08 +2.900420109943292e-08 +2.9491458791749545e-08 +2.7738678885908928e-08 +1.989793092658149e-08 +3.4442437441761837e-08 +4.1444845762141405e-08 +3.640650753598937e-08 +3.3007784459003975e-08 +3.2866595604998245e-08 +3.4616006044590765e-08 +3.5180761460613674e-08 +3.2131723234498114e-08 +2.876874937258402e-08 +2.292880690779876e-08 +1.5584356672185283e-08 +7.445945133574518e-09 +4.269606828963688e-09 +1.1591456986083812e-08 +2.9496800628484337e-08 +3.534101656265743e-08 +2.9187713736798922e-08 +1.875370949798908e-08 +1.8645886578049896e-08 +2.3612808556162948e-08 +1.853403673503372e-08 +2.0536650235855366e-08 +3.230734638991735e-08 +1.8447663344137313e-08 +3.3017153218815765e-08 +3.785357001639267e-08 +3.52112510210538e-08 +3.275869050295545e-08 +3.3119634302020156e-08 +3.322984050296409e-08 +3.5108934302056627e-08 +3.2724831476267236e-08 +2.8832276138676232e-08 +2.2515266562422256e-08 +1.4520509340925589e-08 +8.604219701884611e-09 +5.042693877643483e-09 +9.83275996878312e-09 +2.3222114835590635e-08 +2.8199063030344373e-08 +2.0741201491746084e-08 +1.8631093799399702e-08 +2.028073516520703e-08 +2.561550423908821e-08 +2.914349976505557e-08 +2.331736389367715e-08 +2.7749033830964064e-08 +1.7195783359812946e-08 +2.7794316170054377e-08 +2.926184199425711e-08 +2.9140705573532753e-08 +2.781231405074544e-08 +2.8889392700686698e-08 +3.1258374019411455e-08 +3.417214050298137e-08 +3.204888367405703e-08 +2.8724206672426217e-08 +2.1706430298671167e-08 +1.45853510206756e-08 +8.627559419310472e-09 +6.644340894941298e-09 +2.752064976502581e-08 +5.572069898061353e-08 +5.822207566825751e-08 +4.29937318689202e-08 +3.3939318603448055e-08 +3.6117883988103385e-08 +3.583164372122215e-08 +3.194525204140207e-08 +3.135600635850273e-08 +2.7335575667691172e-08 +2.003575031433912e-08 +2.7185675510702556e-08 +3.264404646841646e-08 +3.432064356420858e-08 +2.9538466955015714e-08 +2.8521216876504126e-08 +3.034935777135711e-08 +3.180677519681554e-08 +3.116452205708635e-08 +2.7712955887478314e-08 +2.2159253689574285e-08 +1.5708944741261353e-08 +9.776629592015998e-09 +7.873702982875927e-09 +2.694274521242495e-08 +5.4338560362063856e-08 +6.030646036217327e-08 +4.8049903611556076e-08 +3.6315531947290684e-08 +3.7234574411985714e-08 +3.790592001639363e-08 +2.981952974936937e-08 +3.113805941972322e-08 +2.882487974935114e-08 +1.607473728443917e-08 +2.7521800314476386e-08 +3.155768124076702e-08 +3.1090804710146216e-08 +3.0758049372620496e-08 +2.7969035322333877e-08 +2.953986405077712e-08 +3.366828202573508e-08 +3.55175437212164e-08 +3.321512990641751e-08 +2.69134062014354e-08 +1.890213037711268e-08 +1.0104536185428604e-08 +6.50849387767036e-09 +2.2574191130712194e-08 +4.336560588776533e-08 +4.536402810130275e-08 +4.481603783441672e-08 +4.3578046625602815e-08 +4.525604081715634e-08 +4.216977409810446e-08 +4.1514125275486475e-08 +4.068745549525153e-08 +3.1703225746264195e-08 +2.0617846154224202e-08 +2.7703587127666528e-08 +2.81338104400763e-08 +2.5606628571898097e-08 +2.6258168289335473e-08 +2.450752511818877e-08 +2.5191691130760187e-08 +2.994485745737795e-08 +3.177760055003322e-08 +2.9608814835707747e-08 +2.6286028022460002e-08 +2.063247456866717e-08 +1.4629236264004505e-08 +9.763727001748886e-09 +2.305298406635677e-08 +4.3068764129518125e-08 +4.19042437213335e-08 +3.822125274795357e-08 +3.5527816484167924e-08 +4.469161412954788e-08 +4.704974741059582e-08 +4.5236317112289425e-08 +4.7123711303846795e-08 +3.67669582424324e-08 +1.824072880724184e-08 +2.3120291209215144e-08 +2.4045086421163025e-08 +2.7504213344303376e-08 +2.8553267896912878e-08 +2.828247786551074e-08 +2.8571841052329234e-08 +2.793040973363615e-08 +2.7335575667691172e-08 +2.3896418995728587e-08 +1.8274670016033672e-08 +1.208701507086527e-08 +7.1074370487959426e-09 +6.188969858826196e-09 +2.7515307928291022e-08 +6.05103541612351e-08 +6.63923738630698e-08 +5.330528477334789e-08 +3.7333192936320334e-08 +3.609388681384863e-08 +3.9872537755833145e-08 +2.900420109943292e-08 +2.9491458791749545e-08 +2.7738678885908928e-08 +1.989793092658149e-08 +3.4442437441761837e-08 +4.1444845762141405e-08 +3.640650753598937e-08 +3.3007784459003975e-08 +3.2866595604998245e-08 +3.4616006044590765e-08 +3.5180761460613674e-08 +3.2131723234498114e-08 +2.876874937258402e-08 +2.292880690779876e-08 +1.5584356672185283e-08 +7.445945133574518e-09 +4.269606828963688e-09 +1.1591456986083812e-08 +2.9496800628484337e-08 +3.534101656265743e-08 +2.9187713736798922e-08 +1.875370949798908e-08 +1.8645886578049896e-08 +2.3612808556162948e-08 +1.853403673503372e-08 +2.0536650235855366e-08 +3.230734638991735e-08 +1.8447663344137313e-08 +3.3017153218815765e-08 +3.785357001639267e-08 +3.52112510210538e-08 +3.275869050295545e-08 +3.3119634302020156e-08 +3.322984050296409e-08 +3.5108934302056627e-08 +3.2724831476267236e-08 +2.8832276138676232e-08 +2.2515266562422256e-08 +1.4520509340925589e-08 +8.604219701884611e-09 +5.042693877643483e-09 +9.83275996878312e-09 +2.3222114835590635e-08 +2.8199063030344373e-08 +2.0741201491746084e-08 +1.8631093799399702e-08 +2.028073516520703e-08 +2.561550423908821e-08 +2.914349976505557e-08 +2.331736389367715e-08 +2.7749033830964064e-08 +1.7195783359812946e-08 +2.7794316170054377e-08 +2.926184199425711e-08 +2.9140705573532753e-08 +2.781231405074544e-08 +2.8889392700686698e-08 +3.1258374019411455e-08 +3.417214050298137e-08 +3.204888367405703e-08 +2.8724206672426217e-08 +2.1706430298671167e-08 +1.45853510206756e-08 +8.627559419310472e-09 +6.644340894941298e-09 +2.752064976502581e-08 +5.572069898061353e-08 +5.822207566825751e-08 +4.29937318689202e-08 +3.3939318603448055e-08 +3.6117883988103385e-08 +3.583164372122215e-08 +3.194525204140207e-08 +3.135600635850273e-08 +2.7335575667691172e-08 +2.003575031433912e-08 +2.7185675510702556e-08 +3.264404646841646e-08 +3.432064356420858e-08 +2.9538466955015714e-08 +2.8521216876504126e-08 +3.034935777135711e-08 +3.180677519681554e-08 +3.116452205708635e-08 +2.7712955887478314e-08 +2.2159253689574285e-08 +1.5708944741261353e-08 +9.776629592015998e-09 +7.873702982875927e-09 +2.694274521242495e-08 +5.4338560362063856e-08 +6.030646036217327e-08 +4.8049903611556076e-08 +3.6315531947290684e-08 +3.7234574411985714e-08 +3.790592001639363e-08 +2.981952974936937e-08 +3.113805941972322e-08 +2.882487974935114e-08 +1.607473728443917e-08 +2.7521800314476386e-08 +3.155768124076702e-08 +3.1090804710146216e-08 +3.0758049372620496e-08 +2.7969035322333877e-08 +2.953986405077712e-08 +3.366828202573508e-08 +3.55175437212164e-08 +3.321512990641751e-08 +2.69134062014354e-08 +1.890213037711268e-08 +1.0104536185428604e-08 +6.50849387767036e-09 +2.2574191130712194e-08 +4.336560588776533e-08 +4.536402810130275e-08 +4.481603783441672e-08 +4.3578046625602815e-08 +4.525604081715634e-08 +4.216977409810446e-08 +4.1514125275486475e-08 +4.068745549525153e-08 +3.1703225746264195e-08 +2.0617846154224202e-08 +2.7703587127666528e-08 +2.81338104400763e-08 +2.5606628571898097e-08 +2.6258168289335473e-08 +2.450752511818877e-08 +2.5191691130760187e-08 +2.994485745737795e-08 +3.177760055003322e-08 +2.9608814835707747e-08 +2.6286028022460002e-08 +2.063247456866717e-08 +1.4629236264004505e-08 +9.763727001748886e-09 +2.305298406635677e-08 +4.3068764129518125e-08 +4.19042437213335e-08 +3.822125274795357e-08 +3.5527816484167924e-08 +4.469161412954788e-08 +4.704974741059582e-08 +4.5236317112289425e-08 +4.7123711303846795e-08 +3.67669582424324e-08 +1.824072880724184e-08 +2.3120291209215144e-08 +2.4045086421163025e-08 +2.7504213344303376e-08 +2.8553267896912878e-08 +2.828247786551074e-08 +2.8571841052329234e-08 +2.793040973363615e-08 +2.7335575667691172e-08 +2.3896418995728587e-08 +1.8274670016033672e-08 +1.208701507086527e-08 +7.1074370487959426e-09 +6.188969858826196e-09 +2.7515307928291022e-08 +6.05103541612351e-08 +6.63923738630698e-08 +5.330528477334789e-08 +3.7333192936320334e-08 +3.609388681384863e-08 +3.9872537755833145e-08 +2.900420109943292e-08 +2.9491458791749545e-08 +2.7738678885908928e-08 +1.989793092658149e-08 +3.4442437441761837e-08 +4.1444845762141405e-08 +3.640650753598937e-08 +3.3007784459003975e-08 +3.2866595604998245e-08 +3.4616006044590765e-08 +3.5180761460613674e-08 +3.2131723234498114e-08 +2.876874937258402e-08 +2.292880690779876e-08 +1.5584356672185283e-08 +7.445945133574518e-09 +4.269606828963688e-09 +1.1591456986083812e-08 +2.9496800628484337e-08 +3.534101656265743e-08 +2.9187713736798922e-08 +1.875370949798908e-08 +1.8645886578049896e-08 +2.3612808556162948e-08 +1.853403673503372e-08 +2.0536650235855366e-08 +3.230734638991735e-08 +1.8447663344137313e-08 +3.3017153218815765e-08 +3.785357001639267e-08 +3.52112510210538e-08 +3.275869050295545e-08 +3.3119634302020156e-08 +3.322984050296409e-08 +3.5108934302056627e-08 +3.2724831476267236e-08 +2.8832276138676232e-08 +2.2515266562422256e-08 +1.4520509340925589e-08 +8.604219701884611e-09 +5.042693877643483e-09 +9.83275996878312e-09 +2.3222114835590635e-08 +2.8199063030344373e-08 +2.0741201491746084e-08 +1.8631093799399702e-08 +2.028073516520703e-08 +2.561550423908821e-08 +2.914349976505557e-08 +2.331736389367715e-08 +2.7749033830964064e-08 +1.7195783359812946e-08 +2.7794316170054377e-08 +2.926184199425711e-08 +2.9140705573532753e-08 +2.781231405074544e-08 +2.8889392700686698e-08 +3.1258374019411455e-08 +3.417214050298137e-08 +3.204888367405703e-08 +2.8724206672426217e-08 +2.1706430298671167e-08 +1.45853510206756e-08 +8.627559419310472e-09 +6.644340894941298e-09 +2.752064976502581e-08 +5.572069898061353e-08 +5.822207566825751e-08 +4.29937318689202e-08 +3.3939318603448055e-08 +3.6117883988103385e-08 +3.583164372122215e-08 +3.194525204140207e-08 +3.135600635850273e-08 +2.7335575667691172e-08 +2.003575031433912e-08 +2.7185675510702556e-08 +3.264404646841646e-08 +3.432064356420858e-08 +2.9538466955015714e-08 +2.8521216876504126e-08 +3.034935777135711e-08 +3.180677519681554e-08 +3.116452205708635e-08 +2.7712955887478314e-08 +2.2159253689574285e-08 +1.5708944741261353e-08 +9.776629592015998e-09 +7.873702982875927e-09 +2.694274521242495e-08 +5.4338560362063856e-08 +6.030646036217327e-08 +4.8049903611556076e-08 +3.6315531947290684e-08 +3.7234574411985714e-08 +3.790592001639363e-08 +2.981952974936937e-08 +3.113805941972322e-08 +2.882487974935114e-08 +1.607473728443917e-08 +2.7521800314476386e-08 +3.155768124076702e-08 +3.1090804710146216e-08 +3.0758049372620496e-08 +2.7969035322333877e-08 +2.953986405077712e-08 +3.366828202573508e-08 +3.55175437212164e-08 +3.321512990641751e-08 +2.69134062014354e-08 +1.890213037711268e-08 +1.0104536185428604e-08 +6.50849387767036e-09 +2.2574191130712194e-08 +4.336560588776533e-08 +4.536402810130275e-08 +4.481603783441672e-08 +4.3578046625602815e-08 +4.525604081715634e-08 +4.216977409810446e-08 +4.1514125275486475e-08 +4.068745549525153e-08 +3.1703225746264195e-08 +2.0617846154224202e-08 +2.7703587127666528e-08 +2.81338104400763e-08 +2.5606628571898097e-08 +2.6258168289335473e-08 +2.450752511818877e-08 +2.5191691130760187e-08 +2.994485745737795e-08 +3.177760055003322e-08 +2.9608814835707747e-08 +2.6286028022460002e-08 +2.063247456866717e-08 +1.4629236264004505e-08 +9.763727001748886e-09 +2.305298406635677e-08 +4.3068764129518125e-08 +4.19042437213335e-08 +3.822125274795357e-08 +3.5527816484167924e-08 +4.469161412954788e-08 +4.704974741059582e-08 +4.5236317112289425e-08 +4.7123711303846795e-08 +3.67669582424324e-08 +1.824072880724184e-08 +2.3120291209215144e-08 +2.4045086421163025e-08 +2.7504213344303376e-08 +2.8553267896912878e-08 +2.828247786551074e-08 +2.8571841052329234e-08 +2.793040973363615e-08 +3.1025634301981756e-08 +2.6760218760302295e-08 +2.2533757535735002e-08 +1.590396287313306e-08 +1.003427048684019e-08 +7.899179434995702e-09 +2.749040675089653e-08 +5.447744811716844e-08 +5.961300777189369e-08 +4.3419024255113235e-08 +3.5198841523408355e-08 +3.470147543234743e-08 +3.3943098980214214e-08 +2.8277218210879558e-08 +3.1402685793354447e-08 +3.0633461303544426e-08 +2.518339073829535e-08 +3.277340109950203e-08 +3.462734717488924e-08 +3.1824690895403e-08 +2.9802928964439717e-08 +3.016543422347305e-08 +3.286199340719596e-08 +3.3241756907987856e-08 +3.077662252803685e-08 +2.7904358006791088e-08 +2.149267464717588e-08 +1.368586789664027e-08 +8.776966483677418e-09 +4.652082339174782e-09 +1.0778347252944883e-08 +2.754859168025395e-08 +3.360730290485484e-08 +2.4996837363095704e-08 +2.3507533281435744e-08 +2.1651614835561842e-08 +2.2543783752375682e-08 +2.707177111509607e-08 +2.8545049686551657e-08 +2.5517214443168037e-08 +1.8812387519968176e-08 +2.989439764576008e-08 +3.5918838933154685e-08 +3.512635690802241e-08 +3.037606695503107e-08 +3.149851012616625e-08 +3.200779262225094e-08 +3.583041098966797e-08 +3.327339701787854e-08 +3.069707025174025e-08 +2.4261225353663063e-08 +1.5116247410010296e-08 +9.481431475841041e-09 +5.7983583203574965e-09 +7.869511695591705e-09 +2.4811681083657456e-08 +3.1588992622243264e-08 +2.5520830455726975e-08 +1.7072921114912736e-08 +2.2004915698990607e-08 +2.6421792857627324e-08 +2.8400655730505056e-08 +2.714967974932042e-08 +3.3682746075970825e-08 +2.1324201334770907e-08 +3.013198610730289e-08 +3.5399365856222076e-08 +3.351903932557536e-08 +3.164158916855506e-08 +3.432828649984451e-08 +3.666053241825462e-08 +4.026446420795964e-08 +4.034960486730186e-08 +3.498985243392258e-08 +2.6395494584471426e-08 +1.932249183708899e-08 +1.1729769466463114e-08 +9.758713893428543e-09 +3.1462514364784115e-08 +6.33734142868763e-08 +6.680369529164877e-08 +4.7293335165702345e-08 +3.94405064371439e-08 +3.896606915299077e-08 +3.5454016955124184e-08 +3.3725809498263606e-08 +3.2702067033566654e-08 +2.9917572998978706e-08 +1.8326691287620182e-08 +3.25930935641769e-08 +3.849352205722073e-08 +3.799163595046113e-08 +3.501121978086174e-08 +3.324151036167702e-08 +3.558419340724588e-08 +4.118194521268604e-08 +4.207419631160349e-08 +3.622077598182584e-08 +2.9575941994262868e-08 +2.0777115071024614e-08 +1.2422811146224645e-08 +1.1035823783561849e-08 +2.9043812873373986e-08 +6.300753956159486e-08 +6.216081734807855e-08 +4.660785423947313e-08 +4.077793799132855e-08 +3.9790520016428185e-08 +3.91308442707332e-08 +3.4584941209425355e-08 +2.9744744035082292e-08 +2.741471703346971e-08 +1.9574708713074777e-08 +3.0307116170100454e-08 +3.5142628964537626e-08 +2.880088257509638e-08 +2.827869748874458e-08 +2.8987189403985195e-08 +3.233701412932134e-08 +3.624477315608059e-08 +3.479623139781228e-08 +3.3419434615997394e-08 +2.912698116222952e-08 +2.200992880731095e-08 +1.3124481946865455e-08 +8.851341287446441e-09 +2.3984846939215295e-08 +4.359251067583856e-08 +3.867826742614091e-08 +3.842679018908764e-08 +4.2116684459171e-08 +4.672430628029158e-08 +4.312629160204665e-08 +4.1689666248802095e-08 +3.897305463179781e-08 +4.015754529116019e-08 +1.8233907692642028e-08 +2.3026521428993645e-08 +2.6492551648837415e-08 +2.678265447458842e-08 +2.445764058129618e-08 +2.541185698633722e-08 +2.777771538512472e-08 +3.302487833655531e-08 +3.4852608320890235e-08 +3.284407770860851e-08 +2.835192174306303e-08 +2.198050761421779e-08 +1.4157346625063356e-08 +9.793476923256496e-09 +2.4993139168433152e-08 +4.2960365934853663e-08 +4.1869151963091106e-08 +3.486592182167541e-08 +3.5335428179611804e-08 +5.16356731563628e-08 +4.9843034930270275e-08 +4.0811961382223994e-08 +3.4305028964522264e-08 +3.679087323458354e-08 +1.95202219783799e-08 +2.1026537755487583e-08 +2.5067678336409405e-08 +2.664245180582603e-08 +2.6832621193584623e-08 +2.8068229121393778e-08 +2.8718947017795038e-08 +3.130661491423181e-08 +3.1025634301981756e-08 +2.6760218760302295e-08 +2.2533757535735002e-08 +1.590396287313306e-08 +1.003427048684019e-08 +7.899179434995702e-09 +2.749040675089653e-08 +5.447744811716844e-08 +5.961300777189369e-08 +4.3419024255113235e-08 +3.5198841523408355e-08 +3.470147543234743e-08 +3.3943098980214214e-08 +2.8277218210879558e-08 +3.1402685793354447e-08 +3.0633461303544426e-08 +2.518339073829535e-08 +3.277340109950203e-08 +3.462734717488924e-08 +3.1824690895403e-08 +2.9802928964439717e-08 +3.016543422347305e-08 +3.286199340719596e-08 +3.3241756907987856e-08 +3.077662252803685e-08 +2.7904358006791088e-08 +2.149267464717588e-08 +1.368586789664027e-08 +8.776966483677418e-09 +4.652082339174782e-09 +1.0778347252944883e-08 +2.754859168025395e-08 +3.360730290485484e-08 +2.4996837363095704e-08 +2.3507533281435744e-08 +2.1651614835561842e-08 +2.2543783752375682e-08 +2.707177111509607e-08 +2.8545049686551657e-08 +2.5517214443168037e-08 +1.8812387519968176e-08 +2.989439764576008e-08 +3.5918838933154685e-08 +3.512635690802241e-08 +3.037606695503107e-08 +3.149851012616625e-08 +3.200779262225094e-08 +3.583041098966797e-08 +3.327339701787854e-08 +3.069707025174025e-08 +2.4261225353663063e-08 +1.5116247410010296e-08 +9.481431475841041e-09 +5.7983583203574965e-09 +7.869511695591705e-09 +2.4811681083657456e-08 +3.1588992622243264e-08 +2.5520830455726975e-08 +1.7072921114912736e-08 +2.2004915698990607e-08 +2.6421792857627324e-08 +2.8400655730505056e-08 +2.714967974932042e-08 +3.3682746075970825e-08 +2.1324201334770907e-08 +3.013198610730289e-08 +3.5399365856222076e-08 +3.351903932557536e-08 +3.164158916855506e-08 +3.432828649984451e-08 +3.666053241825462e-08 +4.026446420795964e-08 +4.034960486730186e-08 +3.498985243392258e-08 +2.6395494584471426e-08 +1.932249183708899e-08 +1.1729769466463114e-08 +9.758713893428543e-09 +3.1462514364784115e-08 +6.33734142868763e-08 +6.680369529164877e-08 +4.7293335165702345e-08 +3.94405064371439e-08 +3.896606915299077e-08 +3.5454016955124184e-08 +3.3725809498263606e-08 +3.2702067033566654e-08 +2.9917572998978706e-08 +1.8326691287620182e-08 +3.25930935641769e-08 +3.849352205722073e-08 +3.799163595046113e-08 +3.501121978086174e-08 +3.324151036167702e-08 +3.558419340724588e-08 +4.118194521268604e-08 +4.207419631160349e-08 +3.622077598182584e-08 +2.9575941994262868e-08 +2.0777115071024614e-08 +1.2422811146224645e-08 +1.1035823783561849e-08 +2.9043812873373986e-08 +6.300753956159486e-08 +6.216081734807855e-08 +4.660785423947313e-08 +4.077793799132855e-08 +3.9790520016428185e-08 +3.91308442707332e-08 +3.4584941209425355e-08 +2.9744744035082292e-08 +2.741471703346971e-08 +1.9574708713074777e-08 +3.0307116170100454e-08 +3.5142628964537626e-08 +2.880088257509638e-08 +2.827869748874458e-08 +2.8987189403985195e-08 +3.233701412932134e-08 +3.624477315608059e-08 +3.479623139781228e-08 +3.3419434615997394e-08 +2.912698116222952e-08 +2.200992880731095e-08 +1.3124481946865455e-08 +8.851341287446441e-09 +2.3984846939215295e-08 +4.359251067583856e-08 +3.867826742614091e-08 +3.842679018908764e-08 +4.2116684459171e-08 +4.672430628029158e-08 +4.312629160204665e-08 +4.1689666248802095e-08 +3.897305463179781e-08 +4.015754529116019e-08 +1.8233907692642028e-08 +2.3026521428993645e-08 +2.6492551648837415e-08 +2.678265447458842e-08 +2.445764058129618e-08 +2.541185698633722e-08 +2.777771538512472e-08 +3.302487833655531e-08 +3.4852608320890235e-08 +3.284407770860851e-08 +2.835192174306303e-08 +2.198050761421779e-08 +1.4157346625063356e-08 +9.793476923256496e-09 +2.4993139168433152e-08 +4.2960365934853663e-08 +4.1869151963091106e-08 +3.486592182167541e-08 +3.5335428179611804e-08 +5.16356731563628e-08 +4.9843034930270275e-08 +4.0811961382223994e-08 +3.4305028964522264e-08 +3.679087323458354e-08 +1.95202219783799e-08 +2.1026537755487583e-08 +2.5067678336409405e-08 +2.664245180582603e-08 +2.6832621193584623e-08 +2.8068229121393778e-08 +2.8718947017795038e-08 +3.130661491423181e-08 +3.1025634301981756e-08 +2.6760218760302295e-08 +2.2533757535735002e-08 +1.590396287313306e-08 +1.003427048684019e-08 +7.899179434995702e-09 +2.749040675089653e-08 +5.447744811716844e-08 +5.961300777189369e-08 +4.3419024255113235e-08 +3.5198841523408355e-08 +3.470147543234743e-08 +3.3943098980214214e-08 +2.8277218210879558e-08 +3.1402685793354447e-08 +3.0633461303544426e-08 +2.518339073829535e-08 +3.277340109950203e-08 +3.462734717488924e-08 +3.1824690895403e-08 +2.9802928964439717e-08 +3.016543422347305e-08 +3.286199340719596e-08 +3.3241756907987856e-08 +3.077662252803685e-08 +2.7904358006791088e-08 +2.149267464717588e-08 +1.368586789664027e-08 +8.776966483677418e-09 +4.652082339174782e-09 +1.0778347252944883e-08 +2.754859168025395e-08 +3.360730290485484e-08 +2.4996837363095704e-08 +2.3507533281435744e-08 +2.1651614835561842e-08 +2.2543783752375682e-08 +2.707177111509607e-08 +2.8545049686551657e-08 +2.5517214443168037e-08 +1.8812387519968176e-08 +2.989439764576008e-08 +3.5918838933154685e-08 +3.512635690802241e-08 +3.037606695503107e-08 +3.149851012616625e-08 +3.200779262225094e-08 +3.583041098966797e-08 +3.327339701787854e-08 +3.069707025174025e-08 +2.4261225353663063e-08 +1.5116247410010296e-08 +9.481431475841041e-09 +5.7983583203574965e-09 +7.869511695591705e-09 +2.4811681083657456e-08 +3.1588992622243264e-08 +2.5520830455726975e-08 +1.7072921114912736e-08 +2.2004915698990607e-08 +2.6421792857627324e-08 +2.8400655730505056e-08 +2.714967974932042e-08 +3.3682746075970825e-08 +2.1324201334770907e-08 +3.013198610730289e-08 +3.5399365856222076e-08 +3.351903932557536e-08 +3.164158916855506e-08 +3.432828649984451e-08 +3.666053241825462e-08 +4.026446420795964e-08 +4.034960486730186e-08 +3.498985243392258e-08 +2.6395494584471426e-08 +1.932249183708899e-08 +1.1729769466463114e-08 +9.758713893428543e-09 +3.1462514364784115e-08 +6.33734142868763e-08 +6.680369529164877e-08 +4.7293335165702345e-08 +3.94405064371439e-08 +3.896606915299077e-08 +3.5454016955124184e-08 +3.3725809498263606e-08 +3.2702067033566654e-08 +2.9917572998978706e-08 +1.8326691287620182e-08 +3.25930935641769e-08 +3.849352205722073e-08 +3.799163595046113e-08 +3.501121978086174e-08 +3.324151036167702e-08 +3.558419340724588e-08 +4.118194521268604e-08 +4.207419631160349e-08 +3.622077598182584e-08 +2.9575941994262868e-08 +2.0777115071024614e-08 +1.2422811146224645e-08 +1.1035823783561849e-08 +2.9043812873373986e-08 +6.300753956159486e-08 +6.216081734807855e-08 +4.660785423947313e-08 +4.077793799132855e-08 +3.9790520016428185e-08 +3.91308442707332e-08 +3.4584941209425355e-08 +2.9744744035082292e-08 +2.741471703346971e-08 +1.9574708713074777e-08 +3.0307116170100454e-08 +3.5142628964537626e-08 +2.880088257509638e-08 +2.827869748874458e-08 +2.8987189403985195e-08 +3.233701412932134e-08 +3.624477315608059e-08 +3.479623139781228e-08 +3.3419434615997394e-08 +2.912698116222952e-08 +2.200992880731095e-08 +1.3124481946865455e-08 +8.851341287446441e-09 +2.3984846939215295e-08 +4.359251067583856e-08 +3.867826742614091e-08 +3.842679018908764e-08 +4.2116684459171e-08 +4.672430628029158e-08 +4.312629160204665e-08 +4.1689666248802095e-08 +3.897305463179781e-08 +4.015754529116019e-08 +1.8233907692642028e-08 +2.3026521428993645e-08 +2.6492551648837415e-08 +2.678265447458842e-08 +2.445764058129618e-08 +2.541185698633722e-08 +2.777771538512472e-08 +3.302487833655531e-08 +3.4852608320890235e-08 +3.284407770860851e-08 +2.835192174306303e-08 +2.198050761421779e-08 +1.4157346625063356e-08 +9.793476923256496e-09 +2.4993139168433152e-08 +4.2960365934853663e-08 +4.1869151963091106e-08 +3.486592182167541e-08 +3.5335428179611804e-08 +5.16356731563628e-08 +4.9843034930270275e-08 +4.0811961382223994e-08 +3.4305028964522264e-08 +3.679087323458354e-08 +1.95202219783799e-08 +2.1026537755487583e-08 +2.5067678336409405e-08 +2.664245180582603e-08 +2.6832621193584623e-08 +2.8068229121393778e-08 +2.8718947017795038e-08 +3.130661491423181e-08 +3.1025634301981756e-08 +2.6760218760302295e-08 +2.2533757535735002e-08 +1.590396287313306e-08 +1.003427048684019e-08 +7.899179434995702e-09 +2.749040675089653e-08 +5.447744811716844e-08 +5.961300777189369e-08 +4.3419024255113235e-08 +3.5198841523408355e-08 +3.470147543234743e-08 +3.3943098980214214e-08 +2.8277218210879558e-08 +3.1402685793354447e-08 +3.0633461303544426e-08 +2.518339073829535e-08 +3.277340109950203e-08 +3.462734717488924e-08 +3.1824690895403e-08 +2.9802928964439717e-08 +3.016543422347305e-08 +3.286199340719596e-08 +3.3241756907987856e-08 +3.077662252803685e-08 +2.7904358006791088e-08 +2.149267464717588e-08 +1.368586789664027e-08 +8.776966483677418e-09 +4.652082339174782e-09 +1.0778347252944883e-08 +2.754859168025395e-08 +3.360730290485484e-08 +2.4996837363095704e-08 +2.3507533281435744e-08 +2.1651614835561842e-08 +2.2543783752375682e-08 +2.707177111509607e-08 +2.8545049686551657e-08 +2.5517214443168037e-08 +1.8812387519968176e-08 +2.989439764576008e-08 +3.5918838933154685e-08 +3.512635690802241e-08 +3.037606695503107e-08 +3.149851012616625e-08 +3.200779262225094e-08 +3.583041098966797e-08 +3.327339701787854e-08 +3.069707025174025e-08 +2.4261225353663063e-08 +1.5116247410010296e-08 +9.481431475841041e-09 +5.7983583203574965e-09 +7.869511695591705e-09 +2.4811681083657456e-08 +3.1588992622243264e-08 +2.5520830455726975e-08 +1.7072921114912736e-08 +2.2004915698990607e-08 +2.6421792857627324e-08 +2.8400655730505056e-08 +2.714967974932042e-08 +3.3682746075970825e-08 +2.1324201334770907e-08 +3.013198610730289e-08 +3.5399365856222076e-08 +3.351903932557536e-08 +3.164158916855506e-08 +3.432828649984451e-08 +3.666053241825462e-08 +4.026446420795964e-08 +4.034960486730186e-08 +3.498985243392258e-08 +2.6395494584471426e-08 +1.932249183708899e-08 +1.1729769466463114e-08 +9.758713893428543e-09 +3.1462514364784115e-08 +6.33734142868763e-08 +6.680369529164877e-08 +4.7293335165702345e-08 +3.94405064371439e-08 +3.896606915299077e-08 +3.5454016955124184e-08 +3.3725809498263606e-08 +3.2702067033566654e-08 +2.9917572998978706e-08 +1.8326691287620182e-08 +3.25930935641769e-08 +3.849352205722073e-08 +3.799163595046113e-08 +3.501121978086174e-08 +3.324151036167702e-08 +3.558419340724588e-08 +4.118194521268604e-08 +4.207419631160349e-08 +3.622077598182584e-08 +2.9575941994262868e-08 +2.0777115071024614e-08 +1.2422811146224645e-08 +1.1035823783561849e-08 +2.9043812873373986e-08 +6.300753956159486e-08 +6.216081734807855e-08 +4.660785423947313e-08 +4.077793799132855e-08 +3.9790520016428185e-08 +3.91308442707332e-08 +3.4584941209425355e-08 +2.9744744035082292e-08 +2.741471703346971e-08 +1.9574708713074777e-08 +3.0307116170100454e-08 +3.5142628964537626e-08 +2.880088257509638e-08 +2.827869748874458e-08 +2.8987189403985195e-08 +3.233701412932134e-08 +3.624477315608059e-08 +3.479623139781228e-08 +3.3419434615997394e-08 +2.912698116222952e-08 +2.200992880731095e-08 +1.3124481946865455e-08 +8.851341287446441e-09 +2.3984846939215295e-08 +4.359251067583856e-08 +3.867826742614091e-08 +3.842679018908764e-08 +4.2116684459171e-08 +4.672430628029158e-08 +4.312629160204665e-08 +4.1689666248802095e-08 +3.897305463179781e-08 +4.015754529116019e-08 +1.8233907692642028e-08 +2.3026521428993645e-08 +2.6492551648837415e-08 +2.678265447458842e-08 +2.445764058129618e-08 +2.541185698633722e-08 +2.777771538512472e-08 +3.302487833655531e-08 +3.4852608320890235e-08 +3.284407770860851e-08 +2.835192174306303e-08 +2.198050761421779e-08 +1.4157346625063356e-08 +9.793476923256496e-09 +2.4993139168433152e-08 +4.2960365934853663e-08 +4.1869151963091106e-08 +3.486592182167541e-08 +3.5335428179611804e-08 +5.16356731563628e-08 +4.9843034930270275e-08 +4.0811961382223994e-08 +3.4305028964522264e-08 +3.679087323458354e-08 +1.95202219783799e-08 +2.1026537755487583e-08 +2.5067678336409405e-08 +2.664245180582603e-08 +2.6832621193584623e-08 +2.8068229121393778e-08 +2.8718947017795038e-08 +3.130661491423181e-08 +3.1025634301981756e-08 +2.6760218760302295e-08 +2.2533757535735002e-08 +1.590396287313306e-08 +1.003427048684019e-08 +7.899179434995702e-09 +2.749040675089653e-08 +5.447744811716844e-08 +5.961300777189369e-08 +4.3419024255113235e-08 +3.5198841523408355e-08 +3.470147543234743e-08 +3.3943098980214214e-08 +2.8277218210879558e-08 +3.1402685793354447e-08 +3.0633461303544426e-08 +2.518339073829535e-08 +3.277340109950203e-08 +3.462734717488924e-08 +3.1824690895403e-08 +2.9802928964439717e-08 +3.016543422347305e-08 +3.286199340719596e-08 +3.3241756907987856e-08 +3.077662252803685e-08 +2.7904358006791088e-08 +2.149267464717588e-08 +1.368586789664027e-08 +8.776966483677418e-09 +4.652082339174782e-09 +1.0778347252944883e-08 +2.754859168025395e-08 +3.360730290485484e-08 +2.4996837363095704e-08 +2.3507533281435744e-08 +2.1651614835561842e-08 +2.2543783752375682e-08 +2.707177111509607e-08 +2.8545049686551657e-08 +2.5517214443168037e-08 +1.8812387519968176e-08 +2.989439764576008e-08 +3.5918838933154685e-08 +3.512635690802241e-08 +3.037606695503107e-08 +3.149851012616625e-08 +3.200779262225094e-08 +3.583041098966797e-08 +3.592787896455202e-08 +3.1921337049250926e-08 +2.62536482736368e-08 +1.7754210753857724e-08 +1.064258241777756e-08 +4.956813579368753e-09 +7.80754638946812e-09 +2.0863488461921013e-08 +2.776530588747928e-08 +2.302109741015524e-08 +1.7811902590593474e-08 +2.0391270094565416e-08 +2.1212680220169175e-08 +2.321677299885584e-08 +1.9893246546675594e-08 +2.208356397214746e-08 +2.045175612282398e-08 +3.1151866013130066e-08 +3.265440141347159e-08 +3.1238650314544534e-08 +3.1020045918936125e-08 +3.279509717485565e-08 +3.4818420565787565e-08 +3.764186891748769e-08 +3.8660269545449844e-08 +3.247360078552479e-08 +2.6405520801112116e-08 +1.7881839560767442e-08 +1.2692614992383436e-08 +9.334572056686072e-09 +3.1299054160699486e-08 +6.184071805450911e-08 +6.447087409851337e-08 +4.740165117826318e-08 +3.967497197874946e-08 +3.6338871664716544e-08 +3.470336562073051e-08 +3.193843092680226e-08 +3.170856758299899e-08 +3.049087535377729e-08 +2.0404665777454202e-08 +3.2011079906395435e-08 +3.8759956437131427e-08 +3.684420941982785e-08 +3.305643626434238e-08 +3.589180102106627e-08 +3.899277833666473e-08 +4.220461931003602e-08 +3.842761201012376e-08 +3.357829262227974e-08 +2.642672378384405e-08 +1.8165203454022246e-08 +1.00249017270284e-08 +7.960651648497613e-09 +2.8764968995817857e-08 +5.8181642073280324e-08 +6.1087190346489e-08 +4.9989729985218024e-08 +3.9044635244044025e-08 +3.743690675107891e-08 +3.478735573062216e-08 +3.3345799451160875e-08 +3.0937863815323946e-08 +3.321134952965135e-08 +1.976808320287424e-08 +2.9047921978554603e-08 +3.5641803061878016e-08 +3.147163657828507e-08 +2.970620062848818e-08 +2.8443965699108674e-08 +3.0340482104167e-08 +3.5163996311476794e-08 +3.649296310898938e-08 +3.381875745744898e-08 +2.7574479042891793e-08 +2.138115353257415e-08 +1.3254000942158252e-08 +9.026717896554839e-09 +2.256465800669318e-08 +4.149481248113761e-08 +4.511181122531696e-08 +4.321825337598868e-08 +4.025772527546344e-08 +4.1859865385382924e-08 +4.3938990424667516e-08 +3.6279207457494095e-08 +3.821582872911516e-08 +3.558690541666508e-08 +2.105184984340014e-08 +2.14550352437215e-08 +2.6497236028743313e-08 +2.2507952355200772e-08 +2.2270199529450733e-08 +2.3945481711585058e-08 +2.5414568995756422e-08 +2.8336964600205607e-08 +2.9547589168516668e-08 +2.772002354838896e-08 +2.3770433830891116e-08 +1.9401633202867524e-08 +1.4144444034796244e-08 +1.0141764678364923e-08 +2.3902829199810338e-08 +4.3042301492155e-08 +4.448607668841381e-08 +3.9972224647514715e-08 +3.588497990646646e-08 +3.90492374418463e-08 +4.3183736892471566e-08 +3.6252580455923755e-08 +4.0767993956791476e-08 +3.125442927843807e-08 +1.762271938807823e-08 +2.1474183673863136e-08 +2.139750777119297e-08 +2.7219041444769103e-08 +2.5802057614287868e-08 +2.7132010597043803e-08 +2.939563445893774e-08 +3.1145373626944706e-08 +2.977548014183325e-08 +2.611656852481168e-08 +2.0954464050619697e-08 +1.4570969152543467e-08 +7.621568288993752e-09 +7.665453532322657e-09 +2.790263218261523e-08 +6.036349474208013e-08 +6.29207552601804e-08 +4.586484584071539e-08 +3.536690392529527e-08 +3.5631694663133716e-08 +3.438096522825992e-08 +3.118876577765194e-08 +3.058711059710715e-08 +3.2256311303574184e-08 +1.8959904395952044e-08 +3.499897464742353e-08 +3.9876400314702916e-08 +3.563851577773353e-08 +3.283742095821592e-08 +3.167832456886971e-08 +3.44287130304586e-08 +3.6081312951995964e-08 +3.601318398810147e-08 +3.13382550241225e-08 +2.6463870094676766e-08 +1.6192586421019042e-08 +9.763809183852497e-09 +5.225959968698648e-09 +1.0060979670514148e-08 +2.505231028303393e-08 +3.088321271642185e-08 +2.7989745212444144e-08 +1.9780410518416067e-08 +2.9301289403990956e-08 +2.3878256750830293e-08 +1.848785039280367e-08 +2.135978618563498e-08 +3.359333194724077e-08 +1.8518504317451014e-08 +2.9403359576677293e-08 +3.540750188447968e-08 +3.6677461931598734e-08 +2.9658945918911174e-08 +3.3248002747862384e-08 +3.437036373689395e-08 +3.8162574725974475e-08 +3.592787896455202e-08 +3.1921337049250926e-08 +2.62536482736368e-08 +1.7754210753857724e-08 +1.064258241777756e-08 +4.956813579368753e-09 +7.80754638946812e-09 +2.0863488461921013e-08 +2.776530588747928e-08 +2.302109741015524e-08 +1.7811902590593474e-08 +2.0391270094565416e-08 +2.1212680220169175e-08 +2.321677299885584e-08 +1.9893246546675594e-08 +2.208356397214746e-08 +2.045175612282398e-08 +3.1151866013130066e-08 +3.265440141347159e-08 +3.1238650314544534e-08 +3.1020045918936125e-08 +3.279509717485565e-08 +3.4818420565787565e-08 +3.764186891748769e-08 +3.8660269545449844e-08 +3.247360078552479e-08 +2.6405520801112116e-08 +1.7881839560767442e-08 +1.2692614992383436e-08 +9.334572056686072e-09 +3.1299054160699486e-08 +6.184071805450911e-08 +6.447087409851337e-08 +4.740165117826318e-08 +3.967497197874946e-08 +3.6338871664716544e-08 +3.470336562073051e-08 +3.193843092680226e-08 +3.170856758299899e-08 +3.049087535377729e-08 +2.0404665777454202e-08 +3.2011079906395435e-08 +3.8759956437131427e-08 +3.684420941982785e-08 +3.305643626434238e-08 +3.589180102106627e-08 +3.899277833666473e-08 +4.220461931003602e-08 +3.842761201012376e-08 +3.357829262227974e-08 +2.642672378384405e-08 +1.8165203454022246e-08 +1.00249017270284e-08 +7.960651648497613e-09 +2.8764968995817857e-08 +5.8181642073280324e-08 +6.1087190346489e-08 +4.9989729985218024e-08 +3.9044635244044025e-08 +3.743690675107891e-08 +3.478735573062216e-08 +3.3345799451160875e-08 +3.0937863815323946e-08 +3.321134952965135e-08 +1.976808320287424e-08 +2.9047921978554603e-08 +3.5641803061878016e-08 +3.147163657828507e-08 +2.970620062848818e-08 +2.8443965699108674e-08 +3.0340482104167e-08 +3.5163996311476794e-08 +3.649296310898938e-08 +3.381875745744898e-08 +2.7574479042891793e-08 +2.138115353257415e-08 +1.3254000942158252e-08 +9.026717896554839e-09 +2.256465800669318e-08 +4.149481248113761e-08 +4.511181122531696e-08 +4.321825337598868e-08 +4.025772527546344e-08 +4.1859865385382924e-08 +4.3938990424667516e-08 +3.6279207457494095e-08 +3.821582872911516e-08 +3.558690541666508e-08 +2.105184984340014e-08 +2.14550352437215e-08 +2.6497236028743313e-08 +2.2507952355200772e-08 +2.2270199529450733e-08 +2.3945481711585058e-08 +2.5414568995756422e-08 +2.8336964600205607e-08 +2.9547589168516668e-08 +2.772002354838896e-08 +2.3770433830891116e-08 +1.9401633202867524e-08 +1.4144444034796244e-08 +1.0141764678364923e-08 +2.3902829199810338e-08 +4.3042301492155e-08 +4.448607668841381e-08 +3.9972224647514715e-08 +3.588497990646646e-08 +3.90492374418463e-08 +4.3183736892471566e-08 +3.6252580455923755e-08 +4.0767993956791476e-08 +3.125442927843807e-08 +1.762271938807823e-08 +2.1474183673863136e-08 +2.139750777119297e-08 +2.7219041444769103e-08 +2.5802057614287868e-08 +2.7132010597043803e-08 +2.939563445893774e-08 +3.1145373626944706e-08 +2.977548014183325e-08 +2.611656852481168e-08 +2.0954464050619697e-08 +1.4570969152543467e-08 +7.621568288993752e-09 +7.665453532322657e-09 +2.790263218261523e-08 +6.036349474208013e-08 +6.29207552601804e-08 +4.586484584071539e-08 +3.536690392529527e-08 +3.5631694663133716e-08 +3.438096522825992e-08 +3.118876577765194e-08 +3.058711059710715e-08 +3.2256311303574184e-08 +1.8959904395952044e-08 +3.499897464742353e-08 +3.9876400314702916e-08 +3.563851577773353e-08 +3.283742095821592e-08 +3.167832456886971e-08 +3.44287130304586e-08 +3.6081312951995964e-08 +3.601318398810147e-08 +3.13382550241225e-08 +2.6463870094676766e-08 +1.6192586421019042e-08 +9.763809183852497e-09 +5.225959968698648e-09 +1.0060979670514148e-08 +2.505231028303393e-08 +3.088321271642185e-08 +2.7989745212444144e-08 +1.9780410518416067e-08 +2.9301289403990956e-08 +2.3878256750830293e-08 +1.848785039280367e-08 +2.135978618563498e-08 +3.359333194724077e-08 +1.8518504317451014e-08 +2.9403359576677293e-08 +3.540750188447968e-08 +3.6677461931598734e-08 +2.9658945918911174e-08 +3.3248002747862384e-08 +3.437036373689395e-08 +3.8162574725974475e-08 +3.592787896455202e-08 +3.1921337049250926e-08 +2.62536482736368e-08 +1.7754210753857724e-08 +1.064258241777756e-08 +4.956813579368753e-09 +7.80754638946812e-09 +2.0863488461921013e-08 +2.776530588747928e-08 +2.302109741015524e-08 +1.7811902590593474e-08 +2.0391270094565416e-08 +2.1212680220169175e-08 +2.321677299885584e-08 +1.9893246546675594e-08 +2.208356397214746e-08 +2.045175612282398e-08 +3.1151866013130066e-08 +3.265440141347159e-08 +3.1238650314544534e-08 +3.1020045918936125e-08 +3.279509717485565e-08 +3.4818420565787565e-08 +3.764186891748769e-08 +3.8660269545449844e-08 +3.247360078552479e-08 +2.6405520801112116e-08 +1.7881839560767442e-08 +1.2692614992383436e-08 +9.334572056686072e-09 +3.1299054160699486e-08 +6.184071805450911e-08 +6.447087409851337e-08 +4.740165117826318e-08 +3.967497197874946e-08 +3.6338871664716544e-08 +3.470336562073051e-08 +3.193843092680226e-08 +3.170856758299899e-08 +3.049087535377729e-08 +2.0404665777454202e-08 +3.2011079906395435e-08 +3.8759956437131427e-08 +3.684420941982785e-08 +3.305643626434238e-08 +3.589180102106627e-08 +3.899277833666473e-08 +4.220461931003602e-08 +3.842761201012376e-08 +3.357829262227974e-08 +2.642672378384405e-08 +1.8165203454022246e-08 +1.00249017270284e-08 +7.960651648497613e-09 +2.8764968995817857e-08 +5.8181642073280324e-08 +6.1087190346489e-08 +4.9989729985218024e-08 +3.9044635244044025e-08 +3.743690675107891e-08 +3.478735573062216e-08 +3.3345799451160875e-08 +3.0937863815323946e-08 +3.321134952965135e-08 +1.976808320287424e-08 +2.9047921978554603e-08 +3.5641803061878016e-08 +3.147163657828507e-08 +2.970620062848818e-08 +2.8443965699108674e-08 +3.0340482104167e-08 +3.5163996311476794e-08 +3.649296310898938e-08 +3.381875745744898e-08 +2.7574479042891793e-08 +2.138115353257415e-08 +1.3254000942158252e-08 +9.026717896554839e-09 +2.256465800669318e-08 +4.149481248113761e-08 +4.511181122531696e-08 +4.321825337598868e-08 +4.025772527546344e-08 +4.1859865385382924e-08 +4.3938990424667516e-08 +3.6279207457494095e-08 +3.821582872911516e-08 +3.558690541666508e-08 +2.105184984340014e-08 +2.14550352437215e-08 +2.6497236028743313e-08 +2.2507952355200772e-08 +2.2270199529450733e-08 +2.3945481711585058e-08 +2.5414568995756422e-08 +2.8336964600205607e-08 +2.9547589168516668e-08 +2.772002354838896e-08 +2.3770433830891116e-08 +1.9401633202867524e-08 +1.4144444034796244e-08 +1.0141764678364923e-08 +2.3902829199810338e-08 +4.3042301492155e-08 +4.448607668841381e-08 +3.9972224647514715e-08 +3.588497990646646e-08 +3.90492374418463e-08 +4.3183736892471566e-08 +3.6252580455923755e-08 +4.0767993956791476e-08 +3.125442927843807e-08 +1.762271938807823e-08 +2.1474183673863136e-08 +2.139750777119297e-08 +2.7219041444769103e-08 +2.5802057614287868e-08 +2.7132010597043803e-08 +2.939563445893774e-08 +3.1145373626944706e-08 +2.977548014183325e-08 +2.611656852481168e-08 +2.0954464050619697e-08 +1.4570969152543467e-08 +7.621568288993752e-09 +7.665453532322657e-09 +2.790263218261523e-08 +6.036349474208013e-08 +6.29207552601804e-08 +4.586484584071539e-08 +3.536690392529527e-08 +3.5631694663133716e-08 +3.438096522825992e-08 +3.118876577765194e-08 +3.058711059710715e-08 +3.2256311303574184e-08 +1.8959904395952044e-08 +3.499897464742353e-08 +3.9876400314702916e-08 +3.563851577773353e-08 +3.283742095821592e-08 +3.167832456886971e-08 +3.44287130304586e-08 +3.6081312951995964e-08 +3.601318398810147e-08 +3.13382550241225e-08 +2.6463870094676766e-08 +1.6192586421019042e-08 +9.763809183852497e-09 +5.225959968698648e-09 +1.0060979670514148e-08 +2.505231028303393e-08 +3.088321271642185e-08 +2.7989745212444144e-08 +1.9780410518416067e-08 +2.9301289403990956e-08 +2.3878256750830293e-08 +1.848785039280367e-08 +2.135978618563498e-08 +3.359333194724077e-08 +1.8518504317451014e-08 +2.9403359576677293e-08 +3.540750188447968e-08 +3.6677461931598734e-08 +2.9658945918911174e-08 +3.3248002747862384e-08 +3.437036373689395e-08 +3.8162574725974475e-08 +3.592787896455202e-08 +3.1921337049250926e-08 +2.62536482736368e-08 +1.7754210753857724e-08 +1.064258241777756e-08 +4.956813579368753e-09 +7.80754638946812e-09 +2.0863488461921013e-08 +2.776530588747928e-08 +2.302109741015524e-08 +1.7811902590593474e-08 +2.0391270094565416e-08 +2.1212680220169175e-08 +2.321677299885584e-08 +1.9893246546675594e-08 +2.208356397214746e-08 +2.045175612282398e-08 +3.1151866013130066e-08 +3.265440141347159e-08 +3.1238650314544534e-08 +3.1020045918936125e-08 +3.279509717485565e-08 +3.4818420565787565e-08 +3.764186891748769e-08 +3.8660269545449844e-08 +3.247360078552479e-08 +2.6405520801112116e-08 +1.7881839560767442e-08 +1.2692614992383436e-08 +9.334572056686072e-09 +3.1299054160699486e-08 +6.184071805450911e-08 +6.447087409851337e-08 +4.740165117826318e-08 +3.967497197874946e-08 +3.6338871664716544e-08 +3.470336562073051e-08 +3.193843092680226e-08 +3.170856758299899e-08 +3.049087535377729e-08 +2.0404665777454202e-08 +3.2011079906395435e-08 +3.8759956437131427e-08 +3.684420941982785e-08 +3.305643626434238e-08 +3.589180102106627e-08 +3.899277833666473e-08 +4.220461931003602e-08 +3.842761201012376e-08 +3.357829262227974e-08 +2.642672378384405e-08 +1.8165203454022246e-08 +1.00249017270284e-08 +7.960651648497613e-09 +2.8764968995817857e-08 +5.8181642073280324e-08 +6.1087190346489e-08 +4.9989729985218024e-08 +3.9044635244044025e-08 +3.743690675107891e-08 +3.478735573062216e-08 +3.3345799451160875e-08 +3.0937863815323946e-08 +3.321134952965135e-08 +1.976808320287424e-08 +2.9047921978554603e-08 +3.5641803061878016e-08 +3.147163657828507e-08 +2.970620062848818e-08 +2.8443965699108674e-08 +3.0340482104167e-08 +3.5163996311476794e-08 +3.649296310898938e-08 +3.381875745744898e-08 +2.7574479042891793e-08 +2.138115353257415e-08 +1.3254000942158252e-08 +9.026717896554839e-09 +2.256465800669318e-08 +4.149481248113761e-08 +4.511181122531696e-08 +4.321825337598868e-08 +4.025772527546344e-08 +4.1859865385382924e-08 +4.3938990424667516e-08 +3.6279207457494095e-08 +3.821582872911516e-08 +3.558690541666508e-08 +2.105184984340014e-08 +2.14550352437215e-08 +2.6497236028743313e-08 +2.2507952355200772e-08 +2.2270199529450733e-08 +2.3945481711585058e-08 +2.5414568995756422e-08 +2.8336964600205607e-08 +2.9547589168516668e-08 +2.772002354838896e-08 +2.3770433830891116e-08 +1.9401633202867524e-08 +1.4144444034796244e-08 +1.0141764678364923e-08 +2.3902829199810338e-08 +4.3042301492155e-08 +4.448607668841381e-08 +3.9972224647514715e-08 +3.588497990646646e-08 +3.90492374418463e-08 +4.3183736892471566e-08 +3.6252580455923755e-08 +4.0767993956791476e-08 +3.125442927843807e-08 +1.762271938807823e-08 +2.1474183673863136e-08 +2.139750777119297e-08 +2.7219041444769103e-08 +2.5802057614287868e-08 +2.7132010597043803e-08 +2.939563445893774e-08 +3.1145373626944706e-08 +2.977548014183325e-08 +2.611656852481168e-08 +2.0954464050619697e-08 +1.4570969152543467e-08 +7.621568288993752e-09 +7.665453532322657e-09 +2.790263218261523e-08 +6.036349474208013e-08 +6.29207552601804e-08 +4.586484584071539e-08 +3.536690392529527e-08 +3.5631694663133716e-08 +3.438096522825992e-08 +3.118876577765194e-08 +3.058711059710715e-08 +3.2256311303574184e-08 +1.8959904395952044e-08 +3.499897464742353e-08 +3.9876400314702916e-08 +3.563851577773353e-08 +3.283742095821592e-08 +3.167832456886971e-08 +3.44287130304586e-08 +3.6081312951995964e-08 +3.601318398810147e-08 +3.13382550241225e-08 +2.6463870094676766e-08 +1.6192586421019042e-08 +9.763809183852497e-09 +5.225959968698648e-09 +1.0060979670514148e-08 +2.505231028303393e-08 +3.088321271642185e-08 +2.7989745212444144e-08 +1.9780410518416067e-08 +2.9301289403990956e-08 +2.3878256750830293e-08 +1.848785039280367e-08 +2.135978618563498e-08 +3.359333194724077e-08 +1.8518504317451014e-08 +2.9403359576677293e-08 +3.540750188447968e-08 +3.6677461931598734e-08 +2.9658945918911174e-08 +3.3248002747862384e-08 +3.437036373689395e-08 +3.8162574725974475e-08 +3.592787896455202e-08 +3.1921337049250926e-08 +2.62536482736368e-08 +1.7754210753857724e-08 +1.064258241777756e-08 +4.956813579368753e-09 +7.80754638946812e-09 +2.0863488461921013e-08 +2.776530588747928e-08 +2.302109741015524e-08 +1.7811902590593474e-08 +2.0391270094565416e-08 +2.1212680220169175e-08 +2.321677299885584e-08 +1.9893246546675594e-08 +2.208356397214746e-08 +2.045175612282398e-08 +3.1151866013130066e-08 +3.265440141347159e-08 +3.1238650314544534e-08 +3.1020045918936125e-08 +3.279509717485565e-08 +3.4818420565787565e-08 +3.764186891748769e-08 +3.8660269545449844e-08 +3.247360078552479e-08 +2.6405520801112116e-08 +1.7881839560767442e-08 +1.2692614992383436e-08 +9.334572056686072e-09 +3.1299054160699486e-08 +6.184071805450911e-08 +6.447087409851337e-08 +4.740165117826318e-08 +3.967497197874946e-08 +3.6338871664716544e-08 +3.470336562073051e-08 +3.193843092680226e-08 +3.170856758299899e-08 +3.049087535377729e-08 +2.0404665777454202e-08 +3.2011079906395435e-08 +3.8759956437131427e-08 +3.684420941982785e-08 +3.305643626434238e-08 +3.589180102106627e-08 +3.899277833666473e-08 +4.220461931003602e-08 +3.842761201012376e-08 +3.357829262227974e-08 +2.642672378384405e-08 +1.8165203454022246e-08 +1.00249017270284e-08 +7.960651648497613e-09 +2.8764968995817857e-08 +5.8181642073280324e-08 +6.1087190346489e-08 +4.9989729985218024e-08 +3.9044635244044025e-08 +3.743690675107891e-08 +3.478735573062216e-08 +3.3345799451160875e-08 +3.0937863815323946e-08 +3.321134952965135e-08 +1.976808320287424e-08 +2.9047921978554603e-08 +3.5641803061878016e-08 +3.147163657828507e-08 +2.970620062848818e-08 +2.8443965699108674e-08 +3.0340482104167e-08 +3.5163996311476794e-08 +3.612330800694179e-08 +3.4467338619156324e-08 +2.9416919623773295e-08 +2.2499323234321496e-08 +1.4318670094454071e-08 +9.94658218228599e-09 +2.3527832261027953e-08 +4.376328508714467e-08 +4.579811397258229e-08 +4.232608445917484e-08 +4.453481067585584e-08 +4.736812087998942e-08 +4.4987140974137285e-08 +4.2853447018054216e-08 +3.919749395676268e-08 +3.8835810518765464e-08 +2.0696740973691898e-08 +2.3027589796340604e-08 +2.7608502433787234e-08 +2.865320133490529e-08 +2.6301971350560765e-08 +2.5822027865465625e-08 +2.8441171507585858e-08 +3.5269600314618446e-08 +3.455856075416585e-08 +3.133209136635158e-08 +2.8434843485607723e-08 +2.23279735482901e-08 +1.5353014050516992e-08 +1.1161891130502936e-08 +2.436099442744825e-08 +4.0447565934807586e-08 +3.944001334452223e-08 +3.758047888608939e-08 +3.567796318746738e-08 +3.939185463180549e-08 +4.462233461620281e-08 +4.5538582889375027e-08 +3.933958681390814e-08 +3.418282417645095e-08 +1.9785341444632794e-08 +2.3909650314410148e-08 +2.473426554205478e-08 +2.6015977629990372e-08 +2.853140745735204e-08 +3.056146978078015e-08 +3.016272221405385e-08 +3.204674693936312e-08 +3.115466020465288e-08 +2.828864152328165e-08 +2.273608987482819e-08 +1.6163987048962003e-08 +9.735291993899071e-09 +8.643091836893173e-09 +2.7197591915726322e-08 +6.037836970283394e-08 +5.983350235588518e-08 +5.1105269859649784e-08 +3.947469419224657e-08 +3.910849073855069e-08 +3.615675612311195e-08 +2.8920457535852108e-08 +2.8902459655161036e-08 +3.397473909010491e-08 +2.0652773548259383e-08 +3.9975840660073653e-08 +4.0214333124756196e-08 +3.6379305259693736e-08 +3.4871838933135485e-08 +3.417057904301274e-08 +3.4361981162325504e-08 +3.526746357992453e-08 +3.337801483577685e-08 +2.946598233962977e-08 +2.285443210402973e-08 +1.3759831789891232e-08 +8.005769623380702e-09 +4.879151491455241e-09 +1.0444605730175814e-08 +2.5636460675509318e-08 +2.989554819521064e-08 +2.689606577757323e-08 +2.1271769152666333e-08 +2.6195463344279376e-08 +2.4656521272037657e-08 +2.100697841482788e-08 +2.1080613579664398e-08 +2.6036276609582578e-08 +2.3348264364635335e-08 +3.256063163325009e-08 +4.270256067582224e-08 +3.757530141356182e-08 +3.207592158614544e-08 +3.239832197861603e-08 +3.3759175432330153e-08 +3.740025353286787e-08 +3.501664379970015e-08 +3.080875573054921e-08 +2.447226899573915e-08 +1.632851562039359e-08 +8.709823705026265e-09 +4.852360125677669e-09 +8.352742464831335e-09 +2.233265792819599e-08 +3.1356745997435236e-08 +2.4692845761834243e-08 +1.9338928257811427e-08 +1.9024417347287607e-08 +2.5126602904699337e-08 +2.7550810597051484e-08 +1.8833015227974834e-08 +3.07749788859646e-08 +2.104798728453036e-08 +3.483510353282084e-08 +3.823497715925681e-08 +3.332854120940232e-08 +3.1857892465262325e-08 +3.277635965523207e-08 +3.504696899593304e-08 +3.9732745997588816e-08 +3.6231130926880973e-08 +3.2384022292587515e-08 +2.51114813976347e-08 +1.6464444819768138e-08 +8.994255965628027e-09 +7.1767165621410114e-09 +2.8577675981685694e-08 +5.841545015805698e-08 +6.039275157096608e-08 +4.688168500870891e-08 +3.948644623306311e-08 +3.967554725347474e-08 +3.497004654695204e-08 +3.2341205416605566e-08 +2.96193341449701e-08 +3.1787133674052234e-08 +2.3771091287720007e-08 +3.2843748980194056e-08 +3.870777080133769e-08 +3.830688649991746e-08 +3.751424011057797e-08 +3.7333521664734786e-08 +3.92022605187722e-08 +4.072682072288178e-08 +3.9743840581576465e-08 +3.553767833660138e-08 +2.6895819231262385e-08 +1.764564819498603e-08 +1.0751227158752863e-08 +7.09946538474556e-09 +2.7265145604895536e-08 +5.8462458321323144e-08 +5.9155910911602734e-08 +4.8799240032291956e-08 +4.3469894977249186e-08 +4.311495047174816e-08 +3.511098885464693e-08 +2.9433766955013795e-08 +3.120002472584681e-08 +3.4093656594031734e-08 +2.3460936028687633e-08 +3.1229445918939964e-08 +3.234786216699815e-08 +3.4140500393090674e-08 +3.2494885950360346e-08 +3.0468932732112835e-08 +3.243875557359323e-08 +3.499108516547676e-08 +3.612330800694179e-08 +3.4467338619156324e-08 +2.9416919623773295e-08 +2.2499323234321496e-08 +1.4318670094454071e-08 +9.94658218228599e-09 +2.3527832261027953e-08 +4.376328508714467e-08 +4.579811397258229e-08 +4.232608445917484e-08 +4.453481067585584e-08 +4.736812087998942e-08 +4.4987140974137285e-08 +4.2853447018054216e-08 +3.919749395676268e-08 +3.8835810518765464e-08 +2.0696740973691898e-08 +2.3027589796340604e-08 +2.7608502433787234e-08 +2.865320133490529e-08 +2.6301971350560765e-08 +2.5822027865465625e-08 +2.8441171507585858e-08 +3.5269600314618446e-08 +3.455856075416585e-08 +3.133209136635158e-08 +2.8434843485607723e-08 +2.23279735482901e-08 +1.5353014050516992e-08 +1.1161891130502936e-08 +2.436099442744825e-08 +4.0447565934807586e-08 +3.944001334452223e-08 +3.758047888608939e-08 +3.567796318746738e-08 +3.939185463180549e-08 +4.462233461620281e-08 +4.5538582889375027e-08 +3.933958681390814e-08 +3.418282417645095e-08 +1.9785341444632794e-08 +2.3909650314410148e-08 +2.473426554205478e-08 +2.6015977629990372e-08 +2.853140745735204e-08 +3.056146978078015e-08 +3.016272221405385e-08 +3.204674693936312e-08 +3.115466020465288e-08 +2.828864152328165e-08 +2.273608987482819e-08 +1.6163987048962003e-08 +9.735291993899071e-09 +8.643091836893173e-09 +2.7197591915726322e-08 +6.037836970283394e-08 +5.983350235588518e-08 +5.1105269859649784e-08 +3.947469419224657e-08 +3.910849073855069e-08 +3.615675612311195e-08 +2.8920457535852108e-08 +2.8902459655161036e-08 +3.397473909010491e-08 +2.0652773548259383e-08 +3.9975840660073653e-08 +4.0214333124756196e-08 +3.6379305259693736e-08 +3.4871838933135485e-08 +3.417057904301274e-08 +3.4361981162325504e-08 +3.526746357992453e-08 +3.337801483577685e-08 +2.946598233962977e-08 +2.285443210402973e-08 +1.3759831789891232e-08 +8.005769623380702e-09 +4.879151491455241e-09 +1.0444605730175814e-08 +2.5636460675509318e-08 +2.989554819521064e-08 +2.689606577757323e-08 +2.1271769152666333e-08 +2.6195463344279376e-08 +2.4656521272037657e-08 +2.100697841482788e-08 +2.1080613579664398e-08 +2.6036276609582578e-08 +2.3348264364635335e-08 +3.256063163325009e-08 +4.270256067582224e-08 +3.757530141356182e-08 +3.207592158614544e-08 +3.239832197861603e-08 +3.3759175432330153e-08 +3.740025353286787e-08 +3.501664379970015e-08 +3.080875573054921e-08 +2.447226899573915e-08 +1.632851562039359e-08 +8.709823705026265e-09 +4.852360125677669e-09 +8.352742464831335e-09 +2.233265792819599e-08 +3.1356745997435236e-08 +2.4692845761834243e-08 +1.9338928257811427e-08 +1.9024417347287607e-08 +2.5126602904699337e-08 +2.7550810597051484e-08 +1.8833015227974834e-08 +3.07749788859646e-08 +2.104798728453036e-08 +3.483510353282084e-08 +3.823497715925681e-08 +3.332854120940232e-08 +3.1857892465262325e-08 +3.277635965523207e-08 +3.504696899593304e-08 +3.9732745997588816e-08 +3.6231130926880973e-08 +3.2384022292587515e-08 +2.51114813976347e-08 +1.6464444819768138e-08 +8.994255965628027e-09 +7.1767165621410114e-09 +2.8577675981685694e-08 +5.841545015805698e-08 +6.039275157096608e-08 +4.688168500870891e-08 +3.948644623306311e-08 +3.967554725347474e-08 +3.497004654695204e-08 +3.2341205416605566e-08 +2.96193341449701e-08 +3.1787133674052234e-08 +2.3771091287720007e-08 +3.2843748980194056e-08 +3.870777080133769e-08 +3.830688649991746e-08 +3.751424011057797e-08 +3.7333521664734786e-08 +3.92022605187722e-08 +4.072682072288178e-08 +3.9743840581576465e-08 +3.553767833660138e-08 +2.6895819231262385e-08 +1.764564819498603e-08 +1.0751227158752863e-08 +7.09946538474556e-09 +2.7265145604895536e-08 +5.8462458321323144e-08 +5.9155910911602734e-08 +4.8799240032291956e-08 +4.3469894977249186e-08 +4.311495047174816e-08 +3.511098885464693e-08 +2.9433766955013795e-08 +3.120002472584681e-08 +3.4093656594031734e-08 +2.3460936028687633e-08 +3.1229445918939964e-08 +3.234786216699815e-08 +3.4140500393090674e-08 +3.2494885950360346e-08 +3.0468932732112835e-08 +3.243875557359323e-08 +3.499108516547676e-08 +3.612330800694179e-08 +3.4467338619156324e-08 +2.9416919623773295e-08 +2.2499323234321496e-08 +1.4318670094454071e-08 +9.94658218228599e-09 +2.3527832261027953e-08 +4.376328508714467e-08 +4.579811397258229e-08 +4.232608445917484e-08 +4.453481067585584e-08 +4.736812087998942e-08 +4.4987140974137285e-08 +4.2853447018054216e-08 +3.919749395676268e-08 +3.8835810518765464e-08 +2.0696740973691898e-08 +2.3027589796340604e-08 +2.7608502433787234e-08 +2.865320133490529e-08 +2.6301971350560765e-08 +2.5822027865465625e-08 +2.8441171507585858e-08 +3.5269600314618446e-08 +3.455856075416585e-08 +3.133209136635158e-08 +2.8434843485607723e-08 +2.23279735482901e-08 +1.5353014050516992e-08 +1.1161891130502936e-08 +2.436099442744825e-08 +4.0447565934807586e-08 +3.944001334452223e-08 +3.758047888608939e-08 +3.567796318746738e-08 +3.939185463180549e-08 +4.462233461620281e-08 +4.5538582889375027e-08 +3.933958681390814e-08 +3.418282417645095e-08 +1.9785341444632794e-08 +2.3909650314410148e-08 +2.473426554205478e-08 +2.6015977629990372e-08 +2.853140745735204e-08 +3.056146978078015e-08 +3.016272221405385e-08 +3.204674693936312e-08 +3.115466020465288e-08 +2.828864152328165e-08 +2.273608987482819e-08 +1.6163987048962003e-08 +9.735291993899071e-09 +8.643091836893173e-09 +2.7197591915726322e-08 +6.037836970283394e-08 +5.983350235588518e-08 +5.1105269859649784e-08 +3.947469419224657e-08 +3.910849073855069e-08 +3.615675612311195e-08 +2.8920457535852108e-08 +2.8902459655161036e-08 +3.397473909010491e-08 +2.0652773548259383e-08 +3.9975840660073653e-08 +4.0214333124756196e-08 +3.6379305259693736e-08 +3.4871838933135485e-08 +3.417057904301274e-08 +3.4361981162325504e-08 +3.526746357992453e-08 +3.337801483577685e-08 +2.946598233962977e-08 +2.285443210402973e-08 +1.3759831789891232e-08 +8.005769623380702e-09 +4.879151491455241e-09 +1.0444605730175814e-08 +2.5636460675509318e-08 +2.989554819521064e-08 +2.689606577757323e-08 +2.1271769152666333e-08 +2.6195463344279376e-08 +2.4656521272037657e-08 +2.100697841482788e-08 +2.1080613579664398e-08 +2.6036276609582578e-08 +2.3348264364635335e-08 +3.256063163325009e-08 +4.270256067582224e-08 +3.757530141356182e-08 +3.207592158614544e-08 +3.239832197861603e-08 +3.3759175432330153e-08 +3.740025353286787e-08 +3.501664379970015e-08 +3.080875573054921e-08 +2.447226899573915e-08 +1.632851562039359e-08 +8.709823705026265e-09 +4.852360125677669e-09 +8.352742464831335e-09 +2.233265792819599e-08 +3.1356745997435236e-08 +2.4692845761834243e-08 +1.9338928257811427e-08 +1.9024417347287607e-08 +2.5126602904699337e-08 +2.7550810597051484e-08 +1.8833015227974834e-08 +3.07749788859646e-08 +2.104798728453036e-08 +3.483510353282084e-08 +3.823497715925681e-08 +3.332854120940232e-08 +3.1857892465262325e-08 +3.277635965523207e-08 +3.504696899593304e-08 +3.9732745997588816e-08 +3.6231130926880973e-08 +3.2384022292587515e-08 +2.51114813976347e-08 +1.6464444819768138e-08 +8.994255965628027e-09 +7.1767165621410114e-09 +2.8577675981685694e-08 +5.841545015805698e-08 +6.039275157096608e-08 +4.688168500870891e-08 +3.948644623306311e-08 +3.967554725347474e-08 +3.497004654695204e-08 +3.2341205416605566e-08 +2.96193341449701e-08 +3.1787133674052234e-08 +2.3771091287720007e-08 +3.2843748980194056e-08 +3.870777080133769e-08 +3.830688649991746e-08 +3.751424011057797e-08 +3.7333521664734786e-08 +3.92022605187722e-08 +4.072682072288178e-08 +3.9743840581576465e-08 +3.553767833660138e-08 +2.6895819231262385e-08 +1.764564819498603e-08 +1.0751227158752863e-08 +7.09946538474556e-09 +2.7265145604895536e-08 +5.8462458321323144e-08 +5.9155910911602734e-08 +4.8799240032291956e-08 +4.3469894977249186e-08 +4.311495047174816e-08 +3.511098885464693e-08 +2.9433766955013795e-08 +3.120002472584681e-08 +3.4093656594031734e-08 +2.3460936028687633e-08 +3.1229445918939964e-08 +3.234786216699815e-08 +3.4140500393090674e-08 +3.2494885950360346e-08 +3.0468932732112835e-08 +3.243875557359323e-08 +3.499108516547676e-08 +3.612330800694179e-08 +3.4467338619156324e-08 +2.9416919623773295e-08 +2.2499323234321496e-08 +1.4318670094454071e-08 +9.94658218228599e-09 +2.3527832261027953e-08 +4.376328508714467e-08 +4.579811397258229e-08 +4.232608445917484e-08 +4.453481067585584e-08 +4.736812087998942e-08 +4.4987140974137285e-08 +4.2853447018054216e-08 +3.919749395676268e-08 +3.8835810518765464e-08 +2.0696740973691898e-08 +2.3027589796340604e-08 +2.7608502433787234e-08 +2.865320133490529e-08 +2.6301971350560765e-08 +2.5822027865465625e-08 +2.8441171507585858e-08 +3.5269600314618446e-08 +3.455856075416585e-08 +3.133209136635158e-08 +2.8434843485607723e-08 +2.23279735482901e-08 +1.5353014050516992e-08 +1.1161891130502936e-08 +2.436099442744825e-08 +4.0447565934807586e-08 +3.944001334452223e-08 +3.758047888608939e-08 +3.567796318746738e-08 +3.939185463180549e-08 +4.462233461620281e-08 +4.5538582889375027e-08 +3.933958681390814e-08 +3.418282417645095e-08 +1.9785341444632794e-08 +2.3909650314410148e-08 +2.473426554205478e-08 +2.6015977629990372e-08 +2.853140745735204e-08 +3.056146978078015e-08 +3.016272221405385e-08 +3.204674693936312e-08 +3.115466020465288e-08 +2.828864152328165e-08 +2.273608987482819e-08 +1.6163987048962003e-08 +9.735291993899071e-09 +8.643091836893173e-09 +2.7197591915726322e-08 +6.037836970283394e-08 +5.983350235588518e-08 +5.1105269859649784e-08 +3.947469419224657e-08 +3.910849073855069e-08 +3.615675612311195e-08 +2.8920457535852108e-08 +2.8902459655161036e-08 +3.397473909010491e-08 +2.0652773548259383e-08 +3.9975840660073653e-08 +4.0214333124756196e-08 +3.6379305259693736e-08 +3.4871838933135485e-08 +3.417057904301274e-08 +3.4361981162325504e-08 +3.526746357992453e-08 +3.337801483577685e-08 +2.946598233962977e-08 +2.285443210402973e-08 +1.3759831789891232e-08 +8.005769623380702e-09 +4.879151491455241e-09 +1.0444605730175814e-08 +2.5636460675509318e-08 +2.989554819521064e-08 +2.689606577757323e-08 +2.1271769152666333e-08 +2.6195463344279376e-08 +2.4656521272037657e-08 +2.100697841482788e-08 +2.1080613579664398e-08 +2.6036276609582578e-08 +2.3348264364635335e-08 +3.256063163325009e-08 +4.270256067582224e-08 +3.757530141356182e-08 +3.207592158614544e-08 +3.239832197861603e-08 +3.3759175432330153e-08 +3.740025353286787e-08 +3.501664379970015e-08 +3.080875573054921e-08 +2.447226899573915e-08 +1.632851562039359e-08 +8.709823705026265e-09 +4.852360125677669e-09 +8.352742464831335e-09 +2.233265792819599e-08 +3.1356745997435236e-08 +2.4692845761834243e-08 +1.9338928257811427e-08 +1.9024417347287607e-08 +2.5126602904699337e-08 +2.7550810597051484e-08 +1.8833015227974834e-08 +3.07749788859646e-08 +2.104798728453036e-08 +3.483510353282084e-08 +3.823497715925681e-08 +3.332854120940232e-08 +3.1857892465262325e-08 +3.277635965523207e-08 +3.504696899593304e-08 +3.9732745997588816e-08 +3.6231130926880973e-08 +3.2384022292587515e-08 +2.51114813976347e-08 +1.6464444819768138e-08 +8.994255965628027e-09 +7.1767165621410114e-09 +2.8577675981685694e-08 +5.841545015805698e-08 +6.039275157096608e-08 +4.688168500870891e-08 +3.948644623306311e-08 +3.967554725347474e-08 +3.497004654695204e-08 +3.2341205416605566e-08 +2.96193341449701e-08 +3.1787133674052234e-08 +2.3771091287720007e-08 +3.2843748980194056e-08 +3.870777080133769e-08 +3.830688649991746e-08 +3.751424011057797e-08 +3.7333521664734786e-08 +3.92022605187722e-08 +4.072682072288178e-08 +3.9743840581576465e-08 +3.553767833660138e-08 +2.6895819231262385e-08 +1.764564819498603e-08 +1.0751227158752863e-08 +7.09946538474556e-09 +2.7265145604895536e-08 +5.8462458321323144e-08 +5.9155910911602734e-08 +4.8799240032291956e-08 +4.3469894977249186e-08 +4.311495047174816e-08 +3.511098885464693e-08 +2.9433766955013795e-08 +3.120002472584681e-08 +3.4093656594031734e-08 +2.3460936028687633e-08 +3.1229445918939964e-08 +3.234786216699815e-08 +3.4140500393090674e-08 +3.2494885950360346e-08 +3.0468932732112835e-08 +3.243875557359323e-08 +3.499108516547676e-08 +3.612330800694179e-08 +3.4467338619156324e-08 +2.9416919623773295e-08 +2.2499323234321496e-08 +1.4318670094454071e-08 +9.94658218228599e-09 +2.3527832261027953e-08 +4.376328508714467e-08 +4.579811397258229e-08 +4.232608445917484e-08 +4.453481067585584e-08 +4.736812087998942e-08 +4.4987140974137285e-08 +4.2853447018054216e-08 +3.919749395676268e-08 +3.8835810518765464e-08 +2.0696740973691898e-08 +2.3027589796340604e-08 +2.7608502433787234e-08 +2.865320133490529e-08 +2.6301971350560765e-08 +2.5822027865465625e-08 +2.8441171507585858e-08 +3.5269600314618446e-08 +3.455856075416585e-08 +3.133209136635158e-08 +2.8434843485607723e-08 +2.23279735482901e-08 +1.5353014050516992e-08 +1.1161891130502936e-08 +2.436099442744825e-08 +4.0447565934807586e-08 +3.944001334452223e-08 +3.758047888608939e-08 +3.567796318746738e-08 +3.939185463180549e-08 +4.462233461620281e-08 +4.5538582889375027e-08 +3.933958681390814e-08 +3.418282417645095e-08 +1.9785341444632794e-08 +2.3909650314410148e-08 +2.473426554205478e-08 +2.6015977629990372e-08 +2.853140745735204e-08 +3.056146978078015e-08 +3.016272221405385e-08 +3.204674693936312e-08 +3.115466020465288e-08 +2.828864152328165e-08 +2.273608987482819e-08 +1.6163987048962003e-08 +9.735291993899071e-09 +8.643091836893173e-09 +2.7197591915726322e-08 +6.037836970283394e-08 +5.983350235588518e-08 +5.1105269859649784e-08 +3.947469419224657e-08 +3.910849073855069e-08 +3.615675612311195e-08 +2.8920457535852108e-08 +2.8902459655161036e-08 +3.397473909010491e-08 +2.0652773548259383e-08 +3.9975840660073653e-08 +4.0214333124756196e-08 +3.6379305259693736e-08 +3.4871838933135485e-08 +3.417057904301274e-08 +3.4361981162325504e-08 +3.526746357992453e-08 +3.6762602590940955e-08 +3.2406375824770026e-08 +2.4372417739850343e-08 +1.5509817504209033e-08 +8.899089089645121e-09 +4.870851098990411e-09 +9.132814992318166e-09 +2.6582951962810812e-08 +3.6057808870362884e-08 +2.541473335996365e-08 +1.9911737519988334e-08 +1.9959978414808685e-08 +2.0062623862220302e-08 +1.8068392935967095e-08 +2.4241912559314203e-08 +2.800042888591373e-08 +1.809691012592052e-08 +3.130595745740291e-08 +4.094024764596261e-08 +3.7405759733809885e-08 +3.804176703366456e-08 +3.798251373696018e-08 +3.9688778572156304e-08 +4.211019207298563e-08 +4.127908445915563e-08 +3.620631193159009e-08 +2.808507645263427e-08 +1.9396537912443567e-08 +9.255841601425602e-09 +5.257682260692952e-09 +8.6102189954483e-09 +2.3522819152707606e-08 +3.3572539875026884e-08 +2.5241657849756395e-08 +2.2216123705273918e-08 +1.6014169074076996e-08 +2.365011923120288e-08 +2.113978469426517e-08 +2.430363131912695e-08 +2.932479348562404e-08 +1.7952023077252245e-08 +3.081886412929351e-08 +3.611435015764806e-08 +3.521790777144638e-08 +3.874960149207628e-08 +4.0030163030561304e-08 +4.026709403527523e-08 +4.1884848744881024e-08 +4.103344215145882e-08 +3.495541813250907e-08 +2.718994898009039e-08 +1.74106895607588e-08 +9.411823234081524e-09 +6.4629649922692115e-09 +2.9738991287829438e-08 +6.051117598227122e-08 +6.611887182224845e-08 +5.1540588462483515e-08 +3.848275620164753e-08 +3.536871193157473e-08 +3.709839866630033e-08 +3.2967268681923163e-08 +2.9705789717970114e-08 +3.119624434908065e-08 +2.8357345761901436e-08 +3.4198356594033656e-08 +3.868862237119605e-08 +3.6691432889212805e-08 +3.860923445910668e-08 +3.992365502427992e-08 +4.267207111538212e-08 +4.821780164923577e-08 +4.5736723941184e-08 +4.043384152350435e-08 +3.3123003768268256e-08 +2.157403492975194e-08 +1.1112088775713955e-08 +7.86926514928087e-09 +2.779143979642795e-08 +6.055391067614956e-08 +6.799377433405678e-08 +5.01831866571211e-08 +3.866306373697265e-08 +3.597751695513378e-08 +3.337464536952875e-08 +3.593461789704822e-08 +3.120922912145137e-08 +3.1488730455836404e-08 +2.0408199607909525e-08 +3.0352809419708825e-08 +3.643444945121751e-08 +3.751045973381181e-08 +3.317905196293176e-08 +3.0882801805903786e-08 +3.2460698195257676e-08 +3.785184419221681e-08 +3.987188029900425e-08 +3.4573600079126874e-08 +2.862673869754217e-08 +2.1199777629902063e-08 +1.280076664073707e-08 +8.332196938928289e-09 +2.2422893877962164e-08 +4.313845455338125e-08 +4.745350808564248e-08 +5.043844427094053e-08 +4.3643874490596166e-08 +4.709059191609109e-08 +4.977128995381685e-08 +4.6937486657061584e-08 +4.273732370565019e-08 +3.818213406663417e-08 +2.0587438775887697e-08 +2.8032315542115258e-08 +2.6965016562503852e-08 +2.6630781947113104e-08 +2.8329403846673294e-08 +2.612585510251986e-08 +2.6425737598600712e-08 +3.101486844640856e-08 +3.478661609168965e-08 +3.302257723765417e-08 +2.649542802246384e-08 +1.9497128807264876e-08 +1.2884263658007046e-08 +8.822495369078566e-09 +2.270551813228446e-08 +4.252792370564636e-08 +4.227718610752559e-08 +3.931090525974749e-08 +3.560293092686945e-08 +4.339058924726343e-08 +4.8363510518940166e-08 +4.753486836821853e-08 +4.222278155493431e-08 +4.167643493012053e-08 +2.1108308948581704e-08 +2.553915706483249e-08 +3.176609505552752e-08 +2.9987263422841835e-08 +3.141361601313486e-08 +3.2029735243915394e-08 +3.2213740973903074e-08 +3.4751113422929186e-08 +3.22018245688793e-08 +2.7979718995803457e-08 +2.2222122998837608e-08 +1.4269771742804821e-08 +6.9400321037379265e-09 +6.6124542387397714e-09 +2.8228895133955598e-08 +5.6868618603868484e-08 +6.444621946742973e-08 +4.8724125589590415e-08 +3.778313995359703e-08 +4.04220894826878e-08 +4.029150212004805e-08 +3.208290706495248e-08 +3.240004780279189e-08 +3.251017182163221e-08 +2.4728677159009153e-08 +3.781971098970445e-08 +4.269089081710931e-08 +3.755861844652855e-08 +3.81458917589412e-08 +3.7685918525023815e-08 +3.9019076609820634e-08 +4.2581095526683435e-08 +3.6762602590940955e-08 +3.2406375824770026e-08 +2.4372417739850343e-08 +1.5509817504209033e-08 +8.899089089645121e-09 +4.870851098990411e-09 +9.132814992318166e-09 +2.6582951962810812e-08 +3.6057808870362884e-08 +2.541473335996365e-08 +1.9911737519988334e-08 +1.9959978414808685e-08 +2.0062623862220302e-08 +1.8068392935967095e-08 +2.4241912559314203e-08 +2.800042888591373e-08 +1.809691012592052e-08 +3.130595745740291e-08 +4.094024764596261e-08 +3.7405759733809885e-08 +3.804176703366456e-08 +3.798251373696018e-08 +3.9688778572156304e-08 +4.211019207298563e-08 +4.127908445915563e-08 +3.620631193159009e-08 +2.808507645263427e-08 +1.9396537912443567e-08 +9.255841601425602e-09 +5.257682260692952e-09 +8.6102189954483e-09 +2.3522819152707606e-08 +3.3572539875026884e-08 +2.5241657849756395e-08 +2.2216123705273918e-08 +1.6014169074076996e-08 +2.365011923120288e-08 +2.113978469426517e-08 +2.430363131912695e-08 +2.932479348562404e-08 +1.7952023077252245e-08 +3.081886412929351e-08 +3.611435015764806e-08 +3.521790777144638e-08 +3.874960149207628e-08 +4.0030163030561304e-08 +4.026709403527523e-08 +4.1884848744881024e-08 +4.103344215145882e-08 +3.495541813250907e-08 +2.718994898009039e-08 +1.74106895607588e-08 +9.411823234081524e-09 +6.4629649922692115e-09 +2.9738991287829438e-08 +6.051117598227122e-08 +6.611887182224845e-08 +5.1540588462483515e-08 +3.848275620164753e-08 +3.536871193157473e-08 +3.709839866630033e-08 +3.2967268681923163e-08 +2.9705789717970114e-08 +3.119624434908065e-08 +2.8357345761901436e-08 +3.4198356594033656e-08 +3.868862237119605e-08 +3.6691432889212805e-08 +3.860923445910668e-08 +3.992365502427992e-08 +4.267207111538212e-08 +4.821780164923577e-08 +4.5736723941184e-08 +4.043384152350435e-08 +3.3123003768268256e-08 +2.157403492975194e-08 +1.1112088775713955e-08 +7.86926514928087e-09 +2.779143979642795e-08 +6.055391067614956e-08 +6.799377433405678e-08 +5.01831866571211e-08 +3.866306373697265e-08 +3.597751695513378e-08 +3.337464536952875e-08 +3.593461789704822e-08 +3.120922912145137e-08 +3.1488730455836404e-08 +2.0408199607909525e-08 +3.0352809419708825e-08 +3.643444945121751e-08 +3.751045973381181e-08 +3.317905196293176e-08 +3.0882801805903786e-08 +3.2460698195257676e-08 +3.785184419221681e-08 +3.987188029900425e-08 +3.4573600079126874e-08 +2.862673869754217e-08 +2.1199777629902063e-08 +1.280076664073707e-08 +8.332196938928289e-09 +2.2422893877962164e-08 +4.313845455338125e-08 +4.745350808564248e-08 +5.043844427094053e-08 +4.3643874490596166e-08 +4.709059191609109e-08 +4.977128995381685e-08 +4.6937486657061584e-08 +4.273732370565019e-08 +3.818213406663417e-08 +2.0587438775887697e-08 +2.8032315542115258e-08 +2.6965016562503852e-08 +2.6630781947113104e-08 +2.8329403846673294e-08 +2.612585510251986e-08 +2.6425737598600712e-08 +3.101486844640856e-08 +3.478661609168965e-08 +3.302257723765417e-08 +2.649542802246384e-08 +1.9497128807264876e-08 +1.2884263658007046e-08 +8.822495369078566e-09 +2.270551813228446e-08 +4.252792370564636e-08 +4.227718610752559e-08 +3.931090525974749e-08 +3.560293092686945e-08 +4.339058924726343e-08 +4.8363510518940166e-08 +4.753486836821853e-08 +4.222278155493431e-08 +4.167643493012053e-08 +2.1108308948581704e-08 +2.553915706483249e-08 +3.176609505552752e-08 +2.9987263422841835e-08 +3.141361601313486e-08 +3.2029735243915394e-08 +3.2213740973903074e-08 +3.4751113422929186e-08 +3.22018245688793e-08 +2.7979718995803457e-08 +2.2222122998837608e-08 +1.4269771742804821e-08 +6.9400321037379265e-09 +6.6124542387397714e-09 +2.8228895133955598e-08 +5.6868618603868484e-08 +6.444621946742973e-08 +4.8724125589590415e-08 +3.778313995359703e-08 +4.04220894826878e-08 +4.029150212004805e-08 +3.208290706495248e-08 +3.240004780279189e-08 +3.251017182163221e-08 +2.4728677159009153e-08 +3.781971098970445e-08 +4.269089081710931e-08 +3.755861844652855e-08 +3.81458917589412e-08 +3.7685918525023815e-08 +3.9019076609820634e-08 +4.2581095526683435e-08 +3.6762602590940955e-08 +3.2406375824770026e-08 +2.4372417739850343e-08 +1.5509817504209033e-08 +8.899089089645121e-09 +4.870851098990411e-09 +9.132814992318166e-09 +2.6582951962810812e-08 +3.6057808870362884e-08 +2.541473335996365e-08 +1.9911737519988334e-08 +1.9959978414808685e-08 +2.0062623862220302e-08 +1.8068392935967095e-08 +2.4241912559314203e-08 +2.800042888591373e-08 +1.809691012592052e-08 +3.130595745740291e-08 +4.094024764596261e-08 +3.7405759733809885e-08 +3.804176703366456e-08 +3.798251373696018e-08 +3.9688778572156304e-08 +4.211019207298563e-08 +4.127908445915563e-08 +3.620631193159009e-08 +2.808507645263427e-08 +1.9396537912443567e-08 +9.255841601425602e-09 +5.257682260692952e-09 +8.6102189954483e-09 +2.3522819152707606e-08 +3.3572539875026884e-08 +2.5241657849756395e-08 +2.2216123705273918e-08 +1.6014169074076996e-08 +2.365011923120288e-08 +2.113978469426517e-08 +2.430363131912695e-08 +2.932479348562404e-08 +1.7952023077252245e-08 +3.081886412929351e-08 +3.611435015764806e-08 +3.521790777144638e-08 +3.874960149207628e-08 +4.0030163030561304e-08 +4.026709403527523e-08 +4.1884848744881024e-08 +4.103344215145882e-08 +3.495541813250907e-08 +2.718994898009039e-08 +1.74106895607588e-08 +9.411823234081524e-09 +6.4629649922692115e-09 +2.9738991287829438e-08 +6.051117598227122e-08 +6.611887182224845e-08 +5.1540588462483515e-08 +3.848275620164753e-08 +3.536871193157473e-08 +3.709839866630033e-08 +3.2967268681923163e-08 +2.9705789717970114e-08 +3.119624434908065e-08 +2.8357345761901436e-08 +3.4198356594033656e-08 +3.868862237119605e-08 +3.6691432889212805e-08 +3.860923445910668e-08 +3.992365502427992e-08 +4.267207111538212e-08 +4.821780164923577e-08 +4.5736723941184e-08 +4.043384152350435e-08 +3.3123003768268256e-08 +2.157403492975194e-08 +1.1112088775713955e-08 +7.86926514928087e-09 +2.779143979642795e-08 +6.055391067614956e-08 +6.799377433405678e-08 +5.01831866571211e-08 +3.866306373697265e-08 +3.597751695513378e-08 +3.337464536952875e-08 +3.593461789704822e-08 +3.120922912145137e-08 +3.1488730455836404e-08 +2.0408199607909525e-08 +3.0352809419708825e-08 +3.643444945121751e-08 +3.751045973381181e-08 +3.317905196293176e-08 +3.0882801805903786e-08 +3.2460698195257676e-08 +3.785184419221681e-08 +3.987188029900425e-08 +3.4573600079126874e-08 +2.862673869754217e-08 +2.1199777629902063e-08 +1.280076664073707e-08 +8.332196938928289e-09 +2.2422893877962164e-08 +4.313845455338125e-08 +4.745350808564248e-08 +5.043844427094053e-08 +4.3643874490596166e-08 +4.709059191609109e-08 +4.977128995381685e-08 +4.6937486657061584e-08 +4.273732370565019e-08 +3.818213406663417e-08 +2.0587438775887697e-08 +2.8032315542115258e-08 +2.6965016562503852e-08 +2.6630781947113104e-08 +2.8329403846673294e-08 +2.612585510251986e-08 +2.6425737598600712e-08 +3.101486844640856e-08 +3.478661609168965e-08 +3.302257723765417e-08 +2.649542802246384e-08 +1.9497128807264876e-08 +1.2884263658007046e-08 +8.822495369078566e-09 +2.270551813228446e-08 +4.252792370564636e-08 +4.227718610752559e-08 +3.931090525974749e-08 +3.560293092686945e-08 +4.339058924726343e-08 +4.8363510518940166e-08 +4.753486836821853e-08 +4.222278155493431e-08 +4.167643493012053e-08 +2.1108308948581704e-08 +2.553915706483249e-08 +3.176609505552752e-08 +2.9987263422841835e-08 +3.141361601313486e-08 +3.2029735243915394e-08 +3.2213740973903074e-08 +3.4751113422929186e-08 +3.22018245688793e-08 +2.7979718995803457e-08 +2.2222122998837608e-08 +1.4269771742804821e-08 +6.9400321037379265e-09 +6.6124542387397714e-09 +2.8228895133955598e-08 +5.6868618603868484e-08 +6.444621946742973e-08 +4.8724125589590415e-08 +3.778313995359703e-08 +4.04220894826878e-08 +4.029150212004805e-08 +3.208290706495248e-08 +3.240004780279189e-08 +3.251017182163221e-08 +2.4728677159009153e-08 +3.781971098970445e-08 +4.269089081710931e-08 +3.755861844652855e-08 +3.81458917589412e-08 +3.7685918525023815e-08 +3.9019076609820634e-08 +4.2581095526683435e-08 +3.6762602590940955e-08 +3.2406375824770026e-08 +2.4372417739850343e-08 +1.5509817504209033e-08 +8.899089089645121e-09 +4.870851098990411e-09 +9.132814992318166e-09 +2.6582951962810812e-08 +3.6057808870362884e-08 +2.541473335996365e-08 +1.9911737519988334e-08 +1.9959978414808685e-08 +2.0062623862220302e-08 +1.8068392935967095e-08 +2.4241912559314203e-08 +2.800042888591373e-08 +1.809691012592052e-08 +3.130595745740291e-08 +4.094024764596261e-08 +3.7405759733809885e-08 +3.804176703366456e-08 +3.798251373696018e-08 +3.9688778572156304e-08 +4.211019207298563e-08 +4.127908445915563e-08 +3.620631193159009e-08 +2.808507645263427e-08 +1.9396537912443567e-08 +9.255841601425602e-09 +5.257682260692952e-09 +8.6102189954483e-09 +2.3522819152707606e-08 +3.3572539875026884e-08 +2.5241657849756395e-08 +2.2216123705273918e-08 +1.6014169074076996e-08 +2.365011923120288e-08 +2.113978469426517e-08 +2.430363131912695e-08 +2.932479348562404e-08 +1.7952023077252245e-08 +3.081886412929351e-08 +3.611435015764806e-08 +3.521790777144638e-08 +3.874960149207628e-08 +4.0030163030561304e-08 +4.026709403527523e-08 +4.1884848744881024e-08 +4.103344215145882e-08 +3.495541813250907e-08 +2.718994898009039e-08 +1.74106895607588e-08 +9.411823234081524e-09 +6.4629649922692115e-09 +2.9738991287829438e-08 +6.051117598227122e-08 +6.611887182224845e-08 +5.1540588462483515e-08 +3.848275620164753e-08 +3.536871193157473e-08 +3.709839866630033e-08 +3.2967268681923163e-08 +2.9705789717970114e-08 +3.119624434908065e-08 +2.8357345761901436e-08 +3.4198356594033656e-08 +3.868862237119605e-08 +3.6691432889212805e-08 +3.860923445910668e-08 +3.992365502427992e-08 +4.267207111538212e-08 +4.821780164923577e-08 +4.5736723941184e-08 +4.043384152350435e-08 +3.3123003768268256e-08 +2.157403492975194e-08 +1.1112088775713955e-08 +7.86926514928087e-09 +2.779143979642795e-08 +6.055391067614956e-08 +6.799377433405678e-08 +5.01831866571211e-08 +3.866306373697265e-08 +3.597751695513378e-08 +3.337464536952875e-08 +3.593461789704822e-08 +3.120922912145137e-08 +3.1488730455836404e-08 +2.0408199607909525e-08 +3.0352809419708825e-08 +3.643444945121751e-08 +3.751045973381181e-08 +3.317905196293176e-08 +3.0882801805903786e-08 +3.2460698195257676e-08 +3.785184419221681e-08 +3.987188029900425e-08 +3.4573600079126874e-08 +2.862673869754217e-08 +2.1199777629902063e-08 +1.280076664073707e-08 +8.332196938928289e-09 +2.2422893877962164e-08 +4.313845455338125e-08 +4.745350808564248e-08 +5.043844427094053e-08 +4.3643874490596166e-08 +4.709059191609109e-08 +4.977128995381685e-08 +4.6937486657061584e-08 +4.273732370565019e-08 +3.818213406663417e-08 +2.0587438775887697e-08 +2.8032315542115258e-08 +2.6965016562503852e-08 +2.6630781947113104e-08 +2.8329403846673294e-08 +2.612585510251986e-08 +2.6425737598600712e-08 +3.101486844640856e-08 +3.478661609168965e-08 +3.302257723765417e-08 +2.649542802246384e-08 +1.9497128807264876e-08 +1.2884263658007046e-08 +8.822495369078566e-09 +2.270551813228446e-08 +4.252792370564636e-08 +4.227718610752559e-08 +3.931090525974749e-08 +3.560293092686945e-08 +4.339058924726343e-08 +4.8363510518940166e-08 +4.753486836821853e-08 +4.222278155493431e-08 +4.167643493012053e-08 +2.1108308948581704e-08 +2.553915706483249e-08 +3.176609505552752e-08 +2.9987263422841835e-08 +3.141361601313486e-08 +3.2029735243915394e-08 +3.2213740973903074e-08 +3.4751113422929186e-08 +3.22018245688793e-08 +2.7979718995803457e-08 +2.2222122998837608e-08 +1.4269771742804821e-08 +6.9400321037379265e-09 +6.6124542387397714e-09 +2.8228895133955598e-08 +5.6868618603868484e-08 +6.444621946742973e-08 +4.8724125589590415e-08 +3.778313995359703e-08 +4.04220894826878e-08 +4.029150212004805e-08 +3.208290706495248e-08 +3.240004780279189e-08 +3.251017182163221e-08 +2.4728677159009153e-08 +3.781971098970445e-08 +4.269089081710931e-08 +3.755861844652855e-08 +3.81458917589412e-08 +3.7685918525023815e-08 +3.9019076609820634e-08 +4.2581095526683435e-08 +3.6762602590940955e-08 +3.2406375824770026e-08 +2.4372417739850343e-08 +1.5509817504209033e-08 +8.899089089645121e-09 +4.870851098990411e-09 +9.132814992318166e-09 +2.6582951962810812e-08 +3.6057808870362884e-08 +2.541473335996365e-08 +1.9911737519988334e-08 +1.9959978414808685e-08 +2.0062623862220302e-08 +1.8068392935967095e-08 +2.4241912559314203e-08 +2.800042888591373e-08 +1.809691012592052e-08 +3.130595745740291e-08 +4.094024764596261e-08 +3.7405759733809885e-08 +3.804176703366456e-08 +3.798251373696018e-08 +3.9688778572156304e-08 +4.211019207298563e-08 +4.127908445915563e-08 +3.620631193159009e-08 +2.808507645263427e-08 +1.9396537912443567e-08 +9.255841601425602e-09 +5.257682260692952e-09 +8.6102189954483e-09 +2.3522819152707606e-08 +3.3572539875026884e-08 +2.5241657849756395e-08 +2.2216123705273918e-08 +1.6014169074076996e-08 +2.365011923120288e-08 +2.113978469426517e-08 +2.430363131912695e-08 +2.932479348562404e-08 +1.7952023077252245e-08 +3.081886412929351e-08 +3.611435015764806e-08 +3.521790777144638e-08 +3.874960149207628e-08 +4.0030163030561304e-08 +4.026709403527523e-08 +4.1884848744881024e-08 +4.139118084848265e-08 +3.687100078560542e-08 +2.9257321978558438e-08 +2.0038297959551093e-08 +1.2121449372278773e-08 +8.726342307852313e-09 +2.5439305808943694e-08 +5.437250157085569e-08 +6.356202221466626e-08 +5.237424372152548e-08 +4.40420467825972e-08 +3.960856883903081e-08 +3.931172708078362e-08 +3.375999725336628e-08 +3.0194362323944536e-08 +2.6571364286201495e-08 +2.1477553140111236e-08 +2.6781175196723398e-08 +3.7741227080754814e-08 +4.1266921507821034e-08 +3.93224107542532e-08 +3.700397142924993e-08 +3.815172668829766e-08 +4.255545471035644e-08 +4.167536656277357e-08 +3.68620429363117e-08 +2.9109722920470963e-08 +1.8883228493281877e-08 +1.066099120898669e-08 +7.376583438125838e-09 +2.729925117789459e-08 +5.726383234013947e-08 +6.096786193204413e-08 +4.709626248124032e-08 +3.883844034608107e-08 +3.6161769231432297e-08 +3.63797161702118e-08 +3.2640759184271965e-08 +2.7374365620596127e-08 +3.0217208948748725e-08 +1.9247706122801904e-08 +2.9694448587671636e-08 +3.778124976521395e-08 +3.569472833660426e-08 +3.4935283517124085e-08 +3.352388806968848e-08 +3.482072166468871e-08 +4.085420298348065e-08 +4.184170314048463e-08 +3.938347205723705e-08 +3.361815094253165e-08 +2.5176487441591935e-08 +1.5021080534027388e-08 +8.773761381636542e-09 +2.2151035479213068e-08 +4.309193948273676e-08 +4.298469183752286e-08 +4.0515119623976784e-08 +4.326082370565979e-08 +4.8480620016587526e-08 +4.45871606758568e-08 +4.5376191052637354e-08 +4.30969525910571e-08 +4.083932802272686e-08 +2.126018147605702e-08 +2.7143680455756733e-08 +3.2472285871866996e-08 +3.067562072269747e-08 +2.786039058135857e-08 +2.7915616954985956e-08 +3.100812951391236e-08 +3.749040730053044e-08 +3.9353311225211375e-08 +3.67736971749286e-08 +3.1746782261178655e-08 +2.4059139560880712e-08 +1.5951792857435348e-08 +1.1006402590468688e-08 +2.3599988147999445e-08 +4.11627967825444e-08 +4.210057676686301e-08 +4.033604482020585e-08 +4.144057229275356e-08 +4.283659968681371e-08 +4.612224018922875e-08 +4.48003410526268e-08 +4.116822080138281e-08 +4.069986499289698e-08 +2.1408766719387843e-08 +2.662856303031558e-08 +2.862419105233019e-08 +3.022838571483998e-08 +2.9932776688146966e-08 +2.978912237103287e-08 +3.0828232889105296e-08 +3.334358053436335e-08 +3.2056937520211025e-08 +2.8921936813717125e-08 +2.1977959969005814e-08 +1.4845128650193706e-08 +1.0022025353401973e-08 +6.886778100597233e-09 +2.6894504317604597e-08 +5.9556302120401284e-08 +6.528694238738233e-08 +4.677558791294558e-08 +3.643790109956922e-08 +3.803749356427673e-08 +3.529778877615743e-08 +3.0749091523326765e-08 +2.9122789874945298e-08 +3.1405808713291714e-08 +2.1108308948581704e-08 +3.951981216712966e-08 +4.172081326607111e-08 +4.252496514991631e-08 +3.9431219859435724e-08 +3.863808037747456e-08 +4.049958720639409e-08 +4.3924772920742606e-08 +4.106245243403392e-08 +3.516588649985987e-08 +2.6923843328594146e-08 +1.5724559340947667e-08 +9.253704866731686e-09 +4.846607378424817e-09 +8.330060204234372e-09 +2.3403490738262722e-08 +3.227176153905327e-08 +3.144772158613393e-08 +2.4029964914098385e-08 +2.111751334418627e-08 +2.026191546347984e-08 +1.9748934772732603e-08 +2.2247928179371825e-08 +2.4477117739852266e-08 +1.7689862166729384e-08 +3.2135585793367885e-08 +4.164726028333821e-08 +4.090679952979245e-08 +3.725059992219009e-08 +3.7970186421418355e-08 +3.8031494270713044e-08 +4.139027684534291e-08 +3.8826030848435617e-08 +3.337579591897932e-08 +2.5234918917260192e-08 +1.6238361852731026e-08 +8.990804317276315e-09 +4.904627943575017e-09 +7.598228571567891e-09 +1.910175070678667e-08 +2.83800280224984e-08 +2.7330973469888893e-08 +2.5702535086813514e-08 +2.450777166449961e-08 +2.4578366091502472e-08 +2.3561116012990887e-08 +2.3629984615817896e-08 +2.9840650549997706e-08 +2.123133555768914e-08 +2.6621988462026596e-08 +3.637799034603594e-08 +3.4957719231410216e-08 +3.482565259090544e-08 +3.548458869766791e-08 +3.830031193162849e-08 +4.248814756749806e-08 +4.139118084848265e-08 +3.687100078560542e-08 +2.9257321978558438e-08 +2.0038297959551093e-08 +1.2121449372278773e-08 +8.726342307852313e-09 +2.5439305808943694e-08 +5.437250157085569e-08 +6.356202221466626e-08 +5.237424372152548e-08 +4.40420467825972e-08 +3.960856883903081e-08 +3.931172708078362e-08 +3.375999725336628e-08 +3.0194362323944536e-08 +2.6571364286201495e-08 +2.1477553140111236e-08 +2.6781175196723398e-08 +3.7741227080754814e-08 +4.1266921507821034e-08 +3.93224107542532e-08 +3.700397142924993e-08 +3.815172668829766e-08 +4.255545471035644e-08 +4.167536656277357e-08 +3.68620429363117e-08 +2.9109722920470963e-08 +1.8883228493281877e-08 +1.066099120898669e-08 +7.376583438125838e-09 +2.729925117789459e-08 +5.726383234013947e-08 +6.096786193204413e-08 +4.709626248124032e-08 +3.883844034608107e-08 +3.6161769231432297e-08 +3.63797161702118e-08 +3.2640759184271965e-08 +2.7374365620596127e-08 +3.0217208948748725e-08 +1.9247706122801904e-08 +2.9694448587671636e-08 +3.778124976521395e-08 +3.569472833660426e-08 +3.4935283517124085e-08 +3.352388806968848e-08 +3.482072166468871e-08 +4.085420298348065e-08 +4.184170314048463e-08 +3.938347205723705e-08 +3.361815094253165e-08 +2.5176487441591935e-08 +1.5021080534027388e-08 +8.773761381636542e-09 +2.2151035479213068e-08 +4.309193948273676e-08 +4.298469183752286e-08 +4.0515119623976784e-08 +4.326082370565979e-08 +4.8480620016587526e-08 +4.45871606758568e-08 +4.5376191052637354e-08 +4.30969525910571e-08 +4.083932802272686e-08 +2.126018147605702e-08 +2.7143680455756733e-08 +3.2472285871866996e-08 +3.067562072269747e-08 +2.786039058135857e-08 +2.7915616954985956e-08 +3.100812951391236e-08 +3.749040730053044e-08 +3.9353311225211375e-08 +3.67736971749286e-08 +3.1746782261178655e-08 +2.4059139560880712e-08 +1.5951792857435348e-08 +1.1006402590468688e-08 +2.3599988147999445e-08 +4.11627967825444e-08 +4.210057676686301e-08 +4.033604482020585e-08 +4.144057229275356e-08 +4.283659968681371e-08 +4.612224018922875e-08 +4.48003410526268e-08 +4.116822080138281e-08 +4.069986499289698e-08 +2.1408766719387843e-08 +2.662856303031558e-08 +2.862419105233019e-08 +3.022838571483998e-08 +2.9932776688146966e-08 +2.978912237103287e-08 +3.0828232889105296e-08 +3.334358053436335e-08 +3.2056937520211025e-08 +2.8921936813717125e-08 +2.1977959969005814e-08 +1.4845128650193706e-08 +1.0022025353401973e-08 +6.886778100597233e-09 +2.6894504317604597e-08 +5.9556302120401284e-08 +6.528694238738233e-08 +4.677558791294558e-08 +3.643790109956922e-08 +3.803749356427673e-08 +3.529778877615743e-08 +3.0749091523326765e-08 +2.9122789874945298e-08 +3.1405808713291714e-08 +2.1108308948581704e-08 +3.951981216712966e-08 +4.172081326607111e-08 +4.252496514991631e-08 +3.9431219859435724e-08 +3.863808037747456e-08 +4.049958720639409e-08 +4.3924772920742606e-08 +4.106245243403392e-08 +3.516588649985987e-08 +2.6923843328594146e-08 +1.5724559340947667e-08 +9.253704866731686e-09 +4.846607378424817e-09 +8.330060204234372e-09 +2.3403490738262722e-08 +3.227176153905327e-08 +3.144772158613393e-08 +2.4029964914098385e-08 +2.111751334418627e-08 +2.026191546347984e-08 +1.9748934772732603e-08 +2.2247928179371825e-08 +2.4477117739852266e-08 +1.7689862166729384e-08 +3.2135585793367885e-08 +4.164726028333821e-08 +4.090679952979245e-08 +3.725059992219009e-08 +3.7970186421418355e-08 +3.8031494270713044e-08 +4.139027684534291e-08 +3.8826030848435617e-08 +3.337579591897932e-08 +2.5234918917260192e-08 +1.6238361852731026e-08 +8.990804317276315e-09 +4.904627943575017e-09 +7.598228571567891e-09 +1.910175070678667e-08 +2.83800280224984e-08 +2.7330973469888893e-08 +2.5702535086813514e-08 +2.450777166449961e-08 +2.4578366091502472e-08 +2.3561116012990887e-08 +2.3629984615817896e-08 +2.9840650549997706e-08 +2.123133555768914e-08 +2.6621988462026596e-08 +3.637799034603594e-08 +3.4957719231410216e-08 +3.482565259090544e-08 +3.548458869766791e-08 +3.830031193162849e-08 +4.248814756749806e-08 +4.139118084848265e-08 +3.687100078560542e-08 +2.9257321978558438e-08 +2.0038297959551093e-08 +1.2121449372278773e-08 +8.726342307852313e-09 +2.5439305808943694e-08 +5.437250157085569e-08 +6.356202221466626e-08 +5.237424372152548e-08 +4.40420467825972e-08 +3.960856883903081e-08 +3.931172708078362e-08 +3.375999725336628e-08 +3.0194362323944536e-08 +2.6571364286201495e-08 +2.1477553140111236e-08 +2.6781175196723398e-08 +3.7741227080754814e-08 +4.1266921507821034e-08 +3.93224107542532e-08 +3.700397142924993e-08 +3.815172668829766e-08 +4.255545471035644e-08 +4.167536656277357e-08 +3.68620429363117e-08 +2.9109722920470963e-08 +1.8883228493281877e-08 +1.066099120898669e-08 +7.376583438125838e-09 +2.729925117789459e-08 +5.726383234013947e-08 +6.096786193204413e-08 +4.709626248124032e-08 +3.883844034608107e-08 +3.6161769231432297e-08 +3.63797161702118e-08 +3.2640759184271965e-08 +2.7374365620596127e-08 +3.0217208948748725e-08 +1.9247706122801904e-08 +2.9694448587671636e-08 +3.778124976521395e-08 +3.569472833660426e-08 +3.4935283517124085e-08 +3.352388806968848e-08 +3.482072166468871e-08 +4.085420298348065e-08 +4.184170314048463e-08 +3.938347205723705e-08 +3.361815094253165e-08 +2.5176487441591935e-08 +1.5021080534027388e-08 +8.773761381636542e-09 +2.2151035479213068e-08 +4.309193948273676e-08 +4.298469183752286e-08 +4.0515119623976784e-08 +4.326082370565979e-08 +4.8480620016587526e-08 +4.45871606758568e-08 +4.5376191052637354e-08 +4.30969525910571e-08 +4.083932802272686e-08 +2.126018147605702e-08 +2.7143680455756733e-08 +3.2472285871866996e-08 +3.067562072269747e-08 +2.786039058135857e-08 +2.7915616954985956e-08 +3.100812951391236e-08 +3.749040730053044e-08 +3.9353311225211375e-08 +3.67736971749286e-08 +3.1746782261178655e-08 +2.4059139560880712e-08 +1.5951792857435348e-08 +1.1006402590468688e-08 +2.3599988147999445e-08 +4.11627967825444e-08 +4.210057676686301e-08 +4.033604482020585e-08 +4.144057229275356e-08 +4.283659968681371e-08 +4.612224018922875e-08 +4.48003410526268e-08 +4.116822080138281e-08 +4.069986499289698e-08 +2.1408766719387843e-08 +2.662856303031558e-08 +2.862419105233019e-08 +3.022838571483998e-08 +2.9932776688146966e-08 +2.978912237103287e-08 +3.0828232889105296e-08 +3.334358053436335e-08 +3.2056937520211025e-08 +2.8921936813717125e-08 +2.1977959969005814e-08 +1.4845128650193706e-08 +1.0022025353401973e-08 +6.886778100597233e-09 +2.6894504317604597e-08 +5.9556302120401284e-08 +6.528694238738233e-08 +4.677558791294558e-08 +3.643790109956922e-08 +3.803749356427673e-08 +3.529778877615743e-08 +3.0749091523326765e-08 +2.9122789874945298e-08 +3.1405808713291714e-08 +2.1108308948581704e-08 +3.951981216712966e-08 +4.172081326607111e-08 +4.252496514991631e-08 +3.9431219859435724e-08 +3.863808037747456e-08 +4.049958720639409e-08 +4.3924772920742606e-08 +4.106245243403392e-08 +3.516588649985987e-08 +2.6923843328594146e-08 +1.5724559340947667e-08 +9.253704866731686e-09 +4.846607378424817e-09 +8.330060204234372e-09 +2.3403490738262722e-08 +3.227176153905327e-08 +3.144772158613393e-08 +2.4029964914098385e-08 +2.111751334418627e-08 +2.026191546347984e-08 +1.9748934772732603e-08 +2.2247928179371825e-08 +2.4477117739852266e-08 +1.7689862166729384e-08 +3.2135585793367885e-08 +4.164726028333821e-08 +4.090679952979245e-08 +3.725059992219009e-08 +3.7970186421418355e-08 +3.8031494270713044e-08 +4.139027684534291e-08 +3.8826030848435617e-08 +3.337579591897932e-08 +2.5234918917260192e-08 +1.6238361852731026e-08 +8.990804317276315e-09 +4.904627943575017e-09 +7.598228571567891e-09 +1.910175070678667e-08 +2.83800280224984e-08 +2.7330973469888893e-08 +2.5702535086813514e-08 +2.450777166449961e-08 +2.4578366091502472e-08 +2.3561116012990887e-08 +2.3629984615817896e-08 +2.9840650549997706e-08 +2.123133555768914e-08 +2.6621988462026596e-08 +3.637799034603594e-08 +3.4957719231410216e-08 +3.482565259090544e-08 +3.548458869766791e-08 +3.830031193162849e-08 +4.248814756749806e-08 +4.139118084848265e-08 +3.687100078560542e-08 +2.9257321978558438e-08 +2.0038297959551093e-08 +1.2121449372278773e-08 +8.726342307852313e-09 +2.5439305808943694e-08 +5.437250157085569e-08 +6.356202221466626e-08 +5.237424372152548e-08 +4.40420467825972e-08 +3.960856883903081e-08 +3.931172708078362e-08 +3.375999725336628e-08 +3.0194362323944536e-08 +2.6571364286201495e-08 +2.1477553140111236e-08 +2.6781175196723398e-08 +3.7741227080754814e-08 +4.1266921507821034e-08 +3.93224107542532e-08 +3.700397142924993e-08 +3.815172668829766e-08 +4.255545471035644e-08 +4.167536656277357e-08 +3.68620429363117e-08 +2.9109722920470963e-08 +1.8883228493281877e-08 +1.066099120898669e-08 +7.376583438125838e-09 +2.729925117789459e-08 +5.726383234013947e-08 +6.096786193204413e-08 +4.709626248124032e-08 +3.883844034608107e-08 +3.6161769231432297e-08 +3.63797161702118e-08 +3.2640759184271965e-08 +2.7374365620596127e-08 +3.0217208948748725e-08 +1.9247706122801904e-08 +2.9694448587671636e-08 +3.778124976521395e-08 +3.569472833660426e-08 +3.4935283517124085e-08 +3.352388806968848e-08 +3.482072166468871e-08 +4.085420298348065e-08 +4.184170314048463e-08 +3.938347205723705e-08 +3.361815094253165e-08 +2.5176487441591935e-08 +1.5021080534027388e-08 +8.773761381636542e-09 +2.2151035479213068e-08 +4.309193948273676e-08 +4.298469183752286e-08 +4.0515119623976784e-08 +4.326082370565979e-08 +4.8480620016587526e-08 +4.45871606758568e-08 +4.5376191052637354e-08 +4.30969525910571e-08 +4.083932802272686e-08 +2.126018147605702e-08 +2.7143680455756733e-08 +3.2472285871866996e-08 +3.067562072269747e-08 +2.786039058135857e-08 +2.7915616954985956e-08 +3.100812951391236e-08 +3.749040730053044e-08 +3.9353311225211375e-08 +3.67736971749286e-08 +3.1746782261178655e-08 +2.4059139560880712e-08 +1.5951792857435348e-08 +1.1006402590468688e-08 +2.3599988147999445e-08 +4.11627967825444e-08 +4.210057676686301e-08 +4.033604482020585e-08 +4.144057229275356e-08 +4.283659968681371e-08 +4.612224018922875e-08 +4.48003410526268e-08 +4.116822080138281e-08 +4.069986499289698e-08 +2.1408766719387843e-08 +2.662856303031558e-08 +2.862419105233019e-08 +3.022838571483998e-08 +2.9932776688146966e-08 +2.978912237103287e-08 +3.0828232889105296e-08 +3.334358053436335e-08 +3.2056937520211025e-08 +2.8921936813717125e-08 +2.1977959969005814e-08 +1.4845128650193706e-08 +1.0022025353401973e-08 +6.886778100597233e-09 +2.6894504317604597e-08 +5.9556302120401284e-08 +6.528694238738233e-08 +4.677558791294558e-08 +3.643790109956922e-08 +3.803749356427673e-08 +3.529778877615743e-08 +3.0749091523326765e-08 +2.9122789874945298e-08 +3.1405808713291714e-08 +2.1108308948581704e-08 +3.951981216712966e-08 +4.172081326607111e-08 +4.252496514991631e-08 +3.9431219859435724e-08 +3.863808037747456e-08 +4.049958720639409e-08 +4.3924772920742606e-08 +4.106245243403392e-08 +3.516588649985987e-08 +2.6923843328594146e-08 +1.5724559340947667e-08 +9.253704866731686e-09 +4.846607378424817e-09 +8.330060204234372e-09 +2.3403490738262722e-08 +3.227176153905327e-08 +3.144772158613393e-08 +2.4029964914098385e-08 +2.111751334418627e-08 +2.026191546347984e-08 +1.9748934772732603e-08 +2.2247928179371825e-08 +2.4477117739852266e-08 +1.7689862166729384e-08 +3.2135585793367885e-08 +4.164726028333821e-08 +4.090679952979245e-08 +3.725059992219009e-08 +3.7970186421418355e-08 +3.8031494270713044e-08 +4.139027684534291e-08 +3.8826030848435617e-08 +3.337579591897932e-08 +2.5234918917260192e-08 +1.6238361852731026e-08 +8.990804317276315e-09 +4.904627943575017e-09 +7.598228571567891e-09 +1.910175070678667e-08 +2.83800280224984e-08 +2.7330973469888893e-08 +2.5702535086813514e-08 +2.450777166449961e-08 +2.4578366091502472e-08 +2.3561116012990887e-08 +2.3629984615817896e-08 +2.9840650549997706e-08 +2.123133555768914e-08 +2.6621988462026596e-08 +3.637799034603594e-08 +3.4957719231410216e-08 +3.482565259090544e-08 +3.548458869766791e-08 +3.830031193162849e-08 +4.248814756749806e-08 +4.139118084848265e-08 +3.687100078560542e-08 +2.9257321978558438e-08 +2.0038297959551093e-08 +1.2121449372278773e-08 +8.726342307852313e-09 +2.5439305808943694e-08 +5.437250157085569e-08 +6.356202221466626e-08 +5.237424372152548e-08 +4.40420467825972e-08 +3.960856883903081e-08 +3.931172708078362e-08 +3.375999725336628e-08 +3.0194362323944536e-08 +2.6571364286201495e-08 +2.1477553140111236e-08 +2.6781175196723398e-08 +3.7741227080754814e-08 +4.1266921507821034e-08 +3.93224107542532e-08 +3.700397142924993e-08 +3.815172668829766e-08 +4.255545471035644e-08 +4.167536656277357e-08 +3.68620429363117e-08 +2.9109722920470963e-08 +1.8883228493281877e-08 +1.066099120898669e-08 +7.376583438125838e-09 +2.729925117789459e-08 +5.726383234013947e-08 +6.096786193204413e-08 +4.709626248124032e-08 +3.883844034608107e-08 +3.6161769231432297e-08 +3.63797161702118e-08 +3.2640759184271965e-08 +2.7374365620596127e-08 +3.0217208948748725e-08 +1.9247706122801904e-08 +2.9694448587671636e-08 +3.778124976521395e-08 +3.569472833660426e-08 +3.4935283517124085e-08 +3.352388806968848e-08 +3.482072166468871e-08 +4.085420298348065e-08 +4.184170314048463e-08 +3.938347205723705e-08 +3.361815094253165e-08 +2.5176487441591935e-08 +1.5021080534027388e-08 +8.773761381636542e-09 +2.2151035479213068e-08 +4.309193948273676e-08 +4.298469183752286e-08 +4.0515119623976784e-08 +4.326082370565979e-08 +4.8480620016587526e-08 +4.45871606758568e-08 +4.5376191052637354e-08 +4.30969525910571e-08 +4.083932802272686e-08 +2.126018147605702e-08 +2.7143680455756733e-08 +3.2472285871866996e-08 +3.067562072269747e-08 +2.786039058135857e-08 +2.7915616954985956e-08 +3.100812951391236e-08 +3.749040730053044e-08 +3.4662849843649705e-08 +3.796985769300391e-08 +3.5421472842093754e-08 +2.9849690581395044e-08 +2.2315892779059104e-08 +1.4979578571703237e-08 +9.36571907395509e-09 +2.2300689089890848e-08 +4.4232627080873846e-08 +4.3018222135796626e-08 +3.709815211998949e-08 +4.4654139090300725e-08 +4.759642276382406e-08 +5.177012307787233e-08 +4.9480776217547786e-08 +4.459809089563722e-08 +4.47201313195013e-08 +2.5564140424330593e-08 +2.973323854057658e-08 +3.2126956672488606e-08 +2.9341229906346477e-08 +3.040852888595788e-08 +3.0317964207777264e-08 +3.1300451256460894e-08 +3.172360690796002e-08 +3.1790503140300334e-08 +2.840418956096038e-08 +2.08634062798174e-08 +1.3628093877800904e-08 +7.435836734830222e-09 +6.034796232449743e-09 +2.71596237838575e-08 +5.921327401992403e-08 +6.537241177513901e-08 +5.023890612337016e-08 +4.484603430223518e-08 +4.011407095834934e-08 +3.649066201008824e-08 +3.068901640558626e-08 +3.0874583595542565e-08 +3.3180859969211225e-08 +2.1665585793175913e-08 +3.351501240249836e-08 +4.2465629671108316e-08 +4.0198965071380724e-08 +3.9175633517201836e-08 +3.952079835237301e-08 +4.1933582732323056e-08 +4.3888941523567696e-08 +4.0032628493669674e-08 +3.454491852496622e-08 +2.6838127394526638e-08 +1.719709827347074e-08 +8.609150628101342e-09 +4.93519968611875e-09 +7.904192543316045e-09 +2.6886368289346992e-08 +3.641521883897226e-08 +2.959451514967922e-08 +2.3734848980027035e-08 +2.6640068524821277e-08 +2.2509595997273015e-08 +2.3397162716284577e-08 +2.4853676138603285e-08 +3.153639607593147e-08 +1.883761742577712e-08 +3.486625055008986e-08 +4.4736074647602065e-08 +4.1239061774696505e-08 +4.0519064364950175e-08 +4.075385863497018e-08 +4.28089043178964e-08 +4.5367644113861695e-08 +4.4585845762199004e-08 +3.8857506594119084e-08 +3.1365950393039806e-08 +2.0881321978404856e-08 +1.0845325667388813e-08 +5.9457108321341375e-09 +8.48965784944923e-09 +2.1701252826143597e-08 +3.278597496135469e-08 +2.7426551256389862e-08 +2.440307166449769e-08 +2.0848202590649148e-08 +2.6431901256371627e-08 +2.817342221401737e-08 +2.80703658560877e-08 +3.275729340719404e-08 +1.9111037284494845e-08 +3.020668963948637e-08 +3.968146436493482e-08 +3.8228484773071445e-08 +3.8020974961450686e-08 +3.708779717493436e-08 +3.968910730057075e-08 +4.326353571507899e-08 +4.21241630305997e-08 +3.780072692377004e-08 +2.991831263791122e-08 +1.843459638966298e-08 +1.0604860832219567e-08 +8.36202904253951e-09 +2.9181714443235233e-08 +5.882258029935173e-08 +6.802138752087047e-08 +5.314305730081744e-08 +4.132116169620508e-08 +3.6849633438666255e-08 +3.7080811696127326e-08 +3.666751789706166e-08 +3.235525855632325e-08 +3.2955845369521076e-08 +2.2043212559273887e-08 +3.559906836799968e-08 +4.156737927862717e-08 +4.094115164910234e-08 +4.124530761457103e-08 +4.0493341366519564e-08 +4.4799683595797905e-08 +5.1154825668127926e-08 +5.1085546154782856e-08 +4.653232888625352e-08 +3.743000345437549e-08 +2.5051652826205026e-08 +1.4618963501052981e-08 +9.616867582593916e-09 +2.797454152327589e-08 +6.118548014240918e-08 +6.683878704989118e-08 +5.036628838396904e-08 +4.3097610047885996e-08 +4.391721216721029e-08 +4.014472488299669e-08 +3.7082373156095954e-08 +3.2995046232944086e-08 +3.332969175885289e-08 +2.1996368760214938e-08 +3.085568171171177e-08 +3.68432232345845e-08 +3.3642805573615304e-08 +3.3517560047710337e-08 +3.216870518112359e-08 +3.498804442764311e-08 +4.2196812010192874e-08 +4.523187927869436e-08 +4.1766753061990315e-08 +3.548056177459091e-08 +2.5639008320721294e-08 +1.558082284172996e-08 +1.0622283438185352e-08 +2.413006271629802e-08 +4.697709843100265e-08 +4.662240047181248e-08 +4.420246624884818e-08 +4.808680337607795e-08 +5.017135243420094e-08 +5.43206446634764e-08 +4.7860145134315546e-08 +4.345674584067123e-08 +4.410360117820272e-08 +2.2700998116585786e-08 +2.8284203689686594e-08 +3.187161687656556e-08 +2.8246646468335827e-08 +2.7923342072725502e-08 +2.5509078414910432e-08 +2.820834960805255e-08 +3.4662849843649705e-08 +3.796985769300391e-08 +3.5421472842093754e-08 +2.9849690581395044e-08 +2.2315892779059104e-08 +1.4979578571703237e-08 +9.36571907395509e-09 +2.2300689089890848e-08 +4.4232627080873846e-08 +4.3018222135796626e-08 +3.709815211998949e-08 +4.4654139090300725e-08 +4.759642276382406e-08 +5.177012307787233e-08 +4.9480776217547786e-08 +4.459809089563722e-08 +4.47201313195013e-08 +2.5564140424330593e-08 +2.973323854057658e-08 +3.2126956672488606e-08 +2.9341229906346477e-08 +3.040852888595788e-08 +3.0317964207777264e-08 +3.1300451256460894e-08 +3.172360690796002e-08 +3.1790503140300334e-08 +2.840418956096038e-08 +2.08634062798174e-08 +1.3628093877800904e-08 +7.435836734830222e-09 +6.034796232449743e-09 +2.71596237838575e-08 +5.921327401992403e-08 +6.537241177513901e-08 +5.023890612337016e-08 +4.484603430223518e-08 +4.011407095834934e-08 +3.649066201008824e-08 +3.068901640558626e-08 +3.0874583595542565e-08 +3.3180859969211225e-08 +2.1665585793175913e-08 +3.351501240249836e-08 +4.2465629671108316e-08 +4.0198965071380724e-08 +3.9175633517201836e-08 +3.952079835237301e-08 +4.1933582732323056e-08 +4.3888941523567696e-08 +4.0032628493669674e-08 +3.454491852496622e-08 +2.6838127394526638e-08 +1.719709827347074e-08 +8.609150628101342e-09 +4.93519968611875e-09 +7.904192543316045e-09 +2.6886368289346992e-08 +3.641521883897226e-08 +2.959451514967922e-08 +2.3734848980027035e-08 +2.6640068524821277e-08 +2.2509595997273015e-08 +2.3397162716284577e-08 +2.4853676138603285e-08 +3.153639607593147e-08 +1.883761742577712e-08 +3.486625055008986e-08 +4.4736074647602065e-08 +4.1239061774696505e-08 +4.0519064364950175e-08 +4.075385863497018e-08 +4.28089043178964e-08 +4.5367644113861695e-08 +4.4585845762199004e-08 +3.8857506594119084e-08 +3.1365950393039806e-08 +2.0881321978404856e-08 +1.0845325667388813e-08 +5.9457108321341375e-09 +8.48965784944923e-09 +2.1701252826143597e-08 +3.278597496135469e-08 +2.7426551256389862e-08 +2.440307166449769e-08 +2.0848202590649148e-08 +2.6431901256371627e-08 +2.817342221401737e-08 +2.80703658560877e-08 +3.275729340719404e-08 +1.9111037284494845e-08 +3.020668963948637e-08 +3.968146436493482e-08 +3.8228484773071445e-08 +3.8020974961450686e-08 +3.708779717493436e-08 +3.968910730057075e-08 +4.326353571507899e-08 +4.21241630305997e-08 +3.780072692377004e-08 +2.991831263791122e-08 +1.843459638966298e-08 +1.0604860832219567e-08 +8.36202904253951e-09 +2.9181714443235233e-08 +5.882258029935173e-08 +6.802138752087047e-08 +5.314305730081744e-08 +4.132116169620508e-08 +3.6849633438666255e-08 +3.7080811696127326e-08 +3.666751789706166e-08 +3.235525855632325e-08 +3.2955845369521076e-08 +2.2043212559273887e-08 +3.559906836799968e-08 +4.156737927862717e-08 +4.094115164910234e-08 +4.124530761457103e-08 +4.0493341366519564e-08 +4.4799683595797905e-08 +5.1154825668127926e-08 +5.1085546154782856e-08 +4.653232888625352e-08 +3.743000345437549e-08 +2.5051652826205026e-08 +1.4618963501052981e-08 +9.616867582593916e-09 +2.797454152327589e-08 +6.118548014240918e-08 +6.683878704989118e-08 +5.036628838396904e-08 +4.3097610047885996e-08 +4.391721216721029e-08 +4.014472488299669e-08 +3.7082373156095954e-08 +3.2995046232944086e-08 +3.332969175885289e-08 +2.1996368760214938e-08 +3.085568171171177e-08 +3.68432232345845e-08 +3.3642805573615304e-08 +3.3517560047710337e-08 +3.216870518112359e-08 +3.498804442764311e-08 +4.2196812010192874e-08 +4.523187927869436e-08 +4.1766753061990315e-08 +3.548056177459091e-08 +2.5639008320721294e-08 +1.558082284172996e-08 +1.0622283438185352e-08 +2.413006271629802e-08 +4.697709843100265e-08 +4.662240047181248e-08 +4.420246624884818e-08 +4.808680337607795e-08 +5.017135243420094e-08 +5.43206446634764e-08 +4.7860145134315546e-08 +4.345674584067123e-08 +4.410360117820272e-08 +2.2700998116585786e-08 +2.8284203689686594e-08 +3.187161687656556e-08 +2.8246646468335827e-08 +2.7923342072725502e-08 +2.5509078414910432e-08 +2.820834960805255e-08 +3.4662849843649705e-08 +3.796985769300391e-08 +3.5421472842093754e-08 +2.9849690581395044e-08 +2.2315892779059104e-08 +1.4979578571703237e-08 +9.36571907395509e-09 +2.2300689089890848e-08 +4.4232627080873846e-08 +4.3018222135796626e-08 +3.709815211998949e-08 +4.4654139090300725e-08 +4.759642276382406e-08 +5.177012307787233e-08 +4.9480776217547786e-08 +4.459809089563722e-08 +4.47201313195013e-08 +2.5564140424330593e-08 +2.973323854057658e-08 +3.2126956672488606e-08 +2.9341229906346477e-08 +3.040852888595788e-08 +3.0317964207777264e-08 +3.1300451256460894e-08 +3.172360690796002e-08 +3.1790503140300334e-08 +2.840418956096038e-08 +2.08634062798174e-08 +1.3628093877800904e-08 +7.435836734830222e-09 +6.034796232449743e-09 +2.71596237838575e-08 +5.921327401992403e-08 +6.537241177513901e-08 +5.023890612337016e-08 +4.484603430223518e-08 +4.011407095834934e-08 +3.649066201008824e-08 +3.068901640558626e-08 +3.0874583595542565e-08 +3.3180859969211225e-08 +2.1665585793175913e-08 +3.351501240249836e-08 +4.2465629671108316e-08 +4.0198965071380724e-08 +3.9175633517201836e-08 +3.952079835237301e-08 +4.1933582732323056e-08 +4.3888941523567696e-08 +4.0032628493669674e-08 +3.454491852496622e-08 +2.6838127394526638e-08 +1.719709827347074e-08 +8.609150628101342e-09 +4.93519968611875e-09 +7.904192543316045e-09 +2.6886368289346992e-08 +3.641521883897226e-08 +2.959451514967922e-08 +2.3734848980027035e-08 +2.6640068524821277e-08 +2.2509595997273015e-08 +2.3397162716284577e-08 +2.4853676138603285e-08 +3.153639607593147e-08 +1.883761742577712e-08 +3.486625055008986e-08 +4.4736074647602065e-08 +4.1239061774696505e-08 +4.0519064364950175e-08 +4.075385863497018e-08 +4.28089043178964e-08 +4.5367644113861695e-08 +4.4585845762199004e-08 +3.8857506594119084e-08 +3.1365950393039806e-08 +2.0881321978404856e-08 +1.0845325667388813e-08 +5.9457108321341375e-09 +8.48965784944923e-09 +2.1701252826143597e-08 +3.278597496135469e-08 +2.7426551256389862e-08 +2.440307166449769e-08 +2.0848202590649148e-08 +2.6431901256371627e-08 +2.817342221401737e-08 +2.80703658560877e-08 +3.275729340719404e-08 +1.9111037284494845e-08 +3.020668963948637e-08 +3.968146436493482e-08 +3.8228484773071445e-08 +3.8020974961450686e-08 +3.708779717493436e-08 +3.968910730057075e-08 +4.326353571507899e-08 +4.21241630305997e-08 +3.780072692377004e-08 +2.991831263791122e-08 +1.843459638966298e-08 +1.0604860832219567e-08 +8.36202904253951e-09 +2.9181714443235233e-08 +5.882258029935173e-08 +6.802138752087047e-08 +5.314305730081744e-08 +4.132116169620508e-08 +3.6849633438666255e-08 +3.7080811696127326e-08 +3.666751789706166e-08 +3.235525855632325e-08 +3.2955845369521076e-08 +2.2043212559273887e-08 +3.559906836799968e-08 +4.156737927862717e-08 +4.094115164910234e-08 +4.124530761457103e-08 +4.0493341366519564e-08 +4.4799683595797905e-08 +5.1154825668127926e-08 +5.1085546154782856e-08 +4.653232888625352e-08 +3.743000345437549e-08 +2.5051652826205026e-08 +1.4618963501052981e-08 +9.616867582593916e-09 +2.797454152327589e-08 +6.118548014240918e-08 +6.683878704989118e-08 +5.036628838396904e-08 +4.3097610047885996e-08 +4.391721216721029e-08 +4.014472488299669e-08 +3.7082373156095954e-08 +3.2995046232944086e-08 +3.332969175885289e-08 +2.1996368760214938e-08 +3.085568171171177e-08 +3.68432232345845e-08 +3.3642805573615304e-08 +3.3517560047710337e-08 +3.216870518112359e-08 +3.498804442764311e-08 +4.2196812010192874e-08 +4.523187927869436e-08 +4.1766753061990315e-08 +3.548056177459091e-08 +2.5639008320721294e-08 +1.558082284172996e-08 +1.0622283438185352e-08 +2.413006271629802e-08 +4.697709843100265e-08 +4.662240047181248e-08 +4.420246624884818e-08 +4.808680337607795e-08 +5.017135243420094e-08 +5.43206446634764e-08 +4.7860145134315546e-08 +4.345674584067123e-08 +4.410360117820272e-08 +2.2700998116585786e-08 +2.8284203689686594e-08 +3.187161687656556e-08 +2.8246646468335827e-08 +2.7923342072725502e-08 +2.5509078414910432e-08 +2.820834960805255e-08 +3.4662849843649705e-08 +3.796985769300391e-08 +3.5421472842093754e-08 +2.9849690581395044e-08 +2.2315892779059104e-08 +1.4979578571703237e-08 +9.36571907395509e-09 +2.2300689089890848e-08 +4.4232627080873846e-08 +4.3018222135796626e-08 +3.709815211998949e-08 +4.4654139090300725e-08 +4.759642276382406e-08 +5.177012307787233e-08 +4.9480776217547786e-08 +4.459809089563722e-08 +4.47201313195013e-08 +2.5564140424330593e-08 +2.973323854057658e-08 +3.2126956672488606e-08 +2.9341229906346477e-08 +3.040852888595788e-08 +3.0317964207777264e-08 +3.1300451256460894e-08 +3.172360690796002e-08 +3.1790503140300334e-08 +2.840418956096038e-08 +2.08634062798174e-08 +1.3628093877800904e-08 +7.435836734830222e-09 +6.034796232449743e-09 +2.71596237838575e-08 +5.921327401992403e-08 +6.537241177513901e-08 +5.023890612337016e-08 +4.484603430223518e-08 +4.011407095834934e-08 +3.649066201008824e-08 +3.068901640558626e-08 +3.0874583595542565e-08 +3.3180859969211225e-08 +2.1665585793175913e-08 +3.351501240249836e-08 +4.2465629671108316e-08 +4.0198965071380724e-08 +3.9175633517201836e-08 +3.952079835237301e-08 +4.1933582732323056e-08 +4.3888941523567696e-08 +4.0032628493669674e-08 +3.454491852496622e-08 +2.6838127394526638e-08 +1.719709827347074e-08 +8.609150628101342e-09 +4.93519968611875e-09 +7.904192543316045e-09 +2.6886368289346992e-08 +3.641521883897226e-08 +2.959451514967922e-08 +2.3734848980027035e-08 +2.6640068524821277e-08 +2.2509595997273015e-08 +2.3397162716284577e-08 +2.4853676138603285e-08 +3.153639607593147e-08 +1.883761742577712e-08 +3.486625055008986e-08 +4.4736074647602065e-08 +4.1239061774696505e-08 +4.0519064364950175e-08 +4.075385863497018e-08 +4.28089043178964e-08 +4.5367644113861695e-08 +4.4585845762199004e-08 +3.8857506594119084e-08 +3.1365950393039806e-08 +2.0881321978404856e-08 +1.0845325667388813e-08 +5.9457108321341375e-09 +8.48965784944923e-09 +2.1701252826143597e-08 +3.278597496135469e-08 +2.7426551256389862e-08 +2.440307166449769e-08 +2.0848202590649148e-08 +2.6431901256371627e-08 +2.817342221401737e-08 +2.80703658560877e-08 +3.275729340719404e-08 +1.9111037284494845e-08 +3.020668963948637e-08 +3.968146436493482e-08 +3.8228484773071445e-08 +3.8020974961450686e-08 +3.708779717493436e-08 +3.968910730057075e-08 +4.326353571507899e-08 +4.21241630305997e-08 +3.780072692377004e-08 +2.991831263791122e-08 +1.843459638966298e-08 +1.0604860832219567e-08 +8.36202904253951e-09 +2.9181714443235233e-08 +5.882258029935173e-08 +6.802138752087047e-08 +5.314305730081744e-08 +4.132116169620508e-08 +3.6849633438666255e-08 +3.7080811696127326e-08 +3.666751789706166e-08 +3.235525855632325e-08 +3.2955845369521076e-08 +2.2043212559273887e-08 +3.559906836799968e-08 +4.156737927862717e-08 +4.094115164910234e-08 +4.124530761457103e-08 +4.0493341366519564e-08 +4.4799683595797905e-08 +5.1154825668127926e-08 +5.1085546154782856e-08 +4.653232888625352e-08 +3.743000345437549e-08 +2.5051652826205026e-08 +1.4618963501052981e-08 +9.616867582593916e-09 +2.797454152327589e-08 +6.118548014240918e-08 +6.683878704989118e-08 +5.036628838396904e-08 +4.3097610047885996e-08 +4.391721216721029e-08 +4.014472488299669e-08 +3.7082373156095954e-08 +3.2995046232944086e-08 +3.332969175885289e-08 +2.1996368760214938e-08 +3.085568171171177e-08 +3.68432232345845e-08 +3.3642805573615304e-08 +3.3517560047710337e-08 +3.216870518112359e-08 +3.498804442764311e-08 +4.2196812010192874e-08 +4.523187927869436e-08 +4.1766753061990315e-08 +3.548056177459091e-08 +2.5639008320721294e-08 +1.558082284172996e-08 +1.0622283438185352e-08 +2.413006271629802e-08 +4.697709843100265e-08 +4.662240047181248e-08 +4.420246624884818e-08 +4.808680337607795e-08 +5.017135243420094e-08 +5.43206446634764e-08 +4.7860145134315546e-08 +4.345674584067123e-08 +4.410360117820272e-08 +2.2700998116585786e-08 +2.8284203689686594e-08 +3.187161687656556e-08 +2.8246646468335827e-08 +2.7923342072725502e-08 +2.5509078414910432e-08 +2.820834960805255e-08 +3.4662849843649705e-08 +3.796985769300391e-08 +3.5421472842093754e-08 +2.9849690581395044e-08 +2.2315892779059104e-08 +1.4979578571703237e-08 +9.36571907395509e-09 +2.2300689089890848e-08 +4.4232627080873846e-08 +4.3018222135796626e-08 +3.709815211998949e-08 +4.4654139090300725e-08 +4.759642276382406e-08 +5.177012307787233e-08 +4.9480776217547786e-08 +4.459809089563722e-08 +4.47201313195013e-08 +2.5564140424330593e-08 +2.973323854057658e-08 +3.2126956672488606e-08 +2.9341229906346477e-08 +3.040852888595788e-08 +3.0317964207777264e-08 +3.1300451256460894e-08 +3.172360690796002e-08 +3.1790503140300334e-08 +2.840418956096038e-08 +2.08634062798174e-08 +1.3628093877800904e-08 +7.435836734830222e-09 +6.034796232449743e-09 +2.71596237838575e-08 +5.921327401992403e-08 +6.537241177513901e-08 +5.023890612337016e-08 +4.484603430223518e-08 +4.011407095834934e-08 +3.649066201008824e-08 +3.068901640558626e-08 +3.0874583595542565e-08 +3.3180859969211225e-08 +2.1665585793175913e-08 +3.351501240249836e-08 +4.2465629671108316e-08 +4.0198965071380724e-08 +3.9175633517201836e-08 +3.952079835237301e-08 +4.1933582732323056e-08 +4.320255659419875e-08 +4.369145792858762e-08 +3.894149670401073e-08 +3.033275698642745e-08 +2.0578974019215637e-08 +1.2271267347163782e-08 +6.307558634338575e-09 +6.64450525914852e-09 +2.278391985913048e-08 +3.0051776374177405e-08 +2.798769065985384e-08 +2.4630633909399817e-08 +3.0233070094745875e-08 +2.7632828336456437e-08 +2.8230785322338677e-08 +2.835085337571607e-08 +3.3426666641115266e-08 +2.087984270053984e-08 +2.8541598038199948e-08 +3.440693477300137e-08 +3.1283932653634847e-08 +3.018622629568693e-08 +3.120051781846848e-08 +3.4445971272217156e-08 +4.5683387755939696e-08 +4.487381185325608e-08 +4.124489670405297e-08 +3.211988901157796e-08 +2.2828626923495507e-08 +1.3176421036348353e-08 +5.991075353328063e-09 +8.04373775524953e-09 +1.808104897992337e-08 +2.6606702590754737e-08 +2.541407590313475e-08 +2.498409913703581e-08 +2.782505227680533e-08 +3.0535089325520645e-08 +2.6593471272073173e-08 +3.135304780277269e-08 +3.465964474160883e-08 +1.9390456436776265e-08 +3.0634858399305834e-08 +3.6296301335045434e-08 +3.59014163271889e-08 +3.586172237114421e-08 +3.840361483586901e-08 +4.2375886813963813e-08 +4.836646907467021e-08 +4.7629706515787e-08 +4.3111498823396454e-08 +3.3079693799664635e-08 +2.212399756712466e-08 +1.2966363579515615e-08 +8.010289639079372e-09 +2.76885478027055e-08 +5.6497402041852264e-08 +5.975962064473781e-08 +5.229460926312527e-08 +4.4061606123256894e-08 +4.136775894895318e-08 +4.2394295605172947e-08 +4.3267644820259605e-08 +4.308503618603333e-08 +3.8746889482657085e-08 +2.6217323783840216e-08 +3.124432087969378e-08 +3.6494771115268856e-08 +3.7079743328780364e-08 +3.687330188450657e-08 +3.7454904631769975e-08 +4.18812327323221e-08 +4.6852921272444654e-08 +4.776440298360736e-08 +4.3437926138944047e-08 +3.471643257520485e-08 +2.360434379949089e-08 +1.41589902671356e-08 +8.802771664211643e-09 +2.860364552642714e-08 +5.850091954581364e-08 +5.97230496086304e-08 +4.8849946390220674e-08 +4.25012145219724e-08 +4.329969584066835e-08 +4.1758781397939946e-08 +3.925452833666953e-08 +4.018310392538358e-08 +3.6559366248708025e-08 +2.2717516719411836e-08 +2.985799097385988e-08 +3.226748806966544e-08 +3.348550902730159e-08 +3.2558330534348953e-08 +3.1646684458979014e-08 +3.5048119545383616e-08 +4.314609748901718e-08 +4.599872048749963e-08 +4.295313390973578e-08 +3.619209442766518e-08 +2.5490751805804922e-08 +1.550743422320428e-08 +9.691653296881005e-09 +2.4666465306574734e-08 +4.3852945762185566e-08 +4.699246648437814e-08 +4.17909146004523e-08 +4.581750894903477e-08 +5.0574455652418706e-08 +5.5644927081083095e-08 +5.1785326767040587e-08 +4.715239285800744e-08 +4.613464968687418e-08 +2.408330109934269e-08 +2.951085376820202e-08 +3.079741460025073e-08 +2.716389725324533e-08 +2.731774215120733e-08 +2.7460163736767242e-08 +3.1031880141856285e-08 +3.6725785008522695e-08 +3.911309293635297e-08 +3.740165062862928e-08 +3.2150049843603634e-08 +2.5010808320709775e-08 +1.7650661303306373e-08 +1.131228438011323e-08 +2.44456419941688e-08 +4.4772892230020325e-08 +4.2994389325749095e-08 +3.8559760832732145e-08 +4.4501526923892894e-08 +5.071917833687975e-08 +5.276986836831453e-08 +5.4089219859704496e-08 +5.145240706530764e-08 +4.5904868525174526e-08 +2.5467165542068223e-08 +2.598392660958162e-08 +2.942390510258033e-08 +3.0278763344354247e-08 +3.1644794270595935e-08 +3.2408266013153105e-08 +3.400703665682449e-08 +3.732185180602185e-08 +3.6746001806011294e-08 +3.3408340032009745e-08 +2.6945785950258595e-08 +1.7694546546635278e-08 +9.458831397347691e-09 +6.661516954596243e-09 +2.446298241803097e-08 +5.715740651596169e-08 +6.123347449091869e-08 +4.9403771586463166e-08 +4.4552890738650516e-08 +4.2353615463884915e-08 +3.62880009425806e-08 +3.7049253768340246e-08 +3.5656678022631817e-08 +3.5558388226711655e-08 +2.5701713265777388e-08 +3.5616573156069076e-08 +4.225318893327082e-08 +4.016124348582274e-08 +3.9258801806057365e-08 +3.8299654474799595e-08 +3.999540000073336e-08 +4.320255659419875e-08 +4.369145792858762e-08 +3.894149670401073e-08 +3.033275698642745e-08 +2.0578974019215637e-08 +1.2271267347163782e-08 +6.307558634338575e-09 +6.64450525914852e-09 +2.278391985913048e-08 +3.0051776374177405e-08 +2.798769065985384e-08 +2.4630633909399817e-08 +3.0233070094745875e-08 +2.7632828336456437e-08 +2.8230785322338677e-08 +2.835085337571607e-08 +3.3426666641115266e-08 +2.087984270053984e-08 +2.8541598038199948e-08 +3.440693477300137e-08 +3.1283932653634847e-08 +3.018622629568693e-08 +3.120051781846848e-08 +3.4445971272217156e-08 +4.5683387755939696e-08 +4.487381185325608e-08 +4.124489670405297e-08 +3.211988901157796e-08 +2.2828626923495507e-08 +1.3176421036348353e-08 +5.991075353328063e-09 +8.04373775524953e-09 +1.808104897992337e-08 +2.6606702590754737e-08 +2.541407590313475e-08 +2.498409913703581e-08 +2.782505227680533e-08 +3.0535089325520645e-08 +2.6593471272073173e-08 +3.135304780277269e-08 +3.465964474160883e-08 +1.9390456436776265e-08 +3.0634858399305834e-08 +3.6296301335045434e-08 +3.59014163271889e-08 +3.586172237114421e-08 +3.840361483586901e-08 +4.2375886813963813e-08 +4.836646907467021e-08 +4.7629706515787e-08 +4.3111498823396454e-08 +3.3079693799664635e-08 +2.212399756712466e-08 +1.2966363579515615e-08 +8.010289639079372e-09 +2.76885478027055e-08 +5.6497402041852264e-08 +5.975962064473781e-08 +5.229460926312527e-08 +4.4061606123256894e-08 +4.136775894895318e-08 +4.2394295605172947e-08 +4.3267644820259605e-08 +4.308503618603333e-08 +3.8746889482657085e-08 +2.6217323783840216e-08 +3.124432087969378e-08 +3.6494771115268856e-08 +3.7079743328780364e-08 +3.687330188450657e-08 +3.7454904631769975e-08 +4.18812327323221e-08 +4.6852921272444654e-08 +4.776440298360736e-08 +4.3437926138944047e-08 +3.471643257520485e-08 +2.360434379949089e-08 +1.41589902671356e-08 +8.802771664211643e-09 +2.860364552642714e-08 +5.850091954581364e-08 +5.97230496086304e-08 +4.8849946390220674e-08 +4.25012145219724e-08 +4.329969584066835e-08 +4.1758781397939946e-08 +3.925452833666953e-08 +4.018310392538358e-08 +3.6559366248708025e-08 +2.2717516719411836e-08 +2.985799097385988e-08 +3.226748806966544e-08 +3.348550902730159e-08 +3.2558330534348953e-08 +3.1646684458979014e-08 +3.5048119545383616e-08 +4.314609748901718e-08 +4.599872048749963e-08 +4.295313390973578e-08 +3.619209442766518e-08 +2.5490751805804922e-08 +1.550743422320428e-08 +9.691653296881005e-09 +2.4666465306574734e-08 +4.3852945762185566e-08 +4.699246648437814e-08 +4.17909146004523e-08 +4.581750894903477e-08 +5.0574455652418706e-08 +5.5644927081083095e-08 +5.1785326767040587e-08 +4.715239285800744e-08 +4.613464968687418e-08 +2.408330109934269e-08 +2.951085376820202e-08 +3.079741460025073e-08 +2.716389725324533e-08 +2.731774215120733e-08 +2.7460163736767242e-08 +3.1031880141856285e-08 +3.6725785008522695e-08 +3.911309293635297e-08 +3.740165062862928e-08 +3.2150049843603634e-08 +2.5010808320709775e-08 +1.7650661303306373e-08 +1.131228438011323e-08 +2.44456419941688e-08 +4.4772892230020325e-08 +4.2994389325749095e-08 +3.8559760832732145e-08 +4.4501526923892894e-08 +5.071917833687975e-08 +5.276986836831453e-08 +5.4089219859704496e-08 +5.145240706530764e-08 +4.5904868525174526e-08 +2.5467165542068223e-08 +2.598392660958162e-08 +2.942390510258033e-08 +3.0278763344354247e-08 +3.1644794270595935e-08 +3.2408266013153105e-08 +3.400703665682449e-08 +3.732185180602185e-08 +3.6746001806011294e-08 +3.3408340032009745e-08 +2.6945785950258595e-08 +1.7694546546635278e-08 +9.458831397347691e-09 +6.661516954596243e-09 +2.446298241803097e-08 +5.715740651596169e-08 +6.123347449091869e-08 +4.9403771586463166e-08 +4.4552890738650516e-08 +4.2353615463884915e-08 +3.62880009425806e-08 +3.7049253768340246e-08 +3.5656678022631817e-08 +3.5558388226711655e-08 +2.5701713265777388e-08 +3.5616573156069076e-08 +4.225318893327082e-08 +4.016124348582274e-08 +3.9258801806057365e-08 +3.8299654474799595e-08 +3.999540000073336e-08 +4.320255659419875e-08 +4.369145792858762e-08 +3.894149670401073e-08 +3.033275698642745e-08 +2.0578974019215637e-08 +1.2271267347163782e-08 +6.307558634338575e-09 +6.64450525914852e-09 +2.278391985913048e-08 +3.0051776374177405e-08 +2.798769065985384e-08 +2.4630633909399817e-08 +3.0233070094745875e-08 +2.7632828336456437e-08 +2.8230785322338677e-08 +2.835085337571607e-08 +3.3426666641115266e-08 +2.087984270053984e-08 +2.8541598038199948e-08 +3.440693477300137e-08 +3.1283932653634847e-08 +3.018622629568693e-08 +3.120051781846848e-08 +3.4445971272217156e-08 +4.5683387755939696e-08 +4.487381185325608e-08 +4.124489670405297e-08 +3.211988901157796e-08 +2.2828626923495507e-08 +1.3176421036348353e-08 +5.991075353328063e-09 +8.04373775524953e-09 +1.808104897992337e-08 +2.6606702590754737e-08 +2.541407590313475e-08 +2.498409913703581e-08 +2.782505227680533e-08 +3.0535089325520645e-08 +2.6593471272073173e-08 +3.135304780277269e-08 +3.465964474160883e-08 +1.9390456436776265e-08 +3.0634858399305834e-08 +3.6296301335045434e-08 +3.59014163271889e-08 +3.586172237114421e-08 +3.840361483586901e-08 +4.2375886813963813e-08 +4.836646907467021e-08 +4.7629706515787e-08 +4.3111498823396454e-08 +3.3079693799664635e-08 +2.212399756712466e-08 +1.2966363579515615e-08 +8.010289639079372e-09 +2.76885478027055e-08 +5.6497402041852264e-08 +5.975962064473781e-08 +5.229460926312527e-08 +4.4061606123256894e-08 +4.136775894895318e-08 +4.2394295605172947e-08 +4.3267644820259605e-08 +4.308503618603333e-08 +3.8746889482657085e-08 +2.6217323783840216e-08 +3.124432087969378e-08 +3.6494771115268856e-08 +3.7079743328780364e-08 +3.687330188450657e-08 +3.7454904631769975e-08 +4.18812327323221e-08 +4.6852921272444654e-08 +4.776440298360736e-08 +4.3437926138944047e-08 +3.471643257520485e-08 +2.360434379949089e-08 +1.41589902671356e-08 +8.802771664211643e-09 +2.860364552642714e-08 +5.850091954581364e-08 +5.97230496086304e-08 +4.8849946390220674e-08 +4.25012145219724e-08 +4.329969584066835e-08 +4.1758781397939946e-08 +3.925452833666953e-08 +4.018310392538358e-08 +3.6559366248708025e-08 +2.2717516719411836e-08 +2.985799097385988e-08 +3.226748806966544e-08 +3.348550902730159e-08 +3.2558330534348953e-08 +3.1646684458979014e-08 +3.5048119545383616e-08 +4.314609748901718e-08 +4.599872048749963e-08 +4.295313390973578e-08 +3.619209442766518e-08 +2.5490751805804922e-08 +1.550743422320428e-08 +9.691653296881005e-09 +2.4666465306574734e-08 +4.3852945762185566e-08 +4.699246648437814e-08 +4.17909146004523e-08 +4.581750894903477e-08 +5.0574455652418706e-08 +5.5644927081083095e-08 +5.1785326767040587e-08 +4.715239285800744e-08 +4.613464968687418e-08 +2.408330109934269e-08 +2.951085376820202e-08 +3.079741460025073e-08 +2.716389725324533e-08 +2.731774215120733e-08 +2.7460163736767242e-08 +3.1031880141856285e-08 +3.6725785008522695e-08 +3.911309293635297e-08 +3.740165062862928e-08 +3.2150049843603634e-08 +2.5010808320709775e-08 +1.7650661303306373e-08 +1.131228438011323e-08 +2.44456419941688e-08 +4.4772892230020325e-08 +4.2994389325749095e-08 +3.8559760832732145e-08 +4.4501526923892894e-08 +5.071917833687975e-08 +5.276986836831453e-08 +5.4089219859704496e-08 +5.145240706530764e-08 +4.5904868525174526e-08 +2.5467165542068223e-08 +2.598392660958162e-08 +2.942390510258033e-08 +3.0278763344354247e-08 +3.1644794270595935e-08 +3.2408266013153105e-08 +3.400703665682449e-08 +3.732185180602185e-08 +3.6746001806011294e-08 +3.3408340032009745e-08 +2.6945785950258595e-08 +1.7694546546635278e-08 +9.458831397347691e-09 +6.661516954596243e-09 +2.446298241803097e-08 +5.715740651596169e-08 +6.123347449091869e-08 +4.9403771586463166e-08 +4.4552890738650516e-08 +4.2353615463884915e-08 +3.62880009425806e-08 +3.7049253768340246e-08 +3.5656678022631817e-08 +3.5558388226711655e-08 +2.5701713265777388e-08 +3.5616573156069076e-08 +4.225318893327082e-08 +4.016124348582274e-08 +3.9258801806057365e-08 +3.8299654474799595e-08 +3.999540000073336e-08 +4.320255659419875e-08 +4.369145792858762e-08 +3.894149670401073e-08 +3.033275698642745e-08 +2.0578974019215637e-08 +1.2271267347163782e-08 +6.307558634338575e-09 +6.64450525914852e-09 +2.278391985913048e-08 +3.0051776374177405e-08 +2.798769065985384e-08 +2.4630633909399817e-08 +3.0233070094745875e-08 +2.7632828336456437e-08 +2.8230785322338677e-08 +2.835085337571607e-08 +3.3426666641115266e-08 +2.087984270053984e-08 +2.8541598038199948e-08 +3.440693477300137e-08 +3.1283932653634847e-08 +3.018622629568693e-08 +3.120051781846848e-08 +3.4445971272217156e-08 +4.5683387755939696e-08 +4.487381185325608e-08 +4.124489670405297e-08 +3.211988901157796e-08 +2.2828626923495507e-08 +1.3176421036348353e-08 +5.991075353328063e-09 +8.04373775524953e-09 +1.808104897992337e-08 +2.6606702590754737e-08 +2.541407590313475e-08 +2.498409913703581e-08 +2.782505227680533e-08 +3.0535089325520645e-08 +2.6593471272073173e-08 +3.135304780277269e-08 +3.465964474160883e-08 +1.9390456436776265e-08 +3.0634858399305834e-08 +3.6296301335045434e-08 +3.59014163271889e-08 +3.586172237114421e-08 +3.840361483586901e-08 +4.2375886813963813e-08 +4.836646907467021e-08 +4.7629706515787e-08 +4.3111498823396454e-08 +3.3079693799664635e-08 +2.212399756712466e-08 +1.2966363579515615e-08 +8.010289639079372e-09 +2.76885478027055e-08 +5.6497402041852264e-08 +5.975962064473781e-08 +5.229460926312527e-08 +4.4061606123256894e-08 +4.136775894895318e-08 +4.2394295605172947e-08 +4.3267644820259605e-08 +4.308503618603333e-08 +3.8746889482657085e-08 +2.6217323783840216e-08 +3.124432087969378e-08 +3.6494771115268856e-08 +3.7079743328780364e-08 +3.687330188450657e-08 +3.7454904631769975e-08 +4.18812327323221e-08 +4.6852921272444654e-08 +4.776440298360736e-08 +4.3437926138944047e-08 +3.471643257520485e-08 +2.360434379949089e-08 +1.41589902671356e-08 +8.802771664211643e-09 +2.860364552642714e-08 +5.850091954581364e-08 +5.97230496086304e-08 +4.8849946390220674e-08 +4.25012145219724e-08 +4.329969584066835e-08 +4.1758781397939946e-08 +3.925452833666953e-08 +4.018310392538358e-08 +3.6559366248708025e-08 +2.2717516719411836e-08 +2.985799097385988e-08 +3.226748806966544e-08 +3.348550902730159e-08 +3.2558330534348953e-08 +3.1646684458979014e-08 +3.5048119545383616e-08 +4.314609748901718e-08 +4.599872048749963e-08 +4.295313390973578e-08 +3.619209442766518e-08 +2.5490751805804922e-08 +1.550743422320428e-08 +9.691653296881005e-09 +2.4666465306574734e-08 +4.3852945762185566e-08 +4.699246648437814e-08 +4.17909146004523e-08 +4.581750894903477e-08 +5.0574455652418706e-08 +5.5644927081083095e-08 +5.1785326767040587e-08 +4.715239285800744e-08 +4.613464968687418e-08 +2.408330109934269e-08 +2.951085376820202e-08 +3.079741460025073e-08 +2.716389725324533e-08 +2.731774215120733e-08 +2.7460163736767242e-08 +3.1031880141856285e-08 +3.6725785008522695e-08 +3.911309293635297e-08 +3.740165062862928e-08 +3.2150049843603634e-08 +2.5010808320709775e-08 +1.7650661303306373e-08 +1.131228438011323e-08 +2.44456419941688e-08 +4.4772892230020325e-08 +4.2994389325749095e-08 +3.8559760832732145e-08 +4.4501526923892894e-08 +5.071917833687975e-08 +5.276986836831453e-08 +5.4089219859704496e-08 +5.145240706530764e-08 +4.5904868525174526e-08 +2.5467165542068223e-08 +2.598392660958162e-08 +2.942390510258033e-08 +3.0278763344354247e-08 +3.1644794270595935e-08 +3.2408266013153105e-08 +3.400703665682449e-08 +3.732185180602185e-08 +3.6746001806011294e-08 +3.3408340032009745e-08 +2.6945785950258595e-08 +1.7694546546635278e-08 +9.458831397347691e-09 +6.661516954596243e-09 +2.446298241803097e-08 +5.715740651596169e-08 +6.123347449091869e-08 +4.9403771586463166e-08 +4.4552890738650516e-08 +4.2353615463884915e-08 +3.62880009425806e-08 +3.7049253768340246e-08 +3.5656678022631817e-08 +3.5558388226711655e-08 +2.5701713265777388e-08 +3.5616573156069076e-08 +4.225318893327082e-08 +4.016124348582274e-08 +3.9258801806057365e-08 +3.8299654474799595e-08 +3.999540000073336e-08 +4.320255659419875e-08 +4.369145792858762e-08 +3.894149670401073e-08 +3.033275698642745e-08 +2.0578974019215637e-08 +1.2271267347163782e-08 +6.307558634338575e-09 +6.64450525914852e-09 +2.278391985913048e-08 +3.0051776374177405e-08 +2.798769065985384e-08 +2.4630633909399817e-08 +3.0233070094745875e-08 +2.7632828336456437e-08 +2.8230785322338677e-08 +2.835085337571607e-08 +3.3426666641115266e-08 +2.087984270053984e-08 +2.8541598038199948e-08 +3.440693477300137e-08 +3.1283932653634847e-08 +3.018622629568693e-08 +3.120051781846848e-08 +3.4445971272217156e-08 +4.5683387755939696e-08 +4.487381185325608e-08 +4.124489670405297e-08 +3.211988901157796e-08 +2.2828626923495507e-08 +1.3176421036348353e-08 +5.991075353328063e-09 +8.04373775524953e-09 +1.808104897992337e-08 +2.6606702590754737e-08 +2.541407590313475e-08 +2.498409913703581e-08 +2.782505227680533e-08 +3.0535089325520645e-08 +2.6593471272073173e-08 +3.135304780277269e-08 +3.465964474160883e-08 +1.9390456436776265e-08 +3.0634858399305834e-08 +3.6296301335045434e-08 +3.59014163271889e-08 +3.586172237114421e-08 +3.840361483586901e-08 +4.2375886813963813e-08 +4.836646907467021e-08 +4.7629706515787e-08 +4.3111498823396454e-08 +3.3079693799664635e-08 +2.212399756712466e-08 +1.2966363579515615e-08 +8.010289639079372e-09 +2.76885478027055e-08 +5.6497402041852264e-08 +5.975962064473781e-08 +5.229460926312527e-08 +4.4061606123256894e-08 +4.136775894895318e-08 +4.2394295605172947e-08 +4.3267644820259605e-08 +4.308503618603333e-08 +3.8746889482657085e-08 +2.6217323783840216e-08 +3.124432087969378e-08 +3.6494771115268856e-08 +3.7079743328780364e-08 +3.687330188450657e-08 +3.7454904631769975e-08 +4.18812327323221e-08 \ No newline at end of file diff --git a/examples/curve_examples/interconnector_8_price_curve.csv b/examples/curve_examples/interconnector_8_price_curve.csv new file mode 100644 index 0000000..0e71a91 --- /dev/null +++ b/examples/curve_examples/interconnector_8_price_curve.csv @@ -0,0 +1,8760 @@ +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.01 +0.01 +0.0 +0.0 +0.0 +0.0 +0.02 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.02 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.01 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.01 +0.01 +0.01 +0.02 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.01 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.01 +0.01 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.01 +14.45 +14.45 +26.01 +14.45 +0.01 +0.01 +0.0 +0.0 +0.01 +14.45 +0.01 +0.03 +0.12 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +14.45 +14.45 +14.45 +14.45 +14.45 +0.02 +0.01 +0.01 +0.01 +0.0 +0.01 +0.02 +0.02 +0.02 +0.02 +14.45 +45.18 +26.01 +26.01 +26.01 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +45.19 +45.19 +45.19 +45.18 +45.18 +45.18 +14.45 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +14.45 +14.46 +14.46 +14.46 +26.01 +26.01 +26.02 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +26.01 +26.01 +26.01 +45.18 +45.18 +45.18 +26.02 +26.02 +45.18 +26.02 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +26.01 +26.01 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +26.01 +45.18 +45.18 +45.18 +43.01 +43.01 +45.18 +45.18 +43.01 +26.01 +26.01 +26.01 +26.01 +14.45 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +45.18 +45.18 +45.18 +57.37 +45.19 +45.19 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +60.17 +103.94 +118.57 +105.28 +105.28 +105.28 +105.28 +105.28 +103.94 +105.28 +83.48 +72.01 +72.01 +72.01 +72.01 +72.01 +72.01 +83.48 +60.17 +60.17 +60.17 +60.17 +60.17 +60.17 +83.49 +105.28 +103.94 +105.28 +124.41 +137.56 +118.57 +103.95 +83.49 +86.31 +86.3 +83.48 +83.48 +86.3 +86.33 +105.28 +105.28 +118.57 +105.28 +103.96 +103.96 +103.96 +103.95 +104.48 +137.56 +150.0 +141.96 +150.0 +150.0 +150.0 +150.0 +124.41 +124.41 +105.28 +103.94 +105.28 +105.28 +103.96 +103.95 +105.28 +118.57 +150.0 +150.0 +137.56 +105.28 +103.99 +103.99 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +103.96 +83.5 +86.3 +86.3 +86.3 +105.28 +118.57 +124.41 +124.41 +118.59 +103.94 +83.48 +83.48 +83.48 +86.3 +103.96 +86.3 +105.28 +83.48 +105.28 +68.57 +45.18 +45.18 +45.18 +43.02 +14.45 +14.45 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +14.45 +14.45 +0.01 +0.01 +0.02 +14.45 +14.45 +14.48 +26.02 +26.01 +26.03 +26.02 +26.03 +26.01 +26.02 +14.46 +14.45 +14.45 +0.0 +0.0 +0.0 +0.0 +14.45 +14.45 +14.46 +14.46 +14.45 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.01 +14.45 +14.45 +14.45 +14.45 +14.45 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.01 +14.45 +14.45 +14.45 +14.45 +14.45 +0.01 +14.45 +14.46 +14.46 +14.46 +14.45 +14.45 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.01 +0.01 +0.0 +0.04 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.01 +14.45 +14.46 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +14.45 +45.18 +43.01 +45.18 +45.18 +45.18 +14.46 +14.46 +14.46 +45.18 +45.18 +45.18 +45.19 +105.28 +83.48 +105.28 +83.48 +83.48 +83.48 +103.94 +103.94 +60.17 +60.17 +45.19 +45.19 +45.19 +60.17 +103.96 +103.96 +103.94 +103.96 +105.28 +103.94 +60.17 +60.17 +60.17 +57.37 +60.17 +45.19 +45.19 +45.19 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +14.45 +14.45 +14.45 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +43.03 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +43.01 +26.01 +26.03 +14.46 +14.45 +14.45 +26.02 +26.01 +26.01 +26.01 +26.02 +26.01 +45.18 +26.01 +26.01 +43.01 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +26.01 +43.01 +43.01 +14.45 +14.45 +14.45 +45.18 +45.18 +43.01 +45.18 +14.5 +14.46 +45.18 +45.18 +45.18 +45.19 +118.57 +124.41 +105.28 +124.41 +137.56 +141.96 +119.92 +118.57 +103.98 +104.47 +105.28 +105.28 +105.28 +104.47 +150.0 +150.0 +150.0 +103.96 +103.99 +118.57 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +141.96 +104.47 +104.47 +124.41 +118.58 +103.96 +103.95 +103.94 +103.96 +105.28 +118.57 +137.56 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +103.94 +103.95 +86.3 +86.3 +103.94 +86.3 +103.95 +104.47 +105.28 +103.94 +86.3 +86.32 +86.32 +86.31 +104.47 +105.28 +105.28 +103.94 +118.57 +105.28 +83.49 +83.49 +83.48 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +34.33 +26.02 +26.02 +26.02 +26.02 +26.02 +26.01 +45.18 +45.18 +36.54 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +45.18 +45.18 +45.18 +45.18 +60.17 +105.28 +137.56 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +104.47 +103.94 +60.17 +45.19 +45.19 +83.48 +83.48 +103.94 +124.41 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +124.41 +105.28 +103.94 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +57.37 +72.02 +103.95 +118.57 +124.41 +137.56 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +141.96 +103.97 +105.28 +105.28 +86.3 +141.96 +86.3 +68.57 +83.48 +103.95 +137.56 +141.96 +150.0 +137.56 +105.28 +124.41 +83.48 +45.21 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +57.37 +45.19 +45.19 +45.21 +105.28 +137.56 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +137.56 +105.28 +105.28 +124.41 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +83.48 +83.48 +83.48 +83.48 +83.48 +86.3 +86.3 +83.48 +83.48 +83.48 +83.48 +83.48 +86.3 +86.3 +83.48 +103.97 +150.0 +150.0 +150.0 +150.0 +150.0 +137.56 +150.0 +118.58 +105.28 +105.28 +118.57 +118.58 +118.59 +150.0 +150.0 +150.0 +150.0 +105.28 +105.28 +104.47 +105.28 +137.56 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +104.47 +105.28 +104.48 +137.56 +141.96 +137.56 +141.96 +104.47 +83.48 +45.19 +45.18 +45.18 +45.18 +14.45 +14.45 +14.45 +45.18 +45.18 +45.18 +45.18 +14.46 +14.46 +14.46 +14.46 +14.45 +14.45 +14.45 +45.18 +45.18 +45.18 +45.18 +14.45 +14.45 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.02 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.01 +26.01 +14.49 +26.01 +26.02 +45.18 +45.18 +26.01 +26.01 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +26.03 +26.01 +14.46 +14.46 +14.46 +14.46 +14.46 +14.47 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +43.01 +45.18 +14.45 +0.02 +0.02 +0.02 +0.05 +0.02 +0.02 +14.45 +14.45 +14.45 +14.46 +14.46 +14.46 +14.45 +45.18 +14.46 +26.02 +14.45 +14.45 +14.45 +14.45 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.01 +0.01 +0.02 +14.45 +0.02 +0.02 +0.01 +0.01 +0.03 +26.01 +45.18 +45.19 +45.2 +60.17 +83.48 +105.28 +57.37 +60.17 +45.2 +45.19 +45.18 +45.18 +45.18 +45.18 +26.01 +14.45 +14.45 +14.45 +14.45 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +14.45 +14.45 +26.01 +26.01 +14.45 +14.45 +0.01 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.05 +0.01 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +14.46 +14.46 +14.46 +14.46 +45.18 +45.18 +45.18 +45.18 +57.37 +45.19 +45.19 +45.19 +45.19 +57.37 +45.19 +45.19 +45.19 +45.19 +45.19 +45.19 +45.18 +45.19 +60.17 +60.17 +72.01 +60.17 +68.57 +60.17 +68.57 +60.17 +57.37 +105.28 +105.28 +86.3 +68.57 +45.19 +60.17 +45.18 +45.18 +43.01 +45.18 +45.18 +45.18 +45.18 +45.18 +43.02 +45.18 +43.04 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +45.19 +45.19 +60.17 +72.01 +103.95 +103.94 +119.92 +118.57 +105.28 +105.28 +105.28 +83.48 +75.03 +68.57 +83.48 +75.02 +73.62 +45.2 +45.18 +45.19 +60.17 +68.57 +45.2 +57.37 +45.2 +45.2 +57.37 +60.17 +83.48 +83.48 +86.3 +103.95 +103.94 +82.35 +83.5 +86.3 +83.48 +83.5 +82.35 +72.01 +82.35 +73.61 +60.17 +83.49 +86.31 +104.47 +103.95 +103.95 +103.95 +103.95 +137.56 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +137.56 +137.56 +118.57 +104.47 +104.47 +86.3 +150.0 +141.96 +72.01 +45.2 +45.19 +45.18 +45.18 +45.18 +45.18 +45.19 +57.37 +57.37 +57.37 +45.18 +45.18 +45.18 +45.18 +45.18 +43.02 +43.01 +43.01 +43.02 +43.06 +14.45 +45.18 +14.45 +0.01 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.01 +14.45 +14.49 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +14.46 +45.18 +45.18 +45.18 +45.19 +45.19 +45.18 +45.18 +45.18 +26.02 +26.02 +26.02 +26.02 +26.02 +26.02 +14.46 +26.02 +26.02 +26.01 +26.01 +26.01 +26.02 +26.01 +26.03 +45.18 +45.18 +45.18 +45.2 +68.57 +73.61 +60.17 +57.37 +57.37 +45.19 +45.19 +45.19 +45.19 +45.19 +45.19 +45.19 +45.19 +45.19 +45.18 +45.18 +45.18 +45.18 +43.01 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +14.45 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.01 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +14.45 +14.45 +14.45 +14.45 +14.45 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +14.46 +14.46 +14.45 +45.18 +14.45 +14.45 +14.45 +14.45 +26.01 +43.04 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +43.01 +0.02 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +0.01 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +14.45 +0.03 +0.01 +0.01 +0.01 +0.01 +14.45 +45.18 +45.18 +45.18 +45.18 +45.19 +57.37 +45.19 +45.19 +45.19 +45.19 +45.19 +45.18 +45.18 +45.19 +57.37 +45.19 +45.19 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +68.57 +103.94 +137.56 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +124.41 +105.28 +105.28 +104.47 +103.95 +89.33 +104.47 +104.47 +103.95 +103.94 +103.94 +86.32 +86.31 +86.3 +103.96 +124.41 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +141.96 +105.28 +118.57 +150.0 +150.0 +150.0 +150.0 +141.96 +118.57 +124.41 +137.56 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +105.28 +104.47 +105.28 +104.47 +150.0 +118.57 +104.47 +104.47 +104.47 +86.3 +60.17 +86.3 +118.57 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +105.28 +103.94 +86.3 +86.3 +86.3 +86.3 +86.3 +73.61 +45.19 +57.37 +45.18 +45.19 +45.18 +45.18 +45.18 +45.18 +57.37 +103.94 +103.94 +83.48 +83.48 +83.48 +68.57 +60.17 +45.19 +45.19 +57.37 +45.18 +45.18 +45.18 +45.18 +43.04 +14.47 +0.01 +0.01 +0.0 +0.0 +0.0 +0.01 +14.45 +14.46 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +43.04 +43.04 +43.04 +14.54 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +45.18 +45.18 +45.18 +105.28 +105.28 +105.28 +103.95 +103.94 +89.33 +103.94 +103.94 +103.95 +86.3 +60.17 +45.23 +45.2 +57.37 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +60.17 +73.61 +83.48 +83.48 +83.48 +86.3 +86.3 +83.48 +73.61 +73.61 +60.17 +45.19 +45.19 +45.18 +45.18 +45.18 +26.01 +26.01 +26.01 +26.01 +26.01 +26.01 +26.01 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +43.01 +14.47 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +0.04 +14.45 +14.45 +14.45 +14.45 +14.45 +45.18 +45.18 +45.18 +45.19 +60.17 +72.01 +72.01 +105.28 +72.01 +60.17 +45.19 +45.19 +45.19 +45.19 +45.19 +45.19 +60.17 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.2 +103.94 +73.61 +73.61 +73.61 +73.61 +45.2 +45.2 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +14.46 +26.04 +14.45 +14.45 +14.45 +34.32 +14.5 +14.46 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +26.02 +26.02 +26.02 +26.01 +14.49 +43.01 +45.18 +45.18 +45.19 +60.17 +60.17 +57.37 +60.17 +57.37 +45.19 +45.19 +45.19 +45.19 +45.19 +45.18 +45.19 +45.19 +45.18 +45.18 +45.18 +26.02 +26.02 +26.02 +43.01 +14.48 +43.04 +45.18 +45.19 +57.37 +45.19 +57.37 +60.17 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +26.01 +26.01 +26.01 +26.01 +26.01 +45.18 +45.18 +57.37 +57.37 +45.19 +57.37 +57.37 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +43.01 +26.01 +26.01 +26.01 +26.01 +45.18 +45.18 +45.18 +45.19 +57.37 +45.19 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +26.01 +26.01 +26.01 +26.01 +26.01 +45.18 +45.18 +60.17 +72.01 +60.17 +60.17 +72.01 +60.17 +68.57 +60.17 +60.17 +60.17 +60.17 +60.17 +60.17 +68.57 +57.37 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +45.21 +45.19 +45.19 +45.19 +45.19 +45.19 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +14.45 +0.01 +0.01 +0.0 +0.0 +0.0 +0.0 +0.0 +0.01 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +26.01 +14.45 +26.01 +45.18 +14.45 +14.45 +14.45 +0.04 +14.45 +14.45 +14.45 +14.45 +43.02 +45.18 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +14.45 +26.01 +26.01 +26.01 +26.01 +26.02 +26.01 +26.01 +45.18 +45.18 +45.18 +45.18 +45.18 +45.2 +57.37 +57.37 +57.37 +60.17 +45.19 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +103.94 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +141.96 +137.56 +124.41 +124.41 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +118.57 +105.28 +105.28 +104.47 +83.48 +60.17 +45.19 +45.18 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +26.03 +26.01 +26.01 +26.01 +26.01 +45.18 +26.01 +26.02 +45.18 +45.18 +45.18 +26.01 +43.01 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +43.02 +43.01 +43.01 +43.01 +43.02 +43.02 +43.02 +43.01 +43.01 +45.18 +45.18 +60.17 +105.28 +105.28 +105.28 +105.28 +105.28 +83.48 +83.48 +83.48 +83.48 +68.57 +60.17 +60.17 +68.57 +60.17 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.2 +60.17 +60.17 +60.17 +72.01 +60.17 +60.17 +57.37 +45.19 +57.37 +45.19 +45.19 +45.19 +57.37 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +45.19 +45.19 +60.17 +72.01 +73.61 +73.61 +73.61 +68.57 +60.17 +45.19 +45.21 +45.19 +45.19 +45.18 +45.18 +45.19 +57.37 +45.18 +45.18 +45.18 +45.18 +26.04 +26.02 +26.01 +26.01 +14.5 +14.53 +14.53 +14.52 +14.51 +14.51 +14.5 +14.45 +14.48 +45.18 +14.49 +14.45 +14.45 +14.45 +0.01 +0.01 +0.01 +0.03 +0.01 +0.01 +0.01 +0.01 +0.02 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +0.01 +0.01 +0.01 +0.01 +0.01 +0.01 +0.03 +0.01 +0.01 +0.01 +0.01 +0.01 +0.01 +0.01 +0.01 +14.45 +45.18 +45.18 +45.18 +45.19 +60.17 +60.17 +60.17 +60.17 +60.17 +45.19 +57.37 +45.19 +45.19 +57.37 +45.19 +45.18 +45.19 +45.18 +45.18 +45.18 +45.19 +45.19 +45.19 +45.19 +86.3 +124.41 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +118.57 +104.48 +105.28 +104.48 +104.47 +104.47 +103.94 +86.31 +104.47 +103.94 +103.95 +86.3 +86.3 +103.94 +103.95 +86.3 +104.47 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +137.56 +124.41 +118.57 +105.28 +105.28 +150.0 +124.41 +60.17 +45.2 +57.37 +60.17 +60.17 +60.17 +60.17 +45.19 +105.28 +103.95 +119.92 +103.95 +105.28 +105.28 +105.28 +103.97 +103.96 +86.3 +86.3 +86.3 +86.3 +83.48 +83.48 +57.37 +45.18 +45.18 +26.02 +26.02 +26.02 +26.02 +26.02 +14.45 +14.46 +14.45 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +43.03 +43.01 +43.02 +43.01 +43.01 +43.01 +43.02 +26.01 +26.01 +26.01 +26.01 +26.01 +26.01 +26.01 +26.01 +26.02 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +57.37 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.01 +26.01 +26.01 +26.01 +26.01 +26.01 +14.47 +26.01 +26.01 +26.01 +26.04 +26.04 +26.04 +14.45 +14.45 +14.45 +14.45 +0.02 +0.02 +0.02 +0.01 +0.01 +0.01 +0.01 +14.45 +14.45 +26.02 +26.01 +14.49 +26.01 +45.18 +14.45 +14.45 +14.45 +14.45 +14.45 +14.46 +14.46 +45.18 +14.46 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +14.48 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +45.19 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +45.19 +45.18 +57.37 +57.37 +57.37 +57.37 +57.37 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +43.04 +45.18 +45.18 +26.03 +26.03 +26.01 +26.02 +14.47 +14.5 +14.48 +14.48 +45.18 +45.18 +45.18 +45.19 +60.17 +60.17 +60.17 +60.17 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +45.19 +45.19 +45.18 +45.19 +45.18 +45.19 +45.18 +45.19 +45.18 +45.18 +45.18 +45.18 +45.19 +45.19 +60.17 +73.61 +72.02 +73.61 +73.61 +45.19 +57.37 +45.18 +45.18 +45.18 +45.18 +26.01 +26.02 +14.45 +0.02 +0.0 +0.01 +0.01 +0.01 +0.01 +0.01 +0.02 +0.01 +0.01 +0.01 +0.01 +0.01 +0.01 +0.01 +0.01 +0.01 +0.01 +0.01 +0.01 +0.01 +0.01 +0.0 +0.02 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.02 +14.45 +14.45 +14.45 +14.46 +14.45 +14.46 +14.45 +14.45 +14.45 +0.07 +0.01 +0.0 +0.02 +0.01 +0.01 +0.01 +0.01 +0.02 +0.02 +0.02 +14.45 +14.45 +26.02 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +43.01 +14.45 +14.45 +14.45 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.01 +0.01 +0.01 +0.03 +0.01 +0.01 +0.01 +0.01 +0.01 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.02 +0.01 +0.01 +0.01 +0.01 +0.01 +0.01 +0.02 +26.02 +14.46 +26.02 +45.18 +26.01 +14.46 +14.46 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +0.02 +0.01 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +14.45 +14.45 +14.45 +14.45 +14.45 +45.18 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +0.08 +14.45 +0.02 +0.03 +26.02 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +72.01 +83.48 +83.48 +83.48 +83.48 +83.48 +83.48 +83.48 +72.01 +60.17 +60.17 +57.37 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +45.18 +45.18 +45.18 +60.17 +86.3 +118.57 +118.57 +124.41 +124.41 +137.56 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +83.48 +105.28 +105.28 +68.57 +57.37 +45.19 +60.17 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +57.37 +83.48 +83.48 +86.3 +83.48 +83.48 +83.48 +83.48 +83.48 +83.48 +86.3 +105.28 +105.28 +83.48 +83.48 +60.17 +57.37 +45.19 +60.17 +72.01 +72.01 +73.61 +72.01 +86.3 +103.97 +118.57 +118.57 +105.28 +105.28 +105.28 +105.28 +60.17 +60.17 +60.17 +60.17 +57.37 +60.17 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +73.61 +103.95 +119.92 +105.28 +103.94 +103.94 +103.94 +103.94 +86.3 +86.3 +60.17 +60.17 +60.17 +60.17 +60.17 +60.17 +60.17 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +43.01 +14.46 +14.45 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.01 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.01 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +26.01 +26.01 +14.45 +14.45 +26.01 +26.01 +45.18 +45.18 +45.18 +45.19 +45.19 +57.37 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +26.02 +14.45 +0.01 +0.01 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.01 +0.01 +0.01 +0.01 +0.01 +0.01 +14.45 +43.01 +45.18 +45.18 +43.01 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +14.46 +14.46 +14.46 +14.45 +0.01 +0.01 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +14.45 +26.01 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +60.17 +60.17 +118.57 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +103.94 +72.01 +83.48 +68.57 +73.61 +72.01 +73.61 +57.37 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +14.49 +26.01 +26.01 +14.49 +14.45 +14.45 +0.05 +14.45 +14.45 +26.01 +26.04 +26.01 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +73.61 +83.48 +105.28 +103.95 +105.28 +103.94 +83.48 +86.3 +103.95 +60.17 +60.17 +60.17 +57.37 +57.37 +57.37 +45.19 +45.18 +45.19 +45.19 +45.2 +45.19 +45.18 +45.2 +45.19 +45.19 +45.19 +45.19 +45.19 +60.17 +45.2 +45.19 +60.17 +60.17 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +14.45 +14.45 +14.45 +14.45 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +26.01 +26.01 +14.47 +14.45 +0.02 +0.02 +0.02 +0.01 +0.01 +0.02 +0.02 +14.45 +26.01 +45.18 +45.18 +45.18 +57.37 +60.17 +60.17 +60.17 +60.17 +60.17 +60.17 +45.2 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +124.41 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +124.42 +150.0 +150.0 +150.0 +45.19 +45.19 +45.19 +45.18 +45.19 +45.19 +45.18 +45.19 +45.19 +60.17 +83.48 +60.17 +45.21 +45.18 +45.18 +45.18 +45.18 +26.01 +26.01 +45.18 +14.46 +14.46 +0.02 +0.01 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.01 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.01 +0.01 +0.01 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +14.45 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +43.01 +34.35 +26.05 +26.05 +26.05 +26.05 +26.05 +43.01 +45.18 +45.18 +45.19 +57.37 +60.17 +60.17 +60.17 +68.57 +105.28 +86.3 +60.17 +60.17 +60.17 +45.2 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +83.48 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +137.56 +118.57 +103.94 +83.48 +83.48 +86.32 +86.3 +86.3 +118.57 +118.57 +105.28 +105.28 +103.95 +86.3 +83.48 +118.57 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +137.56 +124.41 +104.47 +86.31 +86.31 +118.57 +83.48 +83.48 +83.48 +83.48 +73.61 +73.61 +83.48 +86.3 +86.3 +89.33 +124.41 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +103.94 +86.3 +103.94 +68.57 +105.28 +60.17 +60.17 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +43.02 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +60.17 +105.28 +60.17 +73.61 +60.17 +60.17 +60.17 +124.41 +124.41 +124.41 +124.41 +105.28 +103.95 +86.3 +83.48 +86.3 +86.3 +105.28 +124.41 +141.96 +124.41 +124.41 +118.57 +124.41 +124.41 +119.92 +118.57 +73.61 +73.61 +73.61 +73.61 +83.48 +103.94 +103.94 +68.57 +60.17 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +43.01 +43.01 +43.01 +14.46 +14.46 +14.46 +14.46 +14.46 +0.01 +0.05 +14.45 +26.03 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +60.17 +60.17 +60.17 +60.17 +60.17 +60.17 +57.37 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +83.48 +141.96 +137.56 +150.0 +150.0 +141.96 +141.96 +83.48 +72.01 +57.37 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +43.01 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +14.53 +14.49 +14.49 +14.54 +26.02 +14.45 +0.02 +0.0 +0.01 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.01 +0.02 +0.01 +0.01 +0.01 +0.01 +0.01 +0.01 +0.01 +0.01 +0.01 +0.02 +45.18 +45.18 +45.18 +45.19 +57.37 +60.17 +60.17 +83.48 +60.17 +83.48 +86.3 +103.94 +103.94 +60.17 +105.28 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +141.96 +103.96 +103.94 +86.3 +86.3 +60.17 +45.21 +60.17 +60.17 +60.17 +60.17 +60.17 +60.17 +60.17 +45.22 +45.21 +68.57 +86.3 +83.48 +86.3 +86.3 +83.48 +105.28 +105.28 +105.28 +60.17 +60.17 +60.17 +45.19 +45.18 +45.18 +45.18 +57.37 +57.37 +57.37 +57.37 +57.37 +57.37 +45.19 +45.19 +45.2 +60.17 +103.94 +118.57 +150.0 +150.0 +150.0 +150.0 +137.56 +124.42 +103.94 +89.33 +103.94 +103.96 +86.3 +86.3 +86.3 +86.3 +83.48 +83.48 +103.94 +103.95 +118.57 +137.56 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +141.96 +105.28 +68.57 +60.17 +45.19 +45.19 +45.18 +45.18 +45.18 +43.01 +26.03 +26.03 +26.04 +14.49 +43.01 +45.18 +45.18 +45.18 +45.18 +14.46 +14.45 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +14.45 +14.45 +0.0 +14.45 +0.06 +0.06 +0.03 +14.45 +14.45 +14.45 +0.04 +0.04 +0.04 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +83.48 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +124.41 +105.28 +89.33 +104.47 +104.47 +73.61 +60.17 +73.61 +73.61 +73.61 +73.61 +73.61 +73.61 +73.61 +104.47 +118.57 +118.57 +105.28 +83.48 +83.48 +83.48 +83.48 +83.48 +83.48 +68.57 +83.48 +72.01 +60.17 +60.17 +68.57 +72.01 +72.01 +73.61 +73.61 +68.57 +57.37 +86.3 +119.92 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +141.96 +124.41 +105.28 +86.3 +105.28 +68.57 +45.19 +45.18 +45.19 +45.19 +45.19 +45.19 +45.2 +45.18 +45.19 +45.21 +45.21 +45.19 +45.19 +57.37 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +26.02 +26.01 +26.01 +45.18 +0.02 +14.45 +14.45 +0.01 +14.45 +26.02 +14.5 +14.45 +14.45 +0.01 +0.0 +0.01 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +14.45 +14.45 +14.45 +14.46 +14.46 +14.46 +14.46 +14.46 +14.46 +14.46 +14.45 +14.45 +26.03 +14.45 +14.45 +0.04 +0.04 +14.45 +14.45 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +26.02 +26.02 +26.02 +26.03 +26.02 +45.18 +45.18 +26.02 +26.01 +45.18 +45.18 +45.18 +45.18 +60.17 +60.17 +68.57 +83.48 +103.94 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +105.28 +83.48 +60.17 +60.17 +45.19 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +45.19 +45.19 +57.37 +57.37 +45.19 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +83.48 +83.48 +83.48 +83.48 +105.28 +60.17 +60.17 +60.17 +57.37 +57.37 +45.19 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +14.45 +14.45 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +14.48 +14.45 +0.03 +0.02 +0.05 +0.02 +0.01 +0.01 +0.0 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +43.01 +43.02 +43.01 +43.01 +43.03 +43.01 +43.04 +26.03 +26.01 +14.5 +26.01 +26.02 +26.04 +26.02 +45.18 +45.18 +45.21 +45.18 +45.19 +57.37 +57.37 +45.19 +57.37 +57.37 +45.19 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +45.19 +45.19 +57.37 +57.37 +57.37 +45.18 +45.18 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.22 +60.17 +103.94 +103.95 +86.3 +86.3 +86.3 +86.3 +68.57 +72.01 +60.17 +60.17 +60.17 +68.57 +60.17 +60.17 +60.17 +57.37 +57.37 +57.37 +57.37 +60.17 +60.17 +73.61 +124.41 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +86.31 +86.3 +68.57 +45.19 +45.19 +60.17 +60.17 +45.18 +45.18 +26.01 +45.18 +26.01 +26.01 +14.55 +26.03 +26.03 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +14.46 +45.18 +45.18 +45.18 +45.18 +43.01 +43.01 +14.56 +43.02 +43.01 +43.01 +43.01 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.21 +45.2 +45.19 +45.19 +45.18 +45.18 +45.18 +45.19 +45.19 +60.17 +60.17 +45.19 +45.19 +45.19 +45.19 +45.19 +45.19 +45.18 +57.37 +45.19 +45.19 +45.18 +45.18 +45.2 +45.18 +45.18 +45.19 +45.19 +45.19 +45.19 +45.18 +45.18 +45.18 +45.18 +45.19 +60.17 +68.57 +68.57 +68.57 +68.57 +83.48 +103.95 +124.41 +124.41 +124.41 +124.41 +124.41 +118.57 +118.57 +86.3 +60.17 +45.21 +45.19 +45.19 +45.19 +45.18 +45.18 +45.19 +45.19 +45.2 +45.19 +45.19 +45.19 +45.19 +45.18 +45.19 +45.19 +45.19 +57.37 +45.19 +45.2 +45.2 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +26.01 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +45.19 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +45.19 +45.19 +45.18 +57.37 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +45.19 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +45.19 +45.19 +45.19 +45.19 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +26.04 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +26.01 +26.01 +26.01 +14.48 +14.46 +14.45 +0.01 +0.01 +0.02 +0.03 +14.45 +14.45 +0.02 +14.45 +14.47 +14.45 +14.45 +26.01 +26.02 +26.01 +26.02 +26.02 +14.5 +26.01 +45.18 +45.18 +14.49 +45.18 +26.02 +26.02 +14.49 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +26.01 +45.18 +45.18 +45.18 +26.07 +26.06 +26.02 +26.01 +26.02 +26.02 +14.45 +14.45 +0.0 +14.45 +14.45 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.01 +0.01 +14.45 +26.01 +26.01 +26.01 +26.01 +26.01 +26.01 +26.01 +26.04 +14.46 +14.46 +14.46 +14.46 +14.47 +14.45 +14.45 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.2 +83.48 +150.0 +137.56 +141.97 +137.56 +150.0 +150.0 +141.96 +118.58 +105.28 +89.34 +86.3 +68.57 +105.28 +105.28 +83.48 +60.17 +60.17 +60.17 +60.17 +68.57 +86.3 +103.95 +105.28 +118.57 +137.56 +137.56 +137.56 +124.41 +124.41 +124.41 +124.41 +103.94 +68.57 +73.61 +72.01 +86.3 +103.94 +103.95 +57.37 +45.18 +45.18 +45.18 +57.37 +45.19 +45.19 +45.18 +60.17 +73.61 +73.61 +73.61 +73.61 +73.61 +60.17 +45.19 +45.19 +45.18 +45.18 +45.18 +45.18 +43.05 +45.18 +43.03 +14.45 +0.01 +0.01 +0.0 +0.0 +0.0 +0.0 +0.0 +0.01 +14.46 +43.01 +43.01 +43.01 +14.45 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.04 +26.01 +45.18 +45.18 +45.19 +45.19 +57.37 +45.2 +45.19 +45.19 +45.19 +45.19 +45.2 +57.37 +57.37 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +103.95 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +141.96 +124.41 +150.0 +150.0 +68.57 +68.57 +60.17 +60.17 +60.17 +60.17 +60.17 +60.17 +60.17 +60.17 +83.48 +60.17 +45.25 +45.22 +45.21 +60.17 +57.37 +57.37 +45.22 +45.19 +45.19 +45.19 +57.37 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +45.19 +105.28 +105.28 +105.28 +105.28 +103.94 +103.94 +60.17 +45.19 +45.19 +57.37 +60.17 +57.37 +60.17 +45.2 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +45.18 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +60.17 +60.17 +60.17 +45.19 +45.18 +45.18 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +45.19 +57.37 +60.17 +45.19 +45.19 +105.28 +60.17 +105.28 +60.17 +45.19 +57.37 +57.37 +45.18 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +60.17 +60.17 +57.37 +57.37 +57.37 +45.19 +45.19 +45.2 +45.2 +45.19 +45.19 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +45.19 +45.19 +45.21 +45.23 +45.2 +60.17 +57.37 +45.19 +45.19 +45.19 +57.37 +60.17 +45.19 +57.37 +45.18 +45.19 +45.19 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +14.45 +14.45 +14.45 +14.46 +0.01 +0.01 +0.0 +0.0 +0.0 +0.0 +0.01 +0.01 +0.01 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +26.01 +26.01 +26.01 +43.01 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +43.01 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +14.56 +26.04 +26.04 +26.04 +43.01 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +26.02 +26.02 +43.01 +43.04 +45.18 +45.18 +83.48 +118.57 +124.41 +124.41 +137.56 +124.41 +119.92 +150.0 +124.41 +118.57 +104.47 +104.47 +105.28 +103.96 +105.28 +141.96 +141.96 +124.41 +103.94 +86.32 +104.47 +104.47 +83.48 +104.0 +141.96 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +124.41 +103.96 +89.33 +60.17 +60.17 +60.17 +60.17 +60.17 +60.17 +45.19 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +60.17 +60.17 +60.17 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +103.95 +137.56 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +137.56 +141.96 +124.42 +118.58 +137.56 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +137.56 +118.57 +83.48 +86.3 +86.3 +86.3 +86.3 +103.96 +137.56 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +104.47 +104.47 +104.47 +86.32 +118.57 +124.42 +105.28 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +57.37 +45.19 +60.17 +60.17 +45.19 +45.19 +57.37 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +57.37 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +26.02 +26.01 +26.01 +26.01 +14.45 +14.52 +26.01 +14.47 +26.01 +43.02 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +43.01 +43.02 +43.02 +43.01 +43.02 +43.01 +26.02 +14.5 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +45.19 +45.19 +45.19 +45.19 +45.19 +45.19 +45.19 +45.19 +57.37 +57.37 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +45.19 +45.19 +45.2 +57.37 +45.19 +45.19 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +14.45 +0.01 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +14.45 +14.45 +14.45 +14.45 +14.46 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.01 +0.01 +0.01 +0.01 +0.01 +0.01 +14.45 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +14.46 +14.45 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +45.18 +45.18 +45.18 +45.18 +45.18 +43.02 +43.04 +14.46 +14.46 +14.46 +14.45 +14.46 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +14.45 +45.18 +45.18 +45.18 +45.18 +45.18 +73.61 +103.95 +105.28 +105.28 +105.28 +103.95 +103.95 +105.28 +86.31 +86.3 +73.61 +73.61 +60.17 +72.02 +60.17 +60.17 +60.17 +57.37 +60.17 +60.17 +60.17 +83.48 +83.48 +105.28 +105.28 +105.28 +105.28 +105.28 +105.28 +103.95 +105.28 +60.17 +45.2 +45.2 +45.19 +45.19 +45.19 +45.19 +60.17 +60.17 +60.17 +60.17 +60.17 +60.17 +45.2 +45.19 +45.19 +57.37 +83.48 +104.47 +124.41 +124.41 +124.41 +119.92 +124.41 +118.57 +103.95 +103.94 +103.94 +86.3 +103.94 +86.3 +68.57 +45.23 +45.19 +45.19 +45.19 +45.19 +45.19 +45.18 +45.18 +60.17 +45.18 +57.37 +60.17 +45.19 +45.19 +45.18 +45.18 +45.18 +45.18 +43.02 +45.18 +45.18 +45.18 +43.01 +26.01 +0.03 +0.05 +0.04 +0.04 +0.02 +0.02 +0.03 +0.02 +45.18 +34.32 +45.18 +45.18 +45.19 +45.19 +45.18 +45.18 +45.18 +45.18 +45.19 +45.18 +45.19 +57.37 +45.21 +60.17 +60.17 +60.17 +45.18 +45.18 +45.18 +60.17 +83.48 +118.57 +137.56 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +105.28 +103.95 +103.94 +83.48 +60.17 +83.48 +83.48 +60.17 +60.17 +45.2 +57.37 +57.37 +60.17 +60.17 +60.17 +105.28 +83.48 +105.28 +105.28 +105.28 +103.95 +86.3 +83.48 +86.3 +83.48 +103.94 +57.37 +57.37 +45.18 +57.37 +45.19 +45.19 +45.18 +45.18 +45.18 +26.01 +26.01 +26.01 +26.01 +26.01 +43.01 +43.02 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +26.04 +45.18 +26.01 +0.04 +14.45 +26.01 +26.01 +26.01 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +45.19 +57.37 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +26.01 +43.01 +14.45 +14.45 +0.01 +0.01 +0.01 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +14.49 +14.49 +14.49 +45.18 +14.46 +14.46 +14.46 +14.46 +14.45 +14.46 +14.46 +14.46 +26.02 +45.18 +14.46 +14.46 +0.01 +0.02 +0.03 +14.45 +0.04 +26.02 +14.49 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +14.46 +14.45 +14.5 +14.49 +26.01 +14.49 +14.51 +26.04 +14.45 +14.45 +45.18 +43.04 +43.02 +45.18 +43.01 +14.46 +14.46 +14.46 +14.46 +14.46 +14.46 +14.46 +14.46 +14.46 +14.46 +43.02 +14.51 +26.01 +26.01 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +43.01 +43.01 +43.01 +45.18 +45.18 +45.18 +14.49 +26.01 +26.02 +26.01 +26.02 +14.5 +14.51 +26.01 +45.18 +45.18 +45.2 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +57.37 +45.18 +45.18 +45.18 +26.01 +14.45 +14.45 +14.45 +14.46 +14.46 +45.18 +43.04 +14.45 +14.47 +14.45 +0.0 +0.0 +0.0 +14.45 +45.18 +43.01 +43.02 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +105.28 +105.28 +103.95 +103.95 +103.99 +103.95 +103.99 +103.97 +86.3 +89.35 +105.28 +86.3 +83.48 +83.48 +86.3 +83.48 +83.48 +73.61 +60.17 +45.22 +45.2 +45.19 +45.19 +45.19 +45.19 +45.19 +68.57 +60.17 +60.17 +45.19 +45.19 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +45.2 +45.2 +57.37 +57.37 +45.23 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +83.48 +83.48 +83.48 +83.48 +86.3 +86.3 +83.48 +83.48 +60.17 +60.17 +60.17 +57.37 +60.17 +45.18 +45.18 +43.01 +45.18 +14.47 +14.45 +0.01 +14.45 +14.46 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +43.02 +45.18 +45.18 +45.18 +45.18 +45.19 +45.18 +45.18 +45.18 +45.18 +26.01 +26.01 +26.01 +45.18 +45.18 +45.18 +73.61 +83.48 +68.57 +73.61 +68.57 +73.61 +73.61 +60.17 +57.37 +57.37 +45.18 +45.19 +72.01 +83.48 +83.48 +73.61 +60.17 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +57.37 +105.28 +105.28 +105.28 +103.98 +89.38 +60.17 +60.17 +45.19 +45.19 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +26.01 +14.45 +0.02 +0.0 +0.0 +0.0 +0.01 +0.01 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +14.45 +0.0 +14.45 +0.0 +0.01 +0.01 +0.01 +0.0 +0.0 +0.0 +0.0 +14.45 +14.45 +14.45 +14.45 +26.02 +26.01 +26.01 +26.01 +14.45 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +14.45 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +43.01 +43.01 +43.01 +43.01 +43.01 +43.01 +43.04 +45.18 +43.03 +26.01 +26.01 +26.01 +26.02 +26.01 +26.02 +26.02 +43.02 +45.18 +45.18 +45.18 +43.01 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +43.01 +34.32 +26.02 +14.45 +14.45 +14.45 +14.46 +14.46 +45.18 +45.18 +0.01 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +26.01 +45.18 +43.01 +45.18 +45.18 +45.18 +45.18 +26.01 +26.01 +14.45 +14.45 +14.45 +14.45 +26.01 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +43.02 +43.01 +43.01 +43.01 +14.45 +14.45 +14.45 +14.47 +14.46 +0.01 +0.01 +0.01 +0.01 +0.02 +0.01 +14.45 +43.03 +43.01 +43.01 +43.01 +45.18 +45.18 +45.18 +45.18 +45.18 +26.01 +26.01 +26.02 +43.01 +26.01 +26.01 +45.18 +26.02 +14.46 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +45.18 +45.18 +43.01 +45.18 +43.02 +43.01 +43.01 +43.01 +14.45 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.05 +0.04 +0.02 +0.0 +0.01 +0.04 +0.02 +14.45 +14.45 +26.02 +45.18 +45.18 +26.02 +26.02 +26.03 +26.03 +26.01 +26.01 +26.01 +43.01 +43.01 +45.18 +45.18 +26.02 +26.01 +26.01 +14.45 +14.45 +14.45 +45.18 +45.18 +45.18 +45.18 +57.37 +57.37 +57.37 +57.37 +57.37 +57.37 +45.19 +45.19 +45.19 +45.19 +45.19 +45.19 +45.19 +45.19 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +57.37 +45.19 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +45.19 +45.19 +57.37 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +60.17 +60.17 +72.01 +60.17 +60.17 +57.37 +45.19 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +43.01 +43.01 +14.45 +14.45 +14.45 +14.46 +14.46 +43.02 +43.01 +14.46 +14.46 +14.46 +14.46 +14.45 +0.01 +0.01 +0.01 +0.01 +0.01 +0.01 +0.01 +0.01 +0.05 +0.02 +0.01 +0.01 +0.05 +0.01 +0.01 +0.01 +0.02 +14.45 +14.45 +0.04 +0.02 +0.01 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.01 +0.01 +14.45 +14.45 +14.46 +14.46 +14.46 +14.45 +14.45 +14.45 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +14.45 +14.46 +14.46 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +26.01 +26.01 +43.01 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +45.19 +45.19 +45.19 +45.18 +45.18 +26.01 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +26.03 +14.45 +0.02 +0.0 +0.01 +0.0 +0.0 +0.0 +0.0 +0.0 +26.02 +26.01 +26.02 +26.02 +26.02 +14.45 +14.45 +14.45 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +14.45 +14.45 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +14.45 +14.45 +14.45 +26.02 +45.18 +43.01 +43.01 +26.01 +14.45 +14.45 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +14.45 +14.45 +14.45 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +14.45 +14.45 +14.45 +14.45 +14.45 +0.02 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +14.45 +14.45 +14.45 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.01 +0.01 +0.01 +0.0 +0.0 +0.0 +0.01 +0.01 +14.45 +14.45 +14.45 +14.45 +14.46 +14.46 +14.46 +14.45 +0.01 +0.01 +0.0 +0.01 +0.0 +0.0 +0.0 +0.02 +0.01 +0.01 +0.0 +0.0 +0.0 +0.01 +0.01 +0.01 +14.45 +26.01 +26.04 +45.18 +45.18 +45.18 +26.02 +26.01 +26.02 +43.01 +43.01 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +26.03 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +26.02 +26.01 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +14.45 +26.01 +26.01 +26.01 +26.01 +26.01 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +14.45 +14.45 +43.01 +45.18 +45.18 +45.18 +83.49 +103.95 +103.96 +103.94 +86.3 +103.95 +86.3 +83.48 +73.61 +73.62 +73.61 +72.01 +72.01 +60.17 +68.57 +73.62 +68.57 +60.17 +45.18 +45.18 +45.18 +45.18 +57.37 +45.19 +72.01 +83.48 +103.94 +86.3 +86.3 +86.3 +83.49 +72.01 +72.01 +68.57 +72.01 +72.01 +68.57 +72.01 +72.01 +86.3 +103.95 +103.95 +68.57 +73.61 +83.48 +73.61 +73.61 +86.3 +137.56 +137.56 +141.96 +150.0 +150.0 +141.96 +150.0 +124.41 +86.3 +86.3 +103.94 +83.49 +83.49 +83.49 +83.48 +86.3 +89.33 +103.95 +86.3 +83.48 +73.61 +73.61 +105.28 +124.41 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +141.96 +124.41 +104.47 +104.47 +137.56 +141.96 +150.0 +150.0 +119.92 +86.3 +83.48 +83.48 +86.3 +86.3 +105.28 +137.56 +141.96 +141.96 +104.47 +105.28 +45.18 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +14.46 +14.46 +14.45 +14.45 +14.46 +14.45 +14.45 +14.46 +14.46 +26.02 +14.45 +0.01 +0.01 +0.0 +0.0 +0.0 +0.0 +0.01 +14.45 +14.46 +26.02 +26.02 +26.01 +26.02 +26.02 +26.05 +45.18 +26.01 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.2 +60.17 +103.95 +103.96 +104.47 +103.95 +103.96 +103.94 +103.95 +60.17 +60.17 +45.19 +45.19 +45.19 +45.19 +45.19 +45.18 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +45.19 +57.37 +45.18 +45.18 +45.18 +45.18 +14.49 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +14.53 +26.02 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +14.46 +14.45 +0.04 +0.04 +0.04 +14.45 +14.45 +14.45 +45.18 +14.46 +26.01 +26.01 +26.01 +26.01 +45.18 +45.18 +26.01 +26.01 +26.01 +14.45 +14.45 +14.45 +0.01 +0.01 +0.01 +0.01 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.01 +14.45 +14.45 +14.45 +14.45 +14.45 +14.47 +14.47 +14.47 +14.45 +14.45 +0.01 +0.01 +0.01 +0.0 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +14.47 +43.01 +45.18 +45.18 +45.19 +45.19 +60.17 +60.17 +60.17 +73.61 +73.61 +45.19 +45.19 +45.19 +60.17 +60.17 +119.92 +150.0 +150.0 +150.0 +103.96 +118.57 +118.57 +118.57 +118.57 +118.57 +150.0 +150.0 +150.0 +103.95 +83.48 +83.48 +60.17 +86.3 +68.57 +57.37 +57.37 +45.21 +45.21 +45.22 +103.95 +137.56 +137.56 +105.28 +68.57 +73.61 +83.48 +68.57 +83.48 +83.49 +118.57 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +124.41 +118.57 +103.97 +103.98 +86.3 +72.01 +60.17 +60.17 +60.17 +86.3 +68.57 +105.28 +105.28 +68.57 +68.57 +86.3 +86.3 +60.17 +60.17 +60.17 +86.3 +86.3 +86.3 +86.3 +103.94 +60.17 +60.17 +60.17 +60.17 +72.01 +60.17 +72.01 +103.95 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +124.41 +103.98 +105.28 +103.97 +105.28 +105.28 +124.41 +124.41 +137.56 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +141.96 +118.57 +103.96 +118.57 +118.58 +105.28 +60.17 +60.17 +60.17 +103.94 +105.28 +105.28 +105.28 +105.28 +119.92 +118.57 +103.94 +103.94 +86.3 +60.17 +83.48 +60.17 +60.17 +45.19 +45.19 +45.18 +45.19 +45.19 +45.19 +45.19 +57.37 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +43.03 +43.02 +36.54 +14.46 +14.45 +14.46 +14.45 +14.46 +14.46 +45.18 +45.18 +43.01 +14.46 +14.46 +45.18 +14.45 +14.45 +14.46 +14.45 +14.45 +14.45 +14.46 +14.45 +14.45 +14.45 +14.45 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +14.45 +0.0 +0.0 +0.0 +0.0 +0.0 +0.01 +14.45 +14.45 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +43.04 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +43.01 +43.01 +43.01 +45.18 +45.18 +45.18 +43.01 +43.04 +45.18 +45.18 +45.18 +45.19 +45.18 +45.19 +45.19 +57.37 +60.17 +73.61 +73.61 +103.94 +103.94 +105.28 +103.94 +105.28 +105.28 +103.94 +73.61 +68.57 +73.61 +68.57 +68.57 +60.17 +73.61 +68.57 +60.17 +57.37 +45.19 +45.19 +45.19 +45.21 +45.2 +45.2 +60.17 +57.37 +45.19 +57.37 +45.18 +45.18 +45.18 +14.45 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.03 +14.45 +14.45 +14.45 +14.45 +45.18 +26.02 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +26.01 +26.01 +26.01 +26.01 +45.18 +45.18 +45.18 +45.18 +45.18 +26.01 +26.01 +26.01 +43.01 +45.18 +45.18 +26.02 +26.01 +26.01 +14.45 +14.45 +0.01 +14.45 +0.01 +0.01 +0.01 +0.01 +0.0 +0.01 +0.01 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +14.45 +26.01 +26.01 +26.02 +43.01 +45.18 +45.18 +26.04 +26.04 +26.01 +26.02 +45.18 +45.18 +26.04 +26.04 +43.01 +45.18 +45.18 +14.51 +43.01 +14.53 +14.52 +14.45 +14.45 +14.46 +43.02 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +45.18 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +57.37 +45.19 +45.19 +45.18 +45.18 +45.18 +45.18 +45.19 +45.19 +57.37 +45.19 +45.19 +45.19 +45.19 +45.19 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +45.19 +57.37 +57.37 +45.19 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +26.01 +14.46 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +26.01 +26.01 +26.01 +26.02 +26.01 +14.46 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +0.05 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +0.06 +45.18 +26.03 +26.01 +26.01 +26.01 +45.18 +43.02 +34.32 +26.01 +14.45 +14.45 +0.02 +0.01 +0.01 +0.02 +0.02 +0.02 +14.45 +14.45 +14.47 +45.18 +14.47 +26.01 +26.02 +45.18 +45.18 +45.18 +45.19 +45.19 +45.19 +45.19 +45.18 +45.18 +45.18 +45.18 +43.04 +43.01 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +14.45 +14.45 +45.18 +45.18 +45.18 +43.02 +43.02 +45.18 +26.02 +26.02 +26.02 +26.01 +45.18 +26.01 +26.01 +26.01 +45.18 +45.18 +45.18 +45.18 +26.01 +43.01 +45.18 +45.18 +45.19 +73.61 +68.57 +60.17 +60.17 +60.17 +60.17 +68.57 +45.21 +45.21 +45.19 +45.19 +45.19 +45.18 +45.18 +45.18 +45.18 +45.2 +45.19 +45.19 +45.19 +45.19 +60.17 +83.48 +137.56 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +68.57 +60.17 +45.19 +45.18 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +14.45 +14.45 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +14.45 +14.45 +14.45 +0.0 +14.45 +14.45 +0.0 +0.0 +0.01 +14.45 +0.02 +0.02 +14.45 +14.45 +14.45 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +60.17 +86.3 +83.48 +73.61 +68.57 +73.61 +86.3 +118.57 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +124.41 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +137.6 +119.92 +119.92 +118.58 +120.93 +150.0 +105.28 +118.57 +141.96 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +118.58 +118.59 +103.94 +73.61 +60.17 +60.17 +60.17 +45.19 +45.19 +45.19 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +45.19 +60.17 +60.17 +83.48 +83.48 +105.28 +105.28 +68.57 +60.17 +68.57 +57.37 +57.37 +45.19 +45.19 +45.19 +45.18 +45.19 +86.3 +86.3 +60.17 +45.19 +45.19 +45.19 +45.19 +45.19 +83.5 +83.53 +83.48 +86.3 +86.3 +68.57 +57.37 +45.18 +45.18 +14.45 +14.45 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.05 +0.0 +0.0 +0.0 +0.0 +0.02 +0.02 +0.02 +14.45 +14.45 +0.05 +0.02 +14.45 +0.01 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.01 +14.45 +14.45 +0.0 +0.0 +0.02 +14.45 +0.0 +14.45 +14.45 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +43.01 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +43.02 +43.02 +26.03 +26.03 +26.01 +43.02 +43.01 +26.01 +26.01 +14.46 +14.46 +14.46 +26.02 +14.45 +14.49 +14.45 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.01 +0.01 +0.0 +0.0 +0.0 +14.45 +14.45 +14.45 +14.46 +14.46 +14.46 +14.46 +14.45 +14.45 +0.01 +0.01 +0.01 +0.02 +0.0 +0.0 +14.45 +26.02 +26.01 +14.45 +14.46 +14.46 +14.46 +45.18 +45.18 +45.19 +83.48 +86.3 +83.48 +83.48 +86.3 +83.48 +86.3 +105.28 +86.3 +86.3 +86.3 +86.3 +60.17 +45.19 +60.17 +105.28 +60.17 +57.37 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +45.19 +45.19 +45.18 +45.18 +45.18 +45.18 +43.02 +14.46 +26.02 +26.04 +26.03 +26.02 +14.46 +14.46 +14.46 +14.46 +14.46 +14.47 +14.47 +26.01 +26.01 +45.18 +14.48 +26.01 +26.04 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +26.01 +26.01 +26.01 +14.46 +14.46 +14.46 +14.46 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +72.01 +105.28 +105.28 +57.37 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +57.37 +60.17 +60.17 +83.48 +124.41 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +124.41 +105.28 +105.28 +118.57 +141.96 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +118.57 +103.97 +104.5 +103.94 +60.17 +45.19 +57.37 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +45.2 +45.19 +45.18 +45.19 +105.28 +103.95 +105.28 +118.57 +118.57 +103.96 +137.56 +118.57 +104.47 +104.5 +103.94 +60.17 +45.18 +45.18 +45.18 +14.46 +14.46 +14.46 +14.46 +14.46 +45.18 +45.18 +43.01 +43.02 +14.48 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +43.01 +43.01 +43.01 +43.01 +43.02 +43.02 +14.46 +14.46 +14.46 +45.18 +14.46 +14.46 +43.01 +43.02 +43.01 +43.04 +43.01 +43.04 +45.18 +45.18 +45.2 +57.37 +45.19 +57.37 +57.37 +57.37 +45.19 +45.19 +45.19 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +45.19 +45.2 +45.21 +45.19 +45.19 +45.19 +45.19 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +43.01 +43.01 +14.45 +14.45 +14.45 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +14.45 +14.46 +14.46 +14.45 +14.45 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +60.17 +60.17 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +0.0 +0.0 +0.0 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +14.46 +26.01 +43.02 +43.01 +43.01 +45.18 +45.18 +45.18 +26.04 +45.18 +26.02 +26.02 +26.01 +26.01 +26.02 +26.02 +26.04 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +57.37 +83.48 +60.17 +60.17 +83.48 +83.48 +60.17 +60.17 +60.17 +60.17 +60.17 +60.17 +60.17 +60.17 +45.19 +45.19 +45.19 +103.95 +150.0 +141.96 +137.56 +137.56 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +141.96 +105.28 +103.94 +83.48 +83.48 +83.48 +83.48 +86.3 +89.34 +105.28 +141.96 +141.96 +105.28 +104.0 +104.0 +105.28 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +103.96 +105.28 +103.96 +105.28 +104.47 +118.57 +150.0 +150.0 +150.0 +137.56 +86.3 +86.3 +86.3 +141.96 +150.0 +150.0 +150.0 +150.0 +150.0 +141.96 +104.47 +86.31 +68.57 +45.18 +45.18 +43.02 +26.01 +14.45 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.01 +26.01 +14.45 +0.01 +14.45 +14.45 +0.01 +0.01 +0.02 +0.01 +0.0 +0.0 +0.0 +0.0 +0.0 +0.01 +0.01 +0.01 +0.01 +0.0 +0.0 +0.01 +0.02 +0.01 +0.01 +43.02 +14.46 +14.45 +26.02 +26.03 +26.03 +26.02 +26.01 +26.01 +26.02 +26.02 +26.01 +43.01 +14.46 +14.46 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +60.17 +57.37 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.19 +86.3 +103.95 +103.96 +119.92 +105.28 +103.94 +103.96 +105.28 +105.28 +86.3 +83.49 +86.31 +86.31 +103.94 +103.96 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +150.0 +141.96 +103.96 +83.48 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +43.01 +43.02 +14.46 +14.46 +14.46 +43.01 +43.01 +43.01 +43.01 +45.18 +26.03 +34.32 +43.02 +43.01 +43.04 +45.18 +14.46 +45.18 +45.18 +45.18 +26.02 +26.01 +26.01 +26.02 +45.18 +26.01 +26.01 +26.02 +45.18 +45.18 +45.19 +45.19 +45.19 +45.18 +45.18 +45.18 +45.18 +45.19 +45.18 +45.2 +45.19 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +45.18 +14.45 +14.45 +14.45 +14.45 +14.45 +0.01 +0.01 +0.01 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.01 +14.45 +14.46 +14.46 +14.46 +14.45 +14.45 +14.47 +14.46 +14.45 +14.46 +14.46 +26.01 +26.01 +26.01 +26.01 +26.02 +26.02 +26.02 +26.02 +26.01 +26.02 +26.04 +26.04 +26.04 +26.02 +26.02 +26.02 +26.01 +14.49 +14.48 +14.45 +14.45 +0.02 +0.02 +0.01 +0.01 +14.45 +26.02 +14.45 +14.45 +0.01 +14.45 +0.01 +0.01 +0.01 +14.45 +0.01 +0.01 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +0.01 +0.01 +0.01 +0.01 +0.01 +0.01 +0.02 +0.02 +0.02 +0.01 +0.01 +0.01 +0.02 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +14.45 +0.02 +14.45 +14.45 +14.45 +0.01 +0.01 +0.01 +0.0 +0.0 +0.0 +0.01 +0.02 +14.45 +14.45 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +45.18 +60.17 +45.18 +45.18 +45.18 +45.18 +43.01 +14.46 +14.46 +14.45 +14.45 +14.45 +14.45 +14.45 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.01 +0.0 +14.45 +0.01 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.02 +0.01 +0.02 +0.01 +0.01 +0.01 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.0 +0.02 +0.01 +0.02 +0.01 +0.01 +0.01 +0.0 +0.0 \ No newline at end of file diff --git a/examples/excel_to_scenario.ipynb b/examples/excel_to_scenario.ipynb new file mode 100644 index 0000000..dcddc81 --- /dev/null +++ b/examples/excel_to_scenario.ipynb @@ -0,0 +1,196 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "42081dd2", + "metadata": {}, + "source": [ + "This is still a testing workbook to demonstrate progress on the excel to scenario flows." + ] + }, + { + "cell_type": "markdown", + "id": "386ce0b0", + "metadata": {}, + "source": [ + "# Curves" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "id": "c617dc0a", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Found 3 curve files\n", + "✓ Loaded curve 'interconnector_8_price': 8760 values\n", + "✓ Loaded curve 'electric_vehicle_profile_5': 8760 values\n", + "✓ Loaded curve 'agriculture_electricity': 8760 values\n", + "Created DataFrame with 3 curves and 8760 rows\n" + ] + } + ], + "source": [ + "# For now a custom csv to pd df function - this will be handled by the reverse packer in the end\n", + "\n", + "import pandas as pd\n", + "from pathlib import Path\n", + "from typing import Union\n", + "\n", + "def read_curves_to_dataframe(\n", + " curves_path: Union[str, Path],\n", + " pattern: str = \"*.csv\",\n", + " validate_length: bool = True\n", + ") -> pd.DataFrame:\n", + " \"\"\"\n", + " Read multiple curve CSV files into a single DataFrame.\n", + "\n", + " Args:\n", + " curves_path: Directory path containing the curve CSV files\n", + " pattern: File pattern to match (default: \"*.csv\")\n", + " validate_length: Whether to validate each curve has exactly 8760 values\n", + "\n", + " Returns:\n", + " DataFrame with curves as columns, where column names are the curve keys\n", + " (derived from filenames without extension)\n", + "\n", + " Raises:\n", + " ValueError: If validation fails or files have issues\n", + " FileNotFoundError: If no files found matching the pattern\n", + " \"\"\"\n", + " curves_path = Path(curves_path)\n", + "\n", + " if not curves_path.exists():\n", + " raise FileNotFoundError(f\"Directory not found: {curves_path}\")\n", + "\n", + " # Find all CSV files matching the pattern\n", + " csv_files = list(curves_path.glob(pattern))\n", + "\n", + " if not csv_files:\n", + " raise FileNotFoundError(f\"No files found matching pattern '{pattern}' in {curves_path}\")\n", + "\n", + " print(f\"Found {len(csv_files)} curve files\")\n", + "\n", + " curves_data = {}\n", + " errors = []\n", + "\n", + " for csv_file in csv_files:\n", + " # Use filename (without extension) as curve key, remove _curve suffix if present\n", + " curve_key = csv_file.stem\n", + " if curve_key.endswith('_curve'):\n", + " curve_key = curve_key[:-6] # Remove '_curve' suffix\n", + "\n", + " try:\n", + " # Read CSV file - assuming single column of values, no headers\n", + " curve_data = pd.read_csv(\n", + " csv_file,\n", + " header=None, # No header row\n", + " index_col=False, # No index column\n", + " dtype=float # All values should be numeric\n", + " )\n", + "\n", + " # Convert DataFrame to Series if single column\n", + " if isinstance(curve_data, pd.DataFrame):\n", + " if len(curve_data.columns) == 1:\n", + " curve_data = curve_data.iloc[:, 0]\n", + " else:\n", + " errors.append(f\"{curve_key}: Expected 1 column, found {len(curve_data.columns)}\")\n", + " continue\n", + "\n", + " # Drop any NaN values\n", + " curve_data = curve_data.dropna()\n", + "\n", + " # Validate length if requested\n", + " if validate_length and len(curve_data) != 8760:\n", + " errors.append(f\"{curve_key}: Expected 8760 values, found {len(curve_data)}\")\n", + " continue\n", + "\n", + " # Store with curve key as column name\n", + " curves_data[curve_key] = curve_data.values\n", + " print(f\"✓ Loaded curve '{curve_key}': {len(curve_data)} values\")\n", + "\n", + " except Exception as e:\n", + " errors.append(f\"{curve_key}: Error reading file - {str(e)}\")\n", + " continue\n", + "\n", + " if errors:\n", + " error_msg = \"Errors reading curve files:\\n\" + \"\\n\".join(f\" - {err}\" for err in errors)\n", + " if not curves_data: # No curves loaded successfully\n", + " raise ValueError(error_msg)\n", + " else:\n", + " print(f\"Warning: Some curves failed to load:\\n{error_msg}\")\n", + "\n", + " if not curves_data:\n", + " raise ValueError(\"No curves were successfully loaded\")\n", + "\n", + " # Create DataFrame from the curves\n", + " df = pd.DataFrame(curves_data)\n", + "\n", + " # Set index to represent hours (0-8759 for a full year)\n", + " df.index.name = \"hour\"\n", + "\n", + " print(f\"Created DataFrame with {len(df.columns)} curves and {len(df)} rows\")\n", + " return df\n", + "\n", + "# User uploads Excel/CSV → DataFrame → CustomCurves object\n", + "from pyetm.models.custom_curves import CustomCurves\n", + "\n", + "df = read_curves_to_dataframe(\"curve_examples/\")\n", + "custom_curves = CustomCurves._from_dataframe(df)" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "id": "e75a03b2", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Environment setup complete\n", + " Using ETM API at http://localhost:3000/api/v3\n", + " Token loaded? True\n", + "API connection ready\n" + ] + } + ], + "source": [ + "from example_helpers import setup_notebook\n", + "from pyetm.models import Scenario\n", + "\n", + "setup_notebook()\n", + "scenario = Scenario.load(2690288)\n", + "\n", + "# Update curves on scenario\n", + "scenario.update_custom_curves(custom_curves)" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "pyetm-qKH2ozgc", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/src/pyetm/models/base.py b/src/pyetm/models/base.py index fd7b593..c2162af 100644 --- a/src/pyetm/models/base.py +++ b/src/pyetm/models/base.py @@ -20,7 +20,6 @@ class Base(BaseModel): # Enable assignment validation model_config = ConfigDict(validate_assignment=True) - _warning_collector: WarningCollector = PrivateAttr(default_factory=WarningCollector) def __init__(self, **data: Any) -> None: @@ -52,9 +51,15 @@ def __setattr__(self, name: str, value: Any) -> None: Handle assignment with validation error capture. Simplified from the original complex implementation. """ - # Skip validation for private attributes - if name.startswith("_") or name not in self.__class__.model_fields: - super().__setattr__(name, value) + # Skip validation for private attributes, methods/functions, or existing methods + if ( + name.startswith("_") + or name not in self.__class__.model_fields + or callable(value) + or hasattr(self.__class__, name) + ): + # Use object.__setattr__ to bypass Pydantic for these cases + object.__setattr__(self, name, value) return # Clear existing warnings for this field @@ -106,17 +111,32 @@ def _clear_warnings_for_attr(self, field: str) -> None: def _merge_submodel_warnings(self, *submodels: Base, key_attr: str = None) -> None: """ Merge warnings from nested Base models. - Maintains compatibility with existing code while using the new system. """ self._warning_collector.merge_submodel_warnings(*submodels, key_attr=key_attr) @classmethod - def load_safe(cls: Type[T], **data: Any) -> T: + def from_dataframe(cls: Type[T], df: pd.DataFrame, **kwargs) -> T: """ - Alternate constructor that always returns an instance, - converting all validation errors into warnings. + Create an instance from a pandas DataFrame. """ - return cls(**data) + try: + return cls._from_dataframe(df, **kwargs) + except Exception as e: + # Create a fallback instance with warnings + instance = cls.model_construct() + instance.add_warning( + "from_dataframe", f"Failed to create from DataFrame: {e}" + ) + return instance + + @classmethod + def _from_dataframe(cls, df: pd.DataFrame, **kwargs): + """ + Private method to be implemented by each subclass for specific deserialization logic. + """ + raise NotImplementedError( + f"{cls.__name__} must implement _from_dataframe() class method" + ) def _get_serializable_fields(self) -> List[str]: """ diff --git a/src/pyetm/models/custom_curves.py b/src/pyetm/models/custom_curves.py index b60ea51..2cf6cd3 100644 --- a/src/pyetm/models/custom_curves.py +++ b/src/pyetm/models/custom_curves.py @@ -2,9 +2,9 @@ import pandas as pd from pathlib import Path from typing import Optional +from pyetm.models.warnings import WarningCollector from pyetm.clients import BaseClient from pyetm.models.base import Base -from pyetm.models.warnings import WarningCollector from pyetm.services.scenario_runners.fetch_custom_curves import ( DownloadCustomCurveRunner, ) @@ -121,6 +121,69 @@ def from_json(cls, data: dict) -> CustomCurve: curve.add_warning("base", f"Failed to create curve from data: {e}") return curve + def _to_dataframe(self, **kwargs) -> pd.DataFrame: + """ + Serialize CustomCurve to DataFrame with time series data. + """ + curve_data = self.contents() + + if curve_data is None or curve_data.empty: + # Return empty DataFrame with proper structure + return pd.DataFrame({self.key: pd.Series(dtype=float)}) + + # Create DataFrame with curve key as column name + df = pd.DataFrame({self.key: curve_data.values}) + + # TODO: Do we want the hour index? + # Set index to represent hours (0-8759 for a full year) + df.index.name = "hour" + + return df + + @classmethod + def _from_dataframe(cls, df: pd.DataFrame, **kwargs) -> "CustomCurve": + """ + Create CustomCurve from DataFrame containing time series data. + """ + if len(df.columns) != 1: + raise ValueError( + f"DataFrame must contain exactly 1 column, got {len(df.columns)}" + ) + + # Get the curve key from column name + curve_key = df.columns[0] + + curve_data_dict = { + "key": curve_key, + "type": "custom", # Default type for curves created from DataFrame + } + + curve = cls.model_validate(curve_data_dict) + + # Only save data if DataFrame has actual data rows + if not df.empty: + curve_data = df.iloc[:, 0].dropna() + + if not curve_data.empty: + # Save the data to a temporary file and set file_path + file_path = ( + get_settings().path_to_tmp("dataframe_import") + / f"{curve_key.replace('/', '-')}.csv" + ) + + # Ensure directory exists + file_path.parent.mkdir(parents=True, exist_ok=True) + + try: + curve_data.to_csv(file_path, index=False, header=False) + curve.file_path = file_path + except Exception as e: + curve.add_warning( + curve_key, f"Failed to save curve data to file: {e}" + ) + + return curve + class CustomCurves(Base): curves: list[CustomCurve] @@ -186,4 +249,131 @@ def from_json(cls, data: list[dict]) -> CustomCurves: return collection - # TODO: _to_dataframe + def _to_dataframe(self, **kwargs) -> pd.DataFrame: + """ + Serialize CustomCurves collection to DataFrame with time series data. + """ + if not self.curves: + return pd.DataFrame(index=pd.Index([], name="hour")) + + curve_columns = {} + + for curve in self.curves: + try: + curve_df = curve._to_dataframe(**kwargs) + if not curve_df.empty: + # Get the curve data as a Series + curve_series = curve_df.iloc[:, 0] # First (and only) column + curve_columns[curve.key] = curve_series + else: + # TODO: Should we add empty series for curves with no data? currently yes + curve_columns[curve.key] = pd.Series(dtype=float, name=curve.key) + + except Exception as e: + curve_columns[curve.key] = pd.Series(dtype=float, name=curve.key) + self.add_warning( + "curves", f"Failed to serialize curve {curve.key}: {e}" + ) + + if curve_columns: + # Combine all curves into a single DataFrame + result_df = pd.DataFrame(curve_columns) + result_df.index.name = "hour" + return result_df + else: + return pd.DataFrame(index=pd.Index([], name="hour")) + + @classmethod + def _from_dataframe(cls, df: pd.DataFrame, **kwargs) -> "CustomCurves": + """ + Create CustomCurves collection from DataFrame with time series data. + """ + curves = [] + + if len(df.columns) == 0: + return cls.model_validate({"curves": curves}) + + for column_name in df.columns: + try: + # Extract single column as DataFrame for individual curve + curve_df = df[[column_name]] + + curve = CustomCurve._from_dataframe(curve_df, **kwargs) + curves.append(curve) + + except Exception as e: + basic_curve = CustomCurve.model_construct( + key=column_name, type="custom" + ) + basic_curve.add_warning( + "base", f"Failed to create curve from column {column_name}: {e}" + ) + curves.append(basic_curve) + + collection = cls.model_validate({"curves": curves}) + + # Merge warnings from individual curves + collection._merge_submodel_warnings(*curves, key_attr="key") + + return collection + + def validate_for_upload(self) -> dict[str, WarningCollector]: + """ + Validate all curves for upload + """ + validation_errors = {} + + for curve in self.curves: + curve_warnings = WarningCollector() + + if not curve.available(): + curve_warnings.add(curve.key, "Curve has no data available") + validation_errors[curve.key] = curve_warnings + continue + + # Get curve data and validate + try: + # First, try to read the file without forcing dtype to check for non-numeric values + try: + # Read without dtype conversion to preserve non-numeric values + raw_data = pd.read_csv(curve.file_path, header=None, index_col=False) + if raw_data.empty: + curve_warnings.add(curve.key, "Curve contains no data") + validation_errors[curve.key] = curve_warnings + continue + + # Check length first + if len(raw_data) != 8760: + curve_warnings.add( + curve.key, + f"Curve must contain exactly 8,760 values, found {len(raw_data)}", + ) + else: + # Now check if all values can be converted to float + try: + # Try to convert to numeric, this will raise if there are non-numeric values + pd.to_numeric(raw_data.iloc[:, 0], errors='raise') + except (ValueError, TypeError): + curve_warnings.add( + curve.key, "Curve contains non-numeric values" + ) + + except pd.errors.EmptyDataError: + curve_warnings.add(curve.key, "Curve contains no data") + except Exception as e: + # This catches file not found, permission errors, etc. + curve_warnings.add( + curve.key, f"Error reading curve data: {str(e)}" + ) + + except Exception as e: + # Catch any other unexpected errors + curve_warnings.add( + curve.key, f"Error reading curve data: {str(e)}" + ) + + # Only add to validation_errors if there are actual warnings + if len(curve_warnings) > 0: + validation_errors[curve.key] = curve_warnings + + return validation_errors diff --git a/src/pyetm/models/scenario.py b/src/pyetm/models/scenario.py index 4277906..0eb29c0 100644 --- a/src/pyetm/models/scenario.py +++ b/src/pyetm/models/scenario.py @@ -8,7 +8,7 @@ from pyetm.models.output_curves import OutputCurves from pyetm.clients import BaseClient from pyetm.models.base import Base -from pyetm.models.custom_curves import CustomCurves +from pyetm.models.custom_curves import CustomCurve, CustomCurves from pyetm.models.gqueries import Gqueries from pyetm.models.sortables import Sortables from pyetm.services.scenario_runners.fetch_inputs import FetchInputsRunner @@ -21,6 +21,9 @@ from pyetm.services.scenario_runners.update_sortables import UpdateSortablesRunner from pyetm.services.scenario_runners.create_scenario import CreateScenarioRunner from pyetm.services.scenario_runners.update_metadata import UpdateMetadataRunner +from pyetm.services.scenario_runners.update_custom_curves import ( + UpdateCustomCurvesRunner, +) class ScenarioError(Exception): @@ -336,6 +339,38 @@ def custom_curves_series(self): for key in self.custom_curves.attached_keys(): yield self.custom_curve_series(key) + def update_custom_curves(self, custom_curves) -> None: + """ + Upload/update custom curves for this scenario. + + Args: + custom_curves: CustomCurves object containing curves to upload + TODO: Update after the from_excel is implemented + """ + + # Validate curves before uploading + validity_errors = custom_curves.validate_for_upload() + # TODO: Extract all these validity_errors thingys to a single util or something, lots of repetition at the moment + if validity_errors: + error_summary = [] + for key, warning_collector in validity_errors.items(): + warnings_list = [w.message for w in warning_collector] + error_summary.append(f"{key}: {warnings_list}") + raise ScenarioError(f"Could not update custom curves: {error_summary}") + + # Upload curves + result = UpdateCustomCurvesRunner.run(BaseClient(), self, custom_curves) + if not result.success: + raise ScenarioError(f"Could not update custom curves: {result.errors}") + + # Update the scenario's custom curves object + for new_curve in custom_curves.curves: + existing_curve = self.custom_curves._find(new_curve.key) + if existing_curve: + existing_curve.file_path = new_curve.file_path + else: + self.custom_curves.curves.append(new_curve) + @property def output_curves(self) -> OutputCurves: if self._output_curves is not None: diff --git a/src/pyetm/models/warnings.py b/src/pyetm/models/warnings.py index 574c9b6..794c2f8 100644 --- a/src/pyetm/models/warnings.py +++ b/src/pyetm/models/warnings.py @@ -55,11 +55,6 @@ def add( ) -> None: """ Add warning(s) to the collection. - - Handles the complex legacy patterns from the original system: - - Single string messages - - Lists of messages - - Nested dictionaries of warnings """ if isinstance(message, str): self._warnings.append(ModelWarning(field, message, severity)) @@ -69,7 +64,6 @@ def add( if isinstance(msg, str): self._warnings.append(ModelWarning(field, msg, severity)) else: - # Handle nested structures self._warnings.append(ModelWarning(field, str(msg), severity)) elif isinstance(message, dict): @@ -111,22 +105,9 @@ def to_dict(self) -> Dict[str, List[Dict[str, Any]]]: result[warning.field].append(warning.to_dict()) return result - def to_legacy_dict(self) -> Dict[str, List[str]]: - """ - Convert to the old warning format for backward compatibility. - Groups warnings by field and returns just the messages. - """ - result = {} - for warning in self._warnings: - if warning.field not in result: - result[warning.field] = [] - result[warning.field].append(warning.message) - return result - def merge_from(self, other: "WarningCollector", prefix: str = "") -> None: """ Merge warnings from another collector, optionally with a field prefix. - This replaces the complex _merge_submodel_warnings logic. """ for warning in other._warnings: field = f"{prefix}.{warning.field}" if prefix else warning.field @@ -144,7 +125,6 @@ def merge_submodel_warnings( ) -> None: """ Merge warnings from Base model instances. - Maintains compatibility with the original _merge_submodel_warnings method. """ for submodel in submodels: if hasattr(submodel, "_warning_collector"): diff --git a/src/pyetm/services/scenario_runners/update_custom_curves.py b/src/pyetm/services/scenario_runners/update_custom_curves.py new file mode 100644 index 0000000..5e8a9a4 --- /dev/null +++ b/src/pyetm/services/scenario_runners/update_custom_curves.py @@ -0,0 +1,82 @@ +from typing import Any, Dict +from pyetm.services.scenario_runners.base_runner import BaseRunner +from ..service_result import ServiceResult +from pyetm.clients.base_client import BaseClient + + +class UpdateCustomCurvesRunner(BaseRunner[Dict[str, Any]]): + """ + Runner for uploading custom curves to a scenario. + """ + + @staticmethod + def run( + client: BaseClient, + scenario: Any, + custom_curves: Any, + **kwargs, + ) -> ServiceResult[Dict[str, Any]]: + """Upload all curves in the CustomCurves object.""" + + all_errors = [] + successful_uploads = [] + + for curve in custom_curves.curves: + try: + if curve.file_path and curve.file_path.exists(): + # Use file + with open(curve.file_path, "r") as f: + files = { + "file": (f"{curve.key}.csv", f, "application/octet-stream") + } + # Override Content-Type header so multipart/form-data is used + headers = {"Content-Type": None} + + result = UpdateCustomCurvesRunner._make_request( + client=client, + method="put", + path=f"/scenarios/{scenario.id}/custom_curves/{curve.key}", + files=files, + headers=headers, + ) + else: + # Create file content from curve data + curve_data = curve.contents() + file_content = "\n".join(str(value) for value in curve_data) + files = { + "file": ( + f"{curve.key}.csv", + file_content, + "application/octet-stream", + ) + } + # Override Content-Type header so multipart/form-data is used + headers = {"Content-Type": None} + + result = UpdateCustomCurvesRunner._make_request( + client=client, + method="put", + path=f"/scenarios/{scenario.id}/custom_curves/{curve.key}", + files=files, + headers=headers, + ) + + # Check if the request was successful + if result.success: + successful_uploads.append(curve.key) + else: + all_errors.extend(result.errors) + + except Exception as e: + all_errors.append(f"Error uploading {curve.key}: {str(e)}") + + # TODO: This provides some aggregated results, because we actually get multiple ServiceResults - one for each curve upload. Explore further. + return ServiceResult( + success=len(all_errors) == 0, + data={ + "uploaded_curves": successful_uploads, + "total_curves": len(custom_curves.curves), + "successful_uploads": len(successful_uploads), + }, + errors=all_errors, + ) diff --git a/tests/models/test_base.py b/tests/models/test_base.py index deebc14..2cb1cb6 100644 --- a/tests/models/test_base.py +++ b/tests/models/test_base.py @@ -1,4 +1,5 @@ from pyetm.models.base import Base +import pandas as pd def test_valid_initialization_has_no_warnings(dummy_base_model): @@ -8,8 +9,8 @@ def test_valid_initialization_has_no_warnings(dummy_base_model): assert d.a == 10 assert d.b == "string" assert d.c == 3.14 - assert len(d.warnings) == 0 # New: check length instead of empty dict - assert not d.warnings.has_warnings() # New: use has_warnings method + assert len(d.warnings) == 0 + assert not d.warnings.has_warnings() def test_invalid_initialization_becomes_warning_not_exception(dummy_base_model): @@ -17,10 +18,9 @@ def test_invalid_initialization_becomes_warning_not_exception(dummy_base_model): d = dummy_base_model(a="not-an-int", b="hi") assert isinstance(d, dummy_base_model) - assert len(d.warnings) > 0 # New: check that warnings exist + assert len(d.warnings) > 0 - # Check warning content using new API - all_warnings = list(d.warnings) # Get all ModelWarning objects + all_warnings = list(d.warnings) warning_messages = [w.message.lower() for w in all_warnings] assert any("valid integer" in msg for msg in warning_messages) @@ -41,7 +41,7 @@ def test_missing_required_field_becomes_warning(dummy_base_model): def test_assignment_validation_generates_warning_and_skips_assignment(dummy_base_model): """Test that invalid assignments generate warnings and don't change the value.""" d = dummy_base_model(a=1, b="foo") - d.warnings.clear() # Clear any initialization warnings + d.warnings.clear() # Good assignment should work d.a = 42 @@ -50,9 +50,9 @@ def test_assignment_validation_generates_warning_and_skips_assignment(dummy_base # Bad assignment should generate warning and not change value original_b = d.b - d.b = 123 # Invalid: should be string + d.b = 123 - assert d.b == original_b # Value should not change + assert d.b == original_b assert len(d.warnings) == 1 # Check warning content @@ -68,11 +68,10 @@ class Child(Base): x: int def _to_dataframe(self, **kwargs): - import pandas as pd return pd.DataFrame({"x": [self.x]}) - child = Child(x="warning") # Invalid value will create warnings + child = Child(x="warning") assert len(child.warnings) > 0, "child should have at least one warning" parent = dummy_base_model(a=0, b="string") @@ -91,10 +90,9 @@ def _to_dataframe(self, **kwargs): def test_show_warnings_no_warnings_prints_no_warnings(capsys, dummy_base_model): """Test show_warnings output when no warnings exist.""" d = dummy_base_model(a=3, b="string") - d.warnings.clear() # Ensure no warnings + d.warnings.clear() d.show_warnings() - captured = capsys.readouterr() assert "No warnings." in captured.out.strip() @@ -119,7 +117,6 @@ class Child(Base): x: int def _to_dataframe(self, **kwargs): - import pandas as pd return pd.DataFrame({"x": [self.x]}) @@ -144,26 +141,6 @@ def _to_dataframe(self, **kwargs): assert len(parent.warnings) >= 2 -def test_load_safe_always_constructs_and_warns(dummy_base_model): - """Test that load_safe never raises exceptions and creates warnings.""" - # load_safe should never raise, even if data is invalid - data = {"a": "not-int", "b": 123} - d = dummy_base_model.load_safe(**data) - - assert isinstance(d, dummy_base_model) - assert len(d.warnings) > 0 - - # Check that warnings contain expected validation messages - all_warnings = list(d.warnings) - warning_messages = [w.message.lower() for w in all_warnings] - - assert any("valid integer" in msg for msg in warning_messages) - # Should have warning about b being invalid (number instead of string) or missing - assert any( - "valid string" in msg or "field required" in msg for msg in warning_messages - ) - - def test_add_warning_manually(dummy_base_model): """Test manually adding warnings to a model.""" d = dummy_base_model(a=1, b="string") @@ -194,7 +171,7 @@ def test_add_warning_with_severity(dummy_base_model): def test_clear_warnings_for_specific_field(dummy_base_model): """Test clearing warnings for a specific field.""" - d = dummy_base_model(a="invalid", b=123) # Both invalid + d = dummy_base_model(a="invalid", b=123) # Should have warnings for both fields assert d.warnings.has_warnings("a") @@ -221,7 +198,7 @@ def test_assignment_clears_previous_warnings(dummy_base_model): d = dummy_base_model(a=1, b="string") # Make invalid assignment to create warning - d.a = "invalid" # Should create warning + d.a = "invalid" assert d.warnings.has_warnings("a") # Make valid assignment - should clear warnings @@ -242,40 +219,14 @@ def test_get_serializable_fields(dummy_base_model): assert all(not field.startswith("_") for field in fields) -def test_warning_collector_legacy_compatibility(dummy_base_model): - """Test that we can still get legacy dict format if needed.""" - d = dummy_base_model(a="invalid", b="string") - - # New API - assert len(d.warnings) > 0 - assert d.warnings.has_warnings("a") - - # Legacy format available through to_legacy_dict() - legacy_dict = d.warnings.to_legacy_dict() - assert isinstance(legacy_dict, dict) - assert "a" in legacy_dict - assert isinstance(legacy_dict["a"], list) - - -def test_model_construction_with_partial_data(dummy_base_model): - """Test model construction with missing optional fields.""" - # Assuming 'c' is optional in dummy_base_model - d = dummy_base_model(a=1, b="string") - - assert d.a == 1 - assert d.b == "string" - # Optional field 'c' should have default or None - - def test_multiple_validation_errors_all_become_warnings(dummy_base_model): """Test that multiple validation errors all become warnings.""" # Create model with multiple invalid fields - d = dummy_base_model(a="not-int", b=123) # Both invalid + d = dummy_base_model(a="not-int", b=123) assert isinstance(d, dummy_base_model) - assert len(d.warnings) >= 2 # Should have at least 2 warnings + assert len(d.warnings) >= 2 - # Should have warnings for both fields assert d.warnings.has_warnings("a") assert d.warnings.has_warnings("b") @@ -286,7 +237,6 @@ def test_nested_warning_merging_preserves_structure(dummy_base_model): d = dummy_base_model(a=1, b="string") d.warnings.clear() - # Add complex nested warning structure (simulating legacy behavior) complex_warnings = {"sub1": ["Warning 1", "Warning 2"], "sub2": ["Warning 3"]} d.add_warning("parent", complex_warnings) @@ -323,3 +273,65 @@ def test_show_warnings_different_severities(capsys, dummy_base_model): assert "Information message" in captured.out assert "Warning message" in captured.out assert "Error message" in captured.out + + +def test_from_dataframe_not_implemented_creates_fallback(dummy_base_model): + """Test that calling from_dataframe on base class creates fallback with warning.""" + + df = pd.DataFrame({"a": [1], "b": ["test"]}) + + # The base class should create a fallback instance with warnings since _from_dataframe is not implemented + instance = dummy_base_model.from_dataframe(df) + + assert isinstance(instance, dummy_base_model) + assert len(instance.warnings) > 0 + + from_dataframe_warnings = instance.warnings.get_by_field("from_dataframe") + assert len(from_dataframe_warnings) > 0 + assert "must implement _from_dataframe" in from_dataframe_warnings[0].message + + +def test_from_dataframe_error_handling_creates_fallback_instance(dummy_base_model): + """Test that from_dataframe creates fallback instance with warnings on error.""" + + # Override _from_dataframe to raise an error + def failing_from_dataframe(cls, df, **kwargs): + raise ValueError("Intentional test error") + + dummy_base_model._from_dataframe = classmethod(failing_from_dataframe) + + df = pd.DataFrame({"a": [1], "b": ["test"]}) + + # Should not raise, but create instance with warnings + instance = dummy_base_model.from_dataframe(df) + + assert isinstance(instance, dummy_base_model) + assert len(instance.warnings) > 0 + + from_dataframe_warnings = instance.warnings.get_by_field("from_dataframe") + assert len(from_dataframe_warnings) > 0 + assert "Failed to create from DataFrame" in from_dataframe_warnings[0].message + + +def test_from_dataframe_successful_delegation(): + """Test that from_dataframe properly delegates to _from_dataframe.""" + + class TestModel(Base): + x: int + y: str + + def _to_dataframe(self, **kwargs): + return pd.DataFrame({"x": [self.x], "y": [self.y]}) + + @classmethod + def _from_dataframe(cls, df, **kwargs): + row = df.iloc[0] + return cls(x=row["x"], y=row["y"]) + + # Test the successful path + df = pd.DataFrame({"x": [42], "y": ["hello"]}) + instance = TestModel.from_dataframe(df) + + assert instance.x == 42 + assert instance.y == "hello" + assert len(instance.warnings) == 0 diff --git a/tests/models/test_custom_curves.py b/tests/models/test_custom_curves.py index e96edad..db76634 100644 --- a/tests/models/test_custom_curves.py +++ b/tests/models/test_custom_curves.py @@ -182,3 +182,485 @@ def test_custom_curves_from_json_with_invalid_curve(): fallback_curve_warnings = curves.warnings.get_by_field(fallback_curve_key) assert len(fallback_curve_warnings) > 0 assert "Skipped invalid curve data" in fallback_curve_warnings[0].message + + +def test_custom_curve_from_dataframe_basic_roundtrip(): + """Test basic serialization and deserialization of a CustomCurve.""" + import numpy as np + + hours = 24 + test_data = pd.Series(np.random.rand(hours) * 100, name="test_curve") + original = CustomCurve(key="test_curve", type="profile") + + # Save test data to temporary file + temp_dir = Path("/tmp/test_curves") + temp_dir.mkdir(exist_ok=True) + temp_file = temp_dir / "test_curve.csv" + test_data.to_csv(temp_file, index=False, header=False) + original.file_path = temp_file + + try: + # Serialize to DataFrame + df = original.to_dataframe() + + # Should be time series format: one column with curve key, hour index + assert df.shape[1] == 1 + assert df.columns[0] == "test_curve" + assert df.index.name == "hour" + restored = CustomCurve.from_dataframe(df) + + # Verify properties + assert restored.key == original.key + assert restored.type == "custom" # Default type from DataFrame deserialization + assert restored.available() + + # Verify data is preserved + restored_data = restored.contents() + assert restored_data is not None + assert len(restored_data) == hours + + finally: + # Clean up + if temp_file.exists(): + temp_file.unlink() + if restored.file_path and restored.file_path.exists(): + restored.file_path.unlink() + try: + temp_dir.rmdir() + except OSError: + pass # Directory not empty or doesn't exist + + +def test_custom_curve_from_dataframe_without_file_path(): + """Test deserialization of curve without file_path.""" + original = CustomCurve(key="no_file_curve", type="custom") + + df = original.to_dataframe() + restored = CustomCurve.from_dataframe(df) + + assert restored.key == original.key + assert restored.type == "custom" # Default type from DataFrame deserialization + assert restored.file_path is None + assert not restored.available() + + +def test_custom_curve_from_dataframe_alternative_structure(): + """Test deserialization from DataFrame with time series data.""" + import numpy as np + + hours = 12 + data = np.random.rand(hours) * 50 + df = pd.DataFrame({"alt_curve": data}) + df.index.name = "hour" + + restored = CustomCurve.from_dataframe(df) + + assert restored.key == "alt_curve" + assert restored.type == "custom" # Default type from DataFrame deserialization + assert restored.available() # Should have saved the data + + # Verify data was saved correctly + restored_data = restored.contents() + assert restored_data is not None + assert len(restored_data) == hours + + # Clean up + if restored.file_path and restored.file_path.exists(): + restored.file_path.unlink() + + +def test_custom_curve_from_dataframe_invalid_multiple_rows(): + """Test error handling when DataFrame has multiple rows.""" + df = pd.DataFrame( + { + "key": ["curve1", "curve2"], + "type": ["profile", "availability"], + "file_path": [None, "/tmp/test.csv"], + } + ) + + restored = CustomCurve.from_dataframe(df) + + assert isinstance(restored, CustomCurve) + assert len(restored.warnings) > 0 + from_dataframe_warnings = restored.warnings.get_by_field("from_dataframe") + assert len(from_dataframe_warnings) > 0 + + +def test_custom_curve_from_dataframe_fallback_on_error(): + """Test fallback behavior when deserialization fails.""" + df = pd.DataFrame({"invalid_field": ["value"], "another_invalid": ["value2"]}) + + # Base.from_dataframe should handle the error and return instance with warning + restored = CustomCurve.from_dataframe(df) + + assert len(restored.warnings) > 0 + assert len(restored.warnings.get_fields_with_warnings()) > 0 + + +def test_custom_curves_from_dataframe_collection_roundtrip(): + """Test serialization and deserialization of a CustomCurves collection.""" + import numpy as np + + # Create test data for curves + hours = 24 + temp_dir = Path("/tmp/test_curves_collection") + temp_dir.mkdir(exist_ok=True) + + curves_list = [] + test_files = [] + + try: + # Create curves with actual data + for i, (key, curve_type) in enumerate( + [("curve1", "profile"), ("curve2", "availability"), ("curve3", "custom")] + ): + curve = CustomCurve(key=key, type=curve_type) + + # Only add data to some curves to test mixed scenarios + if i < 2: # First two curves get data + data = pd.Series(np.random.rand(hours) * (i + 1) * 10, name=key) + temp_file = temp_dir / f"{key}.csv" + data.to_csv(temp_file, index=False, header=False) + curve.file_path = temp_file + test_files.append(temp_file) + + curves_list.append(curve) + + original_collection = CustomCurves(curves=curves_list) + + # Serialize to DataFrame + df = original_collection.to_dataframe() + + # Should have columns for each curve and hour index + assert df.index.name == "hour" + assert len(df.columns) == 3 # Three curves + assert set(df.columns) == {"curve1", "curve2", "curve3"} + + # Deserialize back + restored_collection = CustomCurves.from_dataframe(df) + assert len(restored_collection.curves) == len(original_collection.curves) + + # Verify each curve (note: type information is not preserved in time series format) + for orig, rest in zip(original_collection.curves, restored_collection.curves): + assert orig.key == rest.key + + finally: + # Clean up + for file_path in test_files: + if file_path.exists(): + file_path.unlink() + + # Clean up any files created during deserialization + for curve in ( + restored_collection.curves if "restored_collection" in locals() else [] + ): + if curve.file_path and curve.file_path.exists(): + curve.file_path.unlink() + + try: + temp_dir.rmdir() + except OSError: + pass # Directory not empty or doesn't exist + + +def test_custom_curves_from_dataframe_empty_collection(): + """Test deserialization of empty collection.""" + empty_collection = CustomCurves(curves=[]) + + df = empty_collection.to_dataframe() + # Should be empty DataFrame with hour index + assert df.empty + assert df.index.name == "hour" + + restored = CustomCurves.from_dataframe(df) + + assert len(restored.curves) == 0 + + +def test_custom_curves_from_dataframe_with_invalid_curve_data(): + """Test handling of invalid curve data in collection.""" + import numpy as np + + hours = 10 + df = pd.DataFrame( + { + "valid_curve": np.random.rand(hours) * 100, + "problem_curve": [np.nan] * hours, # All NaN values + } + ) + df.index.name = "hour" + + restored_collection = CustomCurves.from_dataframe(df) + assert len(restored_collection.curves) == 2 + + # Check that we got both curves + curve_keys = {curve.key for curve in restored_collection.curves} + assert curve_keys == {"valid_curve", "problem_curve"} + + # Valid curve should have data, problem curve might not + valid_curve = next(c for c in restored_collection.curves if c.key == "valid_curve") + assert valid_curve.key == "valid_curve" + + # Clean up any created files + for curve in restored_collection.curves: + if curve.file_path and curve.file_path.exists(): + curve.file_path.unlink() + + +def test_custom_curves_from_dataframe_preserves_warnings(): + """Test that warnings from individual curves are preserved in collection.""" + curves = CustomCurves( + curves=[ + CustomCurve(key="good_curve", type="profile"), + CustomCurve(key="another_curve", type="availability"), + ] + ) + + df = curves.to_dataframe() + restored = CustomCurves.from_dataframe(df) + + assert len(restored.curves) == 2 + + +# --- Validate for Upload Tests --- # + + +def test_validate_for_upload_valid_curves(): + """Test validate_for_upload with valid curves (8760 numeric values)""" + import numpy as np + from pathlib import Path + import shutil + + # Create temporary files with valid data + temp_dir = Path("/tmp/test_curves") + temp_dir.mkdir(exist_ok=True) + + try: + # Valid curve data (8760 values) + valid_data = np.random.uniform(0, 100, 8760) + valid_file = temp_dir / "valid_curve.csv" + pd.Series(valid_data).to_csv(valid_file, header=False, index=False) + + curves = CustomCurves( + curves=[ + CustomCurve(key="valid_curve", type="profile", file_path=valid_file) + ] + ) + + validation_errors = curves.validate_for_upload() + + # Should have no errors + assert len(validation_errors) == 0 + + finally: + # Cleanup - remove entire directory tree + if temp_dir.exists(): + shutil.rmtree(temp_dir) + + +def test_validate_for_upload_curve_no_data(): + """Test validate_for_upload with curve that has no data available""" + curves = CustomCurves( + curves=[CustomCurve(key="no_data_curve", type="profile")] # No file_path set + ) + + validation_errors = curves.validate_for_upload() + + assert len(validation_errors) == 1 + assert "no_data_curve" in validation_errors + warnings_collector = validation_errors["no_data_curve"] + assert len(warnings_collector) == 1 + warnings_list = list(warnings_collector) + assert "Curve has no data available" in warnings_list[0].message + + +def test_validate_for_upload_wrong_length(): + """Test validate_for_upload with curve that has wrong number of values""" + import numpy as np + from pathlib import Path + import shutil + + temp_dir = Path("/tmp/test_curves") + temp_dir.mkdir(exist_ok=True) + + try: + # Wrong length data + short_data = np.random.uniform(0, 100, 100) + short_file = temp_dir / "short_curve.csv" + pd.Series(short_data).to_csv(short_file, header=False, index=False) + + curves = CustomCurves( + curves=[ + CustomCurve(key="short_curve", type="profile", file_path=short_file) + ] + ) + + validation_errors = curves.validate_for_upload() + + assert len(validation_errors) == 1 + assert "short_curve" in validation_errors + warnings_collector = validation_errors["short_curve"] + assert len(warnings_collector) == 1 + warnings_list = list(warnings_collector) + assert ( + "Curve must contain exactly 8,760 values, found 100" + in warnings_list[0].message + ) + + finally: + # Cleanup - remove entire directory tree + if temp_dir.exists(): + shutil.rmtree(temp_dir) + + +def test_validate_for_upload_non_numeric_values(): + """Test validate_for_upload with curve that has non-numeric values""" + from pathlib import Path + import shutil + + temp_dir = Path("/tmp/test_curves") + temp_dir.mkdir(exist_ok=True) + + try: + # Create file with non-numeric data + non_numeric_file = temp_dir / "non_numeric_curve.csv" + with open(non_numeric_file, "w") as f: + # Mix of numeric and non-numeric values + for i in range(8760): + if i % 100 == 0: + f.write("not_a_number\n") + else: + f.write(f"{i * 0.5}\n") + + curves = CustomCurves( + curves=[ + CustomCurve( + key="non_numeric_curve", type="profile", file_path=non_numeric_file + ) + ] + ) + + validation_errors = curves.validate_for_upload() + + assert len(validation_errors) == 1 + assert "non_numeric_curve" in validation_errors + warnings_collector = validation_errors["non_numeric_curve"] + assert len(warnings_collector) == 1 + warnings_list = list(warnings_collector) + assert "Curve contains non-numeric values" in warnings_list[0].message + + finally: + # Cleanup - remove entire directory tree + if temp_dir.exists(): + shutil.rmtree(temp_dir) + + +def test_validate_for_upload_empty_curve(): + """Test validate_for_upload with curve that has empty data""" + from pathlib import Path + import shutil + + temp_dir = Path("/tmp/test_curves") + temp_dir.mkdir(exist_ok=True) + + try: + empty_file = temp_dir / "empty_curve.csv" + empty_file.touch() + + curves = CustomCurves( + curves=[ + CustomCurve(key="empty_curve", type="profile", file_path=empty_file) + ] + ) + + validation_errors = curves.validate_for_upload() + + assert len(validation_errors) == 1 + assert "empty_curve" in validation_errors + warnings_collector = validation_errors["empty_curve"] + assert len(warnings_collector) == 1 + warnings_list = list(warnings_collector) + assert "Curve contains no data" in warnings_list[0].message + + finally: + # Cleanup - remove entire directory tree + if temp_dir.exists(): + shutil.rmtree(temp_dir) + + +def test_validate_for_upload_file_read_error(): + """Test validate_for_upload with curve file that cannot be read""" + from pathlib import Path + + non_existent_file = Path("/tmp/non_existent_curve.csv") + + curves = CustomCurves( + curves=[ + CustomCurve( + key="unreadable_curve", type="profile", file_path=non_existent_file + ) + ] + ) + + validation_errors = curves.validate_for_upload() + + assert len(validation_errors) == 1 + assert "unreadable_curve" in validation_errors + warnings_collector = validation_errors["unreadable_curve"] + assert len(warnings_collector) == 1 + warnings_list = list(warnings_collector) # Convert to list to access by index + assert "Error reading curve data:" in warnings_list[0].message + + +def test_validate_for_upload_multiple_curves_mixed_validity(): + """Test validate_for_upload with mix of valid and invalid curves""" + import numpy as np + from pathlib import Path + import shutil + + temp_dir = Path("/tmp/test_curves") + temp_dir.mkdir(exist_ok=True) + + try: + # Valid curve + valid_data = np.random.uniform(0, 100, 8760) + valid_file = temp_dir / "valid_curve.csv" + pd.Series(valid_data).to_csv(valid_file, header=False, index=False) + + # Invalid curve (wrong length) + invalid_data = np.random.uniform(0, 100, 100) + invalid_file = temp_dir / "invalid_curve.csv" + pd.Series(invalid_data).to_csv(invalid_file, header=False, index=False) + + curves = CustomCurves( + curves=[ + CustomCurve(key="valid_curve", type="profile", file_path=valid_file), + CustomCurve( + key="invalid_curve", type="profile", file_path=invalid_file + ), + CustomCurve(key="no_data_curve", type="profile"), # No file path + ] + ) + + validation_errors = curves.validate_for_upload() + + # Should have errors for 2 curves, but not the valid one + assert len(validation_errors) == 2 + assert "valid_curve" not in validation_errors + assert "invalid_curve" in validation_errors + assert "no_data_curve" in validation_errors + + # Check specific error messages + invalid_warnings = list(validation_errors["invalid_curve"]) + no_data_warnings = list(validation_errors["no_data_curve"]) + assert ( + "Curve must contain exactly 8,760 values, found 100" + in invalid_warnings[0].message + ) + assert "Curve has no data available" in no_data_warnings[0].message + + finally: + # Cleanup - remove entire directory tree + if temp_dir.exists(): + shutil.rmtree(temp_dir) diff --git a/tests/models/test_scenario.py b/tests/models/test_scenario.py index e9d70b5..332dab3 100644 --- a/tests/models/test_scenario.py +++ b/tests/models/test_scenario.py @@ -468,7 +468,7 @@ def mock_runner_run(client, scen, inputs): # ------ sortables ------ # -@pytest.fixture(autouse=True) +@pytest.fixture def patch_sortables_from_json(monkeypatch): dummy = object() monkeypatch.setattr(Sortables, "from_json", staticmethod(lambda data: dummy)) @@ -691,3 +691,229 @@ def test_scenario_show_all_warnings(scenario, capsys): assert f"Warnings for Scenario {scenario.id}" in captured.out assert "Scenario warnings:" in captured.out assert "Test warning" in captured.out + + +# ------ Update Custom Curves Tests ------ # + + +def test_scenario_update_custom_curves_success(monkeypatch, ok_service_result): + """Test successful custom curves update""" + from pyetm.models.custom_curves import CustomCurve, CustomCurves + from pyetm.services.scenario_runners.update_custom_curves import UpdateCustomCurvesRunner + from pyetm.models.warnings import WarningCollector + import pandas as pd + import numpy as np + + scenario = Scenario(id=12345, area_code="nl", end_year=2050) + scenario._custom_curves = CustomCurves(curves=[]) + + # Create valid custom curves (mock file data) + curve = CustomCurve(key="test_curve", type="profile") + custom_curves = CustomCurves(curves=[curve]) + + # Mock validate_for_upload to return no errors + def mock_validate(): + return {} + + # Mock UpdateCustomCurvesRunner to succeed + def mock_runner(client, scenario, curves): + return ok_service_result({ + "uploaded_curves": ["test_curve"], + "total_curves": 1, + "successful_uploads": 1 + }) + + monkeypatch.setattr(custom_curves, "validate_for_upload", mock_validate) + monkeypatch.setattr(UpdateCustomCurvesRunner, "run", mock_runner) + + # Should succeed without raising exception + scenario.update_custom_curves(custom_curves) + + # Verify curve was added to scenario's curves + assert len(scenario.custom_curves.curves) == 1 + assert scenario.custom_curves.curves[0].key == "test_curve" + + +def test_scenario_update_custom_curves_validation_error(): + """Test custom curves update with validation errors""" + from pyetm.models.custom_curves import CustomCurve, CustomCurves + from pyetm.models.warnings import WarningCollector + + scenario = Scenario(id=12345, area_code="nl", end_year=2050) + + # Create custom curves + curve = CustomCurve(key="invalid_curve", type="profile") + custom_curves = CustomCurves(curves=[curve]) + + # Mock validate_for_upload to return validation errors + def mock_validate(): + warning_collector = WarningCollector() + warning_collector.add("invalid_curve", "Curve contains non-numeric values") + return {"invalid_curve": warning_collector} + + custom_curves.validate_for_upload = mock_validate + + # Should raise ScenarioError due to validation failure + with pytest.raises(ScenarioError) as exc_info: + scenario.update_custom_curves(custom_curves) + + assert "Could not update custom curves" in str(exc_info.value) + assert "invalid_curve" in str(exc_info.value) + assert "Curve contains non-numeric values" in str(exc_info.value) + + +def test_scenario_update_custom_curves_runner_failure(monkeypatch, fail_service_result): + """Test custom curves update with runner failure""" + from pyetm.models.custom_curves import CustomCurve, CustomCurves + from pyetm.services.scenario_runners.update_custom_curves import UpdateCustomCurvesRunner + + scenario = Scenario(id=12345, area_code="nl", end_year=2050) + + # Create valid custom curves + curve = CustomCurve(key="test_curve", type="profile") + custom_curves = CustomCurves(curves=[curve]) + + # Mock validate_for_upload to return no errors + def mock_validate(): + return {} + + # Mock UpdateCustomCurvesRunner to fail + def mock_runner(client, scenario, curves): + return fail_service_result(["HTTP 500: Internal server error"]) + + monkeypatch.setattr(custom_curves, "validate_for_upload", mock_validate) + monkeypatch.setattr(UpdateCustomCurvesRunner, "run", mock_runner) + + # Should raise ScenarioError due to runner failure + with pytest.raises(ScenarioError) as exc_info: + scenario.update_custom_curves(custom_curves) + + assert "Could not update custom curves" in str(exc_info.value) + assert "HTTP 500: Internal server error" in str(exc_info.value) + + +def test_scenario_update_custom_curves_updates_existing_curve(monkeypatch, ok_service_result): + """Test that updating existing curves replaces file_path""" + from pyetm.models.custom_curves import CustomCurve, CustomCurves + from pyetm.services.scenario_runners.update_custom_curves import UpdateCustomCurvesRunner + from pathlib import Path + + scenario = Scenario(id=12345, area_code="nl", end_year=2050) + + # Set up scenario with existing curve + existing_curve = CustomCurve(key="existing_curve", type="profile", file_path=Path("/old/path.csv")) + scenario._custom_curves = CustomCurves(curves=[existing_curve]) + + # Create new curves with same key but different file path + new_curve = CustomCurve(key="existing_curve", type="profile", file_path=Path("/new/path.csv")) + custom_curves = CustomCurves(curves=[new_curve]) + + # Mock validate_for_upload to return no errors + def mock_validate(): + return {} + + # Mock UpdateCustomCurvesRunner to succeed + def mock_runner(client, scenario, curves): + return ok_service_result({ + "uploaded_curves": ["existing_curve"], + "total_curves": 1, + "successful_uploads": 1 + }) + + monkeypatch.setattr(custom_curves, "validate_for_upload", mock_validate) + monkeypatch.setattr(UpdateCustomCurvesRunner, "run", mock_runner) + + # Update curves + scenario.update_custom_curves(custom_curves) + + # Verify existing curve was updated with new file path + assert len(scenario.custom_curves.curves) == 1 + updated_curve = scenario.custom_curves.curves[0] + assert updated_curve.key == "existing_curve" + assert updated_curve.file_path == Path("/new/path.csv") + + +def test_scenario_update_custom_curves_adds_new_curve(monkeypatch, ok_service_result): + """Test that new curves are added to scenario's curves collection""" + from pyetm.models.custom_curves import CustomCurve, CustomCurves + from pyetm.services.scenario_runners.update_custom_curves import UpdateCustomCurvesRunner + from pathlib import Path + + scenario = Scenario(id=12345, area_code="nl", end_year=2050) + + # Set up scenario with one existing curve + existing_curve = CustomCurve(key="existing_curve", type="profile", file_path=Path("/old/path.csv")) + scenario._custom_curves = CustomCurves(curves=[existing_curve]) + + # Create new curve with different key + new_curve = CustomCurve(key="new_curve", type="availability", file_path=Path("/new/path.csv")) + custom_curves = CustomCurves(curves=[new_curve]) + + # Mock validate_for_upload to return no errors + def mock_validate(): + return {} + + # Mock UpdateCustomCurvesRunner to succeed + def mock_runner(client, scenario, curves): + return ok_service_result({ + "uploaded_curves": ["new_curve"], + "total_curves": 1, + "successful_uploads": 1 + }) + + monkeypatch.setattr(custom_curves, "validate_for_upload", mock_validate) + monkeypatch.setattr(UpdateCustomCurvesRunner, "run", mock_runner) + + # Update curves + scenario.update_custom_curves(custom_curves) + + # Verify both curves exist + assert len(scenario.custom_curves.curves) == 2 + curve_keys = {curve.key for curve in scenario.custom_curves.curves} + assert curve_keys == {"existing_curve", "new_curve"} + + +def test_scenario_update_custom_curves_multiple_validation_errors(): + """Test custom curves update with multiple validation errors""" + from pyetm.models.custom_curves import CustomCurve, CustomCurves + from pyetm.models.warnings import WarningCollector + + scenario = Scenario(id=12345, area_code="nl", end_year=2050) + + # Create custom curves + curves = [ + CustomCurve(key="curve1", type="profile"), + CustomCurve(key="curve2", type="availability") + ] + custom_curves = CustomCurves(curves=curves) + + # Mock validate_for_upload to return multiple validation errors + def mock_validate(): + errors = {} + + # Curve1 errors + curve1_warnings = WarningCollector() + curve1_warnings.add("curve1", "Wrong length") + curve1_warnings.add("curve1", "Non-numeric values") + errors["curve1"] = curve1_warnings + + # Curve2 errors + curve2_warnings = WarningCollector() + curve2_warnings.add("curve2", "No data available") + errors["curve2"] = curve2_warnings + + return errors + + custom_curves.validate_for_upload = mock_validate + + # Should raise ScenarioError with all validation errors + with pytest.raises(ScenarioError) as exc_info: + scenario.update_custom_curves(custom_curves) + + error_message = str(exc_info.value) + assert "Could not update custom curves" in error_message + assert "curve1" in error_message + assert "curve2" in error_message + assert "Wrong length" in error_message + assert "Non-numeric values" in error_message + assert "No data available" in error_message diff --git a/tests/models/test_warnings.py b/tests/models/test_warnings.py index 486390c..b1cb44a 100644 --- a/tests/models/test_warnings.py +++ b/tests/models/test_warnings.py @@ -193,19 +193,6 @@ def test_get_fields_with_warnings(): assert "field2" in fields -def test_to_legacy_dict(): - """Test conversion to legacy dictionary format.""" - collector = WarningCollector() - collector.add("field1", "Warning 1") - collector.add("field1", "Warning 2") - collector.add("field2", "Warning 3") - - legacy_dict = collector.to_legacy_dict() - - expected = {"field1": ["Warning 1", "Warning 2"], "field2": ["Warning 3"]} - assert legacy_dict == expected - - def test_to_dict(): """Test conversion to detailed dictionary format.""" collector = WarningCollector() diff --git a/tests/services/conftest.py b/tests/services/conftest.py index c6503c0..079fd7d 100644 --- a/tests/services/conftest.py +++ b/tests/services/conftest.py @@ -54,7 +54,6 @@ def mock_method(url, params=None, json=None, **kwargs): if kwargs: call_data.update(kwargs) - # If no parameters, record None for backwards compatibility call_record = (url, call_data if call_data else None) self.calls.append(call_record) diff --git a/tests/services/scenario_runners/test_update_custom_curves.py b/tests/services/scenario_runners/test_update_custom_curves.py new file mode 100644 index 0000000..7036620 --- /dev/null +++ b/tests/services/scenario_runners/test_update_custom_curves.py @@ -0,0 +1,302 @@ +import pandas as pd +import numpy as np +from pathlib import Path +from unittest.mock import Mock, patch +import pytest +from pyetm.models.custom_curves import CustomCurve, CustomCurves +from pyetm.services.scenario_runners.update_custom_curves import ( + UpdateCustomCurvesRunner, +) +from pyetm.services.service_result import ServiceResult + + +@pytest.fixture +def temp_curve_files(): + """Fixture that creates temporary curve files for testing""" + temp_dir = Path("/tmp/test_update_curves") + temp_dir.mkdir(exist_ok=True) + + files = {} + + # Create valid curve file (8760 values) + valid_data = np.random.uniform(0, 100, 8760) + valid_file = temp_dir / "valid_curve.csv" + pd.Series(valid_data).to_csv(valid_file, header=False, index=False) + files["valid"] = valid_file + + # Create another valid curve file + another_data = np.random.uniform(50, 150, 8760) + another_file = temp_dir / "another_curve.csv" + pd.Series(another_data).to_csv(another_file, header=False, index=False) + files["another"] = another_file + + yield files + + # Cleanup + for file_path in files.values(): + file_path.unlink(missing_ok=True) + temp_dir.rmdir() + + +def test_update_custom_curves_success_single_curve(temp_curve_files): + """Test successful upload of a single custom curve""" + # Mock client + mock_client = Mock() + mock_client.session.base_url = "https://engine.example.com/api/v3" + + # Mock scenario + mock_scenario = Mock() + mock_scenario.id = 12345 + + # Create custom curves with one curve + curve = CustomCurve( + key="test_curve", type="profile", file_path=temp_curve_files["valid"] + ) + custom_curves = CustomCurves(curves=[curve]) + + # Mock successful _make_request response + with patch.object( + UpdateCustomCurvesRunner, + "_make_request", + return_value=ServiceResult.ok(data={"status": "uploaded"}), + ) as mock_make_request: + + result = UpdateCustomCurvesRunner.run(mock_client, mock_scenario, custom_curves) + + # Verify result + assert result.success is True + assert result.data["total_curves"] == 1 + assert result.data["successful_uploads"] == 1 + assert "test_curve" in result.data["uploaded_curves"] + assert len(result.errors) == 0 + + # Verify _make_request was called correctly + mock_make_request.assert_called_once() + call_args = mock_make_request.call_args + assert call_args[1]["client"] == mock_client + assert call_args[1]["method"] == "put" + assert "/scenarios/12345/custom_curves/test_curve" in call_args[1]["path"] + assert "files" in call_args[1] + assert call_args[1]["headers"]["Content-Type"] is None + + +def test_update_custom_curves_success_multiple_curves(temp_curve_files): + """Test successful upload of multiple custom curves""" + # Mock client + mock_client = Mock() + mock_client.session.base_url = "https://engine.example.com/api/v3" + + # Mock scenario + mock_scenario = Mock() + mock_scenario.id = 54321 + + # Create custom curves with multiple curves + curves = [ + CustomCurve(key="curve_1", type="profile", file_path=temp_curve_files["valid"]), + CustomCurve( + key="curve_2", type="availability", file_path=temp_curve_files["another"] + ), + ] + custom_curves = CustomCurves(curves=curves) + + # Mock successful _make_request responses + with patch.object( + UpdateCustomCurvesRunner, + "_make_request", + return_value=ServiceResult.ok(data={"status": "uploaded"}), + ) as mock_make_request: + + result = UpdateCustomCurvesRunner.run(mock_client, mock_scenario, custom_curves) + + # Verify result + assert result.success is True + assert result.data["total_curves"] == 2 + assert result.data["successful_uploads"] == 2 + assert set(result.data["uploaded_curves"]) == {"curve_1", "curve_2"} + assert len(result.errors) == 0 + + # Verify _make_request was called twice + assert mock_make_request.call_count == 2 + + +def test_update_custom_curves_curve_without_file(): + """Test upload of curve without file (uses contents() method)""" + # Mock client + mock_client = Mock() + mock_client.session.base_url = "https://engine.example.com/api/v3" + + # Mock scenario + mock_scenario = Mock() + mock_scenario.id = 99999 + + # Create curve without file_path but with contents + curve = CustomCurve(key="no_file_curve", type="profile") + + # Mock curve.contents() to return data + mock_series = pd.Series(np.random.uniform(0, 100, 8760)) + + with patch( + "pyetm.models.custom_curves.CustomCurve.contents", return_value=mock_series + ): + custom_curves = CustomCurves(curves=[curve]) + + # Mock successful _make_request response + with patch.object( + UpdateCustomCurvesRunner, + "_make_request", + return_value=ServiceResult.ok(data={"status": "uploaded"}), + ) as mock_make_request: + + result = UpdateCustomCurvesRunner.run( + mock_client, mock_scenario, custom_curves + ) + + # Verify result + assert result.success is True + assert result.data["successful_uploads"] == 1 + assert "no_file_curve" in result.data["uploaded_curves"] + + # Verify _make_request was called with file content + mock_make_request.assert_called_once() + call_args = mock_make_request.call_args + assert "files" in call_args[1] + + +def test_update_custom_curves_http_error(): + """Test handling of HTTP errors during upload""" + # Mock client + mock_client = Mock() + mock_client.session.base_url = "https://engine.example.com/api/v3" + + # Mock scenario + mock_scenario = Mock() + mock_scenario.id = 12345 + + # Create custom curves + curve = CustomCurve(key="error_curve", type="profile") + mock_series = pd.Series(np.random.uniform(0, 100, 8760)) + + with patch( + "pyetm.models.custom_curves.CustomCurve.contents", return_value=mock_series + ): + custom_curves = CustomCurves(curves=[curve]) + + # Mock _make_request failure response + with patch.object( + UpdateCustomCurvesRunner, + "_make_request", + return_value=ServiceResult.fail(["422: Validation failed"]), + ) as mock_make_request: + + result = UpdateCustomCurvesRunner.run( + mock_client, mock_scenario, custom_curves + ) + + # Verify result shows failure + assert result.success is False + assert result.data["successful_uploads"] == 0 + assert len(result.errors) == 1 + assert "422: Validation failed" in result.errors[0] + + +def test_update_custom_curves_network_exception(): + """Test handling of network exceptions during upload""" + # Mock client + mock_client = Mock() + mock_client.session.base_url = "https://engine.example.com/api/v3" + + # Mock scenario + mock_scenario = Mock() + mock_scenario.id = 12345 + + # Create custom curves + curve = CustomCurve(key="network_error_curve", type="profile") + mock_series = pd.Series(np.random.uniform(0, 100, 8760)) + + with patch( + "pyetm.models.custom_curves.CustomCurve.contents", return_value=mock_series + ): + custom_curves = CustomCurves(curves=[curve]) + + # Mock _make_request raising exception + with patch.object( + UpdateCustomCurvesRunner, + "_make_request", + side_effect=ConnectionError("Network unreachable"), + ): + result = UpdateCustomCurvesRunner.run( + mock_client, mock_scenario, custom_curves + ) + + # Verify result shows failure + assert result.success is False + assert result.data["successful_uploads"] == 0 + assert len(result.errors) == 1 + assert ( + "Error uploading network_error_curve: Network unreachable" + in result.errors[0] + ) + + +def test_update_custom_curves_mixed_success_failure(temp_curve_files): + """Test upload with mix of successful and failed curves""" + # Mock client + mock_client = Mock() + mock_client.session.base_url = "https://engine.example.com/api/v3" + + # Mock scenario + mock_scenario = Mock() + mock_scenario.id = 12345 + + # Create multiple curves + curves = [ + CustomCurve( + key="success_curve", type="profile", file_path=temp_curve_files["valid"] + ), + CustomCurve( + key="fail_curve", type="availability", file_path=temp_curve_files["another"] + ), + ] + custom_curves = CustomCurves(curves=curves) + + # Mock mixed responses (first succeeds, second fails) + success_result = ServiceResult.ok(data={"status": "uploaded"}) + fail_result = ServiceResult.fail(["500: Internal server error"]) + + with patch.object( + UpdateCustomCurvesRunner, + "_make_request", + side_effect=[success_result, fail_result], + ) as mock_make_request: + + result = UpdateCustomCurvesRunner.run(mock_client, mock_scenario, custom_curves) + + # Verify mixed result + assert result.success is False + assert result.data["total_curves"] == 2 + assert result.data["successful_uploads"] == 1 + assert result.data["uploaded_curves"] == ["success_curve"] + assert len(result.errors) == 1 + assert "500: Internal server error" in result.errors[0] + + +def test_update_custom_curves_empty_curves_list(): + """Test upload with empty curves list""" + # Mock client + mock_client = Mock() + mock_client.session.base_url = "https://engine.example.com/api/v3" + + # Mock scenario + mock_scenario = Mock() + mock_scenario.id = 12345 + + custom_curves = CustomCurves(curves=[]) + + result = UpdateCustomCurvesRunner.run(mock_client, mock_scenario, custom_curves) + + # Should succeed with no uploads + assert result.success is True + assert result.data["total_curves"] == 0 + assert result.data["successful_uploads"] == 0 + assert result.data["uploaded_curves"] == [] + assert len(result.errors) == 0 diff --git a/tests/services/scenario_runners/test_update_sortables.py b/tests/services/scenario_runners/test_update_sortables.py new file mode 100644 index 0000000..e200e41 --- /dev/null +++ b/tests/services/scenario_runners/test_update_sortables.py @@ -0,0 +1,445 @@ +from pyetm.services.scenario_runners.update_sortables import UpdateSortablesRunner + + +def test_update_sortables_success(dummy_client, fake_response, dummy_scenario): + """Test successful sortables update""" + body = {"order": ["item_1", "item_2", "item_3"]} + response = fake_response(ok=True, status_code=200, json_data=body) + client = dummy_client(response, method="put") + scenario = dummy_scenario(1) + order = ["item_1", "item_2", "item_3"] + + result = UpdateSortablesRunner.run(client, scenario, "demand", order) + + assert result.success is True + assert result.data == body + assert result.errors == [] + assert client.calls == [ + ("/scenarios/1/user_sortables/demand", {"json": {"order": order}}) + ] + + +def test_update_sortables_with_subtype(dummy_client, fake_response, dummy_scenario): + """Test sortables update with subtype parameter""" + body = {"order": ["heat_item_1", "heat_item_2"]} + response = fake_response(ok=True, status_code=200, json_data=body) + client = dummy_client(response, method="put") + scenario = dummy_scenario(2) + order = ["heat_item_1", "heat_item_2"] + + result = UpdateSortablesRunner.run( + client, scenario, "heat_network", order, subtype="lt" + ) + + assert result.success is True + assert result.data == body + assert result.errors == [] + assert client.calls == [ + ( + "/scenarios/2/user_sortables/heat_network?subtype=lt", + {"json": {"order": order}}, + ) + ] + + +def test_update_sortables_heat_network_mt_subtype( + dummy_client, fake_response, dummy_scenario +): + """Test heat network sortables update with medium temperature subtype""" + body = {"order": ["mt_source_1", "mt_source_2", "mt_source_3"]} + response = fake_response(ok=True, status_code=200, json_data=body) + client = dummy_client(response, method="put") + scenario = dummy_scenario(3) + order = ["mt_source_1", "mt_source_2", "mt_source_3"] + + result = UpdateSortablesRunner.run( + client, scenario, "heat_network", order, subtype="mt" + ) + + assert result.success is True + assert result.data == body + assert result.errors == [] + assert client.calls == [ + ( + "/scenarios/3/user_sortables/heat_network?subtype=mt", + {"json": {"order": order}}, + ) + ] + + +def test_update_sortables_heat_network_ht_subtype( + dummy_client, fake_response, dummy_scenario +): + """Test heat network sortables update with high temperature subtype""" + body = {"order": ["ht_source_1", "ht_source_2"]} + response = fake_response(ok=True, status_code=200, json_data=body) + client = dummy_client(response, method="put") + scenario = dummy_scenario(4) + order = ["ht_source_1", "ht_source_2"] + + result = UpdateSortablesRunner.run( + client, scenario, "heat_network", order, subtype="ht" + ) + + assert result.success is True + assert result.data == body + assert result.errors == [] + assert client.calls == [ + ( + "/scenarios/4/user_sortables/heat_network?subtype=ht", + {"json": {"order": order}}, + ) + ] + + +def test_update_sortables_empty_order(dummy_client, fake_response, dummy_scenario): + """Test sortables update with empty order list""" + body = {"order": []} + response = fake_response(ok=True, status_code=200, json_data=body) + client = dummy_client(response, method="put") + scenario = dummy_scenario(5) + order = [] + + result = UpdateSortablesRunner.run(client, scenario, "demand", order) + + assert result.success is True + assert result.data == body + assert result.errors == [] + assert client.calls == [ + ("/scenarios/5/user_sortables/demand", {"json": {"order": []}}) + ] + + +def test_update_sortables_single_item(dummy_client, fake_response, dummy_scenario): + """Test sortables update with single item in order""" + body = {"order": ["single_item"]} + response = fake_response(ok=True, status_code=200, json_data=body) + client = dummy_client(response, method="put") + scenario = dummy_scenario(6) + order = ["single_item"] + + result = UpdateSortablesRunner.run(client, scenario, "supply", order) + + assert result.success is True + assert result.data == body + assert result.errors == [] + assert client.calls == [ + ("/scenarios/6/user_sortables/supply", {"json": {"order": order}}) + ] + + +def test_update_sortables_numeric_order_items( + dummy_client, fake_response, dummy_scenario +): + """Test sortables update with numeric items in order""" + body = {"order": [1, 2, 3, 4]} + response = fake_response(ok=True, status_code=200, json_data=body) + client = dummy_client(response, method="put") + scenario = dummy_scenario(7) + order = [1, 2, 3, 4] + + result = UpdateSortablesRunner.run(client, scenario, "demand", order) + + assert result.success is True + assert result.data == body + assert result.errors == [] + assert client.calls == [ + ("/scenarios/7/user_sortables/demand", {"json": {"order": order}}) + ] + + +def test_update_sortables_mixed_type_order_items( + dummy_client, fake_response, dummy_scenario +): + """Test sortables update with mixed type items in order""" + body = {"order": ["item_1", 2, "item_3", 4]} + response = fake_response(ok=True, status_code=200, json_data=body) + client = dummy_client(response, method="put") + scenario = dummy_scenario(8) + order = ["item_1", 2, "item_3", 4] + + result = UpdateSortablesRunner.run(client, scenario, "demand", order) + + assert result.success is True + assert result.data == body + assert result.errors == [] + assert client.calls == [ + ("/scenarios/8/user_sortables/demand", {"json": {"order": order}}) + ] + + +def test_update_sortables_with_kwargs(dummy_client, fake_response, dummy_scenario): + """Test sortables update with additional kwargs""" + body = {"order": ["item_1", "item_2"]} + response = fake_response(ok=True, status_code=200, json_data=body) + client = dummy_client(response, method="put") + scenario = dummy_scenario(9) + order = ["item_1", "item_2"] + + result = UpdateSortablesRunner.run(client, scenario, "demand", order, timeout=30) + + assert result.success is True + assert result.data == body + assert result.errors == [] + # Verify the basic structure - kwargs handling might vary + assert len(client.calls) == 1 + assert client.calls[0][0] == "/scenarios/9/user_sortables/demand" + assert client.calls[0][1]["json"] == {"order": order} + + +def test_update_sortables_large_scenario_id( + dummy_client, fake_response, dummy_scenario +): + """Test with large scenario ID""" + body = {"order": ["item_1", "item_2"]} + response = fake_response(ok=True, status_code=200, json_data=body) + client = dummy_client(response, method="put") + scenario = dummy_scenario(999999) + order = ["item_1", "item_2"] + + result = UpdateSortablesRunner.run(client, scenario, "demand", order) + + assert result.success is True + assert client.calls[0][0] == "/scenarios/999999/user_sortables/demand" + + +def test_update_sortables_http_failure_422(dummy_client, fake_response, dummy_scenario): + """Test HTTP 422 validation error""" + response = fake_response(ok=False, status_code=422, text="Invalid sortable order") + client = dummy_client(response, method="put") + scenario = dummy_scenario(10) + order = ["invalid_item"] + + result = UpdateSortablesRunner.run(client, scenario, "demand", order) + + assert result.success is False + assert result.data is None + assert result.errors == ["422: Invalid sortable order"] + + +def test_update_sortables_http_failure_404(dummy_client, fake_response, dummy_scenario): + """Test HTTP 404 scenario not found""" + response = fake_response(ok=False, status_code=404, text="Scenario not found") + client = dummy_client(response, method="put") + scenario = dummy_scenario(999) + order = ["item_1", "item_2"] + + result = UpdateSortablesRunner.run(client, scenario, "demand", order) + + assert result.success is False + assert result.data is None + assert result.errors == ["404: Scenario not found"] + + +def test_update_sortables_http_failure_400(dummy_client, fake_response, dummy_scenario): + """Test HTTP 400 bad request""" + response = fake_response( + ok=False, status_code=400, text="Bad request - invalid sortable type" + ) + client = dummy_client(response, method="put") + scenario = dummy_scenario(11) + order = ["item_1"] + + result = UpdateSortablesRunner.run(client, scenario, "invalid_type", order) + + assert result.success is False + assert result.data is None + assert result.errors == ["400: Bad request - invalid sortable type"] + + +def test_update_sortables_http_failure_403(dummy_client, fake_response, dummy_scenario): + """Test HTTP 403 forbidden access""" + response = fake_response( + ok=False, status_code=403, text="Forbidden - access denied" + ) + client = dummy_client(response, method="put") + scenario = dummy_scenario(12) + order = ["item_1", "item_2"] + + result = UpdateSortablesRunner.run(client, scenario, "demand", order) + + assert result.success is False + assert result.data is None + assert result.errors == ["403: Forbidden - access denied"] + + +def test_update_sortables_http_failure_500(dummy_client, fake_response, dummy_scenario): + """Test HTTP 500 internal server error""" + response = fake_response(ok=False, status_code=500, text="Internal Server Error") + client = dummy_client(response, method="put") + scenario = dummy_scenario(13) + order = ["item_1", "item_2"] + + result = UpdateSortablesRunner.run(client, scenario, "demand", order) + + assert result.success is False + assert result.data is None + assert result.errors == ["500: Internal Server Error"] + + +def test_update_sortables_connection_error(dummy_client, dummy_scenario): + """Test connection error handling""" + client = dummy_client(ConnectionError("Connection failed"), method="put") + scenario = dummy_scenario(14) + order = ["item_1", "item_2"] + + result = UpdateSortablesRunner.run(client, scenario, "demand", order) + + assert result.success is False + assert result.data is None + assert any("Connection failed" in err for err in result.errors) + + +def test_update_sortables_permission_error(dummy_client, dummy_scenario): + """Test permission error handling""" + client = dummy_client(PermissionError("Access denied"), method="put") + scenario = dummy_scenario(15) + order = ["item_1", "item_2"] + + result = UpdateSortablesRunner.run(client, scenario, "demand", order) + + assert result.success is False + assert result.data is None + assert any("Access denied" in err for err in result.errors) + + +def test_update_sortables_value_error(dummy_client, dummy_scenario): + """Test value error handling""" + client = dummy_client(ValueError("Invalid value provided"), method="put") + scenario = dummy_scenario(16) + order = ["item_1", "item_2"] + + result = UpdateSortablesRunner.run(client, scenario, "demand", order) + + assert result.success is False + assert result.data is None + assert any("Invalid value provided" in err for err in result.errors) + + +def test_update_sortables_generic_exception(dummy_client, dummy_scenario): + """Test generic exception handling""" + client = dummy_client(RuntimeError("Unexpected error"), method="put") + scenario = dummy_scenario(17) + order = ["item_1", "item_2"] + + result = UpdateSortablesRunner.run(client, scenario, "demand", order) + + assert result.success is False + assert result.data is None + assert any("Unexpected error" in err for err in result.errors) + + +def test_update_sortables_payload_structure( + dummy_client, fake_response, dummy_scenario +): + """Test that the payload is correctly structured for the API""" + body = {"order": ["a", "b", "c", "d"]} + response = fake_response(ok=True, status_code=200, json_data=body) + client = dummy_client(response, method="put") + scenario = dummy_scenario(18) + order = ["a", "b", "c", "d"] + + UpdateSortablesRunner.run(client, scenario, "demand", order) + + # Verify the exact payload structure + expected_call = ( + "/scenarios/18/user_sortables/demand", + {"json": {"order": ["a", "b", "c", "d"]}}, + ) + assert client.calls == [expected_call] + + +def test_update_sortables_url_construction_no_subtype( + dummy_client, fake_response, dummy_scenario +): + """Test URL construction without subtype""" + body = {"order": ["item_1"]} + response = fake_response(ok=True, status_code=200, json_data=body) + client = dummy_client(response, method="put") + scenario = dummy_scenario(19) + order = ["item_1"] + + UpdateSortablesRunner.run(client, scenario, "supply", order) + + assert client.calls[0][0] == "/scenarios/19/user_sortables/supply" + + +def test_update_sortables_url_construction_with_subtype( + dummy_client, fake_response, dummy_scenario +): + """Test URL construction with subtype""" + body = {"order": ["item_1"]} + response = fake_response(ok=True, status_code=200, json_data=body) + client = dummy_client(response, method="put") + scenario = dummy_scenario(20) + order = ["item_1"] + + UpdateSortablesRunner.run(client, scenario, "heat_network", order, subtype="mt") + + assert client.calls[0][0] == "/scenarios/20/user_sortables/heat_network?subtype=mt" + + +def test_update_sortables_different_sortable_types( + dummy_client, fake_response, dummy_scenario +): + """Test different sortable types""" + body = {"order": ["item_1", "item_2"]} + response = fake_response(ok=True, status_code=200, json_data=body) + client = dummy_client(response, method="put") + scenario = dummy_scenario(21) + order = ["item_1", "item_2"] + + # Test various sortable types + sortable_types = ["demand", "supply", "heat_network", "storage", "conversion"] + + for i, sortable_type in enumerate(sortable_types): + scenario_obj = dummy_scenario(21 + i) + result = UpdateSortablesRunner.run(client, scenario_obj, sortable_type, order) + + assert result.success is True + expected_url = f"/scenarios/{21 + i}/user_sortables/{sortable_type}" + assert client.calls[i][0] == expected_url + + +def test_update_sortables_subtype_none_explicitly( + dummy_client, fake_response, dummy_scenario +): + """Test with subtype explicitly set to None""" + body = {"order": ["item_1", "item_2"]} + response = fake_response(ok=True, status_code=200, json_data=body) + client = dummy_client(response, method="put") + scenario = dummy_scenario(22) + order = ["item_1", "item_2"] + + result = UpdateSortablesRunner.run(client, scenario, "demand", order, subtype=None) + + assert result.success is True + assert result.data == body + assert result.errors == [] + assert client.calls == [ + ("/scenarios/22/user_sortables/demand", {"json": {"order": order}}) + ] + + +def test_update_sortables_complex_order_data( + dummy_client, fake_response, dummy_scenario +): + """Test with complex order data including dictionaries""" + order = [ + {"id": 1, "name": "item_1"}, + {"id": 2, "name": "item_2"}, + {"id": 3, "name": "item_3"}, + ] + body = {"order": order} + response = fake_response(ok=True, status_code=200, json_data=body) + client = dummy_client(response, method="put") + scenario = dummy_scenario(23) + + result = UpdateSortablesRunner.run(client, scenario, "demand", order) + + assert result.success is True + assert result.data == body + assert result.errors == [] + assert client.calls == [ + ("/scenarios/23/user_sortables/demand", {"json": {"order": order}}) + ] From 2a317b228c4c9375a6b61e95682b6d469595cfb8 Mon Sep 17 00:00:00 2001 From: louispt1 <81332401+louispt1@users.noreply.github.com> Date: Wed, 13 Aug 2025 10:07:12 +0200 Subject: [PATCH 09/19] From excel bulk (#69) * Start from excel bulk * Improved styling for packer * Unpack for inputs and metadata first implementation no tests * Unpack for sortables and custom curves early commit before playing around * From dataset for sortables * Parse options from main sheet to enable repeating submodels across all scenarios listed in main * Added gqueries * WIP refactoring packer to suite new input format - partially working * New excel format working pre-clean up * Split packer into individual packs * Simplify query processing * Tests for query pack and custom curves pack * Fix tests for multi-index * Simplifying normalisation * Simplifying inputs pack * Improved tests * refining notebooks --------- Co-authored-by: Nora Schinkel --- Pipfile | 1 + Pipfile.lock | 19 +- .../advanced_scenario_example.ipynb | 0 examples/create_and_update_a_scenario.ipynb | 84 +- .../agriculture_electricity_curve.csv | 8760 ----------------- .../electric_vehicle_profile_5_curve.csv | 8760 ----------------- .../interconnector_8_price_curve.csv | 8760 ----------------- examples/excel_to_scenario.ipynb | 196 - examples/excel_to_scenarios.ipynb | 1474 +++ examples/exploring_a_scenario.ipynb | 23 +- examples/full_multi_scenario_flow.ipynb | 174 + examples/myc_notebook_for_tim.ipynb | 5 +- examples/scenario_to_excel.ipynb | 107 +- examples/serialization_deserialization.ipynb | 14 +- src/pyetm/models/__init__.py | 1 + src/pyetm/models/custom_curves.py | 57 +- src/pyetm/models/inputs.py | 1 - src/pyetm/models/output_curves.py | 5 +- .../models/packables/custom_curves_pack.py | 61 + src/pyetm/models/packables/inputs_pack.py | 176 + .../models/packables/output_curves_pack.py | 28 + src/pyetm/models/packables/packable.py | 215 + src/pyetm/models/packables/query_pack.py | 41 + src/pyetm/models/packables/sortable_pack.py | 54 + src/pyetm/models/scenario.py | 69 +- src/pyetm/models/scenario_packer.py | 501 +- src/pyetm/models/scenarios.py | 48 + src/pyetm/models/sortables.py | 41 +- src/pyetm/utils/excel.py | 177 +- .../packables/test_custom_curves_pack.py | 81 + tests/models/packables/test_gquery_pack.py | 85 + tests/models/packables/test_inputs_pack.py | 172 + .../packables/test_output_curves_pack.py | 43 + tests/models/packables/test_packable.py | 221 + tests/models/packables/test_query_pack.py | 63 + tests/models/packables/test_sortable_pack.py | 77 + tests/models/test_scenario_packer.py | 661 +- tests/models/test_sortables.py | 8 +- tests/utils/test_excel.py | 85 +- 39 files changed, 4401 insertions(+), 26947 deletions(-) rename examples/{ => advanced_examples}/advanced_scenario_example.ipynb (100%) delete mode 100644 examples/curve_examples/agriculture_electricity_curve.csv delete mode 100644 examples/curve_examples/electric_vehicle_profile_5_curve.csv delete mode 100644 examples/curve_examples/interconnector_8_price_curve.csv delete mode 100644 examples/excel_to_scenario.ipynb create mode 100644 examples/excel_to_scenarios.ipynb create mode 100644 examples/full_multi_scenario_flow.ipynb create mode 100644 src/pyetm/models/packables/custom_curves_pack.py create mode 100644 src/pyetm/models/packables/inputs_pack.py create mode 100644 src/pyetm/models/packables/output_curves_pack.py create mode 100644 src/pyetm/models/packables/packable.py create mode 100644 src/pyetm/models/packables/query_pack.py create mode 100644 src/pyetm/models/packables/sortable_pack.py create mode 100644 src/pyetm/models/scenarios.py create mode 100644 tests/models/packables/test_custom_curves_pack.py create mode 100644 tests/models/packables/test_gquery_pack.py create mode 100644 tests/models/packables/test_inputs_pack.py create mode 100644 tests/models/packables/test_output_curves_pack.py create mode 100644 tests/models/packables/test_packable.py create mode 100644 tests/models/packables/test_query_pack.py create mode 100644 tests/models/packables/test_sortable_pack.py diff --git a/Pipfile b/Pipfile index 13191b6..fd1d27a 100644 --- a/Pipfile +++ b/Pipfile @@ -12,6 +12,7 @@ pyyaml = "*" pydantic-settings = "*" pyetm = {file = ".", editable = true} xlsxwriter = "*" +openpyxl = "*" [dev-packages] pytest = "*" diff --git a/Pipfile.lock b/Pipfile.lock index 833e859..c2ab727 100644 --- a/Pipfile.lock +++ b/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "20f4dddea89cfeba955e7c97b967ea5d2ce533161caec9f36c422323c54deb69" + "sha256": "9c4a4dd242a69bb0fa72de6d543863742a6ac38a51db7cf772696af377dfa7bf" }, "pipfile-spec": 6, "requires": { @@ -137,6 +137,14 @@ "index": "pypi", "version": "==0.9.9" }, + "et-xmlfile": { + "hashes": [ + "sha256:7a91720bc756843502c3b7504c77b8fe44217c85c537d85037f0f536151b2caa", + "sha256:dab3f4764309081ce75662649be815c4c9081e88f0837825f90fd28317d4da54" + ], + "markers": "python_version >= '3.8'", + "version": "==2.0.0" + }, "idna": { "hashes": [ "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", @@ -202,6 +210,15 @@ "markers": "python_version >= '3.11'", "version": "==2.3.1" }, + "openpyxl": { + "hashes": [ + "sha256:5282c12b107bffeef825f4617dc029afaf41d0ea60823bbb665ef3079dc79de2", + "sha256:cf0e3cf56142039133628b5acffe8ef0c12bc902d2aadd3e0fe5878dc08d1050" + ], + "index": "pypi", + "markers": "python_version >= '3.8'", + "version": "==3.1.5" + }, "pandas": { "hashes": [ "sha256:034abd6f3db8b9880aaee98f4f5d4dbec7c4829938463ec046517220b2f8574e", diff --git a/examples/advanced_scenario_example.ipynb b/examples/advanced_examples/advanced_scenario_example.ipynb similarity index 100% rename from examples/advanced_scenario_example.ipynb rename to examples/advanced_examples/advanced_scenario_example.ipynb diff --git a/examples/create_and_update_a_scenario.ipynb b/examples/create_and_update_a_scenario.ipynb index 380ce50..0fa51bd 100644 --- a/examples/create_and_update_a_scenario.ipynb +++ b/examples/create_and_update_a_scenario.ipynb @@ -20,21 +20,10 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "id": "3ada4b30", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Environment setup complete\n", - " Using ETM API at https://beta.engine.energytransitionmodel.com/api/v3\n", - " Token loaded? True\n", - "API connection ready\n" - ] - } - ], + "outputs": [], "source": [ "from example_helpers import setup_notebook\n", "from pyetm.models import Scenario\n", @@ -52,7 +41,7 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "id": "4770e6a9", "metadata": {}, "outputs": [], @@ -77,19 +66,10 @@ }, { "cell_type": "code", - "execution_count": 6, + "execution_count": null, "id": "5a1549ac", "metadata": {}, - "outputs": [ - { - "ename": "ScenarioError", - "evalue": "Could not update user values: {'external_coupling_industry_chemical_other_burner_crude_oil_share': ['user: Input should be a valid number, unable to parse string as a number']}", - "output_type": "error", - "traceback": [ - "\u001b[31mScenarioError\u001b[39m\u001b[31m:\u001b[39m Could not update user values: {'external_coupling_industry_chemical_other_burner_crude_oil_share': ['user: Input should be a valid number, unable to parse string as a number']}\n" - ] - } - ], + "outputs": [], "source": [ "scenario.update_user_values({\n", " \"co_firing_biocoal_share\": 80.0,\n", @@ -107,31 +87,10 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "id": "7fc4dc21", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Area: nl2019\n", - "End year: 2050\n", - "Start year: 2019\n", - "Version: beta\n", - "Modified inputs: 1\n", - "First input: co_firing_biocoal_share = 80.0\n" - ] - }, - { - "ename": "IndexError", - "evalue": "list index out of range", - "output_type": "error", - "traceback": [ - "\u001b[31mIndexError\u001b[39m\u001b[31m:\u001b[39m list index out of range\n" - ] - } - ], + "outputs": [], "source": [ "print(f\"Area: {scenario.area_code}\")\n", "print(f\"End year: {scenario.end_year}\")\n", @@ -153,18 +112,10 @@ }, { "cell_type": "code", - "execution_count": 7, + "execution_count": null, "id": "c6a65f6a", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "False\n" - ] - } - ], + "outputs": [], "source": [ "scenario.update_metadata(\n", " private= True,\n", @@ -195,19 +146,10 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "id": "98ab2f5c", "metadata": {}, - "outputs": [ - { - "ename": "AttributeError", - "evalue": "'Scenario' object has no attribute 'remove_inputs'", - "output_type": "error", - "traceback": [ - "\u001b[31mAttributeError\u001b[39m\u001b[31m:\u001b[39m 'Scenario' object has no attribute 'remove_inputs'\n" - ] - } - ], + "outputs": [], "source": [ "scenario.remove_user_values([\"co_firing_biocoal_share\"])\n", "user_vals = scenario.user_values()\n", @@ -217,7 +159,7 @@ ], "metadata": { "kernelspec": { - "display_name": "pyetm-FWBOHxp3", + "display_name": "pyetm-qKH2ozgc", "language": "python", "name": "python3" }, @@ -231,7 +173,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.11" + "version": "3.12.9" } }, "nbformat": 4, diff --git a/examples/curve_examples/agriculture_electricity_curve.csv b/examples/curve_examples/agriculture_electricity_curve.csv deleted file mode 100644 index 8c5c7b9..0000000 --- a/examples/curve_examples/agriculture_electricity_curve.csv +++ /dev/null @@ -1,8760 +0,0 @@ -3.083099492094933e-08 -3.2365569328779384e-08 -3.1947049035734825e-08 -3.2365569328779384e-08 -3.278408962182394e-08 -3.292359638617213e-08 -3.3063103150520315e-08 -3.390014373660944e-08 -3.390014373660944e-08 -3.2365569328779384e-08 -3.348162344356488e-08 -3.362113020791307e-08 -3.348162344356488e-08 -3.320260991486851e-08 -3.278408962182394e-08 -3.348162344356488e-08 -3.417915726530581e-08 -3.613225196618043e-08 -3.5713731673135874e-08 -3.557422490878769e-08 -3.5713731673135874e-08 -3.627175873052862e-08 -3.5713731673135874e-08 -3.557422490878769e-08 -3.180754227138664e-08 -3.2644582857475756e-08 -3.22260625644312e-08 -3.22260625644312e-08 -3.250507609312757e-08 -3.3342116679216694e-08 -3.724830608096593e-08 -3.027296786355658e-08 -4.199153606880429e-08 -4.478167135576803e-08 -4.631624576359808e-08 -4.687427282099083e-08 -4.366561724098254e-08 -4.492117812011622e-08 -4.492117812011622e-08 -4.310759018358978e-08 -3.8085346667055053e-08 -3.027296786355658e-08 -2.6227271697459155e-08 -2.5808751404414597e-08 -2.4971710818325472e-08 -2.2739602588754482e-08 -2.0367987594835303e-08 -3.487669108704675e-08 -3.2644582857475756e-08 -3.3063103150520315e-08 -3.22260625644312e-08 -3.1947049035734825e-08 -3.292359638617213e-08 -3.417915726530581e-08 -3.892238725314418e-08 -3.22260625644312e-08 -4.575821870620534e-08 -4.840884722882089e-08 -4.93853945792582e-08 -5.008292840099913e-08 -4.6595259292294455e-08 -4.8548353993169076e-08 -4.812983370012452e-08 -4.5897725470553524e-08 -3.961992107488511e-08 -3.083099492094933e-08 -2.6645791990503717e-08 -2.5808751404414597e-08 -2.4413683760932724e-08 -2.2600095824406296e-08 -2.0367987594835303e-08 -3.5295211380091315e-08 -3.2644582857475756e-08 -3.3342116679216694e-08 -3.250507609312757e-08 -3.292359638617213e-08 -3.4039650500957626e-08 -3.5992745201832246e-08 -4.115449548271517e-08 -3.320260991486851e-08 -4.729279311403539e-08 -5.008292840099913e-08 -5.0919968987088255e-08 -5.175700957317738e-08 -4.910638105056182e-08 -5.0919968987088255e-08 -5.147799604448101e-08 -4.966440810795457e-08 -4.394463076967891e-08 -3.5016197851394936e-08 -3.0970501685297515e-08 -2.9993954334860204e-08 -2.8877900220074708e-08 -2.6924805519200093e-08 -2.385565670353998e-08 -4.031745489662604e-08 -3.6550772259225e-08 -3.696929255226956e-08 -3.627175873052862e-08 -3.613225196618043e-08 -3.5713731673135874e-08 -3.627175873052862e-08 -4.045696166097423e-08 -3.069148815660114e-08 -4.1852029304456096e-08 -4.408413753402709e-08 -4.492117812011622e-08 -4.520019164881259e-08 -4.213104283315248e-08 -4.2689069890545226e-08 -4.1712522540107916e-08 -3.892238725314418e-08 -3.417915726530581e-08 -2.9017406984422894e-08 -2.5250724347021848e-08 -2.4274176996584538e-08 -2.3297629646147227e-08 -2.1902562002665358e-08 -2.008897406613893e-08 -3.459767755835038e-08 -3.208655580008301e-08 -3.2644582857475756e-08 -3.152852874269026e-08 -3.152852874269026e-08 -3.1947049035734825e-08 -3.2365569328779384e-08 -3.278408962182394e-08 -3.54347181444395e-08 -3.948041431053692e-08 -4.1712522540107916e-08 -4.408413753402709e-08 -4.478167135576803e-08 -4.3526110476634344e-08 -4.2410056361848854e-08 -4.213104283315248e-08 -4.101498871836698e-08 -4.0735975189670606e-08 -3.9759427839233295e-08 -3.822485343140324e-08 -3.7387812845314116e-08 -3.682978578792137e-08 -3.5713731673135874e-08 -3.417915726530581e-08 -3.362113020791307e-08 -3.124951521399389e-08 -3.1947049035734825e-08 -3.069148815660114e-08 -3.0970501685297515e-08 -3.11100084496457e-08 -3.152852874269026e-08 -3.1389021978342073e-08 -3.208655580008301e-08 -3.208655580008301e-08 -3.1947049035734825e-08 -3.320260991486851e-08 -3.4039650500957626e-08 -3.417915726530581e-08 -3.4318664029654005e-08 -3.417915726530581e-08 -3.417915726530581e-08 -3.417915726530581e-08 -3.6550772259225e-08 -3.627175873052862e-08 -3.557422490878769e-08 -3.515570461574312e-08 -3.4737184322698563e-08 -3.390014373660944e-08 -3.3342116679216694e-08 -3.180754227138664e-08 -3.250507609312757e-08 -3.124951521399389e-08 -3.180754227138664e-08 -3.208655580008301e-08 -3.376063697226125e-08 -3.948041431053692e-08 -3.278408962182394e-08 -4.631624576359808e-08 -4.9245887814910014e-08 -5.036194192969551e-08 -5.1338489280132814e-08 -4.785082017142814e-08 -4.966440810795457e-08 -4.9943421636650945e-08 -4.771131340707996e-08 -4.0735975189670606e-08 -3.1389021978342073e-08 -2.7482832576592838e-08 -2.6645791990503717e-08 -2.5250724347021848e-08 -2.3018616117450855e-08 -2.008897406613893e-08 -3.515570461574312e-08 -3.250507609312757e-08 -3.348162344356488e-08 -3.250507609312757e-08 -3.278408962182394e-08 -3.3063103150520315e-08 -3.459767755835038e-08 -3.9759427839233295e-08 -3.348162344356488e-08 -4.7432299878383586e-08 -5.064095545839188e-08 -5.203602310187375e-08 -5.273355692361469e-08 -4.896687428621364e-08 -5.064095545839188e-08 -5.064095545839188e-08 -4.82693404644727e-08 -4.1433509011411543e-08 -3.1947049035734825e-08 -2.7482832576592838e-08 -2.6785298754851907e-08 -2.5808751404414597e-08 -2.3297629646147227e-08 -2.0228480830487117e-08 -3.4318664029654005e-08 -3.22260625644312e-08 -3.2644582857475756e-08 -3.1668035507038446e-08 -3.1668035507038446e-08 -3.2644582857475756e-08 -3.4039650500957626e-08 -3.961992107488511e-08 -3.376063697226125e-08 -4.799032693577633e-08 -5.0919968987088255e-08 -5.217552986622194e-08 -5.315207721665925e-08 -4.9524901343606386e-08 -5.1338489280132814e-08 -5.119898251578463e-08 -4.896687428621364e-08 -4.213104283315248e-08 -3.2644582857475756e-08 -2.845937992703015e-08 -2.7482832576592838e-08 -2.5948258168762783e-08 -2.413467023223635e-08 -2.14840417096208e-08 -3.710879931661774e-08 -3.459767755835038e-08 -3.487669108704675e-08 -3.376063697226125e-08 -3.417915726530581e-08 -3.487669108704675e-08 -3.6550772259225e-08 -4.2549563126197034e-08 -3.515570461574312e-08 -4.980391487230276e-08 -5.273355692361469e-08 -5.3849611038400187e-08 -5.48261583888375e-08 -5.147799604448101e-08 -5.343109074535562e-08 -5.3989117802748366e-08 -5.1338489280132814e-08 -4.464216459141985e-08 -3.515570461574312e-08 -3.11100084496457e-08 -2.9993954334860204e-08 -2.873839345572652e-08 -2.650628522615553e-08 -2.315812288179904e-08 -3.948041431053692e-08 -3.710879931661774e-08 -3.7666826374010495e-08 -3.682978578792137e-08 -3.6690279023573184e-08 -3.6550772259225e-08 -3.7387812845314116e-08 -4.29680834192416e-08 -3.459767755835038e-08 -4.8548353993169076e-08 -5.161750280882919e-08 -5.2873063687962876e-08 -5.315207721665925e-08 -4.93853945792582e-08 -5.008292840099913e-08 -4.896687428621364e-08 -4.50606848844644e-08 -3.86433737244478e-08 -3.180754227138664e-08 -2.7482832576592838e-08 -2.650628522615553e-08 -2.5390231111370035e-08 -2.3716149939191793e-08 -2.14840417096208e-08 -3.724830608096593e-08 -3.4737184322698563e-08 -3.5016197851394936e-08 -3.376063697226125e-08 -3.4039650500957626e-08 -3.417915726530581e-08 -3.459767755835038e-08 -3.54347181444395e-08 -3.8364360195751426e-08 -4.366561724098254e-08 -4.687427282099083e-08 -4.93853945792582e-08 -4.9943421636650945e-08 -4.785082017142814e-08 -4.673476605664265e-08 -4.603723223490171e-08 -4.50606848844644e-08 -4.408413753402709e-08 -4.2828576654893406e-08 -4.087548195401879e-08 -4.045696166097423e-08 -3.989893460358149e-08 -3.86433737244478e-08 -3.7666826374010495e-08 -3.710879931661774e-08 -3.515570461574312e-08 -3.5713731673135874e-08 -3.445817079400219e-08 -3.445817079400219e-08 -3.445817079400219e-08 -3.5016197851394936e-08 -3.4318664029654005e-08 -3.487669108704675e-08 -3.487669108704675e-08 -3.5016197851394936e-08 -3.613225196618043e-08 -3.682978578792137e-08 -3.710879931661774e-08 -3.724830608096593e-08 -3.710879931661774e-08 -3.627175873052862e-08 -3.585323843748406e-08 -3.75273196096623e-08 -3.696929255226956e-08 -3.627175873052862e-08 -3.5713731673135874e-08 -3.487669108704675e-08 -3.390014373660944e-08 -3.362113020791307e-08 -3.208655580008301e-08 -3.292359638617213e-08 -3.152852874269026e-08 -3.208655580008301e-08 -3.292359638617213e-08 -3.459767755835038e-08 -4.0735975189670606e-08 -3.445817079400219e-08 -4.896687428621364e-08 -5.1896516337525566e-08 -5.343109074535562e-08 -5.440763809579293e-08 -5.078046222274007e-08 -5.245454339491831e-08 -5.273355692361469e-08 -5.0222435165347324e-08 -4.2549563126197034e-08 -3.250507609312757e-08 -2.8877900220074708e-08 -2.804085963398559e-08 -2.6785298754851907e-08 -2.4413683760932724e-08 -2.0926014652228048e-08 -3.627175873052862e-08 -3.4039650500957626e-08 -3.54347181444395e-08 -3.487669108704675e-08 -3.5016197851394936e-08 -3.5295211380091315e-08 -3.710879931661774e-08 -4.29680834192416e-08 -3.557422490878769e-08 -5.036194192969551e-08 -5.343109074535562e-08 -5.48261583888375e-08 -5.5663198974926615e-08 -5.175700957317738e-08 -5.3849611038400187e-08 -5.3710104274051994e-08 -5.0919968987088255e-08 -4.310759018358978e-08 -3.3342116679216694e-08 -2.9017406984422894e-08 -2.8319873162681962e-08 -2.706431228354828e-08 -2.4274176996584538e-08 -2.0647001123531675e-08 -3.5016197851394936e-08 -3.278408962182394e-08 -3.3342116679216694e-08 -3.22260625644312e-08 -3.250507609312757e-08 -3.292359638617213e-08 -3.459767755835038e-08 -4.045696166097423e-08 -3.459767755835038e-08 -4.896687428621364e-08 -5.1896516337525566e-08 -5.301257045231106e-08 -5.4268131331444745e-08 -5.0222435165347324e-08 -5.1896516337525566e-08 -5.2315036630570125e-08 -5.0222435165347324e-08 -4.324709694793797e-08 -3.376063697226125e-08 -2.9575434041815645e-08 -2.8598886691378335e-08 -2.6924805519200093e-08 -2.46926972896291e-08 -2.14840417096208e-08 -3.682978578792137e-08 -3.459767755835038e-08 -3.4737184322698563e-08 -3.362113020791307e-08 -3.390014373660944e-08 -3.417915726530581e-08 -3.5713731673135874e-08 -4.227054959750066e-08 -3.585323843748406e-08 -5.036194192969551e-08 -5.343109074535562e-08 -5.4686651624489304e-08 -5.5663198974926615e-08 -5.1896516337525566e-08 -5.3570597509703814e-08 -5.3570597509703814e-08 -5.078046222274007e-08 -4.3386603712286164e-08 -3.390014373660944e-08 -3.027296786355658e-08 -2.943592727746746e-08 -2.8180366398333776e-08 -2.552973787571822e-08 -2.1902562002665358e-08 -3.696929255226956e-08 -3.487669108704675e-08 -3.54347181444395e-08 -3.459767755835038e-08 -3.487669108704675e-08 -3.515570461574312e-08 -3.627175873052862e-08 -4.2549563126197034e-08 -3.515570461574312e-08 -4.910638105056182e-08 -5.203602310187375e-08 -5.343109074535562e-08 -5.3849611038400187e-08 -5.008292840099913e-08 -5.064095545839188e-08 -4.966440810795457e-08 -4.5897725470553524e-08 -3.892238725314418e-08 -3.1947049035734825e-08 -2.7901352869637404e-08 -2.6785298754851907e-08 -2.552973787571822e-08 -2.385565670353998e-08 -2.1623548473968986e-08 -3.7387812845314116e-08 -3.459767755835038e-08 -3.459767755835038e-08 -3.348162344356488e-08 -3.3342116679216694e-08 -3.320260991486851e-08 -3.376063697226125e-08 -3.487669108704675e-08 -3.850386696009961e-08 -4.3805124005330716e-08 -4.701377958533902e-08 -4.966440810795457e-08 -5.008292840099913e-08 -4.82693404644727e-08 -4.701377958533902e-08 -4.61767389992499e-08 -4.520019164881259e-08 -4.366561724098254e-08 -4.2549563126197034e-08 -4.059646842532242e-08 -4.045696166097423e-08 -3.948041431053692e-08 -3.86433737244478e-08 -3.7666826374010495e-08 -3.6690279023573184e-08 -3.515570461574312e-08 -3.557422490878769e-08 -3.417915726530581e-08 -3.4039650500957626e-08 -3.4039650500957626e-08 -3.4737184322698563e-08 -3.4039650500957626e-08 -3.459767755835038e-08 -3.4737184322698563e-08 -3.487669108704675e-08 -3.6411265494876805e-08 -3.7666826374010495e-08 -3.8782880488795985e-08 -3.906189401749236e-08 -3.920140078184055e-08 -3.822485343140324e-08 -3.7387812845314116e-08 -3.8364360195751426e-08 -3.7666826374010495e-08 -3.6690279023573184e-08 -3.585323843748406e-08 -3.5295211380091315e-08 -3.4039650500957626e-08 -3.362113020791307e-08 -3.1947049035734825e-08 -3.278408962182394e-08 -3.1947049035734825e-08 -3.180754227138664e-08 -3.278408962182394e-08 -3.4318664029654005e-08 -4.059646842532242e-08 -3.417915726530581e-08 -4.868786075751727e-08 -5.175700957317738e-08 -5.3291583981007435e-08 -5.4268131331444745e-08 -5.0501448694043697e-08 -5.245454339491831e-08 -5.203602310187375e-08 -4.966440810795457e-08 -4.213104283315248e-08 -3.22260625644312e-08 -2.9156913748771087e-08 -2.8319873162681962e-08 -2.6785298754851907e-08 -2.413467023223635e-08 -2.0647001123531675e-08 -3.54347181444395e-08 -3.320260991486851e-08 -3.4039650500957626e-08 -3.376063697226125e-08 -3.348162344356488e-08 -3.390014373660944e-08 -3.5713731673135874e-08 -4.213104283315248e-08 -3.557422490878769e-08 -5.036194192969551e-08 -5.3570597509703814e-08 -5.510517191753387e-08 -5.580270573927481e-08 -5.217552986622194e-08 -5.4268131331444745e-08 -5.412862456709656e-08 -5.147799604448101e-08 -4.366561724098254e-08 -3.4318664029654005e-08 -3.069148815660114e-08 -3.027296786355658e-08 -2.873839345572652e-08 -2.5390231111370035e-08 -2.1344534945272613e-08 -3.5992745201832246e-08 -3.4039650500957626e-08 -3.445817079400219e-08 -3.348162344356488e-08 -3.376063697226125e-08 -3.390014373660944e-08 -3.5016197851394936e-08 -4.087548195401879e-08 -3.487669108704675e-08 -4.9245887814910014e-08 -5.217552986622194e-08 -5.3849611038400187e-08 -5.4686651624489304e-08 -5.0222435165347324e-08 -5.1896516337525566e-08 -5.245454339491831e-08 -4.980391487230276e-08 -4.2689069890545226e-08 -3.3342116679216694e-08 -2.985444757051202e-08 -2.8877900220074708e-08 -2.6924805519200093e-08 -2.4274176996584538e-08 -2.050749435918349e-08 -3.4318664029654005e-08 -3.208655580008301e-08 -3.250507609312757e-08 -3.1389021978342073e-08 -3.1668035507038446e-08 -3.1947049035734825e-08 -3.3342116679216694e-08 -3.989893460358149e-08 -3.445817079400219e-08 -4.82693404644727e-08 -5.147799604448101e-08 -5.2873063687962876e-08 -5.3710104274051994e-08 -5.008292840099913e-08 -5.147799604448101e-08 -5.1338489280132814e-08 -4.896687428621364e-08 -4.157301577575972e-08 -3.2644582857475756e-08 -3.013346109920839e-08 -2.9575434041815645e-08 -2.7901352869637404e-08 -2.5111217582673662e-08 -2.1344534945272613e-08 -3.4737184322698563e-08 -3.292359638617213e-08 -3.3063103150520315e-08 -3.2365569328779384e-08 -3.250507609312757e-08 -3.250507609312757e-08 -3.390014373660944e-08 -4.045696166097423e-08 -3.390014373660944e-08 -4.7432299878383586e-08 -5.008292840099913e-08 -5.147799604448101e-08 -5.203602310187375e-08 -4.812983370012452e-08 -4.868786075751727e-08 -4.82693404644727e-08 -4.436315106272346e-08 -3.7387812845314116e-08 -3.0970501685297515e-08 -2.7482832576592838e-08 -2.6227271697459155e-08 -2.4832204053977286e-08 -2.287910935310267e-08 -2.050749435918349e-08 -3.5016197851394936e-08 -3.250507609312757e-08 -3.348162344356488e-08 -3.292359638617213e-08 -3.278408962182394e-08 -3.22260625644312e-08 -3.3063103150520315e-08 -3.4737184322698563e-08 -3.794583990270687e-08 -4.324709694793797e-08 -4.7432299878383586e-08 -5.0501448694043697e-08 -5.0919968987088255e-08 -4.896687428621364e-08 -4.701377958533902e-08 -4.6455752527946275e-08 -4.492117812011622e-08 -4.324709694793797e-08 -4.1433509011411543e-08 -3.961992107488511e-08 -3.892238725314418e-08 -3.7666826374010495e-08 -3.6550772259225e-08 -3.5713731673135874e-08 -3.445817079400219e-08 -3.3063103150520315e-08 -3.362113020791307e-08 -3.320260991486851e-08 -3.22260625644312e-08 -3.152852874269026e-08 -3.180754227138664e-08 -3.1947049035734825e-08 -3.250507609312757e-08 -3.2365569328779384e-08 -3.320260991486851e-08 -3.4737184322698563e-08 -3.6550772259225e-08 -3.7666826374010495e-08 -3.7666826374010495e-08 -3.7806333138358674e-08 -3.724830608096593e-08 -3.682978578792137e-08 -3.8085346667055053e-08 -3.7806333138358674e-08 -3.6690279023573184e-08 -3.585323843748406e-08 -3.557422490878769e-08 -3.445817079400219e-08 -3.362113020791307e-08 -3.180754227138664e-08 -3.250507609312757e-08 -3.1668035507038446e-08 -3.1668035507038446e-08 -3.2365569328779384e-08 -3.362113020791307e-08 -4.003844136792967e-08 -3.390014373660944e-08 -4.82693404644727e-08 -5.119898251578463e-08 -5.2594050159266504e-08 -5.343109074535562e-08 -4.980391487230276e-08 -5.1896516337525566e-08 -5.1338489280132814e-08 -4.868786075751727e-08 -4.1433509011411543e-08 -3.22260625644312e-08 -2.9296420513119273e-08 -2.8319873162681962e-08 -2.6645791990503717e-08 -2.3576643174843603e-08 -2.0367987594835303e-08 -3.445817079400219e-08 -3.2365569328779384e-08 -3.2644582857475756e-08 -3.180754227138664e-08 -3.180754227138664e-08 -3.2365569328779384e-08 -3.417915726530581e-08 -4.087548195401879e-08 -3.54347181444395e-08 -4.93853945792582e-08 -5.245454339491831e-08 -5.412862456709656e-08 -5.454714486014112e-08 -5.0919968987088255e-08 -5.2873063687962876e-08 -5.2873063687962876e-08 -5.0222435165347324e-08 -4.2689069890545226e-08 -3.3342116679216694e-08 -3.0551981392252956e-08 -2.985444757051202e-08 -2.873839345572652e-08 -2.552973787571822e-08 -2.1623548473968986e-08 -3.5992745201832246e-08 -3.417915726530581e-08 -3.445817079400219e-08 -3.348162344356488e-08 -3.376063697226125e-08 -3.4039650500957626e-08 -3.4737184322698563e-08 -4.087548195401879e-08 -3.487669108704675e-08 -4.882736752186545e-08 -5.1896516337525566e-08 -5.3710104274051994e-08 -5.440763809579293e-08 -5.0222435165347324e-08 -5.1896516337525566e-08 -5.175700957317738e-08 -4.93853945792582e-08 -4.199153606880429e-08 -3.250507609312757e-08 -2.985444757051202e-08 -2.9017406984422894e-08 -2.6924805519200093e-08 -2.413467023223635e-08 -2.050749435918349e-08 -3.417915726530581e-08 -3.208655580008301e-08 -3.250507609312757e-08 -3.180754227138664e-08 -3.1947049035734825e-08 -3.208655580008301e-08 -3.348162344356488e-08 -3.9340907546188736e-08 -3.376063697226125e-08 -4.701377958533902e-08 -5.0222435165347324e-08 -5.175700957317738e-08 -5.273355692361469e-08 -4.93853945792582e-08 -5.0919968987088255e-08 -5.105947575143644e-08 -4.8548353993169076e-08 -4.101498871836698e-08 -3.1947049035734825e-08 -3.013346109920839e-08 -2.9296420513119273e-08 -2.7901352869637404e-08 -2.4971710818325472e-08 -2.106552141657624e-08 -3.417915726530581e-08 -3.278408962182394e-08 -3.320260991486851e-08 -3.320260991486851e-08 -3.3342116679216694e-08 -3.320260991486851e-08 -3.4737184322698563e-08 -4.059646842532242e-08 -3.362113020791307e-08 -4.673476605664265e-08 -4.966440810795457e-08 -5.0501448694043697e-08 -5.1338489280132814e-08 -4.785082017142814e-08 -4.8548353993169076e-08 -4.812983370012452e-08 -4.4502657827071654e-08 -3.75273196096623e-08 -3.083099492094933e-08 -2.7622339340941025e-08 -2.6366778461807345e-08 -2.5111217582673662e-08 -2.315812288179904e-08 -2.106552141657624e-08 -3.613225196618043e-08 -3.376063697226125e-08 -3.54347181444395e-08 -3.5016197851394936e-08 -3.4318664029654005e-08 -3.362113020791307e-08 -3.4318664029654005e-08 -3.585323843748406e-08 -3.86433737244478e-08 -4.366561724098254e-08 -4.882736752186545e-08 -5.1338489280132814e-08 -5.175700957317738e-08 -4.9943421636650945e-08 -4.799032693577633e-08 -4.7153286349687207e-08 -4.533969841316077e-08 -4.3386603712286164e-08 -4.1712522540107916e-08 -4.059646842532242e-08 -3.961992107488511e-08 -3.794583990270687e-08 -3.627175873052862e-08 -3.54347181444395e-08 -3.4318664029654005e-08 -3.3063103150520315e-08 -3.4318664029654005e-08 -3.4039650500957626e-08 -3.320260991486851e-08 -3.1947049035734825e-08 -3.22260625644312e-08 -3.22260625644312e-08 -3.278408962182394e-08 -3.180754227138664e-08 -3.278408962182394e-08 -3.445817079400219e-08 -3.5713731673135874e-08 -3.6690279023573184e-08 -3.710879931661774e-08 -3.696929255226956e-08 -3.682978578792137e-08 -3.627175873052862e-08 -3.7806333138358674e-08 -3.8085346667055053e-08 -3.6411265494876805e-08 -3.5713731673135874e-08 -3.5295211380091315e-08 -3.417915726530581e-08 -3.3342116679216694e-08 -3.1668035507038446e-08 -3.278408962182394e-08 -3.1668035507038446e-08 -3.180754227138664e-08 -3.250507609312757e-08 -3.4039650500957626e-08 -4.031745489662604e-08 -3.4039650500957626e-08 -4.729279311403539e-08 -5.036194192969551e-08 -5.217552986622194e-08 -5.343109074535562e-08 -4.9943421636650945e-08 -5.161750280882919e-08 -5.147799604448101e-08 -4.8548353993169076e-08 -4.1433509011411543e-08 -3.208655580008301e-08 -2.9714940806163832e-08 -2.873839345572652e-08 -2.6924805519200093e-08 -2.3995163467888165e-08 -2.078650788787986e-08 -3.4737184322698563e-08 -3.278408962182394e-08 -3.320260991486851e-08 -3.2365569328779384e-08 -3.2644582857475756e-08 -3.320260991486851e-08 -3.4737184322698563e-08 -4.087548195401879e-08 -3.515570461574312e-08 -4.8548353993169076e-08 -5.175700957317738e-08 -5.315207721665925e-08 -5.412862456709656e-08 -5.036194192969551e-08 -5.175700957317738e-08 -5.147799604448101e-08 -4.882736752186545e-08 -4.157301577575972e-08 -3.1947049035734825e-08 -2.985444757051202e-08 -2.9296420513119273e-08 -2.845937992703015e-08 -2.5669244640066407e-08 -2.218157553136173e-08 -3.682978578792137e-08 -3.4737184322698563e-08 -3.5295211380091315e-08 -3.4318664029654005e-08 -3.417915726530581e-08 -3.390014373660944e-08 -3.487669108704675e-08 -4.087548195401879e-08 -3.4737184322698563e-08 -4.785082017142814e-08 -5.105947575143644e-08 -5.245454339491831e-08 -5.3570597509703814e-08 -4.9524901343606386e-08 -5.078046222274007e-08 -5.0501448694043697e-08 -4.840884722882089e-08 -4.101498871836698e-08 -3.1389021978342073e-08 -2.943592727746746e-08 -2.8598886691378335e-08 -2.6785298754851907e-08 -2.3995163467888165e-08 -2.0926014652228048e-08 -3.5016197851394936e-08 -3.292359638617213e-08 -3.348162344356488e-08 -3.3063103150520315e-08 -3.3063103150520315e-08 -3.3342116679216694e-08 -3.487669108704675e-08 -4.059646842532242e-08 -3.4318664029654005e-08 -4.729279311403539e-08 -5.0919968987088255e-08 -5.2315036630570125e-08 -5.301257045231106e-08 -4.9524901343606386e-08 -5.105947575143644e-08 -5.1338489280132814e-08 -4.868786075751727e-08 -4.129400224706335e-08 -3.152852874269026e-08 -2.9714940806163832e-08 -2.8877900220074708e-08 -2.7482832576592838e-08 -2.4832204053977286e-08 -2.14840417096208e-08 -3.5713731673135874e-08 -3.459767755835038e-08 -3.5295211380091315e-08 -3.5016197851394936e-08 -3.515570461574312e-08 -3.515570461574312e-08 -3.6411265494876805e-08 -4.199153606880429e-08 -3.4318664029654005e-08 -4.701377958533902e-08 -4.9943421636650945e-08 -5.0919968987088255e-08 -5.161750280882919e-08 -4.799032693577633e-08 -4.840884722882089e-08 -4.771131340707996e-08 -4.422364429837528e-08 -3.7387812845314116e-08 -2.9993954334860204e-08 -2.706431228354828e-08 -2.5808751404414597e-08 -2.4832204053977286e-08 -2.3018616117450855e-08 -2.106552141657624e-08 -3.627175873052862e-08 -3.417915726530581e-08 -3.487669108704675e-08 -3.417915726530581e-08 -3.390014373660944e-08 -3.4318664029654005e-08 -3.459767755835038e-08 -3.5713731673135874e-08 -3.892238725314418e-08 -4.3805124005330716e-08 -4.910638105056182e-08 -5.2594050159266504e-08 -5.3291583981007435e-08 -5.161750280882919e-08 -4.966440810795457e-08 -4.771131340707996e-08 -4.5897725470553524e-08 -4.366561724098254e-08 -4.213104283315248e-08 -4.1852029304456096e-08 -4.087548195401879e-08 -3.948041431053692e-08 -3.8085346667055053e-08 -3.696929255226956e-08 -3.5713731673135874e-08 -3.445817079400219e-08 -3.613225196618043e-08 -3.5016197851394936e-08 -3.4737184322698563e-08 -3.376063697226125e-08 -3.4039650500957626e-08 -3.320260991486851e-08 -3.3342116679216694e-08 -3.1668035507038446e-08 -3.292359638617213e-08 -3.459767755835038e-08 -3.6411265494876805e-08 -3.710879931661774e-08 -3.7666826374010495e-08 -3.724830608096593e-08 -3.724830608096593e-08 -3.627175873052862e-08 -3.7387812845314116e-08 -3.850386696009961e-08 -3.682978578792137e-08 -3.627175873052862e-08 -3.515570461574312e-08 -3.445817079400219e-08 -3.320260991486851e-08 -3.1947049035734825e-08 -3.3063103150520315e-08 -3.208655580008301e-08 -3.1668035507038446e-08 -3.1947049035734825e-08 -3.376063697226125e-08 -4.003844136792967e-08 -3.348162344356488e-08 -4.5897725470553524e-08 -4.93853945792582e-08 -5.147799604448101e-08 -5.2594050159266504e-08 -4.93853945792582e-08 -5.105947575143644e-08 -5.105947575143644e-08 -4.868786075751727e-08 -4.115449548271517e-08 -3.083099492094933e-08 -2.9575434041815645e-08 -2.8877900220074708e-08 -2.7482832576592838e-08 -2.413467023223635e-08 -2.0926014652228048e-08 -3.5713731673135874e-08 -3.348162344356488e-08 -3.4039650500957626e-08 -3.292359638617213e-08 -3.278408962182394e-08 -3.3063103150520315e-08 -3.4318664029654005e-08 -4.031745489662604e-08 -3.4039650500957626e-08 -4.729279311403539e-08 -5.078046222274007e-08 -5.217552986622194e-08 -5.301257045231106e-08 -4.910638105056182e-08 -5.064095545839188e-08 -5.008292840099913e-08 -4.7571806642731765e-08 -4.031745489662604e-08 -3.041247462790477e-08 -2.9017406984422894e-08 -2.8598886691378335e-08 -2.7901352869637404e-08 -2.5111217582673662e-08 -2.1344534945272613e-08 -3.5295211380091315e-08 -3.3342116679216694e-08 -3.376063697226125e-08 -3.292359638617213e-08 -3.2644582857475756e-08 -3.2644582857475756e-08 -3.376063697226125e-08 -3.9759427839233295e-08 -3.376063697226125e-08 -4.6455752527946275e-08 -4.9943421636650945e-08 -5.147799604448101e-08 -5.273355692361469e-08 -4.8548353993169076e-08 -4.9943421636650945e-08 -4.980391487230276e-08 -4.7571806642731765e-08 -4.003844136792967e-08 -2.9993954334860204e-08 -2.9017406984422894e-08 -2.845937992703015e-08 -2.706431228354828e-08 -2.4413683760932724e-08 -2.078650788787986e-08 -3.4737184322698563e-08 -3.250507609312757e-08 -3.348162344356488e-08 -3.278408962182394e-08 -3.250507609312757e-08 -3.292359638617213e-08 -3.4318664029654005e-08 -4.003844136792967e-08 -3.348162344356488e-08 -4.6455752527946275e-08 -5.0222435165347324e-08 -5.147799604448101e-08 -5.217552986622194e-08 -4.868786075751727e-08 -5.036194192969551e-08 -5.036194192969551e-08 -4.785082017142814e-08 -4.045696166097423e-08 -3.041247462790477e-08 -2.9156913748771087e-08 -2.8598886691378335e-08 -2.706431228354828e-08 -2.4274176996584538e-08 -2.0926014652228048e-08 -3.4737184322698563e-08 -3.278408962182394e-08 -3.3063103150520315e-08 -3.250507609312757e-08 -3.250507609312757e-08 -3.2365569328779384e-08 -3.390014373660944e-08 -3.9759427839233295e-08 -3.3063103150520315e-08 -4.5618711941857144e-08 -4.896687428621364e-08 -5.036194192969551e-08 -5.064095545839188e-08 -4.687427282099083e-08 -4.7153286349687207e-08 -4.631624576359808e-08 -4.2828576654893406e-08 -3.5992745201832246e-08 -2.8598886691378335e-08 -2.6366778461807345e-08 -2.5250724347021848e-08 -2.4413683760932724e-08 -2.2321082295709924e-08 -2.008897406613893e-08 -3.417915726530581e-08 -3.208655580008301e-08 -3.1947049035734825e-08 -3.1389021978342073e-08 -3.152852874269026e-08 -3.22260625644312e-08 -3.250507609312757e-08 -3.362113020791307e-08 -3.6690279023573184e-08 -4.087548195401879e-08 -4.575821870620534e-08 -4.966440810795457e-08 -5.078046222274007e-08 -4.868786075751727e-08 -4.729279311403539e-08 -4.533969841316077e-08 -4.3805124005330716e-08 -4.115449548271517e-08 -3.906189401749236e-08 -3.892238725314418e-08 -3.8364360195751426e-08 -3.7806333138358674e-08 -3.710879931661774e-08 -3.682978578792137e-08 -3.557422490878769e-08 -3.390014373660944e-08 -3.487669108704675e-08 -3.376063697226125e-08 -3.362113020791307e-08 -3.320260991486851e-08 -3.348162344356488e-08 -3.2644582857475756e-08 -3.2365569328779384e-08 -3.0970501685297515e-08 -3.2644582857475756e-08 -3.417915726530581e-08 -3.5016197851394936e-08 -3.515570461574312e-08 -3.557422490878769e-08 -3.487669108704675e-08 -3.459767755835038e-08 -3.376063697226125e-08 -3.4039650500957626e-08 -3.5992745201832246e-08 -3.54347181444395e-08 -3.5016197851394936e-08 -3.390014373660944e-08 -3.3342116679216694e-08 -3.250507609312757e-08 -3.11100084496457e-08 -3.1947049035734825e-08 -3.1389021978342073e-08 -3.11100084496457e-08 -3.11100084496457e-08 -3.3063103150520315e-08 -3.906189401749236e-08 -3.2365569328779384e-08 -4.464216459141985e-08 -4.785082017142814e-08 -4.980391487230276e-08 -5.064095545839188e-08 -4.729279311403539e-08 -4.910638105056182e-08 -4.9245887814910014e-08 -4.7153286349687207e-08 -3.961992107488511e-08 -2.9296420513119273e-08 -2.873839345572652e-08 -2.845937992703015e-08 -2.6785298754851907e-08 -2.3576643174843603e-08 -2.0228480830487117e-08 -3.4737184322698563e-08 -3.208655580008301e-08 -3.2644582857475756e-08 -3.1668035507038446e-08 -3.1389021978342073e-08 -3.1389021978342073e-08 -3.278408962182394e-08 -3.8782880488795985e-08 -3.278408962182394e-08 -4.5479205177508965e-08 -4.8548353993169076e-08 -4.9943421636650945e-08 -5.078046222274007e-08 -4.687427282099083e-08 -4.882736752186545e-08 -4.868786075751727e-08 -4.61767389992499e-08 -3.8782880488795985e-08 -2.8319873162681962e-08 -2.7761846105289214e-08 -2.804085963398559e-08 -2.7343325812244652e-08 -2.413467023223635e-08 -1.9670453773094368e-08 -3.250507609312757e-08 -3.0551981392252956e-08 -3.11100084496457e-08 -3.013346109920839e-08 -3.027296786355658e-08 -3.069148815660114e-08 -3.250507609312757e-08 -3.8364360195751426e-08 -3.2644582857475756e-08 -4.50606848844644e-08 -4.812983370012452e-08 -4.966440810795457e-08 -5.078046222274007e-08 -4.687427282099083e-08 -4.868786075751727e-08 -4.868786075751727e-08 -4.631624576359808e-08 -3.9340907546188736e-08 -2.9017406984422894e-08 -2.845937992703015e-08 -2.845937992703015e-08 -2.706431228354828e-08 -2.413467023223635e-08 -2.008897406613893e-08 -3.3063103150520315e-08 -3.11100084496457e-08 -3.180754227138664e-08 -3.11100084496457e-08 -3.069148815660114e-08 -3.11100084496457e-08 -3.250507609312757e-08 -3.7806333138358674e-08 -3.208655580008301e-08 -4.4502657827071654e-08 -4.799032693577633e-08 -4.9524901343606386e-08 -5.0501448694043697e-08 -4.701377958533902e-08 -4.8548353993169076e-08 -4.8548353993169076e-08 -4.61767389992499e-08 -3.906189401749236e-08 -2.873839345572652e-08 -2.8180366398333776e-08 -2.845937992703015e-08 -2.706431228354828e-08 -2.3995163467888165e-08 -1.9809960537442554e-08 -3.208655580008301e-08 -2.9575434041815645e-08 -2.943592727746746e-08 -2.873839345572652e-08 -2.8598886691378335e-08 -2.9017406984422894e-08 -3.0970501685297515e-08 -3.6550772259225e-08 -3.083099492094933e-08 -4.2689069890545226e-08 -4.61767389992499e-08 -4.729279311403539e-08 -4.799032693577633e-08 -4.436315106272346e-08 -4.520019164881259e-08 -4.436315106272346e-08 -4.087548195401879e-08 -3.445817079400219e-08 -2.706431228354828e-08 -2.5111217582673662e-08 -2.4413683760932724e-08 -2.3437136410495414e-08 -2.14840417096208e-08 -1.8972919951353434e-08 -3.180754227138664e-08 -2.943592727746746e-08 -2.9575434041815645e-08 -2.873839345572652e-08 -2.873839345572652e-08 -2.873839345572652e-08 -2.9296420513119273e-08 -3.013346109920839e-08 -3.292359638617213e-08 -3.6411265494876805e-08 -4.087548195401879e-08 -4.394463076967891e-08 -4.492117812011622e-08 -4.2410056361848854e-08 -4.157301577575972e-08 -4.087548195401879e-08 -3.9759427839233295e-08 -3.7666826374010495e-08 -3.5016197851394936e-08 -3.487669108704675e-08 -3.5016197851394936e-08 -3.3342116679216694e-08 -3.3063103150520315e-08 -3.292359638617213e-08 -3.1668035507038446e-08 -2.985444757051202e-08 -3.027296786355658e-08 -2.9296420513119273e-08 -2.943592727746746e-08 -2.9156913748771087e-08 -2.9575434041815645e-08 -2.9575434041815645e-08 -2.9156913748771087e-08 -2.845937992703015e-08 -3.041247462790477e-08 -3.2644582857475756e-08 -3.348162344356488e-08 -3.362113020791307e-08 -3.390014373660944e-08 -3.390014373660944e-08 -3.4737184322698563e-08 -3.417915726530581e-08 -3.3342116679216694e-08 -3.5295211380091315e-08 -3.5713731673135874e-08 -3.4737184322698563e-08 -3.4318664029654005e-08 -3.362113020791307e-08 -3.320260991486851e-08 -3.11100084496457e-08 -3.152852874269026e-08 -3.0970501685297515e-08 -3.11100084496457e-08 -3.11100084496457e-08 -3.292359638617213e-08 -3.850386696009961e-08 -3.152852874269026e-08 -4.366561724098254e-08 -4.701377958533902e-08 -4.882736752186545e-08 -4.9524901343606386e-08 -4.575821870620534e-08 -4.771131340707996e-08 -4.771131340707996e-08 -4.5479205177508965e-08 -3.822485343140324e-08 -2.804085963398559e-08 -2.7482832576592838e-08 -2.845937992703015e-08 -2.6366778461807345e-08 -2.3018616117450855e-08 -1.9251933480049806e-08 -3.208655580008301e-08 -2.943592727746746e-08 -2.985444757051202e-08 -2.943592727746746e-08 -2.9714940806163832e-08 -2.9714940806163832e-08 -3.1389021978342073e-08 -3.7387812845314116e-08 -3.152852874269026e-08 -4.394463076967891e-08 -4.701377958533902e-08 -4.868786075751727e-08 -4.966440810795457e-08 -4.5479205177508965e-08 -4.7432299878383586e-08 -4.729279311403539e-08 -4.492117812011622e-08 -3.7387812845314116e-08 -2.6924805519200093e-08 -2.6785298754851907e-08 -2.845937992703015e-08 -2.7343325812244652e-08 -2.413467023223635e-08 -1.9251933480049806e-08 -3.124951521399389e-08 -2.943592727746746e-08 -3.027296786355658e-08 -2.985444757051202e-08 -3.027296786355658e-08 -3.069148815660114e-08 -3.2644582857475756e-08 -3.850386696009961e-08 -3.208655580008301e-08 -4.4502657827071654e-08 -4.7571806642731765e-08 -4.868786075751727e-08 -4.9524901343606386e-08 -4.5479205177508965e-08 -4.7432299878383586e-08 -4.729279311403539e-08 -4.492117812011622e-08 -3.7806333138358674e-08 -2.7343325812244652e-08 -2.706431228354828e-08 -2.8598886691378335e-08 -2.6924805519200093e-08 -2.4274176996584538e-08 -1.9949467301790744e-08 -3.22260625644312e-08 -2.9993954334860204e-08 -3.069148815660114e-08 -2.985444757051202e-08 -3.013346109920839e-08 -3.027296786355658e-08 -3.22260625644312e-08 -3.8364360195751426e-08 -3.152852874269026e-08 -4.3386603712286164e-08 -4.7153286349687207e-08 -4.882736752186545e-08 -4.9943421636650945e-08 -4.61767389992499e-08 -4.785082017142814e-08 -4.785082017142814e-08 -4.5479205177508965e-08 -3.8364360195751426e-08 -2.7901352869637404e-08 -2.7482832576592838e-08 -2.9156913748771087e-08 -2.804085963398559e-08 -2.4832204053977286e-08 -2.0228480830487117e-08 -3.22260625644312e-08 -3.013346109920839e-08 -3.027296786355658e-08 -2.9714940806163832e-08 -2.985444757051202e-08 -3.0551981392252956e-08 -3.124951521399389e-08 -3.75273196096623e-08 -3.027296786355658e-08 -4.213104283315248e-08 -4.5618711941857144e-08 -4.6595259292294455e-08 -4.7432299878383586e-08 -4.366561724098254e-08 -4.436315106272346e-08 -4.310759018358978e-08 -3.948041431053692e-08 -3.3342116679216694e-08 -2.5390231111370035e-08 -2.3995163467888165e-08 -2.4274176996584538e-08 -2.3018616117450855e-08 -2.078650788787986e-08 -1.82753861296125e-08 -3.083099492094933e-08 -2.845937992703015e-08 -2.9017406984422894e-08 -2.845937992703015e-08 -2.873839345572652e-08 -2.873839345572652e-08 -2.9017406984422894e-08 -2.9714940806163832e-08 -3.208655580008301e-08 -3.6411265494876805e-08 -4.101498871836698e-08 -4.422364429837528e-08 -4.478167135576803e-08 -4.227054959750066e-08 -4.1433509011411543e-08 -4.059646842532242e-08 -3.989893460358149e-08 -3.8085346667055053e-08 -3.5713731673135874e-08 -3.515570461574312e-08 -3.54347181444395e-08 -3.320260991486851e-08 -3.278408962182394e-08 -3.1668035507038446e-08 -3.0551981392252956e-08 -2.8877900220074708e-08 -2.943592727746746e-08 -2.873839345572652e-08 -2.873839345572652e-08 -2.845937992703015e-08 -2.873839345572652e-08 -2.9017406984422894e-08 -2.804085963398559e-08 -2.804085963398559e-08 -2.985444757051202e-08 -3.1947049035734825e-08 -3.320260991486851e-08 -3.3342116679216694e-08 -3.3342116679216694e-08 -3.362113020791307e-08 -3.445817079400219e-08 -3.3342116679216694e-08 -3.208655580008301e-08 -3.376063697226125e-08 -3.515570461574312e-08 -3.4318664029654005e-08 -3.4039650500957626e-08 -3.362113020791307e-08 -3.3063103150520315e-08 -3.124951521399389e-08 -3.1668035507038446e-08 -3.083099492094933e-08 -3.11100084496457e-08 -3.11100084496457e-08 -3.278408962182394e-08 -3.8364360195751426e-08 -3.11100084496457e-08 -4.3526110476634344e-08 -4.687427282099083e-08 -4.882736752186545e-08 -4.966440810795457e-08 -4.5897725470553524e-08 -4.799032693577633e-08 -4.771131340707996e-08 -4.520019164881259e-08 -3.794583990270687e-08 -2.7203819047896466e-08 -2.650628522615553e-08 -2.873839345572652e-08 -2.650628522615553e-08 -2.315812288179904e-08 -1.9391440244397992e-08 -3.1947049035734825e-08 -2.9575434041815645e-08 -2.9993954334860204e-08 -2.9575434041815645e-08 -2.985444757051202e-08 -3.013346109920839e-08 -3.180754227138664e-08 -3.822485343140324e-08 -3.1389021978342073e-08 -4.394463076967891e-08 -4.7153286349687207e-08 -4.882736752186545e-08 -4.966440810795457e-08 -4.5897725470553524e-08 -4.771131340707996e-08 -4.7432299878383586e-08 -4.464216459141985e-08 -3.696929255226956e-08 -2.6366778461807345e-08 -2.552973787571822e-08 -2.8319873162681962e-08 -2.7343325812244652e-08 -2.3995163467888165e-08 -1.953094700874618e-08 -3.180754227138664e-08 -2.9296420513119273e-08 -2.9714940806163832e-08 -2.9575434041815645e-08 -3.027296786355658e-08 -3.013346109920839e-08 -3.208655580008301e-08 -3.8085346667055053e-08 -3.0970501685297515e-08 -4.3526110476634344e-08 -4.729279311403539e-08 -4.8548353993169076e-08 -4.9245887814910014e-08 -4.520019164881259e-08 -4.701377958533902e-08 -4.673476605664265e-08 -4.4502657827071654e-08 -3.710879931661774e-08 -2.6785298754851907e-08 -2.608776493311097e-08 -2.9156913748771087e-08 -2.7482832576592838e-08 -2.4832204053977286e-08 -1.9949467301790744e-08 -3.208655580008301e-08 -2.9575434041815645e-08 -3.041247462790477e-08 -2.9575434041815645e-08 -2.985444757051202e-08 -3.013346109920839e-08 -3.208655580008301e-08 -3.8085346667055053e-08 -3.083099492094933e-08 -4.310759018358978e-08 -4.687427282099083e-08 -4.882736752186545e-08 -4.9943421636650945e-08 -4.603723223490171e-08 -4.7571806642731765e-08 -4.785082017142814e-08 -4.50606848844644e-08 -3.794583990270687e-08 -2.7482832576592838e-08 -2.6227271697459155e-08 -2.9575434041815645e-08 -2.873839345572652e-08 -2.5948258168762783e-08 -2.078650788787986e-08 -3.2644582857475756e-08 -3.041247462790477e-08 -3.083099492094933e-08 -3.027296786355658e-08 -3.0551981392252956e-08 -3.0970501685297515e-08 -3.180754227138664e-08 -3.8085346667055053e-08 -3.041247462790477e-08 -4.2549563126197034e-08 -4.5897725470553524e-08 -4.7153286349687207e-08 -4.7571806642731765e-08 -4.366561724098254e-08 -4.422364429837528e-08 -4.324709694793797e-08 -3.961992107488511e-08 -3.3063103150520315e-08 -2.5111217582673662e-08 -2.3716149939191793e-08 -2.455319052528091e-08 -2.3437136410495414e-08 -2.0926014652228048e-08 -1.82753861296125e-08 -3.0551981392252956e-08 -2.8180366398333776e-08 -2.8877900220074708e-08 -2.8180366398333776e-08 -2.8598886691378335e-08 -2.8319873162681962e-08 -2.8598886691378335e-08 -2.943592727746746e-08 -3.124951521399389e-08 -3.6550772259225e-08 -4.157301577575972e-08 -4.478167135576803e-08 -4.533969841316077e-08 -4.2549563126197034e-08 -4.115449548271517e-08 -4.031745489662604e-08 -3.920140078184055e-08 -3.696929255226956e-08 -3.5016197851394936e-08 -3.390014373660944e-08 -3.459767755835038e-08 -3.278408962182394e-08 -3.22260625644312e-08 -3.0970501685297515e-08 -2.9993954334860204e-08 -2.8180366398333776e-08 -2.8877900220074708e-08 -2.8180366398333776e-08 -2.8319873162681962e-08 -2.8180366398333776e-08 -2.804085963398559e-08 -2.7761846105289214e-08 -2.706431228354828e-08 -2.7622339340941025e-08 -2.9575434041815645e-08 -3.083099492094933e-08 -3.069148815660114e-08 -3.0970501685297515e-08 -3.0970501685297515e-08 -3.069148815660114e-08 -3.041247462790477e-08 -2.9296420513119273e-08 -2.8598886691378335e-08 -2.9993954334860204e-08 -3.1668035507038446e-08 -3.0970501685297515e-08 -3.027296786355658e-08 -2.985444757051202e-08 -2.943592727746746e-08 -2.7901352869637404e-08 -2.9156913748771087e-08 -2.8598886691378335e-08 -2.8877900220074708e-08 -2.9575434041815645e-08 -3.0970501685297515e-08 -3.682978578792137e-08 -3.027296786355658e-08 -4.310759018358978e-08 -4.6595259292294455e-08 -4.82693404644727e-08 -4.910638105056182e-08 -4.520019164881259e-08 -4.701377958533902e-08 -4.7153286349687207e-08 -4.4502657827071654e-08 -3.724830608096593e-08 -2.6366778461807345e-08 -2.552973787571822e-08 -2.8319873162681962e-08 -2.650628522615553e-08 -2.287910935310267e-08 -1.9391440244397992e-08 -3.22260625644312e-08 -2.9714940806163832e-08 -3.027296786355658e-08 -2.9575434041815645e-08 -2.985444757051202e-08 -3.0551981392252956e-08 -3.250507609312757e-08 -3.906189401749236e-08 -3.1668035507038446e-08 -4.436315106272346e-08 -4.785082017142814e-08 -4.9245887814910014e-08 -4.9943421636650945e-08 -4.61767389992499e-08 -4.82693404644727e-08 -4.799032693577633e-08 -4.50606848844644e-08 -3.7387812845314116e-08 -2.706431228354828e-08 -2.5669244640066407e-08 -2.9296420513119273e-08 -2.8877900220074708e-08 -2.5111217582673662e-08 -2.0228480830487117e-08 -3.278408962182394e-08 -2.9993954334860204e-08 -3.013346109920839e-08 -2.9156913748771087e-08 -2.9714940806163832e-08 -2.9714940806163832e-08 -3.124951521399389e-08 -3.724830608096593e-08 -3.027296786355658e-08 -4.29680834192416e-08 -4.6595259292294455e-08 -4.840884722882089e-08 -4.9245887814910014e-08 -4.5479205177508965e-08 -4.7153286349687207e-08 -4.701377958533902e-08 -4.492117812011622e-08 -3.7666826374010495e-08 -2.7203819047896466e-08 -2.552973787571822e-08 -2.9714940806163832e-08 -2.8319873162681962e-08 -2.5111217582673662e-08 -1.9809960537442554e-08 -3.1947049035734825e-08 -2.9156913748771087e-08 -2.9575434041815645e-08 -2.8180366398333776e-08 -2.845937992703015e-08 -2.873839345572652e-08 -3.013346109920839e-08 -3.557422490878769e-08 -2.9993954334860204e-08 -4.2689069890545226e-08 -4.6455752527946275e-08 -4.840884722882089e-08 -4.910638105056182e-08 -4.5479205177508965e-08 -4.6455752527946275e-08 -4.687427282099083e-08 -4.422364429837528e-08 -3.710879931661774e-08 -2.6645791990503717e-08 -2.4832204053977286e-08 -2.8877900220074708e-08 -2.8180366398333776e-08 -2.4971710818325472e-08 -1.9670453773094368e-08 -3.083099492094933e-08 -2.7901352869637404e-08 -2.8180366398333776e-08 -2.7343325812244652e-08 -2.7482832576592838e-08 -2.7761846105289214e-08 -2.943592727746746e-08 -3.5016197851394936e-08 -2.8877900220074708e-08 -4.087548195401879e-08 -4.408413753402709e-08 -4.5618711941857144e-08 -4.6455752527946275e-08 -4.2410056361848854e-08 -4.3386603712286164e-08 -4.29680834192416e-08 -3.948041431053692e-08 -3.320260991486851e-08 -2.5808751404414597e-08 -2.3995163467888165e-08 -2.5669244640066407e-08 -2.46926972896291e-08 -2.1902562002665358e-08 -1.911242671570162e-08 -3.11100084496457e-08 -2.804085963398559e-08 -2.8319873162681962e-08 -2.706431228354828e-08 -2.7343325812244652e-08 -2.7343325812244652e-08 -2.804085963398559e-08 -2.8319873162681962e-08 -2.9575434041815645e-08 -3.54347181444395e-08 -4.017794813227786e-08 -4.310759018358978e-08 -4.408413753402709e-08 -4.129400224706335e-08 -3.989893460358149e-08 -3.961992107488511e-08 -3.822485343140324e-08 -3.5713731673135874e-08 -3.348162344356488e-08 -3.2365569328779384e-08 -3.390014373660944e-08 -3.278408962182394e-08 -3.1947049035734825e-08 -3.069148815660114e-08 -2.9714940806163832e-08 -2.7761846105289214e-08 -2.845937992703015e-08 -2.7203819047896466e-08 -2.7622339340941025e-08 -2.7203819047896466e-08 -2.706431228354828e-08 -2.6227271697459155e-08 -2.552973787571822e-08 -2.5808751404414597e-08 -2.8319873162681962e-08 -2.9575434041815645e-08 -2.9993954334860204e-08 -3.027296786355658e-08 -3.0551981392252956e-08 -2.985444757051202e-08 -2.985444757051202e-08 -2.9714940806163832e-08 -2.9714940806163832e-08 -2.985444757051202e-08 -3.1947049035734825e-08 -3.124951521399389e-08 -2.9993954334860204e-08 -2.9156913748771087e-08 -2.8877900220074708e-08 -2.7482832576592838e-08 -2.873839345572652e-08 -2.8180366398333776e-08 -2.845937992703015e-08 -2.9714940806163832e-08 -3.041247462790477e-08 -3.515570461574312e-08 -2.9296420513119273e-08 -4.213104283315248e-08 -4.603723223490171e-08 -4.729279311403539e-08 -4.785082017142814e-08 -4.3805124005330716e-08 -4.5618711941857144e-08 -4.603723223490171e-08 -4.366561724098254e-08 -3.613225196618043e-08 -2.5390231111370035e-08 -2.3437136410495414e-08 -2.8180366398333776e-08 -2.6924805519200093e-08 -2.2739602588754482e-08 -1.8972919951353434e-08 -3.083099492094933e-08 -2.845937992703015e-08 -2.873839345572652e-08 -2.7901352869637404e-08 -2.8319873162681962e-08 -2.9017406984422894e-08 -3.083099492094933e-08 -3.627175873052862e-08 -2.9993954334860204e-08 -4.310759018358978e-08 -4.701377958533902e-08 -4.8548353993169076e-08 -4.896687428621364e-08 -4.478167135576803e-08 -4.687427282099083e-08 -4.687427282099083e-08 -4.4502657827071654e-08 -3.682978578792137e-08 -2.6227271697459155e-08 -2.3995163467888165e-08 -2.9296420513119273e-08 -2.9156913748771087e-08 -2.5250724347021848e-08 -1.953094700874618e-08 -3.11100084496457e-08 -2.873839345572652e-08 -2.9017406984422894e-08 -2.873839345572652e-08 -2.8598886691378335e-08 -2.9156913748771087e-08 -3.0551981392252956e-08 -3.557422490878769e-08 -2.9575434041815645e-08 -4.227054959750066e-08 -4.603723223490171e-08 -4.7571806642731765e-08 -4.840884722882089e-08 -4.478167135576803e-08 -4.6455752527946275e-08 -4.6595259292294455e-08 -4.422364429837528e-08 -3.696929255226956e-08 -2.6227271697459155e-08 -2.3716149939191793e-08 -2.8877900220074708e-08 -2.7901352869637404e-08 -2.4413683760932724e-08 -1.9251933480049806e-08 -3.027296786355658e-08 -2.7622339340941025e-08 -2.8180366398333776e-08 -2.6924805519200093e-08 -2.7203819047896466e-08 -2.7343325812244652e-08 -2.9017406984422894e-08 -3.390014373660944e-08 -2.873839345572652e-08 -4.101498871836698e-08 -4.478167135576803e-08 -4.6455752527946275e-08 -4.701377958533902e-08 -4.3386603712286164e-08 -4.50606848844644e-08 -4.520019164881259e-08 -4.2828576654893406e-08 -3.5992745201832246e-08 -2.552973787571822e-08 -2.3297629646147227e-08 -2.804085963398559e-08 -2.7761846105289214e-08 -2.413467023223635e-08 -1.8833413187005247e-08 -2.9156913748771087e-08 -2.6366778461807345e-08 -2.6924805519200093e-08 -2.5948258168762783e-08 -2.6366778461807345e-08 -2.650628522615553e-08 -2.8180366398333776e-08 -3.3063103150520315e-08 -2.7343325812244652e-08 -3.906189401749236e-08 -4.29680834192416e-08 -4.4502657827071654e-08 -4.5479205177508965e-08 -4.1433509011411543e-08 -4.227054959750066e-08 -4.1852029304456096e-08 -3.8085346667055053e-08 -3.208655580008301e-08 -2.4971710818325472e-08 -2.2739602588754482e-08 -2.4971710818325472e-08 -2.4274176996584538e-08 -2.1623548473968986e-08 -1.8693906422657058e-08 -3.069148815660114e-08 -2.7482832576592838e-08 -2.7901352869637404e-08 -2.6785298754851907e-08 -2.6785298754851907e-08 -2.6924805519200093e-08 -2.7482832576592838e-08 -2.706431228354828e-08 -2.873839345572652e-08 -3.4737184322698563e-08 -3.9759427839233295e-08 -4.2828576654893406e-08 -4.29680834192416e-08 -4.003844136792967e-08 -3.920140078184055e-08 -3.822485343140324e-08 -3.724830608096593e-08 -3.515570461574312e-08 -3.278408962182394e-08 -3.124951521399389e-08 -3.3342116679216694e-08 -3.250507609312757e-08 -3.180754227138664e-08 -3.0551981392252956e-08 -2.943592727746746e-08 -2.7761846105289214e-08 -2.8598886691378335e-08 -2.7761846105289214e-08 -2.7761846105289214e-08 -2.7622339340941025e-08 -2.804085963398559e-08 -2.6785298754851907e-08 -2.6227271697459155e-08 -2.706431228354828e-08 -2.9017406984422894e-08 -2.9993954334860204e-08 -3.1389021978342073e-08 -3.152852874269026e-08 -3.0970501685297515e-08 -2.9714940806163832e-08 -2.9156913748771087e-08 -2.845937992703015e-08 -2.8319873162681962e-08 -2.804085963398559e-08 -3.041247462790477e-08 -3.027296786355658e-08 -2.9017406984422894e-08 -2.8180366398333776e-08 -2.7761846105289214e-08 -2.7482832576592838e-08 -2.8598886691378335e-08 -2.8319873162681962e-08 -2.8877900220074708e-08 -3.0970501685297515e-08 -3.320260991486851e-08 -4.115449548271517e-08 -3.348162344356488e-08 -4.2689069890545226e-08 -4.5897725470553524e-08 -4.7153286349687207e-08 -4.5897725470553524e-08 -4.422364429837528e-08 -4.5479205177508965e-08 -4.478167135576803e-08 -4.059646842532242e-08 -3.180754227138664e-08 -2.3576643174843603e-08 -2.1623548473968986e-08 -2.7203819047896466e-08 -2.5808751404414597e-08 -2.1344534945272613e-08 -1.7996372600916123e-08 -2.8319873162681962e-08 -2.7622339340941025e-08 -2.7343325812244652e-08 -2.6924805519200093e-08 -2.7482832576592838e-08 -2.9017406984422894e-08 -3.2365569328779384e-08 -4.366561724098254e-08 -3.557422490878769e-08 -4.366561724098254e-08 -4.6455752527946275e-08 -4.7432299878383586e-08 -4.5618711941857144e-08 -4.464216459141985e-08 -4.575821870620534e-08 -4.4502657827071654e-08 -3.9759427839233295e-08 -3.083099492094933e-08 -2.2739602588754482e-08 -2.106552141657624e-08 -2.6785298754851907e-08 -2.5948258168762783e-08 -2.1205028180924427e-08 -1.757785230787156e-08 -2.845937992703015e-08 -2.7622339340941025e-08 -2.804085963398559e-08 -2.8180366398333776e-08 -2.804085963398559e-08 -2.8877900220074708e-08 -3.208655580008301e-08 -4.324709694793797e-08 -3.515570461574312e-08 -4.3386603712286164e-08 -4.603723223490171e-08 -4.687427282099083e-08 -4.50606848844644e-08 -4.422364429837528e-08 -4.520019164881259e-08 -4.408413753402709e-08 -3.948041431053692e-08 -3.0551981392252956e-08 -2.3018616117450855e-08 -2.1763055238317172e-08 -2.6785298754851907e-08 -2.5669244640066407e-08 -2.1205028180924427e-08 -1.729883877917519e-08 -2.8319873162681962e-08 -2.650628522615553e-08 -2.6366778461807345e-08 -2.608776493311097e-08 -2.608776493311097e-08 -2.6645791990503717e-08 -3.069148815660114e-08 -4.1852029304456096e-08 -3.4039650500957626e-08 -4.199153606880429e-08 -4.492117812011622e-08 -4.61767389992499e-08 -4.50606848844644e-08 -4.422364429837528e-08 -4.5479205177508965e-08 -4.394463076967891e-08 -3.906189401749236e-08 -3.013346109920839e-08 -2.2600095824406296e-08 -2.1623548473968986e-08 -2.6645791990503717e-08 -2.5808751404414597e-08 -2.14840417096208e-08 -1.7438345543523375e-08 -2.7203819047896466e-08 -2.608776493311097e-08 -2.5948258168762783e-08 -2.5390231111370035e-08 -2.5808751404414597e-08 -2.6645791990503717e-08 -3.013346109920839e-08 -4.017794813227786e-08 -3.208655580008301e-08 -3.948041431053692e-08 -4.2549563126197034e-08 -4.3805124005330716e-08 -4.227054959750066e-08 -4.059646842532242e-08 -4.059646842532242e-08 -3.850386696009961e-08 -3.3342116679216694e-08 -2.6785298754851907e-08 -2.14840417096208e-08 -1.9949467301790744e-08 -2.246058906005811e-08 -2.1623548473968986e-08 -1.8972919951353434e-08 -1.6601304957434254e-08 -2.7343325812244652e-08 -2.5948258168762783e-08 -2.5948258168762783e-08 -2.5250724347021848e-08 -2.5390231111370035e-08 -2.5390231111370035e-08 -2.5948258168762783e-08 -2.6366778461807345e-08 -2.9714940806163832e-08 -3.515570461574312e-08 -3.961992107488511e-08 -4.1852029304456096e-08 -4.059646842532242e-08 -3.850386696009961e-08 -3.7666826374010495e-08 -3.6550772259225e-08 -3.487669108704675e-08 -3.320260991486851e-08 -3.11100084496457e-08 -2.9993954334860204e-08 -3.1668035507038446e-08 -3.11100084496457e-08 -2.9575434041815645e-08 -2.8598886691378335e-08 -2.7343325812244652e-08 -2.706431228354828e-08 -2.7622339340941025e-08 -2.706431228354828e-08 -2.6924805519200093e-08 -2.7482832576592838e-08 -2.7482832576592838e-08 -2.608776493311097e-08 -2.5669244640066407e-08 -2.7622339340941025e-08 -2.9017406984422894e-08 -2.985444757051202e-08 -3.069148815660114e-08 -3.069148815660114e-08 -2.943592727746746e-08 -2.8598886691378335e-08 -2.706431228354828e-08 -2.5808751404414597e-08 -2.4971710818325472e-08 -2.5111217582673662e-08 -2.706431228354828e-08 -2.804085963398559e-08 -2.6785298754851907e-08 -2.608776493311097e-08 -2.7343325812244652e-08 -2.706431228354828e-08 -2.7622339340941025e-08 -2.706431228354828e-08 -2.6924805519200093e-08 -2.7482832576592838e-08 -2.7482832576592838e-08 -2.608776493311097e-08 -2.5669244640066407e-08 -2.7622339340941025e-08 -2.9017406984422894e-08 -2.985444757051202e-08 -3.069148815660114e-08 -3.069148815660114e-08 -2.943592727746746e-08 -2.8598886691378335e-08 -2.706431228354828e-08 -2.5808751404414597e-08 -2.4971710818325472e-08 -2.5111217582673662e-08 -2.706431228354828e-08 -2.804085963398559e-08 -2.6785298754851907e-08 -2.608776493311097e-08 -2.6645791990503717e-08 -2.7343325812244652e-08 -2.650628522615553e-08 -2.6785298754851907e-08 -2.7343325812244652e-08 -2.9296420513119273e-08 -3.4737184322698563e-08 -2.9156913748771087e-08 -4.1852029304456096e-08 -4.50606848844644e-08 -4.6455752527946275e-08 -4.673476605664265e-08 -4.2828576654893406e-08 -4.464216459141985e-08 -4.533969841316077e-08 -4.310759018358978e-08 -3.585323843748406e-08 -2.5669244640066407e-08 -2.106552141657624e-08 -2.1344534945272613e-08 -2.6227271697459155e-08 -2.4413683760932724e-08 -1.8414892893960685e-08 -2.8180366398333776e-08 -2.5669244640066407e-08 -2.608776493311097e-08 -2.6645791990503717e-08 -2.6227271697459155e-08 -2.650628522615553e-08 -2.7482832576592838e-08 -3.292359638617213e-08 -2.804085963398559e-08 -4.059646842532242e-08 -4.408413753402709e-08 -4.5897725470553524e-08 -4.673476605664265e-08 -4.2689069890545226e-08 -4.464216459141985e-08 -4.492117812011622e-08 -4.2689069890545226e-08 -3.613225196618043e-08 -2.5250724347021848e-08 -2.106552141657624e-08 -2.1344534945272613e-08 -2.5948258168762783e-08 -2.4413683760932724e-08 -1.855439965830887e-08 -2.8598886691378335e-08 -2.6785298754851907e-08 -2.5948258168762783e-08 -2.4832204053977286e-08 -2.552973787571822e-08 -2.5948258168762783e-08 -2.706431228354828e-08 -3.292359638617213e-08 -2.7901352869637404e-08 -4.031745489662604e-08 -4.394463076967891e-08 -4.575821870620534e-08 -4.673476605664265e-08 -4.3386603712286164e-08 -4.533969841316077e-08 -4.5618711941857144e-08 -4.29680834192416e-08 -3.5713731673135874e-08 -2.4971710818325472e-08 -2.0367987594835303e-08 -2.078650788787986e-08 -2.552973787571822e-08 -2.46926972896291e-08 -1.9391440244397992e-08 -2.8877900220074708e-08 -2.6227271697459155e-08 -2.6366778461807345e-08 -2.5669244640066407e-08 -2.608776493311097e-08 -2.6785298754851907e-08 -2.845937992703015e-08 -3.362113020791307e-08 -2.7343325812244652e-08 -3.86433737244478e-08 -4.1852029304456096e-08 -4.324709694793797e-08 -4.3805124005330716e-08 -3.989893460358149e-08 -4.045696166097423e-08 -3.948041431053692e-08 -3.5713731673135874e-08 -2.985444757051202e-08 -2.246058906005811e-08 -1.9251933480049806e-08 -1.8972919951353434e-08 -2.1763055238317172e-08 -2.106552141657624e-08 -1.771735907221975e-08 -2.845937992703015e-08 -2.5390231111370035e-08 -2.5669244640066407e-08 -2.5250724347021848e-08 -2.5390231111370035e-08 -2.608776493311097e-08 -2.5808751404414597e-08 -2.5808751404414597e-08 -2.7622339340941025e-08 -3.3063103150520315e-08 -3.682978578792137e-08 -3.948041431053692e-08 -4.003844136792967e-08 -3.822485343140324e-08 -3.710879931661774e-08 -3.6411265494876805e-08 -3.54347181444395e-08 -3.348162344356488e-08 -3.11100084496457e-08 -2.9575434041815645e-08 -2.943592727746746e-08 -3.0551981392252956e-08 -3.0970501685297515e-08 -2.9296420513119273e-08 -2.873839345572652e-08 -2.706431228354828e-08 -2.804085963398559e-08 -2.7482832576592838e-08 -2.706431228354828e-08 -2.6785298754851907e-08 -2.7343325812244652e-08 -2.650628522615553e-08 -2.4971710818325472e-08 -2.5669244640066407e-08 -2.7482832576592838e-08 -2.8877900220074708e-08 -2.9575434041815645e-08 -2.9714940806163832e-08 -2.9575434041815645e-08 -2.845937992703015e-08 -2.7761846105289214e-08 -2.6366778461807345e-08 -2.552973787571822e-08 -2.4832204053977286e-08 -2.455319052528091e-08 -2.6227271697459155e-08 -2.7343325812244652e-08 -2.5948258168762783e-08 -2.5111217582673662e-08 -2.2739602588754482e-08 -2.385565670353998e-08 -2.3437136410495414e-08 -2.3716149939191793e-08 -2.455319052528091e-08 -2.6366778461807345e-08 -3.152852874269026e-08 -2.6785298754851907e-08 -3.9759427839233295e-08 -4.366561724098254e-08 -4.5618711941857144e-08 -4.631624576359808e-08 -4.324709694793797e-08 -4.50606848844644e-08 -4.4502657827071654e-08 -4.227054959750066e-08 -3.4737184322698563e-08 -2.3576643174843603e-08 -1.9391440244397992e-08 -1.911242671570162e-08 -2.3018616117450855e-08 -2.287910935310267e-08 -1.8414892893960685e-08 -2.8598886691378335e-08 -2.4971710818325472e-08 -2.5669244640066407e-08 -2.5111217582673662e-08 -2.5390231111370035e-08 -2.552973787571822e-08 -2.6785298754851907e-08 -3.208655580008301e-08 -2.7203819047896466e-08 -3.9759427839233295e-08 -4.324709694793797e-08 -4.478167135576803e-08 -4.5618711941857144e-08 -4.199153606880429e-08 -4.3805124005330716e-08 -4.4502657827071654e-08 -4.227054959750066e-08 -3.5295211380091315e-08 -2.455319052528091e-08 -2.050749435918349e-08 -2.106552141657624e-08 -2.5390231111370035e-08 -2.46926972896291e-08 -1.855439965830887e-08 -2.706431228354828e-08 -2.4413683760932724e-08 -2.455319052528091e-08 -2.455319052528091e-08 -2.3995163467888165e-08 -2.4413683760932724e-08 -2.608776493311097e-08 -3.11100084496457e-08 -2.6785298754851907e-08 -3.920140078184055e-08 -4.2689069890545226e-08 -4.436315106272346e-08 -4.5618711941857144e-08 -4.199153606880429e-08 -4.408413753402709e-08 -4.464216459141985e-08 -4.2410056361848854e-08 -3.5713731673135874e-08 -2.4832204053977286e-08 -2.0926014652228048e-08 -2.0926014652228048e-08 -2.5111217582673662e-08 -2.5111217582673662e-08 -1.9251933480049806e-08 -2.8877900220074708e-08 -2.6227271697459155e-08 -2.6366778461807345e-08 -2.5669244640066407e-08 -2.6645791990503717e-08 -2.6645791990503717e-08 -2.8180366398333776e-08 -3.362113020791307e-08 -2.804085963398559e-08 -4.031745489662604e-08 -4.394463076967891e-08 -4.5479205177508965e-08 -4.631624576359808e-08 -4.2689069890545226e-08 -4.492117812011622e-08 -4.492117812011622e-08 -4.199153606880429e-08 -3.5295211380091315e-08 -2.5111217582673662e-08 -2.0926014652228048e-08 -2.106552141657624e-08 -2.5111217582673662e-08 -2.5669244640066407e-08 -2.008897406613893e-08 -2.943592727746746e-08 -2.650628522615553e-08 -2.6785298754851907e-08 -2.6227271697459155e-08 -2.6785298754851907e-08 -2.7343325812244652e-08 -2.9017406984422894e-08 -3.417915726530581e-08 -2.7622339340941025e-08 -3.961992107488511e-08 -4.2689069890545226e-08 -4.422364429837528e-08 -4.478167135576803e-08 -4.087548195401879e-08 -4.129400224706335e-08 -4.017794813227786e-08 -3.6550772259225e-08 -3.069148815660114e-08 -2.287910935310267e-08 -1.9391440244397992e-08 -1.9251933480049806e-08 -2.1902562002665358e-08 -2.2321082295709924e-08 -1.911242671570162e-08 -2.9993954334860204e-08 -2.706431228354828e-08 -2.7482832576592838e-08 -2.7343325812244652e-08 -2.7622339340941025e-08 -2.8598886691378335e-08 -2.7901352869637404e-08 -2.706431228354828e-08 -2.9156913748771087e-08 -3.459767755835038e-08 -3.822485343140324e-08 -4.0735975189670606e-08 -4.115449548271517e-08 -3.9759427839233295e-08 -3.794583990270687e-08 -3.724830608096593e-08 -3.5016197851394936e-08 -3.320260991486851e-08 -2.985444757051202e-08 -2.8180366398333776e-08 -2.845937992703015e-08 -2.985444757051202e-08 -3.11100084496457e-08 -3.027296786355658e-08 -2.873839345572652e-08 -2.706431228354828e-08 -2.7901352869637404e-08 -2.6645791990503717e-08 -2.6785298754851907e-08 -2.6366778461807345e-08 -2.6645791990503717e-08 -2.5669244640066407e-08 -2.385565670353998e-08 -2.5390231111370035e-08 -2.7343325812244652e-08 -2.8877900220074708e-08 -2.9714940806163832e-08 -2.985444757051202e-08 -2.943592727746746e-08 -2.8319873162681962e-08 -2.6924805519200093e-08 -2.5808751404414597e-08 -2.4971710818325472e-08 -2.413467023223635e-08 -2.385565670353998e-08 -2.4971710818325472e-08 -2.6366778461807345e-08 -2.5111217582673662e-08 -2.3995163467888165e-08 -2.246058906005811e-08 -2.3437136410495414e-08 -2.315812288179904e-08 -2.3576643174843603e-08 -2.455319052528091e-08 -2.5808751404414597e-08 -3.041247462790477e-08 -2.5948258168762783e-08 -3.8364360195751426e-08 -4.227054959750066e-08 -4.366561724098254e-08 -4.464216459141985e-08 -4.115449548271517e-08 -4.310759018358978e-08 -4.2689069890545226e-08 -4.101498871836698e-08 -3.376063697226125e-08 -2.2739602588754482e-08 -1.8693906422657058e-08 -1.855439965830887e-08 -2.1344534945272613e-08 -2.246058906005811e-08 -1.7856865836567937e-08 -2.8180366398333776e-08 -2.455319052528091e-08 -2.5390231111370035e-08 -2.4274176996584538e-08 -2.46926972896291e-08 -2.455319052528091e-08 -2.552973787571822e-08 -3.027296786355658e-08 -2.5948258168762783e-08 -3.8364360195751426e-08 -4.199153606880429e-08 -4.394463076967891e-08 -4.533969841316077e-08 -4.157301577575972e-08 -4.324709694793797e-08 -4.366561724098254e-08 -4.1433509011411543e-08 -3.487669108704675e-08 -2.3995163467888165e-08 -1.9391440244397992e-08 -1.9391440244397992e-08 -2.246058906005811e-08 -2.3576643174843603e-08 -1.813587936526431e-08 -2.650628522615553e-08 -2.3716149939191793e-08 -2.413467023223635e-08 -2.315812288179904e-08 -2.3297629646147227e-08 -2.3716149939191793e-08 -2.552973787571822e-08 -3.013346109920839e-08 -2.5948258168762783e-08 -3.8085346667055053e-08 -4.1712522540107916e-08 -4.3526110476634344e-08 -4.464216459141985e-08 -4.115449548271517e-08 -4.310759018358978e-08 -4.3805124005330716e-08 -4.157301577575972e-08 -3.459767755835038e-08 -2.4274176996584538e-08 -1.9949467301790744e-08 -1.9670453773094368e-08 -2.2600095824406296e-08 -2.4413683760932724e-08 -1.8972919951353434e-08 -2.7901352869637404e-08 -2.5111217582673662e-08 -2.5669244640066407e-08 -2.4971710818325472e-08 -2.552973787571822e-08 -2.5250724347021848e-08 -2.7203819047896466e-08 -3.22260625644312e-08 -2.7343325812244652e-08 -3.9759427839233295e-08 -4.3386603712286164e-08 -4.520019164881259e-08 -4.61767389992499e-08 -4.2689069890545226e-08 -4.464216459141985e-08 -4.492117812011622e-08 -4.199153606880429e-08 -3.5295211380091315e-08 -2.5111217582673662e-08 -2.106552141657624e-08 -2.050749435918349e-08 -2.287910935310267e-08 -2.4971710818325472e-08 -1.953094700874618e-08 -2.9017406984422894e-08 -2.5669244640066407e-08 -2.552973787571822e-08 -2.4832204053977286e-08 -2.5390231111370035e-08 -2.5808751404414597e-08 -2.706431228354828e-08 -3.180754227138664e-08 -2.608776493311097e-08 -3.794583990270687e-08 -4.129400224706335e-08 -4.324709694793797e-08 -4.4502657827071654e-08 -4.115449548271517e-08 -4.157301577575972e-08 -4.101498871836698e-08 -3.724830608096593e-08 -3.11100084496457e-08 -2.3437136410495414e-08 -1.953094700874618e-08 -1.9251933480049806e-08 -2.1344534945272613e-08 -2.218157553136173e-08 -1.911242671570162e-08 -3.013346109920839e-08 -2.706431228354828e-08 -2.7203819047896466e-08 -2.650628522615553e-08 -2.6645791990503717e-08 -2.6645791990503717e-08 -2.650628522615553e-08 -2.5808751404414597e-08 -2.804085963398559e-08 -3.3342116679216694e-08 -3.794583990270687e-08 -4.059646842532242e-08 -4.101498871836698e-08 -3.961992107488511e-08 -3.8085346667055053e-08 -3.75273196096623e-08 -3.54347181444395e-08 -3.3342116679216694e-08 -3.013346109920839e-08 -2.8598886691378335e-08 -2.873839345572652e-08 -2.9156913748771087e-08 -3.083099492094933e-08 -2.9575434041815645e-08 -2.7482832576592838e-08 -2.552973787571822e-08 -2.5948258168762783e-08 -2.4832204053977286e-08 -2.46926972896291e-08 -2.455319052528091e-08 -2.455319052528091e-08 -2.315812288179904e-08 -2.1902562002665358e-08 -2.3716149939191793e-08 -2.650628522615553e-08 -2.7901352869637404e-08 -2.8598886691378335e-08 -2.8877900220074708e-08 -2.8877900220074708e-08 -2.8180366398333776e-08 -2.7343325812244652e-08 -2.6785298754851907e-08 -2.552973787571822e-08 -2.3995163467888165e-08 -2.385565670353998e-08 -2.413467023223635e-08 -2.6366778461807345e-08 -2.4971710818325472e-08 -2.413467023223635e-08 -2.2042068767013544e-08 -2.315812288179904e-08 -2.2321082295709924e-08 -2.3018616117450855e-08 -2.3716149939191793e-08 -2.4832204053977286e-08 -2.943592727746746e-08 -2.4971710818325472e-08 -3.682978578792137e-08 -4.0735975189670606e-08 -4.2689069890545226e-08 -4.3805124005330716e-08 -3.989893460358149e-08 -4.1712522540107916e-08 -4.157301577575972e-08 -4.003844136792967e-08 -3.320260991486851e-08 -2.2739602588754482e-08 -1.8693906422657058e-08 -1.8414892893960685e-08 -2.008897406613893e-08 -2.1623548473968986e-08 -1.757785230787156e-08 -2.7203819047896466e-08 -2.46926972896291e-08 -2.5250724347021848e-08 -2.413467023223635e-08 -2.4971710818325472e-08 -2.5250724347021848e-08 -2.6227271697459155e-08 -2.9575434041815645e-08 -2.4274176996584538e-08 -3.5295211380091315e-08 -3.8782880488795985e-08 -4.059646842532242e-08 -4.1712522540107916e-08 -3.8364360195751426e-08 -4.003844136792967e-08 -3.989893460358149e-08 -3.8085346667055053e-08 -3.22260625644312e-08 -2.287910935310267e-08 -1.82753861296125e-08 -1.7856865836567937e-08 -1.9809960537442554e-08 -2.14840417096208e-08 -1.7159332014827002e-08 -2.5948258168762783e-08 -2.385565670353998e-08 -2.4413683760932724e-08 -2.315812288179904e-08 -2.3297629646147227e-08 -2.3716149939191793e-08 -2.5111217582673662e-08 -2.943592727746746e-08 -2.5250724347021848e-08 -3.7666826374010495e-08 -4.087548195401879e-08 -4.2828576654893406e-08 -4.408413753402709e-08 -4.0735975189670606e-08 -4.29680834192416e-08 -4.310759018358978e-08 -4.115449548271517e-08 -3.417915726530581e-08 -2.3995163467888165e-08 -1.9391440244397992e-08 -1.855439965830887e-08 -2.050749435918349e-08 -2.2739602588754482e-08 -1.82753861296125e-08 -2.6366778461807345e-08 -2.3297629646147227e-08 -2.3576643174843603e-08 -2.2600095824406296e-08 -2.287910935310267e-08 -2.3576643174843603e-08 -2.4971710818325472e-08 -2.9296420513119273e-08 -2.552973787571822e-08 -3.7806333138358674e-08 -4.115449548271517e-08 -4.3526110476634344e-08 -4.478167135576803e-08 -4.1433509011411543e-08 -4.310759018358978e-08 -4.3526110476634344e-08 -4.1433509011411543e-08 -3.445817079400219e-08 -2.4274176996584538e-08 -2.0367987594835303e-08 -1.953094700874618e-08 -2.0647001123531675e-08 -2.3437136410495414e-08 -1.8693906422657058e-08 -2.7622339340941025e-08 -2.455319052528091e-08 -2.4413683760932724e-08 -2.4274176996584538e-08 -2.455319052528091e-08 -2.455319052528091e-08 -2.4971710818325472e-08 -2.8319873162681962e-08 -2.3018616117450855e-08 -3.3063103150520315e-08 -3.613225196618043e-08 -3.794583990270687e-08 -3.892238725314418e-08 -3.613225196618043e-08 -3.682978578792137e-08 -3.6550772259225e-08 -3.348162344356488e-08 -2.7901352869637404e-08 -2.14840417096208e-08 -1.7996372600916123e-08 -1.7438345543523375e-08 -1.8833413187005247e-08 -1.953094700874618e-08 -1.7019825250478813e-08 -2.7203819047896466e-08 -2.315812288179904e-08 -2.3297629646147227e-08 -2.315812288179904e-08 -2.2739602588754482e-08 -2.2739602588754482e-08 -2.3576643174843603e-08 -2.455319052528091e-08 -2.9714940806163832e-08 -4.157301577575972e-08 -4.82693404644727e-08 -5.105947575143644e-08 -5.2873063687962876e-08 -5.105947575143644e-08 -5.064095545839188e-08 -5.175700957317738e-08 -5.036194192969551e-08 -4.6455752527946275e-08 -3.557422490878769e-08 -3.027296786355658e-08 -2.9017406984422894e-08 -2.9575434041815645e-08 -3.3063103150520315e-08 -2.985444757051202e-08 -2.6645791990503717e-08 -2.3576643174843603e-08 -2.3995163467888165e-08 -2.3297629646147227e-08 -2.246058906005811e-08 -2.2600095824406296e-08 -2.2321082295709924e-08 -2.050749435918349e-08 -1.9949467301790744e-08 -2.1763055238317172e-08 -2.455319052528091e-08 -2.6924805519200093e-08 -2.7343325812244652e-08 -2.845937992703015e-08 -2.8180366398333776e-08 -2.804085963398559e-08 -2.8180366398333776e-08 -2.804085963398559e-08 -2.6645791990503717e-08 -2.5390231111370035e-08 -2.4971710818325472e-08 -2.4971710818325472e-08 -2.6785298754851907e-08 -2.5948258168762783e-08 -2.5111217582673662e-08 -2.315812288179904e-08 -2.3716149939191793e-08 -2.287910935310267e-08 -2.3297629646147227e-08 -2.3716149939191793e-08 -2.4832204053977286e-08 -2.7901352869637404e-08 -2.2739602588754482e-08 -3.3063103150520315e-08 -3.557422490878769e-08 -3.75273196096623e-08 -3.8364360195751426e-08 -3.557422490878769e-08 -3.724830608096593e-08 -3.724830608096593e-08 -3.515570461574312e-08 -2.9575434041815645e-08 -2.106552141657624e-08 -1.757785230787156e-08 -1.7019825250478813e-08 -1.729883877917519e-08 -1.855439965830887e-08 -1.6043277900041506e-08 -2.5250724347021848e-08 -2.3018616117450855e-08 -2.3576643174843603e-08 -2.246058906005811e-08 -2.2600095824406296e-08 -2.287910935310267e-08 -2.3995163467888165e-08 -2.6645791990503717e-08 -2.3018616117450855e-08 -3.362113020791307e-08 -3.682978578792137e-08 -3.822485343140324e-08 -3.892238725314418e-08 -3.6690279023573184e-08 -3.850386696009961e-08 -3.86433737244478e-08 -3.682978578792137e-08 -3.069148815660114e-08 -2.2042068767013544e-08 -1.7996372600916123e-08 -1.7159332014827002e-08 -1.82753861296125e-08 -2.050749435918349e-08 -1.7019825250478813e-08 -2.5948258168762783e-08 -2.455319052528091e-08 -2.5250724347021848e-08 -2.3995163467888165e-08 -2.4274176996584538e-08 -2.455319052528091e-08 -2.5390231111370035e-08 -2.8319873162681962e-08 -2.455319052528091e-08 -3.5713731673135874e-08 -3.822485343140324e-08 -4.017794813227786e-08 -4.1433509011411543e-08 -3.822485343140324e-08 -3.961992107488511e-08 -3.948041431053692e-08 -3.75273196096623e-08 -3.180754227138664e-08 -2.246058906005811e-08 -1.82753861296125e-08 -1.7438345543523375e-08 -1.7996372600916123e-08 -2.0228480830487117e-08 -1.7159332014827002e-08 -2.650628522615553e-08 -2.3297629646147227e-08 -2.385565670353998e-08 -2.3297629646147227e-08 -2.3716149939191793e-08 -2.4413683760932724e-08 -2.5111217582673662e-08 -2.8319873162681962e-08 -2.46926972896291e-08 -3.6550772259225e-08 -3.961992107488511e-08 -4.1852029304456096e-08 -4.310759018358978e-08 -3.989893460358149e-08 -4.1712522540107916e-08 -4.213104283315248e-08 -3.989893460358149e-08 -3.3342116679216694e-08 -2.3437136410495414e-08 -1.9949467301790744e-08 -1.9251933480049806e-08 -2.0367987594835303e-08 -2.2600095824406296e-08 -1.8414892893960685e-08 -2.7203819047896466e-08 -2.455319052528091e-08 -2.46926972896291e-08 -2.3995163467888165e-08 -2.3576643174843603e-08 -2.3576643174843603e-08 -2.3576643174843603e-08 -2.5808751404414597e-08 -2.1205028180924427e-08 -3.041247462790477e-08 -3.3063103150520315e-08 -3.459767755835038e-08 -3.54347181444395e-08 -3.278408962182394e-08 -3.376063697226125e-08 -3.3342116679216694e-08 -3.0970501685297515e-08 -2.650628522615553e-08 -2.050749435918349e-08 -1.771735907221975e-08 -1.6880318486130626e-08 -1.771735907221975e-08 -1.8414892893960685e-08 -1.6880318486130626e-08 -2.6785298754851907e-08 -2.46926972896291e-08 -2.46926972896291e-08 -2.3576643174843603e-08 -2.3437136410495414e-08 -2.3297629646147227e-08 -2.315812288179904e-08 -2.1902562002665358e-08 -2.3995163467888165e-08 -2.8877900220074708e-08 -3.2644582857475756e-08 -3.5295211380091315e-08 -3.5992745201832246e-08 -3.487669108704675e-08 -3.417915726530581e-08 -3.3342116679216694e-08 -3.22260625644312e-08 -3.0970501685297515e-08 -2.8877900220074708e-08 -2.6785298754851907e-08 -2.6645791990503717e-08 -2.5948258168762783e-08 -2.7622339340941025e-08 -2.7622339340941025e-08 -2.5669244640066407e-08 -2.3437136410495414e-08 -2.3995163467888165e-08 -2.3437136410495414e-08 -2.3018616117450855e-08 -2.315812288179904e-08 -2.246058906005811e-08 -2.0228480830487117e-08 -1.9949467301790744e-08 -2.078650788787986e-08 -2.3018616117450855e-08 -2.5669244640066407e-08 -2.6366778461807345e-08 -2.804085963398559e-08 -2.8319873162681962e-08 -2.7482832576592838e-08 -2.7761846105289214e-08 -2.6785298754851907e-08 -2.608776493311097e-08 -2.552973787571822e-08 -2.4832204053977286e-08 -2.455319052528091e-08 -2.6227271697459155e-08 -2.6366778461807345e-08 -2.5669244640066407e-08 -2.4274176996584538e-08 -2.5111217582673662e-08 -2.46926972896291e-08 -2.4971710818325472e-08 -2.4971710818325472e-08 -2.6227271697459155e-08 -2.9017406984422894e-08 -2.4413683760932724e-08 -3.487669108704675e-08 -3.75273196096623e-08 -3.906189401749236e-08 -4.017794813227786e-08 -3.7666826374010495e-08 -3.948041431053692e-08 -3.920140078184055e-08 -3.724830608096593e-08 -3.124951521399389e-08 -2.218157553136173e-08 -1.82753861296125e-08 -1.7159332014827002e-08 -1.729883877917519e-08 -1.8693906422657058e-08 -1.6182784664389692e-08 -2.552973787571822e-08 -2.3018616117450855e-08 -2.3437136410495414e-08 -2.2739602588754482e-08 -2.2739602588754482e-08 -2.287910935310267e-08 -2.3995163467888165e-08 -2.7482832576592838e-08 -2.455319052528091e-08 -3.627175873052862e-08 -3.9759427839233295e-08 -4.1433509011411543e-08 -4.2549563126197034e-08 -3.9759427839233295e-08 -4.199153606880429e-08 -4.2410056361848854e-08 -4.017794813227786e-08 -3.3342116679216694e-08 -2.3297629646147227e-08 -1.9251933480049806e-08 -1.8693906422657058e-08 -1.9391440244397992e-08 -2.1623548473968986e-08 -1.813587936526431e-08 -2.804085963398559e-08 -2.5250724347021848e-08 -2.5808751404414597e-08 -2.455319052528091e-08 -2.4971710818325472e-08 -2.5250724347021848e-08 -2.6227271697459155e-08 -2.9156913748771087e-08 -2.552973787571822e-08 -3.6690279023573184e-08 -3.9759427839233295e-08 -4.1433509011411543e-08 -4.2549563126197034e-08 -3.892238725314418e-08 -4.017794813227786e-08 -4.045696166097423e-08 -3.822485343140324e-08 -3.208655580008301e-08 -2.2739602588754482e-08 -1.855439965830887e-08 -1.7856865836567937e-08 -1.8414892893960685e-08 -2.008897406613893e-08 -1.729883877917519e-08 -2.7482832576592838e-08 -2.4413683760932724e-08 -2.4832204053977286e-08 -2.455319052528091e-08 -2.4413683760932724e-08 -2.4413683760932724e-08 -2.4832204053977286e-08 -2.46926972896291e-08 -2.9993954334860204e-08 -4.031745489662604e-08 -4.533969841316077e-08 -4.729279311403539e-08 -4.93853945792582e-08 -4.82693404644727e-08 -4.8548353993169076e-08 -4.9245887814910014e-08 -4.701377958533902e-08 -4.29680834192416e-08 -3.4039650500957626e-08 -2.9156913748771087e-08 -2.7482832576592838e-08 -2.6924805519200093e-08 -2.9017406984422894e-08 -2.7901352869637404e-08 -2.552973787571822e-08 -2.4832204053977286e-08 -2.4832204053977286e-08 -2.455319052528091e-08 -2.4274176996584538e-08 -2.4413683760932724e-08 -2.46926972896291e-08 -2.4971710818325472e-08 -1.771735907221975e-08 -2.4971710818325472e-08 -2.8598886691378335e-08 -2.9714940806163832e-08 -3.0970501685297515e-08 -2.9993954334860204e-08 -2.985444757051202e-08 -3.027296786355658e-08 -2.873839345572652e-08 -2.5948258168762783e-08 -2.050749435918349e-08 -1.7438345543523375e-08 -1.6322291428737878e-08 -1.6182784664389692e-08 -1.729883877917519e-08 -1.6601304957434254e-08 -2.6645791990503717e-08 -2.5390231111370035e-08 -2.5390231111370035e-08 -2.455319052528091e-08 -2.46926972896291e-08 -2.4413683760932724e-08 -2.3995163467888165e-08 -2.246058906005811e-08 -2.455319052528091e-08 -3.013346109920839e-08 -3.4318664029654005e-08 -3.710879931661774e-08 -3.7666826374010495e-08 -3.6550772259225e-08 -3.557422490878769e-08 -3.487669108704675e-08 -3.348162344356488e-08 -3.1947049035734825e-08 -2.9296420513119273e-08 -2.706431228354828e-08 -2.6924805519200093e-08 -2.6645791990503717e-08 -2.7482832576592838e-08 -2.7622339340941025e-08 -2.6366778461807345e-08 -2.3995163467888165e-08 -2.4832204053977286e-08 -2.3995163467888165e-08 -2.413467023223635e-08 -2.3995163467888165e-08 -2.315812288179904e-08 -2.14840417096208e-08 -2.0926014652228048e-08 -2.1763055238317172e-08 -2.3995163467888165e-08 -2.5948258168762783e-08 -2.6645791990503717e-08 -2.7343325812244652e-08 -2.7901352869637404e-08 -2.6785298754851907e-08 -2.6366778461807345e-08 -2.5390231111370035e-08 -2.46926972896291e-08 -2.3995163467888165e-08 -2.3437136410495414e-08 -2.3297629646147227e-08 -2.4971710818325472e-08 -2.5111217582673662e-08 -2.46926972896291e-08 -2.2739602588754482e-08 -2.385565670353998e-08 -2.3437136410495414e-08 -2.3995163467888165e-08 -2.3995163467888165e-08 -2.4971710818325472e-08 -2.8598886691378335e-08 -2.552973787571822e-08 -3.7806333138358674e-08 -4.087548195401879e-08 -4.2828576654893406e-08 -4.436315106272346e-08 -4.115449548271517e-08 -4.310759018358978e-08 -4.310759018358978e-08 -4.087548195401879e-08 -3.390014373660944e-08 -2.3576643174843603e-08 -1.8972919951353434e-08 -1.7996372600916123e-08 -1.813587936526431e-08 -1.9949467301790744e-08 -1.7019825250478813e-08 -2.650628522615553e-08 -2.3716149939191793e-08 -2.385565670353998e-08 -2.385565670353998e-08 -2.3995163467888165e-08 -2.3716149939191793e-08 -2.4274176996584538e-08 -2.804085963398559e-08 -2.5390231111370035e-08 -3.724830608096593e-08 -4.087548195401879e-08 -4.2828576654893406e-08 -4.436315106272346e-08 -4.101498871836698e-08 -4.324709694793797e-08 -4.3386603712286164e-08 -4.115449548271517e-08 -3.445817079400219e-08 -2.3716149939191793e-08 -1.9949467301790744e-08 -1.953094700874618e-08 -1.9670453773094368e-08 -2.1344534945272613e-08 -1.813587936526431e-08 -2.845937992703015e-08 -2.4832204053977286e-08 -2.4971710818325472e-08 -2.385565670353998e-08 -2.3995163467888165e-08 -2.4274176996584538e-08 -2.5250724347021848e-08 -2.873839345572652e-08 -2.5808751404414597e-08 -3.8085346667055053e-08 -4.157301577575972e-08 -4.310759018358978e-08 -4.436315106272346e-08 -4.0735975189670606e-08 -4.2410056361848854e-08 -4.29680834192416e-08 -4.045696166097423e-08 -3.362113020791307e-08 -2.3716149939191793e-08 -1.9251933480049806e-08 -1.855439965830887e-08 -1.8833413187005247e-08 -2.0367987594835303e-08 -1.82753861296125e-08 -2.7761846105289214e-08 -2.413467023223635e-08 -2.4413683760932724e-08 -2.3437136410495414e-08 -2.3995163467888165e-08 -2.3437136410495414e-08 -2.385565670353998e-08 -2.7622339340941025e-08 -2.5111217582673662e-08 -3.682978578792137e-08 -4.059646842532242e-08 -4.2689069890545226e-08 -4.422364429837528e-08 -4.129400224706335e-08 -4.3526110476634344e-08 -4.3805124005330716e-08 -4.1433509011411543e-08 -3.5295211380091315e-08 -2.46926972896291e-08 -2.0228480830487117e-08 -1.9670453773094368e-08 -1.9809960537442554e-08 -2.1344534945272613e-08 -1.911242671570162e-08 -2.8180366398333776e-08 -2.4971710818325472e-08 -2.4971710818325472e-08 -2.413467023223635e-08 -2.3995163467888165e-08 -2.4274176996584538e-08 -2.4413683760932724e-08 -2.6785298754851907e-08 -2.3018616117450855e-08 -3.320260991486851e-08 -3.6690279023573184e-08 -3.822485343140324e-08 -3.8782880488795985e-08 -3.5713731673135874e-08 -3.6550772259225e-08 -3.5992745201832246e-08 -3.362113020791307e-08 -2.845937992703015e-08 -2.2321082295709924e-08 -1.8972919951353434e-08 -1.82753861296125e-08 -1.8414892893960685e-08 -1.9670453773094368e-08 -1.82753861296125e-08 -2.8877900220074708e-08 -2.5669244640066407e-08 -2.5111217582673662e-08 -2.385565670353998e-08 -2.3995163467888165e-08 -2.413467023223635e-08 -2.3018616117450855e-08 -2.2042068767013544e-08 -2.4274176996584538e-08 -2.985444757051202e-08 -3.4318664029654005e-08 -3.696929255226956e-08 -3.794583990270687e-08 -3.6550772259225e-08 -3.515570461574312e-08 -3.487669108704675e-08 -3.362113020791307e-08 -3.1947049035734825e-08 -2.9017406984422894e-08 -2.7482832576592838e-08 -2.7203819047896466e-08 -2.650628522615553e-08 -2.6924805519200093e-08 -2.706431228354828e-08 -2.608776493311097e-08 -2.413467023223635e-08 -2.4832204053977286e-08 -2.3995163467888165e-08 -2.3576643174843603e-08 -2.3716149939191793e-08 -2.3297629646147227e-08 -2.246058906005811e-08 -2.2739602588754482e-08 -2.3995163467888165e-08 -2.5808751404414597e-08 -2.7761846105289214e-08 -2.845937992703015e-08 -2.8598886691378335e-08 -2.804085963398559e-08 -2.6924805519200093e-08 -2.5808751404414597e-08 -2.552973787571822e-08 -2.5250724347021848e-08 -2.4274176996584538e-08 -2.4413683760932724e-08 -2.4413683760932724e-08 -2.5111217582673662e-08 -2.5390231111370035e-08 -2.4413683760932724e-08 -2.413467023223635e-08 -2.4832204053977286e-08 -2.3995163467888165e-08 -2.3576643174843603e-08 -2.3716149939191793e-08 -2.3297629646147227e-08 -2.246058906005811e-08 -2.2739602588754482e-08 -2.3995163467888165e-08 -2.5808751404414597e-08 -2.7761846105289214e-08 -2.845937992703015e-08 -2.8598886691378335e-08 -2.804085963398559e-08 -2.6924805519200093e-08 -2.5808751404414597e-08 -2.552973787571822e-08 -2.5250724347021848e-08 -2.4274176996584538e-08 -2.4413683760932724e-08 -2.4413683760932724e-08 -2.5111217582673662e-08 -2.5390231111370035e-08 -2.4413683760932724e-08 -2.315812288179904e-08 -2.3576643174843603e-08 -2.3297629646147227e-08 -2.3716149939191793e-08 -2.3018616117450855e-08 -2.3576643174843603e-08 -2.7343325812244652e-08 -2.5111217582673662e-08 -3.710879931661774e-08 -4.0735975189670606e-08 -4.2828576654893406e-08 -4.408413753402709e-08 -4.0735975189670606e-08 -4.324709694793797e-08 -4.324709694793797e-08 -4.129400224706335e-08 -3.4318664029654005e-08 -2.385565670353998e-08 -1.9391440244397992e-08 -1.855439965830887e-08 -1.8414892893960685e-08 -1.953094700874618e-08 -1.7438345543523375e-08 -2.650628522615553e-08 -2.315812288179904e-08 -2.3437136410495414e-08 -2.2739602588754482e-08 -2.2739602588754482e-08 -2.3437136410495414e-08 -2.3297629646147227e-08 -2.7203819047896466e-08 -2.5390231111370035e-08 -3.794583990270687e-08 -4.157301577575972e-08 -4.366561724098254e-08 -4.533969841316077e-08 -4.1712522540107916e-08 -4.3386603712286164e-08 -4.366561724098254e-08 -4.1433509011411543e-08 -3.459767755835038e-08 -2.455319052528091e-08 -2.0647001123531675e-08 -1.9809960537442554e-08 -1.8833413187005247e-08 -2.0228480830487117e-08 -1.8414892893960685e-08 -2.804085963398559e-08 -2.6924805519200093e-08 -2.6785298754851907e-08 -2.5669244640066407e-08 -2.650628522615553e-08 -2.6645791990503717e-08 -2.4971710818325472e-08 -2.8180366398333776e-08 -2.552973787571822e-08 -3.7666826374010495e-08 -4.1433509011411543e-08 -4.3386603712286164e-08 -4.50606848844644e-08 -4.1852029304456096e-08 -4.394463076967891e-08 -4.408413753402709e-08 -4.1852029304456096e-08 -3.54347181444395e-08 -2.4971710818325472e-08 -2.0228480830487117e-08 -1.911242671570162e-08 -1.9251933480049806e-08 -2.0228480830487117e-08 -1.8414892893960685e-08 -2.7343325812244652e-08 -2.385565670353998e-08 -2.413467023223635e-08 -2.3297629646147227e-08 -2.3437136410495414e-08 -2.385565670353998e-08 -2.3576643174843603e-08 -2.6227271697459155e-08 -2.3437136410495414e-08 -3.4318664029654005e-08 -3.7806333138358674e-08 -3.948041431053692e-08 -4.031745489662604e-08 -3.682978578792137e-08 -3.7806333138358674e-08 -3.710879931661774e-08 -3.417915726530581e-08 -2.873839345572652e-08 -2.2042068767013544e-08 -1.8693906422657058e-08 -1.7996372600916123e-08 -1.7856865836567937e-08 -1.8833413187005247e-08 -1.82753861296125e-08 -2.9017406984422894e-08 -2.5808751404414597e-08 -2.5111217582673662e-08 -2.3297629646147227e-08 -2.2739602588754482e-08 -2.2739602588754482e-08 -2.14840417096208e-08 -2.0926014652228048e-08 -2.3576643174843603e-08 -2.9156913748771087e-08 -3.390014373660944e-08 -3.6411265494876805e-08 -3.7666826374010495e-08 -3.627175873052862e-08 -3.557422490878769e-08 -3.5295211380091315e-08 -3.417915726530581e-08 -3.208655580008301e-08 -2.9575434041815645e-08 -2.7901352869637404e-08 -2.7761846105289214e-08 -2.6785298754851907e-08 -2.6645791990503717e-08 -2.706431228354828e-08 -2.5808751404414597e-08 -2.3576643174843603e-08 -2.385565670353998e-08 -2.315812288179904e-08 -2.287910935310267e-08 -2.3018616117450855e-08 -2.2042068767013544e-08 -2.1344534945272613e-08 -2.287910935310267e-08 -2.455319052528091e-08 -2.608776493311097e-08 -2.8180366398333776e-08 -2.8877900220074708e-08 -2.873839345572652e-08 -2.7901352869637404e-08 -2.6785298754851907e-08 -2.5948258168762783e-08 -2.5111217582673662e-08 -2.5250724347021848e-08 -2.4832204053977286e-08 -2.4971710818325472e-08 -2.455319052528091e-08 -2.4274176996584538e-08 -2.5111217582673662e-08 -2.4274176996584538e-08 -2.2739602588754482e-08 -2.3995163467888165e-08 -2.3297629646147227e-08 -2.3716149939191793e-08 -2.3995163467888165e-08 -2.2739602588754482e-08 -2.650628522615553e-08 -2.4413683760932724e-08 -3.6690279023573184e-08 -4.017794813227786e-08 -4.115449548271517e-08 -4.2689069890545226e-08 -3.920140078184055e-08 -4.1433509011411543e-08 -4.1433509011411543e-08 -3.9759427839233295e-08 -3.348162344356488e-08 -2.287910935310267e-08 -1.8833413187005247e-08 -1.7996372600916123e-08 -1.7019825250478813e-08 -1.7159332014827002e-08 -1.6182784664389692e-08 -2.5250724347021848e-08 -2.3716149939191793e-08 -2.3995163467888165e-08 -2.315812288179904e-08 -2.3716149939191793e-08 -2.413467023223635e-08 -2.385565670353998e-08 -2.7482832576592838e-08 -2.4971710818325472e-08 -3.710879931661774e-08 -4.115449548271517e-08 -4.29680834192416e-08 -4.422364429837528e-08 -4.087548195401879e-08 -4.29680834192416e-08 -4.324709694793797e-08 -4.101498871836698e-08 -3.417915726530581e-08 -2.3437136410495414e-08 -1.8833413187005247e-08 -1.7856865836567937e-08 -1.729883877917519e-08 -1.813587936526431e-08 -1.7438345543523375e-08 -2.6785298754851907e-08 -2.413467023223635e-08 -2.4971710818325472e-08 -2.4274176996584538e-08 -2.413467023223635e-08 -2.4832204053977286e-08 -2.385565670353998e-08 -2.804085963398559e-08 -2.5808751404414597e-08 -3.8085346667055053e-08 -4.1852029304456096e-08 -4.408413753402709e-08 -4.5618711941857144e-08 -4.2549563126197034e-08 -4.408413753402709e-08 -4.408413753402709e-08 -4.227054959750066e-08 -3.5295211380091315e-08 -2.4971710818325472e-08 -2.0926014652228048e-08 -2.008897406613893e-08 -1.8972919951353434e-08 -1.9391440244397992e-08 -1.8833413187005247e-08 -2.8877900220074708e-08 -2.5808751404414597e-08 -2.5111217582673662e-08 -2.4832204053977286e-08 -2.5390231111370035e-08 -2.5669244640066407e-08 -2.4413683760932724e-08 -2.804085963398559e-08 -2.5250724347021848e-08 -3.75273196096623e-08 -4.115449548271517e-08 -4.2828576654893406e-08 -4.422364429837528e-08 -4.101498871836698e-08 -4.29680834192416e-08 -4.310759018358978e-08 -4.087548195401879e-08 -3.445817079400219e-08 -2.413467023223635e-08 -1.9670453773094368e-08 -1.8693906422657058e-08 -1.8972919951353434e-08 -1.8972919951353434e-08 -1.757785230787156e-08 -2.650628522615553e-08 -2.3437136410495414e-08 -2.385565670353998e-08 -2.287910935310267e-08 -2.3018616117450855e-08 -2.287910935310267e-08 -2.2600095824406296e-08 -2.5948258168762783e-08 -2.315812288179904e-08 -3.390014373660944e-08 -3.7387812845314116e-08 -3.9340907546188736e-08 -4.059646842532242e-08 -3.724830608096593e-08 -3.8085346667055053e-08 -3.724830608096593e-08 -3.4039650500957626e-08 -2.8598886691378335e-08 -2.1902562002665358e-08 -1.8414892893960685e-08 -1.757785230787156e-08 -1.6880318486130626e-08 -1.6880318486130626e-08 -1.7159332014827002e-08 -2.7761846105289214e-08 -2.4832204053977286e-08 -2.455319052528091e-08 -2.2600095824406296e-08 -2.2042068767013544e-08 -2.1902562002665358e-08 -2.0647001123531675e-08 -2.078650788787986e-08 -2.3995163467888165e-08 -2.9156913748771087e-08 -3.362113020791307e-08 -3.6411265494876805e-08 -3.75273196096623e-08 -3.613225196618043e-08 -3.557422490878769e-08 -3.4737184322698563e-08 -3.376063697226125e-08 -3.152852874269026e-08 -2.9296420513119273e-08 -2.7343325812244652e-08 -2.7761846105289214e-08 -2.6785298754851907e-08 -2.6227271697459155e-08 -2.6924805519200093e-08 -2.608776493311097e-08 -2.385565670353998e-08 -2.413467023223635e-08 -2.3297629646147227e-08 -2.315812288179904e-08 -2.315812288179904e-08 -2.1623548473968986e-08 -2.0367987594835303e-08 -2.1623548473968986e-08 -2.3576643174843603e-08 -2.5948258168762783e-08 -2.8180366398333776e-08 -2.943592727746746e-08 -2.9575434041815645e-08 -2.845937992703015e-08 -2.7622339340941025e-08 -2.7203819047896466e-08 -2.608776493311097e-08 -2.6227271697459155e-08 -2.5948258168762783e-08 -2.552973787571822e-08 -2.5390231111370035e-08 -2.5390231111370035e-08 -2.6227271697459155e-08 -2.4971710818325472e-08 -2.4413683760932724e-08 -2.5111217582673662e-08 -2.46926972896291e-08 -2.4832204053977286e-08 -2.5111217582673662e-08 -2.4971710818325472e-08 -2.873839345572652e-08 -2.552973787571822e-08 -3.7666826374010495e-08 -4.129400224706335e-08 -4.310759018358978e-08 -4.422364429837528e-08 -4.101498871836698e-08 -4.324709694793797e-08 -4.3526110476634344e-08 -4.1433509011411543e-08 -3.5016197851394936e-08 -2.455319052528091e-08 -2.0367987594835303e-08 -1.9251933480049806e-08 -1.82753861296125e-08 -1.771735907221975e-08 -1.674081172178244e-08 -2.6645791990503717e-08 -2.46926972896291e-08 -2.4971710818325472e-08 -2.413467023223635e-08 -2.4274176996584538e-08 -2.4832204053977286e-08 -2.46926972896291e-08 -2.7901352869637404e-08 -2.5390231111370035e-08 -3.7666826374010495e-08 -4.1712522540107916e-08 -4.3805124005330716e-08 -4.5479205177508965e-08 -4.1852029304456096e-08 -4.3526110476634344e-08 -4.422364429837528e-08 -4.213104283315248e-08 -3.5295211380091315e-08 -2.455319052528091e-08 -1.9949467301790744e-08 -1.855439965830887e-08 -1.7996372600916123e-08 -1.855439965830887e-08 -1.757785230787156e-08 -2.7482832576592838e-08 -2.46926972896291e-08 -2.552973787571822e-08 -2.4832204053977286e-08 -2.4971710818325472e-08 -2.4971710818325472e-08 -2.4832204053977286e-08 -2.8877900220074708e-08 -2.5669244640066407e-08 -3.75273196096623e-08 -4.129400224706335e-08 -4.324709694793797e-08 -4.464216459141985e-08 -4.1712522540107916e-08 -4.310759018358978e-08 -4.3386603712286164e-08 -4.129400224706335e-08 -3.445817079400219e-08 -2.4413683760932724e-08 -1.953094700874618e-08 -1.8414892893960685e-08 -1.82753861296125e-08 -1.855439965830887e-08 -1.771735907221975e-08 -2.7203819047896466e-08 -2.4274176996584538e-08 -2.4274176996584538e-08 -2.3297629646147227e-08 -2.3437136410495414e-08 -2.3576643174843603e-08 -2.3437136410495414e-08 -2.7761846105289214e-08 -2.4971710818325472e-08 -3.710879931661774e-08 -4.0735975189670606e-08 -4.29680834192416e-08 -4.422364429837528e-08 -4.101498871836698e-08 -4.2828576654893406e-08 -4.310759018358978e-08 -4.087548195401879e-08 -3.417915726530581e-08 -2.3995163467888165e-08 -1.9251933480049806e-08 -1.82753861296125e-08 -1.813587936526431e-08 -1.7856865836567937e-08 -1.7438345543523375e-08 -2.7343325812244652e-08 -2.3716149939191793e-08 -2.3995163467888165e-08 -2.2321082295709924e-08 -2.287910935310267e-08 -2.246058906005811e-08 -2.1902562002665358e-08 -2.5111217582673662e-08 -2.2600095824406296e-08 -3.362113020791307e-08 -3.724830608096593e-08 -3.920140078184055e-08 -4.045696166097423e-08 -3.724830608096593e-08 -3.794583990270687e-08 -3.696929255226956e-08 -3.4039650500957626e-08 -2.8598886691378335e-08 -2.1623548473968986e-08 -1.82753861296125e-08 -1.729883877917519e-08 -1.6322291428737878e-08 -1.6043277900041506e-08 -1.6182784664389692e-08 -2.6924805519200093e-08 -2.3995163467888165e-08 -2.3716149939191793e-08 -2.2321082295709924e-08 -2.1763055238317172e-08 -2.1763055238317172e-08 -2.008897406613893e-08 -2.050749435918349e-08 -2.3716149939191793e-08 -2.845937992703015e-08 -3.2644582857475756e-08 -3.5713731673135874e-08 -3.696929255226956e-08 -3.557422490878769e-08 -3.445817079400219e-08 -3.348162344356488e-08 -3.320260991486851e-08 -3.069148815660114e-08 -2.804085963398559e-08 -2.5948258168762783e-08 -2.6366778461807345e-08 -2.552973787571822e-08 -2.5111217582673662e-08 -2.6227271697459155e-08 -2.5808751404414597e-08 -2.3716149939191793e-08 -2.4274176996584538e-08 -2.2739602588754482e-08 -2.2739602588754482e-08 -2.2600095824406296e-08 -2.0647001123531675e-08 -1.9670453773094368e-08 -2.078650788787986e-08 -2.2321082295709924e-08 -2.5111217582673662e-08 -2.7203819047896466e-08 -2.8598886691378335e-08 -2.9017406984422894e-08 -2.873839345572652e-08 -2.804085963398559e-08 -2.8319873162681962e-08 -2.7622339340941025e-08 -2.6924805519200093e-08 -2.6366778461807345e-08 -2.608776493311097e-08 -2.5948258168762783e-08 -2.608776493311097e-08 -2.650628522615553e-08 -2.5390231111370035e-08 -2.3716149939191793e-08 -2.4413683760932724e-08 -2.3716149939191793e-08 -2.3716149939191793e-08 -2.3995163467888165e-08 -2.3716149939191793e-08 -2.7901352869637404e-08 -2.46926972896291e-08 -3.710879931661774e-08 -4.087548195401879e-08 -4.324709694793797e-08 -4.478167135576803e-08 -4.199153606880429e-08 -4.3386603712286164e-08 -4.310759018358978e-08 -4.087548195401879e-08 -3.4039650500957626e-08 -2.385565670353998e-08 -2.008897406613893e-08 -1.953094700874618e-08 -1.813587936526431e-08 -1.757785230787156e-08 -1.674081172178244e-08 -2.6366778461807345e-08 -2.3297629646147227e-08 -2.385565670353998e-08 -2.3018616117450855e-08 -2.3297629646147227e-08 -2.315812288179904e-08 -2.3437136410495414e-08 -2.6645791990503717e-08 -2.455319052528091e-08 -3.682978578792137e-08 -4.059646842532242e-08 -4.310759018358978e-08 -4.464216459141985e-08 -4.115449548271517e-08 -4.2828576654893406e-08 -4.366561724098254e-08 -4.1712522540107916e-08 -3.5016197851394936e-08 -2.455319052528091e-08 -2.008897406613893e-08 -1.8414892893960685e-08 -1.7856865836567937e-08 -1.813587936526431e-08 -1.7159332014827002e-08 -2.6645791990503717e-08 -2.385565670353998e-08 -2.4274176996584538e-08 -2.3576643174843603e-08 -2.3716149939191793e-08 -2.3576643174843603e-08 -2.3716149939191793e-08 -2.7622339340941025e-08 -2.5250724347021848e-08 -3.710879931661774e-08 -4.115449548271517e-08 -4.29680834192416e-08 -4.4502657827071654e-08 -4.129400224706335e-08 -4.2549563126197034e-08 -4.29680834192416e-08 -4.1433509011411543e-08 -3.459767755835038e-08 -2.4274176996584538e-08 -1.9251933480049806e-08 -1.771735907221975e-08 -1.729883877917519e-08 -1.729883877917519e-08 -1.6601304957434254e-08 -2.6645791990503717e-08 -2.4274176996584538e-08 -2.455319052528091e-08 -2.2739602588754482e-08 -2.2739602588754482e-08 -2.3437136410495414e-08 -2.3576643174843603e-08 -2.7482832576592838e-08 -2.4971710818325472e-08 -3.7387812845314116e-08 -4.129400224706335e-08 -4.394463076967891e-08 -4.5479205177508965e-08 -4.2689069890545226e-08 -4.464216459141985e-08 -4.50606848844644e-08 -4.310759018358978e-08 -3.613225196618043e-08 -2.5669244640066407e-08 -2.050749435918349e-08 -1.911242671570162e-08 -1.8693906422657058e-08 -1.813587936526431e-08 -1.7438345543523375e-08 -2.7482832576592838e-08 -2.4413683760932724e-08 -2.455319052528091e-08 -2.2739602588754482e-08 -2.3297629646147227e-08 -2.3018616117450855e-08 -2.246058906005811e-08 -2.5808751404414597e-08 -2.3576643174843603e-08 -3.5295211380091315e-08 -3.906189401749236e-08 -4.129400224706335e-08 -4.213104283315248e-08 -3.86433737244478e-08 -3.948041431053692e-08 -3.8782880488795985e-08 -3.557422490878769e-08 -2.943592727746746e-08 -2.1902562002665358e-08 -1.855439965830887e-08 -1.729883877917519e-08 -1.6601304957434254e-08 -1.6322291428737878e-08 -1.576426437134513e-08 -2.650628522615553e-08 -2.3437136410495414e-08 -2.315812288179904e-08 -2.1902562002665358e-08 -2.14840417096208e-08 -2.1344534945272613e-08 -1.9670453773094368e-08 -1.9670453773094368e-08 -2.246058906005811e-08 -2.7761846105289214e-08 -3.1668035507038446e-08 -3.445817079400219e-08 -3.54347181444395e-08 -3.390014373660944e-08 -3.278408962182394e-08 -3.1947049035734825e-08 -3.152852874269026e-08 -2.9575434041815645e-08 -2.706431228354828e-08 -2.4971710818325472e-08 -2.455319052528091e-08 -2.3995163467888165e-08 -2.3716149939191793e-08 -2.5390231111370035e-08 -2.4971710818325472e-08 -2.287910935310267e-08 -2.3297629646147227e-08 -2.2042068767013544e-08 -2.1902562002665358e-08 -2.14840417096208e-08 -1.9809960537442554e-08 -1.8693906422657058e-08 -1.9391440244397992e-08 -2.078650788787986e-08 -2.315812288179904e-08 -2.4971710818325472e-08 -2.608776493311097e-08 -2.6645791990503717e-08 -2.7203819047896466e-08 -2.6645791990503717e-08 -2.706431228354828e-08 -2.650628522615553e-08 -2.5250724347021848e-08 -2.4832204053977286e-08 -2.4274176996584538e-08 -2.46926972896291e-08 -2.4832204053977286e-08 -2.5808751404414597e-08 -2.5250724347021848e-08 -2.2042068767013544e-08 -2.246058906005811e-08 -2.14840417096208e-08 -2.1623548473968986e-08 -2.1902562002665358e-08 -2.106552141657624e-08 -2.552973787571822e-08 -2.3576643174843603e-08 -3.613225196618043e-08 -3.948041431053692e-08 -4.199153606880429e-08 -4.3805124005330716e-08 -4.0735975189670606e-08 -4.2410056361848854e-08 -4.213104283315248e-08 -4.017794813227786e-08 -3.362113020791307e-08 -2.3297629646147227e-08 -1.911242671570162e-08 -1.855439965830887e-08 -1.7159332014827002e-08 -1.7019825250478813e-08 -1.6601304957434254e-08 -2.7203819047896466e-08 -2.455319052528091e-08 -2.4413683760932724e-08 -2.3995163467888165e-08 -2.4832204053977286e-08 -2.46926972896291e-08 -2.413467023223635e-08 -2.7622339340941025e-08 -2.4971710818325472e-08 -3.7387812845314116e-08 -4.101498871836698e-08 -4.29680834192416e-08 -4.436315106272346e-08 -4.115449548271517e-08 -4.310759018358978e-08 -4.366561724098254e-08 -4.157301577575972e-08 -3.5016197851394936e-08 -2.4413683760932724e-08 -2.008897406613893e-08 -1.8414892893960685e-08 -1.7019825250478813e-08 -1.6880318486130626e-08 -1.7159332014827002e-08 -2.6924805519200093e-08 -2.4274176996584538e-08 -2.3995163467888165e-08 -2.287910935310267e-08 -2.3018616117450855e-08 -2.3018616117450855e-08 -2.2321082295709924e-08 -2.650628522615553e-08 -2.46926972896291e-08 -3.6690279023573184e-08 -4.059646842532242e-08 -4.2549563126197034e-08 -4.394463076967891e-08 -4.0735975189670606e-08 -4.2410056361848854e-08 -4.310759018358978e-08 -4.157301577575972e-08 -3.5016197851394936e-08 -2.455319052528091e-08 -1.9391440244397992e-08 -1.7856865836567937e-08 -1.7019825250478813e-08 -1.674081172178244e-08 -1.7159332014827002e-08 -2.7761846105289214e-08 -2.5111217582673662e-08 -2.4971710818325472e-08 -2.3716149939191793e-08 -2.3716149939191793e-08 -2.4274176996584538e-08 -2.3716149939191793e-08 -2.7343325812244652e-08 -2.4832204053977286e-08 -3.696929255226956e-08 -4.101498871836698e-08 -4.3386603712286164e-08 -4.50606848844644e-08 -4.2828576654893406e-08 -4.4502657827071654e-08 -4.478167135576803e-08 -4.29680834192416e-08 -3.6411265494876805e-08 -2.5669244640066407e-08 -2.078650788787986e-08 -1.9251933480049806e-08 -1.8693906422657058e-08 -1.82753861296125e-08 -1.7996372600916123e-08 -2.8180366398333776e-08 -2.455319052528091e-08 -2.455319052528091e-08 -2.3437136410495414e-08 -2.385565670353998e-08 -2.385565670353998e-08 -2.385565670353998e-08 -2.7622339340941025e-08 -2.4274176996584538e-08 -3.585323843748406e-08 -3.948041431053692e-08 -4.1712522540107916e-08 -4.310759018358978e-08 -3.9759427839233295e-08 -4.045696166097423e-08 -3.9759427839233295e-08 -3.627175873052862e-08 -2.9993954334860204e-08 -2.2321082295709924e-08 -1.8833413187005247e-08 -1.757785230787156e-08 -1.7019825250478813e-08 -1.6461798193086064e-08 -1.6043277900041506e-08 -2.6785298754851907e-08 -2.3995163467888165e-08 -2.3995163467888165e-08 -2.3018616117450855e-08 -2.2739602588754482e-08 -2.218157553136173e-08 -2.0926014652228048e-08 -2.0367987594835303e-08 -2.3576643174843603e-08 -2.9017406984422894e-08 -3.3342116679216694e-08 -3.5713731673135874e-08 -3.682978578792137e-08 -3.487669108704675e-08 -3.376063697226125e-08 -3.278408962182394e-08 -3.1668035507038446e-08 -3.013346109920839e-08 -2.7482832576592838e-08 -2.5808751404414597e-08 -2.5390231111370035e-08 -2.5669244640066407e-08 -2.4832204053977286e-08 -2.5808751404414597e-08 -2.4832204053977286e-08 -2.2739602588754482e-08 -2.315812288179904e-08 -2.218157553136173e-08 -2.2042068767013544e-08 -2.1763055238317172e-08 -2.050749435918349e-08 -1.9251933480049806e-08 -2.050749435918349e-08 -2.2042068767013544e-08 -2.385565670353998e-08 -2.5808751404414597e-08 -2.7343325812244652e-08 -2.804085963398559e-08 -2.8180366398333776e-08 -2.7761846105289214e-08 -2.7761846105289214e-08 -2.650628522615553e-08 -2.5390231111370035e-08 -2.46926972896291e-08 -2.3995163467888165e-08 -2.4413683760932724e-08 -2.413467023223635e-08 -2.5250724347021848e-08 -2.4971710818325472e-08 -2.218157553136173e-08 -2.2739602588754482e-08 -2.2042068767013544e-08 -2.2321082295709924e-08 -2.2600095824406296e-08 -2.1763055238317172e-08 -2.5669244640066407e-08 -2.3995163467888165e-08 -3.6411265494876805e-08 -4.003844136792967e-08 -4.2549563126197034e-08 -4.436315106272346e-08 -4.129400224706335e-08 -4.3526110476634344e-08 -4.366561724098254e-08 -4.115449548271517e-08 -3.4318664029654005e-08 -2.3995163467888165e-08 -1.8972919951353434e-08 -1.82753861296125e-08 -1.7438345543523375e-08 -1.7019825250478813e-08 -1.6880318486130626e-08 -2.7622339340941025e-08 -2.5250724347021848e-08 -2.5390231111370035e-08 -2.5390231111370035e-08 -2.5669244640066407e-08 -2.5669244640066407e-08 -2.4832204053977286e-08 -2.873839345572652e-08 -2.5948258168762783e-08 -3.8364360195751426e-08 -4.227054959750066e-08 -4.4502657827071654e-08 -4.575821870620534e-08 -4.2410056361848854e-08 -4.436315106272346e-08 -4.478167135576803e-08 -4.29680834192416e-08 -3.6411265494876805e-08 -2.6227271697459155e-08 -2.1344534945272613e-08 -2.008897406613893e-08 -1.8833413187005247e-08 -1.82753861296125e-08 -1.813587936526431e-08 -2.9575434041815645e-08 -2.6785298754851907e-08 -2.706431228354828e-08 -2.6366778461807345e-08 -2.6924805519200093e-08 -2.608776493311097e-08 -2.5111217582673662e-08 -2.8877900220074708e-08 -2.552973787571822e-08 -3.8085346667055053e-08 -4.157301577575972e-08 -4.3805124005330716e-08 -4.520019164881259e-08 -4.1852029304456096e-08 -4.3805124005330716e-08 -4.408413753402709e-08 -4.199153606880429e-08 -3.5295211380091315e-08 -2.5111217582673662e-08 -2.0228480830487117e-08 -1.8972919951353434e-08 -1.855439965830887e-08 -1.855439965830887e-08 -1.82753861296125e-08 -2.9296420513119273e-08 -2.6227271697459155e-08 -2.650628522615553e-08 -2.5669244640066407e-08 -2.4971710818325472e-08 -2.552973787571822e-08 -2.413467023223635e-08 -2.7901352869637404e-08 -2.5111217582673662e-08 -3.724830608096593e-08 -4.087548195401879e-08 -4.2689069890545226e-08 -4.422364429837528e-08 -4.1852029304456096e-08 -4.3386603712286164e-08 -4.366561724098254e-08 -4.199153606880429e-08 -3.5713731673135874e-08 -2.5250724347021848e-08 -2.078650788787986e-08 -1.9251933480049806e-08 -1.911242671570162e-08 -1.855439965830887e-08 -1.7996372600916123e-08 -2.7901352869637404e-08 -2.4413683760932724e-08 -2.4274176996584538e-08 -2.3576643174843603e-08 -2.3995163467888165e-08 -2.385565670353998e-08 -2.4274176996584538e-08 -2.8319873162681962e-08 -2.455319052528091e-08 -3.5992745201832246e-08 -3.961992107488511e-08 -4.213104283315248e-08 -4.3386603712286164e-08 -4.003844136792967e-08 -4.059646842532242e-08 -3.961992107488511e-08 -3.5992745201832246e-08 -2.985444757051202e-08 -2.246058906005811e-08 -1.8972919951353434e-08 -1.7856865836567937e-08 -1.7159332014827002e-08 -1.6322291428737878e-08 -1.6043277900041506e-08 -2.6924805519200093e-08 -2.4274176996584538e-08 -2.455319052528091e-08 -2.385565670353998e-08 -2.3018616117450855e-08 -2.2739602588754482e-08 -2.1205028180924427e-08 -2.0926014652228048e-08 -2.385565670353998e-08 -2.9017406984422894e-08 -3.3342116679216694e-08 -3.613225196618043e-08 -3.710879931661774e-08 -3.557422490878769e-08 -3.4318664029654005e-08 -3.320260991486851e-08 -3.250507609312757e-08 -3.0551981392252956e-08 -2.7901352869637404e-08 -2.6645791990503717e-08 -2.5948258168762783e-08 -2.7203819047896466e-08 -2.5808751404414597e-08 -2.608776493311097e-08 -2.5390231111370035e-08 -2.3018616117450855e-08 -2.3995163467888165e-08 -2.3018616117450855e-08 -2.2600095824406296e-08 -2.14840417096208e-08 -2.050749435918349e-08 -1.953094700874618e-08 -2.0926014652228048e-08 -2.246058906005811e-08 -2.3995163467888165e-08 -2.608776493311097e-08 -2.7622339340941025e-08 -2.8319873162681962e-08 -2.8319873162681962e-08 -2.7622339340941025e-08 -2.706431228354828e-08 -2.608776493311097e-08 -2.4971710818325472e-08 -2.3995163467888165e-08 -2.3576643174843603e-08 -2.287910935310267e-08 -2.218157553136173e-08 -2.315812288179904e-08 -2.3297629646147227e-08 -2.1623548473968986e-08 -2.287910935310267e-08 -2.2321082295709924e-08 -2.2739602588754482e-08 -2.3018616117450855e-08 -2.218157553136173e-08 -2.6227271697459155e-08 -2.3995163467888165e-08 -3.5992745201832246e-08 -3.9759427839233295e-08 -4.1852029304456096e-08 -4.3386603712286164e-08 -4.101498871836698e-08 -4.3526110476634344e-08 -4.394463076967891e-08 -4.129400224706335e-08 -3.487669108704675e-08 -2.4971710818325472e-08 -1.953094700874618e-08 -1.855439965830887e-08 -1.7438345543523375e-08 -1.6601304957434254e-08 -1.6322291428737878e-08 -2.6227271697459155e-08 -2.3576643174843603e-08 -2.413467023223635e-08 -2.3576643174843603e-08 -2.3716149939191793e-08 -2.385565670353998e-08 -2.315812288179904e-08 -2.706431228354828e-08 -2.4971710818325472e-08 -3.724830608096593e-08 -4.115449548271517e-08 -4.3526110476634344e-08 -4.492117812011622e-08 -4.157301577575972e-08 -4.3805124005330716e-08 -4.3805124005330716e-08 -4.227054959750066e-08 -3.613225196618043e-08 -2.6227271697459155e-08 -2.106552141657624e-08 -2.008897406613893e-08 -1.9391440244397992e-08 -1.8693906422657058e-08 -1.82753861296125e-08 -3.0551981392252956e-08 -2.7761846105289214e-08 -2.845937992703015e-08 -2.7622339340941025e-08 -2.8180366398333776e-08 -2.6785298754851907e-08 -2.552973787571822e-08 -2.9296420513119273e-08 -2.5390231111370035e-08 -3.7806333138358674e-08 -4.157301577575972e-08 -4.366561724098254e-08 -4.520019164881259e-08 -4.1852029304456096e-08 -4.366561724098254e-08 -4.422364429837528e-08 -4.2410056361848854e-08 -3.5713731673135874e-08 -2.552973787571822e-08 -2.0647001123531675e-08 -1.953094700874618e-08 -1.8972919951353434e-08 -1.8414892893960685e-08 -1.7856865836567937e-08 -2.873839345572652e-08 -2.5669244640066407e-08 -2.5808751404414597e-08 -2.4971710818325472e-08 -2.4832204053977286e-08 -2.552973787571822e-08 -2.4413683760932724e-08 -2.7901352869637404e-08 -2.5111217582673662e-08 -3.7806333138358674e-08 -4.1852029304456096e-08 -4.3805124005330716e-08 -4.520019164881259e-08 -4.2549563126197034e-08 -4.4502657827071654e-08 -4.4502657827071654e-08 -4.29680834192416e-08 -3.6690279023573184e-08 -2.608776493311097e-08 -2.1344534945272613e-08 -1.9670453773094368e-08 -1.9251933480049806e-08 -1.855439965830887e-08 -1.757785230787156e-08 -2.7761846105289214e-08 -2.4274176996584538e-08 -2.413467023223635e-08 -2.3437136410495414e-08 -2.385565670353998e-08 -2.3995163467888165e-08 -2.385565670353998e-08 -2.7482832576592838e-08 -2.4274176996584538e-08 -3.5992745201832246e-08 -3.961992107488511e-08 -4.213104283315248e-08 -4.2828576654893406e-08 -3.989893460358149e-08 -4.017794813227786e-08 -3.9340907546188736e-08 -3.557422490878769e-08 -3.013346109920839e-08 -2.315812288179904e-08 -1.953094700874618e-08 -1.8833413187005247e-08 -1.82753861296125e-08 -1.7019825250478813e-08 -1.6043277900041506e-08 -2.706431228354828e-08 -2.4413683760932724e-08 -2.4832204053977286e-08 -2.385565670353998e-08 -2.315812288179904e-08 -2.287910935310267e-08 -2.14840417096208e-08 -2.1205028180924427e-08 -2.3995163467888165e-08 -2.943592727746746e-08 -3.4318664029654005e-08 -3.682978578792137e-08 -3.6690279023573184e-08 -3.5713731673135874e-08 -3.487669108704675e-08 -3.390014373660944e-08 -3.292359638617213e-08 -3.124951521399389e-08 -2.8319873162681962e-08 -2.7203819047896466e-08 -2.650628522615553e-08 -2.6785298754851907e-08 -2.650628522615553e-08 -2.7482832576592838e-08 -2.7203819047896466e-08 -2.4971710818325472e-08 -2.5948258168762783e-08 -2.4971710818325472e-08 -2.46926972896291e-08 -2.2321082295709924e-08 -2.106552141657624e-08 -1.9949467301790744e-08 -2.0228480830487117e-08 -2.3018616117450855e-08 -2.455319052528091e-08 -2.7343325812244652e-08 -2.873839345572652e-08 -2.943592727746746e-08 -2.8319873162681962e-08 -2.7901352869637404e-08 -2.706431228354828e-08 -2.6645791990503717e-08 -2.46926972896291e-08 -2.3995163467888165e-08 -2.3995163467888165e-08 -2.315812288179904e-08 -2.3297629646147227e-08 -2.4413683760932724e-08 -2.413467023223635e-08 -2.2600095824406296e-08 -2.3576643174843603e-08 -2.3297629646147227e-08 -2.3018616117450855e-08 -2.315812288179904e-08 -2.2600095824406296e-08 -2.608776493311097e-08 -2.3437136410495414e-08 -3.5016197851394936e-08 -3.8782880488795985e-08 -4.115449548271517e-08 -4.2689069890545226e-08 -4.017794813227786e-08 -4.2549563126197034e-08 -4.2828576654893406e-08 -4.101498871836698e-08 -3.487669108704675e-08 -2.455319052528091e-08 -1.9391440244397992e-08 -1.7856865836567937e-08 -1.674081172178244e-08 -1.590377113569332e-08 -1.5485250842648757e-08 -2.5808751404414597e-08 -2.3297629646147227e-08 -2.3995163467888165e-08 -2.287910935310267e-08 -2.287910935310267e-08 -2.3297629646147227e-08 -2.3018616117450855e-08 -2.650628522615553e-08 -2.3995163467888165e-08 -3.5713731673135874e-08 -3.906189401749236e-08 -4.1433509011411543e-08 -4.310759018358978e-08 -4.031745489662604e-08 -4.2689069890545226e-08 -4.29680834192416e-08 -4.1433509011411543e-08 -3.5295211380091315e-08 -2.4971710818325472e-08 -2.008897406613893e-08 -1.8693906422657058e-08 -1.8414892893960685e-08 -1.771735907221975e-08 -1.7438345543523375e-08 -2.943592727746746e-08 -2.6924805519200093e-08 -2.7482832576592838e-08 -2.650628522615553e-08 -2.6227271697459155e-08 -2.5808751404414597e-08 -2.5111217582673662e-08 -2.8598886691378335e-08 -2.4413683760932724e-08 -3.6550772259225e-08 -4.017794813227786e-08 -4.227054959750066e-08 -4.3526110476634344e-08 -4.045696166097423e-08 -4.227054959750066e-08 -4.310759018358978e-08 -4.157301577575972e-08 -3.54347181444395e-08 -2.552973787571822e-08 -2.0367987594835303e-08 -1.911242671570162e-08 -1.8414892893960685e-08 -1.771735907221975e-08 -1.6461798193086064e-08 -2.6924805519200093e-08 -2.413467023223635e-08 -2.413467023223635e-08 -2.3297629646147227e-08 -2.3995163467888165e-08 -2.413467023223635e-08 -2.413467023223635e-08 -2.7761846105289214e-08 -2.4413683760932724e-08 -3.6550772259225e-08 -4.017794813227786e-08 -4.2410056361848854e-08 -4.366561724098254e-08 -4.101498871836698e-08 -4.2689069890545226e-08 -4.2549563126197034e-08 -4.115449548271517e-08 -3.515570461574312e-08 -2.552973787571822e-08 -2.106552141657624e-08 -1.953094700874618e-08 -1.9251933480049806e-08 -1.953094700874618e-08 -1.8833413187005247e-08 -3.041247462790477e-08 -2.6645791990503717e-08 -2.6227271697459155e-08 -2.5250724347021848e-08 -2.552973787571822e-08 -2.5948258168762783e-08 -2.5250724347021848e-08 -2.8319873162681962e-08 -2.413467023223635e-08 -3.5295211380091315e-08 -3.850386696009961e-08 -4.031745489662604e-08 -4.101498871836698e-08 -3.850386696009961e-08 -3.8782880488795985e-08 -3.794583990270687e-08 -3.487669108704675e-08 -2.985444757051202e-08 -2.315812288179904e-08 -1.9251933480049806e-08 -1.8693906422657058e-08 -1.7996372600916123e-08 -1.7159332014827002e-08 -1.674081172178244e-08 -2.845937992703015e-08 -2.5111217582673662e-08 -2.4971710818325472e-08 -2.3576643174843603e-08 -2.315812288179904e-08 -2.3018616117450855e-08 -2.218157553136173e-08 -2.1344534945272613e-08 -2.413467023223635e-08 -2.943592727746746e-08 -3.4039650500957626e-08 -3.5992745201832246e-08 -3.585323843748406e-08 -3.487669108704675e-08 -3.4039650500957626e-08 -3.3342116679216694e-08 -3.22260625644312e-08 -3.1668035507038446e-08 -2.8598886691378335e-08 -2.7482832576592838e-08 -2.7622339340941025e-08 -2.6924805519200093e-08 -2.7203819047896466e-08 -2.9156913748771087e-08 -2.8319873162681962e-08 -2.6645791990503717e-08 -2.7203819047896466e-08 -2.6227271697459155e-08 -2.5808751404414597e-08 -2.3995163467888165e-08 -2.287910935310267e-08 -2.1344534945272613e-08 -2.1902562002665358e-08 -2.5808751404414597e-08 -2.6645791990503717e-08 -2.9156913748771087e-08 -3.013346109920839e-08 -3.013346109920839e-08 -2.845937992703015e-08 -2.7901352869637404e-08 -2.804085963398559e-08 -2.7482832576592838e-08 -2.5669244640066407e-08 -2.5111217582673662e-08 -2.552973787571822e-08 -2.46926972896291e-08 -2.46926972896291e-08 -2.608776493311097e-08 -2.5390231111370035e-08 -2.3576643174843603e-08 -2.4274176996584538e-08 -2.3995163467888165e-08 -2.3297629646147227e-08 -2.315812288179904e-08 -2.3297629646147227e-08 -2.5808751404414597e-08 -2.246058906005811e-08 -3.3342116679216694e-08 -3.696929255226956e-08 -3.920140078184055e-08 -4.0735975189670606e-08 -3.8782880488795985e-08 -4.031745489662604e-08 -4.045696166097423e-08 -3.906189401749236e-08 -3.348162344356488e-08 -2.385565670353998e-08 -1.9391440244397992e-08 -1.7856865836567937e-08 -1.7019825250478813e-08 -1.6322291428737878e-08 -1.576426437134513e-08 -2.6924805519200093e-08 -2.455319052528091e-08 -2.5111217582673662e-08 -2.413467023223635e-08 -2.413467023223635e-08 -2.46926972896291e-08 -2.455319052528091e-08 -2.706431228354828e-08 -2.385565670353998e-08 -3.417915726530581e-08 -3.7387812845314116e-08 -3.948041431053692e-08 -4.087548195401879e-08 -3.892238725314418e-08 -4.045696166097423e-08 -4.059646842532242e-08 -3.9340907546188736e-08 -3.376063697226125e-08 -2.385565670353998e-08 -1.9670453773094368e-08 -1.7996372600916123e-08 -1.757785230787156e-08 -1.771735907221975e-08 -1.6880318486130626e-08 -2.804085963398559e-08 -2.5669244640066407e-08 -2.6227271697459155e-08 -2.5948258168762783e-08 -2.5250724347021848e-08 -2.5390231111370035e-08 -2.5390231111370035e-08 -2.8180366398333776e-08 -2.3576643174843603e-08 -3.445817079400219e-08 -3.7806333138358674e-08 -3.9759427839233295e-08 -4.087548195401879e-08 -3.8364360195751426e-08 -3.989893460358149e-08 -3.989893460358149e-08 -3.850386696009961e-08 -3.348162344356488e-08 -2.46926972896291e-08 -1.9670453773094368e-08 -1.8414892893960685e-08 -1.7996372600916123e-08 -1.771735907221975e-08 -1.6322291428737878e-08 -2.650628522615553e-08 -2.3995163467888165e-08 -2.4274176996584538e-08 -2.3716149939191793e-08 -2.385565670353998e-08 -2.413467023223635e-08 -2.413467023223635e-08 -2.7482832576592838e-08 -2.3018616117450855e-08 -3.348162344356488e-08 -3.6411265494876805e-08 -3.850386696009961e-08 -3.948041431053692e-08 -3.7666826374010495e-08 -3.892238725314418e-08 -3.906189401749236e-08 -3.7387812845314116e-08 -3.208655580008301e-08 -2.3995163467888165e-08 -2.008897406613893e-08 -1.8833413187005247e-08 -1.7996372600916123e-08 -1.8414892893960685e-08 -1.8414892893960685e-08 -2.985444757051202e-08 -2.706431228354828e-08 -2.6645791990503717e-08 -2.5808751404414597e-08 -2.5669244640066407e-08 -2.608776493311097e-08 -2.5669244640066407e-08 -2.7761846105289214e-08 -2.2739602588754482e-08 -3.22260625644312e-08 -3.557422490878769e-08 -3.710879931661774e-08 -3.7806333138358674e-08 -3.5713731673135874e-08 -3.585323843748406e-08 -3.5295211380091315e-08 -3.208655580008301e-08 -2.7761846105289214e-08 -2.1902562002665358e-08 -1.813587936526431e-08 -1.674081172178244e-08 -1.6182784664389692e-08 -1.590377113569332e-08 -1.6043277900041506e-08 -2.7343325812244652e-08 -2.4413683760932724e-08 -2.4413683760932724e-08 -2.3576643174843603e-08 -2.287910935310267e-08 -2.2600095824406296e-08 -2.218157553136173e-08 -2.1205028180924427e-08 -2.2600095824406296e-08 -2.7203819047896466e-08 -3.0970501685297515e-08 -3.3063103150520315e-08 -3.376063697226125e-08 -3.362113020791307e-08 -3.2644582857475756e-08 -3.208655580008301e-08 -3.1389021978342073e-08 -3.069148815660114e-08 -2.845937992703015e-08 -2.6924805519200093e-08 -2.7203819047896466e-08 -2.6227271697459155e-08 -2.6645791990503717e-08 -2.7901352869637404e-08 -2.8180366398333776e-08 -2.7343325812244652e-08 -2.8598886691378335e-08 -2.8598886691378335e-08 -2.8319873162681962e-08 -2.7622339340941025e-08 -2.6366778461807345e-08 -2.46926972896291e-08 -2.4832204053977286e-08 -2.706431228354828e-08 -2.804085963398559e-08 -2.9156913748771087e-08 -2.985444757051202e-08 -2.9993954334860204e-08 -2.943592727746746e-08 -2.804085963398559e-08 -2.8598886691378335e-08 -2.8598886691378335e-08 -2.7622339340941025e-08 -2.7622339340941025e-08 -2.7622339340941025e-08 -2.6785298754851907e-08 -2.608776493311097e-08 -2.706431228354828e-08 -2.6366778461807345e-08 -2.4274176996584538e-08 -2.46926972896291e-08 -2.3716149939191793e-08 -2.3437136410495414e-08 -2.3297629646147227e-08 -2.385565670353998e-08 -2.5390231111370035e-08 -2.0926014652228048e-08 -3.041247462790477e-08 -3.390014373660944e-08 -3.5016197851394936e-08 -3.6411265494876805e-08 -3.515570461574312e-08 -3.627175873052862e-08 -3.613225196618043e-08 -3.515570461574312e-08 -3.069148815660114e-08 -2.287910935310267e-08 -1.8972919951353434e-08 -1.7996372600916123e-08 -1.729883877917519e-08 -1.674081172178244e-08 -1.6182784664389692e-08 -2.7622339340941025e-08 -2.5250724347021848e-08 -2.5250724347021848e-08 -2.46926972896291e-08 -2.5111217582673662e-08 -2.552973787571822e-08 -2.5669244640066407e-08 -2.7343325812244652e-08 -2.2739602588754482e-08 -3.208655580008301e-08 -3.5295211380091315e-08 -3.696929255226956e-08 -3.794583990270687e-08 -3.6411265494876805e-08 -3.710879931661774e-08 -3.696929255226956e-08 -3.5713731673135874e-08 -3.1389021978342073e-08 -2.3297629646147227e-08 -1.9391440244397992e-08 -1.813587936526431e-08 -1.7856865836567937e-08 -1.813587936526431e-08 -1.6880318486130626e-08 -2.7901352869637404e-08 -2.5250724347021848e-08 -2.5808751404414597e-08 -2.5250724347021848e-08 -2.5111217582673662e-08 -2.552973787571822e-08 -2.5948258168762783e-08 -2.7622339340941025e-08 -2.2042068767013544e-08 -3.124951521399389e-08 -3.445817079400219e-08 -3.585323843748406e-08 -3.696929255226956e-08 -3.515570461574312e-08 -3.585323843748406e-08 -3.5295211380091315e-08 -3.4039650500957626e-08 -3.013346109920839e-08 -2.246058906005811e-08 -1.82753861296125e-08 -1.7438345543523375e-08 -1.674081172178244e-08 -1.7159332014827002e-08 -1.6043277900041506e-08 -2.6924805519200093e-08 -2.413467023223635e-08 -2.4274176996584538e-08 -2.385565670353998e-08 -2.3576643174843603e-08 -2.3995163467888165e-08 -2.3995163467888165e-08 -2.5808751404414597e-08 -2.078650788787986e-08 -2.9714940806163832e-08 -3.3063103150520315e-08 -3.5016197851394936e-08 -3.585323843748406e-08 -3.487669108704675e-08 -3.613225196618043e-08 -3.5713731673135874e-08 -3.4318664029654005e-08 -2.9993954334860204e-08 -2.2600095824406296e-08 -1.8693906422657058e-08 -1.729883877917519e-08 -1.6322291428737878e-08 -1.674081172178244e-08 -1.6461798193086064e-08 -2.6785298754851907e-08 -2.4274176996584538e-08 -2.4413683760932724e-08 -2.385565670353998e-08 -2.3995163467888165e-08 -2.413467023223635e-08 -2.385565670353998e-08 -2.5250724347021848e-08 -2.008897406613893e-08 -2.845937992703015e-08 -3.250507609312757e-08 -3.417915726530581e-08 -3.4737184322698563e-08 -3.348162344356488e-08 -3.376063697226125e-08 -3.3342116679216694e-08 -3.0551981392252956e-08 -2.6924805519200093e-08 -2.2042068767013544e-08 -1.813587936526431e-08 -1.6880318486130626e-08 -1.6182784664389692e-08 -1.6043277900041506e-08 -1.5485250842648757e-08 -2.6645791990503717e-08 -2.455319052528091e-08 -2.455319052528091e-08 -2.3716149939191793e-08 -2.287910935310267e-08 -2.287910935310267e-08 -2.287910935310267e-08 -2.1763055238317172e-08 -2.246058906005811e-08 -2.7203819047896466e-08 -3.027296786355658e-08 -3.180754227138664e-08 -3.3063103150520315e-08 -3.362113020791307e-08 -3.390014373660944e-08 -3.2644582857475756e-08 -3.22260625644312e-08 -3.083099492094933e-08 -2.8877900220074708e-08 -2.650628522615553e-08 -2.5390231111370035e-08 -2.455319052528091e-08 -2.5669244640066407e-08 -2.6924805519200093e-08 -2.7482832576592838e-08 -2.6366778461807345e-08 -2.7203819047896466e-08 -2.7203819047896466e-08 -2.7203819047896466e-08 -2.6366778461807345e-08 -2.5390231111370035e-08 -2.3716149939191793e-08 -2.3437136410495414e-08 -2.4832204053977286e-08 -2.6227271697459155e-08 -2.8180366398333776e-08 -2.943592727746746e-08 -2.9993954334860204e-08 -2.943592727746746e-08 -2.8319873162681962e-08 -2.845937992703015e-08 -2.8319873162681962e-08 -2.7203819047896466e-08 -2.6785298754851907e-08 -2.6645791990503717e-08 -2.6924805519200093e-08 -2.7343325812244652e-08 -2.7482832576592838e-08 -2.7343325812244652e-08 -2.46926972896291e-08 -2.4971710818325472e-08 -2.4274176996584538e-08 -2.3576643174843603e-08 -2.413467023223635e-08 -2.455319052528091e-08 -2.5390231111370035e-08 -1.9251933480049806e-08 -2.7622339340941025e-08 -3.1389021978342073e-08 -3.2644582857475756e-08 -3.362113020791307e-08 -3.22260625644312e-08 -3.320260991486851e-08 -3.3342116679216694e-08 -3.208655580008301e-08 -2.8319873162681962e-08 -2.14840417096208e-08 -1.7856865836567937e-08 -1.7159332014827002e-08 -1.6880318486130626e-08 -1.7019825250478813e-08 -1.6182784664389692e-08 -2.7343325812244652e-08 -2.3995163467888165e-08 -2.3716149939191793e-08 -2.3716149939191793e-08 -2.3995163467888165e-08 -2.4274176996584538e-08 -2.4413683760932724e-08 -2.4971710818325472e-08 -1.9809960537442554e-08 -2.873839345572652e-08 -3.22260625644312e-08 -3.390014373660944e-08 -3.4737184322698563e-08 -3.320260991486851e-08 -3.362113020791307e-08 -3.362113020791307e-08 -3.250507609312757e-08 -2.9017406984422894e-08 -2.2042068767013544e-08 -1.8414892893960685e-08 -1.771735907221975e-08 -1.771735907221975e-08 -1.8693906422657058e-08 -1.7019825250478813e-08 -2.7761846105289214e-08 -2.5111217582673662e-08 -2.5250724347021848e-08 -2.4274176996584538e-08 -2.413467023223635e-08 -2.455319052528091e-08 -2.5250724347021848e-08 -2.5808751404414597e-08 -1.9949467301790744e-08 -2.8319873162681962e-08 -3.1668035507038446e-08 -3.3063103150520315e-08 -3.390014373660944e-08 -3.2644582857475756e-08 -3.320260991486851e-08 -3.3063103150520315e-08 -3.1947049035734825e-08 -2.8180366398333776e-08 -2.14840417096208e-08 -1.82753861296125e-08 -1.7856865836567937e-08 -1.7019825250478813e-08 -1.757785230787156e-08 -1.6601304957434254e-08 -2.7901352869637404e-08 -2.5669244640066407e-08 -2.6645791990503717e-08 -2.5948258168762783e-08 -2.5390231111370035e-08 -2.4971710818325472e-08 -2.5111217582673662e-08 -2.5948258168762783e-08 -1.9391440244397992e-08 -2.7203819047896466e-08 -3.069148815660114e-08 -3.2365569328779384e-08 -3.320260991486851e-08 -3.22260625644312e-08 -3.320260991486851e-08 -3.2644582857475756e-08 -3.152852874269026e-08 -2.804085963398559e-08 -2.1205028180924427e-08 -1.757785230787156e-08 -1.6880318486130626e-08 -1.6182784664389692e-08 -1.7438345543523375e-08 -1.6601304957434254e-08 -2.7343325812244652e-08 -2.4274176996584538e-08 -2.3995163467888165e-08 -2.315812288179904e-08 -2.315812288179904e-08 -2.287910935310267e-08 -2.315812288179904e-08 -2.5390231111370035e-08 -1.8972919951353434e-08 -2.6785298754851907e-08 -3.013346109920839e-08 -3.1389021978342073e-08 -3.208655580008301e-08 -3.11100084496457e-08 -3.1668035507038446e-08 -3.124951521399389e-08 -2.9714940806163832e-08 -2.650628522615553e-08 -2.1763055238317172e-08 -1.8833413187005247e-08 -1.7996372600916123e-08 -1.7438345543523375e-08 -1.6880318486130626e-08 -1.6182784664389692e-08 -2.7343325812244652e-08 -2.413467023223635e-08 -2.3576643174843603e-08 -2.246058906005811e-08 -2.1902562002665358e-08 -2.1902562002665358e-08 -2.246058906005811e-08 -2.078650788787986e-08 -2.1902562002665358e-08 -2.650628522615553e-08 -2.9156913748771087e-08 -3.1668035507038446e-08 -3.2365569328779384e-08 -3.208655580008301e-08 -3.22260625644312e-08 -3.1668035507038446e-08 -3.1947049035734825e-08 -3.069148815660114e-08 -2.9017406984422894e-08 -2.7622339340941025e-08 -2.608776493311097e-08 -2.6227271697459155e-08 -2.7343325812244652e-08 -2.8877900220074708e-08 -2.8598886691378335e-08 -2.552973787571822e-08 -2.5111217582673662e-08 -2.3995163467888165e-08 -2.3576643174843603e-08 -2.315812288179904e-08 -2.3576643174843603e-08 -2.1205028180924427e-08 -2.1344534945272613e-08 -2.3297629646147227e-08 -2.4274176996584538e-08 -2.6227271697459155e-08 -2.7343325812244652e-08 -2.7901352869637404e-08 -2.7343325812244652e-08 -2.6645791990503717e-08 -2.608776493311097e-08 -2.5808751404414597e-08 -2.46926972896291e-08 -2.413467023223635e-08 -2.4274176996584538e-08 -2.4832204053977286e-08 -2.650628522615553e-08 -2.6645791990503717e-08 -2.6785298754851907e-08 -2.413467023223635e-08 -2.4274176996584538e-08 -2.413467023223635e-08 -2.3437136410495414e-08 -2.385565670353998e-08 -2.4274176996584538e-08 -2.5669244640066407e-08 -1.9391440244397992e-08 -2.804085963398559e-08 -3.1947049035734825e-08 -3.362113020791307e-08 -3.445817079400219e-08 -3.292359638617213e-08 -3.4039650500957626e-08 -3.445817079400219e-08 -3.3342116679216694e-08 -2.9017406984422894e-08 -2.1623548473968986e-08 -1.7856865836567937e-08 -1.674081172178244e-08 -1.674081172178244e-08 -1.771735907221975e-08 -1.6043277900041506e-08 -2.6785298754851907e-08 -2.315812288179904e-08 -2.3437136410495414e-08 -2.3297629646147227e-08 -2.3437136410495414e-08 -2.315812288179904e-08 -2.3437136410495414e-08 -2.3437136410495414e-08 -1.8972919951353434e-08 -2.804085963398559e-08 -3.1389021978342073e-08 -3.292359638617213e-08 -3.376063697226125e-08 -3.208655580008301e-08 -3.278408962182394e-08 -3.292359638617213e-08 -3.1947049035734825e-08 -2.8180366398333776e-08 -2.078650788787986e-08 -1.7159332014827002e-08 -1.6322291428737878e-08 -1.6182784664389692e-08 -1.8414892893960685e-08 -1.6182784664389692e-08 -2.608776493311097e-08 -2.287910935310267e-08 -2.2739602588754482e-08 -2.1902562002665358e-08 -2.1623548473968986e-08 -2.2042068767013544e-08 -2.246058906005811e-08 -2.3576643174843603e-08 -1.9251933480049806e-08 -2.804085963398559e-08 -3.152852874269026e-08 -3.3063103150520315e-08 -3.376063697226125e-08 -3.2365569328779384e-08 -3.3342116679216694e-08 -3.348162344356488e-08 -3.250507609312757e-08 -2.8598886691378335e-08 -2.14840417096208e-08 -1.8693906422657058e-08 -1.855439965830887e-08 -1.813587936526431e-08 -1.9391440244397992e-08 -1.757785230787156e-08 -2.8180366398333776e-08 -2.5669244640066407e-08 -2.7343325812244652e-08 -2.6645791990503717e-08 -2.5948258168762783e-08 -2.5948258168762783e-08 -2.5669244640066407e-08 -2.608776493311097e-08 -1.9949467301790744e-08 -2.8598886691378335e-08 -3.180754227138664e-08 -3.3063103150520315e-08 -3.376063697226125e-08 -3.2365569328779384e-08 -3.3063103150520315e-08 -3.3063103150520315e-08 -3.1947049035734825e-08 -2.7901352869637404e-08 -2.0926014652228048e-08 -1.7159332014827002e-08 -1.7019825250478813e-08 -1.6601304957434254e-08 -1.8972919951353434e-08 -1.7159332014827002e-08 -2.7901352869637404e-08 -2.5390231111370035e-08 -2.5250724347021848e-08 -2.413467023223635e-08 -2.3995163467888165e-08 -2.3716149939191793e-08 -2.4413683760932724e-08 -2.6785298754851907e-08 -2.008897406613893e-08 -2.8319873162681962e-08 -3.124951521399389e-08 -3.2365569328779384e-08 -3.3342116679216694e-08 -3.1947049035734825e-08 -3.278408962182394e-08 -3.278408962182394e-08 -3.069148815660114e-08 -2.706431228354828e-08 -2.1763055238317172e-08 -1.8693906422657058e-08 -1.7856865836567937e-08 -1.771735907221975e-08 -1.757785230787156e-08 -1.674081172178244e-08 -2.804085963398559e-08 -2.4832204053977286e-08 -2.5250724347021848e-08 -2.4413683760932724e-08 -2.4274176996584538e-08 -2.3576643174843603e-08 -2.385565670353998e-08 -2.218157553136173e-08 -2.3018616117450855e-08 -2.6924805519200093e-08 -3.041247462790477e-08 -3.3063103150520315e-08 -3.3342116679216694e-08 -3.320260991486851e-08 -3.208655580008301e-08 -3.1668035507038446e-08 -3.11100084496457e-08 -2.9714940806163832e-08 -2.7901352869637404e-08 -2.7343325812244652e-08 -2.608776493311097e-08 -2.6366778461807345e-08 -2.7761846105289214e-08 -2.804085963398559e-08 -2.706431228354828e-08 -2.385565670353998e-08 -2.3716149939191793e-08 -2.287910935310267e-08 -2.246058906005811e-08 -2.218157553136173e-08 -2.3297629646147227e-08 -2.1763055238317172e-08 -2.2042068767013544e-08 -2.3995163467888165e-08 -2.5111217582673662e-08 -2.6366778461807345e-08 -2.7203819047896466e-08 -2.7622339340941025e-08 -2.7622339340941025e-08 -2.6924805519200093e-08 -2.6227271697459155e-08 -2.5948258168762783e-08 -2.4832204053977286e-08 -2.4274176996584538e-08 -2.4413683760932724e-08 -2.4413683760932724e-08 -2.5808751404414597e-08 -2.552973787571822e-08 -2.4832204053977286e-08 -2.3018616117450855e-08 -2.3297629646147227e-08 -2.3018616117450855e-08 -2.3018616117450855e-08 -2.3297629646147227e-08 -2.4274176996584538e-08 -2.6366778461807345e-08 -2.14840417096208e-08 -3.1389021978342073e-08 -3.5016197851394936e-08 -3.6690279023573184e-08 -3.7666826374010495e-08 -3.627175873052862e-08 -3.8085346667055053e-08 -3.822485343140324e-08 -3.696929255226956e-08 -3.180754227138664e-08 -2.315812288179904e-08 -1.911242671570162e-08 -1.771735907221975e-08 -1.7856865836567937e-08 -1.9949467301790744e-08 -1.757785230787156e-08 -2.7622339340941025e-08 -2.455319052528091e-08 -2.5111217582673662e-08 -2.4413683760932724e-08 -2.4832204053977286e-08 -2.4413683760932724e-08 -2.4832204053977286e-08 -2.6366778461807345e-08 -2.14840417096208e-08 -3.1668035507038446e-08 -3.487669108704675e-08 -3.6690279023573184e-08 -3.794583990270687e-08 -3.5992745201832246e-08 -3.724830608096593e-08 -3.7387812845314116e-08 -3.613225196618043e-08 -3.041247462790477e-08 -2.2042068767013544e-08 -1.7856865836567937e-08 -1.7159332014827002e-08 -1.7856865836567937e-08 -2.0228480830487117e-08 -1.729883877917519e-08 -2.7343325812244652e-08 -2.413467023223635e-08 -2.413467023223635e-08 -2.3297629646147227e-08 -2.315812288179904e-08 -2.287910935310267e-08 -2.3297629646147227e-08 -2.5250724347021848e-08 -2.1205028180924427e-08 -3.0970501685297515e-08 -3.459767755835038e-08 -3.6550772259225e-08 -3.7666826374010495e-08 -3.557422490878769e-08 -3.6690279023573184e-08 -3.6690279023573184e-08 -3.515570461574312e-08 -3.041247462790477e-08 -2.1623548473968986e-08 -1.7996372600916123e-08 -1.7438345543523375e-08 -1.813587936526431e-08 -2.078650788787986e-08 -1.7438345543523375e-08 -2.6924805519200093e-08 -2.3995163467888165e-08 -2.46926972896291e-08 -2.4413683760932724e-08 -2.3995163467888165e-08 -2.4413683760932724e-08 -2.46926972896291e-08 -2.5948258168762783e-08 -2.14840417096208e-08 -3.1947049035734825e-08 -3.54347181444395e-08 -3.682978578792137e-08 -3.7666826374010495e-08 -3.5295211380091315e-08 -3.6690279023573184e-08 -3.682978578792137e-08 -3.557422490878769e-08 -3.027296786355658e-08 -2.1902562002665358e-08 -1.82753861296125e-08 -1.8414892893960685e-08 -1.9391440244397992e-08 -2.218157553136173e-08 -1.855439965830887e-08 -2.8180366398333776e-08 -2.552973787571822e-08 -2.552973787571822e-08 -2.4274176996584538e-08 -2.4413683760932724e-08 -2.413467023223635e-08 -2.46926972896291e-08 -2.7482832576592838e-08 -2.1623548473968986e-08 -3.124951521399389e-08 -3.459767755835038e-08 -3.6411265494876805e-08 -3.724830608096593e-08 -3.54347181444395e-08 -3.627175873052862e-08 -3.585323843748406e-08 -3.3063103150520315e-08 -2.845937992703015e-08 -2.218157553136173e-08 -1.8414892893960685e-08 -1.7159332014827002e-08 -1.729883877917519e-08 -1.855439965830887e-08 -1.7159332014827002e-08 -2.7622339340941025e-08 -2.5111217582673662e-08 -2.552973787571822e-08 -2.4832204053977286e-08 -2.455319052528091e-08 -2.385565670353998e-08 -2.413467023223635e-08 -2.287910935310267e-08 -2.3716149939191793e-08 -2.7622339340941025e-08 -3.1947049035734825e-08 -3.376063697226125e-08 -3.4737184322698563e-08 -3.4039650500957626e-08 -3.320260991486851e-08 -3.22260625644312e-08 -3.124951521399389e-08 -2.9993954334860204e-08 -2.7622339340941025e-08 -2.7343325812244652e-08 -2.7343325812244652e-08 -2.7622339340941025e-08 -2.873839345572652e-08 -2.7901352869637404e-08 -2.608776493311097e-08 -2.385565670353998e-08 -2.4274176996584538e-08 -2.3576643174843603e-08 -2.3018616117450855e-08 -2.2600095824406296e-08 -2.2600095824406296e-08 -2.1344534945272613e-08 -2.078650788787986e-08 -2.2600095824406296e-08 -2.455319052528091e-08 -2.650628522615553e-08 -2.706431228354828e-08 -2.7761846105289214e-08 -2.7482832576592838e-08 -2.6366778461807345e-08 -2.6227271697459155e-08 -2.6645791990503717e-08 -2.5948258168762783e-08 -2.5808751404414597e-08 -2.6924805519200093e-08 -2.7203819047896466e-08 -2.845937992703015e-08 -2.706431228354828e-08 -2.552973787571822e-08 -2.3716149939191793e-08 -2.413467023223635e-08 -2.3576643174843603e-08 -2.315812288179904e-08 -2.3995163467888165e-08 -2.5111217582673662e-08 -2.7622339340941025e-08 -2.315812288179904e-08 -3.4318664029654005e-08 -3.8364360195751426e-08 -4.031745489662604e-08 -4.129400224706335e-08 -3.906189401749236e-08 -4.115449548271517e-08 -4.1433509011411543e-08 -3.9340907546188736e-08 -3.362113020791307e-08 -2.385565670353998e-08 -2.008897406613893e-08 -1.9391440244397992e-08 -2.0228480830487117e-08 -2.2042068767013544e-08 -1.8833413187005247e-08 -2.9156913748771087e-08 -2.6227271697459155e-08 -2.6645791990503717e-08 -2.5948258168762783e-08 -2.650628522615553e-08 -2.6366778461807345e-08 -2.7203819047896466e-08 -2.985444757051202e-08 -2.4274176996584538e-08 -3.557422490878769e-08 -3.948041431053692e-08 -4.157301577575972e-08 -4.3386603712286164e-08 -4.0735975189670606e-08 -4.2828576654893406e-08 -4.324709694793797e-08 -4.129400224706335e-08 -3.445817079400219e-08 -2.455319052528091e-08 -1.9809960537442554e-08 -1.9251933480049806e-08 -2.1344534945272613e-08 -2.3018616117450855e-08 -1.8693906422657058e-08 -2.8319873162681962e-08 -2.5390231111370035e-08 -2.5111217582673662e-08 -2.385565670353998e-08 -2.3576643174843603e-08 -2.3437136410495414e-08 -2.385565670353998e-08 -2.706431228354828e-08 -2.315812288179904e-08 -3.4318664029654005e-08 -3.7806333138358674e-08 -4.017794813227786e-08 -4.1712522540107916e-08 -3.892238725314418e-08 -4.059646842532242e-08 -4.059646842532242e-08 -3.906189401749236e-08 -3.3063103150520315e-08 -2.3018616117450855e-08 -1.8833413187005247e-08 -1.7856865836567937e-08 -2.0228480830487117e-08 -2.246058906005811e-08 -1.7996372600916123e-08 -2.7482832576592838e-08 -2.4413683760932724e-08 -2.455319052528091e-08 -2.385565670353998e-08 -2.3576643174843603e-08 -2.3297629646147227e-08 -2.4413683760932724e-08 -2.7343325812244652e-08 -2.3576643174843603e-08 -3.459767755835038e-08 -3.8364360195751426e-08 -4.059646842532242e-08 -4.213104283315248e-08 -3.906189401749236e-08 -4.0735975189670606e-08 -4.115449548271517e-08 -3.9759427839233295e-08 -3.390014373660944e-08 -2.4274176996584538e-08 -1.9949467301790744e-08 -1.9670453773094368e-08 -2.2321082295709924e-08 -2.4971710818325472e-08 -2.008897406613893e-08 -3.027296786355658e-08 -2.650628522615553e-08 -2.6227271697459155e-08 -2.4832204053977286e-08 -2.4413683760932724e-08 -2.46926972896291e-08 -2.5948258168762783e-08 -2.943592727746746e-08 -2.385565670353998e-08 -3.445817079400219e-08 -3.8085346667055053e-08 -4.031745489662604e-08 -4.101498871836698e-08 -3.850386696009961e-08 -3.948041431053692e-08 -3.892238725314418e-08 -3.613225196618043e-08 -3.041247462790477e-08 -2.315812288179904e-08 -1.953094700874618e-08 -1.855439965830887e-08 -1.9391440244397992e-08 -2.0228480830487117e-08 -1.771735907221975e-08 -2.7482832576592838e-08 -2.4413683760932724e-08 -2.3995163467888165e-08 -2.287910935310267e-08 -2.2321082295709924e-08 -2.218157553136173e-08 -2.2600095824406296e-08 -2.1763055238317172e-08 -2.3018616117450855e-08 -2.7482832576592838e-08 -3.1947049035734825e-08 -3.445817079400219e-08 -3.5713731673135874e-08 -3.417915726530581e-08 -3.348162344356488e-08 -3.3063103150520315e-08 -3.1668035507038446e-08 -3.027296786355658e-08 -2.804085963398559e-08 -2.7622339340941025e-08 -2.7761846105289214e-08 -2.8877900220074708e-08 -2.9296420513119273e-08 -2.8319873162681962e-08 -2.6227271697459155e-08 -2.4413683760932724e-08 -2.4832204053977286e-08 -2.413467023223635e-08 -2.3437136410495414e-08 -2.3018616117450855e-08 -2.2739602588754482e-08 -2.14840417096208e-08 -2.0228480830487117e-08 -2.1623548473968986e-08 -2.3576643174843603e-08 -2.5948258168762783e-08 -2.6366778461807345e-08 -2.7622339340941025e-08 -2.7203819047896466e-08 -2.6645791990503717e-08 -2.6645791990503717e-08 -2.7343325812244652e-08 -2.6785298754851907e-08 -2.6785298754851907e-08 -2.7761846105289214e-08 -2.8598886691378335e-08 -2.985444757051202e-08 -2.8319873162681962e-08 -2.6227271697459155e-08 -2.46926972896291e-08 -2.5250724347021848e-08 -2.46926972896291e-08 -2.413467023223635e-08 -2.46926972896291e-08 -2.5948258168762783e-08 -2.9017406984422894e-08 -2.413467023223635e-08 -3.5713731673135874e-08 -3.948041431053692e-08 -4.1433509011411543e-08 -4.2549563126197034e-08 -3.961992107488511e-08 -4.157301577575972e-08 -4.1852029304456096e-08 -3.989893460358149e-08 -3.3342116679216694e-08 -2.315812288179904e-08 -1.9251933480049806e-08 -1.8972919951353434e-08 -2.1205028180924427e-08 -2.1763055238317172e-08 -1.7856865836567937e-08 -2.7343325812244652e-08 -2.455319052528091e-08 -2.4971710818325472e-08 -2.4413683760932724e-08 -2.4971710818325472e-08 -2.4971710818325472e-08 -2.650628522615553e-08 -2.985444757051202e-08 -2.4971710818325472e-08 -3.682978578792137e-08 -4.0735975189670606e-08 -4.2828576654893406e-08 -4.478167135576803e-08 -4.1712522540107916e-08 -4.3805124005330716e-08 -4.464216459141985e-08 -4.227054959750066e-08 -3.515570461574312e-08 -2.455319052528091e-08 -1.9670453773094368e-08 -1.8833413187005247e-08 -2.2739602588754482e-08 -2.4413683760932724e-08 -1.9391440244397992e-08 -2.8877900220074708e-08 -2.4971710818325472e-08 -2.46926972896291e-08 -2.3576643174843603e-08 -2.3297629646147227e-08 -2.3437136410495414e-08 -2.455319052528091e-08 -2.873839345572652e-08 -2.4832204053977286e-08 -3.627175873052862e-08 -3.9759427839233295e-08 -4.2410056361848854e-08 -4.3805124005330716e-08 -4.059646842532242e-08 -4.2410056361848854e-08 -4.2689069890545226e-08 -4.101498871836698e-08 -3.4318664029654005e-08 -2.385565670353998e-08 -1.953094700874618e-08 -1.8693906422657058e-08 -2.2739602588754482e-08 -2.3716149939191793e-08 -1.8833413187005247e-08 -2.845937992703015e-08 -2.5669244640066407e-08 -2.552973787571822e-08 -2.4832204053977286e-08 -2.4413683760932724e-08 -2.413467023223635e-08 -2.5390231111370035e-08 -2.9156913748771087e-08 -2.5111217582673662e-08 -3.6550772259225e-08 -4.003844136792967e-08 -4.227054959750066e-08 -4.3805124005330716e-08 -4.087548195401879e-08 -4.2410056361848854e-08 -4.29680834192416e-08 -4.157301577575972e-08 -3.557422490878769e-08 -2.5111217582673662e-08 -2.050749435918349e-08 -2.008897406613893e-08 -2.3995163467888165e-08 -2.5250724347021848e-08 -2.008897406613893e-08 -3.027296786355658e-08 -2.6924805519200093e-08 -2.6924805519200093e-08 -2.5390231111370035e-08 -2.4832204053977286e-08 -2.5808751404414597e-08 -2.7203819047896466e-08 -3.083099492094933e-08 -2.5390231111370035e-08 -3.6411265494876805e-08 -3.989893460358149e-08 -4.213104283315248e-08 -4.29680834192416e-08 -4.003844136792967e-08 -4.115449548271517e-08 -4.0735975189670606e-08 -3.7806333138358674e-08 -3.1389021978342073e-08 -2.3576643174843603e-08 -1.9809960537442554e-08 -1.8972919951353434e-08 -2.14840417096208e-08 -2.1205028180924427e-08 -1.82753861296125e-08 -2.845937992703015e-08 -2.5250724347021848e-08 -2.5250724347021848e-08 -2.385565670353998e-08 -2.3576643174843603e-08 -2.3716149939191793e-08 -2.413467023223635e-08 -2.3716149939191793e-08 -2.455319052528091e-08 -2.9993954334860204e-08 -3.5016197851394936e-08 -3.724830608096593e-08 -3.822485343140324e-08 -3.682978578792137e-08 -3.5713731673135874e-08 -3.487669108704675e-08 -3.278408962182394e-08 -3.11100084496457e-08 -2.845937992703015e-08 -2.706431228354828e-08 -2.650628522615553e-08 -2.7901352869637404e-08 -2.7622339340941025e-08 -2.6227271697459155e-08 -2.46926972896291e-08 -2.2600095824406296e-08 -2.3297629646147227e-08 -2.2600095824406296e-08 -2.315812288179904e-08 -2.246058906005811e-08 -2.3018616117450855e-08 -2.246058906005811e-08 -2.1623548473968986e-08 -2.2739602588754482e-08 -2.455319052528091e-08 -2.6645791990503717e-08 -2.7203819047896466e-08 -2.804085963398559e-08 -2.845937992703015e-08 -2.7761846105289214e-08 -2.7761846105289214e-08 -2.7343325812244652e-08 -2.6785298754851907e-08 -2.608776493311097e-08 -2.5808751404414597e-08 -2.8180366398333776e-08 -2.8598886691378335e-08 -2.6924805519200093e-08 -2.5111217582673662e-08 -2.4413683760932724e-08 -2.5111217582673662e-08 -2.455319052528091e-08 -2.455319052528091e-08 -2.4274176996584538e-08 -2.552973787571822e-08 -2.943592727746746e-08 -2.455319052528091e-08 -3.613225196618043e-08 -3.920140078184055e-08 -4.101498871836698e-08 -4.2549563126197034e-08 -3.961992107488511e-08 -4.1852029304456096e-08 -4.1852029304456096e-08 -4.031745489662604e-08 -3.348162344356488e-08 -2.3297629646147227e-08 -1.9251933480049806e-08 -1.9251933480049806e-08 -2.3018616117450855e-08 -2.246058906005811e-08 -1.813587936526431e-08 -2.7761846105289214e-08 -2.4971710818325472e-08 -2.5111217582673662e-08 -2.4274176996584538e-08 -2.46926972896291e-08 -2.4832204053977286e-08 -2.5669244640066407e-08 -2.985444757051202e-08 -2.5669244640066407e-08 -3.724830608096593e-08 -4.0735975189670606e-08 -4.2549563126197034e-08 -4.394463076967891e-08 -4.0735975189670606e-08 -4.2828576654893406e-08 -4.3386603712286164e-08 -4.1433509011411543e-08 -3.4318664029654005e-08 -2.3995163467888165e-08 -1.9670453773094368e-08 -2.008897406613893e-08 -2.455319052528091e-08 -2.455319052528091e-08 -2.008897406613893e-08 -3.0970501685297515e-08 -2.7761846105289214e-08 -2.7901352869637404e-08 -2.7343325812244652e-08 -2.7622339340941025e-08 -2.6924805519200093e-08 -2.8180366398333776e-08 -3.320260991486851e-08 -2.7343325812244652e-08 -3.8782880488795985e-08 -4.1852029304456096e-08 -4.3805124005330716e-08 -4.492117812011622e-08 -4.157301577575972e-08 -4.310759018358978e-08 -4.3386603712286164e-08 -4.157301577575972e-08 -3.487669108704675e-08 -2.4413683760932724e-08 -1.9809960537442554e-08 -1.9809960537442554e-08 -2.4832204053977286e-08 -2.4274176996584538e-08 -1.911242671570162e-08 -2.8877900220074708e-08 -2.6366778461807345e-08 -2.650628522615553e-08 -2.6366778461807345e-08 -2.6227271697459155e-08 -2.6924805519200093e-08 -2.8180366398333776e-08 -3.2644582857475756e-08 -2.6785298754851907e-08 -3.86433737244478e-08 -4.1852029304456096e-08 -4.3386603712286164e-08 -4.464216459141985e-08 -4.199153606880429e-08 -4.366561724098254e-08 -4.366561724098254e-08 -4.1712522540107916e-08 -3.54347181444395e-08 -2.4832204053977286e-08 -2.0647001123531675e-08 -2.078650788787986e-08 -2.608776493311097e-08 -2.5390231111370035e-08 -1.9949467301790744e-08 -2.9156913748771087e-08 -2.5808751404414597e-08 -2.608776493311097e-08 -2.455319052528091e-08 -2.455319052528091e-08 -2.4832204053977286e-08 -2.5948258168762783e-08 -3.041247462790477e-08 -2.5250724347021848e-08 -3.613225196618043e-08 -3.948041431053692e-08 -4.115449548271517e-08 -4.199153606880429e-08 -3.906189401749236e-08 -4.003844136792967e-08 -3.948041431053692e-08 -3.627175873052862e-08 -2.9993954334860204e-08 -2.287910935310267e-08 -1.9251933480049806e-08 -1.9251933480049806e-08 -2.2321082295709924e-08 -2.1344534945272613e-08 -1.813587936526431e-08 -2.8877900220074708e-08 -2.5669244640066407e-08 -2.5808751404414597e-08 -2.4413683760932724e-08 -2.385565670353998e-08 -2.385565670353998e-08 -2.413467023223635e-08 -2.4274176996584538e-08 -2.5948258168762783e-08 -3.1947049035734825e-08 -3.75273196096623e-08 -3.989893460358149e-08 -4.059646842532242e-08 -3.892238725314418e-08 -3.7806333138358674e-08 -3.6411265494876805e-08 -3.5295211380091315e-08 -3.320260991486851e-08 -3.083099492094933e-08 -2.8877900220074708e-08 -2.873839345572652e-08 -3.069148815660114e-08 -3.027296786355658e-08 -2.873839345572652e-08 -2.6785298754851907e-08 -2.46926972896291e-08 -2.4971710818325472e-08 -2.3995163467888165e-08 -2.4971710818325472e-08 -2.3995163467888165e-08 -2.455319052528091e-08 -2.4274176996584538e-08 -2.287910935310267e-08 -2.3576643174843603e-08 -2.6227271697459155e-08 -2.7901352869637404e-08 -2.845937992703015e-08 -2.9296420513119273e-08 -2.943592727746746e-08 -2.9017406984422894e-08 -2.7761846105289214e-08 -2.706431228354828e-08 -2.6645791990503717e-08 -2.608776493311097e-08 -2.552973787571822e-08 -2.804085963398559e-08 -2.7761846105289214e-08 -2.608776493311097e-08 -2.4832204053977286e-08 -2.3716149939191793e-08 -2.455319052528091e-08 -2.3995163467888165e-08 -2.385565670353998e-08 -2.3716149939191793e-08 -2.4971710818325472e-08 -2.943592727746746e-08 -2.5111217582673662e-08 -3.682978578792137e-08 -3.989893460358149e-08 -4.199153606880429e-08 -4.3386603712286164e-08 -4.017794813227786e-08 -4.213104283315248e-08 -4.199153606880429e-08 -4.017794813227786e-08 -3.3342116679216694e-08 -2.315812288179904e-08 -1.9251933480049806e-08 -2.008897406613893e-08 -2.4971710818325472e-08 -2.3018616117450855e-08 -1.7996372600916123e-08 -2.7761846105289214e-08 -2.5111217582673662e-08 -2.5250724347021848e-08 -2.4274176996584538e-08 -2.4274176996584538e-08 -2.455319052528091e-08 -2.5390231111370035e-08 -2.9993954334860204e-08 -2.5948258168762783e-08 -3.7387812845314116e-08 -4.0735975189670606e-08 -4.227054959750066e-08 -4.3386603712286164e-08 -4.031745489662604e-08 -4.2410056361848854e-08 -4.29680834192416e-08 -4.0735975189670606e-08 -3.390014373660944e-08 -2.3437136410495414e-08 -1.9670453773094368e-08 -2.1205028180924427e-08 -2.5250724347021848e-08 -2.3297629646147227e-08 -1.8693906422657058e-08 -2.9575434041815645e-08 -2.7761846105289214e-08 -2.8180366398333776e-08 -2.7622339340941025e-08 -2.7482832576592838e-08 -2.706431228354828e-08 -2.7482832576592838e-08 -3.3342116679216694e-08 -2.7622339340941025e-08 -3.9340907546188736e-08 -4.1712522540107916e-08 -4.310759018358978e-08 -4.408413753402709e-08 -4.0735975189670606e-08 -4.2410056361848854e-08 -4.2549563126197034e-08 -4.087548195401879e-08 -3.417915726530581e-08 -2.3995163467888165e-08 -1.953094700874618e-08 -2.078650788787986e-08 -2.5808751404414597e-08 -2.3576643174843603e-08 -1.82753861296125e-08 -2.7761846105289214e-08 -2.5250724347021848e-08 -2.650628522615553e-08 -2.6366778461807345e-08 -2.6785298754851907e-08 -2.7482832576592838e-08 -2.8319873162681962e-08 -3.348162344356488e-08 -2.7622339340941025e-08 -3.906189401749236e-08 -4.2549563126197034e-08 -4.3805124005330716e-08 -4.492117812011622e-08 -4.199153606880429e-08 -4.408413753402709e-08 -4.366561724098254e-08 -4.157301577575972e-08 -3.5016197851394936e-08 -2.5250724347021848e-08 -2.078650788787986e-08 -2.1623548473968986e-08 -2.6924805519200093e-08 -2.4971710818325472e-08 -1.9251933480049806e-08 -2.8180366398333776e-08 -2.455319052528091e-08 -2.4971710818325472e-08 -2.3576643174843603e-08 -2.3716149939191793e-08 -2.3716149939191793e-08 -2.46926972896291e-08 -2.985444757051202e-08 -2.5390231111370035e-08 -3.6411265494876805e-08 -3.948041431053692e-08 -4.101498871836698e-08 -4.199153606880429e-08 -3.850386696009961e-08 -3.961992107488511e-08 -3.8782880488795985e-08 -3.54347181444395e-08 -2.9156913748771087e-08 -2.218157553136173e-08 -1.8693906422657058e-08 -1.9809960537442554e-08 -2.2739602588754482e-08 -2.0926014652228048e-08 -1.771735907221975e-08 -2.804085963398559e-08 -2.4971710818325472e-08 -2.4832204053977286e-08 -2.3437136410495414e-08 -2.3018616117450855e-08 -2.3018616117450855e-08 -2.3297629646147227e-08 -2.3576643174843603e-08 -2.552973787571822e-08 -3.124951521399389e-08 -3.54347181444395e-08 -3.8364360195751426e-08 -3.948041431053692e-08 -3.794583990270687e-08 -3.6550772259225e-08 -3.54347181444395e-08 -3.487669108704675e-08 -3.2644582857475756e-08 -3.041247462790477e-08 -2.9017406984422894e-08 -2.9017406984422894e-08 -3.11100084496457e-08 -3.013346109920839e-08 -2.8598886691378335e-08 -2.6785298754851907e-08 -2.4971710818325472e-08 -2.5250724347021848e-08 -2.455319052528091e-08 -2.46926972896291e-08 -2.413467023223635e-08 -2.4274176996584538e-08 -2.385565670353998e-08 -2.218157553136173e-08 -2.2321082295709924e-08 -2.4832204053977286e-08 -2.650628522615553e-08 -2.7343325812244652e-08 -2.8319873162681962e-08 -2.8319873162681962e-08 -2.8180366398333776e-08 -2.6924805519200093e-08 -2.6227271697459155e-08 -2.5808751404414597e-08 -2.552973787571822e-08 -2.5111217582673662e-08 -2.650628522615553e-08 -2.608776493311097e-08 -2.455319052528091e-08 -2.3437136410495414e-08 -2.1902562002665358e-08 -2.287910935310267e-08 -2.246058906005811e-08 -2.2321082295709924e-08 -2.2321082295709924e-08 -2.3716149939191793e-08 -2.8598886691378335e-08 -2.5250724347021848e-08 -3.710879931661774e-08 -4.017794813227786e-08 -4.199153606880429e-08 -4.29680834192416e-08 -3.9759427839233295e-08 -4.1712522540107916e-08 -4.1852029304456096e-08 -3.989893460358149e-08 -3.278408962182394e-08 -2.2600095824406296e-08 -1.855439965830887e-08 -2.0367987594835303e-08 -2.5111217582673662e-08 -2.2042068767013544e-08 -1.674081172178244e-08 -2.5250724347021848e-08 -2.2600095824406296e-08 -2.3018616117450855e-08 -2.246058906005811e-08 -2.2600095824406296e-08 -2.3297629646147227e-08 -2.4413683760932724e-08 -2.9575434041815645e-08 -2.6227271697459155e-08 -3.7666826374010495e-08 -4.101498871836698e-08 -4.2410056361848854e-08 -4.366561724098254e-08 -4.045696166097423e-08 -4.227054959750066e-08 -4.2549563126197034e-08 -4.059646842532242e-08 -3.348162344356488e-08 -2.315812288179904e-08 -1.9391440244397992e-08 -2.14840417096208e-08 -2.5808751404414597e-08 -2.3018616117450855e-08 -1.7856865836567937e-08 -2.6645791990503717e-08 -2.46926972896291e-08 -2.4413683760932724e-08 -2.3716149939191793e-08 -2.3716149939191793e-08 -2.385565670353998e-08 -2.455319052528091e-08 -2.9993954334860204e-08 -2.6227271697459155e-08 -3.850386696009961e-08 -4.0735975189670606e-08 -4.2410056361848854e-08 -4.3526110476634344e-08 -4.059646842532242e-08 -4.213104283315248e-08 -4.2410056361848854e-08 -4.031745489662604e-08 -3.362113020791307e-08 -2.3437136410495414e-08 -1.953094700874618e-08 -2.218157553136173e-08 -2.6227271697459155e-08 -2.315812288179904e-08 -1.771735907221975e-08 -2.608776493311097e-08 -2.3297629646147227e-08 -2.4274176996584538e-08 -2.3716149939191793e-08 -2.385565670353998e-08 -2.3995163467888165e-08 -2.5250724347021848e-08 -3.041247462790477e-08 -2.6227271697459155e-08 -3.7666826374010495e-08 -4.115449548271517e-08 -4.2549563126197034e-08 -4.3805124005330716e-08 -4.115449548271517e-08 -4.310759018358978e-08 -4.310759018358978e-08 -4.129400224706335e-08 -3.445817079400219e-08 -2.46926972896291e-08 -2.050749435918349e-08 -2.315812288179904e-08 -2.706431228354828e-08 -2.4413683760932724e-08 -1.855439965830887e-08 -2.7482832576592838e-08 -2.385565670353998e-08 -2.413467023223635e-08 -2.287910935310267e-08 -2.287910935310267e-08 -2.3018616117450855e-08 -2.4274176996584538e-08 -2.9575434041815645e-08 -2.5808751404414597e-08 -3.6690279023573184e-08 -3.9759427839233295e-08 -4.1433509011411543e-08 -4.2410056361848854e-08 -3.8782880488795985e-08 -4.003844136792967e-08 -3.892238725314418e-08 -3.5713731673135874e-08 -2.985444757051202e-08 -2.2739602588754482e-08 -1.911242671570162e-08 -2.0647001123531675e-08 -2.3297629646147227e-08 -2.0647001123531675e-08 -1.7438345543523375e-08 -2.7203819047896466e-08 -2.4274176996584538e-08 -2.46926972896291e-08 -2.3576643174843603e-08 -2.3576643174843603e-08 -2.287910935310267e-08 -2.315812288179904e-08 -2.3576643174843603e-08 -2.5390231111370035e-08 -3.083099492094933e-08 -3.4039650500957626e-08 -3.6690279023573184e-08 -3.794583990270687e-08 -3.627175873052862e-08 -3.5016197851394936e-08 -3.445817079400219e-08 -3.3342116679216694e-08 -3.1947049035734825e-08 -2.9296420513119273e-08 -2.8319873162681962e-08 -2.8877900220074708e-08 -3.0551981392252956e-08 -2.9714940806163832e-08 -2.8877900220074708e-08 -2.7343325812244652e-08 -2.5390231111370035e-08 -2.6366778461807345e-08 -2.5808751404414597e-08 -2.5390231111370035e-08 -2.5250724347021848e-08 -2.5390231111370035e-08 -2.5111217582673662e-08 -2.385565670353998e-08 -2.3297629646147227e-08 -2.4971710818325472e-08 -2.6924805519200093e-08 -2.7901352869637404e-08 -2.8319873162681962e-08 -2.8319873162681962e-08 -2.7761846105289214e-08 -2.7203819047896466e-08 -2.650628522615553e-08 -2.5948258168762783e-08 -2.552973787571822e-08 -2.6227271697459155e-08 -2.7761846105289214e-08 -2.6924805519200093e-08 -2.552973787571822e-08 -2.4274176996584538e-08 -2.2321082295709924e-08 -2.3297629646147227e-08 -2.2739602588754482e-08 -2.3297629646147227e-08 -2.3576643174843603e-08 -2.4971710818325472e-08 -3.013346109920839e-08 -2.6366778461807345e-08 -3.7806333138358674e-08 -4.087548195401879e-08 -4.2549563126197034e-08 -4.366561724098254e-08 -4.045696166097423e-08 -4.2410056361848854e-08 -4.2549563126197034e-08 -4.059646842532242e-08 -3.362113020791307e-08 -2.3437136410495414e-08 -1.9809960537442554e-08 -2.3018616117450855e-08 -2.608776493311097e-08 -2.218157553136173e-08 -1.7159332014827002e-08 -2.5808751404414597e-08 -2.287910935310267e-08 -2.3716149939191793e-08 -2.315812288179904e-08 -2.413467023223635e-08 -2.4971710818325472e-08 -2.5808751404414597e-08 -3.11100084496457e-08 -2.7761846105289214e-08 -3.920140078184055e-08 -4.2549563126197034e-08 -4.394463076967891e-08 -4.520019164881259e-08 -4.1852029304456096e-08 -4.366561724098254e-08 -4.366561724098254e-08 -4.199153606880429e-08 -3.487669108704675e-08 -2.455319052528091e-08 -2.050749435918349e-08 -2.3995163467888165e-08 -2.7622339340941025e-08 -2.4274176996584538e-08 -1.8414892893960685e-08 -2.650628522615553e-08 -2.413467023223635e-08 -2.413467023223635e-08 -2.3576643174843603e-08 -2.413467023223635e-08 -2.385565670353998e-08 -2.5808751404414597e-08 -3.11100084496457e-08 -2.706431228354828e-08 -3.8782880488795985e-08 -4.1712522540107916e-08 -4.366561724098254e-08 -4.492117812011622e-08 -4.157301577575972e-08 -4.324709694793797e-08 -4.324709694793797e-08 -4.1433509011411543e-08 -3.487669108704675e-08 -2.4274176996584538e-08 -2.008897406613893e-08 -2.413467023223635e-08 -2.6924805519200093e-08 -2.385565670353998e-08 -1.813587936526431e-08 -2.5948258168762783e-08 -2.3018616117450855e-08 -2.3576643174843603e-08 -2.246058906005811e-08 -2.2600095824406296e-08 -2.2600095824406296e-08 -2.4413683760932724e-08 -2.985444757051202e-08 -2.6785298754851907e-08 -3.8085346667055053e-08 -4.1433509011411543e-08 -4.324709694793797e-08 -4.464216459141985e-08 -4.1852029304456096e-08 -4.366561724098254e-08 -4.3805124005330716e-08 -4.1852029304456096e-08 -3.5016197851394936e-08 -2.46926972896291e-08 -2.106552141657624e-08 -2.5390231111370035e-08 -2.7761846105289214e-08 -2.46926972896291e-08 -1.8833413187005247e-08 -2.7901352869637404e-08 -2.4274176996584538e-08 -2.46926972896291e-08 -2.3297629646147227e-08 -2.385565670353998e-08 -2.3716149939191793e-08 -2.4832204053977286e-08 -3.0551981392252956e-08 -2.6645791990503717e-08 -3.7387812845314116e-08 -4.059646842532242e-08 -4.227054959750066e-08 -4.29680834192416e-08 -3.961992107488511e-08 -4.087548195401879e-08 -3.989893460358149e-08 -3.6690279023573184e-08 -3.0970501685297515e-08 -2.3716149939191793e-08 -2.008897406613893e-08 -2.2739602588754482e-08 -2.413467023223635e-08 -2.106552141657624e-08 -1.7856865836567937e-08 -2.7761846105289214e-08 -2.4832204053977286e-08 -2.5390231111370035e-08 -2.455319052528091e-08 -2.4274176996584538e-08 -2.3437136410495414e-08 -2.3437136410495414e-08 -2.46926972896291e-08 -2.6924805519200093e-08 -3.152852874269026e-08 -3.54347181444395e-08 -3.822485343140324e-08 -3.8782880488795985e-08 -3.710879931661774e-08 -3.627175873052862e-08 -3.5992745201832246e-08 -3.4737184322698563e-08 -3.348162344356488e-08 -3.069148815660114e-08 -2.9156913748771087e-08 -3.0551981392252956e-08 -3.11100084496457e-08 -3.013346109920839e-08 -2.9575434041815645e-08 -2.7901352869637404e-08 -2.5669244640066407e-08 -2.6645791990503717e-08 -2.5669244640066407e-08 -2.5390231111370035e-08 -2.5390231111370035e-08 -2.552973787571822e-08 -2.552973787571822e-08 -2.4832204053977286e-08 -2.413467023223635e-08 -2.5669244640066407e-08 -2.7901352869637404e-08 -2.8598886691378335e-08 -2.8877900220074708e-08 -2.873839345572652e-08 -2.8180366398333776e-08 -2.7761846105289214e-08 -2.6785298754851907e-08 -2.6366778461807345e-08 -2.5669244640066407e-08 -2.7203819047896466e-08 -2.8180366398333776e-08 -2.7343325812244652e-08 -2.5808751404414597e-08 -2.455319052528091e-08 -2.2600095824406296e-08 -2.3716149939191793e-08 -2.3995163467888165e-08 -2.4413683760932724e-08 -2.46926972896291e-08 -2.5808751404414597e-08 -3.124951521399389e-08 -2.7203819047896466e-08 -3.822485343140324e-08 -4.129400224706335e-08 -4.29680834192416e-08 -4.436315106272346e-08 -4.087548195401879e-08 -4.2689069890545226e-08 -4.2828576654893406e-08 -4.101498871836698e-08 -3.445817079400219e-08 -2.385565670353998e-08 -2.0647001123531675e-08 -2.5250724347021848e-08 -2.6366778461807345e-08 -2.246058906005811e-08 -1.7438345543523375e-08 -2.6366778461807345e-08 -2.3297629646147227e-08 -2.385565670353998e-08 -2.3297629646147227e-08 -2.3995163467888165e-08 -2.4413683760932724e-08 -2.5250724347021848e-08 -3.0970501685297515e-08 -2.804085963398559e-08 -3.9340907546188736e-08 -4.2689069890545226e-08 -4.436315106272346e-08 -4.5479205177508965e-08 -4.199153606880429e-08 -4.3805124005330716e-08 -4.394463076967891e-08 -4.213104283315248e-08 -3.5016197851394936e-08 -2.46926972896291e-08 -2.0926014652228048e-08 -2.5948258168762783e-08 -2.7482832576592838e-08 -2.4413683760932724e-08 -1.813587936526431e-08 -2.6366778461807345e-08 -2.3576643174843603e-08 -2.413467023223635e-08 -2.3297629646147227e-08 -2.3437136410495414e-08 -2.3437136410495414e-08 -2.5250724347021848e-08 -3.11100084496457e-08 -2.7622339340941025e-08 -3.892238725314418e-08 -4.199153606880429e-08 -4.394463076967891e-08 -4.520019164881259e-08 -4.1712522540107916e-08 -4.3526110476634344e-08 -4.3526110476634344e-08 -4.1852029304456096e-08 -3.487669108704675e-08 -2.4413683760932724e-08 -2.106552141657624e-08 -2.552973787571822e-08 -2.6645791990503717e-08 -2.3576643174843603e-08 -1.7856865836567937e-08 -2.6785298754851907e-08 -2.385565670353998e-08 -2.455319052528091e-08 -2.385565670353998e-08 -2.3995163467888165e-08 -2.413467023223635e-08 -2.5390231111370035e-08 -3.1947049035734825e-08 -2.845937992703015e-08 -3.9759427839233295e-08 -4.310759018358978e-08 -4.5479205177508965e-08 -4.673476605664265e-08 -4.3386603712286164e-08 -4.50606848844644e-08 -4.478167135576803e-08 -4.2410056361848854e-08 -3.54347181444395e-08 -2.4971710818325472e-08 -2.1623548473968986e-08 -2.6924805519200093e-08 -2.7901352869637404e-08 -2.46926972896291e-08 -1.8972919951353434e-08 -2.7901352869637404e-08 -2.46926972896291e-08 -2.5250724347021848e-08 -2.385565670353998e-08 -2.455319052528091e-08 -2.46926972896291e-08 -2.5808751404414597e-08 -3.22260625644312e-08 -2.8319873162681962e-08 -3.948041431053692e-08 -4.2689069890545226e-08 -4.436315106272346e-08 -4.478167135576803e-08 -4.115449548271517e-08 -4.1852029304456096e-08 -4.1433509011411543e-08 -3.794583990270687e-08 -3.152852874269026e-08 -2.3995163467888165e-08 -2.1205028180924427e-08 -2.455319052528091e-08 -2.4413683760932724e-08 -2.1344534945272613e-08 -1.8414892893960685e-08 -2.943592727746746e-08 -2.650628522615553e-08 -2.6645791990503717e-08 -2.5390231111370035e-08 -2.552973787571822e-08 -2.5808751404414597e-08 -2.6227271697459155e-08 -2.7482832576592838e-08 -3.013346109920839e-08 -3.376063697226125e-08 -3.75273196096623e-08 -4.059646842532242e-08 -4.115449548271517e-08 -3.920140078184055e-08 -3.794583990270687e-08 -3.724830608096593e-08 -3.5992745201832246e-08 -3.459767755835038e-08 -3.2365569328779384e-08 -3.041247462790477e-08 -3.250507609312757e-08 -3.1668035507038446e-08 -3.027296786355658e-08 -2.9156913748771087e-08 -2.845937992703015e-08 -2.6366778461807345e-08 -2.6645791990503717e-08 -2.650628522615553e-08 -2.5948258168762783e-08 -2.4832204053977286e-08 -2.4971710818325472e-08 -2.46926972896291e-08 -2.4413683760932724e-08 -2.455319052528091e-08 -2.6366778461807345e-08 -2.845937992703015e-08 -2.943592727746746e-08 -3.013346109920839e-08 -2.9993954334860204e-08 -2.943592727746746e-08 -2.9017406984422894e-08 -2.845937992703015e-08 -2.804085963398559e-08 -2.7761846105289214e-08 -2.9296420513119273e-08 -2.943592727746746e-08 -2.845937992703015e-08 -2.706431228354828e-08 -2.6227271697459155e-08 -2.455319052528091e-08 -2.5808751404414597e-08 -2.5948258168762783e-08 -2.5948258168762783e-08 -2.5948258168762783e-08 -2.6924805519200093e-08 -3.208655580008301e-08 -2.8180366398333776e-08 -3.9340907546188736e-08 -4.227054959750066e-08 -4.422364429837528e-08 -4.533969841316077e-08 -4.1852029304456096e-08 -4.3526110476634344e-08 -4.394463076967891e-08 -4.199153606880429e-08 -3.54347181444395e-08 -2.455319052528091e-08 -2.2321082295709924e-08 -2.706431228354828e-08 -2.7203819047896466e-08 -2.3576643174843603e-08 -1.8414892893960685e-08 -2.8319873162681962e-08 -2.5250724347021848e-08 -2.6227271697459155e-08 -2.5808751404414597e-08 -2.5390231111370035e-08 -2.5390231111370035e-08 -2.6366778461807345e-08 -3.1947049035734825e-08 -2.873839345572652e-08 -4.045696166097423e-08 -4.3386603712286164e-08 -4.50606848844644e-08 -4.603723223490171e-08 -4.2689069890545226e-08 -4.408413753402709e-08 -4.436315106272346e-08 -4.2410056361848854e-08 -3.557422490878769e-08 -2.552973787571822e-08 -2.3018616117450855e-08 -2.8598886691378335e-08 -2.873839345572652e-08 -2.552973787571822e-08 -1.9670453773094368e-08 -2.9575434041815645e-08 -2.6785298754851907e-08 -2.7203819047896466e-08 -2.6785298754851907e-08 -2.6645791990503717e-08 -2.6366778461807345e-08 -2.8598886691378335e-08 -3.445817079400219e-08 -3.041247462790477e-08 -4.213104283315248e-08 -4.478167135576803e-08 -4.631624576359808e-08 -4.729279311403539e-08 -4.408413753402709e-08 -4.5897725470553524e-08 -4.5897725470553524e-08 -4.3805124005330716e-08 -3.682978578792137e-08 -2.6785298754851907e-08 -2.4832204053977286e-08 -2.9714940806163832e-08 -2.9017406984422894e-08 -2.5669244640066407e-08 -2.008897406613893e-08 -3.069148815660114e-08 -2.804085963398559e-08 -2.8319873162681962e-08 -2.6924805519200093e-08 -2.650628522615553e-08 -2.650628522615553e-08 -2.7343325812244652e-08 -3.362113020791307e-08 -2.9714940806163832e-08 -4.101498871836698e-08 -4.464216459141985e-08 -4.6455752527946275e-08 -4.7432299878383586e-08 -4.394463076967891e-08 -4.5897725470553524e-08 -4.5618711941857144e-08 -4.310759018358978e-08 -3.585323843748406e-08 -2.5390231111370035e-08 -2.2600095824406296e-08 -2.804085963398559e-08 -2.8180366398333776e-08 -2.4832204053977286e-08 -1.9251933480049806e-08 -2.8180366398333776e-08 -2.5390231111370035e-08 -2.5948258168762783e-08 -2.455319052528091e-08 -2.4971710818325472e-08 -2.5250724347021848e-08 -2.6785298754851907e-08 -3.376063697226125e-08 -2.9156913748771087e-08 -4.087548195401879e-08 -4.408413753402709e-08 -4.533969841316077e-08 -4.575821870620534e-08 -4.1852029304456096e-08 -4.2549563126197034e-08 -4.157301577575972e-08 -3.8085346667055053e-08 -3.1668035507038446e-08 -2.4274176996584538e-08 -2.2042068767013544e-08 -2.4971710818325472e-08 -2.413467023223635e-08 -2.1205028180924427e-08 -1.8414892893960685e-08 -2.9993954334860204e-08 -2.7343325812244652e-08 -2.7203819047896466e-08 -2.5669244640066407e-08 -2.5948258168762783e-08 -2.5948258168762783e-08 -2.650628522615553e-08 -2.7622339340941025e-08 -3.083099492094933e-08 -3.4318664029654005e-08 -3.8085346667055053e-08 -4.101498871836698e-08 -4.1712522540107916e-08 -3.961992107488511e-08 -3.850386696009961e-08 -3.794583990270687e-08 -3.627175873052862e-08 -3.487669108704675e-08 -3.2644582857475756e-08 -3.0970501685297515e-08 -3.3342116679216694e-08 -3.22260625644312e-08 -3.124951521399389e-08 -3.013346109920839e-08 -2.8877900220074708e-08 -2.7203819047896466e-08 -2.7343325812244652e-08 -2.706431228354828e-08 -2.6366778461807345e-08 -2.5111217582673662e-08 -2.5390231111370035e-08 -2.5111217582673662e-08 -2.5390231111370035e-08 -2.5390231111370035e-08 -2.6924805519200093e-08 -2.9156913748771087e-08 -3.013346109920839e-08 -3.041247462790477e-08 -3.041247462790477e-08 -3.013346109920839e-08 -2.9714940806163832e-08 -2.943592727746746e-08 -2.9017406984422894e-08 -2.9296420513119273e-08 -3.0970501685297515e-08 -3.083099492094933e-08 -2.9993954334860204e-08 -2.9017406984422894e-08 -2.8319873162681962e-08 -2.6645791990503717e-08 -2.7761846105289214e-08 -2.6924805519200093e-08 -2.706431228354828e-08 -2.7203819047896466e-08 -2.7622339340941025e-08 -3.2365569328779384e-08 -2.873839345572652e-08 -4.003844136792967e-08 -4.2689069890545226e-08 -4.478167135576803e-08 -4.5618711941857144e-08 -4.213104283315248e-08 -4.3805124005330716e-08 -4.408413753402709e-08 -4.199153606880429e-08 -3.515570461574312e-08 -2.46926972896291e-08 -2.3297629646147227e-08 -2.706431228354828e-08 -2.650628522615553e-08 -2.287910935310267e-08 -1.7996372600916123e-08 -2.8180366398333776e-08 -2.552973787571822e-08 -2.650628522615553e-08 -2.5948258168762783e-08 -2.5669244640066407e-08 -2.5808751404414597e-08 -2.7482832576592838e-08 -3.292359638617213e-08 -2.9296420513119273e-08 -4.129400224706335e-08 -4.422364429837528e-08 -4.603723223490171e-08 -4.687427282099083e-08 -4.3386603712286164e-08 -4.478167135576803e-08 -4.478167135576803e-08 -4.2828576654893406e-08 -3.613225196618043e-08 -2.5808751404414597e-08 -2.3716149939191793e-08 -2.845937992703015e-08 -2.8180366398333776e-08 -2.46926972896291e-08 -1.9809960537442554e-08 -3.11100084496457e-08 -2.9156913748771087e-08 -2.9156913748771087e-08 -2.8877900220074708e-08 -2.845937992703015e-08 -2.8319873162681962e-08 -3.013346109920839e-08 -3.585323843748406e-08 -3.1389021978342073e-08 -4.310759018358978e-08 -4.5479205177508965e-08 -4.673476605664265e-08 -4.771131340707996e-08 -4.422364429837528e-08 -4.603723223490171e-08 -4.6455752527946275e-08 -4.436315106272346e-08 -3.75273196096623e-08 -2.7343325812244652e-08 -2.552973787571822e-08 -2.9575434041815645e-08 -2.8877900220074708e-08 -2.552973787571822e-08 -2.0228480830487117e-08 -3.11100084496457e-08 -2.9017406984422894e-08 -2.9017406984422894e-08 -2.7482832576592838e-08 -2.6645791990503717e-08 -2.6645791990503717e-08 -2.7761846105289214e-08 -3.362113020791307e-08 -2.9575434041815645e-08 -4.129400224706335e-08 -4.408413753402709e-08 -4.5479205177508965e-08 -4.631624576359808e-08 -4.2828576654893406e-08 -4.492117812011622e-08 -4.50606848844644e-08 -4.29680834192416e-08 -3.585323843748406e-08 -2.6227271697459155e-08 -2.4274176996584538e-08 -2.873839345572652e-08 -2.8598886691378335e-08 -2.5250724347021848e-08 -1.9949467301790744e-08 -2.9296420513119273e-08 -2.6785298754851907e-08 -2.7901352869637404e-08 -2.6366778461807345e-08 -2.6785298754851907e-08 -2.6227271697459155e-08 -2.7901352869637404e-08 -3.417915726530581e-08 -2.9156913748771087e-08 -4.031745489662604e-08 -4.29680834192416e-08 -4.394463076967891e-08 -4.4502657827071654e-08 -4.087548195401879e-08 -4.157301577575972e-08 -4.059646842532242e-08 -3.710879931661774e-08 -3.0970501685297515e-08 -2.3576643174843603e-08 -2.1205028180924427e-08 -2.3576643174843603e-08 -2.2739602588754482e-08 -1.9809960537442554e-08 -1.7159332014827002e-08 -2.8180366398333776e-08 -2.5669244640066407e-08 -2.552973787571822e-08 -2.4413683760932724e-08 -2.4274176996584538e-08 -2.413467023223635e-08 -2.4413683760932724e-08 -2.5390231111370035e-08 -2.9017406984422894e-08 -3.2644582857475756e-08 -3.6550772259225e-08 -3.948041431053692e-08 -4.003844136792967e-08 -3.822485343140324e-08 -3.7387812845314116e-08 -3.7387812845314116e-08 -3.682978578792137e-08 -3.5295211380091315e-08 -3.2644582857475756e-08 -3.1668035507038446e-08 -3.320260991486851e-08 -3.1947049035734825e-08 -3.027296786355658e-08 -2.9156913748771087e-08 -2.7622339340941025e-08 -2.5390231111370035e-08 -2.5669244640066407e-08 -2.455319052528091e-08 -2.4413683760932724e-08 -2.385565670353998e-08 -2.385565670353998e-08 -2.385565670353998e-08 -2.4274176996584538e-08 -2.385565670353998e-08 -2.4832204053977286e-08 -2.6785298754851907e-08 -2.7901352869637404e-08 -2.8319873162681962e-08 -2.873839345572652e-08 -2.8319873162681962e-08 -2.8180366398333776e-08 -2.7901352869637404e-08 -2.7203819047896466e-08 -2.7901352869637404e-08 -2.8877900220074708e-08 -2.873839345572652e-08 -2.7901352869637404e-08 -2.7343325812244652e-08 -2.650628522615553e-08 -2.5111217582673662e-08 -2.5808751404414597e-08 -2.5669244640066407e-08 -2.650628522615553e-08 -2.6924805519200093e-08 -2.7901352869637404e-08 -3.278408962182394e-08 -2.8180366398333776e-08 -3.948041431053692e-08 -4.29680834192416e-08 -4.464216459141985e-08 -4.5618711941857144e-08 -4.2689069890545226e-08 -4.422364429837528e-08 -4.394463076967891e-08 -4.199153606880429e-08 -3.5713731673135874e-08 -2.5808751404414597e-08 -2.3297629646147227e-08 -2.608776493311097e-08 -2.5111217582673662e-08 -2.1763055238317172e-08 -1.729883877917519e-08 -2.6785298754851907e-08 -2.4413683760932724e-08 -2.455319052528091e-08 -2.4274176996584538e-08 -2.4274176996584538e-08 -2.4413683760932724e-08 -2.6227271697459155e-08 -3.083099492094933e-08 -2.7343325812244652e-08 -3.961992107488511e-08 -4.3386603712286164e-08 -4.50606848844644e-08 -4.603723223490171e-08 -4.310759018358978e-08 -4.464216459141985e-08 -4.478167135576803e-08 -4.29680834192416e-08 -3.6411265494876805e-08 -2.6366778461807345e-08 -2.3995163467888165e-08 -2.6924805519200093e-08 -2.6645791990503717e-08 -2.315812288179904e-08 -1.8693906422657058e-08 -2.8877900220074708e-08 -2.6645791990503717e-08 -2.6227271697459155e-08 -2.608776493311097e-08 -2.6366778461807345e-08 -2.6645791990503717e-08 -2.6645791990503717e-08 -3.208655580008301e-08 -2.8180366398333776e-08 -4.003844136792967e-08 -4.324709694793797e-08 -4.4502657827071654e-08 -4.61767389992499e-08 -4.2828576654893406e-08 -4.3805124005330716e-08 -4.492117812011622e-08 -4.324709694793797e-08 -3.6690279023573184e-08 -2.7343325812244652e-08 -2.5111217582673662e-08 -2.7343325812244652e-08 -2.650628522615553e-08 -2.3716149939191793e-08 -1.8972919951353434e-08 -2.943592727746746e-08 -2.7203819047896466e-08 -2.6924805519200093e-08 -2.6645791990503717e-08 -2.6227271697459155e-08 -2.6227271697459155e-08 -2.7622339340941025e-08 -3.250507609312757e-08 -2.804085963398559e-08 -4.003844136792967e-08 -4.2828576654893406e-08 -4.464216459141985e-08 -4.5897725470553524e-08 -4.2549563126197034e-08 -4.3805124005330716e-08 -4.408413753402709e-08 -4.2410056361848854e-08 -3.613225196618043e-08 -2.706431228354828e-08 -2.552973787571822e-08 -2.8180366398333776e-08 -2.7761846105289214e-08 -2.4971710818325472e-08 -2.008897406613893e-08 -2.9993954334860204e-08 -2.6645791990503717e-08 -2.6785298754851907e-08 -2.5948258168762783e-08 -2.5948258168762783e-08 -2.5390231111370035e-08 -2.6924805519200093e-08 -3.208655580008301e-08 -2.7622339340941025e-08 -3.86433737244478e-08 -4.1852029304456096e-08 -4.3386603712286164e-08 -4.436315106272346e-08 -4.129400224706335e-08 -4.1433509011411543e-08 -4.101498871836698e-08 -3.7806333138358674e-08 -3.22260625644312e-08 -2.5250724347021848e-08 -2.315812288179904e-08 -2.3995163467888165e-08 -2.3297629646147227e-08 -2.0647001123531675e-08 -1.7856865836567937e-08 -2.873839345572652e-08 -2.5948258168762783e-08 -2.5669244640066407e-08 -2.455319052528091e-08 -2.4413683760932724e-08 -2.4971710818325472e-08 -2.5390231111370035e-08 -2.6227271697459155e-08 -2.9714940806163832e-08 -3.4039650500957626e-08 -3.7387812845314116e-08 -4.087548195401879e-08 -4.115449548271517e-08 -3.920140078184055e-08 -3.7666826374010495e-08 -3.7387812845314116e-08 -3.696929255226956e-08 -3.5713731673135874e-08 -3.362113020791307e-08 -3.320260991486851e-08 -3.3342116679216694e-08 -3.124951521399389e-08 -2.9714940806163832e-08 -2.9575434041815645e-08 -2.8319873162681962e-08 -2.6227271697459155e-08 -2.6366778461807345e-08 -5.1338489280132814e-08 -2.4971710818325472e-08 -2.4832204053977286e-08 -2.5111217582673662e-08 -2.4832204053977286e-08 -2.3995163467888165e-08 -2.455319052528091e-08 -2.650628522615553e-08 -2.7482832576592838e-08 -2.8319873162681962e-08 -2.873839345572652e-08 -2.845937992703015e-08 -2.873839345572652e-08 -2.8319873162681962e-08 -2.8319873162681962e-08 -2.943592727746746e-08 -2.9156913748771087e-08 -2.8598886691378335e-08 -2.7761846105289214e-08 -2.7343325812244652e-08 -2.6227271697459155e-08 -2.552973787571822e-08 -2.5250724347021848e-08 -2.5808751404414597e-08 -2.6366778461807345e-08 -2.706431228354828e-08 -2.8877900220074708e-08 -3.208655580008301e-08 -4.3386603712286164e-08 -3.5016197851394936e-08 -4.324709694793797e-08 -4.5897725470553524e-08 -4.701377958533902e-08 -4.631624576359808e-08 -4.50606848844644e-08 -4.603723223490171e-08 -4.533969841316077e-08 -4.129400224706335e-08 -3.3063103150520315e-08 -2.7901352869637404e-08 -2.8319873162681962e-08 -2.7343325812244652e-08 -2.5111217582673662e-08 -2.1205028180924427e-08 -1.757785230787156e-08 -2.845937992703015e-08 -2.6924805519200093e-08 -2.7761846105289214e-08 -2.7761846105289214e-08 -2.7343325812244652e-08 -2.7901352869637404e-08 -2.9993954334860204e-08 -4.129400224706335e-08 -3.4737184322698563e-08 -4.2549563126197034e-08 -4.478167135576803e-08 -4.631624576359808e-08 -4.5618711941857144e-08 -4.436315106272346e-08 -4.5897725470553524e-08 -4.5618711941857144e-08 -4.1433509011411543e-08 -3.3342116679216694e-08 -2.8877900220074708e-08 -2.8877900220074708e-08 -2.8319873162681962e-08 -2.608776493311097e-08 -2.1902562002665358e-08 -1.757785230787156e-08 -2.7901352869637404e-08 -2.6366778461807345e-08 -2.6366778461807345e-08 -2.650628522615553e-08 -2.6645791990503717e-08 -2.6645791990503717e-08 -2.985444757051202e-08 -4.087548195401879e-08 -3.445817079400219e-08 -4.2549563126197034e-08 -4.464216459141985e-08 -4.61767389992499e-08 -4.520019164881259e-08 -4.3386603712286164e-08 -4.50606848844644e-08 -4.436315106272346e-08 -4.031745489662604e-08 -3.292359638617213e-08 -2.9017406984422894e-08 -2.8180366398333776e-08 -2.7482832576592838e-08 -2.5669244640066407e-08 -2.14840417096208e-08 -1.757785230787156e-08 -2.7901352869637404e-08 -2.6366778461807345e-08 -2.6227271697459155e-08 -2.5808751404414597e-08 -2.5808751404414597e-08 -2.6645791990503717e-08 -2.9296420513119273e-08 -4.101498871836698e-08 -3.417915726530581e-08 -4.213104283315248e-08 -4.464216459141985e-08 -4.631624576359808e-08 -4.533969841316077e-08 -4.3805124005330716e-08 -4.492117812011622e-08 -4.436315106272346e-08 -4.031745489662604e-08 -3.278408962182394e-08 -2.8598886691378335e-08 -2.8319873162681962e-08 -2.7761846105289214e-08 -2.608776493311097e-08 -2.2042068767013544e-08 -1.757785230787156e-08 -2.7203819047896466e-08 -2.5250724347021848e-08 -2.4971710818325472e-08 -2.46926972896291e-08 -2.4413683760932724e-08 -2.5390231111370035e-08 -2.8319873162681962e-08 -3.961992107488511e-08 -3.320260991486851e-08 -4.087548195401879e-08 -4.3386603712286164e-08 -4.478167135576803e-08 -4.394463076967891e-08 -4.1852029304456096e-08 -4.227054959750066e-08 -4.045696166097423e-08 -3.5992745201832246e-08 -3.013346109920839e-08 -2.7343325812244652e-08 -2.5948258168762783e-08 -2.4971710818325472e-08 -2.3297629646147227e-08 -2.0647001123531675e-08 -1.771735907221975e-08 -2.9156913748771087e-08 -2.7622339340941025e-08 -2.7203819047896466e-08 -2.650628522615553e-08 -2.6366778461807345e-08 -2.650628522615553e-08 -2.7203819047896466e-08 -2.9296420513119273e-08 -3.320260991486851e-08 -3.696929255226956e-08 -4.087548195401879e-08 -4.227054959750066e-08 -4.1712522540107916e-08 -4.031745489662604e-08 -4.003844136792967e-08 -3.86433737244478e-08 -3.7387812845314116e-08 -3.724830608096593e-08 -3.7387812845314116e-08 -3.5713731673135874e-08 -3.348162344356488e-08 -3.250507609312757e-08 -3.208655580008301e-08 -3.0970501685297515e-08 -2.9296420513119273e-08 -2.8180366398333776e-08 -2.8598886691378335e-08 -2.7761846105289214e-08 -2.6645791990503717e-08 -2.6227271697459155e-08 -2.6785298754851907e-08 -2.6227271697459155e-08 -2.5390231111370035e-08 -2.5808751404414597e-08 -2.8180366398333776e-08 -2.9156913748771087e-08 -2.985444757051202e-08 -3.013346109920839e-08 -3.041247462790477e-08 -3.083099492094933e-08 -3.0551981392252956e-08 -3.1389021978342073e-08 -3.292359638617213e-08 -3.1668035507038446e-08 -3.013346109920839e-08 -2.9575434041815645e-08 -2.873839345572652e-08 -2.7203819047896466e-08 -2.6645791990503717e-08 -2.5669244640066407e-08 -2.6366778461807345e-08 -2.5808751404414597e-08 -2.6366778461807345e-08 -2.7203819047896466e-08 -2.9017406984422894e-08 -3.515570461574312e-08 -2.9993954334860204e-08 -4.213104283315248e-08 -4.5479205177508965e-08 -4.729279311403539e-08 -4.82693404644727e-08 -4.520019164881259e-08 -4.673476605664265e-08 -4.7153286349687207e-08 -4.464216459141985e-08 -3.8085346667055053e-08 -3.11100084496457e-08 -2.943592727746746e-08 -2.8598886691378335e-08 -2.6924805519200093e-08 -2.3297629646147227e-08 -1.8693906422657058e-08 -2.9714940806163832e-08 -2.706431228354828e-08 -2.7901352869637404e-08 -2.7901352869637404e-08 -2.7901352869637404e-08 -2.8319873162681962e-08 -2.9156913748771087e-08 -3.515570461574312e-08 -3.069148815660114e-08 -4.2549563126197034e-08 -4.5479205177508965e-08 -4.7153286349687207e-08 -4.799032693577633e-08 -4.422364429837528e-08 -4.631624576359808e-08 -4.687427282099083e-08 -4.478167135576803e-08 -3.850386696009961e-08 -3.152852874269026e-08 -2.9017406984422894e-08 -2.8877900220074708e-08 -2.7343325812244652e-08 -2.3995163467888165e-08 -1.8972919951353434e-08 -2.9575434041815645e-08 -2.6924805519200093e-08 -2.706431228354828e-08 -2.5948258168762783e-08 -2.6227271697459155e-08 -2.6645791990503717e-08 -2.7901352869637404e-08 -3.376063697226125e-08 -2.9993954334860204e-08 -4.199153606880429e-08 -4.492117812011622e-08 -4.631624576359808e-08 -4.729279311403539e-08 -4.324709694793797e-08 -4.492117812011622e-08 -4.520019164881259e-08 -4.3386603712286164e-08 -3.7387812845314116e-08 -3.1668035507038446e-08 -2.873839345572652e-08 -2.873839345572652e-08 -2.6924805519200093e-08 -2.3576643174843603e-08 -1.82753861296125e-08 -2.8180366398333776e-08 -2.552973787571822e-08 -2.5669244640066407e-08 -2.4832204053977286e-08 -2.4832204053977286e-08 -2.5111217582673662e-08 -2.6785298754851907e-08 -3.278408962182394e-08 -2.9714940806163832e-08 -4.1852029304456096e-08 -4.492117812011622e-08 -4.6595259292294455e-08 -4.771131340707996e-08 -4.422364429837528e-08 -4.61767389992499e-08 -4.6595259292294455e-08 -4.4502657827071654e-08 -3.8364360195751426e-08 -3.152852874269026e-08 -2.873839345572652e-08 -2.8180366398333776e-08 -2.706431228354828e-08 -2.3576643174843603e-08 -1.855439965830887e-08 -2.8598886691378335e-08 -2.5948258168762783e-08 -2.6366778461807345e-08 -2.5390231111370035e-08 -2.5250724347021848e-08 -2.5390231111370035e-08 -2.6645791990503717e-08 -3.3063103150520315e-08 -2.9017406984422894e-08 -4.045696166097423e-08 -4.3386603712286164e-08 -4.492117812011622e-08 -4.5479205177508965e-08 -4.1852029304456096e-08 -4.2689069890545226e-08 -4.227054959750066e-08 -3.850386696009961e-08 -3.3063103150520315e-08 -2.9156913748771087e-08 -2.6227271697459155e-08 -2.5390231111370035e-08 -2.413467023223635e-08 -2.1623548473968986e-08 -1.8414892893960685e-08 -3.027296786355658e-08 -2.7761846105289214e-08 -2.8180366398333776e-08 -2.6785298754851907e-08 -2.6227271697459155e-08 -2.608776493311097e-08 -2.6645791990503717e-08 -2.7482832576592838e-08 -3.083099492094933e-08 -3.515570461574312e-08 -3.906189401749236e-08 -4.199153606880429e-08 -4.2828576654893406e-08 -4.1712522540107916e-08 -4.115449548271517e-08 -4.059646842532242e-08 -3.948041431053692e-08 -4.045696166097423e-08 -4.031745489662604e-08 -3.6550772259225e-08 -3.487669108704675e-08 -3.348162344356488e-08 -3.2365569328779384e-08 -3.124951521399389e-08 -2.985444757051202e-08 -2.8180366398333776e-08 -2.8598886691378335e-08 -2.7761846105289214e-08 -2.650628522615553e-08 -2.5669244640066407e-08 -2.5808751404414597e-08 -2.5808751404414597e-08 -2.5808751404414597e-08 -2.5808751404414597e-08 -2.7901352869637404e-08 -2.9575434041815645e-08 -3.013346109920839e-08 -3.083099492094933e-08 -3.0970501685297515e-08 -3.124951521399389e-08 -3.11100084496457e-08 -3.1668035507038446e-08 -3.292359638617213e-08 -3.1389021978342073e-08 -3.013346109920839e-08 -2.943592727746746e-08 -2.873839345572652e-08 -2.7482832576592838e-08 -2.6366778461807345e-08 -2.5111217582673662e-08 -2.6366778461807345e-08 -2.552973787571822e-08 -2.5808751404414597e-08 -2.6366778461807345e-08 -2.8319873162681962e-08 -3.459767755835038e-08 -3.013346109920839e-08 -4.227054959750066e-08 -4.5618711941857144e-08 -4.7432299878383586e-08 -4.812983370012452e-08 -4.533969841316077e-08 -4.7153286349687207e-08 -4.7432299878383586e-08 -4.50606848844644e-08 -3.86433737244478e-08 -3.1668035507038446e-08 -2.9296420513119273e-08 -2.8598886691378335e-08 -2.650628522615553e-08 -2.2739602588754482e-08 -1.813587936526431e-08 -2.9156913748771087e-08 -2.6785298754851907e-08 -2.7622339340941025e-08 -2.6785298754851907e-08 -2.7343325812244652e-08 -2.7622339340941025e-08 -2.9156913748771087e-08 -3.515570461574312e-08 -3.11100084496457e-08 -4.3526110476634344e-08 -4.6455752527946275e-08 -4.785082017142814e-08 -4.868786075751727e-08 -4.492117812011622e-08 -4.673476605664265e-08 -4.701377958533902e-08 -4.478167135576803e-08 -3.86433737244478e-08 -3.1947049035734825e-08 -2.8877900220074708e-08 -2.8598886691378335e-08 -2.7343325812244652e-08 -2.3995163467888165e-08 -1.8972919951353434e-08 -2.943592727746746e-08 -2.6924805519200093e-08 -2.7343325812244652e-08 -2.6366778461807345e-08 -2.6645791990503717e-08 -2.7203819047896466e-08 -2.8598886691378335e-08 -3.515570461574312e-08 -3.124951521399389e-08 -4.3386603712286164e-08 -4.631624576359808e-08 -4.799032693577633e-08 -4.9245887814910014e-08 -4.5479205177508965e-08 -4.7153286349687207e-08 -4.7153286349687207e-08 -4.50606848844644e-08 -3.9340907546188736e-08 -3.292359638617213e-08 -2.9714940806163832e-08 -2.9714940806163832e-08 -2.7761846105289214e-08 -2.455319052528091e-08 -1.911242671570162e-08 -2.985444757051202e-08 -2.7203819047896466e-08 -2.8319873162681962e-08 -2.7482832576592838e-08 -2.7622339340941025e-08 -2.8180366398333776e-08 -3.041247462790477e-08 -3.627175873052862e-08 -3.1947049035734825e-08 -4.436315106272346e-08 -4.785082017142814e-08 -4.93853945792582e-08 -5.036194192969551e-08 -4.7153286349687207e-08 -4.896687428621364e-08 -4.910638105056182e-08 -4.701377958533902e-08 -4.115449548271517e-08 -3.4039650500957626e-08 -3.083099492094933e-08 -2.9993954334860204e-08 -2.873839345572652e-08 -2.4971710818325472e-08 -1.9391440244397992e-08 -3.027296786355658e-08 -2.7622339340941025e-08 -2.873839345572652e-08 -2.7761846105289214e-08 -2.7901352869637404e-08 -2.8598886691378335e-08 -2.9575434041815645e-08 -3.557422490878769e-08 -3.0551981392252956e-08 -4.2689069890545226e-08 -4.520019164881259e-08 -4.687427282099083e-08 -4.729279311403539e-08 -4.3526110476634344e-08 -4.436315106272346e-08 -4.366561724098254e-08 -4.003844136792967e-08 -3.4737184322698563e-08 -3.027296786355658e-08 -2.6645791990503717e-08 -2.5808751404414597e-08 -2.4274176996584538e-08 -2.1623548473968986e-08 -1.855439965830887e-08 -2.9993954334860204e-08 -2.7343325812244652e-08 -2.7482832576592838e-08 -2.650628522615553e-08 -2.6785298754851907e-08 -2.6924805519200093e-08 -2.7343325812244652e-08 -2.8319873162681962e-08 -3.1947049035734825e-08 -3.613225196618043e-08 -3.989893460358149e-08 -4.29680834192416e-08 -4.3805124005330716e-08 -4.2410056361848854e-08 -4.087548195401879e-08 -4.059646842532242e-08 -3.961992107488511e-08 -4.129400224706335e-08 -4.045696166097423e-08 -3.6550772259225e-08 -3.4737184322698563e-08 -3.3063103150520315e-08 -3.180754227138664e-08 -3.027296786355658e-08 -2.9156913748771087e-08 -2.804085963398559e-08 -2.8877900220074708e-08 -2.8319873162681962e-08 -2.7761846105289214e-08 -2.706431228354828e-08 -2.6785298754851907e-08 -2.650628522615553e-08 -2.7343325812244652e-08 -2.6924805519200093e-08 -2.8180366398333776e-08 -2.9993954334860204e-08 -3.083099492094933e-08 -3.2365569328779384e-08 -3.1947049035734825e-08 -3.22260625644312e-08 -3.278408962182394e-08 -3.3342116679216694e-08 -3.4318664029654005e-08 -3.292359638617213e-08 -3.180754227138664e-08 -3.11100084496457e-08 -3.027296786355658e-08 -2.9156913748771087e-08 -2.7622339340941025e-08 -2.5669244640066407e-08 -2.6785298754851907e-08 -2.608776493311097e-08 -2.6227271697459155e-08 -2.7203819047896466e-08 -2.9017406984422894e-08 -3.5295211380091315e-08 -3.124951521399389e-08 -4.3805124005330716e-08 -4.687427282099083e-08 -4.840884722882089e-08 -4.882736752186545e-08 -4.5618711941857144e-08 -4.785082017142814e-08 -4.785082017142814e-08 -4.5618711941857144e-08 -3.961992107488511e-08 -3.2644582857475756e-08 -2.985444757051202e-08 -2.9156913748771087e-08 -2.706431228354828e-08 -2.315812288179904e-08 -1.855439965830887e-08 -2.985444757051202e-08 -2.7622339340941025e-08 -2.845937992703015e-08 -2.7761846105289214e-08 -2.7622339340941025e-08 -2.8180366398333776e-08 -2.985444757051202e-08 -3.613225196618043e-08 -3.1947049035734825e-08 -4.436315106272346e-08 -4.7153286349687207e-08 -4.8548353993169076e-08 -4.93853945792582e-08 -4.533969841316077e-08 -4.7153286349687207e-08 -4.7571806642731765e-08 -4.533969841316077e-08 -3.948041431053692e-08 -3.250507609312757e-08 -2.9296420513119273e-08 -2.8877900220074708e-08 -2.7482832576592838e-08 -2.413467023223635e-08 -1.8833413187005247e-08 -2.9714940806163832e-08 -2.7482832576592838e-08 -2.7901352869637404e-08 -2.7203819047896466e-08 -2.7482832576592838e-08 -2.804085963398559e-08 -2.943592727746746e-08 -3.585323843748406e-08 -3.208655580008301e-08 -4.4502657827071654e-08 -4.785082017142814e-08 -4.9245887814910014e-08 -5.0501448694043697e-08 -4.687427282099083e-08 -4.8548353993169076e-08 -4.8548353993169076e-08 -4.61767389992499e-08 -4.087548195401879e-08 -3.376063697226125e-08 -2.985444757051202e-08 -2.943592727746746e-08 -2.7901352869637404e-08 -2.4413683760932724e-08 -1.911242671570162e-08 -3.013346109920839e-08 -2.7622339340941025e-08 -2.8877900220074708e-08 -2.804085963398559e-08 -2.8598886691378335e-08 -2.9017406984422894e-08 -3.124951521399389e-08 -3.75273196096623e-08 -3.278408962182394e-08 -4.520019164881259e-08 -4.8548353993169076e-08 -4.9943421636650945e-08 -5.1338489280132814e-08 -4.812983370012452e-08 -4.980391487230276e-08 -4.9943421636650945e-08 -4.771131340707996e-08 -4.213104283315248e-08 -3.487669108704675e-08 -3.180754227138664e-08 -3.0551981392252956e-08 -2.9296420513119273e-08 -2.552973787571822e-08 -1.9670453773094368e-08 -3.069148815660114e-08 -2.8180366398333776e-08 -2.9017406984422894e-08 -2.845937992703015e-08 -2.9156913748771087e-08 -2.9993954334860204e-08 -3.069148815660114e-08 -3.682978578792137e-08 -3.1668035507038446e-08 -4.422364429837528e-08 -4.673476605664265e-08 -4.82693404644727e-08 -4.882736752186545e-08 -4.520019164881259e-08 -4.603723223490171e-08 -4.520019164881259e-08 -4.157301577575972e-08 -3.6550772259225e-08 -3.180754227138664e-08 -2.7622339340941025e-08 -2.6366778461807345e-08 -2.4832204053977286e-08 -2.218157553136173e-08 -1.911242671570162e-08 -3.1389021978342073e-08 -2.8877900220074708e-08 -2.8877900220074708e-08 -2.8319873162681962e-08 -2.8598886691378335e-08 -2.8877900220074708e-08 -2.9156913748771087e-08 -3.027296786355658e-08 -3.390014373660944e-08 -3.892238725314418e-08 -4.2689069890545226e-08 -4.5618711941857144e-08 -4.6595259292294455e-08 -4.520019164881259e-08 -4.3386603712286164e-08 -4.199153606880429e-08 -4.087548195401879e-08 -4.2410056361848854e-08 -4.101498871836698e-08 -3.7387812845314116e-08 -3.5713731673135874e-08 -3.362113020791307e-08 -3.250507609312757e-08 -3.083099492094933e-08 -2.985444757051202e-08 -2.8180366398333776e-08 -2.9017406984422894e-08 -2.845937992703015e-08 -2.7901352869637404e-08 -2.7482832576592838e-08 -2.7761846105289214e-08 -2.7203819047896466e-08 -2.804085963398559e-08 -2.7622339340941025e-08 -2.8877900220074708e-08 -3.069148815660114e-08 -3.152852874269026e-08 -3.2644582857475756e-08 -3.278408962182394e-08 -3.3063103150520315e-08 -3.376063697226125e-08 -3.417915726530581e-08 -3.515570461574312e-08 -3.348162344356488e-08 -3.22260625644312e-08 -3.1389021978342073e-08 -3.083099492094933e-08 -2.943592727746746e-08 -2.8319873162681962e-08 -2.6227271697459155e-08 -2.6924805519200093e-08 -2.6645791990503717e-08 -2.6645791990503717e-08 -2.7901352869637404e-08 -2.9296420513119273e-08 -3.585323843748406e-08 -3.1668035507038446e-08 -4.464216459141985e-08 -4.771131340707996e-08 -4.910638105056182e-08 -4.9943421636650945e-08 -4.631624576359808e-08 -4.82693404644727e-08 -4.812983370012452e-08 -4.5897725470553524e-08 -4.003844136792967e-08 -3.22260625644312e-08 -2.9296420513119273e-08 -2.8180366398333776e-08 -2.6366778461807345e-08 -2.287910935310267e-08 -1.8414892893960685e-08 -2.985444757051202e-08 -2.7482832576592838e-08 -2.8180366398333776e-08 -2.7761846105289214e-08 -2.7343325812244652e-08 -2.7901352869637404e-08 -2.9714940806163832e-08 -3.627175873052862e-08 -3.1947049035734825e-08 -4.478167135576803e-08 -4.785082017142814e-08 -4.9245887814910014e-08 -5.0222435165347324e-08 -4.631624576359808e-08 -4.799032693577633e-08 -4.82693404644727e-08 -4.6595259292294455e-08 -4.115449548271517e-08 -3.3342116679216694e-08 -2.9714940806163832e-08 -2.9156913748771087e-08 -2.7622339340941025e-08 -2.4274176996584538e-08 -1.9391440244397992e-08 -3.152852874269026e-08 -2.9296420513119273e-08 -2.9714940806163832e-08 -2.8598886691378335e-08 -2.845937992703015e-08 -2.9017406984422894e-08 -3.013346109920839e-08 -3.6550772259225e-08 -3.2644582857475756e-08 -4.575821870620534e-08 -4.882736752186545e-08 -5.008292840099913e-08 -5.0919968987088255e-08 -4.7153286349687207e-08 -4.896687428621364e-08 -4.896687428621364e-08 -4.701377958533902e-08 -4.199153606880429e-08 -3.348162344356488e-08 -2.943592727746746e-08 -2.8319873162681962e-08 -2.706431228354828e-08 -2.3576643174843603e-08 -1.8693906422657058e-08 -3.013346109920839e-08 -2.7901352869637404e-08 -2.845937992703015e-08 -2.7622339340941025e-08 -2.8180366398333776e-08 -2.845937992703015e-08 -2.985444757051202e-08 -3.6411265494876805e-08 -3.1947049035734825e-08 -4.478167135576803e-08 -4.785082017142814e-08 -4.93853945792582e-08 -5.078046222274007e-08 -4.729279311403539e-08 -4.896687428621364e-08 -4.9524901343606386e-08 -4.729279311403539e-08 -4.1712522540107916e-08 -3.390014373660944e-08 -3.0551981392252956e-08 -2.943592727746746e-08 -2.804085963398559e-08 -2.5390231111370035e-08 -2.1344534945272613e-08 -3.4737184322698563e-08 -3.180754227138664e-08 -3.208655580008301e-08 -3.1389021978342073e-08 -3.180754227138664e-08 -3.292359638617213e-08 -3.376063697226125e-08 -4.031745489662604e-08 -3.417915726530581e-08 -4.673476605664265e-08 -4.910638105056182e-08 -5.0222435165347324e-08 -5.064095545839188e-08 -4.687427282099083e-08 -4.7153286349687207e-08 -4.631624576359808e-08 -4.227054959750066e-08 -3.724830608096593e-08 -3.180754227138664e-08 -2.7482832576592838e-08 -2.5948258168762783e-08 -2.455319052528091e-08 -2.1902562002665358e-08 -1.9391440244397992e-08 -3.2644582857475756e-08 -3.041247462790477e-08 -3.069148815660114e-08 -2.985444757051202e-08 -2.9575434041815645e-08 -2.9575434041815645e-08 -3.027296786355658e-08 -3.1389021978342073e-08 -3.54347181444395e-08 -4.157301577575972e-08 -4.533969841316077e-08 -4.840884722882089e-08 -4.9245887814910014e-08 -4.7571806642731765e-08 -4.5897725470553524e-08 -4.422364429837528e-08 -4.324709694793797e-08 -4.310759018358978e-08 -4.115449548271517e-08 -3.75273196096623e-08 -3.585323843748406e-08 -3.4039650500957626e-08 -3.3063103150520315e-08 -3.1668035507038446e-08 -3.0551981392252956e-08 -2.873839345572652e-08 -2.9156913748771087e-08 -2.8319873162681962e-08 -2.7761846105289214e-08 -2.7901352869637404e-08 -2.8319873162681962e-08 -2.804085963398559e-08 -2.873839345572652e-08 -2.845937992703015e-08 -2.9156913748771087e-08 -3.0970501685297515e-08 -3.22260625644312e-08 -3.278408962182394e-08 -3.3063103150520315e-08 -3.292359638617213e-08 -3.278408962182394e-08 -3.3342116679216694e-08 -3.459767755835038e-08 -3.390014373660944e-08 -3.3063103150520315e-08 -3.2365569328779384e-08 -3.1947049035734825e-08 -3.069148815660114e-08 -2.943592727746746e-08 -2.7343325812244652e-08 -2.804085963398559e-08 -2.7901352869637404e-08 -2.8598886691378335e-08 -2.9296420513119273e-08 -3.069148815660114e-08 -3.7387812845314116e-08 -3.250507609312757e-08 -4.575821870620534e-08 -4.896687428621364e-08 -5.036194192969551e-08 -5.119898251578463e-08 -4.771131340707996e-08 -4.9524901343606386e-08 -4.966440810795457e-08 -4.7432299878383586e-08 -4.115449548271517e-08 -3.208655580008301e-08 -2.845937992703015e-08 -2.706431228354828e-08 -2.5390231111370035e-08 -2.246058906005811e-08 -1.8972919951353434e-08 -3.1668035507038446e-08 -2.943592727746746e-08 -3.013346109920839e-08 -2.9296420513119273e-08 -2.9296420513119273e-08 -2.985444757051202e-08 -3.152852874269026e-08 -3.822485343140324e-08 -3.320260991486851e-08 -4.6455752527946275e-08 -4.93853945792582e-08 -5.078046222274007e-08 -5.175700957317738e-08 -4.82693404644727e-08 -4.9943421636650945e-08 -5.0222435165347324e-08 -4.868786075751727e-08 -4.29680834192416e-08 -3.4318664029654005e-08 -3.013346109920839e-08 -2.943592727746746e-08 -2.7901352869637404e-08 -2.4832204053977286e-08 -2.078650788787986e-08 -3.5016197851394936e-08 -3.2365569328779384e-08 -3.278408962182394e-08 -3.152852874269026e-08 -3.0970501685297515e-08 -3.1389021978342073e-08 -3.3063103150520315e-08 -4.003844136792967e-08 -3.417915726530581e-08 -4.840884722882089e-08 -5.0919968987088255e-08 -5.203602310187375e-08 -5.2873063687962876e-08 -4.910638105056182e-08 -5.0919968987088255e-08 -5.0501448694043697e-08 -4.840884722882089e-08 -4.29680834192416e-08 -3.376063697226125e-08 -2.9296420513119273e-08 -2.7901352869637404e-08 -2.650628522615553e-08 -2.3437136410495414e-08 -1.9809960537442554e-08 -3.22260625644312e-08 -3.041247462790477e-08 -3.083099492094933e-08 -3.0551981392252956e-08 -3.041247462790477e-08 -3.11100084496457e-08 -3.22260625644312e-08 -3.892238725314418e-08 -3.3342116679216694e-08 -4.701377958533902e-08 -5.008292840099913e-08 -5.105947575143644e-08 -5.217552986622194e-08 -4.882736752186545e-08 -5.0222435165347324e-08 -5.036194192969551e-08 -4.840884722882089e-08 -4.2689069890545226e-08 -3.4039650500957626e-08 -3.027296786355658e-08 -2.9017406984422894e-08 -2.7482832576592838e-08 -2.4971710818325472e-08 -2.1902562002665358e-08 -3.7387812845314116e-08 -3.54347181444395e-08 -3.6550772259225e-08 -3.557422490878769e-08 -3.54347181444395e-08 -3.613225196618043e-08 -3.710879931661774e-08 -4.3386603712286164e-08 -3.585323843748406e-08 -4.840884722882089e-08 -5.064095545839188e-08 -5.175700957317738e-08 -5.1896516337525566e-08 -4.799032693577633e-08 -4.840884722882089e-08 -4.729279311403539e-08 -4.3386603712286164e-08 -3.822485343140324e-08 -3.152852874269026e-08 -2.7203819047896466e-08 -2.5669244640066407e-08 -2.4274176996584538e-08 -2.2042068767013544e-08 -2.008897406613893e-08 -3.445817079400219e-08 -3.180754227138664e-08 -3.22260625644312e-08 -3.11100084496457e-08 -3.083099492094933e-08 -3.180754227138664e-08 -3.278408962182394e-08 -3.376063697226125e-08 -3.7806333138358674e-08 -4.3805124005330716e-08 -4.729279311403539e-08 -5.0222435165347324e-08 -5.0501448694043697e-08 -4.799032693577633e-08 -4.631624576359808e-08 -4.50606848844644e-08 -4.3805124005330716e-08 -4.324709694793797e-08 -4.157301577575972e-08 -3.822485343140324e-08 -3.6411265494876805e-08 -3.515570461574312e-08 -3.417915726530581e-08 -3.3063103150520315e-08 -3.1668035507038446e-08 -2.985444757051202e-08 -3.041247462790477e-08 -2.9575434041815645e-08 -2.9156913748771087e-08 -2.9575434041815645e-08 -2.9714940806163832e-08 -2.9714940806163832e-08 -3.041247462790477e-08 -3.0551981392252956e-08 -3.083099492094933e-08 -3.250507609312757e-08 -3.390014373660944e-08 -3.459767755835038e-08 -3.4737184322698563e-08 -3.417915726530581e-08 -3.390014373660944e-08 -3.5016197851394936e-08 -3.627175873052862e-08 -3.5992745201832246e-08 -3.5016197851394936e-08 -3.4318664029654005e-08 -3.376063697226125e-08 -3.2644582857475756e-08 -3.152852874269026e-08 -2.9575434041815645e-08 -3.0551981392252956e-08 -3.027296786355658e-08 -3.083099492094933e-08 -3.124951521399389e-08 -3.250507609312757e-08 -3.906189401749236e-08 -3.376063697226125e-08 -4.7571806642731765e-08 -4.9943421636650945e-08 -5.119898251578463e-08 -5.203602310187375e-08 -4.840884722882089e-08 -5.0222435165347324e-08 -5.0501448694043697e-08 -4.82693404644727e-08 -4.199153606880429e-08 -3.292359638617213e-08 -2.8598886691378335e-08 -2.7482832576592838e-08 -2.5808751404414597e-08 -2.2739602588754482e-08 -1.911242671570162e-08 -3.2644582857475756e-08 -3.027296786355658e-08 -3.0970501685297515e-08 -3.013346109920839e-08 -3.083099492094933e-08 -3.22260625644312e-08 -3.4737184322698563e-08 -4.199153606880429e-08 -3.5295211380091315e-08 -4.896687428621364e-08 -5.1896516337525566e-08 -5.343109074535562e-08 -5.48261583888375e-08 -5.147799604448101e-08 -5.315207721665925e-08 -5.2594050159266504e-08 -5.008292840099913e-08 -4.436315106272346e-08 -3.5295211380091315e-08 -3.027296786355658e-08 -2.9296420513119273e-08 -2.7761846105289214e-08 -2.4832204053977286e-08 -2.0926014652228048e-08 -3.54347181444395e-08 -3.250507609312757e-08 -3.3063103150520315e-08 -3.208655580008301e-08 -3.1668035507038446e-08 -3.2365569328779384e-08 -3.417915726530581e-08 -4.129400224706335e-08 -3.5016197851394936e-08 -4.966440810795457e-08 -5.2594050159266504e-08 -5.3989117802748366e-08 -5.4965665153185677e-08 -5.0501448694043697e-08 -5.203602310187375e-08 -5.175700957317738e-08 -4.93853945792582e-08 -4.394463076967891e-08 -3.5016197851394936e-08 -3.027296786355658e-08 -2.9017406984422894e-08 -2.7482832576592838e-08 -2.46926972896291e-08 -2.078650788787986e-08 -3.417915726530581e-08 -3.208655580008301e-08 -3.208655580008301e-08 -3.152852874269026e-08 -3.1668035507038446e-08 -3.208655580008301e-08 -3.320260991486851e-08 -4.017794813227786e-08 -3.4039650500957626e-08 -4.82693404644727e-08 -5.105947575143644e-08 -5.217552986622194e-08 -5.2873063687962876e-08 -4.980391487230276e-08 -5.119898251578463e-08 -5.1338489280132814e-08 -4.9245887814910014e-08 -4.3526110476634344e-08 -3.487669108704675e-08 -3.083099492094933e-08 -2.9017406984422894e-08 -2.7761846105289214e-08 -2.46926972896291e-08 -2.1205028180924427e-08 -3.627175873052862e-08 -3.459767755835038e-08 -3.54347181444395e-08 -3.417915726530581e-08 -3.390014373660944e-08 -3.4039650500957626e-08 -3.585323843748406e-08 -4.2410056361848854e-08 -3.4737184322698563e-08 -4.812983370012452e-08 -5.105947575143644e-08 -5.217552986622194e-08 -5.245454339491831e-08 -4.882736752186545e-08 -4.910638105056182e-08 -4.771131340707996e-08 -4.436315106272346e-08 -3.9340907546188736e-08 -3.250507609312757e-08 -2.8180366398333776e-08 -2.650628522615553e-08 -2.5111217582673662e-08 -2.3297629646147227e-08 -2.1344534945272613e-08 -3.6411265494876805e-08 -3.376063697226125e-08 -3.4039650500957626e-08 -3.2644582857475756e-08 -3.22260625644312e-08 -3.3063103150520315e-08 -3.362113020791307e-08 -3.459767755835038e-08 -3.7806333138358674e-08 -4.3526110476634344e-08 -4.6455752527946275e-08 -4.93853945792582e-08 -5.008292840099913e-08 -4.771131340707996e-08 -4.603723223490171e-08 -4.4502657827071654e-08 -4.310759018358978e-08 -4.29680834192416e-08 -4.1433509011411543e-08 -3.8782880488795985e-08 -3.724830608096593e-08 -3.6690279023573184e-08 -3.5713731673135874e-08 -3.445817079400219e-08 -3.362113020791307e-08 -3.152852874269026e-08 -3.180754227138664e-08 -3.0970501685297515e-08 -3.0970501685297515e-08 -3.1389021978342073e-08 -3.1389021978342073e-08 -3.152852874269026e-08 -3.1668035507038446e-08 -3.180754227138664e-08 -3.1947049035734825e-08 -3.376063697226125e-08 -3.515570461574312e-08 -3.5992745201832246e-08 -3.613225196618043e-08 -3.585323843748406e-08 -3.5713731673135874e-08 -3.6690279023573184e-08 -3.75273196096623e-08 -3.6411265494876805e-08 -3.557422490878769e-08 -3.4737184322698563e-08 -3.376063697226125e-08 -3.250507609312757e-08 -3.22260625644312e-08 -3.069148815660114e-08 -3.22260625644312e-08 -3.250507609312757e-08 -3.208655580008301e-08 -3.1947049035734825e-08 -3.320260991486851e-08 -3.9759427839233295e-08 -3.250507609312757e-08 -4.533969841316077e-08 -4.7571806642731765e-08 -4.910638105056182e-08 -4.9943421636650945e-08 -4.673476605664265e-08 -4.799032693577633e-08 -4.840884722882089e-08 -4.6595259292294455e-08 -4.115449548271517e-08 -3.2644582857475756e-08 -2.8319873162681962e-08 -2.7203819047896466e-08 -2.552973787571822e-08 -2.287910935310267e-08 -1.9809960537442554e-08 -3.362113020791307e-08 -3.180754227138664e-08 -3.278408962182394e-08 -3.208655580008301e-08 -3.22260625644312e-08 -3.348162344356488e-08 -3.5992745201832246e-08 -4.2549563126197034e-08 -3.445817079400219e-08 -4.771131340707996e-08 -5.105947575143644e-08 -5.273355692361469e-08 -5.3989117802748366e-08 -5.0919968987088255e-08 -5.203602310187375e-08 -5.105947575143644e-08 -4.812983370012452e-08 -4.310759018358978e-08 -3.417915726530581e-08 -2.9575434041815645e-08 -2.8319873162681962e-08 -2.706431228354828e-08 -2.455319052528091e-08 -2.106552141657624e-08 -3.5713731673135874e-08 -3.250507609312757e-08 -3.320260991486851e-08 -3.22260625644312e-08 -3.22260625644312e-08 -3.3063103150520315e-08 -3.417915726530581e-08 -4.087548195401879e-08 -3.445817079400219e-08 -4.840884722882089e-08 -5.161750280882919e-08 -5.315207721665925e-08 -5.3570597509703814e-08 -4.966440810795457e-08 -5.105947575143644e-08 -5.078046222274007e-08 -4.840884722882089e-08 -4.310759018358978e-08 -3.417915726530581e-08 -2.9575434041815645e-08 -2.845937992703015e-08 -2.7203819047896466e-08 -2.4274176996584538e-08 -2.050749435918349e-08 -3.417915726530581e-08 -3.152852874269026e-08 -3.152852874269026e-08 -3.041247462790477e-08 -3.11100084496457e-08 -3.1389021978342073e-08 -3.292359638617213e-08 -3.9759427839233295e-08 -3.3342116679216694e-08 -4.687427282099083e-08 -4.93853945792582e-08 -5.078046222274007e-08 -5.1338489280132814e-08 -4.82693404644727e-08 -4.9524901343606386e-08 -4.980391487230276e-08 -4.7432299878383586e-08 -4.1852029304456096e-08 -3.362113020791307e-08 -2.9714940806163832e-08 -2.8180366398333776e-08 -2.706431228354828e-08 -2.4413683760932724e-08 -2.106552141657624e-08 -3.5713731673135874e-08 -3.292359638617213e-08 -3.3063103150520315e-08 -3.180754227138664e-08 -3.1947049035734825e-08 -3.1947049035734825e-08 -3.376063697226125e-08 -3.920140078184055e-08 -3.0970501685297515e-08 -4.2689069890545226e-08 -4.575821870620534e-08 -4.6595259292294455e-08 -4.701377958533902e-08 -4.3805124005330716e-08 -4.310759018358978e-08 -4.1712522540107916e-08 -3.86433737244478e-08 -3.487669108704675e-08 -2.9993954334860204e-08 -2.650628522615553e-08 -2.4971710818325472e-08 -2.385565670353998e-08 -2.218157553136173e-08 -2.0647001123531675e-08 -3.54347181444395e-08 -3.376063697226125e-08 -3.390014373660944e-08 -3.278408962182394e-08 -3.292359638617213e-08 -3.3063103150520315e-08 -3.3342116679216694e-08 -3.390014373660944e-08 -3.6411265494876805e-08 -4.1852029304456096e-08 -4.4502657827071654e-08 -4.729279311403539e-08 -4.868786075751727e-08 -4.673476605664265e-08 -4.533969841316077e-08 -4.394463076967891e-08 -4.2549563126197034e-08 -4.2410056361848854e-08 -4.115449548271517e-08 -3.9340907546188736e-08 -3.822485343140324e-08 -3.7666826374010495e-08 -3.682978578792137e-08 -3.54347181444395e-08 -3.5016197851394936e-08 -3.445817079400219e-08 -3.459767755835038e-08 -3.362113020791307e-08 -3.390014373660944e-08 -3.4318664029654005e-08 -3.4318664029654005e-08 -3.4318664029654005e-08 -3.4039650500957626e-08 -3.417915726530581e-08 -3.390014373660944e-08 -3.54347181444395e-08 -3.696929255226956e-08 -3.8085346667055053e-08 -3.7666826374010495e-08 -3.75273196096623e-08 -3.75273196096623e-08 -3.822485343140324e-08 -3.948041431053692e-08 -3.794583990270687e-08 -3.7387812845314116e-08 -3.682978578792137e-08 -3.5713731673135874e-08 -3.417915726530581e-08 -3.4039650500957626e-08 -3.1389021978342073e-08 -3.278408962182394e-08 -3.278408962182394e-08 -3.278408962182394e-08 -3.2365569328779384e-08 -3.362113020791307e-08 -3.906189401749236e-08 -2.9017406984422894e-08 -3.8782880488795985e-08 -4.1433509011411543e-08 -4.2549563126197034e-08 -4.2828576654893406e-08 -4.0735975189670606e-08 -4.1433509011411543e-08 -4.157301577575972e-08 -4.031745489662604e-08 -3.613225196618043e-08 -2.9575434041815645e-08 -2.5948258168762783e-08 -2.4413683760932724e-08 -2.315812288179904e-08 -2.14840417096208e-08 -1.9670453773094368e-08 -3.4039650500957626e-08 -3.124951521399389e-08 -3.22260625644312e-08 -3.11100084496457e-08 -3.11100084496457e-08 -3.152852874269026e-08 -3.292359638617213e-08 -3.75273196096623e-08 -2.9156913748771087e-08 -3.961992107488511e-08 -4.310759018358978e-08 -4.492117812011622e-08 -4.520019164881259e-08 -4.29680834192416e-08 -4.3526110476634344e-08 -4.324709694793797e-08 -4.115449548271517e-08 -3.710879931661774e-08 -3.041247462790477e-08 -2.6645791990503717e-08 -2.5390231111370035e-08 -2.4413683760932724e-08 -2.287910935310267e-08 -2.078650788787986e-08 -3.557422490878769e-08 -3.124951521399389e-08 -3.22260625644312e-08 -3.11100084496457e-08 -3.11100084496457e-08 -3.152852874269026e-08 -3.292359638617213e-08 -3.75273196096623e-08 -2.9156913748771087e-08 -3.961992107488511e-08 -4.310759018358978e-08 -4.492117812011622e-08 -4.520019164881259e-08 -4.29680834192416e-08 -4.3526110476634344e-08 -4.324709694793797e-08 -4.115449548271517e-08 -3.710879931661774e-08 -3.041247462790477e-08 -2.6645791990503717e-08 -2.5390231111370035e-08 -2.4413683760932724e-08 -2.287910935310267e-08 -2.078650788787986e-08 -3.557422490878769e-08 -3.11100084496457e-08 -3.124951521399389e-08 -3.124951521399389e-08 -3.1389021978342073e-08 -3.0551981392252956e-08 -3.1389021978342073e-08 -3.320260991486851e-08 -3.920140078184055e-08 -4.840884722882089e-08 -5.203602310187375e-08 -5.3570597509703814e-08 -5.4965665153185677e-08 -5.3710104274051994e-08 -5.3291583981007435e-08 -5.4268131331444745e-08 -5.315207721665925e-08 -5.064095545839188e-08 -4.575821870620534e-08 -4.087548195401879e-08 -3.906189401749236e-08 -3.7387812845314116e-08 -3.5713731673135874e-08 -3.348162344356488e-08 -3.22260625644312e-08 -3.1389021978342073e-08 -3.278408962182394e-08 -3.1947049035734825e-08 -3.1389021978342073e-08 -3.11100084496457e-08 -3.152852874269026e-08 -3.4737184322698563e-08 -2.4832204053977286e-08 -3.2365569328779384e-08 -3.487669108704675e-08 -3.5713731673135874e-08 -3.585323843748406e-08 -3.390014373660944e-08 -3.3063103150520315e-08 -3.22260625644312e-08 -2.9993954334860204e-08 -2.804085963398559e-08 -2.5390231111370035e-08 -2.2739602588754482e-08 -2.1763055238317172e-08 -2.0926014652228048e-08 -1.9670453773094368e-08 -1.8414892893960685e-08 -3.2365569328779384e-08 -3.11100084496457e-08 -3.1389021978342073e-08 -3.124951521399389e-08 -3.152852874269026e-08 -3.2365569328779384e-08 -3.292359638617213e-08 -3.4039650500957626e-08 -3.6550772259225e-08 -3.9759427839233295e-08 -4.129400224706335e-08 -4.29680834192416e-08 -4.3386603712286164e-08 -4.1852029304456096e-08 -4.115449548271517e-08 -4.0735975189670606e-08 -3.989893460358149e-08 -3.961992107488511e-08 -3.906189401749236e-08 -3.6690279023573184e-08 -3.5992745201832246e-08 -3.487669108704675e-08 -3.348162344356488e-08 -3.2365569328779384e-08 -3.1947049035734825e-08 -2.9993954334860204e-08 -3.041247462790477e-08 -2.9714940806163832e-08 -2.943592727746746e-08 -2.8877900220074708e-08 -2.9296420513119273e-08 -2.9714940806163832e-08 -3.041247462790477e-08 -3.069148815660114e-08 -3.027296786355658e-08 -3.1668035507038446e-08 -3.250507609312757e-08 -3.3342116679216694e-08 -3.3063103150520315e-08 -3.376063697226125e-08 -3.3063103150520315e-08 -3.417915726530581e-08 -3.5295211380091315e-08 -3.390014373660944e-08 -3.362113020791307e-08 -3.2365569328779384e-08 -3.1389021978342073e-08 -3.0551981392252956e-08 -2.9714940806163832e-08 -2.7901352869637404e-08 -2.8877900220074708e-08 -2.8319873162681962e-08 -2.845937992703015e-08 -2.845937992703015e-08 -2.9993954334860204e-08 -3.292359638617213e-08 -2.2739602588754482e-08 -2.9156913748771087e-08 -3.1389021978342073e-08 -3.208655580008301e-08 -3.180754227138664e-08 -3.0970501685297515e-08 -3.11100084496457e-08 -3.0970501685297515e-08 -2.985444757051202e-08 -2.7622339340941025e-08 -2.3995163467888165e-08 -2.0926014652228048e-08 -1.9949467301790744e-08 -1.9391440244397992e-08 -1.8414892893960685e-08 -1.7019825250478813e-08 -2.943592727746746e-08 -2.873839345572652e-08 \ No newline at end of file diff --git a/examples/curve_examples/electric_vehicle_profile_5_curve.csv b/examples/curve_examples/electric_vehicle_profile_5_curve.csv deleted file mode 100644 index 7e359fa..0000000 --- a/examples/curve_examples/electric_vehicle_profile_5_curve.csv +++ /dev/null @@ -1,8760 +0,0 @@ -4.058029003214125e-08 -4.199957496152364e-08 -3.8220513109021064e-08 -2.9482090031937756e-08 -2.0295527943857224e-08 -1.2272828807132413e-08 -7.909041287429164e-09 -2.7023941130793784e-08 -5.623902150809556e-08 -6.116353752074473e-08 -4.788438885488115e-08 -4.177447817972987e-08 -3.70509795925161e-08 -4.020299199445773e-08 -3.430708351711257e-08 -3.320773351709241e-08 -3.342009207282629e-08 -2.01240138936186e-08 -3.3284738148177025e-08 -3.7428935087028526e-08 -3.84359945846922e-08 -3.5739353218865674e-08 -3.6394180220447543e-08 -3.901299513415333e-08 -4.3137221821827065e-08 -4.205693806984494e-08 -3.7772045369609385e-08 -3.055111483572502e-08 -2.059664317149226e-08 -1.2367913501011706e-08 -8.901061460131813e-09 -2.525332770846932e-08 -5.172262182198448e-08 -5.70589523558343e-08 -4.648310180618983e-08 -4.8967466798386086e-08 -4.7003478886262174e-08 -4.489665847806027e-08 -4.6052878493780057e-08 -4.4395429828129577e-08 -3.9255103611394826e-08 -2.356234874454507e-08 -3.4071138697641997e-08 -3.6228501099565384e-08 -3.5698755259681256e-08 -3.355322708067803e-08 -3.125812747310062e-08 -3.29047281010743e-08 -3.9551534459123965e-08 -4.324603092700959e-08 -4.066715651565933e-08 -3.5057981397817076e-08 -2.6684282496564638e-08 -1.8025411695777923e-08 -1.1288615934272923e-08 -2.2971377237469868e-08 -4.531348610758126e-08 -4.75251708799923e-08 -3.7950462716551433e-08 -4.585966836818782e-08 -5.327356248135359e-08 -5.363993029925671e-08 -4.869256766180334e-08 -4.633155800712897e-08 -3.908005573070087e-08 -2.822133438042327e-08 -2.6735892857633082e-08 -2.5060281947084308e-08 -2.5567509890578696e-08 -2.4324341209237218e-08 -2.3789417896825527e-08 -2.668937778698859e-08 -3.114709945112056e-08 -3.1219912794920955e-08 -3.0739394035100524e-08 -2.6577856672386862e-08 -2.163542496115024e-08 -1.518355455286867e-08 -1.0374175667380174e-08 -2.780919113080818e-08 -5.895653712823958e-08 -6.21563795144835e-08 -4.7528375982033175e-08 -3.9731348901827415e-08 -4.7043994663342966e-08 -4.2682426060437265e-08 -4.05751947417173e-08 -3.943450714358022e-08 -3.751366483585268e-08 -2.3015591209213225e-08 -2.769890274776063e-08 -2.9947651648900766e-08 -3.1863152119893504e-08 -3.061965471013758e-08 -2.9692065306666882e-08 -2.995233602880666e-08 -3.151248108378032e-08 -2.993474905863365e-08 -2.7434522920440244e-08 -2.1560146154241483e-08 -1.4356145133701225e-08 -8.812386970334268e-09 -6.837222292119088e-09 -2.6956962716349854e-08 -5.889276381583652e-08 -6.76377614612088e-08 -5.616719434953852e-08 -4.510145628026183e-08 -4.4312014992963216e-08 -3.50095761387895e-08 -3.052974748878585e-08 -3.835192229269694e-08 -3.675915094258924e-08 -2.383404277908694e-08 -3.586032527538281e-08 -4.2238396154620635e-08 -4.198272763028314e-08 -3.921902566790907e-08 -3.7451535165521875e-08 -3.981164081705652e-08 -3.619875117805777e-08 -3.5683551570513e-08 -3.338015157047077e-08 -2.60633967037746e-08 -1.717556656232435e-08 -1.0051693092805972e-08 -6.039316248148413e-09 -7.532811617092595e-09 -2.2363969309672232e-08 -3.0926276138714626e-08 -2.8049327237562983e-08 -1.931599945090363e-08 -2.227126789679769e-08 -2.6531095055431525e-08 -2.6586814521680586e-08 -2.9027294270547942e-08 -3.035749379961472e-08 -2.0306869074155705e-08 -2.9707515542145974e-08 -3.5981050785589104e-08 -3.72628450556283e-08 -3.3846699372677125e-08 -3.481521546374669e-08 -3.7008902355466666e-08 -4.163164568365189e-08 -4.1501387049426586e-08 -3.647866342296087e-08 -2.823842825797461e-08 -2.0044132888907563e-08 -1.2029980690958416e-08 -5.6040798274182976e-09 -8.240810439711543e-09 -2.3401354003568804e-08 -2.9870729199919766e-08 -2.69640303772605e-08 -2.38378231558531e-08 -2.3706003061659163e-08 -2.568108555777073e-08 -2.4868140188839024e-08 -3.137079913715292e-08 -3.2018969388342203e-08 -1.7453917347258807e-08 -3.014990180589035e-08 -3.440274348571715e-08 -3.507121271649864e-08 -3.248535282634133e-08 -3.372835714347558e-08 -3.622652872907869e-08 -4.058029003214125e-08 -4.199957496152364e-08 -3.8220513109021064e-08 -2.9482090031937756e-08 -2.0295527943857224e-08 -1.2272828807132413e-08 -7.909041287429164e-09 -2.7023941130793784e-08 -5.623902150809556e-08 -6.116353752074473e-08 -4.788438885488115e-08 -4.177447817972987e-08 -3.70509795925161e-08 -4.020299199445773e-08 -3.430708351711257e-08 -3.320773351709241e-08 -3.342009207282629e-08 -2.01240138936186e-08 -3.3284738148177025e-08 -3.7428935087028526e-08 -3.84359945846922e-08 -3.5739353218865674e-08 -3.6394180220447543e-08 -3.901299513415333e-08 -4.3137221821827065e-08 -4.205693806984494e-08 -3.7772045369609385e-08 -3.055111483572502e-08 -2.059664317149226e-08 -1.2367913501011706e-08 -8.901061460131813e-09 -2.525332770846932e-08 -5.172262182198448e-08 -5.70589523558343e-08 -4.648310180618983e-08 -4.8967466798386086e-08 -4.7003478886262174e-08 -4.489665847806027e-08 -4.6052878493780057e-08 -4.4395429828129577e-08 -3.9255103611394826e-08 -2.356234874454507e-08 -3.4071138697641997e-08 -3.6228501099565384e-08 -3.5698755259681256e-08 -3.355322708067803e-08 -3.125812747310062e-08 -3.29047281010743e-08 -3.9551534459123965e-08 -4.324603092700959e-08 -4.066715651565933e-08 -3.5057981397817076e-08 -2.6684282496564638e-08 -1.8025411695777923e-08 -1.1288615934272923e-08 -2.2971377237469868e-08 -4.531348610758126e-08 -4.75251708799923e-08 -3.7950462716551433e-08 -4.585966836818782e-08 -5.327356248135359e-08 -5.363993029925671e-08 -4.869256766180334e-08 -4.633155800712897e-08 -3.908005573070087e-08 -2.822133438042327e-08 -2.6735892857633082e-08 -2.5060281947084308e-08 -2.5567509890578696e-08 -2.4324341209237218e-08 -2.3789417896825527e-08 -2.668937778698859e-08 -3.114709945112056e-08 -3.1219912794920955e-08 -3.0739394035100524e-08 -2.6577856672386862e-08 -2.163542496115024e-08 -1.518355455286867e-08 -1.0374175667380174e-08 -2.780919113080818e-08 -5.895653712823958e-08 -6.21563795144835e-08 -4.7528375982033175e-08 -3.9731348901827415e-08 -4.7043994663342966e-08 -4.2682426060437265e-08 -4.05751947417173e-08 -3.943450714358022e-08 -3.751366483585268e-08 -2.3015591209213225e-08 -2.769890274776063e-08 -2.9947651648900766e-08 -3.1863152119893504e-08 -3.061965471013758e-08 -2.9692065306666882e-08 -2.995233602880666e-08 -3.151248108378032e-08 -2.993474905863365e-08 -2.7434522920440244e-08 -2.1560146154241483e-08 -1.4356145133701225e-08 -8.812386970334268e-09 -6.837222292119088e-09 -2.6956962716349854e-08 -5.889276381583652e-08 -6.76377614612088e-08 -5.616719434953852e-08 -4.510145628026183e-08 -4.4312014992963216e-08 -3.50095761387895e-08 -3.052974748878585e-08 -3.835192229269694e-08 -3.675915094258924e-08 -2.383404277908694e-08 -3.586032527538281e-08 -4.2238396154620635e-08 -4.198272763028314e-08 -3.921902566790907e-08 -3.7451535165521875e-08 -3.981164081705652e-08 -3.619875117805777e-08 -3.5683551570513e-08 -3.338015157047077e-08 -2.60633967037746e-08 -1.717556656232435e-08 -1.0051693092805972e-08 -6.039316248148413e-09 -7.532811617092595e-09 -2.2363969309672232e-08 -3.0926276138714626e-08 -2.8049327237562983e-08 -1.931599945090363e-08 -2.227126789679769e-08 -2.6531095055431525e-08 -2.6586814521680586e-08 -2.9027294270547942e-08 -3.035749379961472e-08 -2.0306869074155705e-08 -2.9707515542145974e-08 -3.5981050785589104e-08 -3.72628450556283e-08 -3.3846699372677125e-08 -3.481521546374669e-08 -3.7008902355466666e-08 -4.163164568365189e-08 -4.1501387049426586e-08 -3.647866342296087e-08 -2.823842825797461e-08 -2.0044132888907563e-08 -1.2029980690958416e-08 -5.6040798274182976e-09 -8.240810439711543e-09 -2.3401354003568804e-08 -2.9870729199919766e-08 -2.69640303772605e-08 -2.38378231558531e-08 -2.3706003061659163e-08 -2.568108555777073e-08 -2.4868140188839024e-08 -3.137079913715292e-08 -3.2018969388342203e-08 -1.7453917347258807e-08 -3.014990180589035e-08 -3.440274348571715e-08 -3.507121271649864e-08 -3.248535282634133e-08 -3.372835714347558e-08 -3.622652872907869e-08 -4.058029003214125e-08 -4.199957496152364e-08 -3.8220513109021064e-08 -2.9482090031937756e-08 -2.0295527943857224e-08 -1.2272828807132413e-08 -7.909041287429164e-09 -2.7023941130793784e-08 -5.623902150809556e-08 -6.116353752074473e-08 -4.788438885488115e-08 -4.177447817972987e-08 -3.70509795925161e-08 -4.020299199445773e-08 -3.430708351711257e-08 -3.320773351709241e-08 -3.342009207282629e-08 -2.01240138936186e-08 -3.3284738148177025e-08 -3.7428935087028526e-08 -3.84359945846922e-08 -3.5739353218865674e-08 -3.6394180220447543e-08 -3.901299513415333e-08 -4.3137221821827065e-08 -4.205693806984494e-08 -3.7772045369609385e-08 -3.055111483572502e-08 -2.059664317149226e-08 -1.2367913501011706e-08 -8.901061460131813e-09 -2.525332770846932e-08 -5.172262182198448e-08 -5.70589523558343e-08 -4.648310180618983e-08 -4.8967466798386086e-08 -4.7003478886262174e-08 -4.489665847806027e-08 -4.6052878493780057e-08 -4.4395429828129577e-08 -3.9255103611394826e-08 -2.356234874454507e-08 -3.4071138697641997e-08 -3.6228501099565384e-08 -3.5698755259681256e-08 -3.355322708067803e-08 -3.125812747310062e-08 -3.29047281010743e-08 -3.9551534459123965e-08 -4.324603092700959e-08 -4.066715651565933e-08 -3.5057981397817076e-08 -2.6684282496564638e-08 -1.8025411695777923e-08 -1.1288615934272923e-08 -2.2971377237469868e-08 -4.531348610758126e-08 -4.75251708799923e-08 -3.7950462716551433e-08 -4.585966836818782e-08 -5.327356248135359e-08 -5.363993029925671e-08 -4.869256766180334e-08 -4.633155800712897e-08 -3.908005573070087e-08 -2.822133438042327e-08 -2.6735892857633082e-08 -2.5060281947084308e-08 -2.5567509890578696e-08 -2.4324341209237218e-08 -2.3789417896825527e-08 -2.668937778698859e-08 -3.114709945112056e-08 -3.1219912794920955e-08 -3.0739394035100524e-08 -2.6577856672386862e-08 -2.163542496115024e-08 -1.518355455286867e-08 -1.0374175667380174e-08 -2.780919113080818e-08 -5.895653712823958e-08 -6.21563795144835e-08 -4.7528375982033175e-08 -3.9731348901827415e-08 -4.7043994663342966e-08 -4.2682426060437265e-08 -4.05751947417173e-08 -3.943450714358022e-08 -3.751366483585268e-08 -2.3015591209213225e-08 -2.769890274776063e-08 -2.9947651648900766e-08 -3.1863152119893504e-08 -3.061965471013758e-08 -2.9692065306666882e-08 -2.995233602880666e-08 -3.151248108378032e-08 -2.993474905863365e-08 -2.7434522920440244e-08 -2.1560146154241483e-08 -1.4356145133701225e-08 -8.812386970334268e-09 -6.837222292119088e-09 -2.6956962716349854e-08 -5.889276381583652e-08 -6.76377614612088e-08 -5.616719434953852e-08 -4.510145628026183e-08 -4.4312014992963216e-08 -3.50095761387895e-08 -3.052974748878585e-08 -3.835192229269694e-08 -3.675915094258924e-08 -2.383404277908694e-08 -3.586032527538281e-08 -4.2238396154620635e-08 -4.198272763028314e-08 -3.921902566790907e-08 -3.7451535165521875e-08 -3.981164081705652e-08 -3.619875117805777e-08 -3.5683551570513e-08 -3.338015157047077e-08 -2.60633967037746e-08 -1.717556656232435e-08 -1.0051693092805972e-08 -6.039316248148413e-09 -7.532811617092595e-09 -2.2363969309672232e-08 -3.0926276138714626e-08 -2.8049327237562983e-08 -1.931599945090363e-08 -2.227126789679769e-08 -2.6531095055431525e-08 -2.6586814521680586e-08 -2.9027294270547942e-08 -3.035749379961472e-08 -2.0306869074155705e-08 -2.9707515542145974e-08 -3.5981050785589104e-08 -3.72628450556283e-08 -3.3846699372677125e-08 -3.481521546374669e-08 -3.7008902355466666e-08 -4.163164568365189e-08 -4.1501387049426586e-08 -3.647866342296087e-08 -2.823842825797461e-08 -2.0044132888907563e-08 -1.2029980690958416e-08 -5.6040798274182976e-09 -8.240810439711543e-09 -2.3401354003568804e-08 -2.9870729199919766e-08 -2.69640303772605e-08 -2.38378231558531e-08 -2.3706003061659163e-08 -2.568108555777073e-08 -2.4868140188839024e-08 -3.137079913715292e-08 -3.2018969388342203e-08 -1.7453917347258807e-08 -3.014990180589035e-08 -3.440274348571715e-08 -3.507121271649864e-08 -3.248535282634133e-08 -3.372835714347558e-08 -3.622652872907869e-08 -4.058029003214125e-08 -4.199957496152364e-08 -3.8220513109021064e-08 -2.9482090031937756e-08 -2.0295527943857224e-08 -1.2272828807132413e-08 -7.909041287429164e-09 -2.7023941130793784e-08 -5.623902150809556e-08 -6.116353752074473e-08 -4.788438885488115e-08 -4.177447817972987e-08 -3.70509795925161e-08 -4.020299199445773e-08 -3.430708351711257e-08 -3.320773351709241e-08 -3.342009207282629e-08 -2.01240138936186e-08 -3.3284738148177025e-08 -3.7428935087028526e-08 -3.84359945846922e-08 -3.5739353218865674e-08 -3.6394180220447543e-08 -3.901299513415333e-08 -4.3137221821827065e-08 -4.205693806984494e-08 -3.7772045369609385e-08 -3.055111483572502e-08 -2.059664317149226e-08 -1.2367913501011706e-08 -8.901061460131813e-09 -2.525332770846932e-08 -5.172262182198448e-08 -5.70589523558343e-08 -4.648310180618983e-08 -4.8967466798386086e-08 -4.7003478886262174e-08 -4.489665847806027e-08 -4.6052878493780057e-08 -4.4395429828129577e-08 -3.9255103611394826e-08 -2.356234874454507e-08 -3.4071138697641997e-08 -3.6228501099565384e-08 -3.5698755259681256e-08 -3.355322708067803e-08 -3.125812747310062e-08 -3.29047281010743e-08 -3.9551534459123965e-08 -4.324603092700959e-08 -4.066715651565933e-08 -3.5057981397817076e-08 -2.6684282496564638e-08 -1.8025411695777923e-08 -1.1288615934272923e-08 -2.2971377237469868e-08 -4.531348610758126e-08 -4.75251708799923e-08 -3.7950462716551433e-08 -4.585966836818782e-08 -5.327356248135359e-08 -5.363993029925671e-08 -4.869256766180334e-08 -4.633155800712897e-08 -3.908005573070087e-08 -2.822133438042327e-08 -2.6735892857633082e-08 -2.5060281947084308e-08 -2.5567509890578696e-08 -2.4324341209237218e-08 -2.3789417896825527e-08 -2.668937778698859e-08 -3.114709945112056e-08 -3.1219912794920955e-08 -3.0739394035100524e-08 -2.6577856672386862e-08 -2.163542496115024e-08 -1.518355455286867e-08 -1.0374175667380174e-08 -2.780919113080818e-08 -5.895653712823958e-08 -6.21563795144835e-08 -4.7528375982033175e-08 -3.9731348901827415e-08 -4.7043994663342966e-08 -4.2682426060437265e-08 -4.05751947417173e-08 -3.943450714358022e-08 -3.751366483585268e-08 -2.3015591209213225e-08 -2.769890274776063e-08 -2.9947651648900766e-08 -3.1863152119893504e-08 -3.061965471013758e-08 -2.9692065306666882e-08 -2.995233602880666e-08 -3.151248108378032e-08 -2.993474905863365e-08 -2.7434522920440244e-08 -2.1560146154241483e-08 -1.4356145133701225e-08 -8.812386970334268e-09 -6.837222292119088e-09 -2.6956962716349854e-08 -5.889276381583652e-08 -6.76377614612088e-08 -5.616719434953852e-08 -4.510145628026183e-08 -4.4312014992963216e-08 -3.50095761387895e-08 -3.052974748878585e-08 -3.835192229269694e-08 -3.675915094258924e-08 -2.383404277908694e-08 -3.586032527538281e-08 -4.2238396154620635e-08 -4.198272763028314e-08 -3.921902566790907e-08 -3.7451535165521875e-08 -3.981164081705652e-08 -3.619875117805777e-08 -3.5683551570513e-08 -3.338015157047077e-08 -2.60633967037746e-08 -1.717556656232435e-08 -1.0051693092805972e-08 -6.039316248148413e-09 -7.532811617092595e-09 -2.2363969309672232e-08 -3.0926276138714626e-08 -2.8049327237562983e-08 -1.931599945090363e-08 -2.227126789679769e-08 -2.6531095055431525e-08 -2.6586814521680586e-08 -2.9027294270547942e-08 -3.035749379961472e-08 -2.0306869074155705e-08 -2.9707515542145974e-08 -3.5981050785589104e-08 -3.72628450556283e-08 -3.3846699372677125e-08 -3.481521546374669e-08 -3.7008902355466666e-08 -4.163164568365189e-08 -4.1501387049426586e-08 -3.647866342296087e-08 -2.823842825797461e-08 -2.0044132888907563e-08 -1.2029980690958416e-08 -5.6040798274182976e-09 -8.240810439711543e-09 -2.3401354003568804e-08 -2.9870729199919766e-08 -2.69640303772605e-08 -2.38378231558531e-08 -2.3706003061659163e-08 -2.568108555777073e-08 -2.4868140188839024e-08 -3.137079913715292e-08 -3.2018969388342203e-08 -1.7453917347258807e-08 -3.014990180589035e-08 -3.440274348571715e-08 -3.507121271649864e-08 -3.248535282634133e-08 -3.372835714347558e-08 -3.622652872907869e-08 -4.058029003214125e-08 -4.199957496152364e-08 -3.8220513109021064e-08 -2.9482090031937756e-08 -2.0295527943857224e-08 -1.2272828807132413e-08 -7.909041287429164e-09 -2.7023941130793784e-08 -5.623902150809556e-08 -6.116353752074473e-08 -4.788438885488115e-08 -4.177447817972987e-08 -3.70509795925161e-08 -4.020299199445773e-08 -3.430708351711257e-08 -3.320773351709241e-08 -3.342009207282629e-08 -2.01240138936186e-08 -3.3284738148177025e-08 -3.7428935087028526e-08 -3.84359945846922e-08 -3.5739353218865674e-08 -3.6394180220447543e-08 -3.901299513415333e-08 -4.3137221821827065e-08 -4.205693806984494e-08 -3.7772045369609385e-08 -3.055111483572502e-08 -2.059664317149226e-08 -1.2367913501011706e-08 -8.901061460131813e-09 -2.525332770846932e-08 -5.172262182198448e-08 -5.70589523558343e-08 -4.648310180618983e-08 -4.8967466798386086e-08 -4.7003478886262174e-08 -4.489665847806027e-08 -4.6052878493780057e-08 -4.4395429828129577e-08 -3.9255103611394826e-08 -2.356234874454507e-08 -3.4071138697641997e-08 -3.6228501099565384e-08 -3.5698755259681256e-08 -3.355322708067803e-08 -3.125812747310062e-08 -3.29047281010743e-08 -3.9551534459123965e-08 -4.324603092700959e-08 -4.066715651565933e-08 -3.5057981397817076e-08 -2.6684282496564638e-08 -1.8025411695777923e-08 -1.1288615934272923e-08 -2.2971377237469868e-08 -4.531348610758126e-08 -4.75251708799923e-08 -3.7950462716551433e-08 -4.585966836818782e-08 -5.327356248135359e-08 -5.363993029925671e-08 -4.869256766180334e-08 -4.633155800712897e-08 -3.908005573070087e-08 -2.822133438042327e-08 -2.6735892857633082e-08 -2.5060281947084308e-08 -2.5567509890578696e-08 -2.4324341209237218e-08 -2.3789417896825527e-08 -2.668937778698859e-08 -3.179732425490015e-08 -3.244039921566547e-08 -2.9594926060197282e-08 -2.5057405573457883e-08 -1.835561938809167e-08 -1.1413861460177887e-08 -1.0439510439751859e-08 -2.837501491417806e-08 -5.8732262167481936e-08 -6.109614819578273e-08 -5.122451609199106e-08 -4.024893179037693e-08 -4.422654560520654e-08 -4.245330235556649e-08 -4.453883759893283e-08 -3.766570172753522e-08 -3.298888257517317e-08 -1.915212833630094e-08 -2.8105621978537322e-08 -3.0956601334947525e-08 -3.373871208853072e-08 -3.3351387834206506e-08 -3.291598704926917e-08 -3.431415117802322e-08 -3.673885196299703e-08 -3.5738202669415105e-08 -3.249381758301339e-08 -2.4307986970618393e-08 -1.6429681789940187e-08 -9.08819011005675e-09 -5.998389560549547e-09 -2.82694109110364e-08 -6.439600620212268e-08 -7.025090580976536e-08 -5.041288563671715e-08 -4.1202655102796297e-08 -3.8288066798190274e-08 -4.2693931554942966e-08 -3.8359976138850934e-08 -4.215629623311207e-08 -3.579334686093888e-08 -2.32319766880241e-08 -3.4677560440196286e-08 -4.267313948272908e-08 -4.4177071978832014e-08 -4.041452872915548e-08 -3.828699843084332e-08 -4.076791177468786e-08 -4.5038258242584054e-08 -4.545237386268585e-08 -4.0976654317862804e-08 -3.224842182162741e-08 -2.286182849335483e-08 -1.3757366326782865e-08 -8.07685714300524e-09 -1.1919117033185581e-08 -2.7020489482442074e-08 -4.084623131943027e-08 -3.135115761438961e-08 -2.8929004474627774e-08 -2.7424743250110393e-08 -2.8382164757192317e-08 -2.9136514286248533e-08 -2.658763634271671e-08 -3.088329489852546e-08 -1.9860620251541557e-08 -3.22031394825371e-08 -3.976126318754225e-08 -3.880080094262668e-08 -3.639196130365001e-08 -3.83658110682074e-08 -4.166821671975931e-08 -4.626449741058142e-08 -4.672340227715185e-08 -4.292026106829091e-08 -3.3708140345986984e-08 -2.2013462637766273e-08 -1.2531702433510784e-08 -6.406670251294867e-09 -1.111948516503905e-08 -2.787510117790515e-08 -4.0639132418327576e-08 -3.404862080125225e-08 -2.7822668995800577e-08 -2.524954733170316e-08 -2.5566934615853412e-08 -2.6131361303461875e-08 -3.2636732261194974e-08 -3.6672695369589227e-08 -1.9600431711505388e-08 -3.141402692365293e-08 -3.863734073854205e-08 -3.93150965470317e-08 -3.854496805408196e-08 -3.995282967106224e-08 -4.449988328182066e-08 -5.040779034629319e-08 -5.090745753625525e-08 -4.6148949372902694e-08 -3.6968386578385855e-08 -2.4450572920385528e-08 -1.2553645055175237e-08 -9.292001727014961e-09 -2.992727048720495e-08 -6.589024120999936e-08 -6.97830430939012e-08 -5.239963799154164e-08 -4.500908359580174e-08 -4.229863563656836e-08 -4.218949780297138e-08 -4.255898854081177e-08 -4.1685557143621485e-08 -3.5609341130951205e-08 -2.346726405066577e-08 -3.3146507849901336e-08 -4.0237261931664005e-08 -4.3966028336755915e-08 -4.0468111460710625e-08 -3.9027952277010745e-08 -4.1176849922262086e-08 -5.138320973406618e-08 -5.478390518153827e-08 -5.0980928336884546e-08 -4.297959654709891e-08 -3.210131585616161e-08 -2.150286522802379e-08 -1.4277825588958814e-08 -2.942094654685029e-08 -5.5085595683898585e-08 -6.038576609215903e-08 -4.975575753623414e-08 -5.006558406685207e-08 -5.4034979671320446e-08 -5.425383061323969e-08 -5.4351956044952636e-08 -5.07532839098788e-08 -4.3332650864216826e-08 -2.4149704239061334e-08 -3.6544655652161444e-08 -4.182608854079831e-08 -3.9772439953633504e-08 -3.739565133506559e-08 -3.6222994898623366e-08 -3.900140745754402e-08 -4.618404113114511e-08 -5.0264793486007994e-08 -4.6846100157844835e-08 -3.808483045595735e-08 -2.848176946677028e-08 -1.6809280926524854e-08 -1.0566481789832678e-08 -2.4368472998876962e-08 -4.6795722528330575e-08 -4.502330109972665e-08 -4.0002467661643994e-08 -4.6800489090340077e-08 -4.8995983988339525e-08 -5.44245228424422e-08 -4.995233712807447e-08 -4.741595086429171e-08 -4.589434921591216e-08 -2.500300102086662e-08 -2.672964701775856e-08 -2.7953913815269234e-08 -2.5208374097793464e-08 -2.5087977316001614e-08 -2.4755879435304785e-08 -2.711688908997916e-08 -3.179732425490015e-08 -3.244039921566547e-08 -2.9594926060197282e-08 -2.5057405573457883e-08 -1.835561938809167e-08 -1.1413861460177887e-08 -1.0439510439751859e-08 -2.837501491417806e-08 -5.8732262167481936e-08 -6.109614819578273e-08 -5.122451609199106e-08 -4.024893179037693e-08 -4.422654560520654e-08 -4.245330235556649e-08 -4.453883759893283e-08 -3.766570172753522e-08 -3.298888257517317e-08 -1.915212833630094e-08 -2.8105621978537322e-08 -3.0956601334947525e-08 -3.373871208853072e-08 -3.3351387834206506e-08 -3.291598704926917e-08 -3.431415117802322e-08 -3.673885196299703e-08 -3.5738202669415105e-08 -3.249381758301339e-08 -2.4307986970618393e-08 -1.6429681789940187e-08 -9.08819011005675e-09 -5.998389560549547e-09 -2.82694109110364e-08 -6.439600620212268e-08 -7.025090580976536e-08 -5.041288563671715e-08 -4.1202655102796297e-08 -3.8288066798190274e-08 -4.2693931554942966e-08 -3.8359976138850934e-08 -4.215629623311207e-08 -3.579334686093888e-08 -2.32319766880241e-08 -3.4677560440196286e-08 -4.267313948272908e-08 -4.4177071978832014e-08 -4.041452872915548e-08 -3.828699843084332e-08 -4.076791177468786e-08 -4.5038258242584054e-08 -4.545237386268585e-08 -4.0976654317862804e-08 -3.224842182162741e-08 -2.286182849335483e-08 -1.3757366326782865e-08 -8.07685714300524e-09 -1.1919117033185581e-08 -2.7020489482442074e-08 -4.084623131943027e-08 -3.135115761438961e-08 -2.8929004474627774e-08 -2.7424743250110393e-08 -2.8382164757192317e-08 -2.9136514286248533e-08 -2.658763634271671e-08 -3.088329489852546e-08 -1.9860620251541557e-08 -3.22031394825371e-08 -3.976126318754225e-08 -3.880080094262668e-08 -3.639196130365001e-08 -3.83658110682074e-08 -4.166821671975931e-08 -4.626449741058142e-08 -4.672340227715185e-08 -4.292026106829091e-08 -3.3708140345986984e-08 -2.2013462637766273e-08 -1.2531702433510784e-08 -6.406670251294867e-09 -1.111948516503905e-08 -2.787510117790515e-08 -4.0639132418327576e-08 -3.404862080125225e-08 -2.7822668995800577e-08 -2.524954733170316e-08 -2.5566934615853412e-08 -2.6131361303461875e-08 -3.2636732261194974e-08 -3.6672695369589227e-08 -1.9600431711505388e-08 -3.141402692365293e-08 -3.863734073854205e-08 -3.93150965470317e-08 -3.854496805408196e-08 -3.995282967106224e-08 -4.449988328182066e-08 -5.040779034629319e-08 -5.090745753625525e-08 -4.6148949372902694e-08 -3.6968386578385855e-08 -2.4450572920385528e-08 -1.2553645055175237e-08 -9.292001727014961e-09 -2.992727048720495e-08 -6.589024120999936e-08 -6.97830430939012e-08 -5.239963799154164e-08 -4.500908359580174e-08 -4.229863563656836e-08 -4.218949780297138e-08 -4.255898854081177e-08 -4.1685557143621485e-08 -3.5609341130951205e-08 -2.346726405066577e-08 -3.3146507849901336e-08 -4.0237261931664005e-08 -4.3966028336755915e-08 -4.0468111460710625e-08 -3.9027952277010745e-08 -4.1176849922262086e-08 -5.138320973406618e-08 -5.478390518153827e-08 -5.0980928336884546e-08 -4.297959654709891e-08 -3.210131585616161e-08 -2.150286522802379e-08 -1.4277825588958814e-08 -2.942094654685029e-08 -5.5085595683898585e-08 -6.038576609215903e-08 -4.975575753623414e-08 -5.006558406685207e-08 -5.4034979671320446e-08 -5.425383061323969e-08 -5.4351956044952636e-08 -5.07532839098788e-08 -4.3332650864216826e-08 -2.4149704239061334e-08 -3.6544655652161444e-08 -4.182608854079831e-08 -3.9772439953633504e-08 -3.739565133506559e-08 -3.6222994898623366e-08 -3.900140745754402e-08 -4.618404113114511e-08 -5.0264793486007994e-08 -4.6846100157844835e-08 -3.808483045595735e-08 -2.848176946677028e-08 -1.6809280926524854e-08 -1.0566481789832678e-08 -2.4368472998876962e-08 -4.6795722528330575e-08 -4.502330109972665e-08 -4.0002467661643994e-08 -4.6800489090340077e-08 -4.8995983988339525e-08 -5.44245228424422e-08 -4.995233712807447e-08 -4.741595086429171e-08 -4.589434921591216e-08 -2.500300102086662e-08 -2.672964701775856e-08 -2.7953913815269234e-08 -2.5208374097793464e-08 -2.5087977316001614e-08 -2.4755879435304785e-08 -2.711688908997916e-08 -3.179732425490015e-08 -3.244039921566547e-08 -2.9594926060197282e-08 -2.5057405573457883e-08 -1.835561938809167e-08 -1.1413861460177887e-08 -1.0439510439751859e-08 -2.837501491417806e-08 -5.8732262167481936e-08 -6.109614819578273e-08 -5.122451609199106e-08 -4.024893179037693e-08 -4.422654560520654e-08 -4.245330235556649e-08 -4.453883759893283e-08 -3.766570172753522e-08 -3.298888257517317e-08 -1.915212833630094e-08 -2.8105621978537322e-08 -3.0956601334947525e-08 -3.373871208853072e-08 -3.3351387834206506e-08 -3.291598704926917e-08 -3.431415117802322e-08 -3.673885196299703e-08 -3.5738202669415105e-08 -3.249381758301339e-08 -2.4307986970618393e-08 -1.6429681789940187e-08 -9.08819011005675e-09 -5.998389560549547e-09 -2.82694109110364e-08 -6.439600620212268e-08 -7.025090580976536e-08 -5.041288563671715e-08 -4.1202655102796297e-08 -3.8288066798190274e-08 -4.2693931554942966e-08 -3.8359976138850934e-08 -4.215629623311207e-08 -3.579334686093888e-08 -2.32319766880241e-08 -3.4677560440196286e-08 -4.267313948272908e-08 -4.4177071978832014e-08 -4.041452872915548e-08 -3.828699843084332e-08 -4.076791177468786e-08 -4.5038258242584054e-08 -4.545237386268585e-08 -4.0976654317862804e-08 -3.224842182162741e-08 -2.286182849335483e-08 -1.3757366326782865e-08 -8.07685714300524e-09 -1.1919117033185581e-08 -2.7020489482442074e-08 -4.084623131943027e-08 -3.135115761438961e-08 -2.8929004474627774e-08 -2.7424743250110393e-08 -2.8382164757192317e-08 -2.9136514286248533e-08 -2.658763634271671e-08 -3.088329489852546e-08 -1.9860620251541557e-08 -3.22031394825371e-08 -3.976126318754225e-08 -3.880080094262668e-08 -3.639196130365001e-08 -3.83658110682074e-08 -4.166821671975931e-08 -4.626449741058142e-08 -4.672340227715185e-08 -4.292026106829091e-08 -3.3708140345986984e-08 -2.2013462637766273e-08 -1.2531702433510784e-08 -6.406670251294867e-09 -1.111948516503905e-08 -2.787510117790515e-08 -4.0639132418327576e-08 -3.404862080125225e-08 -2.7822668995800577e-08 -2.524954733170316e-08 -2.5566934615853412e-08 -2.6131361303461875e-08 -3.2636732261194974e-08 -3.6672695369589227e-08 -1.9600431711505388e-08 -3.141402692365293e-08 -3.863734073854205e-08 -3.93150965470317e-08 -3.854496805408196e-08 -3.995282967106224e-08 -4.449988328182066e-08 -5.040779034629319e-08 -5.090745753625525e-08 -4.6148949372902694e-08 -3.6968386578385855e-08 -2.4450572920385528e-08 -1.2553645055175237e-08 -9.292001727014961e-09 -2.992727048720495e-08 -6.589024120999936e-08 -6.97830430939012e-08 -5.239963799154164e-08 -4.500908359580174e-08 -4.229863563656836e-08 -4.218949780297138e-08 -4.255898854081177e-08 -4.1685557143621485e-08 -3.5609341130951205e-08 -2.346726405066577e-08 -3.3146507849901336e-08 -4.0237261931664005e-08 -4.3966028336755915e-08 -4.0468111460710625e-08 -3.9027952277010745e-08 -4.1176849922262086e-08 -5.138320973406618e-08 -5.478390518153827e-08 -5.0980928336884546e-08 -4.297959654709891e-08 -3.210131585616161e-08 -2.150286522802379e-08 -1.4277825588958814e-08 -2.942094654685029e-08 -5.5085595683898585e-08 -6.038576609215903e-08 -4.975575753623414e-08 -5.006558406685207e-08 -5.4034979671320446e-08 -5.425383061323969e-08 -5.4351956044952636e-08 -5.07532839098788e-08 -4.3332650864216826e-08 -2.4149704239061334e-08 -3.6544655652161444e-08 -4.182608854079831e-08 -3.9772439953633504e-08 -3.739565133506559e-08 -3.6222994898623366e-08 -3.900140745754402e-08 -4.618404113114511e-08 -5.0264793486007994e-08 -4.6846100157844835e-08 -3.808483045595735e-08 -2.848176946677028e-08 -1.6809280926524854e-08 -1.0566481789832678e-08 -2.4368472998876962e-08 -4.6795722528330575e-08 -4.502330109972665e-08 -4.0002467661643994e-08 -4.6800489090340077e-08 -4.8995983988339525e-08 -5.44245228424422e-08 -4.995233712807447e-08 -4.741595086429171e-08 -4.589434921591216e-08 -2.500300102086662e-08 -2.672964701775856e-08 -2.7953913815269234e-08 -2.5208374097793464e-08 -2.5087977316001614e-08 -2.4755879435304785e-08 -2.711688908997916e-08 -3.179732425490015e-08 -3.244039921566547e-08 -2.9594926060197282e-08 -2.5057405573457883e-08 -1.835561938809167e-08 -1.1413861460177887e-08 -1.0439510439751859e-08 -2.837501491417806e-08 -5.8732262167481936e-08 -6.109614819578273e-08 -5.122451609199106e-08 -4.024893179037693e-08 -4.422654560520654e-08 -4.245330235556649e-08 -4.453883759893283e-08 -3.766570172753522e-08 -3.298888257517317e-08 -1.915212833630094e-08 -2.8105621978537322e-08 -3.0956601334947525e-08 -3.373871208853072e-08 -3.3351387834206506e-08 -3.291598704926917e-08 -3.431415117802322e-08 -3.673885196299703e-08 -3.5738202669415105e-08 -3.249381758301339e-08 -2.4307986970618393e-08 -1.6429681789940187e-08 -9.08819011005675e-09 -5.998389560549547e-09 -2.82694109110364e-08 -6.439600620212268e-08 -7.025090580976536e-08 -5.041288563671715e-08 -4.1202655102796297e-08 -3.8288066798190274e-08 -4.2693931554942966e-08 -3.8359976138850934e-08 -4.215629623311207e-08 -3.579334686093888e-08 -2.32319766880241e-08 -3.4677560440196286e-08 -4.267313948272908e-08 -4.4177071978832014e-08 -4.041452872915548e-08 -3.828699843084332e-08 -4.076791177468786e-08 -4.5038258242584054e-08 -4.545237386268585e-08 -4.0976654317862804e-08 -3.224842182162741e-08 -2.286182849335483e-08 -1.3757366326782865e-08 -8.07685714300524e-09 -1.1919117033185581e-08 -2.7020489482442074e-08 -4.084623131943027e-08 -3.135115761438961e-08 -2.8929004474627774e-08 -2.7424743250110393e-08 -2.8382164757192317e-08 -2.9136514286248533e-08 -2.658763634271671e-08 -3.088329489852546e-08 -1.9860620251541557e-08 -3.22031394825371e-08 -3.976126318754225e-08 -3.880080094262668e-08 -3.639196130365001e-08 -3.83658110682074e-08 -4.166821671975931e-08 -4.626449741058142e-08 -4.672340227715185e-08 -4.292026106829091e-08 -3.3708140345986984e-08 -2.2013462637766273e-08 -1.2531702433510784e-08 -6.406670251294867e-09 -1.111948516503905e-08 -2.787510117790515e-08 -4.0639132418327576e-08 -3.404862080125225e-08 -2.7822668995800577e-08 -2.524954733170316e-08 -2.5566934615853412e-08 -2.6131361303461875e-08 -3.2636732261194974e-08 -3.6672695369589227e-08 -1.9600431711505388e-08 -3.141402692365293e-08 -3.863734073854205e-08 -3.93150965470317e-08 -3.854496805408196e-08 -3.995282967106224e-08 -4.449988328182066e-08 -5.040779034629319e-08 -5.090745753625525e-08 -4.6148949372902694e-08 -3.6968386578385855e-08 -2.4450572920385528e-08 -1.2553645055175237e-08 -9.292001727014961e-09 -2.992727048720495e-08 -6.589024120999936e-08 -6.97830430939012e-08 -5.239963799154164e-08 -4.500908359580174e-08 -4.229863563656836e-08 -4.218949780297138e-08 -4.255898854081177e-08 -4.1685557143621485e-08 -3.5609341130951205e-08 -2.346726405066577e-08 -3.3146507849901336e-08 -4.0237261931664005e-08 -4.3966028336755915e-08 -4.0468111460710625e-08 -3.9027952277010745e-08 -4.1176849922262086e-08 -5.138320973406618e-08 -5.478390518153827e-08 -5.0980928336884546e-08 -4.297959654709891e-08 -3.210131585616161e-08 -2.150286522802379e-08 -1.4277825588958814e-08 -2.942094654685029e-08 -5.5085595683898585e-08 -6.038576609215903e-08 -4.975575753623414e-08 -5.006558406685207e-08 -5.4034979671320446e-08 -5.425383061323969e-08 -5.4351956044952636e-08 -5.07532839098788e-08 -4.3332650864216826e-08 -2.4149704239061334e-08 -3.6544655652161444e-08 -4.182608854079831e-08 -3.9772439953633504e-08 -3.739565133506559e-08 -3.6222994898623366e-08 -3.900140745754402e-08 -4.618404113114511e-08 -5.0264793486007994e-08 -4.6846100157844835e-08 -3.808483045595735e-08 -2.848176946677028e-08 -1.6809280926524854e-08 -1.0566481789832678e-08 -2.4368472998876962e-08 -4.6795722528330575e-08 -4.502330109972665e-08 -4.0002467661643994e-08 -4.6800489090340077e-08 -4.8995983988339525e-08 -5.44245228424422e-08 -4.995233712807447e-08 -4.741595086429171e-08 -4.589434921591216e-08 -2.500300102086662e-08 -2.672964701775856e-08 -2.7953913815269234e-08 -2.5208374097793464e-08 -2.5087977316001614e-08 -2.4755879435304785e-08 -2.711688908997916e-08 -3.02656142077763e-08 -3.052284419208243e-08 -2.7446932418085685e-08 -2.387160000043771e-08 -1.9593857143216417e-08 -1.2883934929592597e-08 -1.1893311852651356e-08 -2.7653209498152262e-08 -4.491145125671046e-08 -4.409636915308485e-08 -3.6775094270690005e-08 -3.4864195997499555e-08 -4.043137606039598e-08 -4.639755023632955e-08 -3.961728014201371e-08 -3.9246967583137205e-08 -3.8794308556441316e-08 -2.3763694898394913e-08 -2.5039818603284873e-08 -2.5472096468284946e-08 -2.7543578571933603e-08 -2.6727428100961036e-08 -2.591875620141716e-08 -2.6437160911002806e-08 -2.7430085086845188e-08 -2.6277563265787942e-08 -2.2838077865410906e-08 -1.7923834615713264e-08 -1.3061530455498522e-08 -9.230282967202212e-09 -6.556241679869038e-09 -2.585958508681639e-08 -6.173536059767829e-08 -6.399380698704466e-08 -4.7220521821901936e-08 -3.499075643706231e-08 -3.611015887036384e-08 -3.3797390110509815e-08 -3.286199340719596e-08 -3.299562150766937e-08 -3.4143212402509876e-08 -2.2226232104018218e-08 -3.499749536955851e-08 -4.1857482104378166e-08 -3.6536766170214675e-08 -3.243029081692117e-08 -3.0985940345937074e-08 -3.0541335165395173e-08 -3.254066138207233e-08 -3.053237731610144e-08 -2.644159874459786e-08 -2.0239479749193717e-08 -1.425703351674493e-08 -9.071014050401804e-09 -4.974236185334536e-09 -1.1641752433494468e-08 -2.835282574620276e-08 -3.751752739472246e-08 -2.977186412927431e-08 -2.1211447488614993e-08 -2.4971936185701213e-08 -2.288270274767232e-08 -2.5643610518523573e-08 -2.3659077080496603e-08 -2.7837954867072443e-08 -1.7572834851185637e-08 -3.251247292053335e-08 -3.870941444340993e-08 -3.758590290492779e-08 -3.314404238679297e-08 -3.374068445901741e-08 -3.672562064431547e-08 -3.8947249451263593e-08 -3.639870023614621e-08 -3.137515478864437e-08 -2.2884675118159017e-08 -1.5230151805616778e-08 -8.359974489949207e-09 -5.4069249608526734e-09 -1.4843320643914238e-08 -2.7998209969116197e-08 -3.5277489796565215e-08 -2.2281705023956437e-08 -1.820037739436826e-08 -2.0462439796293565e-08 -2.226288532222925e-08 -2.3518792229630612e-08 -2.3589386656633478e-08 -2.2312030220189333e-08 -2.3926251099339808e-08 -3.261684419212082e-08 -3.673194866629361e-08 -3.657900777147134e-08 -3.223313595035555e-08 -3.2204372214091284e-08 -3.472678752025998e-08 -3.665888877618238e-08 -3.506817197866499e-08 -3.0240219937760134e-08 -2.2709051962739783e-08 -1.5849640502645406e-08 -1.1737001491580985e-08 -1.5343398744394367e-08 -3.9702174255045084e-08 -6.20640068300234e-08 -6.109154599798046e-08 -4.134121412948645e-08 -3.7827600471651216e-08 -3.6263921586222236e-08 -3.975189442773045e-08 -3.304312276355721e-08 -3.042948532237899e-08 -2.8639066013083993e-08 -2.4419918995738187e-08 -3.241032056574341e-08 -3.6295150785594865e-08 -3.457639427064969e-08 -3.2770195997461156e-08 -3.278704332870165e-08 -3.657514521260157e-08 -3.791356295202956e-08 -3.6543505102710875e-08 -3.1522260754110177e-08 -2.4686764286166943e-08 -1.6460746625105593e-08 -1.0078731004894379e-08 -1.2483708085001272e-08 -3.644340730051124e-08 -5.892218500892969e-08 -5.7337796233390434e-08 -4.618527386269929e-08 -3.8302037755804345e-08 -3.793690266945542e-08 -3.409891624866291e-08 -2.834773045577881e-08 -2.608254513391624e-08 -2.9133637912622105e-08 -1.9781643249970252e-08 -3.229049905867685e-08 -3.432286248100611e-08 -3.175171318739538e-08 -3.013050682943787e-08 -2.9372459105719103e-08 -3.101149898016046e-08 -3.460655510267536e-08 -3.5664238776164146e-08 -3.2318358791801383e-08 -2.7424743250110393e-08 -1.9851169309626152e-08 -1.3424117896635469e-08 -1.2988306201180068e-08 -2.932849168028659e-08 -4.588703500869068e-08 -4.4791629749643904e-08 -4.0026382653795145e-08 -4.478793155498136e-08 -4.496889654713538e-08 -4.3917787441935574e-08 -3.878157033038143e-08 -4.185961883907209e-08 -4.085683281079624e-08 -2.3011564286136224e-08 -2.524108257503111e-08 -2.6002746311308814e-08 -2.4038429670770438e-08 -2.480798288899491e-08 -2.3884995683326493e-08 -2.7093385008346077e-08 -3.02656142077763e-08 -3.052284419208243e-08 -2.7446932418085685e-08 -2.387160000043771e-08 -1.9593857143216417e-08 -1.2883934929592597e-08 -1.1893311852651356e-08 -2.7653209498152262e-08 -4.491145125671046e-08 -4.409636915308485e-08 -3.6775094270690005e-08 -3.4864195997499555e-08 -4.043137606039598e-08 -4.639755023632955e-08 -3.961728014201371e-08 -3.9246967583137205e-08 -3.8794308556441316e-08 -2.3763694898394913e-08 -2.5039818603284873e-08 -2.5472096468284946e-08 -2.7543578571933603e-08 -2.6727428100961036e-08 -2.591875620141716e-08 -2.6437160911002806e-08 -2.7430085086845188e-08 -2.6277563265787942e-08 -2.2838077865410906e-08 -1.7923834615713264e-08 -1.3061530455498522e-08 -9.230282967202212e-09 -6.556241679869038e-09 -2.585958508681639e-08 -6.173536059767829e-08 -6.399380698704466e-08 -4.7220521821901936e-08 -3.499075643706231e-08 -3.611015887036384e-08 -3.3797390110509815e-08 -3.286199340719596e-08 -3.299562150766937e-08 -3.4143212402509876e-08 -2.2226232104018218e-08 -3.499749536955851e-08 -4.1857482104378166e-08 -3.6536766170214675e-08 -3.243029081692117e-08 -3.0985940345937074e-08 -3.0541335165395173e-08 -3.254066138207233e-08 -3.053237731610144e-08 -2.644159874459786e-08 -2.0239479749193717e-08 -1.425703351674493e-08 -9.071014050401804e-09 -4.974236185334536e-09 -1.1641752433494468e-08 -2.835282574620276e-08 -3.751752739472246e-08 -2.977186412927431e-08 -2.1211447488614993e-08 -2.4971936185701213e-08 -2.288270274767232e-08 -2.5643610518523573e-08 -2.3659077080496603e-08 -2.7837954867072443e-08 -1.7572834851185637e-08 -3.251247292053335e-08 -3.870941444340993e-08 -3.758590290492779e-08 -3.314404238679297e-08 -3.374068445901741e-08 -3.672562064431547e-08 -3.8947249451263593e-08 -3.639870023614621e-08 -3.137515478864437e-08 -2.2884675118159017e-08 -1.5230151805616778e-08 -8.359974489949207e-09 -5.4069249608526734e-09 -1.4843320643914238e-08 -2.7998209969116197e-08 -3.5277489796565215e-08 -2.2281705023956437e-08 -1.820037739436826e-08 -2.0462439796293565e-08 -2.226288532222925e-08 -2.3518792229630612e-08 -2.3589386656633478e-08 -2.2312030220189333e-08 -2.3926251099339808e-08 -3.261684419212082e-08 -3.673194866629361e-08 -3.657900777147134e-08 -3.223313595035555e-08 -3.2204372214091284e-08 -3.472678752025998e-08 -3.665888877618238e-08 -3.506817197866499e-08 -3.0240219937760134e-08 -2.2709051962739783e-08 -1.5849640502645406e-08 -1.1737001491580985e-08 -1.5343398744394367e-08 -3.9702174255045084e-08 -6.20640068300234e-08 -6.109154599798046e-08 -4.134121412948645e-08 -3.7827600471651216e-08 -3.6263921586222236e-08 -3.975189442773045e-08 -3.304312276355721e-08 -3.042948532237899e-08 -2.8639066013083993e-08 -2.4419918995738187e-08 -3.241032056574341e-08 -3.6295150785594865e-08 -3.457639427064969e-08 -3.2770195997461156e-08 -3.278704332870165e-08 -3.657514521260157e-08 -3.791356295202956e-08 -3.6543505102710875e-08 -3.1522260754110177e-08 -2.4686764286166943e-08 -1.6460746625105593e-08 -1.0078731004894379e-08 -1.2483708085001272e-08 -3.644340730051124e-08 -5.892218500892969e-08 -5.7337796233390434e-08 -4.618527386269929e-08 -3.8302037755804345e-08 -3.793690266945542e-08 -3.409891624866291e-08 -2.834773045577881e-08 -2.608254513391624e-08 -2.9133637912622105e-08 -1.9781643249970252e-08 -3.229049905867685e-08 -3.432286248100611e-08 -3.175171318739538e-08 -3.013050682943787e-08 -2.9372459105719103e-08 -3.101149898016046e-08 -3.460655510267536e-08 -3.5664238776164146e-08 -3.2318358791801383e-08 -2.7424743250110393e-08 -1.9851169309626152e-08 -1.3424117896635469e-08 -1.2988306201180068e-08 -2.932849168028659e-08 -4.588703500869068e-08 -4.4791629749643904e-08 -4.0026382653795145e-08 -4.478793155498136e-08 -4.496889654713538e-08 -4.3917787441935574e-08 -3.878157033038143e-08 -4.185961883907209e-08 -4.085683281079624e-08 -2.3011564286136224e-08 -2.524108257503111e-08 -2.6002746311308814e-08 -2.4038429670770438e-08 -2.480798288899491e-08 -2.3884995683326493e-08 -2.7093385008346077e-08 -3.02656142077763e-08 -3.052284419208243e-08 -2.7446932418085685e-08 -2.387160000043771e-08 -1.9593857143216417e-08 -1.2883934929592597e-08 -1.1893311852651356e-08 -2.7653209498152262e-08 -4.491145125671046e-08 -4.409636915308485e-08 -3.6775094270690005e-08 -3.4864195997499555e-08 -4.043137606039598e-08 -4.639755023632955e-08 -3.961728014201371e-08 -3.9246967583137205e-08 -3.8794308556441316e-08 -2.3763694898394913e-08 -2.5039818603284873e-08 -2.5472096468284946e-08 -2.7543578571933603e-08 -2.6727428100961036e-08 -2.591875620141716e-08 -2.6437160911002806e-08 -2.7430085086845188e-08 -2.6277563265787942e-08 -2.2838077865410906e-08 -1.7923834615713264e-08 -1.3061530455498522e-08 -9.230282967202212e-09 -6.556241679869038e-09 -2.585958508681639e-08 -6.173536059767829e-08 -6.399380698704466e-08 -4.7220521821901936e-08 -3.499075643706231e-08 -3.611015887036384e-08 -3.3797390110509815e-08 -3.286199340719596e-08 -3.299562150766937e-08 -3.4143212402509876e-08 -2.2226232104018218e-08 -3.499749536955851e-08 -4.1857482104378166e-08 -3.6536766170214675e-08 -3.243029081692117e-08 -3.0985940345937074e-08 -3.0541335165395173e-08 -3.254066138207233e-08 -3.053237731610144e-08 -2.644159874459786e-08 -2.0239479749193717e-08 -1.425703351674493e-08 -9.071014050401804e-09 -4.974236185334536e-09 -1.1641752433494468e-08 -2.835282574620276e-08 -3.751752739472246e-08 -2.977186412927431e-08 -2.1211447488614993e-08 -2.4971936185701213e-08 -2.288270274767232e-08 -2.5643610518523573e-08 -2.3659077080496603e-08 -2.7837954867072443e-08 -1.7572834851185637e-08 -3.251247292053335e-08 -3.870941444340993e-08 -3.758590290492779e-08 -3.314404238679297e-08 -3.374068445901741e-08 -3.672562064431547e-08 -3.8947249451263593e-08 -3.639870023614621e-08 -3.137515478864437e-08 -2.2884675118159017e-08 -1.5230151805616778e-08 -8.359974489949207e-09 -5.4069249608526734e-09 -1.4843320643914238e-08 -2.7998209969116197e-08 -3.5277489796565215e-08 -2.2281705023956437e-08 -1.820037739436826e-08 -2.0462439796293565e-08 -2.226288532222925e-08 -2.3518792229630612e-08 -2.3589386656633478e-08 -2.2312030220189333e-08 -2.3926251099339808e-08 -3.261684419212082e-08 -3.673194866629361e-08 -3.657900777147134e-08 -3.223313595035555e-08 -3.2204372214091284e-08 -3.472678752025998e-08 -3.665888877618238e-08 -3.506817197866499e-08 -3.0240219937760134e-08 -2.2709051962739783e-08 -1.5849640502645406e-08 -1.1737001491580985e-08 -1.5343398744394367e-08 -3.9702174255045084e-08 -6.20640068300234e-08 -6.109154599798046e-08 -4.134121412948645e-08 -3.7827600471651216e-08 -3.6263921586222236e-08 -3.975189442773045e-08 -3.304312276355721e-08 -3.042948532237899e-08 -2.8639066013083993e-08 -2.4419918995738187e-08 -3.241032056574341e-08 -3.6295150785594865e-08 -3.457639427064969e-08 -3.2770195997461156e-08 -3.278704332870165e-08 -3.657514521260157e-08 -3.791356295202956e-08 -3.6543505102710875e-08 -3.1522260754110177e-08 -2.4686764286166943e-08 -1.6460746625105593e-08 -1.0078731004894379e-08 -1.2483708085001272e-08 -3.644340730051124e-08 -5.892218500892969e-08 -5.7337796233390434e-08 -4.618527386269929e-08 -3.8302037755804345e-08 -3.793690266945542e-08 -3.409891624866291e-08 -2.834773045577881e-08 -2.608254513391624e-08 -2.9133637912622105e-08 -1.9781643249970252e-08 -3.229049905867685e-08 -3.432286248100611e-08 -3.175171318739538e-08 -3.013050682943787e-08 -2.9372459105719103e-08 -3.101149898016046e-08 -3.460655510267536e-08 -3.5664238776164146e-08 -3.2318358791801383e-08 -2.7424743250110393e-08 -1.9851169309626152e-08 -1.3424117896635469e-08 -1.2988306201180068e-08 -2.932849168028659e-08 -4.588703500869068e-08 -4.4791629749643904e-08 -4.0026382653795145e-08 -4.478793155498136e-08 -4.496889654713538e-08 -4.3917787441935574e-08 -3.878157033038143e-08 -4.185961883907209e-08 -4.085683281079624e-08 -2.3011564286136224e-08 -2.524108257503111e-08 -2.6002746311308814e-08 -2.4038429670770438e-08 -2.480798288899491e-08 -2.3884995683326493e-08 -2.7093385008346077e-08 -3.02656142077763e-08 -3.052284419208243e-08 -2.7446932418085685e-08 -2.387160000043771e-08 -1.9593857143216417e-08 -1.2883934929592597e-08 -1.1893311852651356e-08 -2.7653209498152262e-08 -4.491145125671046e-08 -4.409636915308485e-08 -3.6775094270690005e-08 -3.4864195997499555e-08 -4.043137606039598e-08 -4.639755023632955e-08 -3.961728014201371e-08 -3.9246967583137205e-08 -3.8794308556441316e-08 -2.3763694898394913e-08 -2.5039818603284873e-08 -2.5472096468284946e-08 -2.7543578571933603e-08 -2.6727428100961036e-08 -2.591875620141716e-08 -2.6437160911002806e-08 -2.7430085086845188e-08 -2.6277563265787942e-08 -2.2838077865410906e-08 -1.7923834615713264e-08 -1.3061530455498522e-08 -9.230282967202212e-09 -6.556241679869038e-09 -2.585958508681639e-08 -6.173536059767829e-08 -6.399380698704466e-08 -4.7220521821901936e-08 -3.499075643706231e-08 -3.611015887036384e-08 -3.3797390110509815e-08 -3.286199340719596e-08 -3.299562150766937e-08 -3.4143212402509876e-08 -2.2226232104018218e-08 -3.499749536955851e-08 -4.1857482104378166e-08 -3.6536766170214675e-08 -3.243029081692117e-08 -3.0985940345937074e-08 -3.0541335165395173e-08 -3.254066138207233e-08 -3.053237731610144e-08 -2.644159874459786e-08 -2.0239479749193717e-08 -1.425703351674493e-08 -9.071014050401804e-09 -4.974236185334536e-09 -1.1641752433494468e-08 -2.835282574620276e-08 -3.751752739472246e-08 -2.977186412927431e-08 -2.1211447488614993e-08 -2.4971936185701213e-08 -2.288270274767232e-08 -2.5643610518523573e-08 -2.3659077080496603e-08 -2.7837954867072443e-08 -1.7572834851185637e-08 -3.251247292053335e-08 -3.870941444340993e-08 -3.758590290492779e-08 -3.314404238679297e-08 -3.374068445901741e-08 -3.672562064431547e-08 -3.8947249451263593e-08 -3.639870023614621e-08 -3.137515478864437e-08 -2.2884675118159017e-08 -1.5230151805616778e-08 -8.359974489949207e-09 -5.4069249608526734e-09 -1.4843320643914238e-08 -2.7998209969116197e-08 -3.5277489796565215e-08 -2.2281705023956437e-08 -1.820037739436826e-08 -2.0462439796293565e-08 -2.226288532222925e-08 -2.3518792229630612e-08 -2.3589386656633478e-08 -2.2312030220189333e-08 -2.3926251099339808e-08 -3.261684419212082e-08 -3.673194866629361e-08 -3.657900777147134e-08 -3.223313595035555e-08 -3.2204372214091284e-08 -3.472678752025998e-08 -3.665888877618238e-08 -3.506817197866499e-08 -3.0240219937760134e-08 -2.2709051962739783e-08 -1.5849640502645406e-08 -1.1737001491580985e-08 -1.5343398744394367e-08 -3.9702174255045084e-08 -6.20640068300234e-08 -6.109154599798046e-08 -4.134121412948645e-08 -3.7827600471651216e-08 -3.6263921586222236e-08 -3.975189442773045e-08 -3.304312276355721e-08 -3.042948532237899e-08 -2.8639066013083993e-08 -2.4419918995738187e-08 -3.241032056574341e-08 -3.6295150785594865e-08 -3.457639427064969e-08 -3.2770195997461156e-08 -3.278704332870165e-08 -3.657514521260157e-08 -3.791356295202956e-08 -3.6543505102710875e-08 -3.1522260754110177e-08 -2.4686764286166943e-08 -1.6460746625105593e-08 -1.0078731004894379e-08 -1.2483708085001272e-08 -3.644340730051124e-08 -5.892218500892969e-08 -5.7337796233390434e-08 -4.618527386269929e-08 -3.8302037755804345e-08 -3.793690266945542e-08 -3.409891624866291e-08 -2.834773045577881e-08 -2.608254513391624e-08 -2.9133637912622105e-08 -1.9781643249970252e-08 -3.229049905867685e-08 -3.432286248100611e-08 -3.175171318739538e-08 -3.013050682943787e-08 -2.9372459105719103e-08 -3.101149898016046e-08 -3.460655510267536e-08 -3.5664238776164146e-08 -3.2318358791801383e-08 -2.7424743250110393e-08 -1.9851169309626152e-08 -1.3424117896635469e-08 -1.2988306201180068e-08 -2.932849168028659e-08 -4.588703500869068e-08 -4.4791629749643904e-08 -4.0026382653795145e-08 -4.478793155498136e-08 -4.496889654713538e-08 -4.3917787441935574e-08 -3.878157033038143e-08 -4.185961883907209e-08 -4.085683281079624e-08 -2.3011564286136224e-08 -2.524108257503111e-08 -2.6002746311308814e-08 -2.4038429670770438e-08 -2.480798288899491e-08 -2.3884995683326493e-08 -2.7093385008346077e-08 -3.02656142077763e-08 -3.052284419208243e-08 -2.7446932418085685e-08 -2.387160000043771e-08 -1.9593857143216417e-08 -1.2883934929592597e-08 -1.1893311852651356e-08 -2.7653209498152262e-08 -4.491145125671046e-08 -4.409636915308485e-08 -3.6775094270690005e-08 -3.4864195997499555e-08 -4.043137606039598e-08 -4.639755023632955e-08 -3.961728014201371e-08 -3.9246967583137205e-08 -3.8794308556441316e-08 -2.3763694898394913e-08 -2.5039818603284873e-08 -2.5472096468284946e-08 -2.7543578571933603e-08 -2.6727428100961036e-08 -2.591875620141716e-08 -2.6437160911002806e-08 -2.7430085086845188e-08 -2.6277563265787942e-08 -2.2838077865410906e-08 -1.7923834615713264e-08 -1.3061530455498522e-08 -9.230282967202212e-09 -6.556241679869038e-09 -2.585958508681639e-08 -6.173536059767829e-08 -6.399380698704466e-08 -4.7220521821901936e-08 -3.499075643706231e-08 -3.611015887036384e-08 -3.3797390110509815e-08 -3.286199340719596e-08 -3.299562150766937e-08 -3.4143212402509876e-08 -2.2226232104018218e-08 -3.499749536955851e-08 -4.1857482104378166e-08 -3.6536766170214675e-08 -3.243029081692117e-08 -3.0985940345937074e-08 -3.0541335165395173e-08 -3.254066138207233e-08 -3.053237731610144e-08 -2.644159874459786e-08 -2.0239479749193717e-08 -1.425703351674493e-08 -9.071014050401804e-09 -4.974236185334536e-09 -1.1641752433494468e-08 -2.835282574620276e-08 -3.751752739472246e-08 -2.977186412927431e-08 -2.1211447488614993e-08 -2.4971936185701213e-08 -2.288270274767232e-08 -2.5643610518523573e-08 -2.3659077080496603e-08 -2.7837954867072443e-08 -1.7572834851185637e-08 -3.251247292053335e-08 -3.870941444340993e-08 -3.758590290492779e-08 -3.314404238679297e-08 -3.374068445901741e-08 -3.672562064431547e-08 -3.7325714364891624e-08 -3.167207872899518e-08 -2.406078320295295e-08 -1.5800084694167263e-08 -9.56049065951596e-09 -5.596519073885978e-09 -9.346652825917062e-09 -2.194319693917786e-08 -3.243579701786319e-08 -2.578570337566904e-08 -2.070635627981452e-08 -2.4616087677060465e-08 -2.3595139403886328e-08 -2.090145659378984e-08 -2.7129216405520988e-08 -3.158792425489631e-08 -1.704070573029676e-08 -3.400605047158115e-08 -3.777007299912269e-08 -3.6565201178064495e-08 -3.571888987506624e-08 -3.383198877613055e-08 -3.9566080691463313e-08 -4.2673386029039914e-08 -3.959131059727225e-08 -3.4407016955104984e-08 -2.5515570801095793e-08 -1.8369425981498515e-08 -1.0952819858913546e-08 -8.651227865150779e-09 -2.9775397959729636e-08 -6.173462095874578e-08 -6.557737394154779e-08 -4.779612527560166e-08 -4.20688544748687e-08 -3.827804058154959e-08 -3.9422426374349226e-08 -3.1413451648927644e-08 -3.092997433337718e-08 -2.8827180848252276e-08 -1.864112001604039e-08 -3.3595468681934686e-08 -3.6086408242419924e-08 -3.5647309262820034e-08 -3.416983940408022e-08 -3.47842328106849e-08 -3.695170361135258e-08 -4.0468029278607005e-08 -3.875740879191945e-08 -3.374084882322463e-08 -2.721920580897633e-08 -2.071202684496376e-08 -1.1522341836945966e-08 -9.784354709755546e-09 -2.9650398980135508e-08 -5.7775333753021683e-08 -6.211742519737132e-08 -4.822873186901619e-08 -3.8035767740100873e-08 -4.283725714364261e-08 -3.60714510995625e-08 -3.145059795976035e-08 -2.9009871664582158e-08 -2.812000384666945e-08 -2.142232676648385e-08 -2.8621150314496537e-08 -3.1909667190538e-08 -3.2843502433883223e-08 -3.1474512951911494e-08 -2.9804819152822796e-08 -3.118350612302076e-08 -3.568807158621167e-08 -3.618995769297127e-08 -3.4015337049289326e-08 -2.8976423548412e-08 -2.0906551884213795e-08 -1.385319065959467e-08 -8.923497174417939e-09 -2.2680288226475518e-08 -4.246004128806268e-08 -4.294779207300098e-08 -4.5546883281839853e-08 -4.601137653145591e-08 -4.722208328187057e-08 -4.455971185325033e-08 -4.071482213575439e-08 -3.919609686100126e-08 -3.429220855635876e-08 -2.1552667582812776e-08 -2.1880491994121763e-08 -2.5024779278323846e-08 -2.340957221393002e-08 -2.5545895997328686e-08 -2.139980887009411e-08 -2.387579128772193e-08 -2.838084984353452e-08 -2.9053592543703837e-08 -2.755722080113323e-08 -2.476163218255764e-08 -1.836424850897095e-08 -1.2363311303209424e-08 -7.770235714428189e-09 -2.177176507104285e-08 -4.137581279510718e-08 -4.087762488301012e-08 -3.5789155573654655e-08 -3.893122394105921e-08 -4.610629686112798e-08 -5.0537473705793214e-08 -4.701424474183537e-08 -3.453604285777611e-08 -3.2959461382080014e-08 -1.8337785871607828e-08 -2.2063840267280545e-08 -2.6118294348987537e-08 -2.9752715699132674e-08 -2.8454156279956586e-08 -2.885101365829981e-08 -2.9448559733663986e-08 -3.0920030298840104e-08 -2.9067727865525134e-08 -2.4992317347397035e-08 -1.9460475589053846e-08 -1.2290087048890972e-08 -7.487447095898671e-09 -6.9106930927483785e-09 -2.7016544741468683e-08 -5.6372403062258135e-08 -5.895826295241544e-08 -4.810595180621959e-08 -4.0753612088659346e-08 -4.026668312475717e-08 -3.558205667255196e-08 -3.137663406650939e-08 -3.199579403512357e-08 -2.896097331293291e-08 -1.9402290659696418e-08 -3.229707362696583e-08 -3.89763419159423e-08 -3.912994026759346e-08 -3.452009952967534e-08 -3.3933976766713263e-08 -3.4867318917436816e-08 -3.6627002119980855e-08 -3.439986711209072e-08 -3.037080730039989e-08 -2.4728841523216376e-08 -1.7694053454013604e-08 -1.013412174272899e-08 -4.7832449765398245e-09 -1.0727805259223392e-08 -2.404615478850998e-08 -3.262908932555904e-08 -2.8356359576658083e-08 -2.323698979634444e-08 -2.0556949215447575e-08 -2.0447811381850597e-08 -2.5025436735152743e-08 -2.3343086892107763e-08 -3.100508877607871e-08 -1.9600102983090943e-08 -3.043786789694743e-08 -3.985486860355653e-08 -3.834370408233572e-08 -3.5027163108962506e-08 -3.3358866405635216e-08 -3.327208210422075e-08 -3.7117300550131134e-08 -3.7325714364891624e-08 -3.167207872899518e-08 -2.406078320295295e-08 -1.5800084694167263e-08 -9.56049065951596e-09 -5.596519073885978e-09 -9.346652825917062e-09 -2.194319693917786e-08 -3.243579701786319e-08 -2.578570337566904e-08 -2.070635627981452e-08 -2.4616087677060465e-08 -2.3595139403886328e-08 -2.090145659378984e-08 -2.7129216405520988e-08 -3.158792425489631e-08 -1.704070573029676e-08 -3.400605047158115e-08 -3.777007299912269e-08 -3.6565201178064495e-08 -3.571888987506624e-08 -3.383198877613055e-08 -3.9566080691463313e-08 -4.2673386029039914e-08 -3.959131059727225e-08 -3.4407016955104984e-08 -2.5515570801095793e-08 -1.8369425981498515e-08 -1.0952819858913546e-08 -8.651227865150779e-09 -2.9775397959729636e-08 -6.173462095874578e-08 -6.557737394154779e-08 -4.779612527560166e-08 -4.20688544748687e-08 -3.827804058154959e-08 -3.9422426374349226e-08 -3.1413451648927644e-08 -3.092997433337718e-08 -2.8827180848252276e-08 -1.864112001604039e-08 -3.3595468681934686e-08 -3.6086408242419924e-08 -3.5647309262820034e-08 -3.416983940408022e-08 -3.47842328106849e-08 -3.695170361135258e-08 -4.0468029278607005e-08 -3.875740879191945e-08 -3.374084882322463e-08 -2.721920580897633e-08 -2.071202684496376e-08 -1.1522341836945966e-08 -9.784354709755546e-09 -2.9650398980135508e-08 -5.7775333753021683e-08 -6.211742519737132e-08 -4.822873186901619e-08 -3.8035767740100873e-08 -4.283725714364261e-08 -3.60714510995625e-08 -3.145059795976035e-08 -2.9009871664582158e-08 -2.812000384666945e-08 -2.142232676648385e-08 -2.8621150314496537e-08 -3.1909667190538e-08 -3.2843502433883223e-08 -3.1474512951911494e-08 -2.9804819152822796e-08 -3.118350612302076e-08 -3.568807158621167e-08 -3.618995769297127e-08 -3.4015337049289326e-08 -2.8976423548412e-08 -2.0906551884213795e-08 -1.385319065959467e-08 -8.923497174417939e-09 -2.2680288226475518e-08 -4.246004128806268e-08 -4.294779207300098e-08 -4.5546883281839853e-08 -4.601137653145591e-08 -4.722208328187057e-08 -4.455971185325033e-08 -4.071482213575439e-08 -3.919609686100126e-08 -3.429220855635876e-08 -2.1552667582812776e-08 -2.1880491994121763e-08 -2.5024779278323846e-08 -2.340957221393002e-08 -2.5545895997328686e-08 -2.139980887009411e-08 -2.387579128772193e-08 -2.838084984353452e-08 -2.9053592543703837e-08 -2.755722080113323e-08 -2.476163218255764e-08 -1.836424850897095e-08 -1.2363311303209424e-08 -7.770235714428189e-09 -2.177176507104285e-08 -4.137581279510718e-08 -4.087762488301012e-08 -3.5789155573654655e-08 -3.893122394105921e-08 -4.610629686112798e-08 -5.0537473705793214e-08 -4.701424474183537e-08 -3.453604285777611e-08 -3.2959461382080014e-08 -1.8337785871607828e-08 -2.2063840267280545e-08 -2.6118294348987537e-08 -2.9752715699132674e-08 -2.8454156279956586e-08 -2.885101365829981e-08 -2.9448559733663986e-08 -3.0920030298840104e-08 -2.9067727865525134e-08 -2.4992317347397035e-08 -1.9460475589053846e-08 -1.2290087048890972e-08 -7.487447095898671e-09 -6.9106930927483785e-09 -2.7016544741468683e-08 -5.6372403062258135e-08 -5.895826295241544e-08 -4.810595180621959e-08 -4.0753612088659346e-08 -4.026668312475717e-08 -3.558205667255196e-08 -3.137663406650939e-08 -3.199579403512357e-08 -2.896097331293291e-08 -1.9402290659696418e-08 -3.229707362696583e-08 -3.89763419159423e-08 -3.912994026759346e-08 -3.452009952967534e-08 -3.3933976766713263e-08 -3.4867318917436816e-08 -3.6627002119980855e-08 -3.439986711209072e-08 -3.037080730039989e-08 -2.4728841523216376e-08 -1.7694053454013604e-08 -1.013412174272899e-08 -4.7832449765398245e-09 -1.0727805259223392e-08 -2.404615478850998e-08 -3.262908932555904e-08 -2.8356359576658083e-08 -2.323698979634444e-08 -2.0556949215447575e-08 -2.0447811381850597e-08 -2.5025436735152743e-08 -2.3343086892107763e-08 -3.100508877607871e-08 -1.9600102983090943e-08 -3.043786789694743e-08 -3.985486860355653e-08 -3.834370408233572e-08 -3.5027163108962506e-08 -3.3358866405635216e-08 -3.327208210422075e-08 -3.7117300550131134e-08 -3.7325714364891624e-08 -3.167207872899518e-08 -2.406078320295295e-08 -1.5800084694167263e-08 -9.56049065951596e-09 -5.596519073885978e-09 -9.346652825917062e-09 -2.194319693917786e-08 -3.243579701786319e-08 -2.578570337566904e-08 -2.070635627981452e-08 -2.4616087677060465e-08 -2.3595139403886328e-08 -2.090145659378984e-08 -2.7129216405520988e-08 -3.158792425489631e-08 -1.704070573029676e-08 -3.400605047158115e-08 -3.777007299912269e-08 -3.6565201178064495e-08 -3.571888987506624e-08 -3.383198877613055e-08 -3.9566080691463313e-08 -4.2673386029039914e-08 -3.959131059727225e-08 -3.4407016955104984e-08 -2.5515570801095793e-08 -1.8369425981498515e-08 -1.0952819858913546e-08 -8.651227865150779e-09 -2.9775397959729636e-08 -6.173462095874578e-08 -6.557737394154779e-08 -4.779612527560166e-08 -4.20688544748687e-08 -3.827804058154959e-08 -3.9422426374349226e-08 -3.1413451648927644e-08 -3.092997433337718e-08 -2.8827180848252276e-08 -1.864112001604039e-08 -3.3595468681934686e-08 -3.6086408242419924e-08 -3.5647309262820034e-08 -3.416983940408022e-08 -3.47842328106849e-08 -3.695170361135258e-08 -4.0468029278607005e-08 -3.875740879191945e-08 -3.374084882322463e-08 -2.721920580897633e-08 -2.071202684496376e-08 -1.1522341836945966e-08 -9.784354709755546e-09 -2.9650398980135508e-08 -5.7775333753021683e-08 -6.211742519737132e-08 -4.822873186901619e-08 -3.8035767740100873e-08 -4.283725714364261e-08 -3.60714510995625e-08 -3.145059795976035e-08 -2.9009871664582158e-08 -2.812000384666945e-08 -2.142232676648385e-08 -2.8621150314496537e-08 -3.1909667190538e-08 -3.2843502433883223e-08 -3.1474512951911494e-08 -2.9804819152822796e-08 -3.118350612302076e-08 -3.568807158621167e-08 -3.618995769297127e-08 -3.4015337049289326e-08 -2.8976423548412e-08 -2.0906551884213795e-08 -1.385319065959467e-08 -8.923497174417939e-09 -2.2680288226475518e-08 -4.246004128806268e-08 -4.294779207300098e-08 -4.5546883281839853e-08 -4.601137653145591e-08 -4.722208328187057e-08 -4.455971185325033e-08 -4.071482213575439e-08 -3.919609686100126e-08 -3.429220855635876e-08 -2.1552667582812776e-08 -2.1880491994121763e-08 -2.5024779278323846e-08 -2.340957221393002e-08 -2.5545895997328686e-08 -2.139980887009411e-08 -2.387579128772193e-08 -2.838084984353452e-08 -2.9053592543703837e-08 -2.755722080113323e-08 -2.476163218255764e-08 -1.836424850897095e-08 -1.2363311303209424e-08 -7.770235714428189e-09 -2.177176507104285e-08 -4.137581279510718e-08 -4.087762488301012e-08 -3.5789155573654655e-08 -3.893122394105921e-08 -4.610629686112798e-08 -5.0537473705793214e-08 -4.701424474183537e-08 -3.453604285777611e-08 -3.2959461382080014e-08 -1.8337785871607828e-08 -2.2063840267280545e-08 -2.6118294348987537e-08 -2.9752715699132674e-08 -2.8454156279956586e-08 -2.885101365829981e-08 -2.9448559733663986e-08 -3.0920030298840104e-08 -2.9067727865525134e-08 -2.4992317347397035e-08 -1.9460475589053846e-08 -1.2290087048890972e-08 -7.487447095898671e-09 -6.9106930927483785e-09 -2.7016544741468683e-08 -5.6372403062258135e-08 -5.895826295241544e-08 -4.810595180621959e-08 -4.0753612088659346e-08 -4.026668312475717e-08 -3.558205667255196e-08 -3.137663406650939e-08 -3.199579403512357e-08 -2.896097331293291e-08 -1.9402290659696418e-08 -3.229707362696583e-08 -3.89763419159423e-08 -3.912994026759346e-08 -3.452009952967534e-08 -3.3933976766713263e-08 -3.4867318917436816e-08 -3.6627002119980855e-08 -3.439986711209072e-08 -3.037080730039989e-08 -2.4728841523216376e-08 -1.7694053454013604e-08 -1.013412174272899e-08 -4.7832449765398245e-09 -1.0727805259223392e-08 -2.404615478850998e-08 -3.262908932555904e-08 -2.8356359576658083e-08 -2.323698979634444e-08 -2.0556949215447575e-08 -2.0447811381850597e-08 -2.5025436735152743e-08 -2.3343086892107763e-08 -3.100508877607871e-08 -1.9600102983090943e-08 -3.043786789694743e-08 -3.985486860355653e-08 -3.834370408233572e-08 -3.5027163108962506e-08 -3.3358866405635216e-08 -3.327208210422075e-08 -3.7117300550131134e-08 -3.7325714364891624e-08 -3.167207872899518e-08 -2.406078320295295e-08 -1.5800084694167263e-08 -9.56049065951596e-09 -5.596519073885978e-09 -9.346652825917062e-09 -2.194319693917786e-08 -3.243579701786319e-08 -2.578570337566904e-08 -2.070635627981452e-08 -2.4616087677060465e-08 -2.3595139403886328e-08 -2.090145659378984e-08 -2.7129216405520988e-08 -3.158792425489631e-08 -1.704070573029676e-08 -3.400605047158115e-08 -3.777007299912269e-08 -3.6565201178064495e-08 -3.571888987506624e-08 -3.383198877613055e-08 -3.9566080691463313e-08 -4.2673386029039914e-08 -3.959131059727225e-08 -3.4407016955104984e-08 -2.5515570801095793e-08 -1.8369425981498515e-08 -1.0952819858913546e-08 -8.651227865150779e-09 -2.9775397959729636e-08 -6.173462095874578e-08 -6.557737394154779e-08 -4.779612527560166e-08 -4.20688544748687e-08 -3.827804058154959e-08 -3.9422426374349226e-08 -3.1413451648927644e-08 -3.092997433337718e-08 -2.8827180848252276e-08 -1.864112001604039e-08 -3.3595468681934686e-08 -3.6086408242419924e-08 -3.5647309262820034e-08 -3.416983940408022e-08 -3.47842328106849e-08 -3.695170361135258e-08 -4.0468029278607005e-08 -3.875740879191945e-08 -3.374084882322463e-08 -2.721920580897633e-08 -2.071202684496376e-08 -1.1522341836945966e-08 -9.784354709755546e-09 -2.9650398980135508e-08 -5.7775333753021683e-08 -6.211742519737132e-08 -4.822873186901619e-08 -3.8035767740100873e-08 -4.283725714364261e-08 -3.60714510995625e-08 -3.145059795976035e-08 -2.9009871664582158e-08 -2.812000384666945e-08 -2.142232676648385e-08 -2.8621150314496537e-08 -3.1909667190538e-08 -3.2843502433883223e-08 -3.1474512951911494e-08 -2.9804819152822796e-08 -3.118350612302076e-08 -3.568807158621167e-08 -3.618995769297127e-08 -3.4015337049289326e-08 -2.8976423548412e-08 -2.0906551884213795e-08 -1.385319065959467e-08 -8.923497174417939e-09 -2.2680288226475518e-08 -4.246004128806268e-08 -4.294779207300098e-08 -4.5546883281839853e-08 -4.601137653145591e-08 -4.722208328187057e-08 -4.455971185325033e-08 -4.071482213575439e-08 -3.919609686100126e-08 -3.429220855635876e-08 -2.1552667582812776e-08 -2.1880491994121763e-08 -2.5024779278323846e-08 -2.340957221393002e-08 -2.5545895997328686e-08 -2.139980887009411e-08 -2.387579128772193e-08 -2.838084984353452e-08 -2.9053592543703837e-08 -2.755722080113323e-08 -2.476163218255764e-08 -1.836424850897095e-08 -1.2363311303209424e-08 -7.770235714428189e-09 -2.177176507104285e-08 -4.137581279510718e-08 -4.087762488301012e-08 -3.5789155573654655e-08 -3.893122394105921e-08 -4.610629686112798e-08 -5.0537473705793214e-08 -4.701424474183537e-08 -3.453604285777611e-08 -3.2959461382080014e-08 -1.8337785871607828e-08 -2.2063840267280545e-08 -2.6118294348987537e-08 -2.9752715699132674e-08 -2.8454156279956586e-08 -2.885101365829981e-08 -2.9448559733663986e-08 -3.0920030298840104e-08 -2.9067727865525134e-08 -2.4992317347397035e-08 -1.9460475589053846e-08 -1.2290087048890972e-08 -7.487447095898671e-09 -6.9106930927483785e-09 -2.7016544741468683e-08 -5.6372403062258135e-08 -5.895826295241544e-08 -4.810595180621959e-08 -4.0753612088659346e-08 -4.026668312475717e-08 -3.558205667255196e-08 -3.137663406650939e-08 -3.199579403512357e-08 -2.896097331293291e-08 -1.9402290659696418e-08 -3.229707362696583e-08 -3.89763419159423e-08 -3.912994026759346e-08 -3.452009952967534e-08 -3.3933976766713263e-08 -3.4867318917436816e-08 -3.6627002119980855e-08 -3.439986711209072e-08 -3.037080730039989e-08 -2.4728841523216376e-08 -1.7694053454013604e-08 -1.013412174272899e-08 -4.7832449765398245e-09 -1.0727805259223392e-08 -2.404615478850998e-08 -3.262908932555904e-08 -2.8356359576658083e-08 -2.323698979634444e-08 -2.0556949215447575e-08 -2.0447811381850597e-08 -2.5025436735152743e-08 -2.3343086892107763e-08 -3.100508877607871e-08 -1.9600102983090943e-08 -3.043786789694743e-08 -3.985486860355653e-08 -3.834370408233572e-08 -3.5027163108962506e-08 -3.3358866405635216e-08 -3.327208210422075e-08 -3.7117300550131134e-08 -3.7325714364891624e-08 -3.167207872899518e-08 -2.406078320295295e-08 -1.5800084694167263e-08 -9.56049065951596e-09 -5.596519073885978e-09 -9.346652825917062e-09 -2.194319693917786e-08 -3.243579701786319e-08 -2.578570337566904e-08 -2.070635627981452e-08 -2.4616087677060465e-08 -2.3595139403886328e-08 -2.090145659378984e-08 -2.7129216405520988e-08 -3.158792425489631e-08 -1.704070573029676e-08 -3.400605047158115e-08 -3.777007299912269e-08 -3.6565201178064495e-08 -3.571888987506624e-08 -3.383198877613055e-08 -3.9566080691463313e-08 -4.2673386029039914e-08 -3.959131059727225e-08 -3.4407016955104984e-08 -2.5515570801095793e-08 -1.8369425981498515e-08 -1.0952819858913546e-08 -8.651227865150779e-09 -2.9775397959729636e-08 -6.173462095874578e-08 -6.557737394154779e-08 -4.779612527560166e-08 -4.20688544748687e-08 -3.827804058154959e-08 -3.9422426374349226e-08 -3.1413451648927644e-08 -3.092997433337718e-08 -2.8827180848252276e-08 -1.864112001604039e-08 -3.3595468681934686e-08 -3.6086408242419924e-08 -3.5647309262820034e-08 -3.416983940408022e-08 -3.47842328106849e-08 -3.695170361135258e-08 -4.0468029278607005e-08 -3.116452205708635e-08 -2.7712955887478314e-08 -2.2159253689574285e-08 -1.5708944741261353e-08 -9.776629592015998e-09 -7.873702982875927e-09 -2.694274521242495e-08 -5.4338560362063856e-08 -6.030646036217327e-08 -4.8049903611556076e-08 -3.6315531947290684e-08 -3.7234574411985714e-08 -3.790592001639363e-08 -2.981952974936937e-08 -3.113805941972322e-08 -2.882487974935114e-08 -1.607473728443917e-08 -2.7521800314476386e-08 -3.155768124076702e-08 -3.1090804710146216e-08 -3.0758049372620496e-08 -2.7969035322333877e-08 -2.953986405077712e-08 -3.366828202573508e-08 -3.55175437212164e-08 -3.321512990641751e-08 -2.69134062014354e-08 -1.890213037711268e-08 -1.0104536185428604e-08 -6.50849387767036e-09 -2.2574191130712194e-08 -4.336560588776533e-08 -4.536402810130275e-08 -4.481603783441672e-08 -4.3578046625602815e-08 -4.525604081715634e-08 -4.216977409810446e-08 -4.1514125275486475e-08 -4.068745549525153e-08 -3.1703225746264195e-08 -2.0617846154224202e-08 -2.7703587127666528e-08 -2.81338104400763e-08 -2.5606628571898097e-08 -2.6258168289335473e-08 -2.450752511818877e-08 -2.5191691130760187e-08 -2.994485745737795e-08 -3.177760055003322e-08 -2.9608814835707747e-08 -2.6286028022460002e-08 -2.063247456866717e-08 -1.4629236264004505e-08 -9.763727001748886e-09 -2.305298406635677e-08 -4.3068764129518125e-08 -4.19042437213335e-08 -3.822125274795357e-08 -3.5527816484167924e-08 -4.469161412954788e-08 -4.704974741059582e-08 -4.5236317112289425e-08 -4.7123711303846795e-08 -3.67669582424324e-08 -1.824072880724184e-08 -2.3120291209215144e-08 -2.4045086421163025e-08 -2.7504213344303376e-08 -2.8553267896912878e-08 -2.828247786551074e-08 -2.8571841052329234e-08 -2.793040973363615e-08 -2.7335575667691172e-08 -2.3896418995728587e-08 -1.8274670016033672e-08 -1.208701507086527e-08 -7.1074370487959426e-09 -6.188969858826196e-09 -2.7515307928291022e-08 -6.05103541612351e-08 -6.63923738630698e-08 -5.330528477334789e-08 -3.7333192936320334e-08 -3.609388681384863e-08 -3.9872537755833145e-08 -2.900420109943292e-08 -2.9491458791749545e-08 -2.7738678885908928e-08 -1.989793092658149e-08 -3.4442437441761837e-08 -4.1444845762141405e-08 -3.640650753598937e-08 -3.3007784459003975e-08 -3.2866595604998245e-08 -3.4616006044590765e-08 -3.5180761460613674e-08 -3.2131723234498114e-08 -2.876874937258402e-08 -2.292880690779876e-08 -1.5584356672185283e-08 -7.445945133574518e-09 -4.269606828963688e-09 -1.1591456986083812e-08 -2.9496800628484337e-08 -3.534101656265743e-08 -2.9187713736798922e-08 -1.875370949798908e-08 -1.8645886578049896e-08 -2.3612808556162948e-08 -1.853403673503372e-08 -2.0536650235855366e-08 -3.230734638991735e-08 -1.8447663344137313e-08 -3.3017153218815765e-08 -3.785357001639267e-08 -3.52112510210538e-08 -3.275869050295545e-08 -3.3119634302020156e-08 -3.322984050296409e-08 -3.5108934302056627e-08 -3.2724831476267236e-08 -2.8832276138676232e-08 -2.2515266562422256e-08 -1.4520509340925589e-08 -8.604219701884611e-09 -5.042693877643483e-09 -9.83275996878312e-09 -2.3222114835590635e-08 -2.8199063030344373e-08 -2.0741201491746084e-08 -1.8631093799399702e-08 -2.028073516520703e-08 -2.561550423908821e-08 -2.914349976505557e-08 -2.331736389367715e-08 -2.7749033830964064e-08 -1.7195783359812946e-08 -2.7794316170054377e-08 -2.926184199425711e-08 -2.9140705573532753e-08 -2.781231405074544e-08 -2.8889392700686698e-08 -3.1258374019411455e-08 -3.417214050298137e-08 -3.204888367405703e-08 -2.8724206672426217e-08 -2.1706430298671167e-08 -1.45853510206756e-08 -8.627559419310472e-09 -6.644340894941298e-09 -2.752064976502581e-08 -5.572069898061353e-08 -5.822207566825751e-08 -4.29937318689202e-08 -3.3939318603448055e-08 -3.6117883988103385e-08 -3.583164372122215e-08 -3.194525204140207e-08 -3.135600635850273e-08 -2.7335575667691172e-08 -2.003575031433912e-08 -2.7185675510702556e-08 -3.264404646841646e-08 -3.432064356420858e-08 -2.9538466955015714e-08 -2.8521216876504126e-08 -3.034935777135711e-08 -3.180677519681554e-08 -3.116452205708635e-08 -2.7712955887478314e-08 -2.2159253689574285e-08 -1.5708944741261353e-08 -9.776629592015998e-09 -7.873702982875927e-09 -2.694274521242495e-08 -5.4338560362063856e-08 -6.030646036217327e-08 -4.8049903611556076e-08 -3.6315531947290684e-08 -3.7234574411985714e-08 -3.790592001639363e-08 -2.981952974936937e-08 -3.113805941972322e-08 -2.882487974935114e-08 -1.607473728443917e-08 -2.7521800314476386e-08 -3.155768124076702e-08 -3.1090804710146216e-08 -3.0758049372620496e-08 -2.7969035322333877e-08 -2.953986405077712e-08 -3.366828202573508e-08 -3.55175437212164e-08 -3.321512990641751e-08 -2.69134062014354e-08 -1.890213037711268e-08 -1.0104536185428604e-08 -6.50849387767036e-09 -2.2574191130712194e-08 -4.336560588776533e-08 -4.536402810130275e-08 -4.481603783441672e-08 -4.3578046625602815e-08 -4.525604081715634e-08 -4.216977409810446e-08 -4.1514125275486475e-08 -4.068745549525153e-08 -3.1703225746264195e-08 -2.0617846154224202e-08 -2.7703587127666528e-08 -2.81338104400763e-08 -2.5606628571898097e-08 -2.6258168289335473e-08 -2.450752511818877e-08 -2.5191691130760187e-08 -2.994485745737795e-08 -3.177760055003322e-08 -2.9608814835707747e-08 -2.6286028022460002e-08 -2.063247456866717e-08 -1.4629236264004505e-08 -9.763727001748886e-09 -2.305298406635677e-08 -4.3068764129518125e-08 -4.19042437213335e-08 -3.822125274795357e-08 -3.5527816484167924e-08 -4.469161412954788e-08 -4.704974741059582e-08 -4.5236317112289425e-08 -4.7123711303846795e-08 -3.67669582424324e-08 -1.824072880724184e-08 -2.3120291209215144e-08 -2.4045086421163025e-08 -2.7504213344303376e-08 -2.8553267896912878e-08 -2.828247786551074e-08 -2.8571841052329234e-08 -2.793040973363615e-08 -2.7335575667691172e-08 -2.3896418995728587e-08 -1.8274670016033672e-08 -1.208701507086527e-08 -7.1074370487959426e-09 -6.188969858826196e-09 -2.7515307928291022e-08 -6.05103541612351e-08 -6.63923738630698e-08 -5.330528477334789e-08 -3.7333192936320334e-08 -3.609388681384863e-08 -3.9872537755833145e-08 -2.900420109943292e-08 -2.9491458791749545e-08 -2.7738678885908928e-08 -1.989793092658149e-08 -3.4442437441761837e-08 -4.1444845762141405e-08 -3.640650753598937e-08 -3.3007784459003975e-08 -3.2866595604998245e-08 -3.4616006044590765e-08 -3.5180761460613674e-08 -3.2131723234498114e-08 -2.876874937258402e-08 -2.292880690779876e-08 -1.5584356672185283e-08 -7.445945133574518e-09 -4.269606828963688e-09 -1.1591456986083812e-08 -2.9496800628484337e-08 -3.534101656265743e-08 -2.9187713736798922e-08 -1.875370949798908e-08 -1.8645886578049896e-08 -2.3612808556162948e-08 -1.853403673503372e-08 -2.0536650235855366e-08 -3.230734638991735e-08 -1.8447663344137313e-08 -3.3017153218815765e-08 -3.785357001639267e-08 -3.52112510210538e-08 -3.275869050295545e-08 -3.3119634302020156e-08 -3.322984050296409e-08 -3.5108934302056627e-08 -3.2724831476267236e-08 -2.8832276138676232e-08 -2.2515266562422256e-08 -1.4520509340925589e-08 -8.604219701884611e-09 -5.042693877643483e-09 -9.83275996878312e-09 -2.3222114835590635e-08 -2.8199063030344373e-08 -2.0741201491746084e-08 -1.8631093799399702e-08 -2.028073516520703e-08 -2.561550423908821e-08 -2.914349976505557e-08 -2.331736389367715e-08 -2.7749033830964064e-08 -1.7195783359812946e-08 -2.7794316170054377e-08 -2.926184199425711e-08 -2.9140705573532753e-08 -2.781231405074544e-08 -2.8889392700686698e-08 -3.1258374019411455e-08 -3.417214050298137e-08 -3.204888367405703e-08 -2.8724206672426217e-08 -2.1706430298671167e-08 -1.45853510206756e-08 -8.627559419310472e-09 -6.644340894941298e-09 -2.752064976502581e-08 -5.572069898061353e-08 -5.822207566825751e-08 -4.29937318689202e-08 -3.3939318603448055e-08 -3.6117883988103385e-08 -3.583164372122215e-08 -3.194525204140207e-08 -3.135600635850273e-08 -2.7335575667691172e-08 -2.003575031433912e-08 -2.7185675510702556e-08 -3.264404646841646e-08 -3.432064356420858e-08 -2.9538466955015714e-08 -2.8521216876504126e-08 -3.034935777135711e-08 -3.180677519681554e-08 -3.116452205708635e-08 -2.7712955887478314e-08 -2.2159253689574285e-08 -1.5708944741261353e-08 -9.776629592015998e-09 -7.873702982875927e-09 -2.694274521242495e-08 -5.4338560362063856e-08 -6.030646036217327e-08 -4.8049903611556076e-08 -3.6315531947290684e-08 -3.7234574411985714e-08 -3.790592001639363e-08 -2.981952974936937e-08 -3.113805941972322e-08 -2.882487974935114e-08 -1.607473728443917e-08 -2.7521800314476386e-08 -3.155768124076702e-08 -3.1090804710146216e-08 -3.0758049372620496e-08 -2.7969035322333877e-08 -2.953986405077712e-08 -3.366828202573508e-08 -3.55175437212164e-08 -3.321512990641751e-08 -2.69134062014354e-08 -1.890213037711268e-08 -1.0104536185428604e-08 -6.50849387767036e-09 -2.2574191130712194e-08 -4.336560588776533e-08 -4.536402810130275e-08 -4.481603783441672e-08 -4.3578046625602815e-08 -4.525604081715634e-08 -4.216977409810446e-08 -4.1514125275486475e-08 -4.068745549525153e-08 -3.1703225746264195e-08 -2.0617846154224202e-08 -2.7703587127666528e-08 -2.81338104400763e-08 -2.5606628571898097e-08 -2.6258168289335473e-08 -2.450752511818877e-08 -2.5191691130760187e-08 -2.994485745737795e-08 -3.177760055003322e-08 -2.9608814835707747e-08 -2.6286028022460002e-08 -2.063247456866717e-08 -1.4629236264004505e-08 -9.763727001748886e-09 -2.305298406635677e-08 -4.3068764129518125e-08 -4.19042437213335e-08 -3.822125274795357e-08 -3.5527816484167924e-08 -4.469161412954788e-08 -4.704974741059582e-08 -4.5236317112289425e-08 -4.7123711303846795e-08 -3.67669582424324e-08 -1.824072880724184e-08 -2.3120291209215144e-08 -2.4045086421163025e-08 -2.7504213344303376e-08 -2.8553267896912878e-08 -2.828247786551074e-08 -2.8571841052329234e-08 -2.793040973363615e-08 -2.7335575667691172e-08 -2.3896418995728587e-08 -1.8274670016033672e-08 -1.208701507086527e-08 -7.1074370487959426e-09 -6.188969858826196e-09 -2.7515307928291022e-08 -6.05103541612351e-08 -6.63923738630698e-08 -5.330528477334789e-08 -3.7333192936320334e-08 -3.609388681384863e-08 -3.9872537755833145e-08 -2.900420109943292e-08 -2.9491458791749545e-08 -2.7738678885908928e-08 -1.989793092658149e-08 -3.4442437441761837e-08 -4.1444845762141405e-08 -3.640650753598937e-08 -3.3007784459003975e-08 -3.2866595604998245e-08 -3.4616006044590765e-08 -3.5180761460613674e-08 -3.2131723234498114e-08 -2.876874937258402e-08 -2.292880690779876e-08 -1.5584356672185283e-08 -7.445945133574518e-09 -4.269606828963688e-09 -1.1591456986083812e-08 -2.9496800628484337e-08 -3.534101656265743e-08 -2.9187713736798922e-08 -1.875370949798908e-08 -1.8645886578049896e-08 -2.3612808556162948e-08 -1.853403673503372e-08 -2.0536650235855366e-08 -3.230734638991735e-08 -1.8447663344137313e-08 -3.3017153218815765e-08 -3.785357001639267e-08 -3.52112510210538e-08 -3.275869050295545e-08 -3.3119634302020156e-08 -3.322984050296409e-08 -3.5108934302056627e-08 -3.2724831476267236e-08 -2.8832276138676232e-08 -2.2515266562422256e-08 -1.4520509340925589e-08 -8.604219701884611e-09 -5.042693877643483e-09 -9.83275996878312e-09 -2.3222114835590635e-08 -2.8199063030344373e-08 -2.0741201491746084e-08 -1.8631093799399702e-08 -2.028073516520703e-08 -2.561550423908821e-08 -2.914349976505557e-08 -2.331736389367715e-08 -2.7749033830964064e-08 -1.7195783359812946e-08 -2.7794316170054377e-08 -2.926184199425711e-08 -2.9140705573532753e-08 -2.781231405074544e-08 -2.8889392700686698e-08 -3.1258374019411455e-08 -3.417214050298137e-08 -3.204888367405703e-08 -2.8724206672426217e-08 -2.1706430298671167e-08 -1.45853510206756e-08 -8.627559419310472e-09 -6.644340894941298e-09 -2.752064976502581e-08 -5.572069898061353e-08 -5.822207566825751e-08 -4.29937318689202e-08 -3.3939318603448055e-08 -3.6117883988103385e-08 -3.583164372122215e-08 -3.194525204140207e-08 -3.135600635850273e-08 -2.7335575667691172e-08 -2.003575031433912e-08 -2.7185675510702556e-08 -3.264404646841646e-08 -3.432064356420858e-08 -2.9538466955015714e-08 -2.8521216876504126e-08 -3.034935777135711e-08 -3.180677519681554e-08 -3.116452205708635e-08 -2.7712955887478314e-08 -2.2159253689574285e-08 -1.5708944741261353e-08 -9.776629592015998e-09 -7.873702982875927e-09 -2.694274521242495e-08 -5.4338560362063856e-08 -6.030646036217327e-08 -4.8049903611556076e-08 -3.6315531947290684e-08 -3.7234574411985714e-08 -3.790592001639363e-08 -2.981952974936937e-08 -3.113805941972322e-08 -2.882487974935114e-08 -1.607473728443917e-08 -2.7521800314476386e-08 -3.155768124076702e-08 -3.1090804710146216e-08 -3.0758049372620496e-08 -2.7969035322333877e-08 -2.953986405077712e-08 -3.366828202573508e-08 -3.55175437212164e-08 -3.321512990641751e-08 -2.69134062014354e-08 -1.890213037711268e-08 -1.0104536185428604e-08 -6.50849387767036e-09 -2.2574191130712194e-08 -4.336560588776533e-08 -4.536402810130275e-08 -4.481603783441672e-08 -4.3578046625602815e-08 -4.525604081715634e-08 -4.216977409810446e-08 -4.1514125275486475e-08 -4.068745549525153e-08 -3.1703225746264195e-08 -2.0617846154224202e-08 -2.7703587127666528e-08 -2.81338104400763e-08 -2.5606628571898097e-08 -2.6258168289335473e-08 -2.450752511818877e-08 -2.5191691130760187e-08 -2.994485745737795e-08 -3.177760055003322e-08 -2.9608814835707747e-08 -2.6286028022460002e-08 -2.063247456866717e-08 -1.4629236264004505e-08 -9.763727001748886e-09 -2.305298406635677e-08 -4.3068764129518125e-08 -4.19042437213335e-08 -3.822125274795357e-08 -3.5527816484167924e-08 -4.469161412954788e-08 -4.704974741059582e-08 -4.5236317112289425e-08 -4.7123711303846795e-08 -3.67669582424324e-08 -1.824072880724184e-08 -2.3120291209215144e-08 -2.4045086421163025e-08 -2.7504213344303376e-08 -2.8553267896912878e-08 -2.828247786551074e-08 -2.8571841052329234e-08 -2.793040973363615e-08 -2.7335575667691172e-08 -2.3896418995728587e-08 -1.8274670016033672e-08 -1.208701507086527e-08 -7.1074370487959426e-09 -6.188969858826196e-09 -2.7515307928291022e-08 -6.05103541612351e-08 -6.63923738630698e-08 -5.330528477334789e-08 -3.7333192936320334e-08 -3.609388681384863e-08 -3.9872537755833145e-08 -2.900420109943292e-08 -2.9491458791749545e-08 -2.7738678885908928e-08 -1.989793092658149e-08 -3.4442437441761837e-08 -4.1444845762141405e-08 -3.640650753598937e-08 -3.3007784459003975e-08 -3.2866595604998245e-08 -3.4616006044590765e-08 -3.5180761460613674e-08 -3.2131723234498114e-08 -2.876874937258402e-08 -2.292880690779876e-08 -1.5584356672185283e-08 -7.445945133574518e-09 -4.269606828963688e-09 -1.1591456986083812e-08 -2.9496800628484337e-08 -3.534101656265743e-08 -2.9187713736798922e-08 -1.875370949798908e-08 -1.8645886578049896e-08 -2.3612808556162948e-08 -1.853403673503372e-08 -2.0536650235855366e-08 -3.230734638991735e-08 -1.8447663344137313e-08 -3.3017153218815765e-08 -3.785357001639267e-08 -3.52112510210538e-08 -3.275869050295545e-08 -3.3119634302020156e-08 -3.322984050296409e-08 -3.5108934302056627e-08 -3.2724831476267236e-08 -2.8832276138676232e-08 -2.2515266562422256e-08 -1.4520509340925589e-08 -8.604219701884611e-09 -5.042693877643483e-09 -9.83275996878312e-09 -2.3222114835590635e-08 -2.8199063030344373e-08 -2.0741201491746084e-08 -1.8631093799399702e-08 -2.028073516520703e-08 -2.561550423908821e-08 -2.914349976505557e-08 -2.331736389367715e-08 -2.7749033830964064e-08 -1.7195783359812946e-08 -2.7794316170054377e-08 -2.926184199425711e-08 -2.9140705573532753e-08 -2.781231405074544e-08 -2.8889392700686698e-08 -3.1258374019411455e-08 -3.417214050298137e-08 -3.204888367405703e-08 -2.8724206672426217e-08 -2.1706430298671167e-08 -1.45853510206756e-08 -8.627559419310472e-09 -6.644340894941298e-09 -2.752064976502581e-08 -5.572069898061353e-08 -5.822207566825751e-08 -4.29937318689202e-08 -3.3939318603448055e-08 -3.6117883988103385e-08 -3.583164372122215e-08 -3.194525204140207e-08 -3.135600635850273e-08 -2.7335575667691172e-08 -2.003575031433912e-08 -2.7185675510702556e-08 -3.264404646841646e-08 -3.432064356420858e-08 -2.9538466955015714e-08 -2.8521216876504126e-08 -3.034935777135711e-08 -3.180677519681554e-08 -3.116452205708635e-08 -2.7712955887478314e-08 -2.2159253689574285e-08 -1.5708944741261353e-08 -9.776629592015998e-09 -7.873702982875927e-09 -2.694274521242495e-08 -5.4338560362063856e-08 -6.030646036217327e-08 -4.8049903611556076e-08 -3.6315531947290684e-08 -3.7234574411985714e-08 -3.790592001639363e-08 -2.981952974936937e-08 -3.113805941972322e-08 -2.882487974935114e-08 -1.607473728443917e-08 -2.7521800314476386e-08 -3.155768124076702e-08 -3.1090804710146216e-08 -3.0758049372620496e-08 -2.7969035322333877e-08 -2.953986405077712e-08 -3.366828202573508e-08 -3.55175437212164e-08 -3.321512990641751e-08 -2.69134062014354e-08 -1.890213037711268e-08 -1.0104536185428604e-08 -6.50849387767036e-09 -2.2574191130712194e-08 -4.336560588776533e-08 -4.536402810130275e-08 -4.481603783441672e-08 -4.3578046625602815e-08 -4.525604081715634e-08 -4.216977409810446e-08 -4.1514125275486475e-08 -4.068745549525153e-08 -3.1703225746264195e-08 -2.0617846154224202e-08 -2.7703587127666528e-08 -2.81338104400763e-08 -2.5606628571898097e-08 -2.6258168289335473e-08 -2.450752511818877e-08 -2.5191691130760187e-08 -2.994485745737795e-08 -3.177760055003322e-08 -2.9608814835707747e-08 -2.6286028022460002e-08 -2.063247456866717e-08 -1.4629236264004505e-08 -9.763727001748886e-09 -2.305298406635677e-08 -4.3068764129518125e-08 -4.19042437213335e-08 -3.822125274795357e-08 -3.5527816484167924e-08 -4.469161412954788e-08 -4.704974741059582e-08 -4.5236317112289425e-08 -4.7123711303846795e-08 -3.67669582424324e-08 -1.824072880724184e-08 -2.3120291209215144e-08 -2.4045086421163025e-08 -2.7504213344303376e-08 -2.8553267896912878e-08 -2.828247786551074e-08 -2.8571841052329234e-08 -2.793040973363615e-08 -3.1025634301981756e-08 -2.6760218760302295e-08 -2.2533757535735002e-08 -1.590396287313306e-08 -1.003427048684019e-08 -7.899179434995702e-09 -2.749040675089653e-08 -5.447744811716844e-08 -5.961300777189369e-08 -4.3419024255113235e-08 -3.5198841523408355e-08 -3.470147543234743e-08 -3.3943098980214214e-08 -2.8277218210879558e-08 -3.1402685793354447e-08 -3.0633461303544426e-08 -2.518339073829535e-08 -3.277340109950203e-08 -3.462734717488924e-08 -3.1824690895403e-08 -2.9802928964439717e-08 -3.016543422347305e-08 -3.286199340719596e-08 -3.3241756907987856e-08 -3.077662252803685e-08 -2.7904358006791088e-08 -2.149267464717588e-08 -1.368586789664027e-08 -8.776966483677418e-09 -4.652082339174782e-09 -1.0778347252944883e-08 -2.754859168025395e-08 -3.360730290485484e-08 -2.4996837363095704e-08 -2.3507533281435744e-08 -2.1651614835561842e-08 -2.2543783752375682e-08 -2.707177111509607e-08 -2.8545049686551657e-08 -2.5517214443168037e-08 -1.8812387519968176e-08 -2.989439764576008e-08 -3.5918838933154685e-08 -3.512635690802241e-08 -3.037606695503107e-08 -3.149851012616625e-08 -3.200779262225094e-08 -3.583041098966797e-08 -3.327339701787854e-08 -3.069707025174025e-08 -2.4261225353663063e-08 -1.5116247410010296e-08 -9.481431475841041e-09 -5.7983583203574965e-09 -7.869511695591705e-09 -2.4811681083657456e-08 -3.1588992622243264e-08 -2.5520830455726975e-08 -1.7072921114912736e-08 -2.2004915698990607e-08 -2.6421792857627324e-08 -2.8400655730505056e-08 -2.714967974932042e-08 -3.3682746075970825e-08 -2.1324201334770907e-08 -3.013198610730289e-08 -3.5399365856222076e-08 -3.351903932557536e-08 -3.164158916855506e-08 -3.432828649984451e-08 -3.666053241825462e-08 -4.026446420795964e-08 -4.034960486730186e-08 -3.498985243392258e-08 -2.6395494584471426e-08 -1.932249183708899e-08 -1.1729769466463114e-08 -9.758713893428543e-09 -3.1462514364784115e-08 -6.33734142868763e-08 -6.680369529164877e-08 -4.7293335165702345e-08 -3.94405064371439e-08 -3.896606915299077e-08 -3.5454016955124184e-08 -3.3725809498263606e-08 -3.2702067033566654e-08 -2.9917572998978706e-08 -1.8326691287620182e-08 -3.25930935641769e-08 -3.849352205722073e-08 -3.799163595046113e-08 -3.501121978086174e-08 -3.324151036167702e-08 -3.558419340724588e-08 -4.118194521268604e-08 -4.207419631160349e-08 -3.622077598182584e-08 -2.9575941994262868e-08 -2.0777115071024614e-08 -1.2422811146224645e-08 -1.1035823783561849e-08 -2.9043812873373986e-08 -6.300753956159486e-08 -6.216081734807855e-08 -4.660785423947313e-08 -4.077793799132855e-08 -3.9790520016428185e-08 -3.91308442707332e-08 -3.4584941209425355e-08 -2.9744744035082292e-08 -2.741471703346971e-08 -1.9574708713074777e-08 -3.0307116170100454e-08 -3.5142628964537626e-08 -2.880088257509638e-08 -2.827869748874458e-08 -2.8987189403985195e-08 -3.233701412932134e-08 -3.624477315608059e-08 -3.479623139781228e-08 -3.3419434615997394e-08 -2.912698116222952e-08 -2.200992880731095e-08 -1.3124481946865455e-08 -8.851341287446441e-09 -2.3984846939215295e-08 -4.359251067583856e-08 -3.867826742614091e-08 -3.842679018908764e-08 -4.2116684459171e-08 -4.672430628029158e-08 -4.312629160204665e-08 -4.1689666248802095e-08 -3.897305463179781e-08 -4.015754529116019e-08 -1.8233907692642028e-08 -2.3026521428993645e-08 -2.6492551648837415e-08 -2.678265447458842e-08 -2.445764058129618e-08 -2.541185698633722e-08 -2.777771538512472e-08 -3.302487833655531e-08 -3.4852608320890235e-08 -3.284407770860851e-08 -2.835192174306303e-08 -2.198050761421779e-08 -1.4157346625063356e-08 -9.793476923256496e-09 -2.4993139168433152e-08 -4.2960365934853663e-08 -4.1869151963091106e-08 -3.486592182167541e-08 -3.5335428179611804e-08 -5.16356731563628e-08 -4.9843034930270275e-08 -4.0811961382223994e-08 -3.4305028964522264e-08 -3.679087323458354e-08 -1.95202219783799e-08 -2.1026537755487583e-08 -2.5067678336409405e-08 -2.664245180582603e-08 -2.6832621193584623e-08 -2.8068229121393778e-08 -2.8718947017795038e-08 -3.130661491423181e-08 -3.1025634301981756e-08 -2.6760218760302295e-08 -2.2533757535735002e-08 -1.590396287313306e-08 -1.003427048684019e-08 -7.899179434995702e-09 -2.749040675089653e-08 -5.447744811716844e-08 -5.961300777189369e-08 -4.3419024255113235e-08 -3.5198841523408355e-08 -3.470147543234743e-08 -3.3943098980214214e-08 -2.8277218210879558e-08 -3.1402685793354447e-08 -3.0633461303544426e-08 -2.518339073829535e-08 -3.277340109950203e-08 -3.462734717488924e-08 -3.1824690895403e-08 -2.9802928964439717e-08 -3.016543422347305e-08 -3.286199340719596e-08 -3.3241756907987856e-08 -3.077662252803685e-08 -2.7904358006791088e-08 -2.149267464717588e-08 -1.368586789664027e-08 -8.776966483677418e-09 -4.652082339174782e-09 -1.0778347252944883e-08 -2.754859168025395e-08 -3.360730290485484e-08 -2.4996837363095704e-08 -2.3507533281435744e-08 -2.1651614835561842e-08 -2.2543783752375682e-08 -2.707177111509607e-08 -2.8545049686551657e-08 -2.5517214443168037e-08 -1.8812387519968176e-08 -2.989439764576008e-08 -3.5918838933154685e-08 -3.512635690802241e-08 -3.037606695503107e-08 -3.149851012616625e-08 -3.200779262225094e-08 -3.583041098966797e-08 -3.327339701787854e-08 -3.069707025174025e-08 -2.4261225353663063e-08 -1.5116247410010296e-08 -9.481431475841041e-09 -5.7983583203574965e-09 -7.869511695591705e-09 -2.4811681083657456e-08 -3.1588992622243264e-08 -2.5520830455726975e-08 -1.7072921114912736e-08 -2.2004915698990607e-08 -2.6421792857627324e-08 -2.8400655730505056e-08 -2.714967974932042e-08 -3.3682746075970825e-08 -2.1324201334770907e-08 -3.013198610730289e-08 -3.5399365856222076e-08 -3.351903932557536e-08 -3.164158916855506e-08 -3.432828649984451e-08 -3.666053241825462e-08 -4.026446420795964e-08 -4.034960486730186e-08 -3.498985243392258e-08 -2.6395494584471426e-08 -1.932249183708899e-08 -1.1729769466463114e-08 -9.758713893428543e-09 -3.1462514364784115e-08 -6.33734142868763e-08 -6.680369529164877e-08 -4.7293335165702345e-08 -3.94405064371439e-08 -3.896606915299077e-08 -3.5454016955124184e-08 -3.3725809498263606e-08 -3.2702067033566654e-08 -2.9917572998978706e-08 -1.8326691287620182e-08 -3.25930935641769e-08 -3.849352205722073e-08 -3.799163595046113e-08 -3.501121978086174e-08 -3.324151036167702e-08 -3.558419340724588e-08 -4.118194521268604e-08 -4.207419631160349e-08 -3.622077598182584e-08 -2.9575941994262868e-08 -2.0777115071024614e-08 -1.2422811146224645e-08 -1.1035823783561849e-08 -2.9043812873373986e-08 -6.300753956159486e-08 -6.216081734807855e-08 -4.660785423947313e-08 -4.077793799132855e-08 -3.9790520016428185e-08 -3.91308442707332e-08 -3.4584941209425355e-08 -2.9744744035082292e-08 -2.741471703346971e-08 -1.9574708713074777e-08 -3.0307116170100454e-08 -3.5142628964537626e-08 -2.880088257509638e-08 -2.827869748874458e-08 -2.8987189403985195e-08 -3.233701412932134e-08 -3.624477315608059e-08 -3.479623139781228e-08 -3.3419434615997394e-08 -2.912698116222952e-08 -2.200992880731095e-08 -1.3124481946865455e-08 -8.851341287446441e-09 -2.3984846939215295e-08 -4.359251067583856e-08 -3.867826742614091e-08 -3.842679018908764e-08 -4.2116684459171e-08 -4.672430628029158e-08 -4.312629160204665e-08 -4.1689666248802095e-08 -3.897305463179781e-08 -4.015754529116019e-08 -1.8233907692642028e-08 -2.3026521428993645e-08 -2.6492551648837415e-08 -2.678265447458842e-08 -2.445764058129618e-08 -2.541185698633722e-08 -2.777771538512472e-08 -3.302487833655531e-08 -3.4852608320890235e-08 -3.284407770860851e-08 -2.835192174306303e-08 -2.198050761421779e-08 -1.4157346625063356e-08 -9.793476923256496e-09 -2.4993139168433152e-08 -4.2960365934853663e-08 -4.1869151963091106e-08 -3.486592182167541e-08 -3.5335428179611804e-08 -5.16356731563628e-08 -4.9843034930270275e-08 -4.0811961382223994e-08 -3.4305028964522264e-08 -3.679087323458354e-08 -1.95202219783799e-08 -2.1026537755487583e-08 -2.5067678336409405e-08 -2.664245180582603e-08 -2.6832621193584623e-08 -2.8068229121393778e-08 -2.8718947017795038e-08 -3.130661491423181e-08 -3.1025634301981756e-08 -2.6760218760302295e-08 -2.2533757535735002e-08 -1.590396287313306e-08 -1.003427048684019e-08 -7.899179434995702e-09 -2.749040675089653e-08 -5.447744811716844e-08 -5.961300777189369e-08 -4.3419024255113235e-08 -3.5198841523408355e-08 -3.470147543234743e-08 -3.3943098980214214e-08 -2.8277218210879558e-08 -3.1402685793354447e-08 -3.0633461303544426e-08 -2.518339073829535e-08 -3.277340109950203e-08 -3.462734717488924e-08 -3.1824690895403e-08 -2.9802928964439717e-08 -3.016543422347305e-08 -3.286199340719596e-08 -3.3241756907987856e-08 -3.077662252803685e-08 -2.7904358006791088e-08 -2.149267464717588e-08 -1.368586789664027e-08 -8.776966483677418e-09 -4.652082339174782e-09 -1.0778347252944883e-08 -2.754859168025395e-08 -3.360730290485484e-08 -2.4996837363095704e-08 -2.3507533281435744e-08 -2.1651614835561842e-08 -2.2543783752375682e-08 -2.707177111509607e-08 -2.8545049686551657e-08 -2.5517214443168037e-08 -1.8812387519968176e-08 -2.989439764576008e-08 -3.5918838933154685e-08 -3.512635690802241e-08 -3.037606695503107e-08 -3.149851012616625e-08 -3.200779262225094e-08 -3.583041098966797e-08 -3.327339701787854e-08 -3.069707025174025e-08 -2.4261225353663063e-08 -1.5116247410010296e-08 -9.481431475841041e-09 -5.7983583203574965e-09 -7.869511695591705e-09 -2.4811681083657456e-08 -3.1588992622243264e-08 -2.5520830455726975e-08 -1.7072921114912736e-08 -2.2004915698990607e-08 -2.6421792857627324e-08 -2.8400655730505056e-08 -2.714967974932042e-08 -3.3682746075970825e-08 -2.1324201334770907e-08 -3.013198610730289e-08 -3.5399365856222076e-08 -3.351903932557536e-08 -3.164158916855506e-08 -3.432828649984451e-08 -3.666053241825462e-08 -4.026446420795964e-08 -4.034960486730186e-08 -3.498985243392258e-08 -2.6395494584471426e-08 -1.932249183708899e-08 -1.1729769466463114e-08 -9.758713893428543e-09 -3.1462514364784115e-08 -6.33734142868763e-08 -6.680369529164877e-08 -4.7293335165702345e-08 -3.94405064371439e-08 -3.896606915299077e-08 -3.5454016955124184e-08 -3.3725809498263606e-08 -3.2702067033566654e-08 -2.9917572998978706e-08 -1.8326691287620182e-08 -3.25930935641769e-08 -3.849352205722073e-08 -3.799163595046113e-08 -3.501121978086174e-08 -3.324151036167702e-08 -3.558419340724588e-08 -4.118194521268604e-08 -4.207419631160349e-08 -3.622077598182584e-08 -2.9575941994262868e-08 -2.0777115071024614e-08 -1.2422811146224645e-08 -1.1035823783561849e-08 -2.9043812873373986e-08 -6.300753956159486e-08 -6.216081734807855e-08 -4.660785423947313e-08 -4.077793799132855e-08 -3.9790520016428185e-08 -3.91308442707332e-08 -3.4584941209425355e-08 -2.9744744035082292e-08 -2.741471703346971e-08 -1.9574708713074777e-08 -3.0307116170100454e-08 -3.5142628964537626e-08 -2.880088257509638e-08 -2.827869748874458e-08 -2.8987189403985195e-08 -3.233701412932134e-08 -3.624477315608059e-08 -3.479623139781228e-08 -3.3419434615997394e-08 -2.912698116222952e-08 -2.200992880731095e-08 -1.3124481946865455e-08 -8.851341287446441e-09 -2.3984846939215295e-08 -4.359251067583856e-08 -3.867826742614091e-08 -3.842679018908764e-08 -4.2116684459171e-08 -4.672430628029158e-08 -4.312629160204665e-08 -4.1689666248802095e-08 -3.897305463179781e-08 -4.015754529116019e-08 -1.8233907692642028e-08 -2.3026521428993645e-08 -2.6492551648837415e-08 -2.678265447458842e-08 -2.445764058129618e-08 -2.541185698633722e-08 -2.777771538512472e-08 -3.302487833655531e-08 -3.4852608320890235e-08 -3.284407770860851e-08 -2.835192174306303e-08 -2.198050761421779e-08 -1.4157346625063356e-08 -9.793476923256496e-09 -2.4993139168433152e-08 -4.2960365934853663e-08 -4.1869151963091106e-08 -3.486592182167541e-08 -3.5335428179611804e-08 -5.16356731563628e-08 -4.9843034930270275e-08 -4.0811961382223994e-08 -3.4305028964522264e-08 -3.679087323458354e-08 -1.95202219783799e-08 -2.1026537755487583e-08 -2.5067678336409405e-08 -2.664245180582603e-08 -2.6832621193584623e-08 -2.8068229121393778e-08 -2.8718947017795038e-08 -3.130661491423181e-08 -3.1025634301981756e-08 -2.6760218760302295e-08 -2.2533757535735002e-08 -1.590396287313306e-08 -1.003427048684019e-08 -7.899179434995702e-09 -2.749040675089653e-08 -5.447744811716844e-08 -5.961300777189369e-08 -4.3419024255113235e-08 -3.5198841523408355e-08 -3.470147543234743e-08 -3.3943098980214214e-08 -2.8277218210879558e-08 -3.1402685793354447e-08 -3.0633461303544426e-08 -2.518339073829535e-08 -3.277340109950203e-08 -3.462734717488924e-08 -3.1824690895403e-08 -2.9802928964439717e-08 -3.016543422347305e-08 -3.286199340719596e-08 -3.3241756907987856e-08 -3.077662252803685e-08 -2.7904358006791088e-08 -2.149267464717588e-08 -1.368586789664027e-08 -8.776966483677418e-09 -4.652082339174782e-09 -1.0778347252944883e-08 -2.754859168025395e-08 -3.360730290485484e-08 -2.4996837363095704e-08 -2.3507533281435744e-08 -2.1651614835561842e-08 -2.2543783752375682e-08 -2.707177111509607e-08 -2.8545049686551657e-08 -2.5517214443168037e-08 -1.8812387519968176e-08 -2.989439764576008e-08 -3.5918838933154685e-08 -3.512635690802241e-08 -3.037606695503107e-08 -3.149851012616625e-08 -3.200779262225094e-08 -3.583041098966797e-08 -3.327339701787854e-08 -3.069707025174025e-08 -2.4261225353663063e-08 -1.5116247410010296e-08 -9.481431475841041e-09 -5.7983583203574965e-09 -7.869511695591705e-09 -2.4811681083657456e-08 -3.1588992622243264e-08 -2.5520830455726975e-08 -1.7072921114912736e-08 -2.2004915698990607e-08 -2.6421792857627324e-08 -2.8400655730505056e-08 -2.714967974932042e-08 -3.3682746075970825e-08 -2.1324201334770907e-08 -3.013198610730289e-08 -3.5399365856222076e-08 -3.351903932557536e-08 -3.164158916855506e-08 -3.432828649984451e-08 -3.666053241825462e-08 -4.026446420795964e-08 -4.034960486730186e-08 -3.498985243392258e-08 -2.6395494584471426e-08 -1.932249183708899e-08 -1.1729769466463114e-08 -9.758713893428543e-09 -3.1462514364784115e-08 -6.33734142868763e-08 -6.680369529164877e-08 -4.7293335165702345e-08 -3.94405064371439e-08 -3.896606915299077e-08 -3.5454016955124184e-08 -3.3725809498263606e-08 -3.2702067033566654e-08 -2.9917572998978706e-08 -1.8326691287620182e-08 -3.25930935641769e-08 -3.849352205722073e-08 -3.799163595046113e-08 -3.501121978086174e-08 -3.324151036167702e-08 -3.558419340724588e-08 -4.118194521268604e-08 -4.207419631160349e-08 -3.622077598182584e-08 -2.9575941994262868e-08 -2.0777115071024614e-08 -1.2422811146224645e-08 -1.1035823783561849e-08 -2.9043812873373986e-08 -6.300753956159486e-08 -6.216081734807855e-08 -4.660785423947313e-08 -4.077793799132855e-08 -3.9790520016428185e-08 -3.91308442707332e-08 -3.4584941209425355e-08 -2.9744744035082292e-08 -2.741471703346971e-08 -1.9574708713074777e-08 -3.0307116170100454e-08 -3.5142628964537626e-08 -2.880088257509638e-08 -2.827869748874458e-08 -2.8987189403985195e-08 -3.233701412932134e-08 -3.624477315608059e-08 -3.479623139781228e-08 -3.3419434615997394e-08 -2.912698116222952e-08 -2.200992880731095e-08 -1.3124481946865455e-08 -8.851341287446441e-09 -2.3984846939215295e-08 -4.359251067583856e-08 -3.867826742614091e-08 -3.842679018908764e-08 -4.2116684459171e-08 -4.672430628029158e-08 -4.312629160204665e-08 -4.1689666248802095e-08 -3.897305463179781e-08 -4.015754529116019e-08 -1.8233907692642028e-08 -2.3026521428993645e-08 -2.6492551648837415e-08 -2.678265447458842e-08 -2.445764058129618e-08 -2.541185698633722e-08 -2.777771538512472e-08 -3.302487833655531e-08 -3.4852608320890235e-08 -3.284407770860851e-08 -2.835192174306303e-08 -2.198050761421779e-08 -1.4157346625063356e-08 -9.793476923256496e-09 -2.4993139168433152e-08 -4.2960365934853663e-08 -4.1869151963091106e-08 -3.486592182167541e-08 -3.5335428179611804e-08 -5.16356731563628e-08 -4.9843034930270275e-08 -4.0811961382223994e-08 -3.4305028964522264e-08 -3.679087323458354e-08 -1.95202219783799e-08 -2.1026537755487583e-08 -2.5067678336409405e-08 -2.664245180582603e-08 -2.6832621193584623e-08 -2.8068229121393778e-08 -2.8718947017795038e-08 -3.130661491423181e-08 -3.1025634301981756e-08 -2.6760218760302295e-08 -2.2533757535735002e-08 -1.590396287313306e-08 -1.003427048684019e-08 -7.899179434995702e-09 -2.749040675089653e-08 -5.447744811716844e-08 -5.961300777189369e-08 -4.3419024255113235e-08 -3.5198841523408355e-08 -3.470147543234743e-08 -3.3943098980214214e-08 -2.8277218210879558e-08 -3.1402685793354447e-08 -3.0633461303544426e-08 -2.518339073829535e-08 -3.277340109950203e-08 -3.462734717488924e-08 -3.1824690895403e-08 -2.9802928964439717e-08 -3.016543422347305e-08 -3.286199340719596e-08 -3.3241756907987856e-08 -3.077662252803685e-08 -2.7904358006791088e-08 -2.149267464717588e-08 -1.368586789664027e-08 -8.776966483677418e-09 -4.652082339174782e-09 -1.0778347252944883e-08 -2.754859168025395e-08 -3.360730290485484e-08 -2.4996837363095704e-08 -2.3507533281435744e-08 -2.1651614835561842e-08 -2.2543783752375682e-08 -2.707177111509607e-08 -2.8545049686551657e-08 -2.5517214443168037e-08 -1.8812387519968176e-08 -2.989439764576008e-08 -3.5918838933154685e-08 -3.512635690802241e-08 -3.037606695503107e-08 -3.149851012616625e-08 -3.200779262225094e-08 -3.583041098966797e-08 -3.592787896455202e-08 -3.1921337049250926e-08 -2.62536482736368e-08 -1.7754210753857724e-08 -1.064258241777756e-08 -4.956813579368753e-09 -7.80754638946812e-09 -2.0863488461921013e-08 -2.776530588747928e-08 -2.302109741015524e-08 -1.7811902590593474e-08 -2.0391270094565416e-08 -2.1212680220169175e-08 -2.321677299885584e-08 -1.9893246546675594e-08 -2.208356397214746e-08 -2.045175612282398e-08 -3.1151866013130066e-08 -3.265440141347159e-08 -3.1238650314544534e-08 -3.1020045918936125e-08 -3.279509717485565e-08 -3.4818420565787565e-08 -3.764186891748769e-08 -3.8660269545449844e-08 -3.247360078552479e-08 -2.6405520801112116e-08 -1.7881839560767442e-08 -1.2692614992383436e-08 -9.334572056686072e-09 -3.1299054160699486e-08 -6.184071805450911e-08 -6.447087409851337e-08 -4.740165117826318e-08 -3.967497197874946e-08 -3.6338871664716544e-08 -3.470336562073051e-08 -3.193843092680226e-08 -3.170856758299899e-08 -3.049087535377729e-08 -2.0404665777454202e-08 -3.2011079906395435e-08 -3.8759956437131427e-08 -3.684420941982785e-08 -3.305643626434238e-08 -3.589180102106627e-08 -3.899277833666473e-08 -4.220461931003602e-08 -3.842761201012376e-08 -3.357829262227974e-08 -2.642672378384405e-08 -1.8165203454022246e-08 -1.00249017270284e-08 -7.960651648497613e-09 -2.8764968995817857e-08 -5.8181642073280324e-08 -6.1087190346489e-08 -4.9989729985218024e-08 -3.9044635244044025e-08 -3.743690675107891e-08 -3.478735573062216e-08 -3.3345799451160875e-08 -3.0937863815323946e-08 -3.321134952965135e-08 -1.976808320287424e-08 -2.9047921978554603e-08 -3.5641803061878016e-08 -3.147163657828507e-08 -2.970620062848818e-08 -2.8443965699108674e-08 -3.0340482104167e-08 -3.5163996311476794e-08 -3.649296310898938e-08 -3.381875745744898e-08 -2.7574479042891793e-08 -2.138115353257415e-08 -1.3254000942158252e-08 -9.026717896554839e-09 -2.256465800669318e-08 -4.149481248113761e-08 -4.511181122531696e-08 -4.321825337598868e-08 -4.025772527546344e-08 -4.1859865385382924e-08 -4.3938990424667516e-08 -3.6279207457494095e-08 -3.821582872911516e-08 -3.558690541666508e-08 -2.105184984340014e-08 -2.14550352437215e-08 -2.6497236028743313e-08 -2.2507952355200772e-08 -2.2270199529450733e-08 -2.3945481711585058e-08 -2.5414568995756422e-08 -2.8336964600205607e-08 -2.9547589168516668e-08 -2.772002354838896e-08 -2.3770433830891116e-08 -1.9401633202867524e-08 -1.4144444034796244e-08 -1.0141764678364923e-08 -2.3902829199810338e-08 -4.3042301492155e-08 -4.448607668841381e-08 -3.9972224647514715e-08 -3.588497990646646e-08 -3.90492374418463e-08 -4.3183736892471566e-08 -3.6252580455923755e-08 -4.0767993956791476e-08 -3.125442927843807e-08 -1.762271938807823e-08 -2.1474183673863136e-08 -2.139750777119297e-08 -2.7219041444769103e-08 -2.5802057614287868e-08 -2.7132010597043803e-08 -2.939563445893774e-08 -3.1145373626944706e-08 -2.977548014183325e-08 -2.611656852481168e-08 -2.0954464050619697e-08 -1.4570969152543467e-08 -7.621568288993752e-09 -7.665453532322657e-09 -2.790263218261523e-08 -6.036349474208013e-08 -6.29207552601804e-08 -4.586484584071539e-08 -3.536690392529527e-08 -3.5631694663133716e-08 -3.438096522825992e-08 -3.118876577765194e-08 -3.058711059710715e-08 -3.2256311303574184e-08 -1.8959904395952044e-08 -3.499897464742353e-08 -3.9876400314702916e-08 -3.563851577773353e-08 -3.283742095821592e-08 -3.167832456886971e-08 -3.44287130304586e-08 -3.6081312951995964e-08 -3.601318398810147e-08 -3.13382550241225e-08 -2.6463870094676766e-08 -1.6192586421019042e-08 -9.763809183852497e-09 -5.225959968698648e-09 -1.0060979670514148e-08 -2.505231028303393e-08 -3.088321271642185e-08 -2.7989745212444144e-08 -1.9780410518416067e-08 -2.9301289403990956e-08 -2.3878256750830293e-08 -1.848785039280367e-08 -2.135978618563498e-08 -3.359333194724077e-08 -1.8518504317451014e-08 -2.9403359576677293e-08 -3.540750188447968e-08 -3.6677461931598734e-08 -2.9658945918911174e-08 -3.3248002747862384e-08 -3.437036373689395e-08 -3.8162574725974475e-08 -3.592787896455202e-08 -3.1921337049250926e-08 -2.62536482736368e-08 -1.7754210753857724e-08 -1.064258241777756e-08 -4.956813579368753e-09 -7.80754638946812e-09 -2.0863488461921013e-08 -2.776530588747928e-08 -2.302109741015524e-08 -1.7811902590593474e-08 -2.0391270094565416e-08 -2.1212680220169175e-08 -2.321677299885584e-08 -1.9893246546675594e-08 -2.208356397214746e-08 -2.045175612282398e-08 -3.1151866013130066e-08 -3.265440141347159e-08 -3.1238650314544534e-08 -3.1020045918936125e-08 -3.279509717485565e-08 -3.4818420565787565e-08 -3.764186891748769e-08 -3.8660269545449844e-08 -3.247360078552479e-08 -2.6405520801112116e-08 -1.7881839560767442e-08 -1.2692614992383436e-08 -9.334572056686072e-09 -3.1299054160699486e-08 -6.184071805450911e-08 -6.447087409851337e-08 -4.740165117826318e-08 -3.967497197874946e-08 -3.6338871664716544e-08 -3.470336562073051e-08 -3.193843092680226e-08 -3.170856758299899e-08 -3.049087535377729e-08 -2.0404665777454202e-08 -3.2011079906395435e-08 -3.8759956437131427e-08 -3.684420941982785e-08 -3.305643626434238e-08 -3.589180102106627e-08 -3.899277833666473e-08 -4.220461931003602e-08 -3.842761201012376e-08 -3.357829262227974e-08 -2.642672378384405e-08 -1.8165203454022246e-08 -1.00249017270284e-08 -7.960651648497613e-09 -2.8764968995817857e-08 -5.8181642073280324e-08 -6.1087190346489e-08 -4.9989729985218024e-08 -3.9044635244044025e-08 -3.743690675107891e-08 -3.478735573062216e-08 -3.3345799451160875e-08 -3.0937863815323946e-08 -3.321134952965135e-08 -1.976808320287424e-08 -2.9047921978554603e-08 -3.5641803061878016e-08 -3.147163657828507e-08 -2.970620062848818e-08 -2.8443965699108674e-08 -3.0340482104167e-08 -3.5163996311476794e-08 -3.649296310898938e-08 -3.381875745744898e-08 -2.7574479042891793e-08 -2.138115353257415e-08 -1.3254000942158252e-08 -9.026717896554839e-09 -2.256465800669318e-08 -4.149481248113761e-08 -4.511181122531696e-08 -4.321825337598868e-08 -4.025772527546344e-08 -4.1859865385382924e-08 -4.3938990424667516e-08 -3.6279207457494095e-08 -3.821582872911516e-08 -3.558690541666508e-08 -2.105184984340014e-08 -2.14550352437215e-08 -2.6497236028743313e-08 -2.2507952355200772e-08 -2.2270199529450733e-08 -2.3945481711585058e-08 -2.5414568995756422e-08 -2.8336964600205607e-08 -2.9547589168516668e-08 -2.772002354838896e-08 -2.3770433830891116e-08 -1.9401633202867524e-08 -1.4144444034796244e-08 -1.0141764678364923e-08 -2.3902829199810338e-08 -4.3042301492155e-08 -4.448607668841381e-08 -3.9972224647514715e-08 -3.588497990646646e-08 -3.90492374418463e-08 -4.3183736892471566e-08 -3.6252580455923755e-08 -4.0767993956791476e-08 -3.125442927843807e-08 -1.762271938807823e-08 -2.1474183673863136e-08 -2.139750777119297e-08 -2.7219041444769103e-08 -2.5802057614287868e-08 -2.7132010597043803e-08 -2.939563445893774e-08 -3.1145373626944706e-08 -2.977548014183325e-08 -2.611656852481168e-08 -2.0954464050619697e-08 -1.4570969152543467e-08 -7.621568288993752e-09 -7.665453532322657e-09 -2.790263218261523e-08 -6.036349474208013e-08 -6.29207552601804e-08 -4.586484584071539e-08 -3.536690392529527e-08 -3.5631694663133716e-08 -3.438096522825992e-08 -3.118876577765194e-08 -3.058711059710715e-08 -3.2256311303574184e-08 -1.8959904395952044e-08 -3.499897464742353e-08 -3.9876400314702916e-08 -3.563851577773353e-08 -3.283742095821592e-08 -3.167832456886971e-08 -3.44287130304586e-08 -3.6081312951995964e-08 -3.601318398810147e-08 -3.13382550241225e-08 -2.6463870094676766e-08 -1.6192586421019042e-08 -9.763809183852497e-09 -5.225959968698648e-09 -1.0060979670514148e-08 -2.505231028303393e-08 -3.088321271642185e-08 -2.7989745212444144e-08 -1.9780410518416067e-08 -2.9301289403990956e-08 -2.3878256750830293e-08 -1.848785039280367e-08 -2.135978618563498e-08 -3.359333194724077e-08 -1.8518504317451014e-08 -2.9403359576677293e-08 -3.540750188447968e-08 -3.6677461931598734e-08 -2.9658945918911174e-08 -3.3248002747862384e-08 -3.437036373689395e-08 -3.8162574725974475e-08 -3.592787896455202e-08 -3.1921337049250926e-08 -2.62536482736368e-08 -1.7754210753857724e-08 -1.064258241777756e-08 -4.956813579368753e-09 -7.80754638946812e-09 -2.0863488461921013e-08 -2.776530588747928e-08 -2.302109741015524e-08 -1.7811902590593474e-08 -2.0391270094565416e-08 -2.1212680220169175e-08 -2.321677299885584e-08 -1.9893246546675594e-08 -2.208356397214746e-08 -2.045175612282398e-08 -3.1151866013130066e-08 -3.265440141347159e-08 -3.1238650314544534e-08 -3.1020045918936125e-08 -3.279509717485565e-08 -3.4818420565787565e-08 -3.764186891748769e-08 -3.8660269545449844e-08 -3.247360078552479e-08 -2.6405520801112116e-08 -1.7881839560767442e-08 -1.2692614992383436e-08 -9.334572056686072e-09 -3.1299054160699486e-08 -6.184071805450911e-08 -6.447087409851337e-08 -4.740165117826318e-08 -3.967497197874946e-08 -3.6338871664716544e-08 -3.470336562073051e-08 -3.193843092680226e-08 -3.170856758299899e-08 -3.049087535377729e-08 -2.0404665777454202e-08 -3.2011079906395435e-08 -3.8759956437131427e-08 -3.684420941982785e-08 -3.305643626434238e-08 -3.589180102106627e-08 -3.899277833666473e-08 -4.220461931003602e-08 -3.842761201012376e-08 -3.357829262227974e-08 -2.642672378384405e-08 -1.8165203454022246e-08 -1.00249017270284e-08 -7.960651648497613e-09 -2.8764968995817857e-08 -5.8181642073280324e-08 -6.1087190346489e-08 -4.9989729985218024e-08 -3.9044635244044025e-08 -3.743690675107891e-08 -3.478735573062216e-08 -3.3345799451160875e-08 -3.0937863815323946e-08 -3.321134952965135e-08 -1.976808320287424e-08 -2.9047921978554603e-08 -3.5641803061878016e-08 -3.147163657828507e-08 -2.970620062848818e-08 -2.8443965699108674e-08 -3.0340482104167e-08 -3.5163996311476794e-08 -3.649296310898938e-08 -3.381875745744898e-08 -2.7574479042891793e-08 -2.138115353257415e-08 -1.3254000942158252e-08 -9.026717896554839e-09 -2.256465800669318e-08 -4.149481248113761e-08 -4.511181122531696e-08 -4.321825337598868e-08 -4.025772527546344e-08 -4.1859865385382924e-08 -4.3938990424667516e-08 -3.6279207457494095e-08 -3.821582872911516e-08 -3.558690541666508e-08 -2.105184984340014e-08 -2.14550352437215e-08 -2.6497236028743313e-08 -2.2507952355200772e-08 -2.2270199529450733e-08 -2.3945481711585058e-08 -2.5414568995756422e-08 -2.8336964600205607e-08 -2.9547589168516668e-08 -2.772002354838896e-08 -2.3770433830891116e-08 -1.9401633202867524e-08 -1.4144444034796244e-08 -1.0141764678364923e-08 -2.3902829199810338e-08 -4.3042301492155e-08 -4.448607668841381e-08 -3.9972224647514715e-08 -3.588497990646646e-08 -3.90492374418463e-08 -4.3183736892471566e-08 -3.6252580455923755e-08 -4.0767993956791476e-08 -3.125442927843807e-08 -1.762271938807823e-08 -2.1474183673863136e-08 -2.139750777119297e-08 -2.7219041444769103e-08 -2.5802057614287868e-08 -2.7132010597043803e-08 -2.939563445893774e-08 -3.1145373626944706e-08 -2.977548014183325e-08 -2.611656852481168e-08 -2.0954464050619697e-08 -1.4570969152543467e-08 -7.621568288993752e-09 -7.665453532322657e-09 -2.790263218261523e-08 -6.036349474208013e-08 -6.29207552601804e-08 -4.586484584071539e-08 -3.536690392529527e-08 -3.5631694663133716e-08 -3.438096522825992e-08 -3.118876577765194e-08 -3.058711059710715e-08 -3.2256311303574184e-08 -1.8959904395952044e-08 -3.499897464742353e-08 -3.9876400314702916e-08 -3.563851577773353e-08 -3.283742095821592e-08 -3.167832456886971e-08 -3.44287130304586e-08 -3.6081312951995964e-08 -3.601318398810147e-08 -3.13382550241225e-08 -2.6463870094676766e-08 -1.6192586421019042e-08 -9.763809183852497e-09 -5.225959968698648e-09 -1.0060979670514148e-08 -2.505231028303393e-08 -3.088321271642185e-08 -2.7989745212444144e-08 -1.9780410518416067e-08 -2.9301289403990956e-08 -2.3878256750830293e-08 -1.848785039280367e-08 -2.135978618563498e-08 -3.359333194724077e-08 -1.8518504317451014e-08 -2.9403359576677293e-08 -3.540750188447968e-08 -3.6677461931598734e-08 -2.9658945918911174e-08 -3.3248002747862384e-08 -3.437036373689395e-08 -3.8162574725974475e-08 -3.592787896455202e-08 -3.1921337049250926e-08 -2.62536482736368e-08 -1.7754210753857724e-08 -1.064258241777756e-08 -4.956813579368753e-09 -7.80754638946812e-09 -2.0863488461921013e-08 -2.776530588747928e-08 -2.302109741015524e-08 -1.7811902590593474e-08 -2.0391270094565416e-08 -2.1212680220169175e-08 -2.321677299885584e-08 -1.9893246546675594e-08 -2.208356397214746e-08 -2.045175612282398e-08 -3.1151866013130066e-08 -3.265440141347159e-08 -3.1238650314544534e-08 -3.1020045918936125e-08 -3.279509717485565e-08 -3.4818420565787565e-08 -3.764186891748769e-08 -3.8660269545449844e-08 -3.247360078552479e-08 -2.6405520801112116e-08 -1.7881839560767442e-08 -1.2692614992383436e-08 -9.334572056686072e-09 -3.1299054160699486e-08 -6.184071805450911e-08 -6.447087409851337e-08 -4.740165117826318e-08 -3.967497197874946e-08 -3.6338871664716544e-08 -3.470336562073051e-08 -3.193843092680226e-08 -3.170856758299899e-08 -3.049087535377729e-08 -2.0404665777454202e-08 -3.2011079906395435e-08 -3.8759956437131427e-08 -3.684420941982785e-08 -3.305643626434238e-08 -3.589180102106627e-08 -3.899277833666473e-08 -4.220461931003602e-08 -3.842761201012376e-08 -3.357829262227974e-08 -2.642672378384405e-08 -1.8165203454022246e-08 -1.00249017270284e-08 -7.960651648497613e-09 -2.8764968995817857e-08 -5.8181642073280324e-08 -6.1087190346489e-08 -4.9989729985218024e-08 -3.9044635244044025e-08 -3.743690675107891e-08 -3.478735573062216e-08 -3.3345799451160875e-08 -3.0937863815323946e-08 -3.321134952965135e-08 -1.976808320287424e-08 -2.9047921978554603e-08 -3.5641803061878016e-08 -3.147163657828507e-08 -2.970620062848818e-08 -2.8443965699108674e-08 -3.0340482104167e-08 -3.5163996311476794e-08 -3.649296310898938e-08 -3.381875745744898e-08 -2.7574479042891793e-08 -2.138115353257415e-08 -1.3254000942158252e-08 -9.026717896554839e-09 -2.256465800669318e-08 -4.149481248113761e-08 -4.511181122531696e-08 -4.321825337598868e-08 -4.025772527546344e-08 -4.1859865385382924e-08 -4.3938990424667516e-08 -3.6279207457494095e-08 -3.821582872911516e-08 -3.558690541666508e-08 -2.105184984340014e-08 -2.14550352437215e-08 -2.6497236028743313e-08 -2.2507952355200772e-08 -2.2270199529450733e-08 -2.3945481711585058e-08 -2.5414568995756422e-08 -2.8336964600205607e-08 -2.9547589168516668e-08 -2.772002354838896e-08 -2.3770433830891116e-08 -1.9401633202867524e-08 -1.4144444034796244e-08 -1.0141764678364923e-08 -2.3902829199810338e-08 -4.3042301492155e-08 -4.448607668841381e-08 -3.9972224647514715e-08 -3.588497990646646e-08 -3.90492374418463e-08 -4.3183736892471566e-08 -3.6252580455923755e-08 -4.0767993956791476e-08 -3.125442927843807e-08 -1.762271938807823e-08 -2.1474183673863136e-08 -2.139750777119297e-08 -2.7219041444769103e-08 -2.5802057614287868e-08 -2.7132010597043803e-08 -2.939563445893774e-08 -3.1145373626944706e-08 -2.977548014183325e-08 -2.611656852481168e-08 -2.0954464050619697e-08 -1.4570969152543467e-08 -7.621568288993752e-09 -7.665453532322657e-09 -2.790263218261523e-08 -6.036349474208013e-08 -6.29207552601804e-08 -4.586484584071539e-08 -3.536690392529527e-08 -3.5631694663133716e-08 -3.438096522825992e-08 -3.118876577765194e-08 -3.058711059710715e-08 -3.2256311303574184e-08 -1.8959904395952044e-08 -3.499897464742353e-08 -3.9876400314702916e-08 -3.563851577773353e-08 -3.283742095821592e-08 -3.167832456886971e-08 -3.44287130304586e-08 -3.6081312951995964e-08 -3.601318398810147e-08 -3.13382550241225e-08 -2.6463870094676766e-08 -1.6192586421019042e-08 -9.763809183852497e-09 -5.225959968698648e-09 -1.0060979670514148e-08 -2.505231028303393e-08 -3.088321271642185e-08 -2.7989745212444144e-08 -1.9780410518416067e-08 -2.9301289403990956e-08 -2.3878256750830293e-08 -1.848785039280367e-08 -2.135978618563498e-08 -3.359333194724077e-08 -1.8518504317451014e-08 -2.9403359576677293e-08 -3.540750188447968e-08 -3.6677461931598734e-08 -2.9658945918911174e-08 -3.3248002747862384e-08 -3.437036373689395e-08 -3.8162574725974475e-08 -3.592787896455202e-08 -3.1921337049250926e-08 -2.62536482736368e-08 -1.7754210753857724e-08 -1.064258241777756e-08 -4.956813579368753e-09 -7.80754638946812e-09 -2.0863488461921013e-08 -2.776530588747928e-08 -2.302109741015524e-08 -1.7811902590593474e-08 -2.0391270094565416e-08 -2.1212680220169175e-08 -2.321677299885584e-08 -1.9893246546675594e-08 -2.208356397214746e-08 -2.045175612282398e-08 -3.1151866013130066e-08 -3.265440141347159e-08 -3.1238650314544534e-08 -3.1020045918936125e-08 -3.279509717485565e-08 -3.4818420565787565e-08 -3.764186891748769e-08 -3.8660269545449844e-08 -3.247360078552479e-08 -2.6405520801112116e-08 -1.7881839560767442e-08 -1.2692614992383436e-08 -9.334572056686072e-09 -3.1299054160699486e-08 -6.184071805450911e-08 -6.447087409851337e-08 -4.740165117826318e-08 -3.967497197874946e-08 -3.6338871664716544e-08 -3.470336562073051e-08 -3.193843092680226e-08 -3.170856758299899e-08 -3.049087535377729e-08 -2.0404665777454202e-08 -3.2011079906395435e-08 -3.8759956437131427e-08 -3.684420941982785e-08 -3.305643626434238e-08 -3.589180102106627e-08 -3.899277833666473e-08 -4.220461931003602e-08 -3.842761201012376e-08 -3.357829262227974e-08 -2.642672378384405e-08 -1.8165203454022246e-08 -1.00249017270284e-08 -7.960651648497613e-09 -2.8764968995817857e-08 -5.8181642073280324e-08 -6.1087190346489e-08 -4.9989729985218024e-08 -3.9044635244044025e-08 -3.743690675107891e-08 -3.478735573062216e-08 -3.3345799451160875e-08 -3.0937863815323946e-08 -3.321134952965135e-08 -1.976808320287424e-08 -2.9047921978554603e-08 -3.5641803061878016e-08 -3.147163657828507e-08 -2.970620062848818e-08 -2.8443965699108674e-08 -3.0340482104167e-08 -3.5163996311476794e-08 -3.612330800694179e-08 -3.4467338619156324e-08 -2.9416919623773295e-08 -2.2499323234321496e-08 -1.4318670094454071e-08 -9.94658218228599e-09 -2.3527832261027953e-08 -4.376328508714467e-08 -4.579811397258229e-08 -4.232608445917484e-08 -4.453481067585584e-08 -4.736812087998942e-08 -4.4987140974137285e-08 -4.2853447018054216e-08 -3.919749395676268e-08 -3.8835810518765464e-08 -2.0696740973691898e-08 -2.3027589796340604e-08 -2.7608502433787234e-08 -2.865320133490529e-08 -2.6301971350560765e-08 -2.5822027865465625e-08 -2.8441171507585858e-08 -3.5269600314618446e-08 -3.455856075416585e-08 -3.133209136635158e-08 -2.8434843485607723e-08 -2.23279735482901e-08 -1.5353014050516992e-08 -1.1161891130502936e-08 -2.436099442744825e-08 -4.0447565934807586e-08 -3.944001334452223e-08 -3.758047888608939e-08 -3.567796318746738e-08 -3.939185463180549e-08 -4.462233461620281e-08 -4.5538582889375027e-08 -3.933958681390814e-08 -3.418282417645095e-08 -1.9785341444632794e-08 -2.3909650314410148e-08 -2.473426554205478e-08 -2.6015977629990372e-08 -2.853140745735204e-08 -3.056146978078015e-08 -3.016272221405385e-08 -3.204674693936312e-08 -3.115466020465288e-08 -2.828864152328165e-08 -2.273608987482819e-08 -1.6163987048962003e-08 -9.735291993899071e-09 -8.643091836893173e-09 -2.7197591915726322e-08 -6.037836970283394e-08 -5.983350235588518e-08 -5.1105269859649784e-08 -3.947469419224657e-08 -3.910849073855069e-08 -3.615675612311195e-08 -2.8920457535852108e-08 -2.8902459655161036e-08 -3.397473909010491e-08 -2.0652773548259383e-08 -3.9975840660073653e-08 -4.0214333124756196e-08 -3.6379305259693736e-08 -3.4871838933135485e-08 -3.417057904301274e-08 -3.4361981162325504e-08 -3.526746357992453e-08 -3.337801483577685e-08 -2.946598233962977e-08 -2.285443210402973e-08 -1.3759831789891232e-08 -8.005769623380702e-09 -4.879151491455241e-09 -1.0444605730175814e-08 -2.5636460675509318e-08 -2.989554819521064e-08 -2.689606577757323e-08 -2.1271769152666333e-08 -2.6195463344279376e-08 -2.4656521272037657e-08 -2.100697841482788e-08 -2.1080613579664398e-08 -2.6036276609582578e-08 -2.3348264364635335e-08 -3.256063163325009e-08 -4.270256067582224e-08 -3.757530141356182e-08 -3.207592158614544e-08 -3.239832197861603e-08 -3.3759175432330153e-08 -3.740025353286787e-08 -3.501664379970015e-08 -3.080875573054921e-08 -2.447226899573915e-08 -1.632851562039359e-08 -8.709823705026265e-09 -4.852360125677669e-09 -8.352742464831335e-09 -2.233265792819599e-08 -3.1356745997435236e-08 -2.4692845761834243e-08 -1.9338928257811427e-08 -1.9024417347287607e-08 -2.5126602904699337e-08 -2.7550810597051484e-08 -1.8833015227974834e-08 -3.07749788859646e-08 -2.104798728453036e-08 -3.483510353282084e-08 -3.823497715925681e-08 -3.332854120940232e-08 -3.1857892465262325e-08 -3.277635965523207e-08 -3.504696899593304e-08 -3.9732745997588816e-08 -3.6231130926880973e-08 -3.2384022292587515e-08 -2.51114813976347e-08 -1.6464444819768138e-08 -8.994255965628027e-09 -7.1767165621410114e-09 -2.8577675981685694e-08 -5.841545015805698e-08 -6.039275157096608e-08 -4.688168500870891e-08 -3.948644623306311e-08 -3.967554725347474e-08 -3.497004654695204e-08 -3.2341205416605566e-08 -2.96193341449701e-08 -3.1787133674052234e-08 -2.3771091287720007e-08 -3.2843748980194056e-08 -3.870777080133769e-08 -3.830688649991746e-08 -3.751424011057797e-08 -3.7333521664734786e-08 -3.92022605187722e-08 -4.072682072288178e-08 -3.9743840581576465e-08 -3.553767833660138e-08 -2.6895819231262385e-08 -1.764564819498603e-08 -1.0751227158752863e-08 -7.09946538474556e-09 -2.7265145604895536e-08 -5.8462458321323144e-08 -5.9155910911602734e-08 -4.8799240032291956e-08 -4.3469894977249186e-08 -4.311495047174816e-08 -3.511098885464693e-08 -2.9433766955013795e-08 -3.120002472584681e-08 -3.4093656594031734e-08 -2.3460936028687633e-08 -3.1229445918939964e-08 -3.234786216699815e-08 -3.4140500393090674e-08 -3.2494885950360346e-08 -3.0468932732112835e-08 -3.243875557359323e-08 -3.499108516547676e-08 -3.612330800694179e-08 -3.4467338619156324e-08 -2.9416919623773295e-08 -2.2499323234321496e-08 -1.4318670094454071e-08 -9.94658218228599e-09 -2.3527832261027953e-08 -4.376328508714467e-08 -4.579811397258229e-08 -4.232608445917484e-08 -4.453481067585584e-08 -4.736812087998942e-08 -4.4987140974137285e-08 -4.2853447018054216e-08 -3.919749395676268e-08 -3.8835810518765464e-08 -2.0696740973691898e-08 -2.3027589796340604e-08 -2.7608502433787234e-08 -2.865320133490529e-08 -2.6301971350560765e-08 -2.5822027865465625e-08 -2.8441171507585858e-08 -3.5269600314618446e-08 -3.455856075416585e-08 -3.133209136635158e-08 -2.8434843485607723e-08 -2.23279735482901e-08 -1.5353014050516992e-08 -1.1161891130502936e-08 -2.436099442744825e-08 -4.0447565934807586e-08 -3.944001334452223e-08 -3.758047888608939e-08 -3.567796318746738e-08 -3.939185463180549e-08 -4.462233461620281e-08 -4.5538582889375027e-08 -3.933958681390814e-08 -3.418282417645095e-08 -1.9785341444632794e-08 -2.3909650314410148e-08 -2.473426554205478e-08 -2.6015977629990372e-08 -2.853140745735204e-08 -3.056146978078015e-08 -3.016272221405385e-08 -3.204674693936312e-08 -3.115466020465288e-08 -2.828864152328165e-08 -2.273608987482819e-08 -1.6163987048962003e-08 -9.735291993899071e-09 -8.643091836893173e-09 -2.7197591915726322e-08 -6.037836970283394e-08 -5.983350235588518e-08 -5.1105269859649784e-08 -3.947469419224657e-08 -3.910849073855069e-08 -3.615675612311195e-08 -2.8920457535852108e-08 -2.8902459655161036e-08 -3.397473909010491e-08 -2.0652773548259383e-08 -3.9975840660073653e-08 -4.0214333124756196e-08 -3.6379305259693736e-08 -3.4871838933135485e-08 -3.417057904301274e-08 -3.4361981162325504e-08 -3.526746357992453e-08 -3.337801483577685e-08 -2.946598233962977e-08 -2.285443210402973e-08 -1.3759831789891232e-08 -8.005769623380702e-09 -4.879151491455241e-09 -1.0444605730175814e-08 -2.5636460675509318e-08 -2.989554819521064e-08 -2.689606577757323e-08 -2.1271769152666333e-08 -2.6195463344279376e-08 -2.4656521272037657e-08 -2.100697841482788e-08 -2.1080613579664398e-08 -2.6036276609582578e-08 -2.3348264364635335e-08 -3.256063163325009e-08 -4.270256067582224e-08 -3.757530141356182e-08 -3.207592158614544e-08 -3.239832197861603e-08 -3.3759175432330153e-08 -3.740025353286787e-08 -3.501664379970015e-08 -3.080875573054921e-08 -2.447226899573915e-08 -1.632851562039359e-08 -8.709823705026265e-09 -4.852360125677669e-09 -8.352742464831335e-09 -2.233265792819599e-08 -3.1356745997435236e-08 -2.4692845761834243e-08 -1.9338928257811427e-08 -1.9024417347287607e-08 -2.5126602904699337e-08 -2.7550810597051484e-08 -1.8833015227974834e-08 -3.07749788859646e-08 -2.104798728453036e-08 -3.483510353282084e-08 -3.823497715925681e-08 -3.332854120940232e-08 -3.1857892465262325e-08 -3.277635965523207e-08 -3.504696899593304e-08 -3.9732745997588816e-08 -3.6231130926880973e-08 -3.2384022292587515e-08 -2.51114813976347e-08 -1.6464444819768138e-08 -8.994255965628027e-09 -7.1767165621410114e-09 -2.8577675981685694e-08 -5.841545015805698e-08 -6.039275157096608e-08 -4.688168500870891e-08 -3.948644623306311e-08 -3.967554725347474e-08 -3.497004654695204e-08 -3.2341205416605566e-08 -2.96193341449701e-08 -3.1787133674052234e-08 -2.3771091287720007e-08 -3.2843748980194056e-08 -3.870777080133769e-08 -3.830688649991746e-08 -3.751424011057797e-08 -3.7333521664734786e-08 -3.92022605187722e-08 -4.072682072288178e-08 -3.9743840581576465e-08 -3.553767833660138e-08 -2.6895819231262385e-08 -1.764564819498603e-08 -1.0751227158752863e-08 -7.09946538474556e-09 -2.7265145604895536e-08 -5.8462458321323144e-08 -5.9155910911602734e-08 -4.8799240032291956e-08 -4.3469894977249186e-08 -4.311495047174816e-08 -3.511098885464693e-08 -2.9433766955013795e-08 -3.120002472584681e-08 -3.4093656594031734e-08 -2.3460936028687633e-08 -3.1229445918939964e-08 -3.234786216699815e-08 -3.4140500393090674e-08 -3.2494885950360346e-08 -3.0468932732112835e-08 -3.243875557359323e-08 -3.499108516547676e-08 -3.612330800694179e-08 -3.4467338619156324e-08 -2.9416919623773295e-08 -2.2499323234321496e-08 -1.4318670094454071e-08 -9.94658218228599e-09 -2.3527832261027953e-08 -4.376328508714467e-08 -4.579811397258229e-08 -4.232608445917484e-08 -4.453481067585584e-08 -4.736812087998942e-08 -4.4987140974137285e-08 -4.2853447018054216e-08 -3.919749395676268e-08 -3.8835810518765464e-08 -2.0696740973691898e-08 -2.3027589796340604e-08 -2.7608502433787234e-08 -2.865320133490529e-08 -2.6301971350560765e-08 -2.5822027865465625e-08 -2.8441171507585858e-08 -3.5269600314618446e-08 -3.455856075416585e-08 -3.133209136635158e-08 -2.8434843485607723e-08 -2.23279735482901e-08 -1.5353014050516992e-08 -1.1161891130502936e-08 -2.436099442744825e-08 -4.0447565934807586e-08 -3.944001334452223e-08 -3.758047888608939e-08 -3.567796318746738e-08 -3.939185463180549e-08 -4.462233461620281e-08 -4.5538582889375027e-08 -3.933958681390814e-08 -3.418282417645095e-08 -1.9785341444632794e-08 -2.3909650314410148e-08 -2.473426554205478e-08 -2.6015977629990372e-08 -2.853140745735204e-08 -3.056146978078015e-08 -3.016272221405385e-08 -3.204674693936312e-08 -3.115466020465288e-08 -2.828864152328165e-08 -2.273608987482819e-08 -1.6163987048962003e-08 -9.735291993899071e-09 -8.643091836893173e-09 -2.7197591915726322e-08 -6.037836970283394e-08 -5.983350235588518e-08 -5.1105269859649784e-08 -3.947469419224657e-08 -3.910849073855069e-08 -3.615675612311195e-08 -2.8920457535852108e-08 -2.8902459655161036e-08 -3.397473909010491e-08 -2.0652773548259383e-08 -3.9975840660073653e-08 -4.0214333124756196e-08 -3.6379305259693736e-08 -3.4871838933135485e-08 -3.417057904301274e-08 -3.4361981162325504e-08 -3.526746357992453e-08 -3.337801483577685e-08 -2.946598233962977e-08 -2.285443210402973e-08 -1.3759831789891232e-08 -8.005769623380702e-09 -4.879151491455241e-09 -1.0444605730175814e-08 -2.5636460675509318e-08 -2.989554819521064e-08 -2.689606577757323e-08 -2.1271769152666333e-08 -2.6195463344279376e-08 -2.4656521272037657e-08 -2.100697841482788e-08 -2.1080613579664398e-08 -2.6036276609582578e-08 -2.3348264364635335e-08 -3.256063163325009e-08 -4.270256067582224e-08 -3.757530141356182e-08 -3.207592158614544e-08 -3.239832197861603e-08 -3.3759175432330153e-08 -3.740025353286787e-08 -3.501664379970015e-08 -3.080875573054921e-08 -2.447226899573915e-08 -1.632851562039359e-08 -8.709823705026265e-09 -4.852360125677669e-09 -8.352742464831335e-09 -2.233265792819599e-08 -3.1356745997435236e-08 -2.4692845761834243e-08 -1.9338928257811427e-08 -1.9024417347287607e-08 -2.5126602904699337e-08 -2.7550810597051484e-08 -1.8833015227974834e-08 -3.07749788859646e-08 -2.104798728453036e-08 -3.483510353282084e-08 -3.823497715925681e-08 -3.332854120940232e-08 -3.1857892465262325e-08 -3.277635965523207e-08 -3.504696899593304e-08 -3.9732745997588816e-08 -3.6231130926880973e-08 -3.2384022292587515e-08 -2.51114813976347e-08 -1.6464444819768138e-08 -8.994255965628027e-09 -7.1767165621410114e-09 -2.8577675981685694e-08 -5.841545015805698e-08 -6.039275157096608e-08 -4.688168500870891e-08 -3.948644623306311e-08 -3.967554725347474e-08 -3.497004654695204e-08 -3.2341205416605566e-08 -2.96193341449701e-08 -3.1787133674052234e-08 -2.3771091287720007e-08 -3.2843748980194056e-08 -3.870777080133769e-08 -3.830688649991746e-08 -3.751424011057797e-08 -3.7333521664734786e-08 -3.92022605187722e-08 -4.072682072288178e-08 -3.9743840581576465e-08 -3.553767833660138e-08 -2.6895819231262385e-08 -1.764564819498603e-08 -1.0751227158752863e-08 -7.09946538474556e-09 -2.7265145604895536e-08 -5.8462458321323144e-08 -5.9155910911602734e-08 -4.8799240032291956e-08 -4.3469894977249186e-08 -4.311495047174816e-08 -3.511098885464693e-08 -2.9433766955013795e-08 -3.120002472584681e-08 -3.4093656594031734e-08 -2.3460936028687633e-08 -3.1229445918939964e-08 -3.234786216699815e-08 -3.4140500393090674e-08 -3.2494885950360346e-08 -3.0468932732112835e-08 -3.243875557359323e-08 -3.499108516547676e-08 -3.612330800694179e-08 -3.4467338619156324e-08 -2.9416919623773295e-08 -2.2499323234321496e-08 -1.4318670094454071e-08 -9.94658218228599e-09 -2.3527832261027953e-08 -4.376328508714467e-08 -4.579811397258229e-08 -4.232608445917484e-08 -4.453481067585584e-08 -4.736812087998942e-08 -4.4987140974137285e-08 -4.2853447018054216e-08 -3.919749395676268e-08 -3.8835810518765464e-08 -2.0696740973691898e-08 -2.3027589796340604e-08 -2.7608502433787234e-08 -2.865320133490529e-08 -2.6301971350560765e-08 -2.5822027865465625e-08 -2.8441171507585858e-08 -3.5269600314618446e-08 -3.455856075416585e-08 -3.133209136635158e-08 -2.8434843485607723e-08 -2.23279735482901e-08 -1.5353014050516992e-08 -1.1161891130502936e-08 -2.436099442744825e-08 -4.0447565934807586e-08 -3.944001334452223e-08 -3.758047888608939e-08 -3.567796318746738e-08 -3.939185463180549e-08 -4.462233461620281e-08 -4.5538582889375027e-08 -3.933958681390814e-08 -3.418282417645095e-08 -1.9785341444632794e-08 -2.3909650314410148e-08 -2.473426554205478e-08 -2.6015977629990372e-08 -2.853140745735204e-08 -3.056146978078015e-08 -3.016272221405385e-08 -3.204674693936312e-08 -3.115466020465288e-08 -2.828864152328165e-08 -2.273608987482819e-08 -1.6163987048962003e-08 -9.735291993899071e-09 -8.643091836893173e-09 -2.7197591915726322e-08 -6.037836970283394e-08 -5.983350235588518e-08 -5.1105269859649784e-08 -3.947469419224657e-08 -3.910849073855069e-08 -3.615675612311195e-08 -2.8920457535852108e-08 -2.8902459655161036e-08 -3.397473909010491e-08 -2.0652773548259383e-08 -3.9975840660073653e-08 -4.0214333124756196e-08 -3.6379305259693736e-08 -3.4871838933135485e-08 -3.417057904301274e-08 -3.4361981162325504e-08 -3.526746357992453e-08 -3.337801483577685e-08 -2.946598233962977e-08 -2.285443210402973e-08 -1.3759831789891232e-08 -8.005769623380702e-09 -4.879151491455241e-09 -1.0444605730175814e-08 -2.5636460675509318e-08 -2.989554819521064e-08 -2.689606577757323e-08 -2.1271769152666333e-08 -2.6195463344279376e-08 -2.4656521272037657e-08 -2.100697841482788e-08 -2.1080613579664398e-08 -2.6036276609582578e-08 -2.3348264364635335e-08 -3.256063163325009e-08 -4.270256067582224e-08 -3.757530141356182e-08 -3.207592158614544e-08 -3.239832197861603e-08 -3.3759175432330153e-08 -3.740025353286787e-08 -3.501664379970015e-08 -3.080875573054921e-08 -2.447226899573915e-08 -1.632851562039359e-08 -8.709823705026265e-09 -4.852360125677669e-09 -8.352742464831335e-09 -2.233265792819599e-08 -3.1356745997435236e-08 -2.4692845761834243e-08 -1.9338928257811427e-08 -1.9024417347287607e-08 -2.5126602904699337e-08 -2.7550810597051484e-08 -1.8833015227974834e-08 -3.07749788859646e-08 -2.104798728453036e-08 -3.483510353282084e-08 -3.823497715925681e-08 -3.332854120940232e-08 -3.1857892465262325e-08 -3.277635965523207e-08 -3.504696899593304e-08 -3.9732745997588816e-08 -3.6231130926880973e-08 -3.2384022292587515e-08 -2.51114813976347e-08 -1.6464444819768138e-08 -8.994255965628027e-09 -7.1767165621410114e-09 -2.8577675981685694e-08 -5.841545015805698e-08 -6.039275157096608e-08 -4.688168500870891e-08 -3.948644623306311e-08 -3.967554725347474e-08 -3.497004654695204e-08 -3.2341205416605566e-08 -2.96193341449701e-08 -3.1787133674052234e-08 -2.3771091287720007e-08 -3.2843748980194056e-08 -3.870777080133769e-08 -3.830688649991746e-08 -3.751424011057797e-08 -3.7333521664734786e-08 -3.92022605187722e-08 -4.072682072288178e-08 -3.9743840581576465e-08 -3.553767833660138e-08 -2.6895819231262385e-08 -1.764564819498603e-08 -1.0751227158752863e-08 -7.09946538474556e-09 -2.7265145604895536e-08 -5.8462458321323144e-08 -5.9155910911602734e-08 -4.8799240032291956e-08 -4.3469894977249186e-08 -4.311495047174816e-08 -3.511098885464693e-08 -2.9433766955013795e-08 -3.120002472584681e-08 -3.4093656594031734e-08 -2.3460936028687633e-08 -3.1229445918939964e-08 -3.234786216699815e-08 -3.4140500393090674e-08 -3.2494885950360346e-08 -3.0468932732112835e-08 -3.243875557359323e-08 -3.499108516547676e-08 -3.612330800694179e-08 -3.4467338619156324e-08 -2.9416919623773295e-08 -2.2499323234321496e-08 -1.4318670094454071e-08 -9.94658218228599e-09 -2.3527832261027953e-08 -4.376328508714467e-08 -4.579811397258229e-08 -4.232608445917484e-08 -4.453481067585584e-08 -4.736812087998942e-08 -4.4987140974137285e-08 -4.2853447018054216e-08 -3.919749395676268e-08 -3.8835810518765464e-08 -2.0696740973691898e-08 -2.3027589796340604e-08 -2.7608502433787234e-08 -2.865320133490529e-08 -2.6301971350560765e-08 -2.5822027865465625e-08 -2.8441171507585858e-08 -3.5269600314618446e-08 -3.455856075416585e-08 -3.133209136635158e-08 -2.8434843485607723e-08 -2.23279735482901e-08 -1.5353014050516992e-08 -1.1161891130502936e-08 -2.436099442744825e-08 -4.0447565934807586e-08 -3.944001334452223e-08 -3.758047888608939e-08 -3.567796318746738e-08 -3.939185463180549e-08 -4.462233461620281e-08 -4.5538582889375027e-08 -3.933958681390814e-08 -3.418282417645095e-08 -1.9785341444632794e-08 -2.3909650314410148e-08 -2.473426554205478e-08 -2.6015977629990372e-08 -2.853140745735204e-08 -3.056146978078015e-08 -3.016272221405385e-08 -3.204674693936312e-08 -3.115466020465288e-08 -2.828864152328165e-08 -2.273608987482819e-08 -1.6163987048962003e-08 -9.735291993899071e-09 -8.643091836893173e-09 -2.7197591915726322e-08 -6.037836970283394e-08 -5.983350235588518e-08 -5.1105269859649784e-08 -3.947469419224657e-08 -3.910849073855069e-08 -3.615675612311195e-08 -2.8920457535852108e-08 -2.8902459655161036e-08 -3.397473909010491e-08 -2.0652773548259383e-08 -3.9975840660073653e-08 -4.0214333124756196e-08 -3.6379305259693736e-08 -3.4871838933135485e-08 -3.417057904301274e-08 -3.4361981162325504e-08 -3.526746357992453e-08 -3.6762602590940955e-08 -3.2406375824770026e-08 -2.4372417739850343e-08 -1.5509817504209033e-08 -8.899089089645121e-09 -4.870851098990411e-09 -9.132814992318166e-09 -2.6582951962810812e-08 -3.6057808870362884e-08 -2.541473335996365e-08 -1.9911737519988334e-08 -1.9959978414808685e-08 -2.0062623862220302e-08 -1.8068392935967095e-08 -2.4241912559314203e-08 -2.800042888591373e-08 -1.809691012592052e-08 -3.130595745740291e-08 -4.094024764596261e-08 -3.7405759733809885e-08 -3.804176703366456e-08 -3.798251373696018e-08 -3.9688778572156304e-08 -4.211019207298563e-08 -4.127908445915563e-08 -3.620631193159009e-08 -2.808507645263427e-08 -1.9396537912443567e-08 -9.255841601425602e-09 -5.257682260692952e-09 -8.6102189954483e-09 -2.3522819152707606e-08 -3.3572539875026884e-08 -2.5241657849756395e-08 -2.2216123705273918e-08 -1.6014169074076996e-08 -2.365011923120288e-08 -2.113978469426517e-08 -2.430363131912695e-08 -2.932479348562404e-08 -1.7952023077252245e-08 -3.081886412929351e-08 -3.611435015764806e-08 -3.521790777144638e-08 -3.874960149207628e-08 -4.0030163030561304e-08 -4.026709403527523e-08 -4.1884848744881024e-08 -4.103344215145882e-08 -3.495541813250907e-08 -2.718994898009039e-08 -1.74106895607588e-08 -9.411823234081524e-09 -6.4629649922692115e-09 -2.9738991287829438e-08 -6.051117598227122e-08 -6.611887182224845e-08 -5.1540588462483515e-08 -3.848275620164753e-08 -3.536871193157473e-08 -3.709839866630033e-08 -3.2967268681923163e-08 -2.9705789717970114e-08 -3.119624434908065e-08 -2.8357345761901436e-08 -3.4198356594033656e-08 -3.868862237119605e-08 -3.6691432889212805e-08 -3.860923445910668e-08 -3.992365502427992e-08 -4.267207111538212e-08 -4.821780164923577e-08 -4.5736723941184e-08 -4.043384152350435e-08 -3.3123003768268256e-08 -2.157403492975194e-08 -1.1112088775713955e-08 -7.86926514928087e-09 -2.779143979642795e-08 -6.055391067614956e-08 -6.799377433405678e-08 -5.01831866571211e-08 -3.866306373697265e-08 -3.597751695513378e-08 -3.337464536952875e-08 -3.593461789704822e-08 -3.120922912145137e-08 -3.1488730455836404e-08 -2.0408199607909525e-08 -3.0352809419708825e-08 -3.643444945121751e-08 -3.751045973381181e-08 -3.317905196293176e-08 -3.0882801805903786e-08 -3.2460698195257676e-08 -3.785184419221681e-08 -3.987188029900425e-08 -3.4573600079126874e-08 -2.862673869754217e-08 -2.1199777629902063e-08 -1.280076664073707e-08 -8.332196938928289e-09 -2.2422893877962164e-08 -4.313845455338125e-08 -4.745350808564248e-08 -5.043844427094053e-08 -4.3643874490596166e-08 -4.709059191609109e-08 -4.977128995381685e-08 -4.6937486657061584e-08 -4.273732370565019e-08 -3.818213406663417e-08 -2.0587438775887697e-08 -2.8032315542115258e-08 -2.6965016562503852e-08 -2.6630781947113104e-08 -2.8329403846673294e-08 -2.612585510251986e-08 -2.6425737598600712e-08 -3.101486844640856e-08 -3.478661609168965e-08 -3.302257723765417e-08 -2.649542802246384e-08 -1.9497128807264876e-08 -1.2884263658007046e-08 -8.822495369078566e-09 -2.270551813228446e-08 -4.252792370564636e-08 -4.227718610752559e-08 -3.931090525974749e-08 -3.560293092686945e-08 -4.339058924726343e-08 -4.8363510518940166e-08 -4.753486836821853e-08 -4.222278155493431e-08 -4.167643493012053e-08 -2.1108308948581704e-08 -2.553915706483249e-08 -3.176609505552752e-08 -2.9987263422841835e-08 -3.141361601313486e-08 -3.2029735243915394e-08 -3.2213740973903074e-08 -3.4751113422929186e-08 -3.22018245688793e-08 -2.7979718995803457e-08 -2.2222122998837608e-08 -1.4269771742804821e-08 -6.9400321037379265e-09 -6.6124542387397714e-09 -2.8228895133955598e-08 -5.6868618603868484e-08 -6.444621946742973e-08 -4.8724125589590415e-08 -3.778313995359703e-08 -4.04220894826878e-08 -4.029150212004805e-08 -3.208290706495248e-08 -3.240004780279189e-08 -3.251017182163221e-08 -2.4728677159009153e-08 -3.781971098970445e-08 -4.269089081710931e-08 -3.755861844652855e-08 -3.81458917589412e-08 -3.7685918525023815e-08 -3.9019076609820634e-08 -4.2581095526683435e-08 -3.6762602590940955e-08 -3.2406375824770026e-08 -2.4372417739850343e-08 -1.5509817504209033e-08 -8.899089089645121e-09 -4.870851098990411e-09 -9.132814992318166e-09 -2.6582951962810812e-08 -3.6057808870362884e-08 -2.541473335996365e-08 -1.9911737519988334e-08 -1.9959978414808685e-08 -2.0062623862220302e-08 -1.8068392935967095e-08 -2.4241912559314203e-08 -2.800042888591373e-08 -1.809691012592052e-08 -3.130595745740291e-08 -4.094024764596261e-08 -3.7405759733809885e-08 -3.804176703366456e-08 -3.798251373696018e-08 -3.9688778572156304e-08 -4.211019207298563e-08 -4.127908445915563e-08 -3.620631193159009e-08 -2.808507645263427e-08 -1.9396537912443567e-08 -9.255841601425602e-09 -5.257682260692952e-09 -8.6102189954483e-09 -2.3522819152707606e-08 -3.3572539875026884e-08 -2.5241657849756395e-08 -2.2216123705273918e-08 -1.6014169074076996e-08 -2.365011923120288e-08 -2.113978469426517e-08 -2.430363131912695e-08 -2.932479348562404e-08 -1.7952023077252245e-08 -3.081886412929351e-08 -3.611435015764806e-08 -3.521790777144638e-08 -3.874960149207628e-08 -4.0030163030561304e-08 -4.026709403527523e-08 -4.1884848744881024e-08 -4.103344215145882e-08 -3.495541813250907e-08 -2.718994898009039e-08 -1.74106895607588e-08 -9.411823234081524e-09 -6.4629649922692115e-09 -2.9738991287829438e-08 -6.051117598227122e-08 -6.611887182224845e-08 -5.1540588462483515e-08 -3.848275620164753e-08 -3.536871193157473e-08 -3.709839866630033e-08 -3.2967268681923163e-08 -2.9705789717970114e-08 -3.119624434908065e-08 -2.8357345761901436e-08 -3.4198356594033656e-08 -3.868862237119605e-08 -3.6691432889212805e-08 -3.860923445910668e-08 -3.992365502427992e-08 -4.267207111538212e-08 -4.821780164923577e-08 -4.5736723941184e-08 -4.043384152350435e-08 -3.3123003768268256e-08 -2.157403492975194e-08 -1.1112088775713955e-08 -7.86926514928087e-09 -2.779143979642795e-08 -6.055391067614956e-08 -6.799377433405678e-08 -5.01831866571211e-08 -3.866306373697265e-08 -3.597751695513378e-08 -3.337464536952875e-08 -3.593461789704822e-08 -3.120922912145137e-08 -3.1488730455836404e-08 -2.0408199607909525e-08 -3.0352809419708825e-08 -3.643444945121751e-08 -3.751045973381181e-08 -3.317905196293176e-08 -3.0882801805903786e-08 -3.2460698195257676e-08 -3.785184419221681e-08 -3.987188029900425e-08 -3.4573600079126874e-08 -2.862673869754217e-08 -2.1199777629902063e-08 -1.280076664073707e-08 -8.332196938928289e-09 -2.2422893877962164e-08 -4.313845455338125e-08 -4.745350808564248e-08 -5.043844427094053e-08 -4.3643874490596166e-08 -4.709059191609109e-08 -4.977128995381685e-08 -4.6937486657061584e-08 -4.273732370565019e-08 -3.818213406663417e-08 -2.0587438775887697e-08 -2.8032315542115258e-08 -2.6965016562503852e-08 -2.6630781947113104e-08 -2.8329403846673294e-08 -2.612585510251986e-08 -2.6425737598600712e-08 -3.101486844640856e-08 -3.478661609168965e-08 -3.302257723765417e-08 -2.649542802246384e-08 -1.9497128807264876e-08 -1.2884263658007046e-08 -8.822495369078566e-09 -2.270551813228446e-08 -4.252792370564636e-08 -4.227718610752559e-08 -3.931090525974749e-08 -3.560293092686945e-08 -4.339058924726343e-08 -4.8363510518940166e-08 -4.753486836821853e-08 -4.222278155493431e-08 -4.167643493012053e-08 -2.1108308948581704e-08 -2.553915706483249e-08 -3.176609505552752e-08 -2.9987263422841835e-08 -3.141361601313486e-08 -3.2029735243915394e-08 -3.2213740973903074e-08 -3.4751113422929186e-08 -3.22018245688793e-08 -2.7979718995803457e-08 -2.2222122998837608e-08 -1.4269771742804821e-08 -6.9400321037379265e-09 -6.6124542387397714e-09 -2.8228895133955598e-08 -5.6868618603868484e-08 -6.444621946742973e-08 -4.8724125589590415e-08 -3.778313995359703e-08 -4.04220894826878e-08 -4.029150212004805e-08 -3.208290706495248e-08 -3.240004780279189e-08 -3.251017182163221e-08 -2.4728677159009153e-08 -3.781971098970445e-08 -4.269089081710931e-08 -3.755861844652855e-08 -3.81458917589412e-08 -3.7685918525023815e-08 -3.9019076609820634e-08 -4.2581095526683435e-08 -3.6762602590940955e-08 -3.2406375824770026e-08 -2.4372417739850343e-08 -1.5509817504209033e-08 -8.899089089645121e-09 -4.870851098990411e-09 -9.132814992318166e-09 -2.6582951962810812e-08 -3.6057808870362884e-08 -2.541473335996365e-08 -1.9911737519988334e-08 -1.9959978414808685e-08 -2.0062623862220302e-08 -1.8068392935967095e-08 -2.4241912559314203e-08 -2.800042888591373e-08 -1.809691012592052e-08 -3.130595745740291e-08 -4.094024764596261e-08 -3.7405759733809885e-08 -3.804176703366456e-08 -3.798251373696018e-08 -3.9688778572156304e-08 -4.211019207298563e-08 -4.127908445915563e-08 -3.620631193159009e-08 -2.808507645263427e-08 -1.9396537912443567e-08 -9.255841601425602e-09 -5.257682260692952e-09 -8.6102189954483e-09 -2.3522819152707606e-08 -3.3572539875026884e-08 -2.5241657849756395e-08 -2.2216123705273918e-08 -1.6014169074076996e-08 -2.365011923120288e-08 -2.113978469426517e-08 -2.430363131912695e-08 -2.932479348562404e-08 -1.7952023077252245e-08 -3.081886412929351e-08 -3.611435015764806e-08 -3.521790777144638e-08 -3.874960149207628e-08 -4.0030163030561304e-08 -4.026709403527523e-08 -4.1884848744881024e-08 -4.103344215145882e-08 -3.495541813250907e-08 -2.718994898009039e-08 -1.74106895607588e-08 -9.411823234081524e-09 -6.4629649922692115e-09 -2.9738991287829438e-08 -6.051117598227122e-08 -6.611887182224845e-08 -5.1540588462483515e-08 -3.848275620164753e-08 -3.536871193157473e-08 -3.709839866630033e-08 -3.2967268681923163e-08 -2.9705789717970114e-08 -3.119624434908065e-08 -2.8357345761901436e-08 -3.4198356594033656e-08 -3.868862237119605e-08 -3.6691432889212805e-08 -3.860923445910668e-08 -3.992365502427992e-08 -4.267207111538212e-08 -4.821780164923577e-08 -4.5736723941184e-08 -4.043384152350435e-08 -3.3123003768268256e-08 -2.157403492975194e-08 -1.1112088775713955e-08 -7.86926514928087e-09 -2.779143979642795e-08 -6.055391067614956e-08 -6.799377433405678e-08 -5.01831866571211e-08 -3.866306373697265e-08 -3.597751695513378e-08 -3.337464536952875e-08 -3.593461789704822e-08 -3.120922912145137e-08 -3.1488730455836404e-08 -2.0408199607909525e-08 -3.0352809419708825e-08 -3.643444945121751e-08 -3.751045973381181e-08 -3.317905196293176e-08 -3.0882801805903786e-08 -3.2460698195257676e-08 -3.785184419221681e-08 -3.987188029900425e-08 -3.4573600079126874e-08 -2.862673869754217e-08 -2.1199777629902063e-08 -1.280076664073707e-08 -8.332196938928289e-09 -2.2422893877962164e-08 -4.313845455338125e-08 -4.745350808564248e-08 -5.043844427094053e-08 -4.3643874490596166e-08 -4.709059191609109e-08 -4.977128995381685e-08 -4.6937486657061584e-08 -4.273732370565019e-08 -3.818213406663417e-08 -2.0587438775887697e-08 -2.8032315542115258e-08 -2.6965016562503852e-08 -2.6630781947113104e-08 -2.8329403846673294e-08 -2.612585510251986e-08 -2.6425737598600712e-08 -3.101486844640856e-08 -3.478661609168965e-08 -3.302257723765417e-08 -2.649542802246384e-08 -1.9497128807264876e-08 -1.2884263658007046e-08 -8.822495369078566e-09 -2.270551813228446e-08 -4.252792370564636e-08 -4.227718610752559e-08 -3.931090525974749e-08 -3.560293092686945e-08 -4.339058924726343e-08 -4.8363510518940166e-08 -4.753486836821853e-08 -4.222278155493431e-08 -4.167643493012053e-08 -2.1108308948581704e-08 -2.553915706483249e-08 -3.176609505552752e-08 -2.9987263422841835e-08 -3.141361601313486e-08 -3.2029735243915394e-08 -3.2213740973903074e-08 -3.4751113422929186e-08 -3.22018245688793e-08 -2.7979718995803457e-08 -2.2222122998837608e-08 -1.4269771742804821e-08 -6.9400321037379265e-09 -6.6124542387397714e-09 -2.8228895133955598e-08 -5.6868618603868484e-08 -6.444621946742973e-08 -4.8724125589590415e-08 -3.778313995359703e-08 -4.04220894826878e-08 -4.029150212004805e-08 -3.208290706495248e-08 -3.240004780279189e-08 -3.251017182163221e-08 -2.4728677159009153e-08 -3.781971098970445e-08 -4.269089081710931e-08 -3.755861844652855e-08 -3.81458917589412e-08 -3.7685918525023815e-08 -3.9019076609820634e-08 -4.2581095526683435e-08 -3.6762602590940955e-08 -3.2406375824770026e-08 -2.4372417739850343e-08 -1.5509817504209033e-08 -8.899089089645121e-09 -4.870851098990411e-09 -9.132814992318166e-09 -2.6582951962810812e-08 -3.6057808870362884e-08 -2.541473335996365e-08 -1.9911737519988334e-08 -1.9959978414808685e-08 -2.0062623862220302e-08 -1.8068392935967095e-08 -2.4241912559314203e-08 -2.800042888591373e-08 -1.809691012592052e-08 -3.130595745740291e-08 -4.094024764596261e-08 -3.7405759733809885e-08 -3.804176703366456e-08 -3.798251373696018e-08 -3.9688778572156304e-08 -4.211019207298563e-08 -4.127908445915563e-08 -3.620631193159009e-08 -2.808507645263427e-08 -1.9396537912443567e-08 -9.255841601425602e-09 -5.257682260692952e-09 -8.6102189954483e-09 -2.3522819152707606e-08 -3.3572539875026884e-08 -2.5241657849756395e-08 -2.2216123705273918e-08 -1.6014169074076996e-08 -2.365011923120288e-08 -2.113978469426517e-08 -2.430363131912695e-08 -2.932479348562404e-08 -1.7952023077252245e-08 -3.081886412929351e-08 -3.611435015764806e-08 -3.521790777144638e-08 -3.874960149207628e-08 -4.0030163030561304e-08 -4.026709403527523e-08 -4.1884848744881024e-08 -4.103344215145882e-08 -3.495541813250907e-08 -2.718994898009039e-08 -1.74106895607588e-08 -9.411823234081524e-09 -6.4629649922692115e-09 -2.9738991287829438e-08 -6.051117598227122e-08 -6.611887182224845e-08 -5.1540588462483515e-08 -3.848275620164753e-08 -3.536871193157473e-08 -3.709839866630033e-08 -3.2967268681923163e-08 -2.9705789717970114e-08 -3.119624434908065e-08 -2.8357345761901436e-08 -3.4198356594033656e-08 -3.868862237119605e-08 -3.6691432889212805e-08 -3.860923445910668e-08 -3.992365502427992e-08 -4.267207111538212e-08 -4.821780164923577e-08 -4.5736723941184e-08 -4.043384152350435e-08 -3.3123003768268256e-08 -2.157403492975194e-08 -1.1112088775713955e-08 -7.86926514928087e-09 -2.779143979642795e-08 -6.055391067614956e-08 -6.799377433405678e-08 -5.01831866571211e-08 -3.866306373697265e-08 -3.597751695513378e-08 -3.337464536952875e-08 -3.593461789704822e-08 -3.120922912145137e-08 -3.1488730455836404e-08 -2.0408199607909525e-08 -3.0352809419708825e-08 -3.643444945121751e-08 -3.751045973381181e-08 -3.317905196293176e-08 -3.0882801805903786e-08 -3.2460698195257676e-08 -3.785184419221681e-08 -3.987188029900425e-08 -3.4573600079126874e-08 -2.862673869754217e-08 -2.1199777629902063e-08 -1.280076664073707e-08 -8.332196938928289e-09 -2.2422893877962164e-08 -4.313845455338125e-08 -4.745350808564248e-08 -5.043844427094053e-08 -4.3643874490596166e-08 -4.709059191609109e-08 -4.977128995381685e-08 -4.6937486657061584e-08 -4.273732370565019e-08 -3.818213406663417e-08 -2.0587438775887697e-08 -2.8032315542115258e-08 -2.6965016562503852e-08 -2.6630781947113104e-08 -2.8329403846673294e-08 -2.612585510251986e-08 -2.6425737598600712e-08 -3.101486844640856e-08 -3.478661609168965e-08 -3.302257723765417e-08 -2.649542802246384e-08 -1.9497128807264876e-08 -1.2884263658007046e-08 -8.822495369078566e-09 -2.270551813228446e-08 -4.252792370564636e-08 -4.227718610752559e-08 -3.931090525974749e-08 -3.560293092686945e-08 -4.339058924726343e-08 -4.8363510518940166e-08 -4.753486836821853e-08 -4.222278155493431e-08 -4.167643493012053e-08 -2.1108308948581704e-08 -2.553915706483249e-08 -3.176609505552752e-08 -2.9987263422841835e-08 -3.141361601313486e-08 -3.2029735243915394e-08 -3.2213740973903074e-08 -3.4751113422929186e-08 -3.22018245688793e-08 -2.7979718995803457e-08 -2.2222122998837608e-08 -1.4269771742804821e-08 -6.9400321037379265e-09 -6.6124542387397714e-09 -2.8228895133955598e-08 -5.6868618603868484e-08 -6.444621946742973e-08 -4.8724125589590415e-08 -3.778313995359703e-08 -4.04220894826878e-08 -4.029150212004805e-08 -3.208290706495248e-08 -3.240004780279189e-08 -3.251017182163221e-08 -2.4728677159009153e-08 -3.781971098970445e-08 -4.269089081710931e-08 -3.755861844652855e-08 -3.81458917589412e-08 -3.7685918525023815e-08 -3.9019076609820634e-08 -4.2581095526683435e-08 -3.6762602590940955e-08 -3.2406375824770026e-08 -2.4372417739850343e-08 -1.5509817504209033e-08 -8.899089089645121e-09 -4.870851098990411e-09 -9.132814992318166e-09 -2.6582951962810812e-08 -3.6057808870362884e-08 -2.541473335996365e-08 -1.9911737519988334e-08 -1.9959978414808685e-08 -2.0062623862220302e-08 -1.8068392935967095e-08 -2.4241912559314203e-08 -2.800042888591373e-08 -1.809691012592052e-08 -3.130595745740291e-08 -4.094024764596261e-08 -3.7405759733809885e-08 -3.804176703366456e-08 -3.798251373696018e-08 -3.9688778572156304e-08 -4.211019207298563e-08 -4.127908445915563e-08 -3.620631193159009e-08 -2.808507645263427e-08 -1.9396537912443567e-08 -9.255841601425602e-09 -5.257682260692952e-09 -8.6102189954483e-09 -2.3522819152707606e-08 -3.3572539875026884e-08 -2.5241657849756395e-08 -2.2216123705273918e-08 -1.6014169074076996e-08 -2.365011923120288e-08 -2.113978469426517e-08 -2.430363131912695e-08 -2.932479348562404e-08 -1.7952023077252245e-08 -3.081886412929351e-08 -3.611435015764806e-08 -3.521790777144638e-08 -3.874960149207628e-08 -4.0030163030561304e-08 -4.026709403527523e-08 -4.1884848744881024e-08 -4.139118084848265e-08 -3.687100078560542e-08 -2.9257321978558438e-08 -2.0038297959551093e-08 -1.2121449372278773e-08 -8.726342307852313e-09 -2.5439305808943694e-08 -5.437250157085569e-08 -6.356202221466626e-08 -5.237424372152548e-08 -4.40420467825972e-08 -3.960856883903081e-08 -3.931172708078362e-08 -3.375999725336628e-08 -3.0194362323944536e-08 -2.6571364286201495e-08 -2.1477553140111236e-08 -2.6781175196723398e-08 -3.7741227080754814e-08 -4.1266921507821034e-08 -3.93224107542532e-08 -3.700397142924993e-08 -3.815172668829766e-08 -4.255545471035644e-08 -4.167536656277357e-08 -3.68620429363117e-08 -2.9109722920470963e-08 -1.8883228493281877e-08 -1.066099120898669e-08 -7.376583438125838e-09 -2.729925117789459e-08 -5.726383234013947e-08 -6.096786193204413e-08 -4.709626248124032e-08 -3.883844034608107e-08 -3.6161769231432297e-08 -3.63797161702118e-08 -3.2640759184271965e-08 -2.7374365620596127e-08 -3.0217208948748725e-08 -1.9247706122801904e-08 -2.9694448587671636e-08 -3.778124976521395e-08 -3.569472833660426e-08 -3.4935283517124085e-08 -3.352388806968848e-08 -3.482072166468871e-08 -4.085420298348065e-08 -4.184170314048463e-08 -3.938347205723705e-08 -3.361815094253165e-08 -2.5176487441591935e-08 -1.5021080534027388e-08 -8.773761381636542e-09 -2.2151035479213068e-08 -4.309193948273676e-08 -4.298469183752286e-08 -4.0515119623976784e-08 -4.326082370565979e-08 -4.8480620016587526e-08 -4.45871606758568e-08 -4.5376191052637354e-08 -4.30969525910571e-08 -4.083932802272686e-08 -2.126018147605702e-08 -2.7143680455756733e-08 -3.2472285871866996e-08 -3.067562072269747e-08 -2.786039058135857e-08 -2.7915616954985956e-08 -3.100812951391236e-08 -3.749040730053044e-08 -3.9353311225211375e-08 -3.67736971749286e-08 -3.1746782261178655e-08 -2.4059139560880712e-08 -1.5951792857435348e-08 -1.1006402590468688e-08 -2.3599988147999445e-08 -4.11627967825444e-08 -4.210057676686301e-08 -4.033604482020585e-08 -4.144057229275356e-08 -4.283659968681371e-08 -4.612224018922875e-08 -4.48003410526268e-08 -4.116822080138281e-08 -4.069986499289698e-08 -2.1408766719387843e-08 -2.662856303031558e-08 -2.862419105233019e-08 -3.022838571483998e-08 -2.9932776688146966e-08 -2.978912237103287e-08 -3.0828232889105296e-08 -3.334358053436335e-08 -3.2056937520211025e-08 -2.8921936813717125e-08 -2.1977959969005814e-08 -1.4845128650193706e-08 -1.0022025353401973e-08 -6.886778100597233e-09 -2.6894504317604597e-08 -5.9556302120401284e-08 -6.528694238738233e-08 -4.677558791294558e-08 -3.643790109956922e-08 -3.803749356427673e-08 -3.529778877615743e-08 -3.0749091523326765e-08 -2.9122789874945298e-08 -3.1405808713291714e-08 -2.1108308948581704e-08 -3.951981216712966e-08 -4.172081326607111e-08 -4.252496514991631e-08 -3.9431219859435724e-08 -3.863808037747456e-08 -4.049958720639409e-08 -4.3924772920742606e-08 -4.106245243403392e-08 -3.516588649985987e-08 -2.6923843328594146e-08 -1.5724559340947667e-08 -9.253704866731686e-09 -4.846607378424817e-09 -8.330060204234372e-09 -2.3403490738262722e-08 -3.227176153905327e-08 -3.144772158613393e-08 -2.4029964914098385e-08 -2.111751334418627e-08 -2.026191546347984e-08 -1.9748934772732603e-08 -2.2247928179371825e-08 -2.4477117739852266e-08 -1.7689862166729384e-08 -3.2135585793367885e-08 -4.164726028333821e-08 -4.090679952979245e-08 -3.725059992219009e-08 -3.7970186421418355e-08 -3.8031494270713044e-08 -4.139027684534291e-08 -3.8826030848435617e-08 -3.337579591897932e-08 -2.5234918917260192e-08 -1.6238361852731026e-08 -8.990804317276315e-09 -4.904627943575017e-09 -7.598228571567891e-09 -1.910175070678667e-08 -2.83800280224984e-08 -2.7330973469888893e-08 -2.5702535086813514e-08 -2.450777166449961e-08 -2.4578366091502472e-08 -2.3561116012990887e-08 -2.3629984615817896e-08 -2.9840650549997706e-08 -2.123133555768914e-08 -2.6621988462026596e-08 -3.637799034603594e-08 -3.4957719231410216e-08 -3.482565259090544e-08 -3.548458869766791e-08 -3.830031193162849e-08 -4.248814756749806e-08 -4.139118084848265e-08 -3.687100078560542e-08 -2.9257321978558438e-08 -2.0038297959551093e-08 -1.2121449372278773e-08 -8.726342307852313e-09 -2.5439305808943694e-08 -5.437250157085569e-08 -6.356202221466626e-08 -5.237424372152548e-08 -4.40420467825972e-08 -3.960856883903081e-08 -3.931172708078362e-08 -3.375999725336628e-08 -3.0194362323944536e-08 -2.6571364286201495e-08 -2.1477553140111236e-08 -2.6781175196723398e-08 -3.7741227080754814e-08 -4.1266921507821034e-08 -3.93224107542532e-08 -3.700397142924993e-08 -3.815172668829766e-08 -4.255545471035644e-08 -4.167536656277357e-08 -3.68620429363117e-08 -2.9109722920470963e-08 -1.8883228493281877e-08 -1.066099120898669e-08 -7.376583438125838e-09 -2.729925117789459e-08 -5.726383234013947e-08 -6.096786193204413e-08 -4.709626248124032e-08 -3.883844034608107e-08 -3.6161769231432297e-08 -3.63797161702118e-08 -3.2640759184271965e-08 -2.7374365620596127e-08 -3.0217208948748725e-08 -1.9247706122801904e-08 -2.9694448587671636e-08 -3.778124976521395e-08 -3.569472833660426e-08 -3.4935283517124085e-08 -3.352388806968848e-08 -3.482072166468871e-08 -4.085420298348065e-08 -4.184170314048463e-08 -3.938347205723705e-08 -3.361815094253165e-08 -2.5176487441591935e-08 -1.5021080534027388e-08 -8.773761381636542e-09 -2.2151035479213068e-08 -4.309193948273676e-08 -4.298469183752286e-08 -4.0515119623976784e-08 -4.326082370565979e-08 -4.8480620016587526e-08 -4.45871606758568e-08 -4.5376191052637354e-08 -4.30969525910571e-08 -4.083932802272686e-08 -2.126018147605702e-08 -2.7143680455756733e-08 -3.2472285871866996e-08 -3.067562072269747e-08 -2.786039058135857e-08 -2.7915616954985956e-08 -3.100812951391236e-08 -3.749040730053044e-08 -3.9353311225211375e-08 -3.67736971749286e-08 -3.1746782261178655e-08 -2.4059139560880712e-08 -1.5951792857435348e-08 -1.1006402590468688e-08 -2.3599988147999445e-08 -4.11627967825444e-08 -4.210057676686301e-08 -4.033604482020585e-08 -4.144057229275356e-08 -4.283659968681371e-08 -4.612224018922875e-08 -4.48003410526268e-08 -4.116822080138281e-08 -4.069986499289698e-08 -2.1408766719387843e-08 -2.662856303031558e-08 -2.862419105233019e-08 -3.022838571483998e-08 -2.9932776688146966e-08 -2.978912237103287e-08 -3.0828232889105296e-08 -3.334358053436335e-08 -3.2056937520211025e-08 -2.8921936813717125e-08 -2.1977959969005814e-08 -1.4845128650193706e-08 -1.0022025353401973e-08 -6.886778100597233e-09 -2.6894504317604597e-08 -5.9556302120401284e-08 -6.528694238738233e-08 -4.677558791294558e-08 -3.643790109956922e-08 -3.803749356427673e-08 -3.529778877615743e-08 -3.0749091523326765e-08 -2.9122789874945298e-08 -3.1405808713291714e-08 -2.1108308948581704e-08 -3.951981216712966e-08 -4.172081326607111e-08 -4.252496514991631e-08 -3.9431219859435724e-08 -3.863808037747456e-08 -4.049958720639409e-08 -4.3924772920742606e-08 -4.106245243403392e-08 -3.516588649985987e-08 -2.6923843328594146e-08 -1.5724559340947667e-08 -9.253704866731686e-09 -4.846607378424817e-09 -8.330060204234372e-09 -2.3403490738262722e-08 -3.227176153905327e-08 -3.144772158613393e-08 -2.4029964914098385e-08 -2.111751334418627e-08 -2.026191546347984e-08 -1.9748934772732603e-08 -2.2247928179371825e-08 -2.4477117739852266e-08 -1.7689862166729384e-08 -3.2135585793367885e-08 -4.164726028333821e-08 -4.090679952979245e-08 -3.725059992219009e-08 -3.7970186421418355e-08 -3.8031494270713044e-08 -4.139027684534291e-08 -3.8826030848435617e-08 -3.337579591897932e-08 -2.5234918917260192e-08 -1.6238361852731026e-08 -8.990804317276315e-09 -4.904627943575017e-09 -7.598228571567891e-09 -1.910175070678667e-08 -2.83800280224984e-08 -2.7330973469888893e-08 -2.5702535086813514e-08 -2.450777166449961e-08 -2.4578366091502472e-08 -2.3561116012990887e-08 -2.3629984615817896e-08 -2.9840650549997706e-08 -2.123133555768914e-08 -2.6621988462026596e-08 -3.637799034603594e-08 -3.4957719231410216e-08 -3.482565259090544e-08 -3.548458869766791e-08 -3.830031193162849e-08 -4.248814756749806e-08 -4.139118084848265e-08 -3.687100078560542e-08 -2.9257321978558438e-08 -2.0038297959551093e-08 -1.2121449372278773e-08 -8.726342307852313e-09 -2.5439305808943694e-08 -5.437250157085569e-08 -6.356202221466626e-08 -5.237424372152548e-08 -4.40420467825972e-08 -3.960856883903081e-08 -3.931172708078362e-08 -3.375999725336628e-08 -3.0194362323944536e-08 -2.6571364286201495e-08 -2.1477553140111236e-08 -2.6781175196723398e-08 -3.7741227080754814e-08 -4.1266921507821034e-08 -3.93224107542532e-08 -3.700397142924993e-08 -3.815172668829766e-08 -4.255545471035644e-08 -4.167536656277357e-08 -3.68620429363117e-08 -2.9109722920470963e-08 -1.8883228493281877e-08 -1.066099120898669e-08 -7.376583438125838e-09 -2.729925117789459e-08 -5.726383234013947e-08 -6.096786193204413e-08 -4.709626248124032e-08 -3.883844034608107e-08 -3.6161769231432297e-08 -3.63797161702118e-08 -3.2640759184271965e-08 -2.7374365620596127e-08 -3.0217208948748725e-08 -1.9247706122801904e-08 -2.9694448587671636e-08 -3.778124976521395e-08 -3.569472833660426e-08 -3.4935283517124085e-08 -3.352388806968848e-08 -3.482072166468871e-08 -4.085420298348065e-08 -4.184170314048463e-08 -3.938347205723705e-08 -3.361815094253165e-08 -2.5176487441591935e-08 -1.5021080534027388e-08 -8.773761381636542e-09 -2.2151035479213068e-08 -4.309193948273676e-08 -4.298469183752286e-08 -4.0515119623976784e-08 -4.326082370565979e-08 -4.8480620016587526e-08 -4.45871606758568e-08 -4.5376191052637354e-08 -4.30969525910571e-08 -4.083932802272686e-08 -2.126018147605702e-08 -2.7143680455756733e-08 -3.2472285871866996e-08 -3.067562072269747e-08 -2.786039058135857e-08 -2.7915616954985956e-08 -3.100812951391236e-08 -3.749040730053044e-08 -3.9353311225211375e-08 -3.67736971749286e-08 -3.1746782261178655e-08 -2.4059139560880712e-08 -1.5951792857435348e-08 -1.1006402590468688e-08 -2.3599988147999445e-08 -4.11627967825444e-08 -4.210057676686301e-08 -4.033604482020585e-08 -4.144057229275356e-08 -4.283659968681371e-08 -4.612224018922875e-08 -4.48003410526268e-08 -4.116822080138281e-08 -4.069986499289698e-08 -2.1408766719387843e-08 -2.662856303031558e-08 -2.862419105233019e-08 -3.022838571483998e-08 -2.9932776688146966e-08 -2.978912237103287e-08 -3.0828232889105296e-08 -3.334358053436335e-08 -3.2056937520211025e-08 -2.8921936813717125e-08 -2.1977959969005814e-08 -1.4845128650193706e-08 -1.0022025353401973e-08 -6.886778100597233e-09 -2.6894504317604597e-08 -5.9556302120401284e-08 -6.528694238738233e-08 -4.677558791294558e-08 -3.643790109956922e-08 -3.803749356427673e-08 -3.529778877615743e-08 -3.0749091523326765e-08 -2.9122789874945298e-08 -3.1405808713291714e-08 -2.1108308948581704e-08 -3.951981216712966e-08 -4.172081326607111e-08 -4.252496514991631e-08 -3.9431219859435724e-08 -3.863808037747456e-08 -4.049958720639409e-08 -4.3924772920742606e-08 -4.106245243403392e-08 -3.516588649985987e-08 -2.6923843328594146e-08 -1.5724559340947667e-08 -9.253704866731686e-09 -4.846607378424817e-09 -8.330060204234372e-09 -2.3403490738262722e-08 -3.227176153905327e-08 -3.144772158613393e-08 -2.4029964914098385e-08 -2.111751334418627e-08 -2.026191546347984e-08 -1.9748934772732603e-08 -2.2247928179371825e-08 -2.4477117739852266e-08 -1.7689862166729384e-08 -3.2135585793367885e-08 -4.164726028333821e-08 -4.090679952979245e-08 -3.725059992219009e-08 -3.7970186421418355e-08 -3.8031494270713044e-08 -4.139027684534291e-08 -3.8826030848435617e-08 -3.337579591897932e-08 -2.5234918917260192e-08 -1.6238361852731026e-08 -8.990804317276315e-09 -4.904627943575017e-09 -7.598228571567891e-09 -1.910175070678667e-08 -2.83800280224984e-08 -2.7330973469888893e-08 -2.5702535086813514e-08 -2.450777166449961e-08 -2.4578366091502472e-08 -2.3561116012990887e-08 -2.3629984615817896e-08 -2.9840650549997706e-08 -2.123133555768914e-08 -2.6621988462026596e-08 -3.637799034603594e-08 -3.4957719231410216e-08 -3.482565259090544e-08 -3.548458869766791e-08 -3.830031193162849e-08 -4.248814756749806e-08 -4.139118084848265e-08 -3.687100078560542e-08 -2.9257321978558438e-08 -2.0038297959551093e-08 -1.2121449372278773e-08 -8.726342307852313e-09 -2.5439305808943694e-08 -5.437250157085569e-08 -6.356202221466626e-08 -5.237424372152548e-08 -4.40420467825972e-08 -3.960856883903081e-08 -3.931172708078362e-08 -3.375999725336628e-08 -3.0194362323944536e-08 -2.6571364286201495e-08 -2.1477553140111236e-08 -2.6781175196723398e-08 -3.7741227080754814e-08 -4.1266921507821034e-08 -3.93224107542532e-08 -3.700397142924993e-08 -3.815172668829766e-08 -4.255545471035644e-08 -4.167536656277357e-08 -3.68620429363117e-08 -2.9109722920470963e-08 -1.8883228493281877e-08 -1.066099120898669e-08 -7.376583438125838e-09 -2.729925117789459e-08 -5.726383234013947e-08 -6.096786193204413e-08 -4.709626248124032e-08 -3.883844034608107e-08 -3.6161769231432297e-08 -3.63797161702118e-08 -3.2640759184271965e-08 -2.7374365620596127e-08 -3.0217208948748725e-08 -1.9247706122801904e-08 -2.9694448587671636e-08 -3.778124976521395e-08 -3.569472833660426e-08 -3.4935283517124085e-08 -3.352388806968848e-08 -3.482072166468871e-08 -4.085420298348065e-08 -4.184170314048463e-08 -3.938347205723705e-08 -3.361815094253165e-08 -2.5176487441591935e-08 -1.5021080534027388e-08 -8.773761381636542e-09 -2.2151035479213068e-08 -4.309193948273676e-08 -4.298469183752286e-08 -4.0515119623976784e-08 -4.326082370565979e-08 -4.8480620016587526e-08 -4.45871606758568e-08 -4.5376191052637354e-08 -4.30969525910571e-08 -4.083932802272686e-08 -2.126018147605702e-08 -2.7143680455756733e-08 -3.2472285871866996e-08 -3.067562072269747e-08 -2.786039058135857e-08 -2.7915616954985956e-08 -3.100812951391236e-08 -3.749040730053044e-08 -3.9353311225211375e-08 -3.67736971749286e-08 -3.1746782261178655e-08 -2.4059139560880712e-08 -1.5951792857435348e-08 -1.1006402590468688e-08 -2.3599988147999445e-08 -4.11627967825444e-08 -4.210057676686301e-08 -4.033604482020585e-08 -4.144057229275356e-08 -4.283659968681371e-08 -4.612224018922875e-08 -4.48003410526268e-08 -4.116822080138281e-08 -4.069986499289698e-08 -2.1408766719387843e-08 -2.662856303031558e-08 -2.862419105233019e-08 -3.022838571483998e-08 -2.9932776688146966e-08 -2.978912237103287e-08 -3.0828232889105296e-08 -3.334358053436335e-08 -3.2056937520211025e-08 -2.8921936813717125e-08 -2.1977959969005814e-08 -1.4845128650193706e-08 -1.0022025353401973e-08 -6.886778100597233e-09 -2.6894504317604597e-08 -5.9556302120401284e-08 -6.528694238738233e-08 -4.677558791294558e-08 -3.643790109956922e-08 -3.803749356427673e-08 -3.529778877615743e-08 -3.0749091523326765e-08 -2.9122789874945298e-08 -3.1405808713291714e-08 -2.1108308948581704e-08 -3.951981216712966e-08 -4.172081326607111e-08 -4.252496514991631e-08 -3.9431219859435724e-08 -3.863808037747456e-08 -4.049958720639409e-08 -4.3924772920742606e-08 -4.106245243403392e-08 -3.516588649985987e-08 -2.6923843328594146e-08 -1.5724559340947667e-08 -9.253704866731686e-09 -4.846607378424817e-09 -8.330060204234372e-09 -2.3403490738262722e-08 -3.227176153905327e-08 -3.144772158613393e-08 -2.4029964914098385e-08 -2.111751334418627e-08 -2.026191546347984e-08 -1.9748934772732603e-08 -2.2247928179371825e-08 -2.4477117739852266e-08 -1.7689862166729384e-08 -3.2135585793367885e-08 -4.164726028333821e-08 -4.090679952979245e-08 -3.725059992219009e-08 -3.7970186421418355e-08 -3.8031494270713044e-08 -4.139027684534291e-08 -3.8826030848435617e-08 -3.337579591897932e-08 -2.5234918917260192e-08 -1.6238361852731026e-08 -8.990804317276315e-09 -4.904627943575017e-09 -7.598228571567891e-09 -1.910175070678667e-08 -2.83800280224984e-08 -2.7330973469888893e-08 -2.5702535086813514e-08 -2.450777166449961e-08 -2.4578366091502472e-08 -2.3561116012990887e-08 -2.3629984615817896e-08 -2.9840650549997706e-08 -2.123133555768914e-08 -2.6621988462026596e-08 -3.637799034603594e-08 -3.4957719231410216e-08 -3.482565259090544e-08 -3.548458869766791e-08 -3.830031193162849e-08 -4.248814756749806e-08 -4.139118084848265e-08 -3.687100078560542e-08 -2.9257321978558438e-08 -2.0038297959551093e-08 -1.2121449372278773e-08 -8.726342307852313e-09 -2.5439305808943694e-08 -5.437250157085569e-08 -6.356202221466626e-08 -5.237424372152548e-08 -4.40420467825972e-08 -3.960856883903081e-08 -3.931172708078362e-08 -3.375999725336628e-08 -3.0194362323944536e-08 -2.6571364286201495e-08 -2.1477553140111236e-08 -2.6781175196723398e-08 -3.7741227080754814e-08 -4.1266921507821034e-08 -3.93224107542532e-08 -3.700397142924993e-08 -3.815172668829766e-08 -4.255545471035644e-08 -4.167536656277357e-08 -3.68620429363117e-08 -2.9109722920470963e-08 -1.8883228493281877e-08 -1.066099120898669e-08 -7.376583438125838e-09 -2.729925117789459e-08 -5.726383234013947e-08 -6.096786193204413e-08 -4.709626248124032e-08 -3.883844034608107e-08 -3.6161769231432297e-08 -3.63797161702118e-08 -3.2640759184271965e-08 -2.7374365620596127e-08 -3.0217208948748725e-08 -1.9247706122801904e-08 -2.9694448587671636e-08 -3.778124976521395e-08 -3.569472833660426e-08 -3.4935283517124085e-08 -3.352388806968848e-08 -3.482072166468871e-08 -4.085420298348065e-08 -4.184170314048463e-08 -3.938347205723705e-08 -3.361815094253165e-08 -2.5176487441591935e-08 -1.5021080534027388e-08 -8.773761381636542e-09 -2.2151035479213068e-08 -4.309193948273676e-08 -4.298469183752286e-08 -4.0515119623976784e-08 -4.326082370565979e-08 -4.8480620016587526e-08 -4.45871606758568e-08 -4.5376191052637354e-08 -4.30969525910571e-08 -4.083932802272686e-08 -2.126018147605702e-08 -2.7143680455756733e-08 -3.2472285871866996e-08 -3.067562072269747e-08 -2.786039058135857e-08 -2.7915616954985956e-08 -3.100812951391236e-08 -3.749040730053044e-08 -3.4662849843649705e-08 -3.796985769300391e-08 -3.5421472842093754e-08 -2.9849690581395044e-08 -2.2315892779059104e-08 -1.4979578571703237e-08 -9.36571907395509e-09 -2.2300689089890848e-08 -4.4232627080873846e-08 -4.3018222135796626e-08 -3.709815211998949e-08 -4.4654139090300725e-08 -4.759642276382406e-08 -5.177012307787233e-08 -4.9480776217547786e-08 -4.459809089563722e-08 -4.47201313195013e-08 -2.5564140424330593e-08 -2.973323854057658e-08 -3.2126956672488606e-08 -2.9341229906346477e-08 -3.040852888595788e-08 -3.0317964207777264e-08 -3.1300451256460894e-08 -3.172360690796002e-08 -3.1790503140300334e-08 -2.840418956096038e-08 -2.08634062798174e-08 -1.3628093877800904e-08 -7.435836734830222e-09 -6.034796232449743e-09 -2.71596237838575e-08 -5.921327401992403e-08 -6.537241177513901e-08 -5.023890612337016e-08 -4.484603430223518e-08 -4.011407095834934e-08 -3.649066201008824e-08 -3.068901640558626e-08 -3.0874583595542565e-08 -3.3180859969211225e-08 -2.1665585793175913e-08 -3.351501240249836e-08 -4.2465629671108316e-08 -4.0198965071380724e-08 -3.9175633517201836e-08 -3.952079835237301e-08 -4.1933582732323056e-08 -4.3888941523567696e-08 -4.0032628493669674e-08 -3.454491852496622e-08 -2.6838127394526638e-08 -1.719709827347074e-08 -8.609150628101342e-09 -4.93519968611875e-09 -7.904192543316045e-09 -2.6886368289346992e-08 -3.641521883897226e-08 -2.959451514967922e-08 -2.3734848980027035e-08 -2.6640068524821277e-08 -2.2509595997273015e-08 -2.3397162716284577e-08 -2.4853676138603285e-08 -3.153639607593147e-08 -1.883761742577712e-08 -3.486625055008986e-08 -4.4736074647602065e-08 -4.1239061774696505e-08 -4.0519064364950175e-08 -4.075385863497018e-08 -4.28089043178964e-08 -4.5367644113861695e-08 -4.4585845762199004e-08 -3.8857506594119084e-08 -3.1365950393039806e-08 -2.0881321978404856e-08 -1.0845325667388813e-08 -5.9457108321341375e-09 -8.48965784944923e-09 -2.1701252826143597e-08 -3.278597496135469e-08 -2.7426551256389862e-08 -2.440307166449769e-08 -2.0848202590649148e-08 -2.6431901256371627e-08 -2.817342221401737e-08 -2.80703658560877e-08 -3.275729340719404e-08 -1.9111037284494845e-08 -3.020668963948637e-08 -3.968146436493482e-08 -3.8228484773071445e-08 -3.8020974961450686e-08 -3.708779717493436e-08 -3.968910730057075e-08 -4.326353571507899e-08 -4.21241630305997e-08 -3.780072692377004e-08 -2.991831263791122e-08 -1.843459638966298e-08 -1.0604860832219567e-08 -8.36202904253951e-09 -2.9181714443235233e-08 -5.882258029935173e-08 -6.802138752087047e-08 -5.314305730081744e-08 -4.132116169620508e-08 -3.6849633438666255e-08 -3.7080811696127326e-08 -3.666751789706166e-08 -3.235525855632325e-08 -3.2955845369521076e-08 -2.2043212559273887e-08 -3.559906836799968e-08 -4.156737927862717e-08 -4.094115164910234e-08 -4.124530761457103e-08 -4.0493341366519564e-08 -4.4799683595797905e-08 -5.1154825668127926e-08 -5.1085546154782856e-08 -4.653232888625352e-08 -3.743000345437549e-08 -2.5051652826205026e-08 -1.4618963501052981e-08 -9.616867582593916e-09 -2.797454152327589e-08 -6.118548014240918e-08 -6.683878704989118e-08 -5.036628838396904e-08 -4.3097610047885996e-08 -4.391721216721029e-08 -4.014472488299669e-08 -3.7082373156095954e-08 -3.2995046232944086e-08 -3.332969175885289e-08 -2.1996368760214938e-08 -3.085568171171177e-08 -3.68432232345845e-08 -3.3642805573615304e-08 -3.3517560047710337e-08 -3.216870518112359e-08 -3.498804442764311e-08 -4.2196812010192874e-08 -4.523187927869436e-08 -4.1766753061990315e-08 -3.548056177459091e-08 -2.5639008320721294e-08 -1.558082284172996e-08 -1.0622283438185352e-08 -2.413006271629802e-08 -4.697709843100265e-08 -4.662240047181248e-08 -4.420246624884818e-08 -4.808680337607795e-08 -5.017135243420094e-08 -5.43206446634764e-08 -4.7860145134315546e-08 -4.345674584067123e-08 -4.410360117820272e-08 -2.2700998116585786e-08 -2.8284203689686594e-08 -3.187161687656556e-08 -2.8246646468335827e-08 -2.7923342072725502e-08 -2.5509078414910432e-08 -2.820834960805255e-08 -3.4662849843649705e-08 -3.796985769300391e-08 -3.5421472842093754e-08 -2.9849690581395044e-08 -2.2315892779059104e-08 -1.4979578571703237e-08 -9.36571907395509e-09 -2.2300689089890848e-08 -4.4232627080873846e-08 -4.3018222135796626e-08 -3.709815211998949e-08 -4.4654139090300725e-08 -4.759642276382406e-08 -5.177012307787233e-08 -4.9480776217547786e-08 -4.459809089563722e-08 -4.47201313195013e-08 -2.5564140424330593e-08 -2.973323854057658e-08 -3.2126956672488606e-08 -2.9341229906346477e-08 -3.040852888595788e-08 -3.0317964207777264e-08 -3.1300451256460894e-08 -3.172360690796002e-08 -3.1790503140300334e-08 -2.840418956096038e-08 -2.08634062798174e-08 -1.3628093877800904e-08 -7.435836734830222e-09 -6.034796232449743e-09 -2.71596237838575e-08 -5.921327401992403e-08 -6.537241177513901e-08 -5.023890612337016e-08 -4.484603430223518e-08 -4.011407095834934e-08 -3.649066201008824e-08 -3.068901640558626e-08 -3.0874583595542565e-08 -3.3180859969211225e-08 -2.1665585793175913e-08 -3.351501240249836e-08 -4.2465629671108316e-08 -4.0198965071380724e-08 -3.9175633517201836e-08 -3.952079835237301e-08 -4.1933582732323056e-08 -4.3888941523567696e-08 -4.0032628493669674e-08 -3.454491852496622e-08 -2.6838127394526638e-08 -1.719709827347074e-08 -8.609150628101342e-09 -4.93519968611875e-09 -7.904192543316045e-09 -2.6886368289346992e-08 -3.641521883897226e-08 -2.959451514967922e-08 -2.3734848980027035e-08 -2.6640068524821277e-08 -2.2509595997273015e-08 -2.3397162716284577e-08 -2.4853676138603285e-08 -3.153639607593147e-08 -1.883761742577712e-08 -3.486625055008986e-08 -4.4736074647602065e-08 -4.1239061774696505e-08 -4.0519064364950175e-08 -4.075385863497018e-08 -4.28089043178964e-08 -4.5367644113861695e-08 -4.4585845762199004e-08 -3.8857506594119084e-08 -3.1365950393039806e-08 -2.0881321978404856e-08 -1.0845325667388813e-08 -5.9457108321341375e-09 -8.48965784944923e-09 -2.1701252826143597e-08 -3.278597496135469e-08 -2.7426551256389862e-08 -2.440307166449769e-08 -2.0848202590649148e-08 -2.6431901256371627e-08 -2.817342221401737e-08 -2.80703658560877e-08 -3.275729340719404e-08 -1.9111037284494845e-08 -3.020668963948637e-08 -3.968146436493482e-08 -3.8228484773071445e-08 -3.8020974961450686e-08 -3.708779717493436e-08 -3.968910730057075e-08 -4.326353571507899e-08 -4.21241630305997e-08 -3.780072692377004e-08 -2.991831263791122e-08 -1.843459638966298e-08 -1.0604860832219567e-08 -8.36202904253951e-09 -2.9181714443235233e-08 -5.882258029935173e-08 -6.802138752087047e-08 -5.314305730081744e-08 -4.132116169620508e-08 -3.6849633438666255e-08 -3.7080811696127326e-08 -3.666751789706166e-08 -3.235525855632325e-08 -3.2955845369521076e-08 -2.2043212559273887e-08 -3.559906836799968e-08 -4.156737927862717e-08 -4.094115164910234e-08 -4.124530761457103e-08 -4.0493341366519564e-08 -4.4799683595797905e-08 -5.1154825668127926e-08 -5.1085546154782856e-08 -4.653232888625352e-08 -3.743000345437549e-08 -2.5051652826205026e-08 -1.4618963501052981e-08 -9.616867582593916e-09 -2.797454152327589e-08 -6.118548014240918e-08 -6.683878704989118e-08 -5.036628838396904e-08 -4.3097610047885996e-08 -4.391721216721029e-08 -4.014472488299669e-08 -3.7082373156095954e-08 -3.2995046232944086e-08 -3.332969175885289e-08 -2.1996368760214938e-08 -3.085568171171177e-08 -3.68432232345845e-08 -3.3642805573615304e-08 -3.3517560047710337e-08 -3.216870518112359e-08 -3.498804442764311e-08 -4.2196812010192874e-08 -4.523187927869436e-08 -4.1766753061990315e-08 -3.548056177459091e-08 -2.5639008320721294e-08 -1.558082284172996e-08 -1.0622283438185352e-08 -2.413006271629802e-08 -4.697709843100265e-08 -4.662240047181248e-08 -4.420246624884818e-08 -4.808680337607795e-08 -5.017135243420094e-08 -5.43206446634764e-08 -4.7860145134315546e-08 -4.345674584067123e-08 -4.410360117820272e-08 -2.2700998116585786e-08 -2.8284203689686594e-08 -3.187161687656556e-08 -2.8246646468335827e-08 -2.7923342072725502e-08 -2.5509078414910432e-08 -2.820834960805255e-08 -3.4662849843649705e-08 -3.796985769300391e-08 -3.5421472842093754e-08 -2.9849690581395044e-08 -2.2315892779059104e-08 -1.4979578571703237e-08 -9.36571907395509e-09 -2.2300689089890848e-08 -4.4232627080873846e-08 -4.3018222135796626e-08 -3.709815211998949e-08 -4.4654139090300725e-08 -4.759642276382406e-08 -5.177012307787233e-08 -4.9480776217547786e-08 -4.459809089563722e-08 -4.47201313195013e-08 -2.5564140424330593e-08 -2.973323854057658e-08 -3.2126956672488606e-08 -2.9341229906346477e-08 -3.040852888595788e-08 -3.0317964207777264e-08 -3.1300451256460894e-08 -3.172360690796002e-08 -3.1790503140300334e-08 -2.840418956096038e-08 -2.08634062798174e-08 -1.3628093877800904e-08 -7.435836734830222e-09 -6.034796232449743e-09 -2.71596237838575e-08 -5.921327401992403e-08 -6.537241177513901e-08 -5.023890612337016e-08 -4.484603430223518e-08 -4.011407095834934e-08 -3.649066201008824e-08 -3.068901640558626e-08 -3.0874583595542565e-08 -3.3180859969211225e-08 -2.1665585793175913e-08 -3.351501240249836e-08 -4.2465629671108316e-08 -4.0198965071380724e-08 -3.9175633517201836e-08 -3.952079835237301e-08 -4.1933582732323056e-08 -4.3888941523567696e-08 -4.0032628493669674e-08 -3.454491852496622e-08 -2.6838127394526638e-08 -1.719709827347074e-08 -8.609150628101342e-09 -4.93519968611875e-09 -7.904192543316045e-09 -2.6886368289346992e-08 -3.641521883897226e-08 -2.959451514967922e-08 -2.3734848980027035e-08 -2.6640068524821277e-08 -2.2509595997273015e-08 -2.3397162716284577e-08 -2.4853676138603285e-08 -3.153639607593147e-08 -1.883761742577712e-08 -3.486625055008986e-08 -4.4736074647602065e-08 -4.1239061774696505e-08 -4.0519064364950175e-08 -4.075385863497018e-08 -4.28089043178964e-08 -4.5367644113861695e-08 -4.4585845762199004e-08 -3.8857506594119084e-08 -3.1365950393039806e-08 -2.0881321978404856e-08 -1.0845325667388813e-08 -5.9457108321341375e-09 -8.48965784944923e-09 -2.1701252826143597e-08 -3.278597496135469e-08 -2.7426551256389862e-08 -2.440307166449769e-08 -2.0848202590649148e-08 -2.6431901256371627e-08 -2.817342221401737e-08 -2.80703658560877e-08 -3.275729340719404e-08 -1.9111037284494845e-08 -3.020668963948637e-08 -3.968146436493482e-08 -3.8228484773071445e-08 -3.8020974961450686e-08 -3.708779717493436e-08 -3.968910730057075e-08 -4.326353571507899e-08 -4.21241630305997e-08 -3.780072692377004e-08 -2.991831263791122e-08 -1.843459638966298e-08 -1.0604860832219567e-08 -8.36202904253951e-09 -2.9181714443235233e-08 -5.882258029935173e-08 -6.802138752087047e-08 -5.314305730081744e-08 -4.132116169620508e-08 -3.6849633438666255e-08 -3.7080811696127326e-08 -3.666751789706166e-08 -3.235525855632325e-08 -3.2955845369521076e-08 -2.2043212559273887e-08 -3.559906836799968e-08 -4.156737927862717e-08 -4.094115164910234e-08 -4.124530761457103e-08 -4.0493341366519564e-08 -4.4799683595797905e-08 -5.1154825668127926e-08 -5.1085546154782856e-08 -4.653232888625352e-08 -3.743000345437549e-08 -2.5051652826205026e-08 -1.4618963501052981e-08 -9.616867582593916e-09 -2.797454152327589e-08 -6.118548014240918e-08 -6.683878704989118e-08 -5.036628838396904e-08 -4.3097610047885996e-08 -4.391721216721029e-08 -4.014472488299669e-08 -3.7082373156095954e-08 -3.2995046232944086e-08 -3.332969175885289e-08 -2.1996368760214938e-08 -3.085568171171177e-08 -3.68432232345845e-08 -3.3642805573615304e-08 -3.3517560047710337e-08 -3.216870518112359e-08 -3.498804442764311e-08 -4.2196812010192874e-08 -4.523187927869436e-08 -4.1766753061990315e-08 -3.548056177459091e-08 -2.5639008320721294e-08 -1.558082284172996e-08 -1.0622283438185352e-08 -2.413006271629802e-08 -4.697709843100265e-08 -4.662240047181248e-08 -4.420246624884818e-08 -4.808680337607795e-08 -5.017135243420094e-08 -5.43206446634764e-08 -4.7860145134315546e-08 -4.345674584067123e-08 -4.410360117820272e-08 -2.2700998116585786e-08 -2.8284203689686594e-08 -3.187161687656556e-08 -2.8246646468335827e-08 -2.7923342072725502e-08 -2.5509078414910432e-08 -2.820834960805255e-08 -3.4662849843649705e-08 -3.796985769300391e-08 -3.5421472842093754e-08 -2.9849690581395044e-08 -2.2315892779059104e-08 -1.4979578571703237e-08 -9.36571907395509e-09 -2.2300689089890848e-08 -4.4232627080873846e-08 -4.3018222135796626e-08 -3.709815211998949e-08 -4.4654139090300725e-08 -4.759642276382406e-08 -5.177012307787233e-08 -4.9480776217547786e-08 -4.459809089563722e-08 -4.47201313195013e-08 -2.5564140424330593e-08 -2.973323854057658e-08 -3.2126956672488606e-08 -2.9341229906346477e-08 -3.040852888595788e-08 -3.0317964207777264e-08 -3.1300451256460894e-08 -3.172360690796002e-08 -3.1790503140300334e-08 -2.840418956096038e-08 -2.08634062798174e-08 -1.3628093877800904e-08 -7.435836734830222e-09 -6.034796232449743e-09 -2.71596237838575e-08 -5.921327401992403e-08 -6.537241177513901e-08 -5.023890612337016e-08 -4.484603430223518e-08 -4.011407095834934e-08 -3.649066201008824e-08 -3.068901640558626e-08 -3.0874583595542565e-08 -3.3180859969211225e-08 -2.1665585793175913e-08 -3.351501240249836e-08 -4.2465629671108316e-08 -4.0198965071380724e-08 -3.9175633517201836e-08 -3.952079835237301e-08 -4.1933582732323056e-08 -4.3888941523567696e-08 -4.0032628493669674e-08 -3.454491852496622e-08 -2.6838127394526638e-08 -1.719709827347074e-08 -8.609150628101342e-09 -4.93519968611875e-09 -7.904192543316045e-09 -2.6886368289346992e-08 -3.641521883897226e-08 -2.959451514967922e-08 -2.3734848980027035e-08 -2.6640068524821277e-08 -2.2509595997273015e-08 -2.3397162716284577e-08 -2.4853676138603285e-08 -3.153639607593147e-08 -1.883761742577712e-08 -3.486625055008986e-08 -4.4736074647602065e-08 -4.1239061774696505e-08 -4.0519064364950175e-08 -4.075385863497018e-08 -4.28089043178964e-08 -4.5367644113861695e-08 -4.4585845762199004e-08 -3.8857506594119084e-08 -3.1365950393039806e-08 -2.0881321978404856e-08 -1.0845325667388813e-08 -5.9457108321341375e-09 -8.48965784944923e-09 -2.1701252826143597e-08 -3.278597496135469e-08 -2.7426551256389862e-08 -2.440307166449769e-08 -2.0848202590649148e-08 -2.6431901256371627e-08 -2.817342221401737e-08 -2.80703658560877e-08 -3.275729340719404e-08 -1.9111037284494845e-08 -3.020668963948637e-08 -3.968146436493482e-08 -3.8228484773071445e-08 -3.8020974961450686e-08 -3.708779717493436e-08 -3.968910730057075e-08 -4.326353571507899e-08 -4.21241630305997e-08 -3.780072692377004e-08 -2.991831263791122e-08 -1.843459638966298e-08 -1.0604860832219567e-08 -8.36202904253951e-09 -2.9181714443235233e-08 -5.882258029935173e-08 -6.802138752087047e-08 -5.314305730081744e-08 -4.132116169620508e-08 -3.6849633438666255e-08 -3.7080811696127326e-08 -3.666751789706166e-08 -3.235525855632325e-08 -3.2955845369521076e-08 -2.2043212559273887e-08 -3.559906836799968e-08 -4.156737927862717e-08 -4.094115164910234e-08 -4.124530761457103e-08 -4.0493341366519564e-08 -4.4799683595797905e-08 -5.1154825668127926e-08 -5.1085546154782856e-08 -4.653232888625352e-08 -3.743000345437549e-08 -2.5051652826205026e-08 -1.4618963501052981e-08 -9.616867582593916e-09 -2.797454152327589e-08 -6.118548014240918e-08 -6.683878704989118e-08 -5.036628838396904e-08 -4.3097610047885996e-08 -4.391721216721029e-08 -4.014472488299669e-08 -3.7082373156095954e-08 -3.2995046232944086e-08 -3.332969175885289e-08 -2.1996368760214938e-08 -3.085568171171177e-08 -3.68432232345845e-08 -3.3642805573615304e-08 -3.3517560047710337e-08 -3.216870518112359e-08 -3.498804442764311e-08 -4.2196812010192874e-08 -4.523187927869436e-08 -4.1766753061990315e-08 -3.548056177459091e-08 -2.5639008320721294e-08 -1.558082284172996e-08 -1.0622283438185352e-08 -2.413006271629802e-08 -4.697709843100265e-08 -4.662240047181248e-08 -4.420246624884818e-08 -4.808680337607795e-08 -5.017135243420094e-08 -5.43206446634764e-08 -4.7860145134315546e-08 -4.345674584067123e-08 -4.410360117820272e-08 -2.2700998116585786e-08 -2.8284203689686594e-08 -3.187161687656556e-08 -2.8246646468335827e-08 -2.7923342072725502e-08 -2.5509078414910432e-08 -2.820834960805255e-08 -3.4662849843649705e-08 -3.796985769300391e-08 -3.5421472842093754e-08 -2.9849690581395044e-08 -2.2315892779059104e-08 -1.4979578571703237e-08 -9.36571907395509e-09 -2.2300689089890848e-08 -4.4232627080873846e-08 -4.3018222135796626e-08 -3.709815211998949e-08 -4.4654139090300725e-08 -4.759642276382406e-08 -5.177012307787233e-08 -4.9480776217547786e-08 -4.459809089563722e-08 -4.47201313195013e-08 -2.5564140424330593e-08 -2.973323854057658e-08 -3.2126956672488606e-08 -2.9341229906346477e-08 -3.040852888595788e-08 -3.0317964207777264e-08 -3.1300451256460894e-08 -3.172360690796002e-08 -3.1790503140300334e-08 -2.840418956096038e-08 -2.08634062798174e-08 -1.3628093877800904e-08 -7.435836734830222e-09 -6.034796232449743e-09 -2.71596237838575e-08 -5.921327401992403e-08 -6.537241177513901e-08 -5.023890612337016e-08 -4.484603430223518e-08 -4.011407095834934e-08 -3.649066201008824e-08 -3.068901640558626e-08 -3.0874583595542565e-08 -3.3180859969211225e-08 -2.1665585793175913e-08 -3.351501240249836e-08 -4.2465629671108316e-08 -4.0198965071380724e-08 -3.9175633517201836e-08 -3.952079835237301e-08 -4.1933582732323056e-08 -4.320255659419875e-08 -4.369145792858762e-08 -3.894149670401073e-08 -3.033275698642745e-08 -2.0578974019215637e-08 -1.2271267347163782e-08 -6.307558634338575e-09 -6.64450525914852e-09 -2.278391985913048e-08 -3.0051776374177405e-08 -2.798769065985384e-08 -2.4630633909399817e-08 -3.0233070094745875e-08 -2.7632828336456437e-08 -2.8230785322338677e-08 -2.835085337571607e-08 -3.3426666641115266e-08 -2.087984270053984e-08 -2.8541598038199948e-08 -3.440693477300137e-08 -3.1283932653634847e-08 -3.018622629568693e-08 -3.120051781846848e-08 -3.4445971272217156e-08 -4.5683387755939696e-08 -4.487381185325608e-08 -4.124489670405297e-08 -3.211988901157796e-08 -2.2828626923495507e-08 -1.3176421036348353e-08 -5.991075353328063e-09 -8.04373775524953e-09 -1.808104897992337e-08 -2.6606702590754737e-08 -2.541407590313475e-08 -2.498409913703581e-08 -2.782505227680533e-08 -3.0535089325520645e-08 -2.6593471272073173e-08 -3.135304780277269e-08 -3.465964474160883e-08 -1.9390456436776265e-08 -3.0634858399305834e-08 -3.6296301335045434e-08 -3.59014163271889e-08 -3.586172237114421e-08 -3.840361483586901e-08 -4.2375886813963813e-08 -4.836646907467021e-08 -4.7629706515787e-08 -4.3111498823396454e-08 -3.3079693799664635e-08 -2.212399756712466e-08 -1.2966363579515615e-08 -8.010289639079372e-09 -2.76885478027055e-08 -5.6497402041852264e-08 -5.975962064473781e-08 -5.229460926312527e-08 -4.4061606123256894e-08 -4.136775894895318e-08 -4.2394295605172947e-08 -4.3267644820259605e-08 -4.308503618603333e-08 -3.8746889482657085e-08 -2.6217323783840216e-08 -3.124432087969378e-08 -3.6494771115268856e-08 -3.7079743328780364e-08 -3.687330188450657e-08 -3.7454904631769975e-08 -4.18812327323221e-08 -4.6852921272444654e-08 -4.776440298360736e-08 -4.3437926138944047e-08 -3.471643257520485e-08 -2.360434379949089e-08 -1.41589902671356e-08 -8.802771664211643e-09 -2.860364552642714e-08 -5.850091954581364e-08 -5.97230496086304e-08 -4.8849946390220674e-08 -4.25012145219724e-08 -4.329969584066835e-08 -4.1758781397939946e-08 -3.925452833666953e-08 -4.018310392538358e-08 -3.6559366248708025e-08 -2.2717516719411836e-08 -2.985799097385988e-08 -3.226748806966544e-08 -3.348550902730159e-08 -3.2558330534348953e-08 -3.1646684458979014e-08 -3.5048119545383616e-08 -4.314609748901718e-08 -4.599872048749963e-08 -4.295313390973578e-08 -3.619209442766518e-08 -2.5490751805804922e-08 -1.550743422320428e-08 -9.691653296881005e-09 -2.4666465306574734e-08 -4.3852945762185566e-08 -4.699246648437814e-08 -4.17909146004523e-08 -4.581750894903477e-08 -5.0574455652418706e-08 -5.5644927081083095e-08 -5.1785326767040587e-08 -4.715239285800744e-08 -4.613464968687418e-08 -2.408330109934269e-08 -2.951085376820202e-08 -3.079741460025073e-08 -2.716389725324533e-08 -2.731774215120733e-08 -2.7460163736767242e-08 -3.1031880141856285e-08 -3.6725785008522695e-08 -3.911309293635297e-08 -3.740165062862928e-08 -3.2150049843603634e-08 -2.5010808320709775e-08 -1.7650661303306373e-08 -1.131228438011323e-08 -2.44456419941688e-08 -4.4772892230020325e-08 -4.2994389325749095e-08 -3.8559760832732145e-08 -4.4501526923892894e-08 -5.071917833687975e-08 -5.276986836831453e-08 -5.4089219859704496e-08 -5.145240706530764e-08 -4.5904868525174526e-08 -2.5467165542068223e-08 -2.598392660958162e-08 -2.942390510258033e-08 -3.0278763344354247e-08 -3.1644794270595935e-08 -3.2408266013153105e-08 -3.400703665682449e-08 -3.732185180602185e-08 -3.6746001806011294e-08 -3.3408340032009745e-08 -2.6945785950258595e-08 -1.7694546546635278e-08 -9.458831397347691e-09 -6.661516954596243e-09 -2.446298241803097e-08 -5.715740651596169e-08 -6.123347449091869e-08 -4.9403771586463166e-08 -4.4552890738650516e-08 -4.2353615463884915e-08 -3.62880009425806e-08 -3.7049253768340246e-08 -3.5656678022631817e-08 -3.5558388226711655e-08 -2.5701713265777388e-08 -3.5616573156069076e-08 -4.225318893327082e-08 -4.016124348582274e-08 -3.9258801806057365e-08 -3.8299654474799595e-08 -3.999540000073336e-08 -4.320255659419875e-08 -4.369145792858762e-08 -3.894149670401073e-08 -3.033275698642745e-08 -2.0578974019215637e-08 -1.2271267347163782e-08 -6.307558634338575e-09 -6.64450525914852e-09 -2.278391985913048e-08 -3.0051776374177405e-08 -2.798769065985384e-08 -2.4630633909399817e-08 -3.0233070094745875e-08 -2.7632828336456437e-08 -2.8230785322338677e-08 -2.835085337571607e-08 -3.3426666641115266e-08 -2.087984270053984e-08 -2.8541598038199948e-08 -3.440693477300137e-08 -3.1283932653634847e-08 -3.018622629568693e-08 -3.120051781846848e-08 -3.4445971272217156e-08 -4.5683387755939696e-08 -4.487381185325608e-08 -4.124489670405297e-08 -3.211988901157796e-08 -2.2828626923495507e-08 -1.3176421036348353e-08 -5.991075353328063e-09 -8.04373775524953e-09 -1.808104897992337e-08 -2.6606702590754737e-08 -2.541407590313475e-08 -2.498409913703581e-08 -2.782505227680533e-08 -3.0535089325520645e-08 -2.6593471272073173e-08 -3.135304780277269e-08 -3.465964474160883e-08 -1.9390456436776265e-08 -3.0634858399305834e-08 -3.6296301335045434e-08 -3.59014163271889e-08 -3.586172237114421e-08 -3.840361483586901e-08 -4.2375886813963813e-08 -4.836646907467021e-08 -4.7629706515787e-08 -4.3111498823396454e-08 -3.3079693799664635e-08 -2.212399756712466e-08 -1.2966363579515615e-08 -8.010289639079372e-09 -2.76885478027055e-08 -5.6497402041852264e-08 -5.975962064473781e-08 -5.229460926312527e-08 -4.4061606123256894e-08 -4.136775894895318e-08 -4.2394295605172947e-08 -4.3267644820259605e-08 -4.308503618603333e-08 -3.8746889482657085e-08 -2.6217323783840216e-08 -3.124432087969378e-08 -3.6494771115268856e-08 -3.7079743328780364e-08 -3.687330188450657e-08 -3.7454904631769975e-08 -4.18812327323221e-08 -4.6852921272444654e-08 -4.776440298360736e-08 -4.3437926138944047e-08 -3.471643257520485e-08 -2.360434379949089e-08 -1.41589902671356e-08 -8.802771664211643e-09 -2.860364552642714e-08 -5.850091954581364e-08 -5.97230496086304e-08 -4.8849946390220674e-08 -4.25012145219724e-08 -4.329969584066835e-08 -4.1758781397939946e-08 -3.925452833666953e-08 -4.018310392538358e-08 -3.6559366248708025e-08 -2.2717516719411836e-08 -2.985799097385988e-08 -3.226748806966544e-08 -3.348550902730159e-08 -3.2558330534348953e-08 -3.1646684458979014e-08 -3.5048119545383616e-08 -4.314609748901718e-08 -4.599872048749963e-08 -4.295313390973578e-08 -3.619209442766518e-08 -2.5490751805804922e-08 -1.550743422320428e-08 -9.691653296881005e-09 -2.4666465306574734e-08 -4.3852945762185566e-08 -4.699246648437814e-08 -4.17909146004523e-08 -4.581750894903477e-08 -5.0574455652418706e-08 -5.5644927081083095e-08 -5.1785326767040587e-08 -4.715239285800744e-08 -4.613464968687418e-08 -2.408330109934269e-08 -2.951085376820202e-08 -3.079741460025073e-08 -2.716389725324533e-08 -2.731774215120733e-08 -2.7460163736767242e-08 -3.1031880141856285e-08 -3.6725785008522695e-08 -3.911309293635297e-08 -3.740165062862928e-08 -3.2150049843603634e-08 -2.5010808320709775e-08 -1.7650661303306373e-08 -1.131228438011323e-08 -2.44456419941688e-08 -4.4772892230020325e-08 -4.2994389325749095e-08 -3.8559760832732145e-08 -4.4501526923892894e-08 -5.071917833687975e-08 -5.276986836831453e-08 -5.4089219859704496e-08 -5.145240706530764e-08 -4.5904868525174526e-08 -2.5467165542068223e-08 -2.598392660958162e-08 -2.942390510258033e-08 -3.0278763344354247e-08 -3.1644794270595935e-08 -3.2408266013153105e-08 -3.400703665682449e-08 -3.732185180602185e-08 -3.6746001806011294e-08 -3.3408340032009745e-08 -2.6945785950258595e-08 -1.7694546546635278e-08 -9.458831397347691e-09 -6.661516954596243e-09 -2.446298241803097e-08 -5.715740651596169e-08 -6.123347449091869e-08 -4.9403771586463166e-08 -4.4552890738650516e-08 -4.2353615463884915e-08 -3.62880009425806e-08 -3.7049253768340246e-08 -3.5656678022631817e-08 -3.5558388226711655e-08 -2.5701713265777388e-08 -3.5616573156069076e-08 -4.225318893327082e-08 -4.016124348582274e-08 -3.9258801806057365e-08 -3.8299654474799595e-08 -3.999540000073336e-08 -4.320255659419875e-08 -4.369145792858762e-08 -3.894149670401073e-08 -3.033275698642745e-08 -2.0578974019215637e-08 -1.2271267347163782e-08 -6.307558634338575e-09 -6.64450525914852e-09 -2.278391985913048e-08 -3.0051776374177405e-08 -2.798769065985384e-08 -2.4630633909399817e-08 -3.0233070094745875e-08 -2.7632828336456437e-08 -2.8230785322338677e-08 -2.835085337571607e-08 -3.3426666641115266e-08 -2.087984270053984e-08 -2.8541598038199948e-08 -3.440693477300137e-08 -3.1283932653634847e-08 -3.018622629568693e-08 -3.120051781846848e-08 -3.4445971272217156e-08 -4.5683387755939696e-08 -4.487381185325608e-08 -4.124489670405297e-08 -3.211988901157796e-08 -2.2828626923495507e-08 -1.3176421036348353e-08 -5.991075353328063e-09 -8.04373775524953e-09 -1.808104897992337e-08 -2.6606702590754737e-08 -2.541407590313475e-08 -2.498409913703581e-08 -2.782505227680533e-08 -3.0535089325520645e-08 -2.6593471272073173e-08 -3.135304780277269e-08 -3.465964474160883e-08 -1.9390456436776265e-08 -3.0634858399305834e-08 -3.6296301335045434e-08 -3.59014163271889e-08 -3.586172237114421e-08 -3.840361483586901e-08 -4.2375886813963813e-08 -4.836646907467021e-08 -4.7629706515787e-08 -4.3111498823396454e-08 -3.3079693799664635e-08 -2.212399756712466e-08 -1.2966363579515615e-08 -8.010289639079372e-09 -2.76885478027055e-08 -5.6497402041852264e-08 -5.975962064473781e-08 -5.229460926312527e-08 -4.4061606123256894e-08 -4.136775894895318e-08 -4.2394295605172947e-08 -4.3267644820259605e-08 -4.308503618603333e-08 -3.8746889482657085e-08 -2.6217323783840216e-08 -3.124432087969378e-08 -3.6494771115268856e-08 -3.7079743328780364e-08 -3.687330188450657e-08 -3.7454904631769975e-08 -4.18812327323221e-08 -4.6852921272444654e-08 -4.776440298360736e-08 -4.3437926138944047e-08 -3.471643257520485e-08 -2.360434379949089e-08 -1.41589902671356e-08 -8.802771664211643e-09 -2.860364552642714e-08 -5.850091954581364e-08 -5.97230496086304e-08 -4.8849946390220674e-08 -4.25012145219724e-08 -4.329969584066835e-08 -4.1758781397939946e-08 -3.925452833666953e-08 -4.018310392538358e-08 -3.6559366248708025e-08 -2.2717516719411836e-08 -2.985799097385988e-08 -3.226748806966544e-08 -3.348550902730159e-08 -3.2558330534348953e-08 -3.1646684458979014e-08 -3.5048119545383616e-08 -4.314609748901718e-08 -4.599872048749963e-08 -4.295313390973578e-08 -3.619209442766518e-08 -2.5490751805804922e-08 -1.550743422320428e-08 -9.691653296881005e-09 -2.4666465306574734e-08 -4.3852945762185566e-08 -4.699246648437814e-08 -4.17909146004523e-08 -4.581750894903477e-08 -5.0574455652418706e-08 -5.5644927081083095e-08 -5.1785326767040587e-08 -4.715239285800744e-08 -4.613464968687418e-08 -2.408330109934269e-08 -2.951085376820202e-08 -3.079741460025073e-08 -2.716389725324533e-08 -2.731774215120733e-08 -2.7460163736767242e-08 -3.1031880141856285e-08 -3.6725785008522695e-08 -3.911309293635297e-08 -3.740165062862928e-08 -3.2150049843603634e-08 -2.5010808320709775e-08 -1.7650661303306373e-08 -1.131228438011323e-08 -2.44456419941688e-08 -4.4772892230020325e-08 -4.2994389325749095e-08 -3.8559760832732145e-08 -4.4501526923892894e-08 -5.071917833687975e-08 -5.276986836831453e-08 -5.4089219859704496e-08 -5.145240706530764e-08 -4.5904868525174526e-08 -2.5467165542068223e-08 -2.598392660958162e-08 -2.942390510258033e-08 -3.0278763344354247e-08 -3.1644794270595935e-08 -3.2408266013153105e-08 -3.400703665682449e-08 -3.732185180602185e-08 -3.6746001806011294e-08 -3.3408340032009745e-08 -2.6945785950258595e-08 -1.7694546546635278e-08 -9.458831397347691e-09 -6.661516954596243e-09 -2.446298241803097e-08 -5.715740651596169e-08 -6.123347449091869e-08 -4.9403771586463166e-08 -4.4552890738650516e-08 -4.2353615463884915e-08 -3.62880009425806e-08 -3.7049253768340246e-08 -3.5656678022631817e-08 -3.5558388226711655e-08 -2.5701713265777388e-08 -3.5616573156069076e-08 -4.225318893327082e-08 -4.016124348582274e-08 -3.9258801806057365e-08 -3.8299654474799595e-08 -3.999540000073336e-08 -4.320255659419875e-08 -4.369145792858762e-08 -3.894149670401073e-08 -3.033275698642745e-08 -2.0578974019215637e-08 -1.2271267347163782e-08 -6.307558634338575e-09 -6.64450525914852e-09 -2.278391985913048e-08 -3.0051776374177405e-08 -2.798769065985384e-08 -2.4630633909399817e-08 -3.0233070094745875e-08 -2.7632828336456437e-08 -2.8230785322338677e-08 -2.835085337571607e-08 -3.3426666641115266e-08 -2.087984270053984e-08 -2.8541598038199948e-08 -3.440693477300137e-08 -3.1283932653634847e-08 -3.018622629568693e-08 -3.120051781846848e-08 -3.4445971272217156e-08 -4.5683387755939696e-08 -4.487381185325608e-08 -4.124489670405297e-08 -3.211988901157796e-08 -2.2828626923495507e-08 -1.3176421036348353e-08 -5.991075353328063e-09 -8.04373775524953e-09 -1.808104897992337e-08 -2.6606702590754737e-08 -2.541407590313475e-08 -2.498409913703581e-08 -2.782505227680533e-08 -3.0535089325520645e-08 -2.6593471272073173e-08 -3.135304780277269e-08 -3.465964474160883e-08 -1.9390456436776265e-08 -3.0634858399305834e-08 -3.6296301335045434e-08 -3.59014163271889e-08 -3.586172237114421e-08 -3.840361483586901e-08 -4.2375886813963813e-08 -4.836646907467021e-08 -4.7629706515787e-08 -4.3111498823396454e-08 -3.3079693799664635e-08 -2.212399756712466e-08 -1.2966363579515615e-08 -8.010289639079372e-09 -2.76885478027055e-08 -5.6497402041852264e-08 -5.975962064473781e-08 -5.229460926312527e-08 -4.4061606123256894e-08 -4.136775894895318e-08 -4.2394295605172947e-08 -4.3267644820259605e-08 -4.308503618603333e-08 -3.8746889482657085e-08 -2.6217323783840216e-08 -3.124432087969378e-08 -3.6494771115268856e-08 -3.7079743328780364e-08 -3.687330188450657e-08 -3.7454904631769975e-08 -4.18812327323221e-08 -4.6852921272444654e-08 -4.776440298360736e-08 -4.3437926138944047e-08 -3.471643257520485e-08 -2.360434379949089e-08 -1.41589902671356e-08 -8.802771664211643e-09 -2.860364552642714e-08 -5.850091954581364e-08 -5.97230496086304e-08 -4.8849946390220674e-08 -4.25012145219724e-08 -4.329969584066835e-08 -4.1758781397939946e-08 -3.925452833666953e-08 -4.018310392538358e-08 -3.6559366248708025e-08 -2.2717516719411836e-08 -2.985799097385988e-08 -3.226748806966544e-08 -3.348550902730159e-08 -3.2558330534348953e-08 -3.1646684458979014e-08 -3.5048119545383616e-08 -4.314609748901718e-08 -4.599872048749963e-08 -4.295313390973578e-08 -3.619209442766518e-08 -2.5490751805804922e-08 -1.550743422320428e-08 -9.691653296881005e-09 -2.4666465306574734e-08 -4.3852945762185566e-08 -4.699246648437814e-08 -4.17909146004523e-08 -4.581750894903477e-08 -5.0574455652418706e-08 -5.5644927081083095e-08 -5.1785326767040587e-08 -4.715239285800744e-08 -4.613464968687418e-08 -2.408330109934269e-08 -2.951085376820202e-08 -3.079741460025073e-08 -2.716389725324533e-08 -2.731774215120733e-08 -2.7460163736767242e-08 -3.1031880141856285e-08 -3.6725785008522695e-08 -3.911309293635297e-08 -3.740165062862928e-08 -3.2150049843603634e-08 -2.5010808320709775e-08 -1.7650661303306373e-08 -1.131228438011323e-08 -2.44456419941688e-08 -4.4772892230020325e-08 -4.2994389325749095e-08 -3.8559760832732145e-08 -4.4501526923892894e-08 -5.071917833687975e-08 -5.276986836831453e-08 -5.4089219859704496e-08 -5.145240706530764e-08 -4.5904868525174526e-08 -2.5467165542068223e-08 -2.598392660958162e-08 -2.942390510258033e-08 -3.0278763344354247e-08 -3.1644794270595935e-08 -3.2408266013153105e-08 -3.400703665682449e-08 -3.732185180602185e-08 -3.6746001806011294e-08 -3.3408340032009745e-08 -2.6945785950258595e-08 -1.7694546546635278e-08 -9.458831397347691e-09 -6.661516954596243e-09 -2.446298241803097e-08 -5.715740651596169e-08 -6.123347449091869e-08 -4.9403771586463166e-08 -4.4552890738650516e-08 -4.2353615463884915e-08 -3.62880009425806e-08 -3.7049253768340246e-08 -3.5656678022631817e-08 -3.5558388226711655e-08 -2.5701713265777388e-08 -3.5616573156069076e-08 -4.225318893327082e-08 -4.016124348582274e-08 -3.9258801806057365e-08 -3.8299654474799595e-08 -3.999540000073336e-08 -4.320255659419875e-08 -4.369145792858762e-08 -3.894149670401073e-08 -3.033275698642745e-08 -2.0578974019215637e-08 -1.2271267347163782e-08 -6.307558634338575e-09 -6.64450525914852e-09 -2.278391985913048e-08 -3.0051776374177405e-08 -2.798769065985384e-08 -2.4630633909399817e-08 -3.0233070094745875e-08 -2.7632828336456437e-08 -2.8230785322338677e-08 -2.835085337571607e-08 -3.3426666641115266e-08 -2.087984270053984e-08 -2.8541598038199948e-08 -3.440693477300137e-08 -3.1283932653634847e-08 -3.018622629568693e-08 -3.120051781846848e-08 -3.4445971272217156e-08 -4.5683387755939696e-08 -4.487381185325608e-08 -4.124489670405297e-08 -3.211988901157796e-08 -2.2828626923495507e-08 -1.3176421036348353e-08 -5.991075353328063e-09 -8.04373775524953e-09 -1.808104897992337e-08 -2.6606702590754737e-08 -2.541407590313475e-08 -2.498409913703581e-08 -2.782505227680533e-08 -3.0535089325520645e-08 -2.6593471272073173e-08 -3.135304780277269e-08 -3.465964474160883e-08 -1.9390456436776265e-08 -3.0634858399305834e-08 -3.6296301335045434e-08 -3.59014163271889e-08 -3.586172237114421e-08 -3.840361483586901e-08 -4.2375886813963813e-08 -4.836646907467021e-08 -4.7629706515787e-08 -4.3111498823396454e-08 -3.3079693799664635e-08 -2.212399756712466e-08 -1.2966363579515615e-08 -8.010289639079372e-09 -2.76885478027055e-08 -5.6497402041852264e-08 -5.975962064473781e-08 -5.229460926312527e-08 -4.4061606123256894e-08 -4.136775894895318e-08 -4.2394295605172947e-08 -4.3267644820259605e-08 -4.308503618603333e-08 -3.8746889482657085e-08 -2.6217323783840216e-08 -3.124432087969378e-08 -3.6494771115268856e-08 -3.7079743328780364e-08 -3.687330188450657e-08 -3.7454904631769975e-08 -4.18812327323221e-08 \ No newline at end of file diff --git a/examples/curve_examples/interconnector_8_price_curve.csv b/examples/curve_examples/interconnector_8_price_curve.csv deleted file mode 100644 index 0e71a91..0000000 --- a/examples/curve_examples/interconnector_8_price_curve.csv +++ /dev/null @@ -1,8760 +0,0 @@ -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.01 -0.01 -0.0 -0.0 -0.0 -0.0 -0.02 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.02 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.01 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.01 -0.01 -0.01 -0.02 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.01 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.01 -0.01 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.01 -14.45 -14.45 -26.01 -14.45 -0.01 -0.01 -0.0 -0.0 -0.01 -14.45 -0.01 -0.03 -0.12 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -14.45 -14.45 -14.45 -14.45 -14.45 -0.02 -0.01 -0.01 -0.01 -0.0 -0.01 -0.02 -0.02 -0.02 -0.02 -14.45 -45.18 -26.01 -26.01 -26.01 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -45.19 -45.19 -45.19 -45.18 -45.18 -45.18 -14.45 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -14.45 -14.46 -14.46 -14.46 -26.01 -26.01 -26.02 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -26.01 -26.01 -26.01 -45.18 -45.18 -45.18 -26.02 -26.02 -45.18 -26.02 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -26.01 -26.01 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -26.01 -45.18 -45.18 -45.18 -43.01 -43.01 -45.18 -45.18 -43.01 -26.01 -26.01 -26.01 -26.01 -14.45 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -45.18 -45.18 -45.18 -57.37 -45.19 -45.19 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -60.17 -103.94 -118.57 -105.28 -105.28 -105.28 -105.28 -105.28 -103.94 -105.28 -83.48 -72.01 -72.01 -72.01 -72.01 -72.01 -72.01 -83.48 -60.17 -60.17 -60.17 -60.17 -60.17 -60.17 -83.49 -105.28 -103.94 -105.28 -124.41 -137.56 -118.57 -103.95 -83.49 -86.31 -86.3 -83.48 -83.48 -86.3 -86.33 -105.28 -105.28 -118.57 -105.28 -103.96 -103.96 -103.96 -103.95 -104.48 -137.56 -150.0 -141.96 -150.0 -150.0 -150.0 -150.0 -124.41 -124.41 -105.28 -103.94 -105.28 -105.28 -103.96 -103.95 -105.28 -118.57 -150.0 -150.0 -137.56 -105.28 -103.99 -103.99 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -103.96 -83.5 -86.3 -86.3 -86.3 -105.28 -118.57 -124.41 -124.41 -118.59 -103.94 -83.48 -83.48 -83.48 -86.3 -103.96 -86.3 -105.28 -83.48 -105.28 -68.57 -45.18 -45.18 -45.18 -43.02 -14.45 -14.45 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -14.45 -14.45 -0.01 -0.01 -0.02 -14.45 -14.45 -14.48 -26.02 -26.01 -26.03 -26.02 -26.03 -26.01 -26.02 -14.46 -14.45 -14.45 -0.0 -0.0 -0.0 -0.0 -14.45 -14.45 -14.46 -14.46 -14.45 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.01 -14.45 -14.45 -14.45 -14.45 -14.45 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.01 -14.45 -14.45 -14.45 -14.45 -14.45 -0.01 -14.45 -14.46 -14.46 -14.46 -14.45 -14.45 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.01 -0.01 -0.0 -0.04 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.01 -14.45 -14.46 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -14.45 -45.18 -43.01 -45.18 -45.18 -45.18 -14.46 -14.46 -14.46 -45.18 -45.18 -45.18 -45.19 -105.28 -83.48 -105.28 -83.48 -83.48 -83.48 -103.94 -103.94 -60.17 -60.17 -45.19 -45.19 -45.19 -60.17 -103.96 -103.96 -103.94 -103.96 -105.28 -103.94 -60.17 -60.17 -60.17 -57.37 -60.17 -45.19 -45.19 -45.19 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -14.45 -14.45 -14.45 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -43.03 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -43.01 -26.01 -26.03 -14.46 -14.45 -14.45 -26.02 -26.01 -26.01 -26.01 -26.02 -26.01 -45.18 -26.01 -26.01 -43.01 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -26.01 -43.01 -43.01 -14.45 -14.45 -14.45 -45.18 -45.18 -43.01 -45.18 -14.5 -14.46 -45.18 -45.18 -45.18 -45.19 -118.57 -124.41 -105.28 -124.41 -137.56 -141.96 -119.92 -118.57 -103.98 -104.47 -105.28 -105.28 -105.28 -104.47 -150.0 -150.0 -150.0 -103.96 -103.99 -118.57 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -141.96 -104.47 -104.47 -124.41 -118.58 -103.96 -103.95 -103.94 -103.96 -105.28 -118.57 -137.56 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -103.94 -103.95 -86.3 -86.3 -103.94 -86.3 -103.95 -104.47 -105.28 -103.94 -86.3 -86.32 -86.32 -86.31 -104.47 -105.28 -105.28 -103.94 -118.57 -105.28 -83.49 -83.49 -83.48 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -34.33 -26.02 -26.02 -26.02 -26.02 -26.02 -26.01 -45.18 -45.18 -36.54 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -45.18 -45.18 -45.18 -45.18 -60.17 -105.28 -137.56 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -104.47 -103.94 -60.17 -45.19 -45.19 -83.48 -83.48 -103.94 -124.41 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -124.41 -105.28 -103.94 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -57.37 -72.02 -103.95 -118.57 -124.41 -137.56 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -141.96 -103.97 -105.28 -105.28 -86.3 -141.96 -86.3 -68.57 -83.48 -103.95 -137.56 -141.96 -150.0 -137.56 -105.28 -124.41 -83.48 -45.21 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -57.37 -45.19 -45.19 -45.21 -105.28 -137.56 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -137.56 -105.28 -105.28 -124.41 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -83.48 -83.48 -83.48 -83.48 -83.48 -86.3 -86.3 -83.48 -83.48 -83.48 -83.48 -83.48 -86.3 -86.3 -83.48 -103.97 -150.0 -150.0 -150.0 -150.0 -150.0 -137.56 -150.0 -118.58 -105.28 -105.28 -118.57 -118.58 -118.59 -150.0 -150.0 -150.0 -150.0 -105.28 -105.28 -104.47 -105.28 -137.56 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -104.47 -105.28 -104.48 -137.56 -141.96 -137.56 -141.96 -104.47 -83.48 -45.19 -45.18 -45.18 -45.18 -14.45 -14.45 -14.45 -45.18 -45.18 -45.18 -45.18 -14.46 -14.46 -14.46 -14.46 -14.45 -14.45 -14.45 -45.18 -45.18 -45.18 -45.18 -14.45 -14.45 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.02 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.01 -26.01 -14.49 -26.01 -26.02 -45.18 -45.18 -26.01 -26.01 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -26.03 -26.01 -14.46 -14.46 -14.46 -14.46 -14.46 -14.47 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -43.01 -45.18 -14.45 -0.02 -0.02 -0.02 -0.05 -0.02 -0.02 -14.45 -14.45 -14.45 -14.46 -14.46 -14.46 -14.45 -45.18 -14.46 -26.02 -14.45 -14.45 -14.45 -14.45 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.01 -0.01 -0.02 -14.45 -0.02 -0.02 -0.01 -0.01 -0.03 -26.01 -45.18 -45.19 -45.2 -60.17 -83.48 -105.28 -57.37 -60.17 -45.2 -45.19 -45.18 -45.18 -45.18 -45.18 -26.01 -14.45 -14.45 -14.45 -14.45 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -14.45 -14.45 -26.01 -26.01 -14.45 -14.45 -0.01 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.05 -0.01 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -14.46 -14.46 -14.46 -14.46 -45.18 -45.18 -45.18 -45.18 -57.37 -45.19 -45.19 -45.19 -45.19 -57.37 -45.19 -45.19 -45.19 -45.19 -45.19 -45.19 -45.18 -45.19 -60.17 -60.17 -72.01 -60.17 -68.57 -60.17 -68.57 -60.17 -57.37 -105.28 -105.28 -86.3 -68.57 -45.19 -60.17 -45.18 -45.18 -43.01 -45.18 -45.18 -45.18 -45.18 -45.18 -43.02 -45.18 -43.04 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -45.19 -45.19 -60.17 -72.01 -103.95 -103.94 -119.92 -118.57 -105.28 -105.28 -105.28 -83.48 -75.03 -68.57 -83.48 -75.02 -73.62 -45.2 -45.18 -45.19 -60.17 -68.57 -45.2 -57.37 -45.2 -45.2 -57.37 -60.17 -83.48 -83.48 -86.3 -103.95 -103.94 -82.35 -83.5 -86.3 -83.48 -83.5 -82.35 -72.01 -82.35 -73.61 -60.17 -83.49 -86.31 -104.47 -103.95 -103.95 -103.95 -103.95 -137.56 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -137.56 -137.56 -118.57 -104.47 -104.47 -86.3 -150.0 -141.96 -72.01 -45.2 -45.19 -45.18 -45.18 -45.18 -45.18 -45.19 -57.37 -57.37 -57.37 -45.18 -45.18 -45.18 -45.18 -45.18 -43.02 -43.01 -43.01 -43.02 -43.06 -14.45 -45.18 -14.45 -0.01 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.01 -14.45 -14.49 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -14.46 -45.18 -45.18 -45.18 -45.19 -45.19 -45.18 -45.18 -45.18 -26.02 -26.02 -26.02 -26.02 -26.02 -26.02 -14.46 -26.02 -26.02 -26.01 -26.01 -26.01 -26.02 -26.01 -26.03 -45.18 -45.18 -45.18 -45.2 -68.57 -73.61 -60.17 -57.37 -57.37 -45.19 -45.19 -45.19 -45.19 -45.19 -45.19 -45.19 -45.19 -45.19 -45.18 -45.18 -45.18 -45.18 -43.01 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -14.45 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.01 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -14.45 -14.45 -14.45 -14.45 -14.45 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -14.46 -14.46 -14.45 -45.18 -14.45 -14.45 -14.45 -14.45 -26.01 -43.04 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -43.01 -0.02 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -0.01 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -14.45 -0.03 -0.01 -0.01 -0.01 -0.01 -14.45 -45.18 -45.18 -45.18 -45.18 -45.19 -57.37 -45.19 -45.19 -45.19 -45.19 -45.19 -45.18 -45.18 -45.19 -57.37 -45.19 -45.19 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -68.57 -103.94 -137.56 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -124.41 -105.28 -105.28 -104.47 -103.95 -89.33 -104.47 -104.47 -103.95 -103.94 -103.94 -86.32 -86.31 -86.3 -103.96 -124.41 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -141.96 -105.28 -118.57 -150.0 -150.0 -150.0 -150.0 -141.96 -118.57 -124.41 -137.56 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -105.28 -104.47 -105.28 -104.47 -150.0 -118.57 -104.47 -104.47 -104.47 -86.3 -60.17 -86.3 -118.57 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -105.28 -103.94 -86.3 -86.3 -86.3 -86.3 -86.3 -73.61 -45.19 -57.37 -45.18 -45.19 -45.18 -45.18 -45.18 -45.18 -57.37 -103.94 -103.94 -83.48 -83.48 -83.48 -68.57 -60.17 -45.19 -45.19 -57.37 -45.18 -45.18 -45.18 -45.18 -43.04 -14.47 -0.01 -0.01 -0.0 -0.0 -0.0 -0.01 -14.45 -14.46 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -43.04 -43.04 -43.04 -14.54 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -45.18 -45.18 -45.18 -105.28 -105.28 -105.28 -103.95 -103.94 -89.33 -103.94 -103.94 -103.95 -86.3 -60.17 -45.23 -45.2 -57.37 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -60.17 -73.61 -83.48 -83.48 -83.48 -86.3 -86.3 -83.48 -73.61 -73.61 -60.17 -45.19 -45.19 -45.18 -45.18 -45.18 -26.01 -26.01 -26.01 -26.01 -26.01 -26.01 -26.01 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -43.01 -14.47 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -0.04 -14.45 -14.45 -14.45 -14.45 -14.45 -45.18 -45.18 -45.18 -45.19 -60.17 -72.01 -72.01 -105.28 -72.01 -60.17 -45.19 -45.19 -45.19 -45.19 -45.19 -45.19 -60.17 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.2 -103.94 -73.61 -73.61 -73.61 -73.61 -45.2 -45.2 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -14.46 -26.04 -14.45 -14.45 -14.45 -34.32 -14.5 -14.46 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -26.02 -26.02 -26.02 -26.01 -14.49 -43.01 -45.18 -45.18 -45.19 -60.17 -60.17 -57.37 -60.17 -57.37 -45.19 -45.19 -45.19 -45.19 -45.19 -45.18 -45.19 -45.19 -45.18 -45.18 -45.18 -26.02 -26.02 -26.02 -43.01 -14.48 -43.04 -45.18 -45.19 -57.37 -45.19 -57.37 -60.17 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -26.01 -26.01 -26.01 -26.01 -26.01 -45.18 -45.18 -57.37 -57.37 -45.19 -57.37 -57.37 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -43.01 -26.01 -26.01 -26.01 -26.01 -45.18 -45.18 -45.18 -45.19 -57.37 -45.19 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -26.01 -26.01 -26.01 -26.01 -26.01 -45.18 -45.18 -60.17 -72.01 -60.17 -60.17 -72.01 -60.17 -68.57 -60.17 -60.17 -60.17 -60.17 -60.17 -60.17 -68.57 -57.37 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -45.21 -45.19 -45.19 -45.19 -45.19 -45.19 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -14.45 -0.01 -0.01 -0.0 -0.0 -0.0 -0.0 -0.0 -0.01 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -26.01 -14.45 -26.01 -45.18 -14.45 -14.45 -14.45 -0.04 -14.45 -14.45 -14.45 -14.45 -43.02 -45.18 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -14.45 -26.01 -26.01 -26.01 -26.01 -26.02 -26.01 -26.01 -45.18 -45.18 -45.18 -45.18 -45.18 -45.2 -57.37 -57.37 -57.37 -60.17 -45.19 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -103.94 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -141.96 -137.56 -124.41 -124.41 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -118.57 -105.28 -105.28 -104.47 -83.48 -60.17 -45.19 -45.18 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -26.03 -26.01 -26.01 -26.01 -26.01 -45.18 -26.01 -26.02 -45.18 -45.18 -45.18 -26.01 -43.01 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -43.02 -43.01 -43.01 -43.01 -43.02 -43.02 -43.02 -43.01 -43.01 -45.18 -45.18 -60.17 -105.28 -105.28 -105.28 -105.28 -105.28 -83.48 -83.48 -83.48 -83.48 -68.57 -60.17 -60.17 -68.57 -60.17 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.2 -60.17 -60.17 -60.17 -72.01 -60.17 -60.17 -57.37 -45.19 -57.37 -45.19 -45.19 -45.19 -57.37 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -45.19 -45.19 -60.17 -72.01 -73.61 -73.61 -73.61 -68.57 -60.17 -45.19 -45.21 -45.19 -45.19 -45.18 -45.18 -45.19 -57.37 -45.18 -45.18 -45.18 -45.18 -26.04 -26.02 -26.01 -26.01 -14.5 -14.53 -14.53 -14.52 -14.51 -14.51 -14.5 -14.45 -14.48 -45.18 -14.49 -14.45 -14.45 -14.45 -0.01 -0.01 -0.01 -0.03 -0.01 -0.01 -0.01 -0.01 -0.02 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -0.01 -0.01 -0.01 -0.01 -0.01 -0.01 -0.03 -0.01 -0.01 -0.01 -0.01 -0.01 -0.01 -0.01 -0.01 -14.45 -45.18 -45.18 -45.18 -45.19 -60.17 -60.17 -60.17 -60.17 -60.17 -45.19 -57.37 -45.19 -45.19 -57.37 -45.19 -45.18 -45.19 -45.18 -45.18 -45.18 -45.19 -45.19 -45.19 -45.19 -86.3 -124.41 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -118.57 -104.48 -105.28 -104.48 -104.47 -104.47 -103.94 -86.31 -104.47 -103.94 -103.95 -86.3 -86.3 -103.94 -103.95 -86.3 -104.47 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -137.56 -124.41 -118.57 -105.28 -105.28 -150.0 -124.41 -60.17 -45.2 -57.37 -60.17 -60.17 -60.17 -60.17 -45.19 -105.28 -103.95 -119.92 -103.95 -105.28 -105.28 -105.28 -103.97 -103.96 -86.3 -86.3 -86.3 -86.3 -83.48 -83.48 -57.37 -45.18 -45.18 -26.02 -26.02 -26.02 -26.02 -26.02 -14.45 -14.46 -14.45 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -43.03 -43.01 -43.02 -43.01 -43.01 -43.01 -43.02 -26.01 -26.01 -26.01 -26.01 -26.01 -26.01 -26.01 -26.01 -26.02 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -57.37 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.01 -26.01 -26.01 -26.01 -26.01 -26.01 -14.47 -26.01 -26.01 -26.01 -26.04 -26.04 -26.04 -14.45 -14.45 -14.45 -14.45 -0.02 -0.02 -0.02 -0.01 -0.01 -0.01 -0.01 -14.45 -14.45 -26.02 -26.01 -14.49 -26.01 -45.18 -14.45 -14.45 -14.45 -14.45 -14.45 -14.46 -14.46 -45.18 -14.46 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -14.48 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -45.19 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -45.19 -45.18 -57.37 -57.37 -57.37 -57.37 -57.37 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -43.04 -45.18 -45.18 -26.03 -26.03 -26.01 -26.02 -14.47 -14.5 -14.48 -14.48 -45.18 -45.18 -45.18 -45.19 -60.17 -60.17 -60.17 -60.17 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -45.19 -45.19 -45.18 -45.19 -45.18 -45.19 -45.18 -45.19 -45.18 -45.18 -45.18 -45.18 -45.19 -45.19 -60.17 -73.61 -72.02 -73.61 -73.61 -45.19 -57.37 -45.18 -45.18 -45.18 -45.18 -26.01 -26.02 -14.45 -0.02 -0.0 -0.01 -0.01 -0.01 -0.01 -0.01 -0.02 -0.01 -0.01 -0.01 -0.01 -0.01 -0.01 -0.01 -0.01 -0.01 -0.01 -0.01 -0.01 -0.01 -0.01 -0.0 -0.02 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.02 -14.45 -14.45 -14.45 -14.46 -14.45 -14.46 -14.45 -14.45 -14.45 -0.07 -0.01 -0.0 -0.02 -0.01 -0.01 -0.01 -0.01 -0.02 -0.02 -0.02 -14.45 -14.45 -26.02 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -43.01 -14.45 -14.45 -14.45 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.01 -0.01 -0.01 -0.03 -0.01 -0.01 -0.01 -0.01 -0.01 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.02 -0.01 -0.01 -0.01 -0.01 -0.01 -0.01 -0.02 -26.02 -14.46 -26.02 -45.18 -26.01 -14.46 -14.46 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -0.02 -0.01 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -14.45 -14.45 -14.45 -14.45 -14.45 -45.18 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -0.08 -14.45 -0.02 -0.03 -26.02 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -72.01 -83.48 -83.48 -83.48 -83.48 -83.48 -83.48 -83.48 -72.01 -60.17 -60.17 -57.37 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -45.18 -45.18 -45.18 -60.17 -86.3 -118.57 -118.57 -124.41 -124.41 -137.56 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -83.48 -105.28 -105.28 -68.57 -57.37 -45.19 -60.17 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -57.37 -83.48 -83.48 -86.3 -83.48 -83.48 -83.48 -83.48 -83.48 -83.48 -86.3 -105.28 -105.28 -83.48 -83.48 -60.17 -57.37 -45.19 -60.17 -72.01 -72.01 -73.61 -72.01 -86.3 -103.97 -118.57 -118.57 -105.28 -105.28 -105.28 -105.28 -60.17 -60.17 -60.17 -60.17 -57.37 -60.17 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -73.61 -103.95 -119.92 -105.28 -103.94 -103.94 -103.94 -103.94 -86.3 -86.3 -60.17 -60.17 -60.17 -60.17 -60.17 -60.17 -60.17 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -43.01 -14.46 -14.45 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.01 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.01 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -26.01 -26.01 -14.45 -14.45 -26.01 -26.01 -45.18 -45.18 -45.18 -45.19 -45.19 -57.37 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -26.02 -14.45 -0.01 -0.01 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.01 -0.01 -0.01 -0.01 -0.01 -0.01 -14.45 -43.01 -45.18 -45.18 -43.01 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -14.46 -14.46 -14.46 -14.45 -0.01 -0.01 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -14.45 -26.01 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -60.17 -60.17 -118.57 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -103.94 -72.01 -83.48 -68.57 -73.61 -72.01 -73.61 -57.37 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -14.49 -26.01 -26.01 -14.49 -14.45 -14.45 -0.05 -14.45 -14.45 -26.01 -26.04 -26.01 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -73.61 -83.48 -105.28 -103.95 -105.28 -103.94 -83.48 -86.3 -103.95 -60.17 -60.17 -60.17 -57.37 -57.37 -57.37 -45.19 -45.18 -45.19 -45.19 -45.2 -45.19 -45.18 -45.2 -45.19 -45.19 -45.19 -45.19 -45.19 -60.17 -45.2 -45.19 -60.17 -60.17 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -14.45 -14.45 -14.45 -14.45 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -26.01 -26.01 -14.47 -14.45 -0.02 -0.02 -0.02 -0.01 -0.01 -0.02 -0.02 -14.45 -26.01 -45.18 -45.18 -45.18 -57.37 -60.17 -60.17 -60.17 -60.17 -60.17 -60.17 -45.2 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -124.41 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -124.42 -150.0 -150.0 -150.0 -45.19 -45.19 -45.19 -45.18 -45.19 -45.19 -45.18 -45.19 -45.19 -60.17 -83.48 -60.17 -45.21 -45.18 -45.18 -45.18 -45.18 -26.01 -26.01 -45.18 -14.46 -14.46 -0.02 -0.01 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.01 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.01 -0.01 -0.01 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -14.45 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -43.01 -34.35 -26.05 -26.05 -26.05 -26.05 -26.05 -43.01 -45.18 -45.18 -45.19 -57.37 -60.17 -60.17 -60.17 -68.57 -105.28 -86.3 -60.17 -60.17 -60.17 -45.2 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -83.48 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -137.56 -118.57 -103.94 -83.48 -83.48 -86.32 -86.3 -86.3 -118.57 -118.57 -105.28 -105.28 -103.95 -86.3 -83.48 -118.57 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -137.56 -124.41 -104.47 -86.31 -86.31 -118.57 -83.48 -83.48 -83.48 -83.48 -73.61 -73.61 -83.48 -86.3 -86.3 -89.33 -124.41 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -103.94 -86.3 -103.94 -68.57 -105.28 -60.17 -60.17 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -43.02 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -60.17 -105.28 -60.17 -73.61 -60.17 -60.17 -60.17 -124.41 -124.41 -124.41 -124.41 -105.28 -103.95 -86.3 -83.48 -86.3 -86.3 -105.28 -124.41 -141.96 -124.41 -124.41 -118.57 -124.41 -124.41 -119.92 -118.57 -73.61 -73.61 -73.61 -73.61 -83.48 -103.94 -103.94 -68.57 -60.17 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -43.01 -43.01 -43.01 -14.46 -14.46 -14.46 -14.46 -14.46 -0.01 -0.05 -14.45 -26.03 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -60.17 -60.17 -60.17 -60.17 -60.17 -60.17 -57.37 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -83.48 -141.96 -137.56 -150.0 -150.0 -141.96 -141.96 -83.48 -72.01 -57.37 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -43.01 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -14.53 -14.49 -14.49 -14.54 -26.02 -14.45 -0.02 -0.0 -0.01 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.01 -0.02 -0.01 -0.01 -0.01 -0.01 -0.01 -0.01 -0.01 -0.01 -0.01 -0.02 -45.18 -45.18 -45.18 -45.19 -57.37 -60.17 -60.17 -83.48 -60.17 -83.48 -86.3 -103.94 -103.94 -60.17 -105.28 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -141.96 -103.96 -103.94 -86.3 -86.3 -60.17 -45.21 -60.17 -60.17 -60.17 -60.17 -60.17 -60.17 -60.17 -45.22 -45.21 -68.57 -86.3 -83.48 -86.3 -86.3 -83.48 -105.28 -105.28 -105.28 -60.17 -60.17 -60.17 -45.19 -45.18 -45.18 -45.18 -57.37 -57.37 -57.37 -57.37 -57.37 -57.37 -45.19 -45.19 -45.2 -60.17 -103.94 -118.57 -150.0 -150.0 -150.0 -150.0 -137.56 -124.42 -103.94 -89.33 -103.94 -103.96 -86.3 -86.3 -86.3 -86.3 -83.48 -83.48 -103.94 -103.95 -118.57 -137.56 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -141.96 -105.28 -68.57 -60.17 -45.19 -45.19 -45.18 -45.18 -45.18 -43.01 -26.03 -26.03 -26.04 -14.49 -43.01 -45.18 -45.18 -45.18 -45.18 -14.46 -14.45 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -14.45 -14.45 -0.0 -14.45 -0.06 -0.06 -0.03 -14.45 -14.45 -14.45 -0.04 -0.04 -0.04 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -83.48 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -124.41 -105.28 -89.33 -104.47 -104.47 -73.61 -60.17 -73.61 -73.61 -73.61 -73.61 -73.61 -73.61 -73.61 -104.47 -118.57 -118.57 -105.28 -83.48 -83.48 -83.48 -83.48 -83.48 -83.48 -68.57 -83.48 -72.01 -60.17 -60.17 -68.57 -72.01 -72.01 -73.61 -73.61 -68.57 -57.37 -86.3 -119.92 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -141.96 -124.41 -105.28 -86.3 -105.28 -68.57 -45.19 -45.18 -45.19 -45.19 -45.19 -45.19 -45.2 -45.18 -45.19 -45.21 -45.21 -45.19 -45.19 -57.37 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -26.02 -26.01 -26.01 -45.18 -0.02 -14.45 -14.45 -0.01 -14.45 -26.02 -14.5 -14.45 -14.45 -0.01 -0.0 -0.01 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -14.45 -14.45 -14.45 -14.46 -14.46 -14.46 -14.46 -14.46 -14.46 -14.46 -14.45 -14.45 -26.03 -14.45 -14.45 -0.04 -0.04 -14.45 -14.45 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -26.02 -26.02 -26.02 -26.03 -26.02 -45.18 -45.18 -26.02 -26.01 -45.18 -45.18 -45.18 -45.18 -60.17 -60.17 -68.57 -83.48 -103.94 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -105.28 -83.48 -60.17 -60.17 -45.19 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -45.19 -45.19 -57.37 -57.37 -45.19 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -83.48 -83.48 -83.48 -83.48 -105.28 -60.17 -60.17 -60.17 -57.37 -57.37 -45.19 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -14.45 -14.45 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -14.48 -14.45 -0.03 -0.02 -0.05 -0.02 -0.01 -0.01 -0.0 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -43.01 -43.02 -43.01 -43.01 -43.03 -43.01 -43.04 -26.03 -26.01 -14.5 -26.01 -26.02 -26.04 -26.02 -45.18 -45.18 -45.21 -45.18 -45.19 -57.37 -57.37 -45.19 -57.37 -57.37 -45.19 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -45.19 -45.19 -57.37 -57.37 -57.37 -45.18 -45.18 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.22 -60.17 -103.94 -103.95 -86.3 -86.3 -86.3 -86.3 -68.57 -72.01 -60.17 -60.17 -60.17 -68.57 -60.17 -60.17 -60.17 -57.37 -57.37 -57.37 -57.37 -60.17 -60.17 -73.61 -124.41 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -86.31 -86.3 -68.57 -45.19 -45.19 -60.17 -60.17 -45.18 -45.18 -26.01 -45.18 -26.01 -26.01 -14.55 -26.03 -26.03 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -14.46 -45.18 -45.18 -45.18 -45.18 -43.01 -43.01 -14.56 -43.02 -43.01 -43.01 -43.01 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.21 -45.2 -45.19 -45.19 -45.18 -45.18 -45.18 -45.19 -45.19 -60.17 -60.17 -45.19 -45.19 -45.19 -45.19 -45.19 -45.19 -45.18 -57.37 -45.19 -45.19 -45.18 -45.18 -45.2 -45.18 -45.18 -45.19 -45.19 -45.19 -45.19 -45.18 -45.18 -45.18 -45.18 -45.19 -60.17 -68.57 -68.57 -68.57 -68.57 -83.48 -103.95 -124.41 -124.41 -124.41 -124.41 -124.41 -118.57 -118.57 -86.3 -60.17 -45.21 -45.19 -45.19 -45.19 -45.18 -45.18 -45.19 -45.19 -45.2 -45.19 -45.19 -45.19 -45.19 -45.18 -45.19 -45.19 -45.19 -57.37 -45.19 -45.2 -45.2 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -26.01 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -45.19 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -45.19 -45.19 -45.18 -57.37 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -45.19 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -45.19 -45.19 -45.19 -45.19 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -26.04 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -26.01 -26.01 -26.01 -14.48 -14.46 -14.45 -0.01 -0.01 -0.02 -0.03 -14.45 -14.45 -0.02 -14.45 -14.47 -14.45 -14.45 -26.01 -26.02 -26.01 -26.02 -26.02 -14.5 -26.01 -45.18 -45.18 -14.49 -45.18 -26.02 -26.02 -14.49 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -26.01 -45.18 -45.18 -45.18 -26.07 -26.06 -26.02 -26.01 -26.02 -26.02 -14.45 -14.45 -0.0 -14.45 -14.45 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.01 -0.01 -14.45 -26.01 -26.01 -26.01 -26.01 -26.01 -26.01 -26.01 -26.04 -14.46 -14.46 -14.46 -14.46 -14.47 -14.45 -14.45 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.2 -83.48 -150.0 -137.56 -141.97 -137.56 -150.0 -150.0 -141.96 -118.58 -105.28 -89.34 -86.3 -68.57 -105.28 -105.28 -83.48 -60.17 -60.17 -60.17 -60.17 -68.57 -86.3 -103.95 -105.28 -118.57 -137.56 -137.56 -137.56 -124.41 -124.41 -124.41 -124.41 -103.94 -68.57 -73.61 -72.01 -86.3 -103.94 -103.95 -57.37 -45.18 -45.18 -45.18 -57.37 -45.19 -45.19 -45.18 -60.17 -73.61 -73.61 -73.61 -73.61 -73.61 -60.17 -45.19 -45.19 -45.18 -45.18 -45.18 -45.18 -43.05 -45.18 -43.03 -14.45 -0.01 -0.01 -0.0 -0.0 -0.0 -0.0 -0.0 -0.01 -14.46 -43.01 -43.01 -43.01 -14.45 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.04 -26.01 -45.18 -45.18 -45.19 -45.19 -57.37 -45.2 -45.19 -45.19 -45.19 -45.19 -45.2 -57.37 -57.37 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -103.95 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -141.96 -124.41 -150.0 -150.0 -68.57 -68.57 -60.17 -60.17 -60.17 -60.17 -60.17 -60.17 -60.17 -60.17 -83.48 -60.17 -45.25 -45.22 -45.21 -60.17 -57.37 -57.37 -45.22 -45.19 -45.19 -45.19 -57.37 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -45.19 -105.28 -105.28 -105.28 -105.28 -103.94 -103.94 -60.17 -45.19 -45.19 -57.37 -60.17 -57.37 -60.17 -45.2 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -45.18 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -60.17 -60.17 -60.17 -45.19 -45.18 -45.18 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -45.19 -57.37 -60.17 -45.19 -45.19 -105.28 -60.17 -105.28 -60.17 -45.19 -57.37 -57.37 -45.18 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -60.17 -60.17 -57.37 -57.37 -57.37 -45.19 -45.19 -45.2 -45.2 -45.19 -45.19 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -45.19 -45.19 -45.21 -45.23 -45.2 -60.17 -57.37 -45.19 -45.19 -45.19 -57.37 -60.17 -45.19 -57.37 -45.18 -45.19 -45.19 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -14.45 -14.45 -14.45 -14.46 -0.01 -0.01 -0.0 -0.0 -0.0 -0.0 -0.01 -0.01 -0.01 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -26.01 -26.01 -26.01 -43.01 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -43.01 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -14.56 -26.04 -26.04 -26.04 -43.01 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -26.02 -26.02 -43.01 -43.04 -45.18 -45.18 -83.48 -118.57 -124.41 -124.41 -137.56 -124.41 -119.92 -150.0 -124.41 -118.57 -104.47 -104.47 -105.28 -103.96 -105.28 -141.96 -141.96 -124.41 -103.94 -86.32 -104.47 -104.47 -83.48 -104.0 -141.96 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -124.41 -103.96 -89.33 -60.17 -60.17 -60.17 -60.17 -60.17 -60.17 -45.19 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -60.17 -60.17 -60.17 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -103.95 -137.56 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -137.56 -141.96 -124.42 -118.58 -137.56 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -137.56 -118.57 -83.48 -86.3 -86.3 -86.3 -86.3 -103.96 -137.56 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -104.47 -104.47 -104.47 -86.32 -118.57 -124.42 -105.28 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -57.37 -45.19 -60.17 -60.17 -45.19 -45.19 -57.37 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -57.37 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -26.02 -26.01 -26.01 -26.01 -14.45 -14.52 -26.01 -14.47 -26.01 -43.02 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -43.01 -43.02 -43.02 -43.01 -43.02 -43.01 -26.02 -14.5 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -45.19 -45.19 -45.19 -45.19 -45.19 -45.19 -45.19 -45.19 -57.37 -57.37 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -45.19 -45.19 -45.2 -57.37 -45.19 -45.19 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -14.45 -0.01 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -14.45 -14.45 -14.45 -14.45 -14.46 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.01 -0.01 -0.01 -0.01 -0.01 -0.01 -14.45 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -14.46 -14.45 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -45.18 -45.18 -45.18 -45.18 -45.18 -43.02 -43.04 -14.46 -14.46 -14.46 -14.45 -14.46 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -14.45 -45.18 -45.18 -45.18 -45.18 -45.18 -73.61 -103.95 -105.28 -105.28 -105.28 -103.95 -103.95 -105.28 -86.31 -86.3 -73.61 -73.61 -60.17 -72.02 -60.17 -60.17 -60.17 -57.37 -60.17 -60.17 -60.17 -83.48 -83.48 -105.28 -105.28 -105.28 -105.28 -105.28 -105.28 -103.95 -105.28 -60.17 -45.2 -45.2 -45.19 -45.19 -45.19 -45.19 -60.17 -60.17 -60.17 -60.17 -60.17 -60.17 -45.2 -45.19 -45.19 -57.37 -83.48 -104.47 -124.41 -124.41 -124.41 -119.92 -124.41 -118.57 -103.95 -103.94 -103.94 -86.3 -103.94 -86.3 -68.57 -45.23 -45.19 -45.19 -45.19 -45.19 -45.19 -45.18 -45.18 -60.17 -45.18 -57.37 -60.17 -45.19 -45.19 -45.18 -45.18 -45.18 -45.18 -43.02 -45.18 -45.18 -45.18 -43.01 -26.01 -0.03 -0.05 -0.04 -0.04 -0.02 -0.02 -0.03 -0.02 -45.18 -34.32 -45.18 -45.18 -45.19 -45.19 -45.18 -45.18 -45.18 -45.18 -45.19 -45.18 -45.19 -57.37 -45.21 -60.17 -60.17 -60.17 -45.18 -45.18 -45.18 -60.17 -83.48 -118.57 -137.56 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -105.28 -103.95 -103.94 -83.48 -60.17 -83.48 -83.48 -60.17 -60.17 -45.2 -57.37 -57.37 -60.17 -60.17 -60.17 -105.28 -83.48 -105.28 -105.28 -105.28 -103.95 -86.3 -83.48 -86.3 -83.48 -103.94 -57.37 -57.37 -45.18 -57.37 -45.19 -45.19 -45.18 -45.18 -45.18 -26.01 -26.01 -26.01 -26.01 -26.01 -43.01 -43.02 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -26.04 -45.18 -26.01 -0.04 -14.45 -26.01 -26.01 -26.01 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -45.19 -57.37 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -26.01 -43.01 -14.45 -14.45 -0.01 -0.01 -0.01 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -14.49 -14.49 -14.49 -45.18 -14.46 -14.46 -14.46 -14.46 -14.45 -14.46 -14.46 -14.46 -26.02 -45.18 -14.46 -14.46 -0.01 -0.02 -0.03 -14.45 -0.04 -26.02 -14.49 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -14.46 -14.45 -14.5 -14.49 -26.01 -14.49 -14.51 -26.04 -14.45 -14.45 -45.18 -43.04 -43.02 -45.18 -43.01 -14.46 -14.46 -14.46 -14.46 -14.46 -14.46 -14.46 -14.46 -14.46 -14.46 -43.02 -14.51 -26.01 -26.01 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -43.01 -43.01 -43.01 -45.18 -45.18 -45.18 -14.49 -26.01 -26.02 -26.01 -26.02 -14.5 -14.51 -26.01 -45.18 -45.18 -45.2 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -57.37 -45.18 -45.18 -45.18 -26.01 -14.45 -14.45 -14.45 -14.46 -14.46 -45.18 -43.04 -14.45 -14.47 -14.45 -0.0 -0.0 -0.0 -14.45 -45.18 -43.01 -43.02 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -105.28 -105.28 -103.95 -103.95 -103.99 -103.95 -103.99 -103.97 -86.3 -89.35 -105.28 -86.3 -83.48 -83.48 -86.3 -83.48 -83.48 -73.61 -60.17 -45.22 -45.2 -45.19 -45.19 -45.19 -45.19 -45.19 -68.57 -60.17 -60.17 -45.19 -45.19 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -45.2 -45.2 -57.37 -57.37 -45.23 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -83.48 -83.48 -83.48 -83.48 -86.3 -86.3 -83.48 -83.48 -60.17 -60.17 -60.17 -57.37 -60.17 -45.18 -45.18 -43.01 -45.18 -14.47 -14.45 -0.01 -14.45 -14.46 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -43.02 -45.18 -45.18 -45.18 -45.18 -45.19 -45.18 -45.18 -45.18 -45.18 -26.01 -26.01 -26.01 -45.18 -45.18 -45.18 -73.61 -83.48 -68.57 -73.61 -68.57 -73.61 -73.61 -60.17 -57.37 -57.37 -45.18 -45.19 -72.01 -83.48 -83.48 -73.61 -60.17 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -57.37 -105.28 -105.28 -105.28 -103.98 -89.38 -60.17 -60.17 -45.19 -45.19 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -26.01 -14.45 -0.02 -0.0 -0.0 -0.0 -0.01 -0.01 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -14.45 -0.0 -14.45 -0.0 -0.01 -0.01 -0.01 -0.0 -0.0 -0.0 -0.0 -14.45 -14.45 -14.45 -14.45 -26.02 -26.01 -26.01 -26.01 -14.45 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -14.45 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -43.01 -43.01 -43.01 -43.01 -43.01 -43.01 -43.04 -45.18 -43.03 -26.01 -26.01 -26.01 -26.02 -26.01 -26.02 -26.02 -43.02 -45.18 -45.18 -45.18 -43.01 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -43.01 -34.32 -26.02 -14.45 -14.45 -14.45 -14.46 -14.46 -45.18 -45.18 -0.01 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -26.01 -45.18 -43.01 -45.18 -45.18 -45.18 -45.18 -26.01 -26.01 -14.45 -14.45 -14.45 -14.45 -26.01 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -43.02 -43.01 -43.01 -43.01 -14.45 -14.45 -14.45 -14.47 -14.46 -0.01 -0.01 -0.01 -0.01 -0.02 -0.01 -14.45 -43.03 -43.01 -43.01 -43.01 -45.18 -45.18 -45.18 -45.18 -45.18 -26.01 -26.01 -26.02 -43.01 -26.01 -26.01 -45.18 -26.02 -14.46 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -45.18 -45.18 -43.01 -45.18 -43.02 -43.01 -43.01 -43.01 -14.45 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.05 -0.04 -0.02 -0.0 -0.01 -0.04 -0.02 -14.45 -14.45 -26.02 -45.18 -45.18 -26.02 -26.02 -26.03 -26.03 -26.01 -26.01 -26.01 -43.01 -43.01 -45.18 -45.18 -26.02 -26.01 -26.01 -14.45 -14.45 -14.45 -45.18 -45.18 -45.18 -45.18 -57.37 -57.37 -57.37 -57.37 -57.37 -57.37 -45.19 -45.19 -45.19 -45.19 -45.19 -45.19 -45.19 -45.19 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -57.37 -45.19 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -45.19 -45.19 -57.37 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -60.17 -60.17 -72.01 -60.17 -60.17 -57.37 -45.19 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -43.01 -43.01 -14.45 -14.45 -14.45 -14.46 -14.46 -43.02 -43.01 -14.46 -14.46 -14.46 -14.46 -14.45 -0.01 -0.01 -0.01 -0.01 -0.01 -0.01 -0.01 -0.01 -0.05 -0.02 -0.01 -0.01 -0.05 -0.01 -0.01 -0.01 -0.02 -14.45 -14.45 -0.04 -0.02 -0.01 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.01 -0.01 -14.45 -14.45 -14.46 -14.46 -14.46 -14.45 -14.45 -14.45 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -14.45 -14.46 -14.46 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -26.01 -26.01 -43.01 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -45.19 -45.19 -45.19 -45.18 -45.18 -26.01 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -26.03 -14.45 -0.02 -0.0 -0.01 -0.0 -0.0 -0.0 -0.0 -0.0 -26.02 -26.01 -26.02 -26.02 -26.02 -14.45 -14.45 -14.45 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -14.45 -14.45 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -14.45 -14.45 -14.45 -26.02 -45.18 -43.01 -43.01 -26.01 -14.45 -14.45 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -14.45 -14.45 -14.45 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -14.45 -14.45 -14.45 -14.45 -14.45 -0.02 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -14.45 -14.45 -14.45 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.01 -0.01 -0.01 -0.0 -0.0 -0.0 -0.01 -0.01 -14.45 -14.45 -14.45 -14.45 -14.46 -14.46 -14.46 -14.45 -0.01 -0.01 -0.0 -0.01 -0.0 -0.0 -0.0 -0.02 -0.01 -0.01 -0.0 -0.0 -0.0 -0.01 -0.01 -0.01 -14.45 -26.01 -26.04 -45.18 -45.18 -45.18 -26.02 -26.01 -26.02 -43.01 -43.01 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -26.03 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -26.02 -26.01 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -14.45 -26.01 -26.01 -26.01 -26.01 -26.01 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -14.45 -14.45 -43.01 -45.18 -45.18 -45.18 -83.49 -103.95 -103.96 -103.94 -86.3 -103.95 -86.3 -83.48 -73.61 -73.62 -73.61 -72.01 -72.01 -60.17 -68.57 -73.62 -68.57 -60.17 -45.18 -45.18 -45.18 -45.18 -57.37 -45.19 -72.01 -83.48 -103.94 -86.3 -86.3 -86.3 -83.49 -72.01 -72.01 -68.57 -72.01 -72.01 -68.57 -72.01 -72.01 -86.3 -103.95 -103.95 -68.57 -73.61 -83.48 -73.61 -73.61 -86.3 -137.56 -137.56 -141.96 -150.0 -150.0 -141.96 -150.0 -124.41 -86.3 -86.3 -103.94 -83.49 -83.49 -83.49 -83.48 -86.3 -89.33 -103.95 -86.3 -83.48 -73.61 -73.61 -105.28 -124.41 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -141.96 -124.41 -104.47 -104.47 -137.56 -141.96 -150.0 -150.0 -119.92 -86.3 -83.48 -83.48 -86.3 -86.3 -105.28 -137.56 -141.96 -141.96 -104.47 -105.28 -45.18 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -14.46 -14.46 -14.45 -14.45 -14.46 -14.45 -14.45 -14.46 -14.46 -26.02 -14.45 -0.01 -0.01 -0.0 -0.0 -0.0 -0.0 -0.01 -14.45 -14.46 -26.02 -26.02 -26.01 -26.02 -26.02 -26.05 -45.18 -26.01 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.2 -60.17 -103.95 -103.96 -104.47 -103.95 -103.96 -103.94 -103.95 -60.17 -60.17 -45.19 -45.19 -45.19 -45.19 -45.19 -45.18 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -45.19 -57.37 -45.18 -45.18 -45.18 -45.18 -14.49 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -14.53 -26.02 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -14.46 -14.45 -0.04 -0.04 -0.04 -14.45 -14.45 -14.45 -45.18 -14.46 -26.01 -26.01 -26.01 -26.01 -45.18 -45.18 -26.01 -26.01 -26.01 -14.45 -14.45 -14.45 -0.01 -0.01 -0.01 -0.01 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.01 -14.45 -14.45 -14.45 -14.45 -14.45 -14.47 -14.47 -14.47 -14.45 -14.45 -0.01 -0.01 -0.01 -0.0 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -14.47 -43.01 -45.18 -45.18 -45.19 -45.19 -60.17 -60.17 -60.17 -73.61 -73.61 -45.19 -45.19 -45.19 -60.17 -60.17 -119.92 -150.0 -150.0 -150.0 -103.96 -118.57 -118.57 -118.57 -118.57 -118.57 -150.0 -150.0 -150.0 -103.95 -83.48 -83.48 -60.17 -86.3 -68.57 -57.37 -57.37 -45.21 -45.21 -45.22 -103.95 -137.56 -137.56 -105.28 -68.57 -73.61 -83.48 -68.57 -83.48 -83.49 -118.57 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -124.41 -118.57 -103.97 -103.98 -86.3 -72.01 -60.17 -60.17 -60.17 -86.3 -68.57 -105.28 -105.28 -68.57 -68.57 -86.3 -86.3 -60.17 -60.17 -60.17 -86.3 -86.3 -86.3 -86.3 -103.94 -60.17 -60.17 -60.17 -60.17 -72.01 -60.17 -72.01 -103.95 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -124.41 -103.98 -105.28 -103.97 -105.28 -105.28 -124.41 -124.41 -137.56 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -141.96 -118.57 -103.96 -118.57 -118.58 -105.28 -60.17 -60.17 -60.17 -103.94 -105.28 -105.28 -105.28 -105.28 -119.92 -118.57 -103.94 -103.94 -86.3 -60.17 -83.48 -60.17 -60.17 -45.19 -45.19 -45.18 -45.19 -45.19 -45.19 -45.19 -57.37 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -43.03 -43.02 -36.54 -14.46 -14.45 -14.46 -14.45 -14.46 -14.46 -45.18 -45.18 -43.01 -14.46 -14.46 -45.18 -14.45 -14.45 -14.46 -14.45 -14.45 -14.45 -14.46 -14.45 -14.45 -14.45 -14.45 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -14.45 -0.0 -0.0 -0.0 -0.0 -0.0 -0.01 -14.45 -14.45 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -43.04 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -43.01 -43.01 -43.01 -45.18 -45.18 -45.18 -43.01 -43.04 -45.18 -45.18 -45.18 -45.19 -45.18 -45.19 -45.19 -57.37 -60.17 -73.61 -73.61 -103.94 -103.94 -105.28 -103.94 -105.28 -105.28 -103.94 -73.61 -68.57 -73.61 -68.57 -68.57 -60.17 -73.61 -68.57 -60.17 -57.37 -45.19 -45.19 -45.19 -45.21 -45.2 -45.2 -60.17 -57.37 -45.19 -57.37 -45.18 -45.18 -45.18 -14.45 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.03 -14.45 -14.45 -14.45 -14.45 -45.18 -26.02 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -26.01 -26.01 -26.01 -26.01 -45.18 -45.18 -45.18 -45.18 -45.18 -26.01 -26.01 -26.01 -43.01 -45.18 -45.18 -26.02 -26.01 -26.01 -14.45 -14.45 -0.01 -14.45 -0.01 -0.01 -0.01 -0.01 -0.0 -0.01 -0.01 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -14.45 -26.01 -26.01 -26.02 -43.01 -45.18 -45.18 -26.04 -26.04 -26.01 -26.02 -45.18 -45.18 -26.04 -26.04 -43.01 -45.18 -45.18 -14.51 -43.01 -14.53 -14.52 -14.45 -14.45 -14.46 -43.02 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -45.18 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -57.37 -45.19 -45.19 -45.18 -45.18 -45.18 -45.18 -45.19 -45.19 -57.37 -45.19 -45.19 -45.19 -45.19 -45.19 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -45.19 -57.37 -57.37 -45.19 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -26.01 -14.46 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -26.01 -26.01 -26.01 -26.02 -26.01 -14.46 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -0.05 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -0.06 -45.18 -26.03 -26.01 -26.01 -26.01 -45.18 -43.02 -34.32 -26.01 -14.45 -14.45 -0.02 -0.01 -0.01 -0.02 -0.02 -0.02 -14.45 -14.45 -14.47 -45.18 -14.47 -26.01 -26.02 -45.18 -45.18 -45.18 -45.19 -45.19 -45.19 -45.19 -45.18 -45.18 -45.18 -45.18 -43.04 -43.01 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -14.45 -14.45 -45.18 -45.18 -45.18 -43.02 -43.02 -45.18 -26.02 -26.02 -26.02 -26.01 -45.18 -26.01 -26.01 -26.01 -45.18 -45.18 -45.18 -45.18 -26.01 -43.01 -45.18 -45.18 -45.19 -73.61 -68.57 -60.17 -60.17 -60.17 -60.17 -68.57 -45.21 -45.21 -45.19 -45.19 -45.19 -45.18 -45.18 -45.18 -45.18 -45.2 -45.19 -45.19 -45.19 -45.19 -60.17 -83.48 -137.56 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -68.57 -60.17 -45.19 -45.18 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -14.45 -14.45 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -14.45 -14.45 -14.45 -0.0 -14.45 -14.45 -0.0 -0.0 -0.01 -14.45 -0.02 -0.02 -14.45 -14.45 -14.45 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -60.17 -86.3 -83.48 -73.61 -68.57 -73.61 -86.3 -118.57 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -124.41 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -137.6 -119.92 -119.92 -118.58 -120.93 -150.0 -105.28 -118.57 -141.96 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -118.58 -118.59 -103.94 -73.61 -60.17 -60.17 -60.17 -45.19 -45.19 -45.19 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -45.19 -60.17 -60.17 -83.48 -83.48 -105.28 -105.28 -68.57 -60.17 -68.57 -57.37 -57.37 -45.19 -45.19 -45.19 -45.18 -45.19 -86.3 -86.3 -60.17 -45.19 -45.19 -45.19 -45.19 -45.19 -83.5 -83.53 -83.48 -86.3 -86.3 -68.57 -57.37 -45.18 -45.18 -14.45 -14.45 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.05 -0.0 -0.0 -0.0 -0.0 -0.02 -0.02 -0.02 -14.45 -14.45 -0.05 -0.02 -14.45 -0.01 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.01 -14.45 -14.45 -0.0 -0.0 -0.02 -14.45 -0.0 -14.45 -14.45 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -43.01 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -43.02 -43.02 -26.03 -26.03 -26.01 -43.02 -43.01 -26.01 -26.01 -14.46 -14.46 -14.46 -26.02 -14.45 -14.49 -14.45 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.01 -0.01 -0.0 -0.0 -0.0 -14.45 -14.45 -14.45 -14.46 -14.46 -14.46 -14.46 -14.45 -14.45 -0.01 -0.01 -0.01 -0.02 -0.0 -0.0 -14.45 -26.02 -26.01 -14.45 -14.46 -14.46 -14.46 -45.18 -45.18 -45.19 -83.48 -86.3 -83.48 -83.48 -86.3 -83.48 -86.3 -105.28 -86.3 -86.3 -86.3 -86.3 -60.17 -45.19 -60.17 -105.28 -60.17 -57.37 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -45.19 -45.19 -45.18 -45.18 -45.18 -45.18 -43.02 -14.46 -26.02 -26.04 -26.03 -26.02 -14.46 -14.46 -14.46 -14.46 -14.46 -14.47 -14.47 -26.01 -26.01 -45.18 -14.48 -26.01 -26.04 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -26.01 -26.01 -26.01 -14.46 -14.46 -14.46 -14.46 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -72.01 -105.28 -105.28 -57.37 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -57.37 -60.17 -60.17 -83.48 -124.41 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -124.41 -105.28 -105.28 -118.57 -141.96 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -118.57 -103.97 -104.5 -103.94 -60.17 -45.19 -57.37 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -45.2 -45.19 -45.18 -45.19 -105.28 -103.95 -105.28 -118.57 -118.57 -103.96 -137.56 -118.57 -104.47 -104.5 -103.94 -60.17 -45.18 -45.18 -45.18 -14.46 -14.46 -14.46 -14.46 -14.46 -45.18 -45.18 -43.01 -43.02 -14.48 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -43.01 -43.01 -43.01 -43.01 -43.02 -43.02 -14.46 -14.46 -14.46 -45.18 -14.46 -14.46 -43.01 -43.02 -43.01 -43.04 -43.01 -43.04 -45.18 -45.18 -45.2 -57.37 -45.19 -57.37 -57.37 -57.37 -45.19 -45.19 -45.19 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -45.19 -45.2 -45.21 -45.19 -45.19 -45.19 -45.19 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -43.01 -43.01 -14.45 -14.45 -14.45 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -14.45 -14.46 -14.46 -14.45 -14.45 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -60.17 -60.17 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -0.0 -0.0 -0.0 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -14.46 -26.01 -43.02 -43.01 -43.01 -45.18 -45.18 -45.18 -26.04 -45.18 -26.02 -26.02 -26.01 -26.01 -26.02 -26.02 -26.04 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -57.37 -83.48 -60.17 -60.17 -83.48 -83.48 -60.17 -60.17 -60.17 -60.17 -60.17 -60.17 -60.17 -60.17 -45.19 -45.19 -45.19 -103.95 -150.0 -141.96 -137.56 -137.56 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -141.96 -105.28 -103.94 -83.48 -83.48 -83.48 -83.48 -86.3 -89.34 -105.28 -141.96 -141.96 -105.28 -104.0 -104.0 -105.28 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -103.96 -105.28 -103.96 -105.28 -104.47 -118.57 -150.0 -150.0 -150.0 -137.56 -86.3 -86.3 -86.3 -141.96 -150.0 -150.0 -150.0 -150.0 -150.0 -141.96 -104.47 -86.31 -68.57 -45.18 -45.18 -43.02 -26.01 -14.45 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.01 -26.01 -14.45 -0.01 -14.45 -14.45 -0.01 -0.01 -0.02 -0.01 -0.0 -0.0 -0.0 -0.0 -0.0 -0.01 -0.01 -0.01 -0.01 -0.0 -0.0 -0.01 -0.02 -0.01 -0.01 -43.02 -14.46 -14.45 -26.02 -26.03 -26.03 -26.02 -26.01 -26.01 -26.02 -26.02 -26.01 -43.01 -14.46 -14.46 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -60.17 -57.37 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.19 -86.3 -103.95 -103.96 -119.92 -105.28 -103.94 -103.96 -105.28 -105.28 -86.3 -83.49 -86.31 -86.31 -103.94 -103.96 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -150.0 -141.96 -103.96 -83.48 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -43.01 -43.02 -14.46 -14.46 -14.46 -43.01 -43.01 -43.01 -43.01 -45.18 -26.03 -34.32 -43.02 -43.01 -43.04 -45.18 -14.46 -45.18 -45.18 -45.18 -26.02 -26.01 -26.01 -26.02 -45.18 -26.01 -26.01 -26.02 -45.18 -45.18 -45.19 -45.19 -45.19 -45.18 -45.18 -45.18 -45.18 -45.19 -45.18 -45.2 -45.19 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -45.18 -14.45 -14.45 -14.45 -14.45 -14.45 -0.01 -0.01 -0.01 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.01 -14.45 -14.46 -14.46 -14.46 -14.45 -14.45 -14.47 -14.46 -14.45 -14.46 -14.46 -26.01 -26.01 -26.01 -26.01 -26.02 -26.02 -26.02 -26.02 -26.01 -26.02 -26.04 -26.04 -26.04 -26.02 -26.02 -26.02 -26.01 -14.49 -14.48 -14.45 -14.45 -0.02 -0.02 -0.01 -0.01 -14.45 -26.02 -14.45 -14.45 -0.01 -14.45 -0.01 -0.01 -0.01 -14.45 -0.01 -0.01 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -0.01 -0.01 -0.01 -0.01 -0.01 -0.01 -0.02 -0.02 -0.02 -0.01 -0.01 -0.01 -0.02 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -14.45 -0.02 -14.45 -14.45 -14.45 -0.01 -0.01 -0.01 -0.0 -0.0 -0.0 -0.01 -0.02 -14.45 -14.45 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -45.18 -60.17 -45.18 -45.18 -45.18 -45.18 -43.01 -14.46 -14.46 -14.45 -14.45 -14.45 -14.45 -14.45 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.01 -0.0 -14.45 -0.01 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.02 -0.01 -0.02 -0.01 -0.01 -0.01 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.0 -0.02 -0.01 -0.02 -0.01 -0.01 -0.01 -0.0 -0.0 \ No newline at end of file diff --git a/examples/excel_to_scenario.ipynb b/examples/excel_to_scenario.ipynb deleted file mode 100644 index dcddc81..0000000 --- a/examples/excel_to_scenario.ipynb +++ /dev/null @@ -1,196 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "42081dd2", - "metadata": {}, - "source": [ - "This is still a testing workbook to demonstrate progress on the excel to scenario flows." - ] - }, - { - "cell_type": "markdown", - "id": "386ce0b0", - "metadata": {}, - "source": [ - "# Curves" - ] - }, - { - "cell_type": "code", - "execution_count": 1, - "id": "c617dc0a", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Found 3 curve files\n", - "✓ Loaded curve 'interconnector_8_price': 8760 values\n", - "✓ Loaded curve 'electric_vehicle_profile_5': 8760 values\n", - "✓ Loaded curve 'agriculture_electricity': 8760 values\n", - "Created DataFrame with 3 curves and 8760 rows\n" - ] - } - ], - "source": [ - "# For now a custom csv to pd df function - this will be handled by the reverse packer in the end\n", - "\n", - "import pandas as pd\n", - "from pathlib import Path\n", - "from typing import Union\n", - "\n", - "def read_curves_to_dataframe(\n", - " curves_path: Union[str, Path],\n", - " pattern: str = \"*.csv\",\n", - " validate_length: bool = True\n", - ") -> pd.DataFrame:\n", - " \"\"\"\n", - " Read multiple curve CSV files into a single DataFrame.\n", - "\n", - " Args:\n", - " curves_path: Directory path containing the curve CSV files\n", - " pattern: File pattern to match (default: \"*.csv\")\n", - " validate_length: Whether to validate each curve has exactly 8760 values\n", - "\n", - " Returns:\n", - " DataFrame with curves as columns, where column names are the curve keys\n", - " (derived from filenames without extension)\n", - "\n", - " Raises:\n", - " ValueError: If validation fails or files have issues\n", - " FileNotFoundError: If no files found matching the pattern\n", - " \"\"\"\n", - " curves_path = Path(curves_path)\n", - "\n", - " if not curves_path.exists():\n", - " raise FileNotFoundError(f\"Directory not found: {curves_path}\")\n", - "\n", - " # Find all CSV files matching the pattern\n", - " csv_files = list(curves_path.glob(pattern))\n", - "\n", - " if not csv_files:\n", - " raise FileNotFoundError(f\"No files found matching pattern '{pattern}' in {curves_path}\")\n", - "\n", - " print(f\"Found {len(csv_files)} curve files\")\n", - "\n", - " curves_data = {}\n", - " errors = []\n", - "\n", - " for csv_file in csv_files:\n", - " # Use filename (without extension) as curve key, remove _curve suffix if present\n", - " curve_key = csv_file.stem\n", - " if curve_key.endswith('_curve'):\n", - " curve_key = curve_key[:-6] # Remove '_curve' suffix\n", - "\n", - " try:\n", - " # Read CSV file - assuming single column of values, no headers\n", - " curve_data = pd.read_csv(\n", - " csv_file,\n", - " header=None, # No header row\n", - " index_col=False, # No index column\n", - " dtype=float # All values should be numeric\n", - " )\n", - "\n", - " # Convert DataFrame to Series if single column\n", - " if isinstance(curve_data, pd.DataFrame):\n", - " if len(curve_data.columns) == 1:\n", - " curve_data = curve_data.iloc[:, 0]\n", - " else:\n", - " errors.append(f\"{curve_key}: Expected 1 column, found {len(curve_data.columns)}\")\n", - " continue\n", - "\n", - " # Drop any NaN values\n", - " curve_data = curve_data.dropna()\n", - "\n", - " # Validate length if requested\n", - " if validate_length and len(curve_data) != 8760:\n", - " errors.append(f\"{curve_key}: Expected 8760 values, found {len(curve_data)}\")\n", - " continue\n", - "\n", - " # Store with curve key as column name\n", - " curves_data[curve_key] = curve_data.values\n", - " print(f\"✓ Loaded curve '{curve_key}': {len(curve_data)} values\")\n", - "\n", - " except Exception as e:\n", - " errors.append(f\"{curve_key}: Error reading file - {str(e)}\")\n", - " continue\n", - "\n", - " if errors:\n", - " error_msg = \"Errors reading curve files:\\n\" + \"\\n\".join(f\" - {err}\" for err in errors)\n", - " if not curves_data: # No curves loaded successfully\n", - " raise ValueError(error_msg)\n", - " else:\n", - " print(f\"Warning: Some curves failed to load:\\n{error_msg}\")\n", - "\n", - " if not curves_data:\n", - " raise ValueError(\"No curves were successfully loaded\")\n", - "\n", - " # Create DataFrame from the curves\n", - " df = pd.DataFrame(curves_data)\n", - "\n", - " # Set index to represent hours (0-8759 for a full year)\n", - " df.index.name = \"hour\"\n", - "\n", - " print(f\"Created DataFrame with {len(df.columns)} curves and {len(df)} rows\")\n", - " return df\n", - "\n", - "# User uploads Excel/CSV → DataFrame → CustomCurves object\n", - "from pyetm.models.custom_curves import CustomCurves\n", - "\n", - "df = read_curves_to_dataframe(\"curve_examples/\")\n", - "custom_curves = CustomCurves._from_dataframe(df)" - ] - }, - { - "cell_type": "code", - "execution_count": 2, - "id": "e75a03b2", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Environment setup complete\n", - " Using ETM API at http://localhost:3000/api/v3\n", - " Token loaded? True\n", - "API connection ready\n" - ] - } - ], - "source": [ - "from example_helpers import setup_notebook\n", - "from pyetm.models import Scenario\n", - "\n", - "setup_notebook()\n", - "scenario = Scenario.load(2690288)\n", - "\n", - "# Update curves on scenario\n", - "scenario.update_custom_curves(custom_curves)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "pyetm-qKH2ozgc", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.9" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/examples/excel_to_scenarios.ipynb b/examples/excel_to_scenarios.ipynb new file mode 100644 index 0000000..20e681b --- /dev/null +++ b/examples/excel_to_scenarios.ipynb @@ -0,0 +1,1474 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "70d54062", + "metadata": {}, + "source": [ + "This notebook is for demonstrating and testing the excel to scenarios flow.\n", + "\n", + "Currently can only handle metadata and inputs." + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "id": "4866f9d1", + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Environment setup complete\n", + " Using ETM API at http://localhost:3000/api/v3\n", + " Token loaded? True\n", + "API connection ready\n" + ] + }, + { + "name": "stderr", + "output_type": "stream", + "text": [ + "/Users/louisparkes-talbot/Desktop/local_model/pyetm/src/pyetm/models/scenario.py:206: FutureWarning: Downcasting object dtype arrays on .fillna, .ffill, .bfill is deprecated and will change in a future version. Call result.infer_objects(copy=False) instead. To opt-in to the future behavior, set `pd.set_option('future.no_silent_downcasting', True)`\n", + " self.update_user_values(series.fillna(\"reset\").to_dict())\n" + ] + }, + { + "data": { + "text/plain": [ + "{'total_scenarios': 2,\n", + " 'inputs': {'scenario_count': 2},\n", + " 'sortables': {'scenario_count': 2},\n", + " 'custom_curves': {'scenario_count': 2},\n", + " 'output_curves': {'scenario_count': 2},\n", + " 'scenario_ids': [2690555, 2690637]}" + ] + }, + "execution_count": 5, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "from example_helpers import setup_notebook\n", + "from pyetm.models.scenario_packer import ScenarioPacker\n", + "\n", + "setup_notebook()\n", + "packer = ScenarioPacker.from_excel(\"my_input_excel.xlsx\")\n", + "packer.get_summary()" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "id": "8205cd53", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
scen_ascen_b
useruser
inputunit
climate_relevant_co2_biomass_gas_future%30.035.0
climate_relevant_co2_biomass_gas_present%20.0None
climate_relevant_co2_biomass_liquid_future%30.0None
climate_relevant_co2_biomass_liquid_present%20.0None
climate_relevant_co2_biomass_solid_future%30.0None
............
capacity_of_energy_battery_wind_turbine_inlandMWNaN0.0
capacity_of_energy_power_hybrid_wind_turbine_offshoreMWNaNNone
capacity_of_energy_power_wind_turbine_coastalMWNaN0.0
capacity_of_energy_power_wind_turbine_inlandMWNaN20000.0
capacity_of_energy_power_wind_turbine_offshoreMWNaN52000.0
\n", + "

1318 rows × 2 columns

\n", + "
" + ], + "text/plain": [ + " scen_a scen_b\n", + " user user\n", + "input unit \n", + "climate_relevant_co2_biomass_gas_future % 30.0 35.0\n", + "climate_relevant_co2_biomass_gas_present % 20.0 None\n", + "climate_relevant_co2_biomass_liquid_future % 30.0 None\n", + "climate_relevant_co2_biomass_liquid_present % 20.0 None\n", + "climate_relevant_co2_biomass_solid_future % 30.0 None\n", + "... ... ...\n", + "capacity_of_energy_battery_wind_turbine_inland MW NaN 0.0\n", + "capacity_of_energy_power_hybrid_wind_turbine_of... MW NaN None\n", + "capacity_of_energy_power_wind_turbine_coastal MW NaN 0.0\n", + "capacity_of_energy_power_wind_turbine_inland MW NaN 20000.0\n", + "capacity_of_energy_power_wind_turbine_offshore MW NaN 52000.0\n", + "\n", + "[1318 rows x 2 columns]" + ] + }, + "execution_count": 6, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "packer.inputs()" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "id": "cd08ff26", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
A: Create from excelB: Load a scenario by id
forecast_storagehydrogen_supplyhydrogen_demandspace_heatingheat_network_ltheat_network_mtheat_network_htforecast_storagehydrogen_supplyhydrogen_demandspace_heatingheat_network_ltheat_network_mtheat_network_ht
sortables
0households_flexibility_p2p_electricityenergy_hydrogen_storage_depleted_gas_fieldenergy_hydrogen_storage_depleted_gas_fieldhouseholds_space_heater_district_heating_lt_st...energy_heat_network_storage_lt_steam_hot_waterenergy_heat_network_storage_mt_steam_hot_waterenergy_heat_network_storage_ht_steam_hot_waterenergy_flexibility_pumped_storage_electricityenergy_hydrogen_storage_depleted_gas_fieldenergy_hydrogen_storage_depleted_gas_fieldhouseholds_space_heater_district_heating_lt_st...energy_heat_network_storage_lt_steam_hot_waterenergy_heat_network_storage_mt_steam_hot_waterenergy_heat_network_storage_ht_steam_hot_water
1energy_flexibility_mv_batteries_electricityenergy_hydrogen_storage_salt_cavernenergy_hydrogen_storage_salt_cavernhouseholds_space_heater_heatpump_surface_water...energy_heat_boiler_lt_electricityenergy_heat_boiler_mt_electricityenergy_heat_boiler_ht_electricitytransport_van_flexibility_p2p_electricityenergy_hydrogen_storage_salt_cavernenergy_hydrogen_storage_salt_cavernhouseholds_space_heater_heatpump_surface_water...energy_heat_boiler_lt_electricityenergy_heat_boiler_mt_electricityenergy_heat_boiler_ht_electricity
2transport_car_flexibility_p2p_electricityenergy_hydrogen_autothermal_reformer_dispatchableNonehouseholds_space_heater_heatpump_air_water_ele...energy_heat_burner_lt_hydrogenenergy_heat_burner_mt_coalenergy_heat_burner_ht_coaltransport_truck_flexibility_p2p_electricityenergy_hydrogen_autothermal_reformer_dispatchableNonehouseholds_space_heater_heatpump_air_water_ele...energy_heat_burner_lt_hydrogenenergy_heat_burner_mt_coalenergy_heat_burner_ht_coal
3energy_flexibility_flow_batteries_electricityenergy_hydrogen_steam_methane_reformer_dispatc...Nonehouseholds_space_heater_heatpump_ground_water_...energy_heat_heatpump_water_water_lt_electricityenergy_heat_burner_mt_crude_oilenergy_heat_burner_ht_crude_oiltransport_bus_flexibility_p2p_electricityenergy_hydrogen_steam_methane_reformer_dispatc...Nonehouseholds_space_heater_heatpump_ground_water_...energy_heat_heatpump_water_water_lt_electricityenergy_heat_burner_mt_crude_oilenergy_heat_burner_ht_crude_oil
4energy_flexibility_hv_opac_electricityenergy_hydrogen_ammonia_reformer_dispatchableNonehouseholds_space_heater_heatpump_pvt_electricityenergy_heat_heatpump_surface_water_water_ts_lt...energy_heat_burner_mt_hydrogenenergy_heat_burner_ht_hydrogenenergy_flexibility_hv_opac_electricityenergy_hydrogen_ammonia_reformer_dispatchableNonehouseholds_space_heater_heatpump_pvt_electricityenergy_heat_heatpump_surface_water_water_ts_lt...energy_heat_burner_mt_hydrogenenergy_heat_burner_ht_hydrogen
5transport_bus_flexibility_p2p_electricityNoneNonehouseholds_space_heater_district_heating_mt_st...energy_heat_heatpump_waste_water_water_ts_lt_e...energy_heat_burner_mt_network_gasenergy_heat_burner_ht_network_gasenergy_flexibility_flow_batteries_electricityNoneNonehouseholds_space_heater_district_heating_mt_st...energy_heat_heatpump_waste_water_water_ts_lt_e...energy_heat_burner_mt_network_gasenergy_heat_burner_ht_network_gas
6transport_truck_flexibility_p2p_electricityNoneNonehouseholds_space_heater_hybrid_heatpump_air_wa...energy_heat_heatpump_drink_water_water_ts_lt_e...energy_heat_burner_mt_waste_mixenergy_heat_burner_ht_waste_mixtransport_car_flexibility_p2p_electricityNoneNonehouseholds_space_heater_hybrid_heatpump_air_wa...energy_heat_heatpump_drink_water_water_ts_lt_e...energy_heat_burner_mt_waste_mixenergy_heat_burner_ht_waste_mix
7transport_van_flexibility_p2p_electricityNoneNonehouseholds_space_heater_hybrid_hydrogen_heatpu...Noneenergy_heat_burner_mt_wood_pelletsenergy_heat_burner_ht_wood_pelletsenergy_flexibility_mv_batteries_electricityNoneNonehouseholds_space_heater_hybrid_hydrogen_heatpu...Noneenergy_heat_burner_mt_wood_pelletsenergy_heat_burner_ht_wood_pellets
8energy_flexibility_pumped_storage_electricityNoneNonehouseholds_space_heater_hybrid_crude_oil_heatp...Noneenergy_heat_heatpump_water_water_mt_electricityenergy_heat_heatpump_water_water_ht_electricityhouseholds_flexibility_p2p_electricityNoneNonehouseholds_space_heater_hybrid_crude_oil_heatp...Noneenergy_heat_heatpump_water_water_mt_electricityenergy_heat_heatpump_water_water_ht_electricity
9NoneNoneNonehouseholds_space_heater_district_heating_ht_st...Noneenergy_heat_heatpump_surface_water_water_ts_mt...NoneNoneNoneNonehouseholds_space_heater_district_heating_ht_st...Noneenergy_heat_heatpump_surface_water_water_ts_mt...None
10NoneNoneNonehouseholds_space_heater_electricityNoneenergy_heat_heatpump_waste_water_water_ts_mt_e...NoneNoneNoneNonehouseholds_space_heater_electricityNoneenergy_heat_heatpump_waste_water_water_ts_mt_e...None
11NoneNoneNonehouseholds_space_heater_combined_network_gasNoneenergy_heat_heatpump_drink_water_water_ts_mt_e...NoneNoneNoneNonehouseholds_space_heater_combined_network_gasNoneenergy_heat_heatpump_drink_water_water_ts_mt_e...None
12NoneNoneNonehouseholds_space_heater_combined_hydrogenNoneNoneNoneNoneNoneNonehouseholds_space_heater_combined_hydrogenNoneNoneNone
13NoneNoneNonehouseholds_space_heater_wood_pelletsNoneNoneNoneNoneNoneNonehouseholds_space_heater_wood_pelletsNoneNoneNone
14NoneNoneNonehouseholds_space_heater_network_gasNoneNoneNoneNoneNoneNonehouseholds_space_heater_network_gasNoneNoneNone
15NoneNoneNonehouseholds_space_heater_coalNoneNoneNoneNoneNoneNonehouseholds_space_heater_coalNoneNoneNone
16NoneNoneNonehouseholds_space_heater_crude_oilNoneNoneNoneNoneNoneNonehouseholds_space_heater_crude_oilNoneNoneNone
\n", + "
" + ], + "text/plain": [ + " A: Create from excel \\\n", + " forecast_storage \n", + "sortables \n", + "0 households_flexibility_p2p_electricity \n", + "1 energy_flexibility_mv_batteries_electricity \n", + "2 transport_car_flexibility_p2p_electricity \n", + "3 energy_flexibility_flow_batteries_electricity \n", + "4 energy_flexibility_hv_opac_electricity \n", + "5 transport_bus_flexibility_p2p_electricity \n", + "6 transport_truck_flexibility_p2p_electricity \n", + "7 transport_van_flexibility_p2p_electricity \n", + "8 energy_flexibility_pumped_storage_electricity \n", + "9 None \n", + "10 None \n", + "11 None \n", + "12 None \n", + "13 None \n", + "14 None \n", + "15 None \n", + "16 None \n", + "\n", + " \\\n", + " hydrogen_supply \n", + "sortables \n", + "0 energy_hydrogen_storage_depleted_gas_field \n", + "1 energy_hydrogen_storage_salt_cavern \n", + "2 energy_hydrogen_autothermal_reformer_dispatchable \n", + "3 energy_hydrogen_steam_methane_reformer_dispatc... \n", + "4 energy_hydrogen_ammonia_reformer_dispatchable \n", + "5 None \n", + "6 None \n", + "7 None \n", + "8 None \n", + "9 None \n", + "10 None \n", + "11 None \n", + "12 None \n", + "13 None \n", + "14 None \n", + "15 None \n", + "16 None \n", + "\n", + " \\\n", + " hydrogen_demand \n", + "sortables \n", + "0 energy_hydrogen_storage_depleted_gas_field \n", + "1 energy_hydrogen_storage_salt_cavern \n", + "2 None \n", + "3 None \n", + "4 None \n", + "5 None \n", + "6 None \n", + "7 None \n", + "8 None \n", + "9 None \n", + "10 None \n", + "11 None \n", + "12 None \n", + "13 None \n", + "14 None \n", + "15 None \n", + "16 None \n", + "\n", + " \\\n", + " space_heating \n", + "sortables \n", + "0 households_space_heater_district_heating_lt_st... \n", + "1 households_space_heater_heatpump_surface_water... \n", + "2 households_space_heater_heatpump_air_water_ele... \n", + "3 households_space_heater_heatpump_ground_water_... \n", + "4 households_space_heater_heatpump_pvt_electricity \n", + "5 households_space_heater_district_heating_mt_st... \n", + "6 households_space_heater_hybrid_heatpump_air_wa... \n", + "7 households_space_heater_hybrid_hydrogen_heatpu... \n", + "8 households_space_heater_hybrid_crude_oil_heatp... \n", + "9 households_space_heater_district_heating_ht_st... \n", + "10 households_space_heater_electricity \n", + "11 households_space_heater_combined_network_gas \n", + "12 households_space_heater_combined_hydrogen \n", + "13 households_space_heater_wood_pellets \n", + "14 households_space_heater_network_gas \n", + "15 households_space_heater_coal \n", + "16 households_space_heater_crude_oil \n", + "\n", + " \\\n", + " heat_network_lt \n", + "sortables \n", + "0 energy_heat_network_storage_lt_steam_hot_water \n", + "1 energy_heat_boiler_lt_electricity \n", + "2 energy_heat_burner_lt_hydrogen \n", + "3 energy_heat_heatpump_water_water_lt_electricity \n", + "4 energy_heat_heatpump_surface_water_water_ts_lt... \n", + "5 energy_heat_heatpump_waste_water_water_ts_lt_e... \n", + "6 energy_heat_heatpump_drink_water_water_ts_lt_e... \n", + "7 None \n", + "8 None \n", + "9 None \n", + "10 None \n", + "11 None \n", + "12 None \n", + "13 None \n", + "14 None \n", + "15 None \n", + "16 None \n", + "\n", + " \\\n", + " heat_network_mt \n", + "sortables \n", + "0 energy_heat_network_storage_mt_steam_hot_water \n", + "1 energy_heat_boiler_mt_electricity \n", + "2 energy_heat_burner_mt_coal \n", + "3 energy_heat_burner_mt_crude_oil \n", + "4 energy_heat_burner_mt_hydrogen \n", + "5 energy_heat_burner_mt_network_gas \n", + "6 energy_heat_burner_mt_waste_mix \n", + "7 energy_heat_burner_mt_wood_pellets \n", + "8 energy_heat_heatpump_water_water_mt_electricity \n", + "9 energy_heat_heatpump_surface_water_water_ts_mt... \n", + "10 energy_heat_heatpump_waste_water_water_ts_mt_e... \n", + "11 energy_heat_heatpump_drink_water_water_ts_mt_e... \n", + "12 None \n", + "13 None \n", + "14 None \n", + "15 None \n", + "16 None \n", + "\n", + " \\\n", + " heat_network_ht \n", + "sortables \n", + "0 energy_heat_network_storage_ht_steam_hot_water \n", + "1 energy_heat_boiler_ht_electricity \n", + "2 energy_heat_burner_ht_coal \n", + "3 energy_heat_burner_ht_crude_oil \n", + "4 energy_heat_burner_ht_hydrogen \n", + "5 energy_heat_burner_ht_network_gas \n", + "6 energy_heat_burner_ht_waste_mix \n", + "7 energy_heat_burner_ht_wood_pellets \n", + "8 energy_heat_heatpump_water_water_ht_electricity \n", + "9 None \n", + "10 None \n", + "11 None \n", + "12 None \n", + "13 None \n", + "14 None \n", + "15 None \n", + "16 None \n", + "\n", + " B: Load a scenario by id \\\n", + " forecast_storage \n", + "sortables \n", + "0 energy_flexibility_pumped_storage_electricity \n", + "1 transport_van_flexibility_p2p_electricity \n", + "2 transport_truck_flexibility_p2p_electricity \n", + "3 transport_bus_flexibility_p2p_electricity \n", + "4 energy_flexibility_hv_opac_electricity \n", + "5 energy_flexibility_flow_batteries_electricity \n", + "6 transport_car_flexibility_p2p_electricity \n", + "7 energy_flexibility_mv_batteries_electricity \n", + "8 households_flexibility_p2p_electricity \n", + "9 None \n", + "10 None \n", + "11 None \n", + "12 None \n", + "13 None \n", + "14 None \n", + "15 None \n", + "16 None \n", + "\n", + " \\\n", + " hydrogen_supply \n", + "sortables \n", + "0 energy_hydrogen_storage_depleted_gas_field \n", + "1 energy_hydrogen_storage_salt_cavern \n", + "2 energy_hydrogen_autothermal_reformer_dispatchable \n", + "3 energy_hydrogen_steam_methane_reformer_dispatc... \n", + "4 energy_hydrogen_ammonia_reformer_dispatchable \n", + "5 None \n", + "6 None \n", + "7 None \n", + "8 None \n", + "9 None \n", + "10 None \n", + "11 None \n", + "12 None \n", + "13 None \n", + "14 None \n", + "15 None \n", + "16 None \n", + "\n", + " \\\n", + " hydrogen_demand \n", + "sortables \n", + "0 energy_hydrogen_storage_depleted_gas_field \n", + "1 energy_hydrogen_storage_salt_cavern \n", + "2 None \n", + "3 None \n", + "4 None \n", + "5 None \n", + "6 None \n", + "7 None \n", + "8 None \n", + "9 None \n", + "10 None \n", + "11 None \n", + "12 None \n", + "13 None \n", + "14 None \n", + "15 None \n", + "16 None \n", + "\n", + " \\\n", + " space_heating \n", + "sortables \n", + "0 households_space_heater_district_heating_lt_st... \n", + "1 households_space_heater_heatpump_surface_water... \n", + "2 households_space_heater_heatpump_air_water_ele... \n", + "3 households_space_heater_heatpump_ground_water_... \n", + "4 households_space_heater_heatpump_pvt_electricity \n", + "5 households_space_heater_district_heating_mt_st... \n", + "6 households_space_heater_hybrid_heatpump_air_wa... \n", + "7 households_space_heater_hybrid_hydrogen_heatpu... \n", + "8 households_space_heater_hybrid_crude_oil_heatp... \n", + "9 households_space_heater_district_heating_ht_st... \n", + "10 households_space_heater_electricity \n", + "11 households_space_heater_combined_network_gas \n", + "12 households_space_heater_combined_hydrogen \n", + "13 households_space_heater_wood_pellets \n", + "14 households_space_heater_network_gas \n", + "15 households_space_heater_coal \n", + "16 households_space_heater_crude_oil \n", + "\n", + " \\\n", + " heat_network_lt \n", + "sortables \n", + "0 energy_heat_network_storage_lt_steam_hot_water \n", + "1 energy_heat_boiler_lt_electricity \n", + "2 energy_heat_burner_lt_hydrogen \n", + "3 energy_heat_heatpump_water_water_lt_electricity \n", + "4 energy_heat_heatpump_surface_water_water_ts_lt... \n", + "5 energy_heat_heatpump_waste_water_water_ts_lt_e... \n", + "6 energy_heat_heatpump_drink_water_water_ts_lt_e... \n", + "7 None \n", + "8 None \n", + "9 None \n", + "10 None \n", + "11 None \n", + "12 None \n", + "13 None \n", + "14 None \n", + "15 None \n", + "16 None \n", + "\n", + " \\\n", + " heat_network_mt \n", + "sortables \n", + "0 energy_heat_network_storage_mt_steam_hot_water \n", + "1 energy_heat_boiler_mt_electricity \n", + "2 energy_heat_burner_mt_coal \n", + "3 energy_heat_burner_mt_crude_oil \n", + "4 energy_heat_burner_mt_hydrogen \n", + "5 energy_heat_burner_mt_network_gas \n", + "6 energy_heat_burner_mt_waste_mix \n", + "7 energy_heat_burner_mt_wood_pellets \n", + "8 energy_heat_heatpump_water_water_mt_electricity \n", + "9 energy_heat_heatpump_surface_water_water_ts_mt... \n", + "10 energy_heat_heatpump_waste_water_water_ts_mt_e... \n", + "11 energy_heat_heatpump_drink_water_water_ts_mt_e... \n", + "12 None \n", + "13 None \n", + "14 None \n", + "15 None \n", + "16 None \n", + "\n", + " \n", + " heat_network_ht \n", + "sortables \n", + "0 energy_heat_network_storage_ht_steam_hot_water \n", + "1 energy_heat_boiler_ht_electricity \n", + "2 energy_heat_burner_ht_coal \n", + "3 energy_heat_burner_ht_crude_oil \n", + "4 energy_heat_burner_ht_hydrogen \n", + "5 energy_heat_burner_ht_network_gas \n", + "6 energy_heat_burner_ht_waste_mix \n", + "7 energy_heat_burner_ht_wood_pellets \n", + "8 energy_heat_heatpump_water_water_ht_electricity \n", + "9 None \n", + "10 None \n", + "11 None \n", + "12 None \n", + "13 None \n", + "14 None \n", + "15 None \n", + "16 None " + ] + }, + "execution_count": 7, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "packer.sortables()" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "id": "0d3e771e", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
A: Create from excelB: Load a scenario by id
interconnector_1_priceinterconnector_1_import_availabilityinterconnector_1_export_availabilityinterconnector_2_priceinterconnector_2_import_availabilityinterconnector_2_export_availabilityinterconnector_3_priceinterconnector_1_priceinterconnector_1_import_availabilityinterconnector_1_export_availability...households_hot_waterindustry_ictindustry_other_electricityweather/solar_pv_profile_1weather/solar_thermalweather/air_temperatureweather/agriculture_heatingweather/wind_offshore_baselineweather/wind_coastal_baselineweather/wind_inland_baseline
00.011.00.026.001.01.00.019.09.09.0...9.09.09.09.09.09.09.09.09.09.0
10.011.00.026.001.01.00.009.09.09.0...9.09.09.09.09.09.09.09.09.09.0
20.011.00.014.481.01.00.009.09.09.0...9.09.09.09.09.09.09.09.09.09.0
30.011.00.00.011.00.00.009.09.09.0...9.09.09.09.09.09.09.09.09.09.0
40.011.00.00.021.00.00.009.09.09.0...9.09.09.09.09.09.09.09.09.09.0
..................................................................
87550.011.00.00.011.00.00.009.09.09.0...9.09.09.09.09.09.09.09.09.09.0
87560.011.00.00.011.00.00.009.09.09.0...9.09.09.09.09.09.09.09.09.09.0
87570.011.00.00.011.00.00.009.09.09.0...9.09.09.09.09.09.09.09.09.09.0
87580.011.00.00.021.00.00.009.09.09.0...9.09.09.09.09.09.09.09.09.09.0
87590.011.00.00.001.00.00.009.09.09.0...9.09.09.09.09.09.09.09.09.09.0
\n", + "

8760 rows × 52 columns

\n", + "
" + ], + "text/plain": [ + " A: Create from excel \\\n", + " interconnector_1_price interconnector_1_import_availability \n", + "0 0.01 1.0 \n", + "1 0.01 1.0 \n", + "2 0.01 1.0 \n", + "3 0.01 1.0 \n", + "4 0.01 1.0 \n", + "... ... ... \n", + "8755 0.01 1.0 \n", + "8756 0.01 1.0 \n", + "8757 0.01 1.0 \n", + "8758 0.01 1.0 \n", + "8759 0.01 1.0 \n", + "\n", + " \\\n", + " interconnector_1_export_availability interconnector_2_price \n", + "0 0.0 26.00 \n", + "1 0.0 26.00 \n", + "2 0.0 14.48 \n", + "3 0.0 0.01 \n", + "4 0.0 0.02 \n", + "... ... ... \n", + "8755 0.0 0.01 \n", + "8756 0.0 0.01 \n", + "8757 0.0 0.01 \n", + "8758 0.0 0.02 \n", + "8759 0.0 0.00 \n", + "\n", + " \\\n", + " interconnector_2_import_availability \n", + "0 1.0 \n", + "1 1.0 \n", + "2 1.0 \n", + "3 1.0 \n", + "4 1.0 \n", + "... ... \n", + "8755 1.0 \n", + "8756 1.0 \n", + "8757 1.0 \n", + "8758 1.0 \n", + "8759 1.0 \n", + "\n", + " \\\n", + " interconnector_2_export_availability interconnector_3_price \n", + "0 1.0 0.01 \n", + "1 1.0 0.00 \n", + "2 1.0 0.00 \n", + "3 0.0 0.00 \n", + "4 0.0 0.00 \n", + "... ... ... \n", + "8755 0.0 0.00 \n", + "8756 0.0 0.00 \n", + "8757 0.0 0.00 \n", + "8758 0.0 0.00 \n", + "8759 0.0 0.00 \n", + "\n", + " B: Load a scenario by id \\\n", + " interconnector_1_price interconnector_1_import_availability \n", + "0 9.0 9.0 \n", + "1 9.0 9.0 \n", + "2 9.0 9.0 \n", + "3 9.0 9.0 \n", + "4 9.0 9.0 \n", + "... ... ... \n", + "8755 9.0 9.0 \n", + "8756 9.0 9.0 \n", + "8757 9.0 9.0 \n", + "8758 9.0 9.0 \n", + "8759 9.0 9.0 \n", + "\n", + " ... \\\n", + " interconnector_1_export_availability ... households_hot_water \n", + "0 9.0 ... 9.0 \n", + "1 9.0 ... 9.0 \n", + "2 9.0 ... 9.0 \n", + "3 9.0 ... 9.0 \n", + "4 9.0 ... 9.0 \n", + "... ... ... ... \n", + "8755 9.0 ... 9.0 \n", + "8756 9.0 ... 9.0 \n", + "8757 9.0 ... 9.0 \n", + "8758 9.0 ... 9.0 \n", + "8759 9.0 ... 9.0 \n", + "\n", + " \\\n", + " industry_ict industry_other_electricity weather/solar_pv_profile_1 \n", + "0 9.0 9.0 9.0 \n", + "1 9.0 9.0 9.0 \n", + "2 9.0 9.0 9.0 \n", + "3 9.0 9.0 9.0 \n", + "4 9.0 9.0 9.0 \n", + "... ... ... ... \n", + "8755 9.0 9.0 9.0 \n", + "8756 9.0 9.0 9.0 \n", + "8757 9.0 9.0 9.0 \n", + "8758 9.0 9.0 9.0 \n", + "8759 9.0 9.0 9.0 \n", + "\n", + " \\\n", + " weather/solar_thermal weather/air_temperature \n", + "0 9.0 9.0 \n", + "1 9.0 9.0 \n", + "2 9.0 9.0 \n", + "3 9.0 9.0 \n", + "4 9.0 9.0 \n", + "... ... ... \n", + "8755 9.0 9.0 \n", + "8756 9.0 9.0 \n", + "8757 9.0 9.0 \n", + "8758 9.0 9.0 \n", + "8759 9.0 9.0 \n", + "\n", + " \\\n", + " weather/agriculture_heating weather/wind_offshore_baseline \n", + "0 9.0 9.0 \n", + "1 9.0 9.0 \n", + "2 9.0 9.0 \n", + "3 9.0 9.0 \n", + "4 9.0 9.0 \n", + "... ... ... \n", + "8755 9.0 9.0 \n", + "8756 9.0 9.0 \n", + "8757 9.0 9.0 \n", + "8758 9.0 9.0 \n", + "8759 9.0 9.0 \n", + "\n", + " \n", + " weather/wind_coastal_baseline weather/wind_inland_baseline \n", + "0 9.0 9.0 \n", + "1 9.0 9.0 \n", + "2 9.0 9.0 \n", + "3 9.0 9.0 \n", + "4 9.0 9.0 \n", + "... ... ... \n", + "8755 9.0 9.0 \n", + "8756 9.0 9.0 \n", + "8757 9.0 9.0 \n", + "8758 9.0 9.0 \n", + "8759 9.0 9.0 \n", + "\n", + "[8760 rows x 52 columns]" + ] + }, + "execution_count": 8, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "packer.custom_curves()" + ] + }, + { + "cell_type": "code", + "execution_count": 9, + "id": "54cc3f61", + "metadata": {}, + "outputs": [ + { + "data": { + "text/html": [ + "
\n", + "\n", + "\n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + " \n", + "
A: Create from excelB: Load a scenario by id
futurefuture
gqueryunit
dashboard_emissionsfactor0.024027-0.947929
dashboard_co2_emissions_versus_start_yearfactor0.028299-0.997037
dashboard_total_costsbln_euro39.30029356.46303
\n", + "
" + ], + "text/plain": [ + " A: Create from excel \\\n", + " future \n", + "gquery unit \n", + "dashboard_emissions factor 0.024027 \n", + "dashboard_co2_emissions_versus_start_year factor 0.028299 \n", + "dashboard_total_costs bln_euro 39.300293 \n", + "\n", + " B: Load a scenario by id \n", + " future \n", + "gquery unit \n", + "dashboard_emissions factor -0.947929 \n", + "dashboard_co2_emissions_versus_start_year factor -0.997037 \n", + "dashboard_total_costs bln_euro 56.46303 " + ] + }, + "execution_count": 9, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "packer.gquery_results()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "pyetm-qKH2ozgc", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/examples/exploring_a_scenario.ipynb b/examples/exploring_a_scenario.ipynb index 168fec0..5fd681c 100644 --- a/examples/exploring_a_scenario.ipynb +++ b/examples/exploring_a_scenario.ipynb @@ -26,7 +26,26 @@ "execution_count": null, "id": "59514b1f", "metadata": {}, - "outputs": [], + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "Environment setup complete\n", + " Using ETM API at http://localhost:3000/api/v3\n", + " Token loaded? True\n", + "API connection ready\n" + ] + }, + { + "ename": "ScenarioError", + "evalue": "Could not load scenario 2690288: [\"HTTPConnectionPool(host='localhost', port=3000): Max retries exceeded with url: /api/v3/scenarios/2690288 (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 61] Connection refused'))\"]", + "output_type": "error", + "traceback": [ + "\u001b[31mScenarioError\u001b[39m\u001b[31m:\u001b[39m Could not load scenario 2690288: [\"HTTPConnectionPool(host='localhost', port=3000): Max retries exceeded with url: /api/v3/scenarios/2690288 (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 61] Connection refused'))\"]\n" + ] + } + ], "source": [ "from example_helpers import setup_notebook\n", "from pyetm.models import Scenario\n", @@ -34,7 +53,7 @@ "setup_notebook()\n", "\n", "# Change the scenario id to anything you want! This is a scenario on pro.\n", - "scenario = Scenario.load(2690288)" + "scenario = Scenario.load(2690555)" ] }, { diff --git a/examples/full_multi_scenario_flow.ipynb b/examples/full_multi_scenario_flow.ipynb new file mode 100644 index 0000000..4dd758a --- /dev/null +++ b/examples/full_multi_scenario_flow.ipynb @@ -0,0 +1,174 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "268e5f69", + "metadata": {}, + "source": [ + "This workbook demonstrates the complete flow from excel created / loaded scenarios to the API, including demonstrating how you can work with scenarios in pandas along the way.\n", + "\n", + "Before you begin you will need to place a config.yml in your root directory. An example.config.yml is available in /examples and will guide you through the setup. The README.md has additional details on environment management if you're setting up for the first time." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "7ad85ac7", + "metadata": {}, + "outputs": [], + "source": [ + "# Check the environment is properly configured.\n", + "from example_helpers import setup_notebook\n", + "setup_notebook()" + ] + }, + { + "cell_type": "markdown", + "id": "2884d014", + "metadata": {}, + "source": [ + "For the purposes of this demonstration workbook, we will use the pre-filled template 'my_input_excel.xlsx' which demonstrated a few of the possibilities afforded by the pyetm package. If it's your first time using the tool, have a look at the excel to get a sense of the structure.\n", + "\n", + "In the example, there are two scenarios, with short names scen_a and scen_b. You can use short names in the parameters sheet to specify which inputs belong to which scenario. Because scen_a has no scenario_id, it is being created. It will be created with all the metadata included in the sheet, plus any of the inputs under the column with its short_name and any sortables and curves specified in the sheets named beside the sortables and custom_curves rows. The same goes for scen_b, but because it has a scenario_id (2690555) that scenario will be loaded, and then updated with anything as set in the excel.\n", + "\n", + "**TODO**: Figure out how to manage the fact that for this example whatever scenario 2690555 is will be constantly updated etc by everyone who wants to try running the script on pro/beta. At the moment its just a local scenario.\n", + "\n", + "Everything in the ETM is structured via scenarios, and so is pyetm." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "077ae081", + "metadata": {}, + "outputs": [], + "source": [ + "from pyetm.models.scenarios import Scenarios\n", + "\n", + "scenarios = Scenarios.from_excel(\"my_input_excel.xlsx\")" + ] + }, + { + "cell_type": "markdown", + "id": "fb319a38", + "metadata": {}, + "source": [ + "Now we have the 'scenarios' in pyetm which represent actual real scenarios in the ETM, one created and one loaded.\n", + "\n", + "The following blocks show how you can explore these scenarios' attributes - run some if you want to explore the data structures." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "17bff6db", + "metadata": {}, + "outputs": [], + "source": [ + "# Metadata\n", + "for scenario in scenarios:\n", + " print(f\"Title: {scenario.title}\")\n", + " print(f\"Area: {scenario.area_code}\")\n", + " print(f\"End year: {scenario.end_year}\")\n", + " print(f\"Version: {scenario.version}\")\n", + " print(f\"Source: {scenario.source}\")\n", + " print(f\"Metadata: {scenario.metadata}\")\n", + " print(\"\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "1f9a4600", + "metadata": {}, + "outputs": [], + "source": [ + "# Inputs\n", + "for scenario in scenarios:\n", + " inputs = scenario.inputs.to_dataframe(columns=[\"user\", \"default\", \"min\", \"max\"]).head(20)\n", + " print(inputs)\n", + " print(\"\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "6e9bf837", + "metadata": {}, + "outputs": [], + "source": [ + "# Sortables\n", + "for scenario in scenarios:\n", + " sortables = scenario.sortables.to_dataframe().head(20)\n", + " print(sortables)\n", + " print(\"\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "9ef38d18", + "metadata": {}, + "outputs": [], + "source": [ + "# Custom Curves\n", + "for scenario in scenarios:\n", + " curves = scenario.custom_curves.to_dataframe().head(20)\n", + " print(curves)\n", + " print(\"\")" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "aa4e8ee8", + "metadata": {}, + "outputs": [], + "source": [ + "# Queries\n", + "for scenario in scenarios:\n", + " print(scenario.results())\n", + " print(\"\")" + ] + }, + { + "cell_type": "markdown", + "id": "86643b22", + "metadata": {}, + "source": [ + "We can directly modify any of the attributes using Pandas, or we can re-export the scenarios to excel and make modifications that way." + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "d24ad5e1", + "metadata": {}, + "outputs": [], + "source": [ + "scenarios.to_excel(\"my_excel.xlsx\")" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "pyetm-qKH2ozgc", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/examples/myc_notebook_for_tim.ipynb b/examples/myc_notebook_for_tim.ipynb index df330f1..6545857 100644 --- a/examples/myc_notebook_for_tim.ipynb +++ b/examples/myc_notebook_for_tim.ipynb @@ -136,7 +136,6 @@ ], "source": [ "scenario = Scenario.load(2690499)\n", - "# maybe add a tag for a study name / scenario name\n", "scenario.to_dataframe()" ] }, @@ -1610,7 +1609,7 @@ ], "metadata": { "kernelspec": { - "display_name": "pyetm-FWBOHxp3", + "display_name": "pyetm-qKH2ozgc", "language": "python", "name": "python3" }, @@ -1624,7 +1623,7 @@ "name": "python", "nbconvert_exporter": "python", "pygments_lexer": "ipython3", - "version": "3.12.11" + "version": "3.12.9" } }, "nbformat": 4, diff --git a/examples/scenario_to_excel.ipynb b/examples/scenario_to_excel.ipynb index 641f69b..6071b68 100644 --- a/examples/scenario_to_excel.ipynb +++ b/examples/scenario_to_excel.ipynb @@ -10,21 +10,10 @@ }, { "cell_type": "code", - "execution_count": 1, + "execution_count": null, "id": "4e9a9e7c", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Environment setup complete\n", - " Using ETM API at https://beta.engine.energytransitionmodel.com/api/v3\n", - " Token loaded? True\n", - "API connection ready\n" - ] - } - ], + "outputs": [], "source": [ "from example_helpers import setup_notebook\n", "from pyetm.models import Scenario\n", @@ -50,13 +39,13 @@ }, { "cell_type": "code", - "execution_count": 2, + "execution_count": null, "id": "c4f42def", "metadata": {}, "outputs": [], "source": [ "# Example beta scenario\n", - "scenario = Scenario.load(2704433)\n", + "scenario = Scenario.load(2690456)\n", "\n", "# Example pro scenario\n", "# scenario = Scenario.load(1340415)" @@ -107,59 +96,17 @@ }, { "cell_type": "code", - "execution_count": 3, + "execution_count": null, "id": "fa8ac6ab", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " 2704434 \\\n", - " value default \n", - "input unit \n", - "climate_relevant_co2_biomass_gas_future % None 0.0 \n", - "climate_relevant_co2_biomass_gas_present % None 0.0 \n", - "climate_relevant_co2_biomass_liquid_future % None 0.0 \n", - "climate_relevant_co2_biomass_liquid_present % None 0.0 \n", - "climate_relevant_co2_biomass_solid_future % None 0.0 \n", - "... ... ... \n", - "capacity_of_energy_battery_wind_turbine_inland MW None 0.0 \n", - "capacity_of_energy_power_hybrid_wind_turbine_of... MW None 0.0 \n", - "capacity_of_energy_power_wind_turbine_coastal MW None 1106.189347 \n", - "capacity_of_energy_power_wind_turbine_inland MW None 2421.16051 \n", - "capacity_of_energy_power_wind_turbine_offshore MW None 956.994305 \n", - "\n", - " 2704433 \n", - " value default \n", - "input unit \n", - "climate_relevant_co2_biomass_gas_future % 0.0 0.0 \n", - "climate_relevant_co2_biomass_gas_present % 0.0 0.0 \n", - "climate_relevant_co2_biomass_liquid_future % 0.0 0.0 \n", - "climate_relevant_co2_biomass_liquid_present % 0.0 0.0 \n", - "climate_relevant_co2_biomass_solid_future % 0.0 0.0 \n", - "... ... ... \n", - "capacity_of_energy_battery_wind_turbine_inland MW 0.0 0.0 \n", - "capacity_of_energy_power_hybrid_wind_turbine_of... MW None 0.0 \n", - "capacity_of_energy_power_wind_turbine_coastal MW 0.0 0.0 \n", - "capacity_of_energy_power_wind_turbine_inland MW 10000.0 10000.0 \n", - "capacity_of_energy_power_wind_turbine_offshore MW 38000.0 38000.0 \n", - "\n", - "[1318 rows x 4 columns]\n", - " 2704434 2704433\n", - "end_year 2050 2050\n", - "private False False\n", - "area_code nl2019 nl2019\n", - "template None 2402170\n" - ] - } - ], + "outputs": [], "source": [ "from pyetm.models import ScenarioPacker\n", "\n", "packer = ScenarioPacker()\n", "\n", - "scenario2 = Scenario.load(2704434)\n", + "scenario = Scenario.load(2690456)\n", + "scenario2 = Scenario.load(2690455)\n", "# Ready the scenario for inputs\n", "packer.add_inputs(scenario)\n", "packer.add_inputs(scenario2)\n", @@ -179,21 +126,10 @@ }, { "cell_type": "code", - "execution_count": 4, + "execution_count": null, "id": "739e2a12", "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " 2704433\n", - " future\n", - "dashboard_total_costs bln_euro 64.226691\n", - "dashboard_co2_emissions_versus_start_year factor -1.026581\n" - ] - } - ], + "outputs": [], "source": [ "scenario.add_queries(\n", " [\"dashboard_total_costs\", \"dashboard_co2_emissions_versus_start_year\"]\n", @@ -212,19 +148,10 @@ }, { "cell_type": "code", - "execution_count": 5, + "execution_count": null, "id": "ce5e2bdb", "metadata": {}, - "outputs": [ - { - "name": "stderr", - "output_type": "stream", - "text": [ - "/Users/noracato/code/work/packages/pyetm/src/pyetm/models/scenario_packer.py:245: FutureWarning: Downcasting object dtype arrays on .fillna, .ffill, .bfill is deprecated and will change in a future version. Call result.infer_objects(copy=False) instead. To opt-in to the future behavior, set `pd.set_option('future.no_silent_downcasting', True)`\n", - " add_frame(sheet_name, df.fillna(''), workbook, column_width=18)\n" - ] - } - ], + "outputs": [], "source": [ "scenario.add_queries(\n", " [\"dashboard_emissions\"]\n", @@ -242,7 +169,7 @@ "id": "68ce86c3", "metadata": {}, "source": [ - "Output curves are still not packing nicely:" + "Output curves:" ] }, { @@ -253,8 +180,14 @@ "outputs": [], "source": [ "packer.add_output_curves(scenario)\n", + "packer.add_output_curves(scenario2)\n", + "packer.add_custom_curves(scenario)\n", + "packer.add_custom_curves(scenario2)\n", + "packer.add_sortables(scenario)\n", + "packer.add_sortables(scenario2)\n", + "\n", "\n", - "packer.to_excel('testing_output_curves.xlsx')" + "# packer.to_excel('testing_output_curves.xlsx')" ] } ], diff --git a/examples/serialization_deserialization.ipynb b/examples/serialization_deserialization.ipynb index 0725fbb..b2b130a 100644 --- a/examples/serialization_deserialization.ipynb +++ b/examples/serialization_deserialization.ipynb @@ -92,7 +92,7 @@ }, { "cell_type": "code", - "execution_count": 9, + "execution_count": null, "id": "serialize", "metadata": {}, "outputs": [ @@ -123,7 +123,7 @@ ], "source": [ "# Serialize to DataFrame with multiple columns\n", - "df = original_inputs.to_df(columns=[\"user\", \"default\", \"min\", \"max\", \"disabled\"])\n", + "df = original_inputs.to_dataframe(columns=[\"user\", \"default\", \"min\", \"max\", \"disabled\"])\n", "\n", "print(f\"DataFrame shape: {df.shape}\")\n", "print(f\"DataFrame index: {df.index.names}\")\n", @@ -190,13 +190,13 @@ "scenario.set_user_values_from_dataframe(df)\n", "reconstructed_inputs = scenario.inputs\n", "\n", - "print(f\"DataFrame shape: {reconstructed_inputs.to_df().shape}\")\n", - "print(f\"DataFrame index: {reconstructed_inputs.to_df().index.names}\")\n", - "print(f\"DataFrame columns: {list(reconstructed_inputs.to_df().columns)}\")\n", + "print(f\"DataFrame shape: {reconstructed_inputs.to_dataframe().shape}\")\n", + "print(f\"DataFrame index: {reconstructed_inputs.to_dataframe().index.names}\")\n", + "print(f\"DataFrame columns: {list(reconstructed_inputs.to_dataframe().columns)}\")\n", "\n", - "print(reconstructed_inputs.to_df().head())\n", + "print(reconstructed_inputs.to_dataframe().head())\n", "\n", - "df_again = reconstructed_inputs.to_df(columns=[\"user\", \"default\", \"min\", \"max\", \"disabled\"])\n", + "df_again = reconstructed_inputs.to_dataframe(columns=[\"user\", \"default\", \"min\", \"max\", \"disabled\"])\n", "\n", "print(df_again.head())\n", "\n", diff --git a/src/pyetm/models/__init__.py b/src/pyetm/models/__init__.py index 5f78c5a..6e0abb7 100644 --- a/src/pyetm/models/__init__.py +++ b/src/pyetm/models/__init__.py @@ -2,5 +2,6 @@ from .gqueries import Gqueries from .inputs import Input, Inputs from .scenario import Scenario +from .scenarios import Scenarios from .sortables import Sortable, Sortables from .scenario_packer import ScenarioPacker diff --git a/src/pyetm/models/custom_curves.py b/src/pyetm/models/custom_curves.py index 2cf6cd3..6e59e65 100644 --- a/src/pyetm/models/custom_curves.py +++ b/src/pyetm/models/custom_curves.py @@ -141,7 +141,9 @@ def _to_dataframe(self, **kwargs) -> pd.DataFrame: return df @classmethod - def _from_dataframe(cls, df: pd.DataFrame, **kwargs) -> "CustomCurve": + def _from_dataframe( + cls, df: pd.DataFrame, scenario_id: str | int | None = None, **kwargs + ) -> "CustomCurve": """ Create CustomCurve from DataFrame containing time series data. """ @@ -150,30 +152,23 @@ def _from_dataframe(cls, df: pd.DataFrame, **kwargs) -> "CustomCurve": f"DataFrame must contain exactly 1 column, got {len(df.columns)}" ) - # Get the curve key from column name curve_key = df.columns[0] - curve_data_dict = { "key": curve_key, - "type": "custom", # Default type for curves created from DataFrame + "type": "custom", } - curve = cls.model_validate(curve_data_dict) - # Only save data if DataFrame has actual data rows if not df.empty: curve_data = df.iloc[:, 0].dropna() - if not curve_data.empty: - # Save the data to a temporary file and set file_path + safe_key = str(curve_key).replace("/", "-") + prefix = f"{scenario_id}_" if scenario_id is not None else "" file_path = ( get_settings().path_to_tmp("dataframe_import") - / f"{curve_key.replace('/', '-')}.csv" + / f"{prefix}{safe_key}.csv" ) - - # Ensure directory exists file_path.parent.mkdir(parents=True, exist_ok=True) - try: curve_data.to_csv(file_path, index=False, header=False) curve.file_path = file_path @@ -181,7 +176,6 @@ def _from_dataframe(cls, df: pd.DataFrame, **kwargs) -> "CustomCurve": curve.add_warning( curve_key, f"Failed to save curve data to file: {e}" ) - return curve @@ -244,7 +238,7 @@ def from_json(cls, data: list[dict]) -> CustomCurves: collection = cls.model_validate({"curves": curves}) - # Merge warnings from individual curves using new system + # Merge warnings from individual curves collection._merge_submodel_warnings(*curves, key_attr="key") return collection @@ -284,23 +278,22 @@ def _to_dataframe(self, **kwargs) -> pd.DataFrame: return pd.DataFrame(index=pd.Index([], name="hour")) @classmethod - def _from_dataframe(cls, df: pd.DataFrame, **kwargs) -> "CustomCurves": + def _from_dataframe( + cls, df: pd.DataFrame, scenario_id: str | int | None = None, **kwargs + ) -> "CustomCurves": """ Create CustomCurves collection from DataFrame with time series data. """ curves = [] - if len(df.columns) == 0: return cls.model_validate({"curves": curves}) - for column_name in df.columns: try: - # Extract single column as DataFrame for individual curve curve_df = df[[column_name]] - - curve = CustomCurve._from_dataframe(curve_df, **kwargs) + curve = CustomCurve._from_dataframe( + curve_df, scenario_id=scenario_id, **kwargs + ) curves.append(curve) - except Exception as e: basic_curve = CustomCurve.model_construct( key=column_name, type="custom" @@ -309,12 +302,8 @@ def _from_dataframe(cls, df: pd.DataFrame, **kwargs) -> "CustomCurves": "base", f"Failed to create curve from column {column_name}: {e}" ) curves.append(basic_curve) - collection = cls.model_validate({"curves": curves}) - - # Merge warnings from individual curves collection._merge_submodel_warnings(*curves, key_attr="key") - return collection def validate_for_upload(self) -> dict[str, WarningCollector]: @@ -336,12 +325,14 @@ def validate_for_upload(self) -> dict[str, WarningCollector]: # First, try to read the file without forcing dtype to check for non-numeric values try: # Read without dtype conversion to preserve non-numeric values - raw_data = pd.read_csv(curve.file_path, header=None, index_col=False) + raw_data = pd.read_csv( + curve.file_path, header=None, index_col=False + ) if raw_data.empty: curve_warnings.add(curve.key, "Curve contains no data") validation_errors[curve.key] = curve_warnings continue - + # Check length first if len(raw_data) != 8760: curve_warnings.add( @@ -352,25 +343,21 @@ def validate_for_upload(self) -> dict[str, WarningCollector]: # Now check if all values can be converted to float try: # Try to convert to numeric, this will raise if there are non-numeric values - pd.to_numeric(raw_data.iloc[:, 0], errors='raise') + pd.to_numeric(raw_data.iloc[:, 0], errors="raise") except (ValueError, TypeError): curve_warnings.add( curve.key, "Curve contains non-numeric values" ) - + except pd.errors.EmptyDataError: curve_warnings.add(curve.key, "Curve contains no data") except Exception as e: # This catches file not found, permission errors, etc. - curve_warnings.add( - curve.key, f"Error reading curve data: {str(e)}" - ) + curve_warnings.add(curve.key, f"Error reading curve data: {str(e)}") except Exception as e: # Catch any other unexpected errors - curve_warnings.add( - curve.key, f"Error reading curve data: {str(e)}" - ) + curve_warnings.add(curve.key, f"Error reading curve data: {str(e)}") # Only add to validation_errors if there are actual warnings if len(curve_warnings) > 0: diff --git a/src/pyetm/models/inputs.py b/src/pyetm/models/inputs.py index a8ee2f1..c970d1a 100644 --- a/src/pyetm/models/inputs.py +++ b/src/pyetm/models/inputs.py @@ -186,7 +186,6 @@ def is_valid_update(self, key_vals: dict) -> dict[str, WarningCollector]: def update(self, key_vals: dict): """ Update the values of certain inputs. - Uses the new warning system for validation. """ for input_obj in self.inputs: if input_obj.key in key_vals: diff --git a/src/pyetm/models/output_curves.py b/src/pyetm/models/output_curves.py index 540bb27..dec1bc8 100644 --- a/src/pyetm/models/output_curves.py +++ b/src/pyetm/models/output_curves.py @@ -147,14 +147,11 @@ def get_contents(self, scenario, curve_name: str) -> Optional[pd.DataFrame]: return None if not curve.available(): - # Try to retrieve it result = curve.retrieve(BaseClient(), scenario) - # Merge any warnings from the curve retrieval using new system self._merge_submodel_warnings(curve, key_attr="key") return result else: contents = curve.contents() - # Merge any warnings from reading contents using new system self._merge_submodel_warnings(curve, key_attr="key") return contents @@ -247,7 +244,7 @@ def from_json(cls, data: list[dict]) -> OutputCurves: collection = cls.model_validate({"curves": curves}) - # Merge warnings from individual curves using new system + # Merge warnings from individual curves collection._merge_submodel_warnings(*curves, key_attr="key") return collection diff --git a/src/pyetm/models/packables/custom_curves_pack.py b/src/pyetm/models/packables/custom_curves_pack.py new file mode 100644 index 0000000..529655a --- /dev/null +++ b/src/pyetm/models/packables/custom_curves_pack.py @@ -0,0 +1,61 @@ +import logging +from typing import ClassVar, Any +import pandas as pd +from pyetm.models.custom_curves import CustomCurves +from pyetm.models.packables.packable import Packable + +logger = logging.getLogger(__name__) + + +class CustomCurvesPack(Packable): + key: ClassVar[str] = "custom_curves" + sheet_name: ClassVar[str] = "CUSTOM_CURVES" + + def _build_dataframe_for_scenario(self, scenario: Any, columns: str = "", **kwargs): + try: + series_list = list(scenario.custom_curves_series()) + except Exception as e: + logger.warning( + "Failed extracting custom curves for %s: %s", scenario.identifier(), e + ) + return None + if not series_list: + return None + return pd.concat(series_list, axis=1) + + def _to_dataframe(self, columns="", **kwargs) -> pd.DataFrame: + return self.build_pack_dataframe(columns=columns, **kwargs) + + def _normalize_curves_dataframe(self, df: pd.DataFrame) -> pd.DataFrame: + return self._normalize_single_header_sheet( + df, + helper_columns={"sortables"}, + drop_empty=True, + reset_index=True, + ) + + def from_dataframe(self, df: pd.DataFrame): + if df is None or getattr(df, "empty", False): + return + try: + df = self._normalize_curves_dataframe(df) + except Exception as e: + logger.warning("Failed to normalize custom curves sheet: %s", e) + return + if df is None or df.empty: + return + + def _apply(scenario, block: pd.DataFrame): + try: + curves = CustomCurves._from_dataframe(block, scenario_id=scenario.id) + except Exception as e: + logger.warning( + "Failed to build custom curves for '%s': %s", + scenario.identifier(), + e, + ) + return + scenario.update_custom_curves(curves) + + for scenario in self.scenarios: + _apply(scenario, df) diff --git a/src/pyetm/models/packables/inputs_pack.py b/src/pyetm/models/packables/inputs_pack.py new file mode 100644 index 0000000..5680174 --- /dev/null +++ b/src/pyetm/models/packables/inputs_pack.py @@ -0,0 +1,176 @@ +import logging +from typing import ClassVar, Dict, Any +import pandas as pd +from pyetm.models.packables.packable import Packable + +logger = logging.getLogger(__name__) + + +class InputsPack(Packable): + key: ClassVar[str] = "inputs" + sheet_name: ClassVar[str] = "PARAMETERS" + + def __init__(self, **data): + super().__init__(**data) + self._scenario_short_names: Dict[str, str] = {} + + def set_scenario_short_names(self, scenario_short_names: Dict[str, str]): + self._scenario_short_names = scenario_short_names or {} + + def _key_for(self, scenario: "Any") -> Any: + short = self._scenario_short_names.get(str(scenario.id)) + if short: + return short + + label = None + try: + label = scenario.identifier() + except Exception: + label = None + + if not isinstance(label, (str, int)): + return scenario.id + return label + + def resolve_scenario(self, label: Any): + if label is None: + return None + label_str = str(label).strip() + # Match short name first + for scenario in self.scenarios: + if self._scenario_short_names.get(str(scenario.id)) == label_str: + return scenario + # Fallback to identifier/title + found = super().resolve_scenario(label_str) + if found is not None: + return found + # Fallback to numeric id + try: + num = int(float(label_str)) + for scenario in self.scenarios: + if scenario.id == num: + return scenario + except Exception: + pass + return None + + def _to_dataframe(self, columns: str = "user", **kwargs): + if not self.scenarios: + return pd.DataFrame() + + def extract_user_map_from_inputs_obj(scen) -> dict[str, Any] | None: + try: + it = iter(scen.inputs) + values = {} + for inp in it: + key = getattr(inp, "key", None) + if key is None: + continue + values[str(key)] = getattr(inp, "user", None) + if values: + return values + except Exception: + pass + + try: + df = scen.inputs.to_dataframe(columns="user") + except Exception: + df = None + if df is None or getattr(df, "empty", False): + return None + + if isinstance(df.index, pd.MultiIndex) and "unit" in (df.index.names or []): + df = df.copy() + df.index = df.index.droplevel("unit") + if isinstance(df, pd.Series): + series = df + else: + cols_lc = [str(c).lower() for c in df.columns] + chosen = None + for candidate in ("user", "value"): + if candidate in cols_lc: + chosen = df.columns[cols_lc.index(candidate)] + break + if chosen is None: + chosen = df.columns[0] + series = df[chosen] + series.index = series.index.map(lambda k: str(k)) + return series.to_dict() + + all_keys: set[str] = set() + per_label_values: dict[Any, dict[str, Any]] = {} + for scen in self.scenarios: + label = self._key_for(scen) + user_map = extract_user_map_from_inputs_obj(scen) + if not user_map: + continue + per_label_values[label] = user_map + all_keys.update(user_map.keys()) + + if not all_keys: + return pd.DataFrame() + + sorted_keys = sorted(all_keys) + data: dict[Any, list[Any]] = {} + for label, value_map in per_label_values.items(): + data[label] = [value_map.get(k) for k in sorted_keys] + + df = pd.DataFrame(data, index=sorted_keys) + df.index.name = "input" + return df + + def from_dataframe(self, df): + if df is None or getattr(df, "empty", False): + return + try: + df = df.dropna(how="all") + if df.empty: + return + header_pos_list = self.first_non_empty_row_positions(df, 1) + if not header_pos_list: + return + header_pos = header_pos_list[0] + header_row = df.iloc[header_pos].astype(str) + data = df.iloc[header_pos + 1 :].copy() + data.columns = header_row.values + if data.empty or len(data.columns) < 2: + return + input_col = data.columns[0] + inputs_series = data[input_col].astype(str).str.strip() + mask = inputs_series != "" + data = data.loc[mask] + inputs_series = inputs_series.loc[mask] + data.index = inputs_series + scenario_cols = [c for c in data.columns if c != input_col] + for col in scenario_cols: + scenario = self.resolve_scenario(col) + if scenario is None: + logger.warning( + "Could not find scenario for PARAMETERS column label '%s'", col + ) + continue + series = data[col] + + def _is_blank_val(v: Any) -> bool: + if v is None: + return True + if isinstance(v, float) and pd.isna(v): + return True + if isinstance(v, str) and v.strip().lower() in {"", "nan"}: + return True + return False + + updates = {k: v for k, v in series.items() if not _is_blank_val(v)} + if not updates: + continue + try: + scenario.update_user_values(updates) + except Exception as e: + logger.warning( + "Failed updating inputs for scenario '%s' from column '%s': %s", + scenario.identifier(), + col, + e, + ) + except Exception as e: + logger.warning("Failed to parse simplified PARAMETERS sheet: %s", e) diff --git a/src/pyetm/models/packables/output_curves_pack.py b/src/pyetm/models/packables/output_curves_pack.py new file mode 100644 index 0000000..ff90d49 --- /dev/null +++ b/src/pyetm/models/packables/output_curves_pack.py @@ -0,0 +1,28 @@ +import logging +from typing import ClassVar, Any + +import pandas as pd + +from pyetm.models.packables.packable import Packable + +logger = logging.getLogger(__name__) + + +class OutputCurvesPack(Packable): + key: ClassVar[str] = "output_curves" + sheet_name: ClassVar[str] = "OUTPUT_CURVES" + + def _build_dataframe_for_scenario(self, scenario: Any, columns: str = "", **kwargs): + try: + series_list = list(scenario.all_output_curves()) + except Exception as e: + logger.warning( + "Failed extracting output curves for %s: %s", scenario.identifier(), e + ) + return None + if not series_list: + return None + return pd.concat(series_list, axis=1) + + def _to_dataframe(self, columns="", **kwargs) -> pd.DataFrame: + return self.build_pack_dataframe(columns=columns, **kwargs) diff --git a/src/pyetm/models/packables/packable.py b/src/pyetm/models/packables/packable.py new file mode 100644 index 0000000..6b2fdfc --- /dev/null +++ b/src/pyetm/models/packables/packable.py @@ -0,0 +1,215 @@ +from typing import ClassVar, Set, Callable, Optional, Dict, Any +import logging +import pandas as pd +from pydantic import BaseModel, Field + +from pyetm.models.scenario import Scenario + +logger = logging.getLogger(__name__) + + +class Packable(BaseModel): + scenarios: Set["Scenario"] = Field(default_factory=set) + key: ClassVar[str] = "base_pack" + sheet_name: ClassVar[str] = "SHEET" + + _scenario_id_cache: Dict[str, "Scenario"] | None = None + + def add(self, *scenarios): + "Adds one or more scenarios to the packable" + if not scenarios: + return + self.scenarios.update(scenarios) + self._scenario_id_cache = None + + def discard(self, scenario): + "Removes a scenario from the pack" + self.scenarios.discard(scenario) + self._scenario_id_cache = None + + def clear(self): + self.scenarios.clear() + self._scenario_id_cache = None + + def summary(self) -> dict: + return {self.key: {"scenario_count": len(self.scenarios)}} + + def _key_for(self, scenario: "Scenario") -> Any: + """Return the identifier used as the top-level column key when packing. + Subclasses can override (e.g. to use short names).""" + return scenario.identifier() + + def _build_dataframe_for_scenario( + self, scenario: "Scenario", columns: str = "", **kwargs + ) -> Optional[pd.DataFrame]: + return None + + def _concat_frames( + self, frames: list[pd.DataFrame], keys: list[Any] + ) -> pd.DataFrame: + if not frames: + return pd.DataFrame() + return pd.concat(frames, axis=1, keys=keys) + + def build_pack_dataframe(self, columns: str = "", **kwargs) -> pd.DataFrame: + frames: list[pd.DataFrame] = [] + keys: list[Any] = [] + for scenario in self.scenarios: + try: + df = self._build_dataframe_for_scenario( + scenario, columns=columns, **kwargs + ) + except Exception as e: + logger.warning( + "Failed building frame for scenario %s in %s: %s", + scenario.identifier(), + self.__class__.__name__, + e, + ) + continue + if df is None or df.empty: + continue + frames.append(df) + keys.append(self._key_for(scenario)) + return self._concat_frames(frames, keys) + + def to_dataframe(self, columns="") -> pd.DataFrame: + """Convert the pack into a dataframe""" + if len(self.scenarios) == 0: + return pd.DataFrame() + return self._to_dataframe(columns=columns) + + def from_dataframe(self, df): + """Should parse the df and call correct setters on identified scenarios""" + raise NotImplementedError + + def _to_dataframe(self, columns="", **kwargs) -> pd.DataFrame: + """Base implementation - kids should implement this or use build_pack_dataframe""" + return pd.DataFrame() + + def _refresh_cache(self): + self._scenario_id_cache = {str(s.identifier()): s for s in self.scenarios} + + def _find_by_identifier(self, identifier: str): + ident_str = str(identifier) + if self._scenario_id_cache is None or len(self._scenario_id_cache) != len( + self.scenarios + ): + self._refresh_cache() + return self._scenario_id_cache.get(ident_str) + + def resolve_scenario(self, label: Any) -> Optional["Scenario"]: + if label is None: + return None + return self._find_by_identifier(label) + + @staticmethod + def is_blank(value: Any) -> bool: + return ( + value is None + or (isinstance(value, float) and pd.isna(value)) + or (isinstance(value, str) and value.strip() == "") + ) + + @staticmethod + def drop_all_blank(df: pd.DataFrame) -> pd.DataFrame: + if df is None: + return pd.DataFrame() + return df.dropna(how="all") + + @staticmethod + def first_non_empty_row_positions(df: pd.DataFrame, count: int = 2) -> list[int]: + positions: list[int] = [] + if df is None: + return positions + for idx, (_, row) in enumerate(df.iterrows()): + if not row.isna().all(): + positions.append(idx) + if len(positions) >= count: + break + return positions + + def _log_fail(self, context: str, exc: Exception): + logger.warning("%s failed in %s: %s", context, self.__class__.__name__, exc) + + def apply_identifier_blocks( + self, + df: pd.DataFrame, + apply_block: Callable[["Scenario", pd.DataFrame], None], + resolve: Optional[Callable[[Any], Optional["Scenario"]]] = None, + ): + if df is None or not isinstance(df.columns, pd.MultiIndex): + return + identifiers = df.columns.get_level_values(0).unique() + for identifier in identifiers: + scenario = ( + resolve(identifier) if resolve else None + ) or self._find_by_identifier(identifier) + if scenario is None: + logger.warning( + "Could not find scenario for identifier '%s' in %s", + identifier, + self.__class__.__name__, + ) + continue + block = df[identifier] + try: + apply_block(scenario, block) + except Exception as e: + logger.warning( + "Failed applying block for scenario '%s' in %s: %s", + identifier, + self.__class__.__name__, + e, + ) + + def _normalize_single_header_sheet( + self, + df: pd.DataFrame, + *, + helper_columns: Optional[set[str]] = None, + drop_empty: bool = True, + reset_index: bool = False, + ) -> pd.DataFrame: + """Normalize a sheet that uses a single header row. + - First non-empty row becomes header. + - Subsequent rows are data. + - Optionally drop columns whose header is blank or in helper_columns. + - Optionally reset the row index. + Returns a DataFrame with a single-level column index. + """ + helper_columns_lc = {h.lower() for h in (helper_columns or set())} + if df is None: + return pd.DataFrame() + df = df.dropna(how="all") + if df.empty: + return df + + positions = self.first_non_empty_row_positions(df, 1) + if not positions: + return pd.DataFrame() + header_pos = positions[0] + header_row = df.iloc[header_pos].astype(str).map(lambda s: s.strip()) + data = df.iloc[header_pos + 1 :].copy() + data.columns = header_row.values + + def _is_blank(v): + return ( + v is None + or (isinstance(v, float) and pd.isna(v)) + or (isinstance(v, str) and v.strip() == "") + ) + + if drop_empty or helper_columns_lc: + keep = [] + for c in data.columns: + if drop_empty and _is_blank(c): + continue + if isinstance(c, str) and c.strip().lower() in helper_columns_lc: + continue + keep.append(c) + data = data[keep] + + if reset_index: + data.reset_index(drop=True, inplace=True) + return data diff --git a/src/pyetm/models/packables/query_pack.py b/src/pyetm/models/packables/query_pack.py new file mode 100644 index 0000000..608e6eb --- /dev/null +++ b/src/pyetm/models/packables/query_pack.py @@ -0,0 +1,41 @@ +import logging +from typing import ClassVar, Any + +import pandas as pd + +from pyetm.models.packables.packable import Packable + +logger = logging.getLogger(__name__) + + +class QueryPack(Packable): + key: ClassVar[str] = "gquery" + sheet_name: ClassVar[str] = "GQUERIES" + output_sheet_name: ClassVar[str] = "GQUERIES_RESULTS" + + def _build_dataframe_for_scenario( + self, scenario: Any, columns: str = "future", **kwargs + ): + try: + return scenario.results(columns=columns) + except Exception as e: + logger.warning( + "Failed building gquery results for %s: %s", scenario.identifier(), e + ) + return None + + def _to_dataframe(self, columns="future", **kwargs) -> pd.DataFrame: + return self.build_pack_dataframe(columns=columns, **kwargs) + + def from_dataframe(self, df: pd.DataFrame): + if df is None or df.empty: + return + + first_col = df.iloc[:, 0].dropna().astype(str).str.strip() + filtered = [q for q in first_col if q and q.lower() != "nan"] + unique_queries = list(dict.fromkeys(filtered)) + + # Apply unique queries to all scenarios + if unique_queries: + for scenario in self.scenarios: + scenario.add_queries(unique_queries) diff --git a/src/pyetm/models/packables/sortable_pack.py b/src/pyetm/models/packables/sortable_pack.py new file mode 100644 index 0000000..17d0651 --- /dev/null +++ b/src/pyetm/models/packables/sortable_pack.py @@ -0,0 +1,54 @@ +import logging +from typing import ClassVar, Any +import pandas as pd +from pyetm.models.packables.packable import Packable + +logger = logging.getLogger(__name__) + + +class SortablePack(Packable): + key: ClassVar[str] = "sortables" + sheet_name: ClassVar[str] = "SORTABLES" + + def _build_dataframe_for_scenario(self, scenario: Any, columns: str = "", **kwargs): + try: + df = scenario.sortables.to_dataframe() + except Exception as e: + logger.warning( + "Failed extracting sortables for %s: %s", scenario.identifier(), e + ) + return None + return df if not df.empty else None + + def _to_dataframe(self, columns="", **kwargs) -> pd.DataFrame: + return self.build_pack_dataframe(columns=columns, **kwargs) + + def _normalize_sortables_dataframe(self, df: pd.DataFrame) -> pd.DataFrame: + """Normalize a sortables sheet expecting a single header row.""" + return self._normalize_single_header_sheet( + df, + helper_columns={"sortables"}, + drop_empty=True, + reset_index=False, + ) + + def from_dataframe(self, df: pd.DataFrame): + """Unpack and update sortables for each scenario from the sheet.""" + if df is None or getattr(df, "empty", False): + return + try: + df = self._normalize_sortables_dataframe(df) + except Exception as e: + logger.warning("Failed to normalize sortables sheet: %s", e) + return + if df is None or df.empty: + return + + def _apply(scenario, block: pd.DataFrame): + scenario.set_sortables_from_dataframe(block) + + if isinstance(df.columns, pd.MultiIndex): + self.apply_identifier_blocks(df, _apply) + else: + for scenario in self.scenarios: + _apply(scenario, df) diff --git a/src/pyetm/models/scenario.py b/src/pyetm/models/scenario.py index 0eb29c0..36ab2ee 100644 --- a/src/pyetm/models/scenario.py +++ b/src/pyetm/models/scenario.py @@ -4,11 +4,12 @@ from typing import Any, Dict, List, Optional, Set, Union from urllib.parse import urlparse from pydantic import Field, PrivateAttr +from os import PathLike from pyetm.models.inputs import Inputs from pyetm.models.output_curves import OutputCurves from pyetm.clients import BaseClient from pyetm.models.base import Base -from pyetm.models.custom_curves import CustomCurve, CustomCurves +from pyetm.models.custom_curves import CustomCurves from pyetm.models.gqueries import Gqueries from pyetm.models.sortables import Sortables from pyetm.services.scenario_runners.fetch_inputs import FetchInputsRunner @@ -98,6 +99,28 @@ def load(cls, scenario_id: int) -> Scenario: scenario.add_warning("metadata", w) return scenario + @classmethod + def from_excel(cls, xlsx_path: PathLike | str) -> List["Scenario"]: + """ + Load or create one or more scenarios from an Excel workbook. + """ + from pyetm.models.scenario_packer import ScenarioPacker + + packer = ScenarioPacker.from_excel(xlsx_path) + scenarios = list(packer._scenarios()) + scenarios.sort(key=lambda s: s.id) + return scenarios + + def to_excel(self, path: PathLike | str, *others: "Scenario") -> None: + """ + Export this scenario – and optionally additional scenarios – to an Excel file. + """ + from pyetm.models.scenario_packer import ScenarioPacker + + packer = ScenarioPacker() + packer.add(self, *others) + packer.to_excel(str(path)) + def update_metadata(self, **kwargs) -> Dict[str, Any]: """ Update metadata for this scenario. @@ -133,6 +156,25 @@ def _to_dataframe(self, **kwargs) -> pd.DataFrame: columns=[self.id], ) + @property + def title(self): + if not self.metadata is None: + return self.metadata.get("title", None) + return None + + @title.setter + def title(self, title: str): + if not self.metadata is None: + self.metadata["title"] = title + else: + self.metadata = {"title": title} + + def identifier(self): + if self.title: + return self.title + + return self.id + def user_values(self) -> Dict[str, Any]: """ Returns the values set by the user for inputs @@ -177,11 +219,14 @@ def set_user_values_from_dataframe(self, dataframe: pd.DataFrame) -> None: """ Extract df to dict, set None/NaN sliders to reset, and call update_inputs. This ensures the dataframe exactly represents the inputs. - # TODO: Add validation for the dataframe structure """ - self.update_user_values( - dataframe["user"].droplevel("unit").fillna("reset").to_dict() - ) + series = dataframe["user"] + # If MultiIndex with 'unit', drop it + if isinstance(series.index, pd.MultiIndex) and "unit" in ( + series.index.names or [] + ): + series = series.droplevel("unit") + self.update_user_values(series.fillna("reset").to_dict()) def update_user_values(self, update_inputs: Dict[str, Any]) -> None: """ @@ -245,15 +290,10 @@ def set_sortables_from_dataframe(self, dataframe: pd.DataFrame) -> None: Args: dataframe: DataFrame with sortable names as columns and order values as rows """ - # Convert DataFrame to dict of lists, handling NaN/None values - sortables_dict = {} - for column in dataframe.columns: - # Filter out NaN/None values and convert to list - order_values = dataframe[column].dropna().tolist() - if order_values: # Only include if there are actual values - sortables_dict[column] = order_values - - self.update_sortables(sortables_dict) + coll = Sortables._from_dataframe(dataframe) + updates = coll.to_updates_dict() + if updates: + self.update_sortables(updates) def update_sortables(self, update_sortables: Dict[str, List[Any]]) -> None: """ @@ -345,7 +385,6 @@ def update_custom_curves(self, custom_curves) -> None: Args: custom_curves: CustomCurves object containing curves to upload - TODO: Update after the from_excel is implemented """ # Validate curves before uploading diff --git a/src/pyetm/models/scenario_packer.py b/src/pyetm/models/scenario_packer.py index 92b9e44..c024c5b 100644 --- a/src/pyetm/models/scenario_packer.py +++ b/src/pyetm/models/scenario_packer.py @@ -1,111 +1,25 @@ import pandas as pd +import logging +from os import PathLike from pydantic import BaseModel -from typing import Optional, Dict, List, Any, Set, Literal, ClassVar +from typing import Optional, Dict, Any from xlsxwriter import Workbook -from pyetm.models.base import Base +from pyetm.models.packables.custom_curves_pack import CustomCurvesPack +from pyetm.models.packables.inputs_pack import InputsPack +from pyetm.models.packables.output_curves_pack import OutputCurvesPack +from pyetm.models.packables.query_pack import QueryPack +from pyetm.models.packables.sortable_pack import SortablePack from pyetm.models import Scenario +from pyetm.models.custom_curves import CustomCurves from pyetm.utils.excel import add_frame - -class Packable(BaseModel): - scenarios: Optional[set["Scenario"]] = set() - key: ClassVar[str] = "base_pack" - - def add(self, *scenarios): - "Adds one or more scenarios to the packable" - self.scenarios.update(scenarios) - - def discard(self, scenario): - "Removes a scenario from the pack" - self.scenarios.discard(scenario) - - def clear(self): - self.scenarios = [] - - def summary(self) -> dict: - return {self.key: {"scenario_count": len(self.scenarios)}} - - def to_dataframe(self, columns="") -> pd.DataFrame: - """Convert the pack into a dataframe""" - if len(self.scenarios) == 0: - return pd.DataFrame() - - return self._to_dataframe(columns=columns) - - def _to_dataframe(self, columns="", **kwargs) -> pd.DataFrame: - """Base implementation - kids should implement this""" - return pd.DataFrame() - - -class InputsPack(Packable): - key: ClassVar[str] = "inputs" - - def _to_dataframe(self, columns="user", **kwargs): - return pd.concat( - [scenario.inputs.to_dataframe(columns=columns) for scenario in self.scenarios], - axis=1, - keys=[scenario.id for scenario in self.scenarios], - ) - - -class QueryPack(Packable): - key: ClassVar[str] = "gquery" - - def _to_dataframe( - self, columns="future", **kwargs - ) -> pd.DataFrame: # Make sure **kwargs is here - if not self.scenarios: - return pd.DataFrame() - - return pd.concat( - [scenario.results(columns=columns) for scenario in self.scenarios], - axis=1, - keys=[scenario.id for scenario in self.scenarios], - copy=False, - ) - - -class SortablePack(Packable): - key: ClassVar[str] = "sortables" - - def _to_dataframe(self, columns="", **kwargs) -> pd.DataFrame: - """PACKS ONLY FIRST SCENARIO""" - for scenario in self.scenarios: - return scenario.sortables.to_dataframe() - - -class CustomCurvesPack(Packable): - key: ClassVar[str] = "custom_curves" - - def _to_dataframe(self, columns="", **kwargs) -> pd.DataFrame: - """PACKS ONLY FIRST SCENARIO""" - for scenario in self.scenarios: - series_list = list(scenario.custom_curves_series()) - if len(series_list) == 0: - continue - return pd.concat(series_list, axis=1) - return pd.DataFrame() - - -class OutputCurvesPack(Packable): - key: ClassVar[str] = "output_curves" - - def _to_dataframe(self, columns="", **kwargs) -> pd.DataFrame: - """PACKS ONLY FIRST SCENARIO""" - for scenario in self.scenarios: - series_list = list(scenario.all_output_curves()) - if len(series_list) == 0: - continue - return pd.concat(series_list, axis=1) - return pd.DataFrame() +logger = logging.getLogger(__name__) class ScenarioPacker(BaseModel): """ Packs one or multiple scenarios for export to dataframes or excel - - TODO: This class doesn't inherit from Base so it doesn't use the warning system yet - consider this further. """ # To avoid keeping all in memory, the packer only remembers which scenarios @@ -145,7 +59,9 @@ def main_info(self) -> pd.DataFrame: if len(self._scenarios()) == 0: return pd.DataFrame() - return pd.concat([scenario.to_dataframe() for scenario in self._scenarios()], axis=1) + return pd.concat( + [scenario.to_dataframe() for scenario in self._scenarios()], axis=1 + ) def inputs(self, columns="user") -> pd.DataFrame: return self._inputs.to_dataframe(columns=columns) @@ -163,25 +79,34 @@ def output_curves(self) -> pd.DataFrame: return self._output_curves.to_dataframe() def to_excel(self, path: str): - """Export to Excel with simplified approach""" if len(self._scenarios()) == 0: raise ValueError("Packer was empty, nothing to export") workbook = Workbook(path) - sheet_configs = [ - ("MAIN", self.main_info), - ("PARAMETERS", self.inputs), - ("GQUERIES_RESULTS", self.gquery_results), - ("SORTABLES", self.sortables), - ("CUSTOM_CURVES", self.custom_curves), - ("OUTPUT_CURVES", self.output_curves), - ] + # Main info sheet (handled separately as it doesn't use a pack) + df = self.main_info() + if not df.empty: + df_filled = df.fillna("").infer_objects(copy=False) + add_frame( + name="MAIN", + frame=df_filled, + workbook=workbook, + column_width=18, + scenario_styling=True, + ) - for sheet_name, data_method in sheet_configs: - df = data_method() + for pack in self.all_pack_data(): + df = pack.to_dataframe() if not df.empty: - add_frame(sheet_name, df.fillna(""), workbook, column_width=18) + df_filled = df.fillna("").infer_objects(copy=False) + add_frame( + name=pack.sheet_name, + frame=df_filled, + workbook=workbook, + column_width=18, + scenario_styling=True, + ) workbook.close() @@ -220,3 +145,361 @@ def get_summary(self) -> Dict[str, Any]: summary["scenario_ids"] = sorted([s.id for s in self._scenarios()]) return summary + + def _first_non_empty_row_index(self, df: pd.DataFrame) -> Optional[int]: + if df is None: + return None + for idx, (_, row) in enumerate(df.iterrows()): + if not row.isna().all(): + return idx + return None + + def _is_empty_or_helper(self, col_name: Any, helper_names: set[str]) -> bool: + if not isinstance(col_name, str): + return True + name = col_name.strip().lower() + return name in (helper_names or set()) or name in {"", "nan"} + + def _normalize_sheet( + self, + df: pd.DataFrame, + *, + helper_names: set[str], + reset_index: bool = True, + rename_map: Optional[Dict[str, str]] = None, + ) -> pd.DataFrame: + if df is None: + return pd.DataFrame() + df = df.dropna(how="all") + if df.empty: + return df + + header_pos = self._first_non_empty_row_index(df) + if header_pos is None: + return pd.DataFrame() + + header = df.iloc[header_pos].astype(str).map(lambda s: s.strip()) + data = df.iloc[header_pos + 1 :].copy() + data.columns = header.values + + keep_cols = [ + col + for col in data.columns + if not self._is_empty_or_helper(col, helper_names) + ] + data = data[keep_cols] + + if rename_map: + data = data.rename(columns=rename_map) + + if reset_index: + data.reset_index(drop=True, inplace=True) + + return data + + def _coerce_bool(self, v: Any) -> Optional[bool]: + if v is None or (isinstance(v, float) and pd.isna(v)): + return None + if isinstance(v, bool): + return v + if isinstance(v, (int, float)): + return bool(int(v)) + if isinstance(v, str): + s = v.strip().lower() + if s in {"true", "yes", "y", "1"}: + return True + if s in {"false", "no", "n", "0"}: + return False + return None + + def _coerce_int(self, v: Any) -> Optional[int]: + if v is None or (isinstance(v, float) and pd.isna(v)): + return None + try: + return int(float(v)) + except (ValueError, TypeError): + return None + + def _load_or_create_scenario( + self, + sid: Optional[int], + area_code: Any, + end_year: Optional[int], + col_name: str, + ) -> Optional["Scenario"]: + scenario: Optional[Scenario] = None + if sid is not None: + try: + scenario = Scenario.load(sid) + except Exception as e: + logger.warning( + "Failed to load scenario %s for column '%s': %s", sid, col_name, e + ) + scenario = None + else: + if area_code and end_year is not None: + try: + scenario = Scenario.new(str(area_code), int(end_year)) + except Exception as e: + logger.warning( + "Failed to create scenario for column '%s' (area_code=%s, end_year=%s): %s", + col_name, + area_code, + end_year, + e, + ) + scenario = None + else: + logger.warning( + "MAIN column '%s' missing required fields for creation (area_code/end_year)", + col_name, + ) + scenario = None + return scenario + + def _collect_meta_updates( + self, + private: Optional[bool], + template: Optional[int], + source: Any, + title: Any, + ) -> Dict[str, Any]: + meta_updates: Dict[str, Any] = {} + if private is not None: + meta_updates["private"] = private + if template is not None: + meta_updates["template"] = template + if isinstance(source, str) and source.strip() != "": + meta_updates["source"] = source.strip() + if isinstance(title, str) and title.strip() != "": + meta_updates["title"] = title.strip() + return meta_updates + + def _apply_metadata( + self, scenario: "Scenario", meta_updates: Dict[str, Any] + ) -> None: + if not meta_updates: + return + try: + scenario.update_metadata(**meta_updates) + except Exception as e: + logger.warning( + "Failed to update metadata for '%s': %s", scenario.identifier(), e + ) + + def _extract_scenario_sheet_info( + self, main_df: pd.DataFrame + ) -> Dict[str, Dict[str, str]]: + scenario_sheets = {} + + if isinstance(main_df, pd.Series): + # Single scenario + identifier = str(main_df.name) + short_name = main_df.get("short_name") + sortables_sheet = main_df.get("sortables") + custom_curves_sheet = main_df.get("custom_curves") + + scenario_sheets[identifier] = { + "short_name": short_name if pd.notna(short_name) else identifier, + "sortables": sortables_sheet if pd.notna(sortables_sheet) else None, + "custom_curves": ( + custom_curves_sheet if pd.notna(custom_curves_sheet) else None + ), + } + else: + # Multiple scenarios + for identifier in main_df.columns: + col_data = main_df[identifier] + short_name = col_data.get("short_name") + sortables_sheet = col_data.get("sortables") + custom_curves_sheet = col_data.get("custom_curves") + + scenario_sheets[str(identifier)] = { + "short_name": ( + short_name if pd.notna(short_name) else str(identifier) + ), + "sortables": sortables_sheet if pd.notna(sortables_sheet) else None, + "custom_curves": ( + custom_curves_sheet if pd.notna(custom_curves_sheet) else None + ), + } + + return scenario_sheets + + def _process_single_scenario_sortables( + self, scenario: "Scenario", df: pd.DataFrame + ): + data = self._normalize_sheet( + df, + helper_names={"sortables", "hour", "index"}, + reset_index=True, + rename_map={"heat_network": "heat_network_lt"}, + ) + if data is None or data.empty: + return + scenario.set_sortables_from_dataframe(data) + + def _process_single_scenario_curves(self, scenario: "Scenario", df: pd.DataFrame): + data = self._normalize_sheet( + df, + helper_names={"curves", "custom_curves", "hour", "index"}, + reset_index=True, + ) + if data is None or data.empty: + return + # Build CustomCurves collection and apply + try: + curves = CustomCurves._from_dataframe(data, scenario_id=scenario.id) + scenario.update_custom_curves(curves) + except Exception as e: + logger.warning( + "Failed processing custom curves for '%s': %s", scenario.identifier(), e + ) + + @classmethod + def from_excel(cls, xlsx_path: PathLike | str) -> "ScenarioPacker": + packer = cls() + + try: + xls = pd.ExcelFile(xlsx_path) + except Exception as e: + logger.warning("Could not open Excel file '%s': %s", xlsx_path, e) + return packer + + # MAIN sheet + try: + main_df = xls.parse("MAIN", index_col=0) + except Exception as e: + logger.warning("Failed to parse MAIN sheet: %s", e) + return packer + + if main_df is None or getattr(main_df, "empty", False): + return packer + + # Build scenarios per MAIN column + scenarios_by_col: Dict[str, Scenario] = {} + for col in main_df.columns: + try: + scenario = packer._setup_scenario_from_main_column( + str(col), main_df[col] + ) + except Exception as e: + logger.warning("Failed to set up scenario for column '%s': %s", col, e) + continue + + if scenario is not None: + packer.add(scenario) + scenarios_by_col[str(col)] = scenario + + if len(scenarios_by_col) == 0: + return packer + + # Extract per-scenario sheet info and short_name mapping + sheet_info = packer._extract_scenario_sheet_info(main_df) + short_name_map: Dict[str, str] = {} + for col_name, scenario in scenarios_by_col.items(): + info = sheet_info.get(col_name, {}) if isinstance(sheet_info, dict) else {} + short = info.get("short_name") if isinstance(info, dict) else None + if short is None or (isinstance(short, float) and pd.isna(short)): + short = str(scenario.identifier()) + short_name_map[str(scenario.id)] = str(short) + + # PARAMETERS (inputs) sheet + params_df = None + try: + params_df = xls.parse(InputsPack.sheet_name, header=None) + except Exception: + params_df = None + + if params_df is not None and not params_df.empty: + try: + packer._inputs.set_scenario_short_names(short_name_map) + packer._inputs.from_dataframe(params_df) + except Exception as e: + logger.warning("Failed to import PARAMETERS: %s", e) + + # GQUERIES sheet (keys to attach to scenarios) + gq_df = None + for sheet in ("GQUERIES", QueryPack.sheet_name): + if sheet in xls.sheet_names: + try: + gq_df = xls.parse(sheet, header=None) + break + except Exception: + gq_df = None + if gq_df is not None and not gq_df.empty: + try: + qp = QueryPack(scenarios=packer._scenarios()) + qp.from_dataframe(gq_df) + except Exception as e: + logger.warning("Failed to import GQUERIES: %s", e) + + # Sortables and Custom Curves + for col_name, scenario in scenarios_by_col.items(): + info = sheet_info.get(col_name, {}) if isinstance(sheet_info, dict) else {} + + sortables_sheet = info.get("sortables") if isinstance(info, dict) else None + if isinstance(sortables_sheet, str) and sortables_sheet in xls.sheet_names: + try: + s_df = xls.parse(sortables_sheet, header=None) + self_ref = packer # clarity + self_ref._process_single_scenario_sortables(scenario, s_df) + except Exception as e: + logger.warning( + "Failed to process SORTABLES sheet '%s' for '%s': %s", + sortables_sheet, + scenario.identifier(), + e, + ) + + curves_sheet = info.get("custom_curves") if isinstance(info, dict) else None + if isinstance(curves_sheet, str) and curves_sheet in xls.sheet_names: + try: + c_df = xls.parse(curves_sheet, header=None) + self_ref = packer + self_ref._process_single_scenario_curves(scenario, c_df) + except Exception as e: + logger.warning( + "Failed to process CUSTOM_CURVES sheet '%s' for '%s': %s", + curves_sheet, + scenario.identifier(), + e, + ) + + return packer + + def _setup_scenario_from_main_column( + self, col_name: str, col_data: pd.Series + ) -> Optional[Scenario]: + scenario_id = ( + col_data.get("scenario_id") if isinstance(col_data, pd.Series) else None + ) + area_code = ( + col_data.get("area_code") if isinstance(col_data, pd.Series) else None + ) + end_year = ( + self._coerce_int(col_data.get("end_year")) + if isinstance(col_data, pd.Series) + else None + ) + private = ( + self._coerce_bool(col_data.get("private")) + if isinstance(col_data, pd.Series) + else None + ) + template = ( + self._coerce_int(col_data.get("template")) + if isinstance(col_data, pd.Series) + else None + ) + source = col_data.get("source") if isinstance(col_data, pd.Series) else None + title = col_data.get("title") if isinstance(col_data, pd.Series) else None + sid = self._coerce_int(scenario_id) + scenario = self._load_or_create_scenario(sid, area_code, end_year, col_name) + + if scenario is None: + return None + meta_updates = self._collect_meta_updates(private, template, source, title) + self._apply_metadata(scenario, meta_updates) + + return scenario diff --git a/src/pyetm/models/scenarios.py b/src/pyetm/models/scenarios.py new file mode 100644 index 0000000..94abc60 --- /dev/null +++ b/src/pyetm/models/scenarios.py @@ -0,0 +1,48 @@ +from __future__ import annotations +from os import PathLike +from typing import Iterable, Iterator, List +from pydantic import BaseModel, Field +from .scenario import Scenario + + +class Scenarios(BaseModel): + """ + A simple collection of Scenario objects with convenience utilities. + #TODO: Make a nice repr or stats functions + """ + + items: List[Scenario] = Field(default_factory=list) + + def __iter__(self) -> Iterator[Scenario]: + return iter(self.items) + + def __len__(self) -> int: + return len(self.items) + + def __getitem__(self, index: int) -> Scenario: + return self.items[index] + + def add(self, *scenarios: Scenario) -> None: + self.items.extend(scenarios) + + def extend(self, scenarios: Iterable[Scenario]) -> None: + self.items.extend(list(scenarios)) + + def to_excel(self, path: PathLike | str) -> None: + """ + Export all scenarios in this collection to an Excel workbook. + """ + from .scenario_packer import ScenarioPacker + + packer = ScenarioPacker() + if self.items: + packer.add(*self.items) + packer.to_excel(str(path)) + + @classmethod + def from_excel(cls, xlsx_path: PathLike | str) -> "Scenarios": + """ + Load or create scenarios from an Excel workbook and wrap them in Scenarios. + """ + scenarios = Scenario.load_from_excel(xlsx_path) + return cls(items=scenarios) diff --git a/src/pyetm/models/sortables.py b/src/pyetm/models/sortables.py index 9e1c559..ea46c14 100644 --- a/src/pyetm/models/sortables.py +++ b/src/pyetm/models/sortables.py @@ -83,13 +83,11 @@ def validate_order(cls, value: list[Any]) -> list[Any]: @model_validator(mode="after") def validate_sortable_consistency(self) -> "Sortable": """Additional validation for the entire sortable""" - # Example: validate that certain types require subtypes if self.type == "heat_network" and self.subtype is None: raise ValueError("heat_network type requires a subtype") - # TODO: check how long these actually ought to be - if len(self.order) > 10: - raise ValueError("Order cannot contain more than 10 items") + if len(self.order) > 17: + raise ValueError("Order cannot contain more than 17 items") return self @@ -261,3 +259,38 @@ def _to_dataframe(self, **kwargs) -> pd.DataFrame: return pd.DataFrame.from_dict( {s.name(): s.order for s in self.sortables}, orient="index" ).T + + @classmethod + def _from_dataframe(cls, df: pd.DataFrame, **kwargs) -> "Sortables": + if df is None: + return cls(sortables=[]) + + # Ensure DataFrame + if isinstance(df, pd.Series): + df = df.to_frame(name=str(df.name)) + + def _extract_order(series: pd.Series) -> List[Any]: + s = series.dropna() + if s.dtype == object: + s = s.astype(str).map(lambda v: v.strip()).replace({"": pd.NA}).dropna() + return s.tolist() + + items: List[Sortable] = [] + for col in df.columns: + name = str(col) + order = _extract_order(df[col]) + if not order: + continue + + if name.startswith("heat_network_"): + subtype = name[len("heat_network_") :] + items.append( + Sortable(type="heat_network", subtype=subtype, order=order) + ) + else: + items.append(Sortable(type=name, order=order)) + + return cls(sortables=items) + + def to_updates_dict(self) -> Dict[str, List[Any]]: + return {s.name(): s.order for s in self.sortables} diff --git a/src/pyetm/utils/excel.py b/src/pyetm/utils/excel.py index 0dc4b61..a0d6be5 100644 --- a/src/pyetm/utils/excel.py +++ b/src/pyetm/utils/excel.py @@ -69,6 +69,48 @@ def write_index( worksheet.write(row + row_offset, 0, value) +def create_scenario_formats(workbook: Workbook) -> dict: + """Create alternating background formats for scenario blocks""" + return { + "white_header": workbook.add_format( + {"bold": True, "bg_color": "#FFFFFF", "border": 1, "align": "center"} + ), + "grey_header": workbook.add_format( + {"bold": True, "bg_color": "#D9D9D9", "border": 1, "align": "center"} + ), + "white_data": workbook.add_format({"bg_color": "#FFFFFF", "border": 1}), + "grey_data": workbook.add_format({"bg_color": "#D9D9D9", "border": 1}), + "bold": workbook.add_format({"bold": True}), + "default": None, + } + + +def get_scenario_blocks(columns: pd.MultiIndex) -> List[tuple]: + """ + Identify scenario blocks in multi-index columns + Returns list of (scenario_name, start_col, end_col) tuples + """ + if not isinstance(columns, pd.MultiIndex): + return [] + + blocks = [] + current_scenario = None + start_col = None + + for i, (scenario, _) in enumerate(columns): + if scenario != current_scenario: + if current_scenario is not None: + blocks.append((current_scenario, start_col, i - 1)) + current_scenario = scenario + start_col = i + + # Add the last block + if current_scenario is not None: + blocks.append((current_scenario, start_col, len(columns) - 1)) + + return blocks + + def add_frame( name: str, frame: pd.DataFrame, @@ -80,8 +122,8 @@ def add_frame( bold_headers: bool = True, nan_as_formula: bool = True, decimal_precision: int = 10, + scenario_styling: bool = True, ) -> Worksheet: - """Add DataFrame to workbook as a new worksheet""" # Create worksheet worksheet = workbook.add_worksheet(str(name)) @@ -94,8 +136,15 @@ def add_frame( ), ) - # Create bold format - bold_format = workbook.add_format({"bold": True}) if bold_headers else None + # Create formats + formats = ( + create_scenario_formats(workbook) + if scenario_styling + else { + "bold": workbook.add_format({"bold": True}) if bold_headers else None, + "default": None, + } + ) # Calculate offsets col_offset = frame.index.nlevels if index else 0 @@ -105,39 +154,126 @@ def add_frame( if index and frame.index.names != [None] * frame.index.nlevels: row_offset += 1 - # Write column headers - if isinstance(frame.columns, pd.MultiIndex): + # Handle multi-index columns with scenario styling + if isinstance(frame.columns, pd.MultiIndex) and scenario_styling: + # Get scenario blocks for alternating colors + scenario_blocks = get_scenario_blocks(frame.columns) + # Write column names - if index and frame.columns.names != [None] * frame.columns.nlevels: + if frame.columns.names != [None] * frame.columns.nlevels: for idx, name in enumerate(frame.columns.names): if name is not None: - worksheet.write(idx, col_offset - 1, name, bold_format) + worksheet.write(idx, col_offset - 1, name, formats["bold"]) - # Write column values + # Write column headers with alternating scenario backgrounds for col_num, values in enumerate(frame.columns.values): + # Determine which scenario block this column belongs to + scenario_idx = next( + ( + i + for i, (_, start, end) in enumerate(scenario_blocks) + if start <= col_num <= end + ), + 0, + ) + is_grey = scenario_idx % 2 == 1 + header_format = ( + formats["grey_header"] if is_grey else formats["white_header"] + ) + for row_num, value in enumerate(values): - worksheet.write(row_num, col_num + col_offset, value, bold_format) + worksheet.write(row_num, col_num + col_offset, value, header_format) + + # Write data with scenario block coloring + for row_num, row_data in enumerate(frame.values): + for col_num, value in enumerate(row_data): + # Determine scenario block + scenario_idx = next( + ( + i + for i, (_, start, end) in enumerate(scenario_blocks) + if start <= col_num <= end + ), + 0, + ) + is_grey = scenario_idx % 2 == 1 + data_format = formats["grey_data"] if is_grey else formats["white_data"] + + worksheet.write( + row_num + row_offset, col_num + col_offset, value, data_format + ) + else: - # Write simple column headers - for col_num, value in enumerate(frame.columns.values): - worksheet.write(row_offset - 1, col_num + col_offset, value, bold_format) + # Standard column handling or single-index scenario styling + bold_format = formats.get("bold") if bold_headers else None + + if isinstance(frame.columns, pd.MultiIndex): + # Write column names without styling + if frame.columns.names != [None] * frame.columns.nlevels: + for idx, name in enumerate(frame.columns.names): + if name is not None: + worksheet.write(idx, col_offset - 1, name, bold_format) + + # Write column values + for col_num, values in enumerate(frame.columns.values): + for row_num, value in enumerate(values): + worksheet.write(row_num, col_num + col_offset, value, bold_format) + + # Write data without styling + for row_num, row_data in enumerate(frame.values): + for col_num, value in enumerate(row_data): + worksheet.write(row_num + row_offset, col_num + col_offset, value) + else: + # Single-level columns + if scenario_styling: + # Alternate header backgrounds by scenario column + for col_num, value in enumerate(frame.columns.values): + is_grey = (col_num % 2) == 1 + header_format = ( + formats["grey_header"] if is_grey else formats["white_header"] + ) + worksheet.write( + row_offset - 1, col_num + col_offset, value, header_format + ) + + # Alternate data backgrounds by scenario column + for row_num, row_data in enumerate(frame.values): + for col_num, value in enumerate(row_data): + is_grey = (col_num % 2) == 1 + data_format = ( + formats["grey_data"] if is_grey else formats["white_data"] + ) + worksheet.write( + row_num + row_offset, + col_num + col_offset, + value, + data_format, + ) + else: + # No scenario styling: write simple headers and data + for col_num, value in enumerate(frame.columns.values): + worksheet.write( + row_offset - 1, col_num + col_offset, value, bold_format + ) + + for row_num, row_data in enumerate(frame.values): + for col_num, value in enumerate(row_data): + worksheet.write( + row_num + row_offset, col_num + col_offset, value + ) # Set column widths set_column_widths(worksheet, col_offset, len(frame.columns), column_width) - # Write data - for row_num, row_data in enumerate(frame.values): - for col_num, value in enumerate(row_data): - worksheet.write(row_num + row_offset, col_num + col_offset, value) - - # Write index if index: set_column_widths( worksheet, 0, frame.index.nlevels, index_width or column_width ) - write_index(worksheet, frame.index, row_offset, bold_format) - # Freeze panes + # Create index format matching the styling + index_format = formats.get("bold") if bold_headers else None + write_index(worksheet, frame.index, row_offset, index_format) + if freeze_panes: worksheet.freeze_panes(row_offset, col_offset) @@ -156,7 +292,6 @@ def add_series( nan_as_formula: bool = True, decimal_precision: int = 10, ) -> Worksheet: - """Add Series to workbook as a new worksheet""" # Create worksheet worksheet = workbook.add_worksheet(str(name)) diff --git a/tests/models/packables/test_custom_curves_pack.py b/tests/models/packables/test_custom_curves_pack.py new file mode 100644 index 0000000..75c5bdf --- /dev/null +++ b/tests/models/packables/test_custom_curves_pack.py @@ -0,0 +1,81 @@ +import pandas as pd +from pyetm.models.packables.custom_curves_pack import CustomCurvesPack + + +class MockScenario: + def __init__(self, id="id1"): + self.id = id + self.curves_updated_with = None + self.custom_series_called = False + + def custom_curves_series(self): + self.custom_series_called = True + return [pd.Series([1, 2, 3], name="curve1")] + + def identifier(self): + return f"scenario-{self.id}" + + def update_custom_curves(self, curves): + self.curves_updated_with = curves + + +class MockCustomCurves: + @staticmethod + def _from_dataframe(df, scenario_id=None): + return {"built_from": df.copy(), "scenario_id": scenario_id} + + +def test_build_dataframe_for_scenario_returns_concatenated_df(monkeypatch): + pack = CustomCurvesPack() + scenario = MockScenario() + + df = pack._build_dataframe_for_scenario(scenario) + assert isinstance(df, pd.DataFrame) + assert "curve1" in df.columns + assert scenario.custom_series_called + + +def test_build_dataframe_for_scenario_returns_none_if_exception(monkeypatch): + pack = CustomCurvesPack() + + def bad_series(): + raise RuntimeError("bad") + + scenario = MockScenario() + scenario.custom_curves_series = bad_series + + result = pack._build_dataframe_for_scenario(scenario) + assert result is None + + +def test_build_dataframe_for_scenario_returns_none_if_empty(monkeypatch): + pack = CustomCurvesPack() + + def empty_series(): + return [] + + scenario = MockScenario() + scenario.custom_curves_series = empty_series + + result = pack._build_dataframe_for_scenario(scenario) + assert result is None + + +def test_from_dataframe_returns_early_for_none_df(): + pack = CustomCurvesPack() + assert pack.from_dataframe(None) is None + + +def test_from_dataframe_returns_early_for_empty_df(): + pack = CustomCurvesPack() + df = pd.DataFrame() + assert pack.from_dataframe(df) is None + + +def test_from_dataframe_returns_early_if_not_multiindex(monkeypatch): + pack = CustomCurvesPack() + + monkeypatch.setattr(pack, "_normalize_curves_dataframe", lambda df: df) + + df = pd.DataFrame({"a": [1, 2]}) + assert pack.from_dataframe(df) is None diff --git a/tests/models/packables/test_gquery_pack.py b/tests/models/packables/test_gquery_pack.py new file mode 100644 index 0000000..f548344 --- /dev/null +++ b/tests/models/packables/test_gquery_pack.py @@ -0,0 +1,85 @@ +import pandas as pd + + +class MockScenario: + def __init__(self): + self.received_queries = None + + def add_queries(self, queries): + self.received_queries = queries + + +class DummyClass: + def __init__(self, scenarios): + self.scenarios = scenarios + + def from_dataframe(self, df: pd.DataFrame): + if df is None or df.empty: + return + + first_col = df.iloc[:, 0].dropna().astype(str).str.strip() + + # Filter out empty strings and literal "nan" + filtered = [q for q in first_col if q and q.lower() != "nan"] + + # Remove duplicates while preserving order + unique_queries = list(dict.fromkeys(filtered)) + + if unique_queries: + for scenario in self.scenarios: + scenario.add_queries(unique_queries) + + +def test_from_dataframe_with_valid_data(): + scenario1 = MockScenario() + scenario2 = MockScenario() + obj = DummyClass([scenario1, scenario2]) + + df = pd.DataFrame({"queries": ["q1", " q2 ", "q1", None, "nan", " "]}) + + obj.from_dataframe(df) + + expected = ["q1", "q2"] + assert scenario1.received_queries == expected + assert scenario2.received_queries == expected + + +def test_from_dataframe_with_empty_df(): + scenario = MockScenario() + obj = DummyClass([scenario]) + + df = pd.DataFrame({"queries": []}) + obj.from_dataframe(df) + + assert scenario.received_queries is None + + +def test_from_dataframe_with_none_df(): + scenario = MockScenario() + obj = DummyClass([scenario]) + + obj.from_dataframe(None) + + assert scenario.received_queries is None + + +def test_from_dataframe_strips_and_deduplicates(): + scenario = MockScenario() + obj = DummyClass([scenario]) + + df = pd.DataFrame({"queries": [" a ", "a", "b", " B ", "nan", "NaN"]}) + + obj.from_dataframe(df) + + assert scenario.received_queries == ["a", "b", "B"] + + +def test_from_dataframe_preserves_order(): + scenario = MockScenario() + obj = DummyClass([scenario]) + + df = pd.DataFrame({"queries": ["x", "y", "z", "x", "y"]}) + + obj.from_dataframe(df) + + assert scenario.received_queries == ["x", "y", "z"] diff --git a/tests/models/packables/test_inputs_pack.py b/tests/models/packables/test_inputs_pack.py new file mode 100644 index 0000000..222f020 --- /dev/null +++ b/tests/models/packables/test_inputs_pack.py @@ -0,0 +1,172 @@ +import pandas as pd +from unittest.mock import Mock + +from pyetm.models.packables.inputs_pack import InputsPack + + +class DummyInput: + def __init__(self, key, user): + self.key = key + self.user = user + + +def make_scenario(id_val, identifier=None): + s = Mock() + s.id = id_val + if identifier is None: + s.identifier = Mock(return_value=str(id_val)) + else: + s.identifier = ( + Mock(side_effect=identifier) + if callable(identifier) + else Mock(return_value=identifier) + ) + s.update_user_values = Mock() + return s + + +def test_key_for_prefers_short_name_and_fallbacks(): + s1 = make_scenario(1, identifier="id-1") + s2 = make_scenario(2, identifier="id-2") + + pack = InputsPack() + pack.set_scenario_short_names({"1": "S1"}) + + assert pack._key_for(s1) == "S1" # short name wins + assert pack._key_for(s2) == "id-2" # falls back to identifier + + s3 = make_scenario( + 3, identifier=lambda: (_ for _ in ()).throw(RuntimeError("boom")) + ) + assert pack._key_for(s3) == 3 # falls back to id when identifier fails + + +def test_resolve_scenario_by_short_identifier_and_numeric(): + s1, s2, s3 = ( + make_scenario(1, "ID1"), + make_scenario(2, "ID2"), + make_scenario(3, "ID3"), + ) + pack = InputsPack() + pack.add(s1, s2, s3) + pack.set_scenario_short_names({"1": "S1"}) + + assert pack.resolve_scenario("S1") is s1 # short name + assert pack.resolve_scenario("ID2") is s2 # identifier + assert pack.resolve_scenario("3") is s3 # numeric id + assert pack.resolve_scenario("missing") is None + + +def test_to_dataframe_from_iterable_inputs_only(): + s = make_scenario(1, "S1") + s.inputs = [DummyInput("a", 10), DummyInput("b", 20)] + + pack = InputsPack() + pack.add(s) + df = pack.to_dataframe() + + assert list(df.index) == ["a", "b"] + assert "S1" in df.columns or 1 in df.columns + col = "S1" if "S1" in df.columns else 1 + assert df.loc["a", col] == 10 + assert df.loc["b", col] == 20 + assert df.index.name == "input" + + +def test_to_dataframe_from_df_and_series_variants(): + s1 = make_scenario(1, "S1") + s1.inputs = Mock() + s1.inputs.__iter__ = Mock(side_effect=TypeError()) + s1.inputs.to_dataframe = Mock( + return_value=pd.DataFrame( + {"user": [1, 2], "unit": ["MW", "MW"]}, index=["a", "b"] + ).set_index("unit", append=True) + ) + + s2 = make_scenario(2, "S2") + s2.inputs = Mock() + s2.inputs.__iter__ = Mock(side_effect=TypeError()) + s2.inputs.to_dataframe = Mock( + return_value=pd.DataFrame({"value": [3, 4]}, index=["c", "d"]) + ) + + # From Series + s3 = make_scenario(3, "S3") + s3.inputs = Mock() + s3.inputs.__iter__ = Mock(side_effect=TypeError()) + s3.inputs.to_dataframe = Mock(return_value=pd.Series([5], index=["e"])) + + pack = InputsPack() + pack.add(s1, s2, s3) + df = pack.to_dataframe() + + # All keys present + for key in ["a", "b", "c", "d", "e"]: + assert key in df.index + + assert df.loc["a", "S1"] == 1 + assert df.loc["c", "S2"] == 3 + assert df.loc["e", "S3"] == 5 + + +def test_to_dataframe_returns_empty_when_no_data(): + s = make_scenario(1, "S1") + s.inputs = Mock() + s.inputs.__iter__ = Mock(side_effect=TypeError()) + s.inputs.to_dataframe = Mock(return_value=pd.DataFrame()) + + pack = InputsPack() + pack.add(s) + df = pack.to_dataframe() + assert df.empty + + +def test_from_dataframe_parses_and_updates(caplog): + s1 = make_scenario(1, "S1") + s2 = make_scenario(2, "S2") + s3 = make_scenario(3, "S3") + + pack = InputsPack() + pack.add(s1, s2, s3) + pack.set_scenario_short_names({"1": "Short1"}) + + df = pd.DataFrame( + [ + ["input", "Short1", "3", "Unknown"], + ["a", 1, 10, 99], + ["b", " ", "nan", 88], + ] + ) + + with caplog.at_level("WARNING"): + pack.from_dataframe(df) + + s1.update_user_values.assert_called_once_with({"a": 1}) + s3.update_user_values.assert_called_once_with({"a": 10}) + # Unknown column should produce a warning and not call any scenario + assert "Could not find scenario for PARAMETERS column label" in caplog.text + + +def test_from_dataframe_handles_update_exception(caplog): + s1 = make_scenario(1, "S1") + s1.update_user_values.side_effect = RuntimeError("fail") + + pack = InputsPack() + pack.add(s1) + + df = pd.DataFrame([["input", "S1"], ["a", 1]]) + + with caplog.at_level("WARNING"): + pack.from_dataframe(df) + assert "Failed updating inputs for scenario" in caplog.text + + +def test_from_dataframe_early_returns(): + pack = InputsPack() + # None and empty + pack.from_dataframe(None) + pack.from_dataframe(pd.DataFrame()) + # No header rows + pack.from_dataframe(pd.DataFrame([[None], [None]])) + # After header but no data columns + pack.from_dataframe(pd.DataFrame([["only-one-col"], [1]])) diff --git a/tests/models/packables/test_output_curves_pack.py b/tests/models/packables/test_output_curves_pack.py new file mode 100644 index 0000000..160682d --- /dev/null +++ b/tests/models/packables/test_output_curves_pack.py @@ -0,0 +1,43 @@ +import pandas as pd +from unittest.mock import Mock + +from pyetm.models.packables.output_curves_pack import OutputCurvesPack + + +def make_scenario(id_val="S"): + s = Mock() + s.identifier = Mock(return_value=str(id_val)) + return s + + +def test_to_dataframe_collects_series(): + s = make_scenario() + s.all_output_curves.return_value = [ + pd.Series([1, 2], name="c1"), + pd.Series([3, 4], name="c2"), + ] + + pack = OutputCurvesPack() + pack.add(s) + + df = pack.to_dataframe() + assert not df.empty + assert "c1" in df.columns.get_level_values(1) or "c1" in df.columns + + +def test_to_dataframe_handles_exception_and_empty(caplog): + s = make_scenario() + s.all_output_curves.side_effect = RuntimeError("fail") + + pack = OutputCurvesPack() + pack.add(s) + + with caplog.at_level("WARNING"): + df = pack.to_dataframe() + assert df.empty + assert "Failed extracting output curves" in caplog.text + + s.all_output_curves.side_effect = None + s.all_output_curves.return_value = [] + df2 = pack.to_dataframe() + assert df2.empty diff --git a/tests/models/packables/test_packable.py b/tests/models/packables/test_packable.py new file mode 100644 index 0000000..e1f7cb6 --- /dev/null +++ b/tests/models/packables/test_packable.py @@ -0,0 +1,221 @@ +import pytest +import pandas as pd +from pyetm.models.packables.packable import Packable + + +class MockScenario: + def __init__(self, id): + self._id = id + + def identifier(self): + return self._id + + +@pytest.fixture +def packable(): + return Packable() + + +def test_add_discard_clear(packable): + s1 = MockScenario("a") + s2 = MockScenario("b") + + packable.add(s1) + assert s1 in packable.scenarios + assert packable._scenario_id_cache is None + + packable.add(s2) + assert s2 in packable.scenarios + + packable.discard(s1) + assert s1 not in packable.scenarios + assert packable._scenario_id_cache is None + + packable.clear() + assert len(packable.scenarios) == 0 + assert packable._scenario_id_cache is None + + +def test_summary(packable): + s1 = MockScenario("id1") + s2 = MockScenario("id2") + packable.add(s1, s2) + summary = packable.summary() + assert "base_pack" in summary + assert summary["base_pack"]["scenario_count"] == 2 + + +def test_key_for_returns_identifier(packable): + s = MockScenario("sc1") + assert packable._key_for(s) == "sc1" + + +def test_build_pack_dataframe_calls_and_concat(monkeypatch, packable): + s1 = MockScenario("sc1") + s2 = MockScenario("sc2") + packable.add(s1, s2) + + # Mock _build_dataframe_for_scenario to return a simple df + def fake_build_df(scenario, **kwargs): + return pd.DataFrame({f"{scenario.identifier()}_col": [1, 2]}) + + monkeypatch.setattr(packable, "_build_dataframe_for_scenario", fake_build_df) + monkeypatch.setattr(packable, "_concat_frames", lambda frames, keys: (frames, keys)) + + frames, keys = packable.build_pack_dataframe() + + assert isinstance(frames[0], pd.DataFrame) + assert keys == ["sc1", "sc2"] or keys == ["sc2", "sc1"] # order not guaranteed + + +def test_build_pack_dataframe_skips_none_empty(monkeypatch, packable): + s = MockScenario("sc") + packable.add(s) + + monkeypatch.setattr(packable, "_build_dataframe_for_scenario", lambda s, **kw: None) + df = packable.build_pack_dataframe() + assert df.empty + + monkeypatch.setattr( + packable, "_build_dataframe_for_scenario", lambda s, **kw: pd.DataFrame() + ) + df = packable.build_pack_dataframe() + assert df.empty + + +def test_build_pack_dataframe_handles_exceptions(monkeypatch, packable): + s = MockScenario("sc") + packable.add(s) + + def raise_exc(scenario, **kwargs): + raise RuntimeError("fail") + + monkeypatch.setattr(packable, "_build_dataframe_for_scenario", raise_exc) + + # Should not raise, just skip scenario + df = packable.build_pack_dataframe() + assert df.empty + + +def test_to_dataframe_returns_empty_if_no_scenarios(monkeypatch, packable): + assert packable.to_dataframe().empty + + monkeypatch.setattr( + packable, "_to_dataframe", lambda **kwargs: pd.DataFrame({"a": [1]}) + ) + packable.add(MockScenario("sc")) + df = packable.to_dataframe() + assert "a" in df.columns + + +def test_refresh_cache_and_find_by_identifier(packable): + s1 = MockScenario("sc1") + s2 = MockScenario("sc2") + packable.add(s1, s2) + + packable._scenario_id_cache = None + packable._refresh_cache() + + assert "sc1" in packable._scenario_id_cache + assert packable._find_by_identifier("sc2") == s2 + assert packable._find_by_identifier("missing") is None + + +def test_resolve_scenario(packable): + s = MockScenario("foo") + packable.add(s) + assert packable.resolve_scenario("foo") == s + assert packable.resolve_scenario(None) is None + assert packable.resolve_scenario("bar") is None + + +def test_is_blank(): + assert Packable.is_blank(None) + assert Packable.is_blank(float("nan")) + assert Packable.is_blank("") + assert Packable.is_blank(" ") + assert not Packable.is_blank("x") + assert not Packable.is_blank(123) + + +def test_drop_all_blank(): + df = pd.DataFrame({"a": [None, None], "b": [None, None]}) + result = Packable.drop_all_blank(df) + assert result.empty + + df2 = pd.DataFrame({"a": [None, 1], "b": [None, 2]}) + result2 = Packable.drop_all_blank(df2) + assert len(result2) == 1 + + +def test_first_non_empty_row_positions(): + df = pd.DataFrame({"a": [None, 1, 2], "b": [None, None, 3]}) + positions = Packable.first_non_empty_row_positions(df, count=2) + assert positions == [1, 2] + + positions = Packable.first_non_empty_row_positions(pd.DataFrame(), count=2) + assert positions == [] + + +def test_apply_identifier_blocks(monkeypatch, packable): + s1 = MockScenario("sc1") + s2 = MockScenario("sc2") + packable.add(s1, s2) + + columns = pd.MultiIndex.from_tuples( + [("sc1", "a"), ("sc1", "b"), ("sc2", "a")], names=["id", "curve"] + ) + df = pd.DataFrame([[1, 2, 3], [4, 5, 6]], columns=columns) + + called = {} + + def apply_block(scenario, block): + called[scenario.identifier()] = block.sum().sum() + + packable.apply_identifier_blocks(df, apply_block) + + assert "sc1" in called + assert "sc2" in called + + # Test with resolve function overriding + def resolve_override(label): + return s1 if label == "sc1" else None + + called.clear() + packable.apply_identifier_blocks(df, apply_block, resolve=resolve_override) + assert "sc1" in called + assert "sc2" in called + + # Test with non-MultiIndex columns + packable.apply_identifier_blocks(pd.DataFrame({"a": [1, 2]}), apply_block) + + +def test_apply_identifier_blocks_logs(monkeypatch, caplog, packable): + s1 = MockScenario("sc1") + packable.add(s1) + + columns = pd.MultiIndex.from_tuples([("sc1", "a")], names=["id", "curve"]) + df = pd.DataFrame([[1]], columns=columns) + + def fail_block(scenario, block): + raise ValueError("fail") + + with caplog.at_level("WARNING"): + packable.apply_identifier_blocks(df, fail_block) + assert "Failed applying block" in caplog.text + + +def test_normalize_single_header_sheet(packable): + df = pd.DataFrame( + [ + ["col1", "col2", "helper"], + [1, 2, 3], + [4, 5, 6], + ] + ) + result = packable._normalize_single_header_sheet( + df, helper_columns={"helper"}, reset_index=True + ) + assert list(result.columns) == ["col1", "col2"] + assert result.shape == (2, 2) + assert result.index.equals(pd.RangeIndex(0, 2)) diff --git a/tests/models/packables/test_query_pack.py b/tests/models/packables/test_query_pack.py new file mode 100644 index 0000000..e046620 --- /dev/null +++ b/tests/models/packables/test_query_pack.py @@ -0,0 +1,63 @@ +import pandas as pd +from unittest.mock import Mock + +from pyetm.models.packables.query_pack import QueryPack + + +def make_scenario(id_val="S"): + s = Mock() + s.identifier = Mock(return_value=str(id_val)) + s.results = Mock( + return_value=pd.DataFrame( + {"future": [1], "unit": ["MW"]}, index=["q1"] + ).set_index("unit", append=True) + ) + s.add_queries = Mock() + return s + + +def test_to_dataframe_calls_results_and_builds(caplog): + s1 = make_scenario("S1") + s2 = make_scenario("S2") + + pack = QueryPack() + pack.add(s1, s2) + + df = pack.to_dataframe() + assert not df.empty + assert "S1" in df.columns or "S2" in df.columns + + +def test_to_dataframe_handles_exception(caplog): + s = make_scenario() + s.results.side_effect = RuntimeError("bad") + + pack = QueryPack() + pack.add(s) + + with caplog.at_level("WARNING"): + df = pack.to_dataframe() + assert df.empty + assert "Failed building gquery results" in caplog.text + + +def test_from_dataframe_applies_unique_queries(): + s1 = make_scenario() + s2 = make_scenario() + + pack = QueryPack() + pack.add(s1, s2) + + df = pd.DataFrame({"queries": ["a", " a ", "b", None, "nan", "B"]}) + pack.from_dataframe(df) + + # Should deduplicate and strip, keep case of non-'nan' values + expected = ["a", "b", "B"] + s1.add_queries.assert_called_once_with(expected) + s2.add_queries.assert_called_once_with(expected) + + +def test_from_dataframe_early_returns(): + pack = QueryPack() + pack.from_dataframe(None) + pack.from_dataframe(pd.DataFrame()) diff --git a/tests/models/packables/test_sortable_pack.py b/tests/models/packables/test_sortable_pack.py new file mode 100644 index 0000000..6f7eda2 --- /dev/null +++ b/tests/models/packables/test_sortable_pack.py @@ -0,0 +1,77 @@ +import pandas as pd +from unittest.mock import Mock + +from pyetm.models.packables.sortable_pack import SortablePack + + +def make_scenario(id_val="S1"): + s = Mock() + s.identifier = Mock(return_value=str(id_val)) + s.sortables = Mock() + return s + + +def test_to_dataframe_builds_from_scenarios(): + s1 = make_scenario("S1") + s2 = make_scenario("S2") + s1.sortables.to_dataframe.return_value = pd.DataFrame({"a": [1]}) + s2.sortables.to_dataframe.return_value = pd.DataFrame({"b": [2]}) + + pack = SortablePack() + pack.add(s1, s2) + + df = pack.to_dataframe() + assert not df.empty + + +def test_to_dataframe_handles_exception_and_empty(caplog): + s = make_scenario("S") + s.sortables.to_dataframe.side_effect = RuntimeError("boom") + pack = SortablePack() + pack.add(s) + + with caplog.at_level("WARNING"): + df = pack.to_dataframe() + assert df.empty + assert "Failed extracting sortables" in caplog.text + + s.sortables.to_dataframe.side_effect = None + s.sortables.to_dataframe.return_value = pd.DataFrame() + df2 = pack.to_dataframe() + assert df2.empty + + +def test_from_dataframe_multiindex_and_single_block(monkeypatch): + s1 = make_scenario("S1") + s2 = make_scenario("S2") + pack = SortablePack() + pack.add(s1, s2) + cols = pd.MultiIndex.from_tuples([("S1", "a"), ("S2", "a")]) + df = pd.DataFrame([[1, 2]], columns=cols) + monkeypatch.setattr(pack, "_normalize_sortables_dataframe", lambda d: d) + pack.from_dataframe(df) + + assert s1.set_sortables_from_dataframe.called + assert s2.set_sortables_from_dataframe.called + + +def test_from_dataframe_normalize_errors_and_empty(caplog, monkeypatch): + s = make_scenario("S") + pack = SortablePack() + pack.add(s) + + with caplog.at_level("WARNING"): + monkeypatch.setattr( + pack, + "_normalize_sortables_dataframe", + lambda d: (_ for _ in ()).throw(RuntimeError("bad")), + ) + pack.from_dataframe(pd.DataFrame([[1]])) + assert "Failed to normalize sortables sheet" in caplog.text + + # empty after normalize + monkeypatch.setattr( + pack, "_normalize_sortables_dataframe", lambda d: pd.DataFrame() + ) + pack.from_dataframe(pd.DataFrame([[1]])) + assert not s.set_sortables_from_dataframe.called diff --git a/tests/models/test_scenario_packer.py b/tests/models/test_scenario_packer.py index b54503f..919a38f 100644 --- a/tests/models/test_scenario_packer.py +++ b/tests/models/test_scenario_packer.py @@ -1,6 +1,5 @@ import pytest import pandas as pd -import numpy as np import tempfile import os from unittest.mock import Mock, patch @@ -11,6 +10,9 @@ SortablePack, ) from pyetm.models import ScenarioPacker, Scenario +from pyetm.models.packables.inputs_pack import InputsPack +from pyetm.models.packables.query_pack import QueryPack +from pyetm.models.custom_curves import CustomCurves class TestScenarioPackerInit: @@ -188,13 +190,14 @@ def test_inputs_no_input_scenarios(self, sample_scenario): def test_inputs_single_scenario(self, scenario_with_inputs): """Test inputs with single scenario""" mock_df = pd.DataFrame( - {"value": [1000, 2000], "unit": ["MW", "MW"], "default": [500, 800]}, + {"user": [1000, 2000], "unit": ["MW", "MW"], "default": [500, 800]}, index=["wind_capacity", "solar_capacity"], ) mock_df.index.name = "input" final_df = mock_df.set_index("unit", append=True) scenario_with_inputs.inputs.to_dataframe = Mock(return_value=final_df) + scenario_with_inputs.identifier = Mock(return_value=scenario_with_inputs.id) packer = ScenarioPacker() packer.add_inputs(scenario_with_inputs) @@ -203,8 +206,6 @@ def test_inputs_single_scenario(self, scenario_with_inputs): assert not result.empty assert "input" in result.index.names - assert (scenario_with_inputs.id, "value") in result.columns - assert (scenario_with_inputs.id, "default") in result.columns def test_inputs_multiple_scenarios(self, multiple_scenarios): """Test inputs with multiple scenarios""" @@ -228,22 +229,19 @@ def test_inputs_multiple_scenarios(self, multiple_scenarios): result = packer.inputs() - # Should have unit column plus value/default for each scenario - expected_columns = ( - [("unit", "")] - + [(s.id, "value") for s in multiple_scenarios] - + [(s.id, "default") for s in multiple_scenarios] - ) - assert len(result.columns) >= len(multiple_scenarios) * 2 - - # Should have all unique input keys - all_keys = { - ("wind_capacity", "MW"), - ("unique_input_0", "GW"), - ("unique_input_1", "GW"), - ("unique_input_2", "GW"), + assert set(result.columns) == {s.id for s in multiple_scenarios} + + expected_keys = { + "wind_capacity", + "unique_input_0", + "unique_input_1", + "unique_input_2", } - assert set(result.index) == all_keys + assert set(result.index) == expected_keys + + for i, s in enumerate(multiple_scenarios): + assert result.loc["wind_capacity", s.id] == 1000 + i * 100 + assert result.loc[f"unique_input_{i}", s.id] == i * 10 class TestGqueryResults: @@ -269,6 +267,7 @@ def test_gquery_results_no_queries(self, sample_scenario): def test_gquery_results_single_scenario(self, scenario_with_queries): """Test gquery_results with single scenario""" + scenario_with_queries.identifier = Mock(return_value=scenario_with_queries.id) packer = ScenarioPacker() packer.add(scenario_with_queries) @@ -288,6 +287,7 @@ def test_gquery_results_multiple_scenarios(self): scenario.area_code = "nl2015" scenario.end_year = 2050 scenario.start_year = 2019 + scenario.identifier = Mock(return_value=scenario.id) mock_results = pd.DataFrame( {"future": [100 + i * 10, 200 + i * 20], "unit": ["MW", "GWh"]}, @@ -366,11 +366,16 @@ def test_custom_curves_with_series(self, sample_scenario): packer = ScenarioPacker() packer.add_custom_curves(sample_scenario) - result = packer.custom_curves() + assert not result.empty - assert "curve1" in result.columns - assert "curve2" in result.columns + if isinstance(result.columns, pd.MultiIndex): + level_1 = result.columns.get_level_values(1) + assert "curve1" in level_1 + assert "curve2" in level_1 + else: + assert "curve1" in result.columns + assert "curve2" in result.columns def test_output_curves_empty(self): """Test output_curves with no scenarios""" @@ -388,8 +393,12 @@ def test_output_curves_with_series(self, sample_scenario): packer = ScenarioPacker() packer.add_output_curves(sample_scenario) result = packer.output_curves() + assert not result.empty - assert "output_curve" in result.columns + if isinstance(result.columns, pd.MultiIndex): + assert "output_curve" in result.columns.get_level_values(1) + else: + assert "output_curve" in result.columns class TestExcelExport: @@ -446,6 +455,7 @@ def test_to_excel_sheet_types(self): scenario.area_code = "nl2015" scenario.end_year = 2050 scenario.start_year = 2019 + scenario.identifier = Mock(return_value=scenario.id) # Mock all data methods to return non-empty DataFrames scenario.to_dataframe = Mock( @@ -567,3 +577,608 @@ def test_get_summary_with_data(self, multiple_scenarios): assert summary["output_curves"]["scenario_count"] == 1 # scenario 2 only assert len(summary["scenario_ids"]) == 3 assert all(s.id in summary["scenario_ids"] for s in multiple_scenarios) + + +class TestFromExcel: + def test_from_excel(self): + ScenarioPacker.from_excel("tests/fixtures/my_input_excel.xlsx") + + +class TestScenarioPackerHelpers: + + def test_first_non_empty_row_index(self): + packer = ScenarioPacker() + + assert packer._first_non_empty_row_index(None) is None + + empty = pd.DataFrame([[float("nan")], [float("nan")]]) + assert packer._first_non_empty_row_index(empty) is None + + def test_is_empty_or_helper(self): + packer = ScenarioPacker() + helpers = {"sortables", "hour", "index"} + + assert packer._is_empty_or_helper(123, helpers) is True + assert packer._is_empty_or_helper(" ", helpers) is True + assert packer._is_empty_or_helper("NaN", helpers) is True + assert packer._is_empty_or_helper("hour", helpers) is True + assert packer._is_empty_or_helper("value", helpers) is False + + def test_normalize_sheet(self): + packer = ScenarioPacker() + + # None -> empty + assert packer._normalize_sheet(None, helper_names=set()).empty + + # Build a frame with header at row 1 (0-based) + raw = pd.DataFrame( + [ + [None, None, None], + ["index", "heat_network", "value"], # header + [1, "hn", 10], + [2, "hn", 20], + ] + ) + + norm = packer._normalize_sheet( + raw, + helper_names={"index"}, + reset_index=False, + rename_map={"heat_network": "heat_network_lt"}, + ) + + # index column removed, rename applied, index preserved + assert list(norm.columns) == ["heat_network_lt", "value"] + assert norm.index.tolist() == [2, 3] # original DataFrame indices kept + + def test_coerce_bool(self): + packer = ScenarioPacker() + na = float("nan") + assert packer._coerce_bool(None) is None + assert packer._coerce_bool(na) is None + assert packer._coerce_bool(True) is True + assert packer._coerce_bool(False) is False + assert packer._coerce_bool(1) is True + assert packer._coerce_bool(0.0) is False + assert packer._coerce_bool("yes") is True + assert packer._coerce_bool("No") is False + assert packer._coerce_bool("1") is True + assert packer._coerce_bool("maybe") is None + + def test_coerce_int(self): + packer = ScenarioPacker() + na = float("nan") + assert packer._coerce_int(None) is None + assert packer._coerce_int(na) is None + assert packer._coerce_int(5) == 5 + assert packer._coerce_int(5.9) == 5 + assert packer._coerce_int("7") == 7 + assert packer._coerce_int("abc") is None + + def test_load_or_create_scenario_load_new_and_failures(self, monkeypatch): + packer = ScenarioPacker() + + loaded = Mock(spec=Scenario) + created = Mock(spec=Scenario) + + # Successful load + monkeypatch.setattr(Scenario, "load", staticmethod(lambda sid: loaded)) + out = packer._load_or_create_scenario(42, "nl2015", 2050, "COL") + assert out is loaded + + # Failing load -> None + def boom(_): + raise RuntimeError("bad") + + monkeypatch.setattr(Scenario, "load", staticmethod(boom)) + assert packer._load_or_create_scenario(42, "nl2015", 2050, "COL") is None + + # Successful new + monkeypatch.setattr(Scenario, "new", staticmethod(lambda a, y: created)) + out = packer._load_or_create_scenario(None, "de", 2030, "COL2") + assert out is created + + # Failing new -> None + def boom2(_, __): + raise ValueError("bad") + + monkeypatch.setattr(Scenario, "new", staticmethod(boom2)) + assert packer._load_or_create_scenario(None, "nl", 2050, "C") is None + + # Missing fields -> None + assert packer._load_or_create_scenario(None, None, None, "C") is None + + def test_collect_and_apply_metadata(self): + packer = ScenarioPacker() + meta = packer._collect_meta_updates(True, 7, " src ", " title ") + assert meta == { + "private": True, + "template": 7, + "source": "src", + "title": "title", + } + + # empty strings trimmed out + meta = packer._collect_meta_updates(None, None, " ", "") + assert meta == {} + + # apply updates + scenario = Mock(spec=Scenario) + packer._apply_metadata(scenario, {"private": False}) + scenario.update_metadata.assert_called_once_with(private=False) + + # swallow exceptions + scenario.update_metadata.side_effect = RuntimeError("boom") + packer._apply_metadata(scenario, {"private": True}) # should not raise + + # no updates does nothing + scenario.update_metadata.reset_mock() + packer._apply_metadata(scenario, {}) + scenario.update_metadata.assert_not_called() + + def test_extract_scenario_sheet_info_series_and_df(self): + packer = ScenarioPacker() + + ser = pd.Series( + { + "short_name": "S", + "sortables": "SORT1", + "custom_curves": "CUR1", + }, + name="COL1", + ) + out = packer._extract_scenario_sheet_info(ser) + assert out == { + "COL1": {"short_name": "S", "sortables": "SORT1", "custom_curves": "CUR1"} + } + + df = pd.DataFrame( + { + "A": {"short_name": None, "sortables": "S_A", "custom_curves": None}, + "B": {"short_name": "B_S", "sortables": None, "custom_curves": "C_B"}, + } + ) + out2 = packer._extract_scenario_sheet_info(df) + assert out2["A"]["short_name"] == "A" + assert out2["A"]["sortables"] == "S_A" + assert out2["A"]["custom_curves"] is None + assert out2["B"]["short_name"] == "B_S" + assert out2["B"]["custom_curves"] == "C_B" + + def test_process_single_scenario_sortables(self): + packer = ScenarioPacker() + scenario = Mock(spec=Scenario) + + # Build a sheet where header row contains helpers + target column to be renamed + raw = pd.DataFrame( + [ + [None, None, None], + ["sortables", "heat_network", "hour"], + [None, "lt", 1], + [None, "mt", 2], + ] + ) + + packer._process_single_scenario_sortables(scenario, raw) + assert scenario.set_sortables_from_dataframe.called + df_arg = scenario.set_sortables_from_dataframe.call_args[0][0] + assert "heat_network_lt" in df_arg.columns + assert "hour" not in df_arg.columns + + def test_process_single_scenario_sortables_empty_after_normalize(self): + packer = ScenarioPacker() + scenario = Mock(spec=Scenario) + + raw = pd.DataFrame( + [ + [None, None], + ["sortables", "hour"], + [None, 1], + ] + ) + + packer._process_single_scenario_sortables(scenario, raw) + scenario.set_sortables_from_dataframe.assert_not_called() + + def test_process_single_scenario_curves_success_and_error(self, monkeypatch): + packer = ScenarioPacker() + scenario = Mock(spec=Scenario) + scenario.id = 999 + + raw = pd.DataFrame( + [ + [None, None], + ["custom_curves", "value"], + ["curve_1", 1.0], + ["curve_2", 2.0], + ] + ) + + dummy_curves = Mock(spec=CustomCurves) + monkeypatch.setattr( + CustomCurves, + "_from_dataframe", + staticmethod(lambda df, scenario_id: dummy_curves), + ) + packer._process_single_scenario_curves(scenario, raw) + scenario.update_custom_curves.assert_called_once_with(dummy_curves) + scenario.update_custom_curves.reset_mock() + + def boom(_df, scenario_id): + raise RuntimeError("bad curves") + + monkeypatch.setattr(CustomCurves, "_from_dataframe", staticmethod(boom)) + packer._process_single_scenario_curves(scenario, raw) + scenario.update_custom_curves.assert_not_called() + + def test_process_single_scenario_curves_empty_after_normalize(self): + packer = ScenarioPacker() + scenario = Mock(spec=Scenario) + scenario.id = 1 + + raw = pd.DataFrame( + [ + [None], + ["custom_curves"], + [None], + ] + ) + packer._process_single_scenario_curves(scenario, raw) + scenario.update_custom_curves.assert_not_called() + + +class TestSetupScenarioFromMainColumn: + + def test_setup_scenario_from_main_column_loads_and_updates(self, monkeypatch): + packer = ScenarioPacker() + scenario = Mock(spec=Scenario) + scenario.identifier = Mock(return_value="SID") + monkeypatch.setattr(Scenario, "load", staticmethod(lambda sid: scenario)) + + ser = pd.Series( + { + "scenario_id": "101", + "area_code": "nl2015", + "end_year": 2050, + "private": "yes", + "template": "7", + "source": " src ", + "title": " title ", + } + ) + + out = packer._setup_scenario_from_main_column("COL", ser) + assert out is scenario + scenario.update_metadata.assert_called_once() + + def test_setup_scenario_from_main_column_creates(self, monkeypatch): + packer = ScenarioPacker() + scenario = Mock(spec=Scenario) + scenario.identifier = Mock(return_value="NEW") + monkeypatch.setattr(Scenario, "new", staticmethod(lambda a, y: scenario)) + + ser = pd.Series( + { + "scenario_id": None, + "area_code": "de", + "end_year": 2030, + "private": 0, + "template": None, + } + ) + + out = packer._setup_scenario_from_main_column("COL", ser) + assert out is scenario + + def test_setup_scenario_from_main_column_returns_none_on_fail(self, monkeypatch): + packer = ScenarioPacker() + monkeypatch.setattr( + ScenarioPacker, "_load_or_create_scenario", lambda self, *a, **k: None + ) + ser = pd.Series({"scenario_id": None, "area_code": None, "end_year": None}) + assert packer._setup_scenario_from_main_column("COL", ser) is None + + +class TestFromExcelDetailed: + + def test_from_excel_full_flow(self, tmp_path, monkeypatch): + # Prepare MAIN with two scenarios: one load, one create + main = pd.DataFrame( + { + "S1": { + "scenario_id": 101, + "area_code": "nl2015", + "end_year": 2050, + "private": "yes", + "template": 3, + "source": "source1", + "title": "Title 1", + "short_name": "Short1", + "sortables": "S1_SORT", + "custom_curves": "S1_CURVES", + }, + "S2": { + "scenario_id": None, + "area_code": "de", + "end_year": 2030, + "private": 0, + "template": None, + "source": "", + "title": "", + "short_name": None, + "sortables": "S2_SORT", + "custom_curves": None, + }, + } + ) + + # Other sheets + params = pd.DataFrame([["helper", "value"], ["input_key", 1]]) + gqueries = pd.DataFrame([["gquery", "future"], ["co2_emissions", 100]]) + s1_sort = pd.DataFrame([[None, None], ["sortables", "value"], ["a", 1]]) + s2_sort = pd.DataFrame([[None, None], ["sortables", "value"], ["b", 2]]) + s1_curves = pd.DataFrame([[None, None], ["custom_curves", "value"], ["x", 1]]) + + path = tmp_path / "import.xlsx" + with pd.ExcelWriter(path, engine="xlsxwriter") as writer: + main.to_excel(writer, sheet_name="MAIN") + params.to_excel(writer, sheet_name="PARAMETERS", header=False, index=False) + gqueries.to_excel(writer, sheet_name="GQUERIES", header=False, index=False) + s1_sort.to_excel(writer, sheet_name="S1_SORT", header=False, index=False) + s2_sort.to_excel(writer, sheet_name="S2_SORT", header=False, index=False) + s1_curves.to_excel( + writer, sheet_name="S1_CURVES", header=False, index=False + ) + + # Patch loading/creating and pack interactions + s_loaded = Mock(spec=Scenario) + s_loaded.id = "101" + s_loaded.identifier = Mock(return_value="101") + s_created = Mock(spec=Scenario) + s_created.id = "created" + s_created.identifier = Mock(return_value="created") + + monkeypatch.setattr(Scenario, "load", staticmethod(lambda sid: s_loaded)) + monkeypatch.setattr(Scenario, "new", staticmethod(lambda a, y: s_created)) + + # Spy on inputs and queries imports + with ( + patch.object(InputsPack, "set_scenario_short_names") as set_sn, + patch.object(InputsPack, "from_dataframe") as from_df, + patch.object(QueryPack, "from_dataframe") as gq_from_df, + patch.object( + ScenarioPacker, "_process_single_scenario_sortables" + ) as proc_sort, + patch.object( + ScenarioPacker, "_process_single_scenario_curves" + ) as proc_curves, + ): + packer = ScenarioPacker.from_excel(str(path)) + + assert isinstance(packer, ScenarioPacker) + assert s_loaded in packer._scenarios() + assert s_created in packer._scenarios() + + set_sn.assert_called_once() + from_df.assert_called_once() + gq_from_df.assert_called_once() + + # Called once for each scenario with a sortables sheet + assert proc_sort.call_count == 2 + proc_curves.assert_called_once() + + def test_from_excel_missing_or_bad_main(self, tmp_path): + packer = ScenarioPacker.from_excel(str(tmp_path / "bad.xlsx")) + assert isinstance(packer, ScenarioPacker) + assert len(packer._scenarios()) == 0 + + # File with no MAIN sheet + path = tmp_path / "no_main.xlsx" + with pd.ExcelWriter(path, engine="xlsxwriter") as writer: + pd.DataFrame([[1]]).to_excel(writer, sheet_name="OTHER") + packer2 = ScenarioPacker.from_excel(str(path)) + assert isinstance(packer2, ScenarioPacker) + assert len(packer2._scenarios()) == 0 + + # File with empty MAIN sheet + path2 = tmp_path / "empty_main.xlsx" + with pd.ExcelWriter(path2, engine="xlsxwriter") as writer: + pd.DataFrame().to_excel(writer, sheet_name="MAIN") + packer3 = ScenarioPacker.from_excel(str(path2)) + assert isinstance(packer3, ScenarioPacker) + assert len(packer3._scenarios()) == 0 + + def test_from_excel_parameters_and_gqueries_errors(self, tmp_path, monkeypatch): + # Prepare a minimal MAIN and both PARAMETERS and GQUERIES sheets + main = pd.DataFrame( + { + "S": { + "scenario_id": None, + "area_code": "nl2015", + "end_year": 2050, + "sortables": None, + "custom_curves": None, + } + } + ) + params = pd.DataFrame([["helper", "value"], ["input_key", 1]]) + gqueries = pd.DataFrame([["gquery", "future"], ["co2_emissions", 100]]) + + path = tmp_path / "errs.xlsx" + with pd.ExcelWriter(path, engine="xlsxwriter") as writer: + main.to_excel(writer, sheet_name="MAIN") + params.to_excel(writer, sheet_name="PARAMETERS", header=False, index=False) + gqueries.to_excel(writer, sheet_name="GQUERIES", header=False, index=False) + + # Create returns a simple scenario + s_created = Mock(spec=Scenario) + s_created.id = "created" + s_created.identifier = Mock(return_value="created") + monkeypatch.setattr(Scenario, "new", staticmethod(lambda a, y: s_created)) + + with ( + patch.object(InputsPack, "set_scenario_short_names") as set_sn, + patch.object( + InputsPack, "from_dataframe", side_effect=RuntimeError("bad params") + ), + patch.object( + QueryPack, "from_dataframe", side_effect=RuntimeError("bad gq") + ), + ): + packer = ScenarioPacker.from_excel(str(path)) + + assert isinstance(packer, ScenarioPacker) + # Scenario was still created even if imports failed + assert s_created in packer._scenarios() + set_sn.assert_called_once() + + def test_from_excel_gqueries_sheet_name_fallback(self, tmp_path, monkeypatch): + main = pd.DataFrame( + {"S": {"scenario_id": None, "area_code": "nl2015", "end_year": 2050}} + ) + + path = tmp_path / "gq_fallback.xlsx" + with pd.ExcelWriter(path, engine="xlsxwriter") as writer: + main.to_excel(writer, sheet_name="MAIN") + pd.DataFrame([["gquery"], ["total_costs"]]).to_excel( + writer, sheet_name="GQ2", header=False, index=False + ) + + s_created = Mock(spec=Scenario) + s_created.id = "created" + s_created.identifier = Mock(return_value="created") + monkeypatch.setattr(Scenario, "new", staticmethod(lambda a, y: s_created)) + + with patch.object(QueryPack, "sheet_name", "GQ2"): + with patch.object(QueryPack, "from_dataframe") as gq_from_df: + packer = ScenarioPacker.from_excel(str(path)) + assert s_created in packer._scenarios() + gq_from_df.assert_called_once() + + def test_from_excel_processing_sortables_and_curves_errors( + self, tmp_path, monkeypatch + ): + main = pd.DataFrame( + { + "S": { + "scenario_id": None, + "area_code": "nl2015", + "end_year": 2050, + "sortables": "S_SORT", + "custom_curves": "S_CURVES", + } + } + ) + + path = tmp_path / "proc_errs.xlsx" + with pd.ExcelWriter(path, engine="xlsxwriter") as writer: + main.to_excel(writer, sheet_name="MAIN") + pd.DataFrame([[None], ["sortables"], ["a"]]).to_excel( + writer, sheet_name="S_SORT", header=False, index=False + ) + pd.DataFrame([[None], ["custom_curves"], ["x"]]).to_excel( + writer, sheet_name="S_CURVES", header=False, index=False + ) + + s_created = Mock(spec=Scenario) + s_created.id = "created" + s_created.identifier = Mock(return_value="created") + monkeypatch.setattr(Scenario, "new", staticmethod(lambda a, y: s_created)) + + with ( + patch.object( + ScenarioPacker, + "_process_single_scenario_sortables", + side_effect=RuntimeError("bad sort"), + ), + patch.object( + ScenarioPacker, + "_process_single_scenario_curves", + side_effect=RuntimeError("bad cur"), + ), + ): + packer = ScenarioPacker.from_excel(str(path)) + assert isinstance(packer, ScenarioPacker) + assert s_created in packer._scenarios() + + def test_from_excel_setup_column_exception_and_all_fail( + self, tmp_path, monkeypatch + ): + # Two columns: first raises, second returns scenario + main = pd.DataFrame( + { + "A": {"scenario_id": None, "area_code": "nl2015", "end_year": 2050}, + "B": {"scenario_id": None, "area_code": "de", "end_year": 2030}, + } + ) + path = tmp_path / "columns_mix.xlsx" + with pd.ExcelWriter(path, engine="xlsxwriter") as writer: + main.to_excel(writer, sheet_name="MAIN") + + # Patch method to raise for A and create for B + def setup(col_name, col_ser): + if col_name == "A": + raise RuntimeError("boom") + s = Mock(spec=Scenario) + s.id = "BID" + s.identifier = Mock(return_value="BID") + return s + + with patch.object( + ScenarioPacker, "_setup_scenario_from_main_column", side_effect=setup + ): + packer = ScenarioPacker.from_excel(str(path)) + assert any(s.id == "BID" for s in packer._scenarios()) + + # All columns fail -> 0 scenarios, early return + with patch.object( + ScenarioPacker, + "_setup_scenario_from_main_column", + side_effect=RuntimeError("e"), + ): + packer2 = ScenarioPacker.from_excel(str(path)) + assert len(packer2._scenarios()) == 0 + + def test_from_excel_missing_parameters_sheet_parse_error( + self, tmp_path, monkeypatch + ): + main = pd.DataFrame( + {"S": {"scenario_id": None, "area_code": "nl2015", "end_year": 2050}} + ) + path = tmp_path / "no_params.xlsx" + with pd.ExcelWriter(path, engine="xlsxwriter") as writer: + main.to_excel(writer, sheet_name="MAIN") + + s_created = Mock(spec=Scenario) + s_created.id = "created" + s_created.identifier = Mock(return_value="created") + monkeypatch.setattr(Scenario, "new", staticmethod(lambda a, y: s_created)) + packer = ScenarioPacker.from_excel(str(path)) + assert s_created in packer._scenarios() + + def test_from_excel_gqueries_parse_raises(self, tmp_path, monkeypatch): + main = pd.DataFrame( + {"S": {"scenario_id": None, "area_code": "nl2015", "end_year": 2050}} + ) + path = tmp_path / "gq_parse_err.xlsx" + with pd.ExcelWriter(path, engine="xlsxwriter") as writer: + main.to_excel(writer, sheet_name="MAIN") + pd.DataFrame([["gquery"], ["total_costs"]]).to_excel( + writer, sheet_name="GQUERIES", header=False, index=False + ) + + s_created = Mock(spec=Scenario) + s_created.id = "created" + s_created.identifier = Mock(return_value="created") + monkeypatch.setattr(Scenario, "new", staticmethod(lambda a, y: s_created)) + + original_parse = pd.ExcelFile.parse + + def parse_proxy(self, sheet_name, *a, **k): + if sheet_name == "GQUERIES": + raise ValueError("bad parse") + return original_parse(self, sheet_name, *a, **k) + + with patch.object(pd.ExcelFile, "parse", parse_proxy): + packer = ScenarioPacker.from_excel(str(path)) + assert s_created in packer._scenarios() diff --git a/tests/models/test_sortables.py b/tests/models/test_sortables.py index 21f399f..0e0d77d 100644 --- a/tests/models/test_sortables.py +++ b/tests/models/test_sortables.py @@ -200,7 +200,7 @@ def test_validation_duplicate_order_items(): def test_validation_order_too_long(): """Test that orders with too many items generate warnings""" - long_order = list(range(15)) # More than 10 items + long_order = list(range(20)) # More than 17 items payload = ("forecast_storage", long_order) result = list(Sortable.from_json(payload)) @@ -213,7 +213,7 @@ def test_validation_order_too_long(): assert len(sortable.warnings) > 0 all_warnings = [w.message for w in sortable.warnings] warning_text = " ".join(all_warnings) - assert "more than 10 items" in warning_text + assert "more than 17 items" in warning_text @pytest.mark.parametrize( @@ -265,11 +265,11 @@ def test_sortable_is_valid_update(): assert "duplicate" in warning_text.lower() # Invalid update - too long - warnings = sortable.is_valid_update(list(range(15))) + warnings = sortable.is_valid_update(list(range(18))) assert len(warnings) > 0 all_warnings = [w.message for w in warnings] warning_text = " ".join(all_warnings) - assert "more than 10 items" in warning_text + assert "more than 17 items" in warning_text def test_name_method(): diff --git a/tests/utils/test_excel.py b/tests/utils/test_excel.py index 8533655..4226249 100644 --- a/tests/utils/test_excel.py +++ b/tests/utils/test_excel.py @@ -8,10 +8,10 @@ from xlsxwriter.worksheet import Worksheet from pyetm.utils.excel import ( + add_frame, handle_numeric_value, set_column_widths, write_index, - add_frame, add_series, ) @@ -154,89 +154,6 @@ def test_write_index_no_names(self): assert len(name_calls) == 0 -class TestAddFrame: - """Test add_frame function""" - - def setup_method(self): - """Setup test data""" - self.temp_dir = tempfile.mkdtemp() - - def teardown_method(self): - """Clean up temp files""" - import shutil - - shutil.rmtree(self.temp_dir, ignore_errors=True) - - def test_add_simple_dataframe(self): - """Test adding simple DataFrame""" - df = pd.DataFrame( - {"A": [1, 2, 3], "B": [4.5, np.nan, 6.7]}, index=["row1", "row2", "row3"] - ) - - file_path = os.path.join(self.temp_dir, "test.xlsx") - workbook = Workbook(file_path, {"nan_inf_to_errors": True}) - - worksheet = add_frame("TestSheet", df, workbook) - - assert worksheet is not None - assert worksheet.name == "TestSheet" - - workbook.close() - - def test_add_dataframe_no_index(self): - """Test adding DataFrame without index""" - df = pd.DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]}) - - file_path = os.path.join(self.temp_dir, "test_no_index.xlsx") - workbook = Workbook(file_path, {"nan_inf_to_errors": True}) - - worksheet = add_frame("TestSheet", df, workbook, index=False) - - assert worksheet is not None - workbook.close() - - def test_add_multiindex_dataframe(self): - """Test adding DataFrame with MultiIndex""" - arrays = [["A", "A", "B", "B"], [1, 2, 1, 2]] - index = pd.MultiIndex.from_arrays(arrays, names=["letter", "number"]) - - columns = pd.MultiIndex.from_tuples( - [("X", "col1"), ("X", "col2"), ("Y", "col1")], names=["group", "item"] - ) - - df = pd.DataFrame(np.random.randn(4, 3), index=index, columns=columns) - - file_path = os.path.join(self.temp_dir, "test_multi.xlsx") - workbook = Workbook(file_path, {"nan_inf_to_errors": True}) - - worksheet = add_frame("MultiTest", df, workbook) - - assert worksheet is not None - workbook.close() - - def test_add_frame_with_custom_options(self): - """Test add_frame with custom options""" - df = pd.DataFrame({"A": [1.123456789, 2.987654321], "B": [np.nan, 4.555555555]}) - - file_path = os.path.join(self.temp_dir, "test_custom.xlsx") - workbook = Workbook(file_path, {"nan_inf_to_errors": True}) - - worksheet = add_frame( - "CustomTest", - df, - workbook, - column_width=[15, 20], - index_width=12, - freeze_panes=False, - bold_headers=False, - nan_as_formula=False, - decimal_precision=3, - ) - - assert worksheet is not None - workbook.close() - - class TestAddSeries: """Test add_series function""" From a8fb8d1db8fe597e158d6e130990acfe3df1a05e Mon Sep 17 00:00:00 2001 From: louispt1 <81332401+louispt1@users.noreply.github.com> Date: Wed, 13 Aug 2025 15:29:00 +0200 Subject: [PATCH 10/19] Output curves (#70) * Export output curves to a separate file by default on to_excel * Swap from pipenv to poetry * Clean up Jupyter notebooks --- .gitignore | 2 + Pipfile | 33 - Pipfile.lock | 1993 ----------- README.md | 177 +- examples/.gitkeep | 0 .../advanced_scenario_example.ipynb | 689 ---- examples/create_and_update_a_scenario.ipynb | 181 - ....ipynb => create_or_query_scenarios.ipynb} | 15 +- examples/example.config.yml | 8 +- examples/example_input_excel.xlsx | Bin 0 -> 1370069 bytes examples/excel_to_scenarios.ipynb | 1474 -------- examples/exploring_a_scenario.ipynb | 211 -- examples/myc_notebook_for_tim.ipynb | 1631 --------- examples/scenario_to_excel.ipynb | 215 -- examples/serialization_deserialization.ipynb | 241 -- poetry.lock | 3036 +++++++++++++++++ pyproject.toml | 88 +- running_notebooks.md | 71 +- src/pyetm/config/settings.py | 49 +- .../models/packables/output_curves_pack.py | 101 +- src/pyetm/models/scenario.py | 38 +- src/pyetm/models/scenario_packer.py | 170 +- src/pyetm/models/scenarios.py | 21 +- .../scenario_runners/update_metadata.py | 3 +- src/pyetm/utils/excel.py | 12 +- .../scenario_runners/test_update_metadata.py | 7 +- 26 files changed, 3616 insertions(+), 6850 deletions(-) delete mode 100644 Pipfile delete mode 100644 Pipfile.lock delete mode 100644 examples/.gitkeep delete mode 100644 examples/advanced_examples/advanced_scenario_example.ipynb delete mode 100644 examples/create_and_update_a_scenario.ipynb rename examples/{full_multi_scenario_flow.ipynb => create_or_query_scenarios.ipynb} (83%) create mode 100644 examples/example_input_excel.xlsx delete mode 100644 examples/excel_to_scenarios.ipynb delete mode 100644 examples/exploring_a_scenario.ipynb delete mode 100644 examples/myc_notebook_for_tim.ipynb delete mode 100644 examples/scenario_to_excel.ipynb delete mode 100644 examples/serialization_deserialization.ipynb create mode 100644 poetry.lock diff --git a/.gitignore b/.gitignore index 8ec5ae8..20a694b 100644 --- a/.gitignore +++ b/.gitignore @@ -18,3 +18,5 @@ import_graph.svg tmp/ *.xlsx +# Keep the example input +!examples/example_input_excel.xlsx diff --git a/Pipfile b/Pipfile deleted file mode 100644 index fd1d27a..0000000 --- a/Pipfile +++ /dev/null @@ -1,33 +0,0 @@ -[[source]] -url = "https://pypi.org/simple" -verify_ssl = true -name = "pypi" - -[packages] -pydantic = "*" -pandas = "*" -requests = "*" -dotenv = "*" -pyyaml = "*" -pydantic-settings = "*" -pyetm = {file = ".", editable = true} -xlsxwriter = "*" -openpyxl = "*" - -[dev-packages] -pytest = "*" -pylint = "*" -requests-mock = "*" -ipykernel = "*" -notebook = "*" -pytest-cov = "*" -pydeps = "*" - -[requires] -python_version = "3.12" - -[scripts] -test = "python -m pytest" -test_with_coverage = "python -m pytest --cov=pyetm tests/ --cov-report=term-missing" -linter = "python -m pylint pyetm" -deptree = "pydeps src/pyetm --show-cycles --max-bacon=2 -o import_graph.svg -T svg" diff --git a/Pipfile.lock b/Pipfile.lock deleted file mode 100644 index c2ab727..0000000 --- a/Pipfile.lock +++ /dev/null @@ -1,1993 +0,0 @@ -{ - "_meta": { - "hash": { - "sha256": "9c4a4dd242a69bb0fa72de6d543863742a6ac38a51db7cf772696af377dfa7bf" - }, - "pipfile-spec": 6, - "requires": { - "python_version": "3.12" - }, - "sources": [ - { - "name": "pypi", - "url": "https://pypi.org/simple", - "verify_ssl": true - } - ] - }, - "default": { - "annotated-types": { - "hashes": [ - "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53", - "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89" - ], - "markers": "python_version >= '3.8'", - "version": "==0.7.0" - }, - "certifi": { - "hashes": [ - "sha256:2e0c7ce7cb5d8f8634ca55d2ba7e6ec2689a2fd6537d8dec1296a477a4910057", - "sha256:d747aa5a8b9bbbb1bb8c22bb13e22bd1f18e9796defa16bab421f7f7a317323b" - ], - "markers": "python_version >= '3.7'", - "version": "==2025.6.15" - }, - "charset-normalizer": { - "hashes": [ - "sha256:005fa3432484527f9732ebd315da8da8001593e2cf46a3d817669f062c3d9ed4", - "sha256:046595208aae0120559a67693ecc65dd75d46f7bf687f159127046628178dc45", - "sha256:0c29de6a1a95f24b9a1aa7aefd27d2487263f00dfd55a77719b530788f75cff7", - "sha256:0c8c57f84ccfc871a48a47321cfa49ae1df56cd1d965a09abe84066f6853b9c0", - "sha256:0f5d9ed7f254402c9e7d35d2f5972c9bbea9040e99cd2861bd77dc68263277c7", - "sha256:18dd2e350387c87dabe711b86f83c9c78af772c748904d372ade190b5c7c9d4d", - "sha256:1b1bde144d98e446b056ef98e59c256e9294f6b74d7af6846bf5ffdafd687a7d", - "sha256:1c95a1e2902a8b722868587c0e1184ad5c55631de5afc0eb96bc4b0d738092c0", - "sha256:1cad5f45b3146325bb38d6855642f6fd609c3f7cad4dbaf75549bf3b904d3184", - "sha256:21b2899062867b0e1fde9b724f8aecb1af14f2778d69aacd1a5a1853a597a5db", - "sha256:24498ba8ed6c2e0b56d4acbf83f2d989720a93b41d712ebd4f4979660db4417b", - "sha256:25a23ea5c7edc53e0f29bae2c44fcb5a1aa10591aae107f2a2b2583a9c5cbc64", - "sha256:289200a18fa698949d2b39c671c2cc7a24d44096784e76614899a7ccf2574b7b", - "sha256:28a1005facc94196e1fb3e82a3d442a9d9110b8434fc1ded7a24a2983c9888d8", - "sha256:32fc0341d72e0f73f80acb0a2c94216bd704f4f0bce10aedea38f30502b271ff", - "sha256:36b31da18b8890a76ec181c3cf44326bf2c48e36d393ca1b72b3f484113ea344", - "sha256:3c21d4fca343c805a52c0c78edc01e3477f6dd1ad7c47653241cf2a206d4fc58", - "sha256:3fddb7e2c84ac87ac3a947cb4e66d143ca5863ef48e4a5ecb83bd48619e4634e", - "sha256:43e0933a0eff183ee85833f341ec567c0980dae57c464d8a508e1b2ceb336471", - "sha256:4a476b06fbcf359ad25d34a057b7219281286ae2477cc5ff5e3f70a246971148", - "sha256:4e594135de17ab3866138f496755f302b72157d115086d100c3f19370839dd3a", - "sha256:50bf98d5e563b83cc29471fa114366e6806bc06bc7a25fd59641e41445327836", - "sha256:5a9979887252a82fefd3d3ed2a8e3b937a7a809f65dcb1e068b090e165bbe99e", - "sha256:5baececa9ecba31eff645232d59845c07aa030f0c81ee70184a90d35099a0e63", - "sha256:5bf4545e3b962767e5c06fe1738f951f77d27967cb2caa64c28be7c4563e162c", - "sha256:6333b3aa5a12c26b2a4d4e7335a28f1475e0e5e17d69d55141ee3cab736f66d1", - "sha256:65c981bdbd3f57670af8b59777cbfae75364b483fa8a9f420f08094531d54a01", - "sha256:68a328e5f55ec37c57f19ebb1fdc56a248db2e3e9ad769919a58672958e8f366", - "sha256:6a0289e4589e8bdfef02a80478f1dfcb14f0ab696b5a00e1f4b8a14a307a3c58", - "sha256:6b66f92b17849b85cad91259efc341dce9c1af48e2173bf38a85c6329f1033e5", - "sha256:6c9379d65defcab82d07b2a9dfbfc2e95bc8fe0ebb1b176a3190230a3ef0e07c", - "sha256:6fc1f5b51fa4cecaa18f2bd7a003f3dd039dd615cd69a2afd6d3b19aed6775f2", - "sha256:70f7172939fdf8790425ba31915bfbe8335030f05b9913d7ae00a87d4395620a", - "sha256:721c76e84fe669be19c5791da68232ca2e05ba5185575086e384352e2c309597", - "sha256:7222ffd5e4de8e57e03ce2cef95a4c43c98fcb72ad86909abdfc2c17d227fc1b", - "sha256:75d10d37a47afee94919c4fab4c22b9bc2a8bf7d4f46f87363bcf0573f3ff4f5", - "sha256:76af085e67e56c8816c3ccf256ebd136def2ed9654525348cfa744b6802b69eb", - "sha256:770cab594ecf99ae64c236bc9ee3439c3f46be49796e265ce0cc8bc17b10294f", - "sha256:7a6ab32f7210554a96cd9e33abe3ddd86732beeafc7a28e9955cdf22ffadbab0", - "sha256:7c48ed483eb946e6c04ccbe02c6b4d1d48e51944b6db70f697e089c193404941", - "sha256:7f56930ab0abd1c45cd15be65cc741c28b1c9a34876ce8c17a2fa107810c0af0", - "sha256:8075c35cd58273fee266c58c0c9b670947c19df5fb98e7b66710e04ad4e9ff86", - "sha256:8272b73e1c5603666618805fe821edba66892e2870058c94c53147602eab29c7", - "sha256:82d8fd25b7f4675d0c47cf95b594d4e7b158aca33b76aa63d07186e13c0e0ab7", - "sha256:844da2b5728b5ce0e32d863af26f32b5ce61bc4273a9c720a9f3aa9df73b1455", - "sha256:8755483f3c00d6c9a77f490c17e6ab0c8729e39e6390328e42521ef175380ae6", - "sha256:915f3849a011c1f593ab99092f3cecfcb4d65d8feb4a64cf1bf2d22074dc0ec4", - "sha256:926ca93accd5d36ccdabd803392ddc3e03e6d4cd1cf17deff3b989ab8e9dbcf0", - "sha256:982bb1e8b4ffda883b3d0a521e23abcd6fd17418f6d2c4118d257a10199c0ce3", - "sha256:98f862da73774290f251b9df8d11161b6cf25b599a66baf087c1ffe340e9bfd1", - "sha256:9cbfacf36cb0ec2897ce0ebc5d08ca44213af24265bd56eca54bee7923c48fd6", - "sha256:a370b3e078e418187da8c3674eddb9d983ec09445c99a3a263c2011993522981", - "sha256:a955b438e62efdf7e0b7b52a64dc5c3396e2634baa62471768a64bc2adb73d5c", - "sha256:aa6af9e7d59f9c12b33ae4e9450619cf2488e2bbe9b44030905877f0b2324980", - "sha256:aa88ca0b1932e93f2d961bf3addbb2db902198dca337d88c89e1559e066e7645", - "sha256:aaeeb6a479c7667fbe1099af9617c83aaca22182d6cf8c53966491a0f1b7ffb7", - "sha256:aaf27faa992bfee0264dc1f03f4c75e9fcdda66a519db6b957a3f826e285cf12", - "sha256:b2680962a4848b3c4f155dc2ee64505a9c57186d0d56b43123b17ca3de18f0fa", - "sha256:b2d318c11350e10662026ad0eb71bb51c7812fc8590825304ae0bdd4ac283acd", - "sha256:b33de11b92e9f75a2b545d6e9b6f37e398d86c3e9e9653c4864eb7e89c5773ef", - "sha256:b3daeac64d5b371dea99714f08ffc2c208522ec6b06fbc7866a450dd446f5c0f", - "sha256:be1e352acbe3c78727a16a455126d9ff83ea2dfdcbc83148d2982305a04714c2", - "sha256:bee093bf902e1d8fc0ac143c88902c3dfc8941f7ea1d6a8dd2bcb786d33db03d", - "sha256:c72fbbe68c6f32f251bdc08b8611c7b3060612236e960ef848e0a517ddbe76c5", - "sha256:c9e36a97bee9b86ef9a1cf7bb96747eb7a15c2f22bdb5b516434b00f2a599f02", - "sha256:cddf7bd982eaa998934a91f69d182aec997c6c468898efe6679af88283b498d3", - "sha256:cf713fe9a71ef6fd5adf7a79670135081cd4431c2943864757f0fa3a65b1fafd", - "sha256:d11b54acf878eef558599658b0ffca78138c8c3655cf4f3a4a673c437e67732e", - "sha256:d41c4d287cfc69060fa91cae9683eacffad989f1a10811995fa309df656ec214", - "sha256:d524ba3f1581b35c03cb42beebab4a13e6cdad7b36246bd22541fa585a56cccd", - "sha256:daac4765328a919a805fa5e2720f3e94767abd632ae410a9062dff5412bae65a", - "sha256:db4c7bf0e07fc3b7d89ac2a5880a6a8062056801b83ff56d8464b70f65482b6c", - "sha256:dc7039885fa1baf9be153a0626e337aa7ec8bf96b0128605fb0d77788ddc1681", - "sha256:dccab8d5fa1ef9bfba0590ecf4d46df048d18ffe3eec01eeb73a42e0d9e7a8ba", - "sha256:dedb8adb91d11846ee08bec4c8236c8549ac721c245678282dcb06b221aab59f", - "sha256:e45ba65510e2647721e35323d6ef54c7974959f6081b58d4ef5d87c60c84919a", - "sha256:e53efc7c7cee4c1e70661e2e112ca46a575f90ed9ae3fef200f2a25e954f4b28", - "sha256:e635b87f01ebc977342e2697d05b56632f5f879a4f15955dfe8cef2448b51691", - "sha256:e70e990b2137b29dc5564715de1e12701815dacc1d056308e2b17e9095372a82", - "sha256:e8082b26888e2f8b36a042a58307d5b917ef2b1cacab921ad3323ef91901c71a", - "sha256:e8323a9b031aa0393768b87f04b4164a40037fb2a3c11ac06a03ffecd3618027", - "sha256:e92fca20c46e9f5e1bb485887d074918b13543b1c2a1185e69bb8d17ab6236a7", - "sha256:eb30abc20df9ab0814b5a2524f23d75dcf83cde762c161917a2b4b7b55b1e518", - "sha256:eba9904b0f38a143592d9fc0e19e2df0fa2e41c3c3745554761c5f6447eedabf", - "sha256:ef8de666d6179b009dce7bcb2ad4c4a779f113f12caf8dc77f0162c29d20490b", - "sha256:efd387a49825780ff861998cd959767800d54f8308936b21025326de4b5a42b9", - "sha256:f0aa37f3c979cf2546b73e8222bbfa3dc07a641585340179d768068e3455e544", - "sha256:f4074c5a429281bf056ddd4c5d3b740ebca4d43ffffe2ef4bf4d2d05114299da", - "sha256:f69a27e45c43520f5487f27627059b64aaf160415589230992cec34c5e18a509", - "sha256:fb707f3e15060adf5b7ada797624a6c6e0138e2a26baa089df64c68ee98e040f", - "sha256:fcbe676a55d7445b22c10967bceaaf0ee69407fbe0ece4d032b6eb8d4565982a", - "sha256:fdb20a30fe1175ecabed17cbf7812f7b804b8a315a25f24678bcdf120a90077f" - ], - "markers": "python_version >= '3.7'", - "version": "==3.4.2" - }, - "dotenv": { - "hashes": [ - "sha256:29cf74a087b31dafdb5a446b6d7e11cbce8ed2741540e2339c69fbef92c94ce9" - ], - "index": "pypi", - "version": "==0.9.9" - }, - "et-xmlfile": { - "hashes": [ - "sha256:7a91720bc756843502c3b7504c77b8fe44217c85c537d85037f0f536151b2caa", - "sha256:dab3f4764309081ce75662649be815c4c9081e88f0837825f90fd28317d4da54" - ], - "markers": "python_version >= '3.8'", - "version": "==2.0.0" - }, - "idna": { - "hashes": [ - "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", - "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3" - ], - "markers": "python_version >= '3.6'", - "version": "==3.10" - }, - "numpy": { - "hashes": [ - "sha256:0025048b3c1557a20bc80d06fdeb8cc7fc193721484cca82b2cfa072fec71a93", - "sha256:010ce9b4f00d5c036053ca684c77441f2f2c934fd23bee058b4d6f196efd8280", - "sha256:0bb3a4a61e1d327e035275d2a993c96fa786e4913aa089843e6a2d9dd205c66a", - "sha256:0c4d9e0a8368db90f93bd192bfa771ace63137c3488d198ee21dfb8e7771916e", - "sha256:15aa4c392ac396e2ad3d0a2680c0f0dee420f9fed14eef09bdb9450ee6dcb7b7", - "sha256:18703df6c4a4fee55fd3d6e5a253d01c5d33a295409b03fda0c86b3ca2ff41a1", - "sha256:1ec9ae20a4226da374362cca3c62cd753faf2f951440b0e3b98e93c235441d2b", - "sha256:23ab05b2d241f76cb883ce8b9a93a680752fbfcbd51c50eff0b88b979e471d8c", - "sha256:25a1992b0a3fdcdaec9f552ef10d8103186f5397ab45e2d25f8ac51b1a6b97e8", - "sha256:2959d8f268f3d8ee402b04a9ec4bb7604555aeacf78b360dc4ec27f1d508177d", - "sha256:2a809637460e88a113e186e87f228d74ae2852a2e0c44de275263376f17b5bdc", - "sha256:2fb86b7e58f9ac50e1e9dd1290154107e47d1eef23a0ae9145ded06ea606f992", - "sha256:36890eb9e9d2081137bd78d29050ba63b8dab95dff7912eadf1185e80074b2a0", - "sha256:39bff12c076812595c3a306f22bfe49919c5513aa1e0e70fac756a0be7c2a2b8", - "sha256:467db865b392168ceb1ef1ffa6f5a86e62468c43e0cfb4ab6da667ede10e58db", - "sha256:4e602e1b8682c2b833af89ba641ad4176053aaa50f5cacda1a27004352dde943", - "sha256:5902660491bd7a48b2ec16c23ccb9124b8abfd9583c5fdfa123fe6b421e03de1", - "sha256:5ccb7336eaf0e77c1635b232c141846493a588ec9ea777a7c24d7166bb8533ae", - "sha256:5f1b8f26d1086835f442286c1d9b64bb3974b0b1e41bb105358fd07d20872952", - "sha256:6269b9edfe32912584ec496d91b00b6d34282ca1d07eb10e82dfc780907d6c2e", - "sha256:6ea9e48336a402551f52cd8f593343699003d2353daa4b72ce8d34f66b722070", - "sha256:762e0c0c6b56bdedfef9a8e1d4538556438288c4276901ea008ae44091954e29", - "sha256:7be91b2239af2658653c5bb6f1b8bccafaf08226a258caf78ce44710a0160d30", - "sha256:7dea630156d39b02a63c18f508f85010230409db5b2927ba59c8ba4ab3e8272e", - "sha256:867ef172a0976aaa1f1d1b63cf2090de8b636a7674607d514505fb7276ab08fc", - "sha256:8d5ee6eec45f08ce507a6570e06f2f879b374a552087a4179ea7838edbcbfa42", - "sha256:8e333040d069eba1652fb08962ec5b76af7f2c7bce1df7e1418c8055cf776f25", - "sha256:a5ee121b60aa509679b682819c602579e1df14a5b07fe95671c8849aad8f2115", - "sha256:a780033466159c2270531e2b8ac063704592a0bc62ec4a1b991c7c40705eb0e8", - "sha256:a894f3816eb17b29e4783e5873f92faf55b710c2519e5c351767c51f79d8526d", - "sha256:a8b740f5579ae4585831b3cf0e3b0425c667274f82a484866d2adf9570539369", - "sha256:ad506d4b09e684394c42c966ec1527f6ebc25da7f4da4b1b056606ffe446b8a3", - "sha256:afed2ce4a84f6b0fc6c1ce734ff368cbf5a5e24e8954a338f3bdffa0718adffb", - "sha256:b0b5397374f32ec0649dd98c652a1798192042e715df918c20672c62fb52d4b8", - "sha256:bada6058dd886061f10ea15f230ccf7dfff40572e99fef440a4a857c8728c9c0", - "sha256:c4913079974eeb5c16ccfd2b1f09354b8fed7e0d6f2cab933104a09a6419b1ee", - "sha256:c5bdf2015ccfcee8253fb8be695516ac4457c743473a43290fd36eba6a1777eb", - "sha256:c6e0bf9d1a2f50d2b65a7cf56db37c095af17b59f6c132396f7c6d5dd76484df", - "sha256:ce2ce9e5de4703a673e705183f64fd5da5bf36e7beddcb63a25ee2286e71ca48", - "sha256:cfecc7822543abdea6de08758091da655ea2210b8ffa1faf116b940693d3df76", - "sha256:d4580adadc53311b163444f877e0789f1c8861e2698f6b2a4ca852fda154f3ff", - "sha256:d70f20df7f08b90a2062c1f07737dd340adccf2068d0f1b9b3d56e2038979fee", - "sha256:e344eb79dab01f1e838ebb67aab09965fb271d6da6b00adda26328ac27d4a66e", - "sha256:e610832418a2bc09d974cc9fecebfa51e9532d6190223bc5ef6a7402ebf3b5cb", - "sha256:e772dda20a6002ef7061713dc1e2585bc1b534e7909b2030b5a46dae8ff077ab", - "sha256:e7cbf5a5eafd8d230a3ce356d892512185230e4781a361229bd902ff403bc660", - "sha256:eabd7e8740d494ce2b4ea0ff05afa1b7b291e978c0ae075487c51e8bd93c0c68", - "sha256:ebb8603d45bc86bbd5edb0d63e52c5fd9e7945d3a503b77e486bd88dde67a19b", - "sha256:ec0bdafa906f95adc9a0c6f26a4871fa753f25caaa0e032578a30457bff0af6a", - "sha256:eccb9a159db9aed60800187bc47a6d3451553f0e1b08b068d8b277ddfbb9b244", - "sha256:ee8340cb48c9b7a5899d1149eece41ca535513a9698098edbade2a8e7a84da77" - ], - "markers": "python_version >= '3.11'", - "version": "==2.3.1" - }, - "openpyxl": { - "hashes": [ - "sha256:5282c12b107bffeef825f4617dc029afaf41d0ea60823bbb665ef3079dc79de2", - "sha256:cf0e3cf56142039133628b5acffe8ef0c12bc902d2aadd3e0fe5878dc08d1050" - ], - "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==3.1.5" - }, - "pandas": { - "hashes": [ - "sha256:034abd6f3db8b9880aaee98f4f5d4dbec7c4829938463ec046517220b2f8574e", - "sha256:094e271a15b579650ebf4c5155c05dcd2a14fd4fdd72cf4854b2f7ad31ea30be", - "sha256:14a0cc77b0f089d2d2ffe3007db58f170dae9b9f54e569b299db871a3ab5bf46", - "sha256:1a881bc1309f3fce34696d07b00f13335c41f5f5a8770a33b09ebe23261cfc67", - "sha256:1d2b33e68d0ce64e26a4acc2e72d747292084f4e8db4c847c6f5f6cbe56ed6d8", - "sha256:213cd63c43263dbb522c1f8a7c9d072e25900f6975596f883f4bebd77295d4f3", - "sha256:23c2b2dc5213810208ca0b80b8666670eb4660bbfd9d45f58592cc4ddcfd62e1", - "sha256:2c7e2fc25f89a49a11599ec1e76821322439d90820108309bf42130d2f36c983", - "sha256:2eb4728a18dcd2908c7fccf74a982e241b467d178724545a48d0caf534b38ebf", - "sha256:34600ab34ebf1131a7613a260a61dbe8b62c188ec0ea4c296da7c9a06b004133", - "sha256:39ff73ec07be5e90330cc6ff5705c651ace83374189dcdcb46e6ff54b4a72cd6", - "sha256:404d681c698e3c8a40a61d0cd9412cc7364ab9a9cc6e144ae2992e11a2e77a20", - "sha256:40cecc4ea5abd2921682b57532baea5588cc5f80f0231c624056b146887274d2", - "sha256:430a63bae10b5086995db1b02694996336e5a8ac9a96b4200572b413dfdfccb9", - "sha256:4930255e28ff5545e2ca404637bcc56f031893142773b3468dc021c6c32a1390", - "sha256:6021910b086b3ca756755e86ddc64e0ddafd5e58e076c72cb1585162e5ad259b", - "sha256:625466edd01d43b75b1883a64d859168e4556261a5035b32f9d743b67ef44634", - "sha256:75651c14fde635e680496148a8526b328e09fe0572d9ae9b638648c46a544ba3", - "sha256:84141f722d45d0c2a89544dd29d35b3abfc13d2250ed7e68394eda7564bd6324", - "sha256:8adff9f138fc614347ff33812046787f7d43b3cef7c0f0171b3340cae333f6ca", - "sha256:951805d146922aed8357e4cc5671b8b0b9be1027f0619cea132a9f3f65f2f09c", - "sha256:9efc0acbbffb5236fbdf0409c04edce96bec4bdaa649d49985427bd1ec73e085", - "sha256:9ff730713d4c4f2f1c860e36c005c7cefc1c7c80c21c0688fd605aa43c9fcf09", - "sha256:a6872d695c896f00df46b71648eea332279ef4077a409e2fe94220208b6bb675", - "sha256:b198687ca9c8529662213538a9bb1e60fa0bf0f6af89292eb68fea28743fcd5a", - "sha256:b9d8c3187be7479ea5c3d30c32a5d73d62a621166675063b2edd21bc47614027", - "sha256:ba24af48643b12ffe49b27065d3babd52702d95ab70f50e1b34f71ca703e2c0d", - "sha256:bb32dc743b52467d488e7a7c8039b821da2826a9ba4f85b89ea95274f863280f", - "sha256:bb3be958022198531eb7ec2008cfc78c5b1eed51af8600c6c5d9160d89d8d249", - "sha256:bf5be867a0541a9fb47a4be0c5790a4bccd5b77b92f0a59eeec9375fafc2aa14", - "sha256:c06f6f144ad0a1bf84699aeea7eff6068ca5c63ceb404798198af7eb86082e33", - "sha256:c6da97aeb6a6d233fb6b17986234cc723b396b50a3c6804776351994f2a658fd", - "sha256:e0f51973ba93a9f97185049326d75b942b9aeb472bec616a129806facb129ebb", - "sha256:e1991bbb96f4050b09b5f811253c4f3cf05ee89a589379aa36cd623f21a31d6f", - "sha256:e5f08eb9a445d07720776df6e641975665c9ea12c9d8a331e0f6890f2dcd76ef", - "sha256:e78ad363ddb873a631e92a3c063ade1ecfb34cae71e9a2be6ad100f875ac1042", - "sha256:ed16339bc354a73e0a609df36d256672c7d296f3f767ac07257801aa064ff73c", - "sha256:f4dd97c19bd06bc557ad787a15b6489d2614ddaab5d104a0310eb314c724b2d2", - "sha256:f925f1ef673b4bd0271b1809b72b3270384f2b7d9d14a189b12b7fc02574d575", - "sha256:f95a2aef32614ed86216d3c450ab12a4e82084e8102e355707a1d96e33d51c34", - "sha256:fa07e138b3f6c04addfeaf56cc7fdb96c3b68a3fe5e5401251f231fce40a0d7a", - "sha256:fa35c266c8cd1a67d75971a1912b185b492d257092bdd2709bbdebe574ed228d" - ], - "index": "pypi", - "markers": "python_version >= '3.9'", - "version": "==2.3.0" - }, - "pydantic": { - "hashes": [ - "sha256:d989c3c6cb79469287b1569f7447a17848c998458d49ebe294e975b9baf0f0db", - "sha256:dde5df002701f6de26248661f6835bbe296a47bf73990135c7d07ce741b9623b" - ], - "index": "pypi", - "markers": "python_version >= '3.9'", - "version": "==2.11.7" - }, - "pydantic-core": { - "hashes": [ - "sha256:0069c9acc3f3981b9ff4cdfaf088e98d83440a4c7ea1bc07460af3d4dc22e72d", - "sha256:031c57d67ca86902726e0fae2214ce6770bbe2f710dc33063187a68744a5ecac", - "sha256:0405262705a123b7ce9f0b92f123334d67b70fd1f20a9372b907ce1080c7ba02", - "sha256:04a1a413977ab517154eebb2d326da71638271477d6ad87a769102f7c2488c56", - "sha256:09fb9dd6571aacd023fe6aaca316bd01cf60ab27240d7eb39ebd66a3a15293b4", - "sha256:0a39979dcbb70998b0e505fb1556a1d550a0781463ce84ebf915ba293ccb7e22", - "sha256:0a9f2c9dd19656823cb8250b0724ee9c60a82f3cdf68a080979d13092a3b0fef", - "sha256:0e03262ab796d986f978f79c943fc5f620381be7287148b8010b4097f79a39ec", - "sha256:0e5b2671f05ba48b94cb90ce55d8bdcaaedb8ba00cc5359f6810fc918713983d", - "sha256:0e6116757f7959a712db11f3e9c0a99ade00a5bbedae83cb801985aa154f071b", - "sha256:0fb2d542b4d66f9470e8065c5469ec676978d625a8b7a363f07d9a501a9cb36a", - "sha256:1082dd3e2d7109ad8b7da48e1d4710c8d06c253cbc4a27c1cff4fbcaa97a9e3f", - "sha256:1a8695a8d00c73e50bff9dfda4d540b7dee29ff9b8053e38380426a85ef10052", - "sha256:1e063337ef9e9820c77acc768546325ebe04ee38b08703244c1309cccc4f1bab", - "sha256:1ea40a64d23faa25e62a70ad163571c0b342b8bf66d5fa612ac0dec4f069d916", - "sha256:2058a32994f1fde4ca0480ab9d1e75a0e8c87c22b53a3ae66554f9af78f2fe8c", - "sha256:235f45e5dbcccf6bd99f9f472858849f73d11120d76ea8707115415f8e5ebebf", - "sha256:2807668ba86cb38c6817ad9bc66215ab8584d1d304030ce4f0887336f28a5e27", - "sha256:2b0a451c263b01acebe51895bfb0e1cc842a5c666efe06cdf13846c7418caa9a", - "sha256:2b3d326aaef0c0399d9afffeb6367d5e26ddc24d351dbc9c636840ac355dc5d8", - "sha256:2bfb5112df54209d820d7bf9317c7a6c9025ea52e49f46b6a2060104bba37de7", - "sha256:2f82865531efd18d6e07a04a17331af02cb7a651583c418df8266f17a63c6612", - "sha256:329467cecfb529c925cf2bbd4d60d2c509bc2fb52a20c1045bf09bb70971a9c1", - "sha256:3a1c81334778f9e3af2f8aeb7a960736e5cab1dfebfb26aabca09afd2906c039", - "sha256:3abcd9392a36025e3bd55f9bd38d908bd17962cc49bc6da8e7e96285336e2bca", - "sha256:3c6db6e52c6d70aa0d00d45cdb9b40f0433b96380071ea80b09277dba021ddf7", - "sha256:3dc625f4aa79713512d1976fe9f0bc99f706a9dee21dfd1810b4bbbf228d0e8a", - "sha256:3eb3fe62804e8f859c49ed20a8451342de53ed764150cb14ca71357c765dc2a6", - "sha256:44857c3227d3fb5e753d5fe4a3420d6376fa594b07b621e220cd93703fe21782", - "sha256:4b25d91e288e2c4e0662b8038a28c6a07eaac3e196cfc4ff69de4ea3db992a1b", - "sha256:4c5b0a576fb381edd6d27f0a85915c6daf2f8138dc5c267a57c08a62900758c7", - "sha256:4e61206137cbc65e6d5256e1166f88331d3b6238e082d9f74613b9b765fb9025", - "sha256:52fb90784e0a242bb96ec53f42196a17278855b0f31ac7c3cc6f5c1ec4811849", - "sha256:53a57d2ed685940a504248187d5685e49eb5eef0f696853647bf37c418c538f7", - "sha256:572c7e6c8bb4774d2ac88929e3d1f12bc45714ae5ee6d9a788a9fb35e60bb04b", - "sha256:5c4aa4e82353f65e548c476b37e64189783aa5384903bfea4f41580f255fddfa", - "sha256:5c92edd15cd58b3c2d34873597a1e20f13094f59cf88068adb18947df5455b4e", - "sha256:5f483cfb75ff703095c59e365360cb73e00185e01aaea067cd19acffd2ab20ea", - "sha256:61c18fba8e5e9db3ab908620af374db0ac1baa69f0f32df4f61ae23f15e586ac", - "sha256:6368900c2d3ef09b69cb0b913f9f8263b03786e5b2a387706c5afb66800efd51", - "sha256:64632ff9d614e5eecfb495796ad51b0ed98c453e447a76bcbeeb69615079fc7e", - "sha256:65132b7b4a1c0beded5e057324b7e16e10910c106d43675d9bd87d4f38dde162", - "sha256:6b99022f1d19bc32a4c2a0d544fc9a76e3be90f0b3f4af413f87d38749300e65", - "sha256:6bdfe4b3789761f3bcb4b1ddf33355a71079858958e3a552f16d5af19768fef2", - "sha256:6fa6dfc3e4d1f734a34710f391ae822e0a8eb8559a85c6979e14e65ee6ba2954", - "sha256:73662edf539e72a9440129f231ed3757faab89630d291b784ca99237fb94db2b", - "sha256:73cf6373c21bc80b2e0dc88444f41ae60b2f070ed02095754eb5a01df12256de", - "sha256:7cb8bc3605c29176e1b105350d2e6474142d7c1bd1d9327c4a9bdb46bf827acc", - "sha256:7f92c15cd1e97d4b12acd1cc9004fa092578acfa57b67ad5e43a197175d01a64", - "sha256:82f68293f055f51b51ea42fafc74b6aad03e70e191799430b90c13d643059ebb", - "sha256:83aa99b1285bc8f038941ddf598501a86f1536789740991d7d8756e34f1e74d9", - "sha256:87acbfcf8e90ca885206e98359d7dca4bcbb35abdc0ff66672a293e1d7a19101", - "sha256:87b31b6846e361ef83fedb187bb5b4372d0da3f7e28d85415efa92d6125d6e6d", - "sha256:881b21b5549499972441da4758d662aeea93f1923f953e9cbaff14b8b9565aef", - "sha256:8d55ab81c57b8ff8548c3e4947f119551253f4e3787a7bbc0b6b3ca47498a9d3", - "sha256:8f57a69461af2a5fa6e6bbd7a5f60d3b7e6cebb687f55106933188e79ad155c1", - "sha256:95237e53bb015f67b63c91af7518a62a8660376a6a0db19b89acc77a4d6199f5", - "sha256:96081f1605125ba0855dfda83f6f3df5ec90c61195421ba72223de35ccfb2f88", - "sha256:970919794d126ba8645f3837ab6046fb4e72bbc057b3709144066204c19a455d", - "sha256:9cb1da0f5a471435a7bc7e439b8a728e8b61e59784b2af70d7c169f8dd8ae290", - "sha256:9fcd347d2cc5c23b06de6d3b7b8275be558a0c90549495c699e379a80bf8379e", - "sha256:9fdac5d6ffa1b5a83bca06ffe7583f5576555e6c8b3a91fbd25ea7780f825f7d", - "sha256:a11c8d26a50bfab49002947d3d237abe4d9e4b5bdc8846a63537b6488e197808", - "sha256:a144d4f717285c6d9234a66778059f33a89096dfb9b39117663fd8413d582dcc", - "sha256:a2b911a5b90e0374d03813674bf0a5fbbb7741570dcd4b4e85a2e48d17def29d", - "sha256:a7ec89dc587667f22b6a0b6579c249fca9026ce7c333fc142ba42411fa243cdc", - "sha256:aa9d91b338f2df0508606f7009fde642391425189bba6d8c653afd80fd6bb64e", - "sha256:b0379a2b24882fef529ec3b4987cb5d003b9cda32256024e6fe1586ac45fc640", - "sha256:bc7aee6f634a6f4a95676fcb5d6559a2c2a390330098dba5e5a5f28a2e4ada30", - "sha256:bdc25f3681f7b78572699569514036afe3c243bc3059d3942624e936ec93450e", - "sha256:c083a3bdd5a93dfe480f1125926afcdbf2917ae714bdb80b36d34318b2bec5d9", - "sha256:c20c462aa4434b33a2661701b861604913f912254e441ab8d78d30485736115a", - "sha256:c2fc0a768ef76c15ab9238afa6da7f69895bb5d1ee83aeea2e3509af4472d0b9", - "sha256:c52b02ad8b4e2cf14ca7b3d918f3eb0ee91e63b3167c32591e57c4317e134f8f", - "sha256:c54c939ee22dc8e2d545da79fc5381f1c020d6d3141d3bd747eab59164dc89fb", - "sha256:c8e7af2f4e0194c22b5b37205bfb293d166a7344a5b0d0eaccebc376546d77d5", - "sha256:cca3868ddfaccfbc4bfb1d608e2ccaaebe0ae628e1416aeb9c4d88c001bb45ab", - "sha256:d3f26877a748dc4251cfcfda9dfb5f13fcb034f5308388066bcfe9031b63ae7d", - "sha256:d53b22f2032c42eaaf025f7c40c2e3b94568ae077a606f006d206a463bc69572", - "sha256:d87c561733f66531dced0da6e864f44ebf89a8fba55f31407b00c2f7f9449593", - "sha256:d946c8bf0d5c24bf4fe333af284c59a19358aa3ec18cb3dc4370080da1e8ad29", - "sha256:dac89aea9af8cd672fa7b510e7b8c33b0bba9a43186680550ccf23020f32d535", - "sha256:db4b41f9bd95fbe5acd76d89920336ba96f03e149097365afe1cb092fceb89a1", - "sha256:dc46a01bf8d62f227d5ecee74178ffc448ff4e5197c756331f71efcc66dc980f", - "sha256:dd14041875d09cc0f9308e37a6f8b65f5585cf2598a53aa0123df8b129d481f8", - "sha256:de4b83bb311557e439b9e186f733f6c645b9417c84e2eb8203f3f820a4b988bf", - "sha256:e799c050df38a639db758c617ec771fd8fb7a5f8eaaa4b27b101f266b216a246", - "sha256:e80b087132752f6b3d714f041ccf74403799d3b23a72722ea2e6ba2e892555b9", - "sha256:eb8c529b2819c37140eb51b914153063d27ed88e3bdc31b71198a198e921e011", - "sha256:eb9b459ca4df0e5c87deb59d37377461a538852765293f9e6ee834f0435a93b9", - "sha256:efec8db3266b76ef9607c2c4c419bdb06bf335ae433b80816089ea7585816f6a", - "sha256:f481959862f57f29601ccced557cc2e817bce7533ab8e01a797a48b49c9692b3", - "sha256:f517ca031dfc037a9c07e748cefd8d96235088b83b4f4ba8939105d20fa1dcd6", - "sha256:f889f7a40498cc077332c7ab6b4608d296d852182211787d4f3ee377aaae66e8", - "sha256:f8de619080e944347f5f20de29a975c2d815d9ddd8be9b9b7268e2e3ef68605a", - "sha256:f941635f2a3d96b2973e867144fde513665c87f13fe0e193c158ac51bfaaa7b2", - "sha256:fa754d1850735a0b0e03bcffd9d4b4343eb417e47196e4485d9cca326073a42c", - "sha256:fa854f5cf7e33842a892e5c73f45327760bc7bc516339fda888c75ae60edaeb6", - "sha256:fe5b32187cbc0c862ee201ad66c30cf218e5ed468ec8dc1cf49dec66e160cc4d" - ], - "markers": "python_version >= '3.9'", - "version": "==2.33.2" - }, - "pydantic-settings": { - "hashes": [ - "sha256:06f0062169818d0f5524420a360d632d5857b83cffd4d42fe29597807a1614ee", - "sha256:a60952460b99cf661dc25c29c0ef171721f98bfcb52ef8d9ea4c943d7c8cc796" - ], - "index": "pypi", - "markers": "python_version >= '3.9'", - "version": "==2.10.1" - }, - "pyetm": { - "editable": true, - "file": "." - }, - "python-dateutil": { - "hashes": [ - "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", - "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", - "version": "==2.9.0.post0" - }, - "python-dotenv": { - "hashes": [ - "sha256:31f23644fe2602f88ff55e1f5c79ba497e01224ee7737937930c448e4d0e24dc", - "sha256:a8a6399716257f45be6a007360200409fce5cda2661e3dec71d23dc15f6189ab" - ], - "markers": "python_version >= '3.9'", - "version": "==1.1.1" - }, - "pytz": { - "hashes": [ - "sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3", - "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00" - ], - "version": "==2025.2" - }, - "pyyaml": { - "hashes": [ - "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff", - "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48", - "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086", - "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e", - "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", - "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5", - "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", - "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee", - "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5", - "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68", - "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a", - "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf", - "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99", - "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8", - "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85", - "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19", - "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", - "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a", - "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", - "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317", - "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c", - "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631", - "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d", - "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", - "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", - "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e", - "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b", - "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8", - "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476", - "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706", - "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", - "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237", - "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b", - "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083", - "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180", - "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425", - "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e", - "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f", - "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725", - "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", - "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab", - "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774", - "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725", - "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", - "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5", - "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d", - "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290", - "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44", - "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed", - "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4", - "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", - "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12", - "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4" - ], - "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==6.0.2" - }, - "requests": { - "hashes": [ - "sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c", - "sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422" - ], - "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==2.32.4" - }, - "six": { - "hashes": [ - "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", - "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", - "version": "==1.17.0" - }, - "typing-extensions": { - "hashes": [ - "sha256:8676b788e32f02ab42d9e7c61324048ae4c6d844a399eebace3d4979d75ceef4", - "sha256:a1514509136dd0b477638fc68d6a91497af5076466ad0fa6c338e44e359944af" - ], - "markers": "python_version >= '3.9'", - "version": "==4.14.0" - }, - "typing-inspection": { - "hashes": [ - "sha256:389055682238f53b04f7badcb49b989835495a96700ced5dab2d8feae4b26f51", - "sha256:6ae134cc0203c33377d43188d4064e9b357dba58cff3185f22924610e70a9d28" - ], - "markers": "python_version >= '3.9'", - "version": "==0.4.1" - }, - "tzdata": { - "hashes": [ - "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8", - "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9" - ], - "markers": "python_version >= '2'", - "version": "==2025.2" - }, - "urllib3": { - "hashes": [ - "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760", - "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc" - ], - "markers": "python_version >= '3.9'", - "version": "==2.5.0" - }, - "xlsxwriter": { - "hashes": [ - "sha256:4f4824234e1eaf9d95df9a8fe974585ff91d0f5e3d3f12ace5b71e443c1c6abd", - "sha256:7e88469d607cdc920151c0ab3ce9cf1a83992d4b7bc730c5ffdd1a12115a7dbe" - ], - "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==3.2.5" - } - }, - "develop": { - "anyio": { - "hashes": [ - "sha256:673c0c244e15788651a4ff38710fea9675823028a6f08a5eda409e0c9840a028", - "sha256:9f76d541cad6e36af7beb62e978876f3b41e3e04f2c1fbf0884604c0a9c4d93c" - ], - "markers": "python_version >= '3.9'", - "version": "==4.9.0" - }, - "appnope": { - "hashes": [ - "sha256:1de3860566df9caf38f01f86f65e0e13e379af54f9e4bee1e66b48f2efffd1ee", - "sha256:502575ee11cd7a28c0205f379b525beefebab9d161b7c964670864014ed7213c" - ], - "markers": "python_version >= '3.6'", - "version": "==0.1.4" - }, - "argon2-cffi": { - "hashes": [ - "sha256:694ae5cc8a42f4c4e2bf2ca0e64e51e23a040c6a517a85074683d3959e1346c1", - "sha256:fdc8b074db390fccb6eb4a3604ae7231f219aa669a2652e0f20e16ba513d5741" - ], - "markers": "python_version >= '3.8'", - "version": "==25.1.0" - }, - "argon2-cffi-bindings": { - "hashes": [ - "sha256:20ef543a89dee4db46a1a6e206cd015360e5a75822f76df533845c3cbaf72670", - "sha256:2c3e3cc67fdb7d82c4718f19b4e7a87123caf8a93fde7e23cf66ac0337d3cb3f", - "sha256:3b9ef65804859d335dc6b31582cad2c5166f0c3e7975f324d9ffaa34ee7e6583", - "sha256:3e385d1c39c520c08b53d63300c3ecc28622f076f4c2b0e6d7e796e9f6502194", - "sha256:58ed19212051f49a523abb1dbe954337dc82d947fb6e5a0da60f7c8471a8476c", - "sha256:5e00316dabdaea0b2dd82d141cc66889ced0cdcbfa599e8b471cf22c620c329a", - "sha256:603ca0aba86b1349b147cab91ae970c63118a0f30444d4bc80355937c950c082", - "sha256:6a22ad9800121b71099d0fb0a65323810a15f2e292f2ba450810a7316e128ee5", - "sha256:8cd69c07dd875537a824deec19f978e0f2078fdda07fd5c42ac29668dda5f40f", - "sha256:93f9bf70084f97245ba10ee36575f0c3f1e7d7724d67d8e5b08e61787c320ed7", - "sha256:9524464572e12979364b7d600abf96181d3541da11e23ddf565a32e70bd4dc0d", - "sha256:b2ef1c30440dbbcba7a5dc3e319408b59676e2e039e2ae11a8775ecf482b192f", - "sha256:b746dba803a79238e925d9046a63aa26bf86ab2a2fe74ce6b009a1c3f5c8f2ae", - "sha256:bb89ceffa6c791807d1305ceb77dbfacc5aa499891d2c55661c6459651fc39e3", - "sha256:bd46088725ef7f58b5a1ef7ca06647ebaf0eb4baff7d1d0d177c6cc8744abd86", - "sha256:ccb949252cb2ab3a08c02024acb77cfb179492d5701c7cbdbfd776124d4d2367", - "sha256:d4966ef5848d820776f5f562a7d45fdd70c2f330c961d0d745b784034bd9f48d", - "sha256:e415e3f62c8d124ee16018e491a009937f8cf7ebf5eb430ffc5de21b900dad93", - "sha256:ed2937d286e2ad0cc79a7087d3c272832865f779430e0cc2b4f3718d3159b0cb", - "sha256:f1152ac548bd5b8bcecfb0b0371f082037e47128653df2e8ba6e914d384f3c3e", - "sha256:f9f8b450ed0547e3d473fdc8612083fd08dd2120d6ac8f73828df9b7d45bb351" - ], - "markers": "python_version >= '3.6'", - "version": "==21.2.0" - }, - "arrow": { - "hashes": [ - "sha256:c728b120ebc00eb84e01882a6f5e7927a53960aa990ce7dd2b10f39005a67f80", - "sha256:d4540617648cb5f895730f1ad8c82a65f2dad0166f57b75f3ca54759c4d67a85" - ], - "markers": "python_version >= '3.8'", - "version": "==1.3.0" - }, - "astroid": { - "hashes": [ - "sha256:104fb9cb9b27ea95e847a94c003be03a9e039334a8ebca5ee27dafaf5c5711eb", - "sha256:c332157953060c6deb9caa57303ae0d20b0fbdb2e59b4a4f2a6ba49d0a7961ce" - ], - "markers": "python_full_version >= '3.9.0'", - "version": "==3.3.10" - }, - "asttokens": { - "hashes": [ - "sha256:0dcd8baa8d62b0c1d118b399b2ddba3c4aff271d0d7a9e0d4c1681c79035bbc7", - "sha256:e3078351a059199dd5138cb1c706e6430c05eff2ff136af5eb4790f9d28932e2" - ], - "markers": "python_version >= '3.8'", - "version": "==3.0.0" - }, - "async-lru": { - "hashes": [ - "sha256:481d52ccdd27275f42c43a928b4a50c3bfb2d67af4e78b170e3e0bb39c66e5bb", - "sha256:ab95404d8d2605310d345932697371a5f40def0487c03d6d0ad9138de52c9943" - ], - "markers": "python_version >= '3.9'", - "version": "==2.0.5" - }, - "attrs": { - "hashes": [ - "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3", - "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b" - ], - "markers": "python_version >= '3.8'", - "version": "==25.3.0" - }, - "babel": { - "hashes": [ - "sha256:0c54cffb19f690cdcc52a3b50bcbf71e07a808d1c80d549f2459b9d2cf0afb9d", - "sha256:4d0b53093fdfb4b21c92b5213dba5a1b23885afa8383709427046b21c366e5f2" - ], - "markers": "python_version >= '3.8'", - "version": "==2.17.0" - }, - "beautifulsoup4": { - "hashes": [ - "sha256:9bbbb14bfde9d79f38b8cd5f8c7c85f4b8f2523190ebed90e950a8dea4cb1c4b", - "sha256:dbb3c4e1ceae6aefebdaf2423247260cd062430a410e38c66f2baa50a8437195" - ], - "markers": "python_full_version >= '3.7.0'", - "version": "==4.13.4" - }, - "bleach": { - "extras": [ - "css" - ], - "hashes": [ - "sha256:117d9c6097a7c3d22fd578fcd8d35ff1e125df6736f554da4e432fdd63f31e5e", - "sha256:123e894118b8a599fd80d3ec1a6d4cc7ce4e5882b1317a7e1ba69b56e95f991f" - ], - "markers": "python_version >= '3.9'", - "version": "==6.2.0" - }, - "certifi": { - "hashes": [ - "sha256:2e0c7ce7cb5d8f8634ca55d2ba7e6ec2689a2fd6537d8dec1296a477a4910057", - "sha256:d747aa5a8b9bbbb1bb8c22bb13e22bd1f18e9796defa16bab421f7f7a317323b" - ], - "markers": "python_version >= '3.7'", - "version": "==2025.6.15" - }, - "cffi": { - "hashes": [ - "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8", - "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2", - "sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1", - "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15", - "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36", - "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824", - "sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8", - "sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36", - "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17", - "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf", - "sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc", - "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3", - "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed", - "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702", - "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1", - "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8", - "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903", - "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6", - "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d", - "sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b", - "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e", - "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be", - "sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c", - "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683", - "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9", - "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c", - "sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8", - "sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1", - "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4", - "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655", - "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67", - "sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595", - "sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0", - "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65", - "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41", - "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6", - "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401", - "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6", - "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3", - "sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16", - "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93", - "sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e", - "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4", - "sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964", - "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c", - "sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576", - "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0", - "sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3", - "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662", - "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3", - "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff", - "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5", - "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd", - "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f", - "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5", - "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14", - "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d", - "sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9", - "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7", - "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382", - "sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a", - "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e", - "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a", - "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4", - "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99", - "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87", - "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b" - ], - "markers": "python_version >= '3.8'", - "version": "==1.17.1" - }, - "charset-normalizer": { - "hashes": [ - "sha256:005fa3432484527f9732ebd315da8da8001593e2cf46a3d817669f062c3d9ed4", - "sha256:046595208aae0120559a67693ecc65dd75d46f7bf687f159127046628178dc45", - "sha256:0c29de6a1a95f24b9a1aa7aefd27d2487263f00dfd55a77719b530788f75cff7", - "sha256:0c8c57f84ccfc871a48a47321cfa49ae1df56cd1d965a09abe84066f6853b9c0", - "sha256:0f5d9ed7f254402c9e7d35d2f5972c9bbea9040e99cd2861bd77dc68263277c7", - "sha256:18dd2e350387c87dabe711b86f83c9c78af772c748904d372ade190b5c7c9d4d", - "sha256:1b1bde144d98e446b056ef98e59c256e9294f6b74d7af6846bf5ffdafd687a7d", - "sha256:1c95a1e2902a8b722868587c0e1184ad5c55631de5afc0eb96bc4b0d738092c0", - "sha256:1cad5f45b3146325bb38d6855642f6fd609c3f7cad4dbaf75549bf3b904d3184", - "sha256:21b2899062867b0e1fde9b724f8aecb1af14f2778d69aacd1a5a1853a597a5db", - "sha256:24498ba8ed6c2e0b56d4acbf83f2d989720a93b41d712ebd4f4979660db4417b", - "sha256:25a23ea5c7edc53e0f29bae2c44fcb5a1aa10591aae107f2a2b2583a9c5cbc64", - "sha256:289200a18fa698949d2b39c671c2cc7a24d44096784e76614899a7ccf2574b7b", - "sha256:28a1005facc94196e1fb3e82a3d442a9d9110b8434fc1ded7a24a2983c9888d8", - "sha256:32fc0341d72e0f73f80acb0a2c94216bd704f4f0bce10aedea38f30502b271ff", - "sha256:36b31da18b8890a76ec181c3cf44326bf2c48e36d393ca1b72b3f484113ea344", - "sha256:3c21d4fca343c805a52c0c78edc01e3477f6dd1ad7c47653241cf2a206d4fc58", - "sha256:3fddb7e2c84ac87ac3a947cb4e66d143ca5863ef48e4a5ecb83bd48619e4634e", - "sha256:43e0933a0eff183ee85833f341ec567c0980dae57c464d8a508e1b2ceb336471", - "sha256:4a476b06fbcf359ad25d34a057b7219281286ae2477cc5ff5e3f70a246971148", - "sha256:4e594135de17ab3866138f496755f302b72157d115086d100c3f19370839dd3a", - "sha256:50bf98d5e563b83cc29471fa114366e6806bc06bc7a25fd59641e41445327836", - "sha256:5a9979887252a82fefd3d3ed2a8e3b937a7a809f65dcb1e068b090e165bbe99e", - "sha256:5baececa9ecba31eff645232d59845c07aa030f0c81ee70184a90d35099a0e63", - "sha256:5bf4545e3b962767e5c06fe1738f951f77d27967cb2caa64c28be7c4563e162c", - "sha256:6333b3aa5a12c26b2a4d4e7335a28f1475e0e5e17d69d55141ee3cab736f66d1", - "sha256:65c981bdbd3f57670af8b59777cbfae75364b483fa8a9f420f08094531d54a01", - "sha256:68a328e5f55ec37c57f19ebb1fdc56a248db2e3e9ad769919a58672958e8f366", - "sha256:6a0289e4589e8bdfef02a80478f1dfcb14f0ab696b5a00e1f4b8a14a307a3c58", - "sha256:6b66f92b17849b85cad91259efc341dce9c1af48e2173bf38a85c6329f1033e5", - "sha256:6c9379d65defcab82d07b2a9dfbfc2e95bc8fe0ebb1b176a3190230a3ef0e07c", - "sha256:6fc1f5b51fa4cecaa18f2bd7a003f3dd039dd615cd69a2afd6d3b19aed6775f2", - "sha256:70f7172939fdf8790425ba31915bfbe8335030f05b9913d7ae00a87d4395620a", - "sha256:721c76e84fe669be19c5791da68232ca2e05ba5185575086e384352e2c309597", - "sha256:7222ffd5e4de8e57e03ce2cef95a4c43c98fcb72ad86909abdfc2c17d227fc1b", - "sha256:75d10d37a47afee94919c4fab4c22b9bc2a8bf7d4f46f87363bcf0573f3ff4f5", - "sha256:76af085e67e56c8816c3ccf256ebd136def2ed9654525348cfa744b6802b69eb", - "sha256:770cab594ecf99ae64c236bc9ee3439c3f46be49796e265ce0cc8bc17b10294f", - "sha256:7a6ab32f7210554a96cd9e33abe3ddd86732beeafc7a28e9955cdf22ffadbab0", - "sha256:7c48ed483eb946e6c04ccbe02c6b4d1d48e51944b6db70f697e089c193404941", - "sha256:7f56930ab0abd1c45cd15be65cc741c28b1c9a34876ce8c17a2fa107810c0af0", - "sha256:8075c35cd58273fee266c58c0c9b670947c19df5fb98e7b66710e04ad4e9ff86", - "sha256:8272b73e1c5603666618805fe821edba66892e2870058c94c53147602eab29c7", - "sha256:82d8fd25b7f4675d0c47cf95b594d4e7b158aca33b76aa63d07186e13c0e0ab7", - "sha256:844da2b5728b5ce0e32d863af26f32b5ce61bc4273a9c720a9f3aa9df73b1455", - "sha256:8755483f3c00d6c9a77f490c17e6ab0c8729e39e6390328e42521ef175380ae6", - "sha256:915f3849a011c1f593ab99092f3cecfcb4d65d8feb4a64cf1bf2d22074dc0ec4", - "sha256:926ca93accd5d36ccdabd803392ddc3e03e6d4cd1cf17deff3b989ab8e9dbcf0", - "sha256:982bb1e8b4ffda883b3d0a521e23abcd6fd17418f6d2c4118d257a10199c0ce3", - "sha256:98f862da73774290f251b9df8d11161b6cf25b599a66baf087c1ffe340e9bfd1", - "sha256:9cbfacf36cb0ec2897ce0ebc5d08ca44213af24265bd56eca54bee7923c48fd6", - "sha256:a370b3e078e418187da8c3674eddb9d983ec09445c99a3a263c2011993522981", - "sha256:a955b438e62efdf7e0b7b52a64dc5c3396e2634baa62471768a64bc2adb73d5c", - "sha256:aa6af9e7d59f9c12b33ae4e9450619cf2488e2bbe9b44030905877f0b2324980", - "sha256:aa88ca0b1932e93f2d961bf3addbb2db902198dca337d88c89e1559e066e7645", - "sha256:aaeeb6a479c7667fbe1099af9617c83aaca22182d6cf8c53966491a0f1b7ffb7", - "sha256:aaf27faa992bfee0264dc1f03f4c75e9fcdda66a519db6b957a3f826e285cf12", - "sha256:b2680962a4848b3c4f155dc2ee64505a9c57186d0d56b43123b17ca3de18f0fa", - "sha256:b2d318c11350e10662026ad0eb71bb51c7812fc8590825304ae0bdd4ac283acd", - "sha256:b33de11b92e9f75a2b545d6e9b6f37e398d86c3e9e9653c4864eb7e89c5773ef", - "sha256:b3daeac64d5b371dea99714f08ffc2c208522ec6b06fbc7866a450dd446f5c0f", - "sha256:be1e352acbe3c78727a16a455126d9ff83ea2dfdcbc83148d2982305a04714c2", - "sha256:bee093bf902e1d8fc0ac143c88902c3dfc8941f7ea1d6a8dd2bcb786d33db03d", - "sha256:c72fbbe68c6f32f251bdc08b8611c7b3060612236e960ef848e0a517ddbe76c5", - "sha256:c9e36a97bee9b86ef9a1cf7bb96747eb7a15c2f22bdb5b516434b00f2a599f02", - "sha256:cddf7bd982eaa998934a91f69d182aec997c6c468898efe6679af88283b498d3", - "sha256:cf713fe9a71ef6fd5adf7a79670135081cd4431c2943864757f0fa3a65b1fafd", - "sha256:d11b54acf878eef558599658b0ffca78138c8c3655cf4f3a4a673c437e67732e", - "sha256:d41c4d287cfc69060fa91cae9683eacffad989f1a10811995fa309df656ec214", - "sha256:d524ba3f1581b35c03cb42beebab4a13e6cdad7b36246bd22541fa585a56cccd", - "sha256:daac4765328a919a805fa5e2720f3e94767abd632ae410a9062dff5412bae65a", - "sha256:db4c7bf0e07fc3b7d89ac2a5880a6a8062056801b83ff56d8464b70f65482b6c", - "sha256:dc7039885fa1baf9be153a0626e337aa7ec8bf96b0128605fb0d77788ddc1681", - "sha256:dccab8d5fa1ef9bfba0590ecf4d46df048d18ffe3eec01eeb73a42e0d9e7a8ba", - "sha256:dedb8adb91d11846ee08bec4c8236c8549ac721c245678282dcb06b221aab59f", - "sha256:e45ba65510e2647721e35323d6ef54c7974959f6081b58d4ef5d87c60c84919a", - "sha256:e53efc7c7cee4c1e70661e2e112ca46a575f90ed9ae3fef200f2a25e954f4b28", - "sha256:e635b87f01ebc977342e2697d05b56632f5f879a4f15955dfe8cef2448b51691", - "sha256:e70e990b2137b29dc5564715de1e12701815dacc1d056308e2b17e9095372a82", - "sha256:e8082b26888e2f8b36a042a58307d5b917ef2b1cacab921ad3323ef91901c71a", - "sha256:e8323a9b031aa0393768b87f04b4164a40037fb2a3c11ac06a03ffecd3618027", - "sha256:e92fca20c46e9f5e1bb485887d074918b13543b1c2a1185e69bb8d17ab6236a7", - "sha256:eb30abc20df9ab0814b5a2524f23d75dcf83cde762c161917a2b4b7b55b1e518", - "sha256:eba9904b0f38a143592d9fc0e19e2df0fa2e41c3c3745554761c5f6447eedabf", - "sha256:ef8de666d6179b009dce7bcb2ad4c4a779f113f12caf8dc77f0162c29d20490b", - "sha256:efd387a49825780ff861998cd959767800d54f8308936b21025326de4b5a42b9", - "sha256:f0aa37f3c979cf2546b73e8222bbfa3dc07a641585340179d768068e3455e544", - "sha256:f4074c5a429281bf056ddd4c5d3b740ebca4d43ffffe2ef4bf4d2d05114299da", - "sha256:f69a27e45c43520f5487f27627059b64aaf160415589230992cec34c5e18a509", - "sha256:fb707f3e15060adf5b7ada797624a6c6e0138e2a26baa089df64c68ee98e040f", - "sha256:fcbe676a55d7445b22c10967bceaaf0ee69407fbe0ece4d032b6eb8d4565982a", - "sha256:fdb20a30fe1175ecabed17cbf7812f7b804b8a315a25f24678bcdf120a90077f" - ], - "markers": "python_version >= '3.7'", - "version": "==3.4.2" - }, - "comm": { - "hashes": [ - "sha256:3fd7a84065306e07bea1773df6eb8282de51ba82f77c72f9c85716ab11fe980e", - "sha256:e6fb86cb70ff661ee8c9c14e7d36d6de3b4066f1441be4063df9c5009f0a64d3" - ], - "markers": "python_version >= '3.8'", - "version": "==0.2.2" - }, - "coverage": { - "extras": [ - "toml" - ], - "hashes": [ - "sha256:02532fd3290bb8fa6bec876520842428e2a6ed6c27014eca81b031c2d30e3f71", - "sha256:0a4be2a28656afe279b34d4f91c3e26eccf2f85500d4a4ff0b1f8b54bf807338", - "sha256:0b3496922cb5f4215bf5caaef4cf12364a26b0be82e9ed6d050f3352cf2d7ef0", - "sha256:0c804506d624e8a20fb3108764c52e0eef664e29d21692afa375e0dd98dc384f", - "sha256:0f16649a7330ec307942ed27d06ee7e7a38417144620bb3d6e9a18ded8a2d3e5", - "sha256:16aa0830d0c08a2c40c264cef801db8bc4fc0e1892782e45bcacbd5889270509", - "sha256:18a0912944d70aaf5f399e350445738a1a20b50fbea788f640751c2ed9208b6c", - "sha256:1c503289ffef1d5105d91bbb4d62cbe4b14bec4d13ca225f9c73cde9bb46207d", - "sha256:2241ad5dbf79ae1d9c08fe52b36d03ca122fb9ac6bca0f34439e99f8327ac89f", - "sha256:25308bd3d00d5eedd5ae7d4357161f4df743e3c0240fa773ee1b0f75e6c7c0f1", - "sha256:2a876e4c3e5a2a1715a6608906aa5a2e0475b9c0f68343c2ada98110512ab1d8", - "sha256:2d04b16a6062516df97969f1ae7efd0de9c31eb6ebdceaa0d213b21c0ca1a683", - "sha256:30f445f85c353090b83e552dcbbdad3ec84c7967e108c3ae54556ca69955563e", - "sha256:31324f18d5969feef7344a932c32428a2d1a3e50b15a6404e97cba1cc9b2c631", - "sha256:34ed2186fe52fcc24d4561041979a0dec69adae7bce2ae8d1c49eace13e55c43", - "sha256:37ab6be0859141b53aa89412a82454b482c81cf750de4f29223d52268a86de67", - "sha256:37ae0383f13cbdcf1e5e7014489b0d71cc0106458878ccde52e8a12ced4298ed", - "sha256:382e7ddd5289f140259b610e5f5c58f713d025cb2f66d0eb17e68d0a94278875", - "sha256:3bb5838701ca68b10ebc0937dbd0eb81974bac54447c55cd58dea5bca8451029", - "sha256:437c576979e4db840539674e68c84b3cda82bc824dd138d56bead1435f1cb5d7", - "sha256:49f1d0788ba5b7ba65933f3a18864117c6506619f5ca80326b478f72acf3f385", - "sha256:52e92b01041151bf607ee858e5a56c62d4b70f4dac85b8c8cb7fb8a351ab2c10", - "sha256:535fde4001b2783ac80865d90e7cc7798b6b126f4cd8a8c54acfe76804e54e58", - "sha256:56f5eb308b17bca3bbff810f55ee26d51926d9f89ba92707ee41d3c061257e55", - "sha256:5add197315a054e92cee1b5f686a2bcba60c4c3e66ee3de77ace6c867bdee7cb", - "sha256:5f646a99a8c2b3ff4c6a6e081f78fad0dde275cd59f8f49dc4eab2e394332e74", - "sha256:600a1d4106fe66f41e5d0136dfbc68fe7200a5cbe85610ddf094f8f22e1b0300", - "sha256:60c458224331ee3f1a5b472773e4a085cc27a86a0b48205409d364272d67140d", - "sha256:64bdd969456e2d02a8b08aa047a92d269c7ac1f47e0c977675d550c9a0863643", - "sha256:66b974b145aa189516b6bf2d8423e888b742517d37872f6ee4c5be0073bd9a3c", - "sha256:684e2110ed84fd1ca5f40e89aa44adf1729dc85444004111aa01866507adf363", - "sha256:68cd53aec6f45b8e4724c0950ce86eacb775c6be01ce6e3669fe4f3a21e768ed", - "sha256:69aa417a030bf11ec46149636314c24c8d60fadb12fc0ee8f10fda0d918c879d", - "sha256:6ad935f0016be24c0e97fc8c40c465f9c4b85cbbe6eac48934c0dc4d2568321e", - "sha256:6b55ad10a35a21b8015eabddc9ba31eb590f54adc9cd39bcf09ff5349fd52125", - "sha256:6cf43c78c4282708a28e466316935ec7489a9c487518a77fa68f716c67909cec", - "sha256:6f424507f57878e424d9a95dc4ead3fbdd72fd201e404e861e465f28ea469951", - "sha256:70760b4c5560be6ca70d11f8988ee6542b003f982b32f83d5ac0b72476607b70", - "sha256:73e9439310f65d55a5a1e0564b48e34f5369bee943d72c88378f2d576f5a5751", - "sha256:7931b9e249edefb07cd6ae10c702788546341d5fe44db5b6108a25da4dca513f", - "sha256:81f34346dd63010453922c8e628a52ea2d2ccd73cb2487f7700ac531b247c8a5", - "sha256:888f8eee13f2377ce86d44f338968eedec3291876b0b8a7289247ba52cb984cd", - "sha256:95335095b6c7b1cc14c3f3f17d5452ce677e8490d101698562b2ffcacc304c8d", - "sha256:9565c3ab1c93310569ec0d86b017f128f027cab0b622b7af288696d7ed43a16d", - "sha256:95c765060e65c692da2d2f51a9499c5e9f5cf5453aeaf1420e3fc847cc060582", - "sha256:9969ef1e69b8c8e1e70d591f91bbc37fc9a3621e447525d1602801a24ceda898", - "sha256:9ca8e220006966b4a7b68e8984a6aee645a0384b0769e829ba60281fe61ec4f7", - "sha256:a39d18b3f50cc121d0ce3838d32d58bd1d15dab89c910358ebefc3665712256c", - "sha256:a66e8f628b71f78c0e0342003d53b53101ba4e00ea8dabb799d9dba0abbbcebe", - "sha256:a8de12b4b87c20de895f10567639c0797b621b22897b0af3ce4b4e204a743626", - "sha256:af41da5dca398d3474129c58cb2b106a5d93bbb196be0d307ac82311ca234342", - "sha256:b30a25f814591a8c0c5372c11ac8967f669b97444c47fd794926e175c4047ece", - "sha256:ba383dc6afd5ec5b7a0d0c23d38895db0e15bcba7fb0fa8901f245267ac30d86", - "sha256:bb4fbcab8764dc072cb651a4bcda4d11fb5658a1d8d68842a862a6610bd8cfa3", - "sha256:be9e3f68ca9edb897c2184ad0eee815c635565dbe7a0e7e814dc1f7cbab92c0a", - "sha256:bfa447506c1a52271f1b0de3f42ea0fa14676052549095e378d5bff1c505ff7b", - "sha256:cc94d7c5e8423920787c33d811c0be67b7be83c705f001f7180c7b186dcf10ca", - "sha256:cea0a27a89e6432705fffc178064503508e3c0184b4f061700e771a09de58187", - "sha256:cf95981b126f23db63e9dbe4cf65bd71f9a6305696fa5e2262693bc4e2183f5b", - "sha256:d4fe2348cc6ec372e25adec0219ee2334a68d2f5222e0cba9c0d613394e12d86", - "sha256:db0f04118d1db74db6c9e1cb1898532c7dcc220f1d2718f058601f7c3f499514", - "sha256:dd24bd8d77c98557880def750782df77ab2b6885a18483dc8588792247174b32", - "sha256:e1b5191d1648acc439b24721caab2fd0c86679d8549ed2c84d5a7ec1bedcc244", - "sha256:e5532482344186c543c37bfad0ee6069e8ae4fc38d073b8bc836fc8f03c9e250", - "sha256:e980b53a959fa53b6f05343afbd1e6f44a23ed6c23c4b4c56c6662bbb40c82ce", - "sha256:ef64c27bc40189f36fcc50c3fb8f16ccda73b6a0b80d9bd6e6ce4cffcd810bbd", - "sha256:f05031cf21699785cd47cb7485f67df619e7bcdae38e0fde40d23d3d0210d3c3" - ], - "markers": "python_version >= '3.9'", - "version": "==7.9.1" - }, - "debugpy": { - "hashes": [ - "sha256:0f920c7f9af409d90f5fd26e313e119d908b0dd2952c2393cd3247a462331f15", - "sha256:1b2ac8c13b2645e0b1eaf30e816404990fbdb168e193322be8f545e8c01644a9", - "sha256:281d44d248a0e1791ad0eafdbbd2912ff0de9eec48022a5bfbc332957487ed3f", - "sha256:329a15d0660ee09fec6786acdb6e0443d595f64f5d096fc3e3ccf09a4259033f", - "sha256:3784ec6e8600c66cbdd4ca2726c72d8ca781e94bce2f396cc606d458146f8f4e", - "sha256:3d937d93ae4fa51cdc94d3e865f535f185d5f9748efb41d0d49e33bf3365bd79", - "sha256:413512d35ff52c2fb0fd2d65e69f373ffd24f0ecb1fac514c04a668599c5ce7f", - "sha256:4c9156f7524a0d70b7a7e22b2e311d8ba76a15496fb00730e46dcdeedb9e1eea", - "sha256:5349b7c3735b766a281873fbe32ca9cca343d4cc11ba4a743f84cb854339ff35", - "sha256:5aa56ef8538893e4502a7d79047fe39b1dae08d9ae257074c6464a7b290b806f", - "sha256:5cd9a579d553b6cb9759a7908a41988ee6280b961f24f63336835d9418216a20", - "sha256:684eaf43c95a3ec39a96f1f5195a7ff3d4144e4a18d69bb66beeb1a6de605d6e", - "sha256:7118d462fe9724c887d355eef395fae68bc764fd862cdca94e70dcb9ade8a23d", - "sha256:7816acea4a46d7e4e50ad8d09d963a680ecc814ae31cdef3622eb05ccacf7b01", - "sha256:7cd287184318416850aa8b60ac90105837bb1e59531898c07569d197d2ed5322", - "sha256:8899c17920d089cfa23e6005ad9f22582fd86f144b23acb9feeda59e84405b84", - "sha256:93fee753097e85623cab1c0e6a68c76308cd9f13ffdf44127e6fab4fbf024339", - "sha256:b1528cfee6c1b1c698eb10b6b096c598738a8238822d218173d21c3086de8123", - "sha256:b44985f97cc3dd9d52c42eb59ee9d7ee0c4e7ecd62bca704891f997de4cef23d", - "sha256:c442f20577b38cc7a9aafecffe1094f78f07fb8423c3dddb384e6b8f49fd2987", - "sha256:c99295c76161ad8d507b413cd33422d7c542889fbb73035889420ac1fad354f2", - "sha256:cf431c343a99384ac7eab2f763980724834f933a271e90496944195318c619e2", - "sha256:d235e4fa78af2de4e5609073972700523e372cf5601742449970110d565ca28c", - "sha256:d5582bcbe42917bc6bbe5c12db1bffdf21f6bfc28d4554b738bf08d50dc0c8c3", - "sha256:f117dedda6d969c5c9483e23f573b38f4e39412845c7bc487b6f2648df30fe84", - "sha256:f6bb5c0dcf80ad5dbc7b7d6eac484e2af34bdacdf81df09b6a3e62792b722826" - ], - "markers": "python_version >= '3.8'", - "version": "==1.8.14" - }, - "decorator": { - "hashes": [ - "sha256:65f266143752f734b0a7cc83c46f4618af75b8c5911b00ccb61d0ac9b6da0360", - "sha256:d316bb415a2d9e2d2b3abcc4084c6502fc09240e292cd76a76afc106a1c8e04a" - ], - "markers": "python_version >= '3.8'", - "version": "==5.2.1" - }, - "defusedxml": { - "hashes": [ - "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69", - "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==0.7.1" - }, - "dill": { - "hashes": [ - "sha256:0633f1d2df477324f53a895b02c901fb961bdbf65a17122586ea7019292cbcf0", - "sha256:44f54bf6412c2c8464c14e8243eb163690a9800dbe2c367330883b19c7561049" - ], - "markers": "python_version >= '3.8'", - "version": "==0.4.0" - }, - "executing": { - "hashes": [ - "sha256:11387150cad388d62750327a53d3339fad4888b39a6fe233c3afbb54ecffd3aa", - "sha256:5d108c028108fe2551d1a7b2e8b713341e2cb4fc0aa7dcf966fa4327a5226755" - ], - "markers": "python_version >= '3.8'", - "version": "==2.2.0" - }, - "fastjsonschema": { - "hashes": [ - "sha256:794d4f0a58f848961ba16af7b9c85a3e88cd360df008c59aac6fc5ae9323b5d4", - "sha256:c9e5b7e908310918cf494a434eeb31384dd84a98b57a30bcb1f535015b554667" - ], - "version": "==2.21.1" - }, - "fqdn": { - "hashes": [ - "sha256:105ed3677e767fb5ca086a0c1f4bb66ebc3c100be518f0e0d755d9eae164d89f", - "sha256:3a179af3761e4df6eb2e026ff9e1a3033d3587bf980a0b1b2e1e5d08d7358014" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4' and python_version < '4'", - "version": "==1.5.1" - }, - "h11": { - "hashes": [ - "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", - "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86" - ], - "markers": "python_version >= '3.8'", - "version": "==0.16.0" - }, - "httpcore": { - "hashes": [ - "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55", - "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8" - ], - "markers": "python_version >= '3.8'", - "version": "==1.0.9" - }, - "httpx": { - "hashes": [ - "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc", - "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad" - ], - "markers": "python_version >= '3.8'", - "version": "==0.28.1" - }, - "idna": { - "hashes": [ - "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9", - "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3" - ], - "markers": "python_version >= '3.6'", - "version": "==3.10" - }, - "iniconfig": { - "hashes": [ - "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", - "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760" - ], - "markers": "python_version >= '3.8'", - "version": "==2.1.0" - }, - "ipykernel": { - "hashes": [ - "sha256:afdb66ba5aa354b09b91379bac28ae4afebbb30e8b39510c9690afb7a10421b5", - "sha256:f093a22c4a40f8828f8e330a9c297cb93dcab13bd9678ded6de8e5cf81c56215" - ], - "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==6.29.5" - }, - "ipython": { - "hashes": [ - "sha256:1a0b6dd9221a1f5dddf725b57ac0cb6fddc7b5f470576231ae9162b9b3455a04", - "sha256:79eb896f9f23f50ad16c3bc205f686f6e030ad246cc309c6279a242b14afe9d8" - ], - "markers": "python_version >= '3.11'", - "version": "==9.3.0" - }, - "ipython-pygments-lexers": { - "hashes": [ - "sha256:09c0138009e56b6854f9535736f4171d855c8c08a563a0dcd8022f78355c7e81", - "sha256:a9462224a505ade19a605f71f8fa63c2048833ce50abc86768a0d81d876dc81c" - ], - "markers": "python_version >= '3.8'", - "version": "==1.1.1" - }, - "isoduration": { - "hashes": [ - "sha256:ac2f9015137935279eac671f94f89eb00584f940f5dc49462a0c4ee692ba1bd9", - "sha256:b2904c2a4228c3d44f409c8ae8e2370eb21a26f7ac2ec5446df141dde3452042" - ], - "markers": "python_version >= '3.7'", - "version": "==20.11.0" - }, - "isort": { - "hashes": [ - "sha256:1cb5df28dfbc742e490c5e41bad6da41b805b0a8be7bc93cd0fb2a8a890ac450", - "sha256:2dc5d7f65c9678d94c88dfc29161a320eec67328bc97aad576874cb4be1e9615" - ], - "markers": "python_full_version >= '3.9.0'", - "version": "==6.0.1" - }, - "jedi": { - "hashes": [ - "sha256:4770dc3de41bde3966b02eb84fbcf557fb33cce26ad23da12c742fb50ecb11f0", - "sha256:a8ef22bde8490f57fe5c7681a3c83cb58874daf72b4784de3cce5b6ef6edb5b9" - ], - "markers": "python_version >= '3.6'", - "version": "==0.19.2" - }, - "jinja2": { - "hashes": [ - "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d", - "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67" - ], - "markers": "python_version >= '3.7'", - "version": "==3.1.6" - }, - "json5": { - "hashes": [ - "sha256:0b4b6ff56801a1c7dc817b0241bca4ce474a0e6a163bfef3fc594d3fd263ff3a", - "sha256:6d37aa6c08b0609f16e1ec5ff94697e2cbbfbad5ac112afa05794da9ab7810db" - ], - "markers": "python_full_version >= '3.8.0'", - "version": "==0.12.0" - }, - "jsonpointer": { - "hashes": [ - "sha256:13e088adc14fca8b6aa8177c044e12701e6ad4b28ff10e65f2267a90109c9942", - "sha256:2b2d729f2091522d61c3b31f82e11870f60b68f43fbc705cb76bf4b832af59ef" - ], - "markers": "python_version >= '3.7'", - "version": "==3.0.0" - }, - "jsonschema": { - "extras": [ - "format-nongpl" - ], - "hashes": [ - "sha256:0b4e8069eb12aedfa881333004bccaec24ecef5a8a6a4b6df142b2cc9599d196", - "sha256:a462455f19f5faf404a7902952b6f0e3ce868f3ee09a359b05eca6673bd8412d" - ], - "markers": "python_version >= '3.9'", - "version": "==4.24.0" - }, - "jsonschema-specifications": { - "hashes": [ - "sha256:4653bffbd6584f7de83a67e0d620ef16900b390ddc7939d56684d6c81e33f1af", - "sha256:630159c9f4dbea161a6a2205c3011cc4f18ff381b189fff48bb39b9bf26ae608" - ], - "markers": "python_version >= '3.9'", - "version": "==2025.4.1" - }, - "jupyter-client": { - "hashes": [ - "sha256:35b3a0947c4a6e9d589eb97d7d4cd5e90f910ee73101611f01283732bd6d9419", - "sha256:e8a19cc986cc45905ac3362915f410f3af85424b4c0905e94fa5f2cb08e8f23f" - ], - "markers": "python_version >= '3.8'", - "version": "==8.6.3" - }, - "jupyter-core": { - "hashes": [ - "sha256:0a5f9706f70e64786b75acba995988915ebd4601c8a52e534a40b51c95f59941", - "sha256:c28d268fc90fb53f1338ded2eb410704c5449a358406e8a948b75706e24863d0" - ], - "markers": "python_version >= '3.8'", - "version": "==5.8.1" - }, - "jupyter-events": { - "hashes": [ - "sha256:6464b2fa5ad10451c3d35fabc75eab39556ae1e2853ad0c0cc31b656731a97fb", - "sha256:fc3fce98865f6784c9cd0a56a20644fc6098f21c8c33834a8d9fe383c17e554b" - ], - "markers": "python_version >= '3.9'", - "version": "==0.12.0" - }, - "jupyter-lsp": { - "hashes": [ - "sha256:45fbddbd505f3fbfb0b6cb2f1bc5e15e83ab7c79cd6e89416b248cb3c00c11da", - "sha256:793147a05ad446f809fd53ef1cd19a9f5256fd0a2d6b7ce943a982cb4f545001" - ], - "markers": "python_version >= '3.8'", - "version": "==2.2.5" - }, - "jupyter-server": { - "hashes": [ - "sha256:3d8db5be3bc64403b1c65b400a1d7f4647a5ce743f3b20dbdefe8ddb7b55af9e", - "sha256:65d4b44fdf2dcbbdfe0aa1ace4a842d4aaf746a2b7b168134d5aaed35621b7f6" - ], - "markers": "python_version >= '3.9'", - "version": "==2.16.0" - }, - "jupyter-server-terminals": { - "hashes": [ - "sha256:41ee0d7dc0ebf2809c668e0fc726dfaf258fcd3e769568996ca731b6194ae9aa", - "sha256:5ae0295167220e9ace0edcfdb212afd2b01ee8d179fe6f23c899590e9b8a5269" - ], - "markers": "python_version >= '3.8'", - "version": "==0.5.3" - }, - "jupyterlab": { - "hashes": [ - "sha256:164302f6d4b6c44773dfc38d585665a4db401a16e5296c37df5cba63904fbdea", - "sha256:a94c32fd7f8b93e82a49dc70a6ec45a5c18281ca2a7228d12765e4e210e5bca2" - ], - "markers": "python_version >= '3.9'", - "version": "==4.4.3" - }, - "jupyterlab-pygments": { - "hashes": [ - "sha256:721aca4d9029252b11cfa9d185e5b5af4d54772bb8072f9b7036f4170054d35d", - "sha256:841a89020971da1d8693f1a99997aefc5dc424bb1b251fd6322462a1b8842780" - ], - "markers": "python_version >= '3.8'", - "version": "==0.3.0" - }, - "jupyterlab-server": { - "hashes": [ - "sha256:e697488f66c3db49df675158a77b3b017520d772c6e1548c7d9bcc5df7944ee4", - "sha256:eb36caca59e74471988f0ae25c77945610b887f777255aa21f8065def9e51ed4" - ], - "markers": "python_version >= '3.8'", - "version": "==2.27.3" - }, - "markupsafe": { - "hashes": [ - "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4", - "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30", - "sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0", - "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9", - "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396", - "sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13", - "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028", - "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca", - "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557", - "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832", - "sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0", - "sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b", - "sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579", - "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a", - "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c", - "sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff", - "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c", - "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22", - "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094", - "sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb", - "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e", - "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5", - "sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a", - "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d", - "sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a", - "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b", - "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8", - "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225", - "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c", - "sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144", - "sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f", - "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87", - "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d", - "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93", - "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf", - "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158", - "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84", - "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb", - "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48", - "sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171", - "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c", - "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6", - "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd", - "sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d", - "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1", - "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d", - "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca", - "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a", - "sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29", - "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe", - "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798", - "sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c", - "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8", - "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f", - "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f", - "sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a", - "sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178", - "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0", - "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79", - "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430", - "sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50" - ], - "markers": "python_version >= '3.9'", - "version": "==3.0.2" - }, - "matplotlib-inline": { - "hashes": [ - "sha256:8423b23ec666be3d16e16b60bdd8ac4e86e840ebd1dd11a30b9f117f2fa0ab90", - "sha256:df192d39a4ff8f21b1895d72e6a13f5fcc5099f00fa84384e0ea28c2cc0653ca" - ], - "markers": "python_version >= '3.8'", - "version": "==0.1.7" - }, - "mccabe": { - "hashes": [ - "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325", - "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e" - ], - "markers": "python_version >= '3.6'", - "version": "==0.7.0" - }, - "mistune": { - "hashes": [ - "sha256:1a32314113cff28aa6432e99e522677c8587fd83e3d51c29b82a52409c842bd9", - "sha256:a7035c21782b2becb6be62f8f25d3df81ccb4d6fa477a6525b15af06539f02a0" - ], - "markers": "python_version >= '3.8'", - "version": "==3.1.3" - }, - "nbclient": { - "hashes": [ - "sha256:4ffee11e788b4a27fabeb7955547e4318a5298f34342a4bfd01f2e1faaeadc3d", - "sha256:90b7fc6b810630db87a6d0c2250b1f0ab4cf4d3c27a299b0cde78a4ed3fd9193" - ], - "markers": "python_full_version >= '3.9.0'", - "version": "==0.10.2" - }, - "nbconvert": { - "hashes": [ - "sha256:1375a7b67e0c2883678c48e506dc320febb57685e5ee67faa51b18a90f3a712b", - "sha256:576a7e37c6480da7b8465eefa66c17844243816ce1ccc372633c6b71c3c0f582" - ], - "markers": "python_version >= '3.8'", - "version": "==7.16.6" - }, - "nbformat": { - "hashes": [ - "sha256:322168b14f937a5d11362988ecac2a4952d3d8e3a2cbeb2319584631226d5b3a", - "sha256:3b48d6c8fbca4b299bf3982ea7db1af21580e4fec269ad087b9e81588891200b" - ], - "markers": "python_version >= '3.8'", - "version": "==5.10.4" - }, - "nest-asyncio": { - "hashes": [ - "sha256:6f172d5449aca15afd6c646851f4e31e02c598d553a667e38cafa997cfec55fe", - "sha256:87af6efd6b5e897c81050477ef65c62e2b2f35d51703cae01aff2905b1852e1c" - ], - "markers": "python_version >= '3.5'", - "version": "==1.6.0" - }, - "notebook": { - "hashes": [ - "sha256:9cdeee954e04101cadb195d90e2ab62b7c9286c1d4f858bf3bb54e40df16c0c3", - "sha256:a1567481cd3853f2610ee0ecf5dfa12bb508e878ee8f92152c134ef7f0568a76" - ], - "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==7.4.3" - }, - "notebook-shim": { - "hashes": [ - "sha256:411a5be4e9dc882a074ccbcae671eda64cceb068767e9a3419096986560e1cef", - "sha256:b4b2cfa1b65d98307ca24361f5b30fe785b53c3fd07b7a47e89acb5e6ac638cb" - ], - "markers": "python_version >= '3.7'", - "version": "==0.2.4" - }, - "overrides": { - "hashes": [ - "sha256:55158fa3d93b98cc75299b1e67078ad9003ca27945c76162c1c0766d6f91820a", - "sha256:c7ed9d062f78b8e4c1a7b70bd8796b35ead4d9f510227ef9c5dc7626c60d7e49" - ], - "markers": "python_version >= '3.6'", - "version": "==7.7.0" - }, - "packaging": { - "hashes": [ - "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484", - "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f" - ], - "markers": "python_version >= '3.8'", - "version": "==25.0" - }, - "pandocfilters": { - "hashes": [ - "sha256:002b4a555ee4ebc03f8b66307e287fa492e4a77b4ea14d3f934328297bb4939e", - "sha256:93be382804a9cdb0a7267585f157e5d1731bbe5545a85b268d6f5fe6232de2bc" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==1.5.1" - }, - "parso": { - "hashes": [ - "sha256:a418670a20291dacd2dddc80c377c5c3791378ee1e8d12bffc35420643d43f18", - "sha256:eb3a7b58240fb99099a345571deecc0f9540ea5f4dd2fe14c2a99d6b281ab92d" - ], - "markers": "python_version >= '3.6'", - "version": "==0.8.4" - }, - "pexpect": { - "hashes": [ - "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523", - "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f" - ], - "markers": "sys_platform != 'win32' and sys_platform != 'emscripten'", - "version": "==4.9.0" - }, - "platformdirs": { - "hashes": [ - "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc", - "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4" - ], - "markers": "python_version >= '3.9'", - "version": "==4.3.8" - }, - "pluggy": { - "hashes": [ - "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", - "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746" - ], - "markers": "python_version >= '3.9'", - "version": "==1.6.0" - }, - "prometheus-client": { - "hashes": [ - "sha256:190f1331e783cf21eb60bca559354e0a4d4378facecf78f5428c39b675d20d28", - "sha256:cca895342e308174341b2cbf99a56bef291fbc0ef7b9e5412a0f26d653ba7094" - ], - "markers": "python_version >= '3.9'", - "version": "==0.22.1" - }, - "prompt-toolkit": { - "hashes": [ - "sha256:52742911fde84e2d423e2f9a4cf1de7d7ac4e51958f648d9540e0fb8db077b07", - "sha256:931a162e3b27fc90c86f1b48bb1fb2c528c2761475e57c9c06de13311c7b54ed" - ], - "markers": "python_version >= '3.8'", - "version": "==3.0.51" - }, - "psutil": { - "hashes": [ - "sha256:101d71dc322e3cffd7cea0650b09b3d08b8e7c4109dd6809fe452dfd00e58b25", - "sha256:1e744154a6580bc968a0195fd25e80432d3afec619daf145b9e5ba16cc1d688e", - "sha256:1fcee592b4c6f146991ca55919ea3d1f8926497a713ed7faaf8225e174581e91", - "sha256:39db632f6bb862eeccf56660871433e111b6ea58f2caea825571951d4b6aa3da", - "sha256:4b1388a4f6875d7e2aff5c4ca1cc16c545ed41dd8bb596cefea80111db353a34", - "sha256:4cf3d4eb1aa9b348dec30105c55cd9b7d4629285735a102beb4441e38db90553", - "sha256:7be9c3eba38beccb6495ea33afd982a44074b78f28c434a1f51cc07fd315c456", - "sha256:84df4eb63e16849689f76b1ffcb36db7b8de703d1bc1fe41773db487621b6c17", - "sha256:a5f098451abc2828f7dc6b58d44b532b22f2088f4999a937557b603ce72b1993", - "sha256:ba3fcef7523064a6c9da440fc4d6bd07da93ac726b5733c29027d7dc95b39d99" - ], - "markers": "python_version >= '3.6'", - "version": "==7.0.0" - }, - "ptyprocess": { - "hashes": [ - "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35", - "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220" - ], - "version": "==0.7.0" - }, - "pure-eval": { - "hashes": [ - "sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0", - "sha256:5f4e983f40564c576c7c8635ae88db5956bb2229d7e9237d03b3c0b0190eaf42" - ], - "version": "==0.2.3" - }, - "pycparser": { - "hashes": [ - "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6", - "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc" - ], - "markers": "python_version >= '3.8'", - "version": "==2.22" - }, - "pydeps": { - "hashes": [ - "sha256:7c86ee63c9ee6ddd088c840364981c5aa214a994d323bb7fa4724fca30829bee", - "sha256:a57415a8fae2ff6840a199b7dfcfecb90c37e4b9b54b58a111808a3440bc03bc" - ], - "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==3.0.1" - }, - "pygments": { - "hashes": [ - "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", - "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b" - ], - "markers": "python_version >= '3.8'", - "version": "==2.19.2" - }, - "pylint": { - "hashes": [ - "sha256:2b11de8bde49f9c5059452e0c310c079c746a0a8eeaa789e5aa966ecc23e4559", - "sha256:43860aafefce92fca4cf6b61fe199cdc5ae54ea28f9bf4cd49de267b5195803d" - ], - "index": "pypi", - "markers": "python_full_version >= '3.9.0'", - "version": "==3.3.7" - }, - "pytest": { - "hashes": [ - "sha256:539c70ba6fcead8e78eebbf1115e8b589e7565830d7d006a8723f19ac8a0afb7", - "sha256:7c67fd69174877359ed9371ec3af8a3d2b04741818c51e5e99cc1742251fa93c" - ], - "index": "pypi", - "markers": "python_version >= '3.9'", - "version": "==8.4.1" - }, - "pytest-cov": { - "hashes": [ - "sha256:25cc6cc0a5358204b8108ecedc51a9b57b34cc6b8c967cc2c01a4e00d8a67da2", - "sha256:f5bc4c23f42f1cdd23c70b1dab1bbaef4fc505ba950d53e0081d0730dd7e86d5" - ], - "index": "pypi", - "markers": "python_version >= '3.9'", - "version": "==6.2.1" - }, - "python-dateutil": { - "hashes": [ - "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", - "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", - "version": "==2.9.0.post0" - }, - "python-json-logger": { - "hashes": [ - "sha256:12b7e74b17775e7d565129296105bbe3910842d9d0eb083fc83a6a617aa8df84", - "sha256:dd980fae8cffb24c13caf6e158d3d61c0d6d22342f932cb6e9deedab3d35eec7" - ], - "markers": "python_version >= '3.8'", - "version": "==3.3.0" - }, - "pyyaml": { - "hashes": [ - "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff", - "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48", - "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086", - "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e", - "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133", - "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5", - "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484", - "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee", - "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5", - "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68", - "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a", - "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf", - "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99", - "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8", - "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85", - "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19", - "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc", - "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a", - "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1", - "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317", - "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c", - "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631", - "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d", - "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652", - "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5", - "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e", - "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b", - "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8", - "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476", - "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706", - "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563", - "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237", - "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b", - "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083", - "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180", - "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425", - "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e", - "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f", - "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725", - "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183", - "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab", - "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774", - "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725", - "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e", - "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5", - "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d", - "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290", - "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44", - "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed", - "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4", - "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba", - "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12", - "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4" - ], - "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==6.0.2" - }, - "pyzmq": { - "hashes": [ - "sha256:00387d12a8af4b24883895f7e6b9495dc20a66027b696536edac35cb988c38f3", - "sha256:04cd50ef3b28e35ced65740fb9956a5b3f77a6ff32fcd887e3210433f437dd0f", - "sha256:0546a720c1f407b2172cb04b6b094a78773491497e3644863cf5c96c42df8cff", - "sha256:096af9e133fec3a72108ddefba1e42985cb3639e9de52cfd336b6fc23aa083e9", - "sha256:100f6e5052ba42b2533011d34a018a5ace34f8cac67cb03cfa37c8bdae0ca617", - "sha256:10f70c1d9a446a85013a36871a296007f6fe4232b530aa254baf9da3f8328bc0", - "sha256:111db5f395e09f7e775f759d598f43cb815fc58e0147623c4816486e1a39dc22", - "sha256:14fe7aaac86e4e93ea779a821967360c781d7ac5115b3f1a171ced77065a0174", - "sha256:15f39d50bd6c9091c67315ceb878a4f531957b121d2a05ebd077eb35ddc5efed", - "sha256:1958947983fef513e6e98eff9cb487b60bf14f588dc0e6bf35fa13751d2c8251", - "sha256:20d5cb29e8c5f76a127c75b6e7a77e846bc4b655c373baa098c26a61b7ecd0ef", - "sha256:21457825249b2a53834fa969c69713f8b5a79583689387a5e7aed880963ac564", - "sha256:2524c40891be6a3106885a3935d58452dd83eb7a5742a33cc780a1ad4c49dec0", - "sha256:26b72c5ae20bf59061c3570db835edb81d1e0706ff141747055591c4b41193f8", - "sha256:26d542258c7a1f35a9cff3d887687d3235006134b0ac1c62a6fe1ad3ac10440e", - "sha256:29f44e3c26b9783816ba9ce274110435d8f5b19bbd82f7a6c7612bb1452a3597", - "sha256:2c386339d7e3f064213aede5d03d054b237937fbca6dd2197ac8cf3b25a6b14e", - "sha256:39ddd3ba0a641f01d8f13a3cfd4c4924eb58e660d8afe87e9061d6e8ca6f7ac3", - "sha256:42c7555123679637c99205b1aa9e8f7d90fe29d4c243c719e347d4852545216c", - "sha256:4c19d39c04c29a6619adfeb19e3735c421b3bfee082f320662f52e59c47202ba", - "sha256:4e7d0a8d460fba526cc047333bdcbf172a159b8bd6be8c3eb63a416ff9ba1477", - "sha256:50360fb2a056ffd16e5f4177eee67f1dd1017332ea53fb095fe7b5bf29c70246", - "sha256:51f5726de3532b8222e569990c8aa34664faa97038304644679a51d906e60c6e", - "sha256:53a48f0228eab6cbf69fde3aa3c03cbe04e50e623ef92ae395fce47ef8a76152", - "sha256:55a0155b148fe0428285a30922f7213539aa84329a5ad828bca4bbbc665c70a4", - "sha256:56e46bbb85d52c1072b3f809cc1ce77251d560bc036d3a312b96db1afe76db2e", - "sha256:5b10bd6f008937705cf6e7bf8b6ece5ca055991e3eb130bca8023e20b86aa9a3", - "sha256:5cd11d46d7b7e5958121b3eaf4cd8638eff3a720ec527692132f05a57f14341d", - "sha256:5d5ef4718ecab24f785794e0e7536436698b459bfbc19a1650ef55280119d93b", - "sha256:60e8cc82d968174650c1860d7b716366caab9973787a1c060cf8043130f7d0f7", - "sha256:63af72b2955fc77caf0a77444baa2431fcabb4370219da38e1a9f8d12aaebe28", - "sha256:656c1866505a5735d0660b7da6d7147174bbf59d4975fc2b7f09f43c9bc25745", - "sha256:661942bc7cd0223d569d808f2e5696d9cc120acc73bf3e88a1f1be7ab648a7e4", - "sha256:67855c14173aec36395d7777aaba3cc527b393821f30143fd20b98e1ff31fd38", - "sha256:67bfbcbd0a04c575e8103a6061d03e393d9f80ffdb9beb3189261e9e9bc5d5e9", - "sha256:6a56e3e5bd2d62a01744fd2f1ce21d760c7c65f030e9522738d75932a14ab62a", - "sha256:6ad0562d4e6abb785be3e4dd68599c41be821b521da38c402bc9ab2a8e7ebc7e", - "sha256:6b0397b0be277b46762956f576e04dc06ced265759e8c2ff41a0ee1aa0064198", - "sha256:6e435540fa1da54667f0026cf1e8407fe6d8a11f1010b7f06b0b17214ebfcf5e", - "sha256:7011ade88c8e535cf140f8d1a59428676fbbce7c6e54fefce58bf117aefb6667", - "sha256:74175b9e12779382432dd1d1f5960ebe7465d36649b98a06c6b26be24d173fab", - "sha256:7cdf07fe0a557b131366f80727ec8ccc4b70d89f1e3f920d94a594d598d754f0", - "sha256:8617c7d43cd8ccdb62aebe984bfed77ca8f036e6c3e46dd3dddda64b10f0ab7a", - "sha256:88b4e43cab04c3c0f0d55df3b1eef62df2b629a1a369b5289a58f6fa8b07c4f4", - "sha256:8c86ea8fe85e2eb0ffa00b53192c401477d5252f6dd1db2e2ed21c1c30d17e5e", - "sha256:8ca7e6a0388dd9e1180b14728051068f4efe83e0d2de058b5ff92c63f399a73f", - "sha256:90252fa2ff3a104219db1f5ced7032a7b5fc82d7c8d2fec2b9a3e6fd4e25576b", - "sha256:9df43a2459cd3a3563404c1456b2c4c69564daa7dbaf15724c09821a3329ce46", - "sha256:a20528da85c7ac7a19b7384e8c3f8fa707841fd85afc4ed56eda59d93e3d98ad", - "sha256:a979b7cf9e33d86c4949df527a3018767e5f53bc3b02adf14d4d8db1db63ccc0", - "sha256:ae2b34bcfaae20c064948a4113bf8709eee89fd08317eb293ae4ebd69b4d9740", - "sha256:b1f08eeb9ce1510e6939b6e5dcd46a17765e2333daae78ecf4606808442e52cf", - "sha256:b801c2e40c5aa6072c2f4876de8dccd100af6d9918d4d0d7aa54a1d982fd4f44", - "sha256:b973ee650e8f442ce482c1d99ca7ab537c69098d53a3d046676a484fd710c87a", - "sha256:bf6c6b061efd00404b9750e2cfbd9507492c8d4b3721ded76cb03786131be2ed", - "sha256:c0dc628b5493f9a8cd9844b8bee9732ef587ab00002157c9329e4fc0ef4d3afa", - "sha256:c0ed2c1f335ba55b5fdc964622254917d6b782311c50e138863eda409fbb3b6d", - "sha256:c2dace4a7041cca2fba5357a2d7c97c5effdf52f63a1ef252cfa496875a3762d", - "sha256:c36ad534c0c29b4afa088dc53543c525b23c0797e01b69fef59b1a9c0e38b688", - "sha256:c45fee3968834cd291a13da5fac128b696c9592a9493a0f7ce0b47fa03cc574d", - "sha256:c5817641eebb391a2268c27fecd4162448e03538387093cdbd8bf3510c316b38", - "sha256:c644aaacc01d0df5c7072826df45e67301f191c55f68d7b2916d83a9ddc1b551", - "sha256:c8878011653dcdc27cc2c57e04ff96f0471e797f5c19ac3d7813a245bcb24371", - "sha256:cae73bb6898c4e045fbed5024cb587e4110fddb66f6163bcab5f81f9d4b9c496", - "sha256:cb0ac5179cba4b2f94f1aa208fbb77b62c4c9bf24dd446278b8b602cf85fcda3", - "sha256:cbabc59dcfaac66655c040dfcb8118f133fb5dde185e5fc152628354c1598e52", - "sha256:cd1dc59763effd1576f8368047c9c31468fce0af89d76b5067641137506792ae", - "sha256:cf209a6dc4b420ed32a7093642843cbf8703ed0a7d86c16c0b98af46762ebefb", - "sha256:d8229f2efece6a660ee211d74d91dbc2a76b95544d46c74c615e491900dc107f", - "sha256:d8c6de908465697a8708e4d6843a1e884f567962fc61eb1706856545141d0cbb", - "sha256:dc1091f59143b471d19eb64f54bae4f54bcf2a466ffb66fe45d94d8d734eb495", - "sha256:dce4199bf5f648a902ce37e7b3afa286f305cd2ef7a8b6ec907470ccb6c8b371", - "sha256:e40609380480b3d12c30f841323f42451c755b8fece84235236f5fe5ffca8c1c", - "sha256:e8c4adce8e37e75c4215297d7745551b8dcfa5f728f23ce09bf4e678a9399413", - "sha256:e918d70862d4cfd4b1c187310015646a14e1f5917922ab45b29f28f345eeb6be", - "sha256:ea6d441c513bf18c578c73c323acf7b4184507fc244762193aa3a871333c9045", - "sha256:ee05728c0b0b2484a9fc20466fa776fffb65d95f7317a3419985b8c908563861", - "sha256:f4162dbbd9c5c84fb930a36f290b08c93e35fce020d768a16fc8891a2f72bab8", - "sha256:f7bbe9e1ed2c8d3da736a15694d87c12493e54cc9dc9790796f0321794bbc91f" - ], - "markers": "python_version >= '3.8'", - "version": "==27.0.0" - }, - "referencing": { - "hashes": [ - "sha256:df2e89862cd09deabbdba16944cc3f10feb6b3e6f18e902f7cc25609a34775aa", - "sha256:e8699adbbf8b5c7de96d8ffa0eb5c158b3beafce084968e2ea8bb08c6794dcd0" - ], - "markers": "python_version >= '3.9'", - "version": "==0.36.2" - }, - "requests": { - "hashes": [ - "sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c", - "sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422" - ], - "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==2.32.4" - }, - "requests-mock": { - "hashes": [ - "sha256:b1e37054004cdd5e56c84454cc7df12b25f90f382159087f4b6915aaeef39563", - "sha256:e9e12e333b525156e82a3c852f22016b9158220d2f47454de9cae8a77d371401" - ], - "index": "pypi", - "markers": "python_version >= '3.5'", - "version": "==1.12.1" - }, - "rfc3339-validator": { - "hashes": [ - "sha256:138a2abdf93304ad60530167e51d2dfb9549521a836871b88d7f4695d0022f6b", - "sha256:24f6ec1eda14ef823da9e36ec7113124b39c04d50a4d3d3a3c2859577e7791fa" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==0.1.4" - }, - "rfc3986-validator": { - "hashes": [ - "sha256:2f235c432ef459970b4306369336b9d5dbdda31b510ca1e327636e01f528bfa9", - "sha256:3d44bde7921b3b9ec3ae4e3adca370438eccebc676456449b145d533b240d055" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==0.1.1" - }, - "rpds-py": { - "hashes": [ - "sha256:0317177b1e8691ab5879f4f33f4b6dc55ad3b344399e23df2e499de7b10a548d", - "sha256:036ded36bedb727beeabc16dc1dad7cb154b3fa444e936a03b67a86dc6a5066e", - "sha256:048893e902132fd6548a2e661fb38bf4896a89eea95ac5816cf443524a85556f", - "sha256:0701942049095741a8aeb298a31b203e735d1c61f4423511d2b1a41dcd8a16da", - "sha256:083a9513a33e0b92cf6e7a6366036c6bb43ea595332c1ab5c8ae329e4bcc0a9c", - "sha256:09eab132f41bf792c7a0ea1578e55df3f3e7f61888e340779b06050a9a3f16e9", - "sha256:0e6a327af8ebf6baba1c10fadd04964c1965d375d318f4435d5f3f9651550f4a", - "sha256:0eb90e94f43e5085623932b68840b6f379f26db7b5c2e6bcef3179bd83c9330f", - "sha256:114a07e85f32b125404f28f2ed0ba431685151c037a26032b213c882f26eb908", - "sha256:115874ae5e2fdcfc16b2aedc95b5eef4aebe91b28e7e21951eda8a5dc0d3461b", - "sha256:140f61d9bed7839446bdd44852e30195c8e520f81329b4201ceead4d64eb3a9f", - "sha256:1521031351865e0181bc585147624d66b3b00a84109b57fcb7a779c3ec3772cd", - "sha256:1c0c434a53714358532d13539272db75a5ed9df75a4a090a753ac7173ec14e11", - "sha256:1d1fadd539298e70cac2f2cb36f5b8a65f742b9b9f1014dd4ea1f7785e2470bf", - "sha256:1de336a4b164c9188cb23f3703adb74a7623ab32d20090d0e9bf499a2203ad65", - "sha256:1ee3e26eb83d39b886d2cb6e06ea701bba82ef30a0de044d34626ede51ec98b0", - "sha256:245550f5a1ac98504147cba96ffec8fabc22b610742e9150138e5d60774686d7", - "sha256:2a40046a529cc15cef88ac5ab589f83f739e2d332cb4d7399072242400ed68c9", - "sha256:2c2cd1a4b0c2b8c5e31ffff50d09f39906fe351389ba143c195566056c13a7ea", - "sha256:2cb9e5b5e26fc02c8a4345048cd9998c2aca7c2712bd1b36da0c72ee969a3523", - "sha256:33358883a4490287e67a2c391dfaea4d9359860281db3292b6886bf0be3d8692", - "sha256:35634369325906bcd01577da4c19e3b9541a15e99f31e91a02d010816b49bfda", - "sha256:35a8d1a24b5936b35c5003313bc177403d8bdef0f8b24f28b1c4a255f94ea992", - "sha256:3af5b4cc10fa41e5bc64e5c198a1b2d2864337f8fcbb9a67e747e34002ce812b", - "sha256:3bcce0edc1488906c2d4c75c94c70a0417e83920dd4c88fec1078c94843a6ce9", - "sha256:3c5b317ecbd8226887994852e85de562f7177add602514d4ac40f87de3ae45a8", - "sha256:3c6564c0947a7f52e4792983f8e6cf9bac140438ebf81f527a21d944f2fd0a40", - "sha256:3ebd879ab996537fc510a2be58c59915b5dd63bccb06d1ef514fee787e05984a", - "sha256:3f0b1798cae2bbbc9b9db44ee068c556d4737911ad53a4e5093d09d04b3bbc24", - "sha256:401ca1c4a20cc0510d3435d89c069fe0a9ae2ee6495135ac46bdd49ec0495763", - "sha256:454601988aab2c6e8fd49e7634c65476b2b919647626208e376afcd22019eeb8", - "sha256:4593c4eae9b27d22df41cde518b4b9e4464d139e4322e2127daa9b5b981b76be", - "sha256:45e484db65e5380804afbec784522de84fa95e6bb92ef1bd3325d33d13efaebd", - "sha256:48d64155d02127c249695abb87d39f0faf410733428d499867606be138161d65", - "sha256:4fbb0dbba559959fcb5d0735a0f87cdbca9e95dac87982e9b95c0f8f7ad10255", - "sha256:4fd52d3455a0aa997734f3835cbc4c9f32571345143960e7d7ebfe7b5fbfa3b2", - "sha256:50f2c501a89c9a5f4e454b126193c5495b9fb441a75b298c60591d8a2eb92e1b", - "sha256:58f77c60956501a4a627749a6dcb78dac522f249dd96b5c9f1c6af29bfacfb66", - "sha256:5a3ddb74b0985c4387719fc536faced33cadf2172769540c62e2a94b7b9be1c4", - "sha256:5c4a128527fe415d73cf1f70a9a688d06130d5810be69f3b553bf7b45e8acf79", - "sha256:5d473be2b13600b93a5675d78f59e63b51b1ba2d0476893415dfbb5477e65b31", - "sha256:5d9e40f32745db28c1ef7aad23f6fc458dc1e29945bd6781060f0d15628b8ddf", - "sha256:5f048bbf18b1f9120685c6d6bb70cc1a52c8cc11bdd04e643d28d3be0baf666d", - "sha256:605ffe7769e24b1800b4d024d24034405d9404f0bc2f55b6db3362cd34145a6f", - "sha256:6099263f526efff9cf3883dfef505518730f7a7a93049b1d90d42e50a22b4793", - "sha256:659d87430a8c8c704d52d094f5ba6fa72ef13b4d385b7e542a08fc240cb4a559", - "sha256:666fa7b1bd0a3810a7f18f6d3a25ccd8866291fbbc3c9b912b917a6715874bb9", - "sha256:68f6f060f0bbdfb0245267da014d3a6da9be127fe3e8cc4a68c6f833f8a23bb1", - "sha256:6d273f136e912aa101a9274c3145dcbddbe4bac560e77e6d5b3c9f6e0ed06d34", - "sha256:6d50841c425d16faf3206ddbba44c21aa3310a0cebc3c1cdfc3e3f4f9f6f5728", - "sha256:771c16060ff4e79584dc48902a91ba79fd93eade3aa3a12d6d2a4aadaf7d542b", - "sha256:785ffacd0ee61c3e60bdfde93baa6d7c10d86f15655bd706c89da08068dc5038", - "sha256:796ad874c89127c91970652a4ee8b00d56368b7e00d3477f4415fe78164c8000", - "sha256:79dc317a5f1c51fd9c6a0c4f48209c6b8526d0524a6904fc1076476e79b00f98", - "sha256:7c9409b47ba0650544b0bb3c188243b83654dfe55dcc173a86832314e1a6a35d", - "sha256:7d779b325cc8238227c47fbc53964c8cc9a941d5dbae87aa007a1f08f2f77b23", - "sha256:816568614ecb22b18a010c7a12559c19f6fe993526af88e95a76d5a60b8b75fb", - "sha256:8378fa4a940f3fb509c081e06cb7f7f2adae8cf46ef258b0e0ed7519facd573e", - "sha256:85608eb70a659bf4c1142b2781083d4b7c0c4e2c90eff11856a9754e965b2540", - "sha256:85fc223d9c76cabe5d0bff82214459189720dc135db45f9f66aa7cffbf9ff6c1", - "sha256:88ec04afe0c59fa64e2f6ea0dd9657e04fc83e38de90f6de201954b4d4eb59bd", - "sha256:8960b6dac09b62dac26e75d7e2c4a22efb835d827a7278c34f72b2b84fa160e3", - "sha256:89706d0683c73a26f76a5315d893c051324d771196ae8b13e6ffa1ffaf5e574f", - "sha256:89c24300cd4a8e4a51e55c31a8ff3918e6651b241ee8876a42cc2b2a078533ba", - "sha256:8c742af695f7525e559c16f1562cf2323db0e3f0fbdcabdf6865b095256b2d40", - "sha256:8dbd586bfa270c1103ece2109314dd423df1fa3d9719928b5d09e4840cec0d72", - "sha256:8eb8c84ecea987a2523e057c0d950bcb3f789696c0499290b8d7b3107a719d78", - "sha256:921954d7fbf3fccc7de8f717799304b14b6d9a45bbeec5a8d7408ccbf531faf5", - "sha256:9a46c2fb2545e21181445515960006e85d22025bd2fe6db23e76daec6eb689fe", - "sha256:9c006f3aadeda131b438c3092124bd196b66312f0caa5823ef09585a669cf449", - "sha256:9ceca1cf097ed77e1a51f1dbc8d174d10cb5931c188a4505ff9f3e119dfe519b", - "sha256:9e5fc7484fa7dce57e25063b0ec9638ff02a908304f861d81ea49273e43838c1", - "sha256:9f2f48ab00181600ee266a095fe815134eb456163f7d6699f525dee471f312cf", - "sha256:9fca84a15333e925dd59ce01da0ffe2ffe0d6e5d29a9eeba2148916d1824948c", - "sha256:a49e1d7a4978ed554f095430b89ecc23f42014a50ac385eb0c4d163ce213c325", - "sha256:a58d1ed49a94d4183483a3ce0af22f20318d4a1434acee255d683ad90bf78129", - "sha256:a61d0b2c7c9a0ae45732a77844917b427ff16ad5464b4d4f5e4adb955f582890", - "sha256:a714bf6e5e81b0e570d01f56e0c89c6375101b8463999ead3a93a5d2a4af91fa", - "sha256:a7b74e92a3b212390bdce1d93da9f6488c3878c1d434c5e751cbc202c5e09500", - "sha256:a8bd2f19e312ce3e1d2c635618e8a8d8132892bb746a7cf74780a489f0f6cdcb", - "sha256:b0be9965f93c222fb9b4cc254235b3b2b215796c03ef5ee64f995b1b69af0762", - "sha256:b24bf3cd93d5b6ecfbedec73b15f143596c88ee249fa98cefa9a9dc9d92c6f28", - "sha256:b5ffe453cde61f73fea9430223c81d29e2fbf412a6073951102146c84e19e34c", - "sha256:bc120d1132cff853ff617754196d0ac0ae63befe7c8498bd67731ba368abe451", - "sha256:bd035756830c712b64725a76327ce80e82ed12ebab361d3a1cdc0f51ea21acb0", - "sha256:bffcf57826d77a4151962bf1701374e0fc87f536e56ec46f1abdd6a903354042", - "sha256:c2013ee878c76269c7b557a9a9c042335d732e89d482606990b70a839635feb7", - "sha256:c4feb9211d15d9160bc85fa72fed46432cdc143eb9cf6d5ca377335a921ac37b", - "sha256:c8980cde3bb8575e7c956a530f2c217c1d6aac453474bf3ea0f9c89868b531b6", - "sha256:c98f126c4fc697b84c423e387337d5b07e4a61e9feac494362a59fd7a2d9ed80", - "sha256:ccc6f3ddef93243538be76f8e47045b4aad7a66a212cd3a0f23e34469473d36b", - "sha256:ccfa689b9246c48947d31dd9d8b16d89a0ecc8e0e26ea5253068efb6c542b76e", - "sha256:cda776f1967cb304816173b30994faaf2fd5bcb37e73118a47964a02c348e1bc", - "sha256:ce4c8e485a3c59593f1a6f683cf0ea5ab1c1dc94d11eea5619e4fb5228b40fbd", - "sha256:d3c10228d6cf6fe2b63d2e7985e94f6916fa46940df46b70449e9ff9297bd3d1", - "sha256:d4ca54b9cf9d80b4016a67a0193ebe0bcf29f6b0a96f09db942087e294d3d4c2", - "sha256:d4cb2b3ddc16710548801c6fcc0cfcdeeff9dafbc983f77265877793f2660309", - "sha256:d50e4864498a9ab639d6d8854b25e80642bd362ff104312d9770b05d66e5fb13", - "sha256:d74ec9bc0e2feb81d3f16946b005748119c0f52a153f6db6a29e8cd68636f295", - "sha256:d8222acdb51a22929c3b2ddb236b69c59c72af4019d2cba961e2f9add9b6e634", - "sha256:db58483f71c5db67d643857404da360dce3573031586034b7d59f245144cc192", - "sha256:dc3c1ff0abc91444cd20ec643d0f805df9a3661fcacf9c95000329f3ddf268a4", - "sha256:dd326a81afe332ede08eb39ab75b301d5676802cdffd3a8f287a5f0b694dc3f5", - "sha256:dec21e02e6cc932538b5203d3a8bd6aa1480c98c4914cb88eea064ecdbc6396a", - "sha256:e1dafef8df605fdb46edcc0bf1573dea0d6d7b01ba87f85cd04dc855b2b4479e", - "sha256:e2f6a2347d3440ae789505693a02836383426249d5293541cd712e07e7aecf54", - "sha256:e37caa8cdb3b7cf24786451a0bdb853f6347b8b92005eeb64225ae1db54d1c2b", - "sha256:e43a005671a9ed5a650f3bc39e4dbccd6d4326b24fb5ea8be5f3a43a6f576c72", - "sha256:e5e2f7280d8d0d3ef06f3ec1b4fd598d386cc6f0721e54f09109a8132182fbfe", - "sha256:e87798852ae0b37c88babb7f7bbbb3e3fecc562a1c340195b44c7e24d403e380", - "sha256:ee86d81551ec68a5c25373c5643d343150cc54672b5e9a0cafc93c1870a53954", - "sha256:f251bf23deb8332823aef1da169d5d89fa84c89f67bdfb566c49dea1fccfd50d", - "sha256:f3d86373ff19ca0441ebeb696ef64cb58b8b5cbacffcda5a0ec2f3911732a194", - "sha256:f4ad628b5174d5315761b67f212774a32f5bad5e61396d38108bd801c0a8f5d9", - "sha256:f70316f760174ca04492b5ab01be631a8ae30cadab1d1081035136ba12738cfa", - "sha256:f73ce1512e04fbe2bc97836e89830d6b4314c171587a99688082d090f934d20a", - "sha256:ff7c23ba0a88cb7b104281a99476cccadf29de2a0ef5ce864959a52675b1ca83" - ], - "markers": "python_version >= '3.9'", - "version": "==0.25.1" - }, - "send2trash": { - "hashes": [ - "sha256:0c31227e0bd08961c7665474a3d1ef7193929fedda4233843689baa056be46c9", - "sha256:b18e7a3966d99871aefeb00cfbcfdced55ce4871194810fc71f4aa484b953abf" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4, 3.5'", - "version": "==1.8.3" - }, - "setuptools": { - "hashes": [ - "sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922", - "sha256:f36b47402ecde768dbfafc46e8e4207b4360c654f1f3bb84475f0a28628fb19c" - ], - "markers": "python_version >= '3.9'", - "version": "==80.9.0" - }, - "six": { - "hashes": [ - "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", - "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", - "version": "==1.17.0" - }, - "sniffio": { - "hashes": [ - "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", - "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc" - ], - "markers": "python_version >= '3.7'", - "version": "==1.3.1" - }, - "soupsieve": { - "hashes": [ - "sha256:6e60cc5c1ffaf1cebcc12e8188320b72071e922c2e897f737cadce79ad5d30c4", - "sha256:ad282f9b6926286d2ead4750552c8a6142bc4c783fd66b0293547c8fe6ae126a" - ], - "markers": "python_version >= '3.8'", - "version": "==2.7" - }, - "stack-data": { - "hashes": [ - "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9", - "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695" - ], - "version": "==0.6.3" - }, - "stdlib-list": { - "hashes": [ - "sha256:9029ea5e3dfde8cd4294cfd4d1797be56a67fc4693c606181730148c3fd1da29", - "sha256:95ebd1d73da9333bba03ccc097f5bac05e3aa03e6822a0c0290f87e1047f1857" - ], - "markers": "python_version >= '3.9'", - "version": "==0.11.1" - }, - "terminado": { - "hashes": [ - "sha256:a4468e1b37bb318f8a86514f65814e1afc977cf29b3992a4500d9dd305dcceb0", - "sha256:de09f2c4b85de4765f7714688fff57d3e75bad1f909b589fde880460c753fd2e" - ], - "markers": "python_version >= '3.8'", - "version": "==0.18.1" - }, - "tinycss2": { - "hashes": [ - "sha256:10c0972f6fc0fbee87c3edb76549357415e94548c1ae10ebccdea16fb404a9b7", - "sha256:3a49cf47b7675da0b15d0c6e1df8df4ebd96e9394bb905a5775adb0d884c5289" - ], - "markers": "python_version >= '3.8'", - "version": "==1.4.0" - }, - "tomlkit": { - "hashes": [ - "sha256:430cf247ee57df2b94ee3fbe588e71d362a941ebb545dec29b53961d61add2a1", - "sha256:c89c649d79ee40629a9fda55f8ace8c6a1b42deb912b2a8fd8d942ddadb606b0" - ], - "markers": "python_version >= '3.8'", - "version": "==0.13.3" - }, - "tornado": { - "hashes": [ - "sha256:02420a0eb7bf617257b9935e2b754d1b63897525d8a289c9d65690d580b4dcf7", - "sha256:13ce6e3396c24e2808774741331638ee6c2f50b114b97a55c5b442df65fd9692", - "sha256:253b76040ee3bab8bcf7ba9feb136436a3787208717a1fb9f2c16b744fba7331", - "sha256:308473f4cc5a76227157cdf904de33ac268af770b2c5f05ca6c1161d82fdd95e", - "sha256:5cae6145f4cdf5ab24744526cc0f55a17d76f02c98f4cff9daa08ae9a217448a", - "sha256:84ceece391e8eb9b2b95578db65e920d2a61070260594819589609ba9bc6308c", - "sha256:908e7d64567cecd4c2b458075589a775063453aeb1d2a1853eedb806922f568b", - "sha256:9e9ca370f717997cb85606d074b0e5b247282cf5e2e1611568b8821afe0342d6", - "sha256:b77e9dfa7ed69754a54c89d82ef746398be82f749df69c4d3abe75c4d1ff4888", - "sha256:caec6314ce8a81cf69bd89909f4b633b9f523834dc1a352021775d45e51d9401", - "sha256:d50065ba7fd11d3bd41bcad0825227cc9a95154bad83239357094c36708001f7", - "sha256:e0a36e1bc684dca10b1aa75a31df8bdfed656831489bc1e6a6ebed05dc1ec365" - ], - "markers": "python_version >= '3.9'", - "version": "==6.5.1" - }, - "traitlets": { - "hashes": [ - "sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7", - "sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f" - ], - "markers": "python_version >= '3.8'", - "version": "==5.14.3" - }, - "types-python-dateutil": { - "hashes": [ - "sha256:13e80d6c9c47df23ad773d54b2826bd52dbbb41be87c3f339381c1700ad21ee5", - "sha256:2b2b3f57f9c6a61fba26a9c0ffb9ea5681c9b83e69cd897c6b5f668d9c0cab93" - ], - "markers": "python_version >= '3.9'", - "version": "==2.9.0.20250516" - }, - "typing-extensions": { - "hashes": [ - "sha256:8676b788e32f02ab42d9e7c61324048ae4c6d844a399eebace3d4979d75ceef4", - "sha256:a1514509136dd0b477638fc68d6a91497af5076466ad0fa6c338e44e359944af" - ], - "markers": "python_version >= '3.9'", - "version": "==4.14.0" - }, - "uri-template": { - "hashes": [ - "sha256:0e00f8eb65e18c7de20d595a14336e9f337ead580c70934141624b6d1ffdacc7", - "sha256:a44a133ea12d44a0c0f06d7d42a52d71282e77e2f937d8abd5655b8d56fc1363" - ], - "markers": "python_version >= '3.7'", - "version": "==1.3.0" - }, - "urllib3": { - "hashes": [ - "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760", - "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc" - ], - "markers": "python_version >= '3.9'", - "version": "==2.5.0" - }, - "wcwidth": { - "hashes": [ - "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859", - "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5" - ], - "version": "==0.2.13" - }, - "webcolors": { - "hashes": [ - "sha256:515291393b4cdf0eb19c155749a096f779f7d909f7cceea072791cb9095b92e9", - "sha256:ecb3d768f32202af770477b8b65f318fa4f566c22948673a977b00d589dd80f6" - ], - "markers": "python_version >= '3.9'", - "version": "==24.11.1" - }, - "webencodings": { - "hashes": [ - "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78", - "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923" - ], - "version": "==0.5.1" - }, - "websocket-client": { - "hashes": [ - "sha256:17b44cc997f5c498e809b22cdf2d9c7a9e71c02c8cc2b6c56e7c2d1239bfa526", - "sha256:3239df9f44da632f96012472805d40a23281a991027ce11d2f45a6f24ac4c3da" - ], - "markers": "python_version >= '3.8'", - "version": "==1.8.0" - } - } -} diff --git a/README.md b/README.md index 385b7ff..b0a1ca4 100644 --- a/README.md +++ b/README.md @@ -1,80 +1,143 @@ # pyetm -This package provides a set of tools for interaction with the Energy Transition Model's API. Learn more -about the Energy Transition Model [here](https://energytransitionmodel.com/). The -package is designed to be a modular tool that advanced users can incorporate into their workflows. The -complete documentation is available [via the ETM documentation page](https://docs.energytransitionmodel.com/main/pyetm/introduction). +This package provides a set of tools for interaction with the Energy Transition Model's API. +Learn more about the Energy Transition Model [here](https://energytransitionmodel.com/). + +The package is designed to be a modular tool that advanced users can incorporate into their scenario workflows. +The complete documentation is available [via the ETM documentation page](https://docs.energytransitionmodel.com/main/pyetm/introduction). + +--- ## Installation -You can clone the pyetm from [our Github](https://github.com/quintel/pyetm). The package is also -available via pip like any other python package - install it and use it in your project! -``` +You can install **pyetm** directly from PyPI: +```bash pip install pyetm ``` -## Just running the Jupyter Notebooks - or a beginner friendly guide to PyETM -If you are not planning on developing the tool, but would like to open and run our Jupyter notebooks -in VS Code, follow the beginner friendly guide at [Running notebooks](running_notebooks.md). +Or clone from [our GitHub repository](https://github.com/quintel/pyetm) if you want the latest development version: +```bash +git clone https://github.com/quintel/pyetm.git +cd pyetm +``` -## Getting started -Make sure you have [Python 3](https://www.python.org/downloads/) installed. Then, install all required -libraries by opening a terminal/command-prompt window in the `pyetm` folder (or navigate to this folder -in the terminal using `cd "path/to/scenario-tools-folder"`). All following examples of running the tool -expect you to be in this folder. +--- -#### Using pipenv -It is recommended (but not required) that you use [`pipenv`](https://pipenv.pypa.io/en/latest/) for -running these tools. When using `pipenv` it will create a virtual environment for you. A virtual -environment helps with keeping the libraries you install here separate of your global libraries (in -other words your `pyetm` will be in a stable and isolated environment and are thus less -likely to break when updating things elsewhere on your computer). +## Running Jupyter Notebooks (Beginner Friendly) -You can install `pipenv` with `pip` or `pip3` if you don't have it installed yet. -``` -pip3 install pipenv -``` +If you only want to open and run our Jupyter notebooks in VS Code without developing the package, +follow the beginner guide here: [Running notebooks](running_notebooks.md). -Then you can create a new environment and install all the libraries in one go by running: -``` -pipenv install -``` +--- -If you plan to develop with the tool, install the dev dependencies too: -``` -pipenv install --dev +## Development Setup (Using Poetry) + +We recommend using [Poetry](https://python-poetry.org/) to manage dependencies and virtual environments. +Poetry ensures all dependencies are installed in an isolated environment, keeping your system clean. + +### Python +Make sure you have **Python 3.12** or later installed: +- **Windows**: [Download from python.org](https://www.python.org/downloads/windows/) +- **macOS**: Install via [Homebrew](https://brew.sh/) + ```bash + brew install python@3.12 + ``` +- **Linux**: Use your package manager or install from source. + +Check your version: +```bash +python3 --version ``` -#### Configuring your settings +--- -You can set your API token and the base url for your requests (depending which -[environment](https://docs.energytransitionmodel.com/api/intro#environments) you want to interact with) -either directly in the ENV or via a config.yml file. +### Poetry +Follow the [official instructions](https://python-poetry.org/docs/#installation): -##### config.yml -pyetm uses a `config.yml` file in the project root to store your personal settings: +```bash +curl -sSL https://install.python-poetry.org | python3 - +``` -1. Duplicate the example file provided (`examples/config.example.yml`) and rename it to `config.yml`. -2. Open `config.yml` and fill in your values: - - **etm_api_token**: Your personal ETM API token (overridden by the `$ETM_API_TOKEN` environment variable if set). - - **base_url**: The API base URL for the target environment (overridden by the `$BASE_URL` environment - variable if set) e.g., default pro, a stable engine at `https://2025-01.engine.energytransitionmodel.com/api/v3`, - or beta at `https://beta.engine.energytransitionmodel.com/api/v3`. - - **local_engine_url** and **local_model_url**: URLs for a local ETM instance, if running locally. - - **proxy_servers**: (Optional) HTTP/HTTPS proxy URLs, if required by your network. - - **csv_separator** and **decimal_separator**: Defaults are `,` and `.`; adjust if your CSV exports - use different separators. +After installation, ensure Poetry is available: +```bash +poetry --version +``` -Your `config.yml` should reside in the root `pyetm/` folder. -##### ENV variables -If you use pyetm as a package, you may want to set your ENV variables using a custom flow. In that -case, the variables you need to set are: +#### Install Dependencies - $ETM_API_TOKEN - Your api token (specific to the environment you are interacting with) - $BASE_URL - The base url of the environment you are interacting with. - $LOCAL_ENGINE_URL - The local url of the engine if running locally. - $LOCAL_MODEL_URL - The local url of the model if running locally. +Navigate to the `pyetm` folder and install all dependencies: +```bash +cd pyetm +poetry install +``` +This will: +- Create a virtual environment +- Install runtime dependencies +If you want development dependencies (testing, linting, etc.) then append the +"--with dev" flag to the install command. + + +#### Activating the Environment +You can either: +- Run commands inside Poetry’s environment: + ```bash + poetry run pytest + poetry run pyetm + ``` +- Or activate the shell: + ```bash + eval $(poetry env activate) + ``` + Then run commands normally: + ```bash + pytest + pyetm + ``` + + +## Configuring Your Settings + +You can configure your API token and base URL either with a **config.yml** file or environment variables. You can now simply set an `environment` and the base URL will be inferred for you. + +### Option 1: `config.yml` +1. Duplicate the example file (`examples/example.config.yml`) and rename it to `config.yml`. +2. Edit `config.yml`: + - **etm_api_token**: Your ETM API token (overridden by `$ETM_API_TOKEN` if set). + - **environment**: pro (default), beta, local, or a stable tag like `2025-01`. When set, `base_url` is inferred automatically. + - (optional) **base_url**: API base URL (overridden by `$BASE_URL` if set). If both `environment` and `base_url` are set, `base_url` wins. + Examples if you need a direct override: + - `https://engine.energytransitionmodel.com/api/v3` (pro) + - `https://beta.engine.energytransitionmodel.com/api/v3` (beta) + - `https://2025-01.engine.energytransitionmodel.com/api/v3` (stable tag) + - **proxy_servers**: (Optional) HTTP/HTTPS proxy URLs. + - **csv_separator** and **decimal_separator**: Defaults are `,` and `.`. + +Place `config.yml` in the project root (`pyetm/` folder). + +### Option 2: Environment Variables +If you prefer, set these environment variables: +```bash +ETM_API_TOKEN= +ENVIRONMENT= +# or provide a direct override instead of ENVIRONMENT +BASE_URL= +``` -#TODO - check links +--- + +## Cross-Platform Notes +- **Windows**: + - Use `py` instead of `python3` if `python3` is not recognized. + - In PowerShell, set environment variables with: + ```powershell + $env:ETM_API_TOKEN="your-token" + ``` +- **macOS/Linux**: + - Use `python3` in commands. + - Set environment variables with: + ```bash + export ETM_API_TOKEN="your-token" + export ENVIRONMENT=beta # or pro/local/2025-01 + ``` diff --git a/examples/.gitkeep b/examples/.gitkeep deleted file mode 100644 index e69de29..0000000 diff --git a/examples/advanced_examples/advanced_scenario_example.ipynb b/examples/advanced_examples/advanced_scenario_example.ipynb deleted file mode 100644 index e9baefc..0000000 --- a/examples/advanced_examples/advanced_scenario_example.ipynb +++ /dev/null @@ -1,689 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "ddbe7ab2", - "metadata": {}, - "source": [ - "# Advanced Scenario Examples\n", - "\n", - "This notebook demonstrates how to use the `Scenario` object within the pyetm package to retrieve and \n", - "inspect data from an ETM scenario. These examples are slightly more advanced, including analytics and\n", - "data operations on the scenario object and its sub-models.\n", - "\n", - "Make sure you have a valid `ETM_API_TOKEN` set in your environment.\n", - "\n", - "## Structure\n", - "\n", - "This notebook is organized into two main sections:\n", - "1. **Setup & Initialization** - Run these cells first to set up your environment and load a scenario\n", - "2. **Exploration Examples** - After setup is complete, these cells can be run in any order to explore different aspects of scenario data" - ] - }, - { - "cell_type": "markdown", - "id": "setup_header", - "metadata": {}, - "source": [ - "## Setup & Initialization\n", - "\n", - "**Run these cells first!** The following cells set up your environment and load a scenario. Complete this section before exploring the examples below." - ] - }, - { - "cell_type": "markdown", - "id": "5ba2f542", - "metadata": {}, - "source": [ - "##### Environment Setup" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "dfa34991", - "metadata": {}, - "outputs": [], - "source": [ - "from example_helpers import setup_notebook\n", - "from pyetm.models import Scenario\n", - "\n", - "setup_notebook()" - ] - }, - { - "cell_type": "markdown", - "id": "f579be0a", - "metadata": {}, - "source": [ - "##### Load a scenario\n", - "\n", - "This cell connects to a specific scenario using its session ID and loads all its data.\n", - "\n", - "The scenario object will contain inputs, outputs, custom curves, and other configuration data." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6a514b5d", - "metadata": {}, - "outputs": [], - "source": [ - "# Connect to your scenario by supplying the session ID\n", - "scenario = Scenario.load(2690288)\n", - "\n", - "print(f\" Scenario {scenario.id} loaded successfully\")\n", - "print(f\" Total inputs: {len(scenario.inputs)}\")\n", - "print(f\" User-modified inputs: {len(scenario.user_values())}\")\n", - "print(\"\\n Setup complete! You can now run any of the exploration examples below in any order.\")" - ] - }, - { - "cell_type": "markdown", - "id": "exploration_header", - "metadata": {}, - "source": [ - "## Exploration Examples\n", - "\n", - "**The cells below can be run in any order** after completing the setup section above. Each cell demonstrates different ways to explore and analyze scenario data using the pyetm package to connect to the Energy Transition Model's API." - ] - }, - { - "cell_type": "markdown", - "id": "basic_properties_section", - "metadata": {}, - "source": [ - "### Basic Scenario Properties" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "basic_properties", - "metadata": {}, - "outputs": [], - "source": [ - "# Display basic scenario properties\n", - "# These properties define the fundamental characteristics of the scenario\n", - "\n", - "print(f\"Scenario ID: {scenario.id}\")\n", - "print(f\"Area Code: {scenario.area_code}\")\n", - "print(f\"End Year: {scenario.end_year}\")\n", - "print(f\"Start Year: {scenario.start_year}\")\n", - "print(f\"Created: {scenario.created_at}\")\n", - "print(f\"Updated: {scenario.updated_at}\")\n", - "print(f\"Private: {scenario.private}\")\n", - "print(f\"Template: {scenario.template}\")\n", - "print(f\"Source: {scenario.source}\")\n", - "print(f\"URL: {scenario.url}\")\n", - "print(f\"Keep Compatible: {scenario.keep_compatible}\")\n", - "print(f\"Scaling: {scenario.scaling}\")\n", - "print(f\"Version: {scenario.version}\")\n", - "\n", - "# Show metadata if available\n", - "if scenario.metadata:\n", - " print(\"\\nMetadata:\")\n", - " print(scenario.metadata)\n", - "else:\n", - " print(\"\\nNo additional metadata available\")" - ] - }, - { - "cell_type": "markdown", - "id": "7418c5e1", - "metadata": {}, - "source": [ - "### Complete Scenario Metadata Export\n", - "\n", - "The `model_dump()` method provides a complete export of all scenario metadata in a structured format. This includes all properties and their current values." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "972bd7c5", - "metadata": {}, - "outputs": [], - "source": [ - "# Export complete scenario metadata\n", - "# model_dump() returns a comprehensive dictionary containing all scenario metadata\n", - "\n", - "full_data = scenario.model_dump()\n", - "print(f\"Complete scenario metadata ({len(full_data)} fields):\")\n", - "print(\"\\n\" + \"-\"*70)\n", - "print(full_data)" - ] - }, - { - "cell_type": "markdown", - "id": "user_values_section", - "metadata": {}, - "source": [ - "### Exploring User-Modified Values\n", - "\n", - "The `user_values()` method returns a dictionary of all inputs that have been modified from their default values." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "user_values_example", - "metadata": {}, - "outputs": [], - "source": [ - "# Display all user-modified input values\n", - "# This shows only the inputs that have been changed from their default values\n", - "# The format is {input_key: user_value}\n", - "\n", - "user_values = scenario.user_values()\n", - "print(f\"Found {len(user_values)} user-modified inputs:\")\n", - "print(\"\\n\" + \"-\"*70)\n", - "print(user_values)" - ] - }, - { - "cell_type": "markdown", - "id": "input_analysis_section", - "metadata": {}, - "source": [ - "### Analyzing Input Properties\n", - "\n", - "Each input in a scenario has various properties that define its behavior:\n", - "- `key`: Unique identifier for the input\n", - "- `unit`: The unit of measurement (e.g., 'MW', '%', 'PJ')\n", - "- `disabled`: Whether the input is currently disabled\n", - "- `user`: The value set by the user (if any)\n", - "- `default`: The default value for this input\n", - "\n", - "Additional properties for specific input types:\n", - "- **Float inputs**: `min` and `max` values defining valid ranges\n", - "- **Enumerable inputs**: `permitted_values` showing available options" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "input_collection_overview", - "metadata": {}, - "outputs": [], - "source": [ - "# Overview of the input collection\n", - "# The inputs property provides access to all scenario inputs through an InputCollection\n", - "\n", - "print(f\"Input Collection Overview:\")\n", - "print(f\" Total inputs: {len(scenario.inputs)}\")\n", - "print(f\" Input collection type: {type(scenario.inputs)}\")\n", - "print(f\" User-modified inputs: {len([inp for inp in scenario.inputs if inp.user is not None])}\")\n", - "print(f\" Disabled inputs: {len([inp for inp in scenario.inputs if inp.disabled])}\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6c4825ba", - "metadata": {}, - "outputs": [], - "source": [ - "# Analyze units used across all inputs\n", - "# This gives you an overview of what types of measurements are used in the scenario\n", - "\n", - "# Count inputs by unit type\n", - "unit_counts = {}\n", - "for input in scenario.inputs:\n", - " unit = input.unit or 'No unit'\n", - " unit_counts[unit] = unit_counts.get(unit, 0) + 1\n", - "\n", - "total_inputs = len(scenario.inputs)\n", - "print(f\"Found {len(unit_counts)} different units used across {total_inputs:,} inputs:\")\n", - "print(\"\\n\" + \"-\"*70)\n", - "\n", - "# Sort by count (most common first) and show percentages\n", - "sorted_units = sorted(unit_counts.items(), key=lambda x: x[1], reverse=True)\n", - "for unit, count in sorted_units:\n", - " percentage = (count / total_inputs) * 100\n", - " print(f\"{unit:15}: {count:4,} inputs ({percentage:5.1f}%)\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "38fd7d1c", - "metadata": {}, - "outputs": [], - "source": [ - "# Identify disabled inputs\n", - "# Disabled inputs are those that do not impact the scenario because of a coupling,\n", - "# or if you are not the owner/editor of the scenario\n", - "\n", - "disabled_inputs = [input.key for input in scenario.inputs if input.disabled]\n", - "print(f\"Found {len(disabled_inputs)} disabled inputs:\")\n", - "print(\"\\n\" + \"-\"*70)\n", - "print(disabled_inputs)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f44d29ef", - "metadata": {}, - "outputs": [], - "source": [ - "# Display default values for all inputs\n", - "# Default values represent the baseline scenario before user modifications\n", - "\n", - "default_values = { input.key: input.default for input in scenario.inputs }\n", - "print(f\"Default values for {len(default_values)} inputs:\")\n", - "print(\"\\n\" + \"-\"*70)\n", - "print(default_values)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "d980ed9b", - "metadata": {}, - "outputs": [], - "source": [ - "# Explore Float input constraints\n", - "# Float inputs have minimum and maximum values that define valid ranges\n", - "# This information helps to understand input range-limitations and validation rules\n", - "\n", - "from pyetm.models.inputs import FloatInput\n", - "\n", - "float_inputs = [input for input in scenario.inputs if isinstance(input, FloatInput)]\n", - "print(f\"Found {len(float_inputs)} float inputs:\")\n", - "print(\"\\n\" + \"-\"*70)\n", - "\n", - "float_details = [input.model_dump() for input in float_inputs]\n", - "print(float_details)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "enumerable_inputs", - "metadata": {}, - "outputs": [], - "source": [ - "# Explore Enumerable input options\n", - "# Some inputs have a limited set of permitted values (like dropdown selections)\n", - "# This is useful for understanding available choices for categorical inputs\n", - "\n", - "from pyetm.models.inputs import EnumInput\n", - "\n", - "enum_inputs = [input for input in scenario.inputs if isinstance(input, EnumInput)]\n", - "print(f\"Found {len(enum_inputs)} enumerable inputs:\")\n", - "print(\"\\n\" + \"-\"*70)\n", - "\n", - "enum_details = [input.model_dump() for input in enum_inputs]\n", - "print(enum_details)" - ] - }, - { - "cell_type": "markdown", - "id": "curves_section", - "metadata": {}, - "source": [ - "### Working with Custom Curves\n", - "\n", - "Custom curves represent time-series data that can be attached to specific inputs. These are typically used for:\n", - "- Load profiles (electricity demand over time)\n", - "- Production profiles (renewable energy output patterns)\n", - "- Availability curves (when technologies are available)\n", - "- Price curves (energy prices over time)\n", - "\n", - "The curves contain hourly data points for an entire year (8760 hours)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "custom_curves_overview", - "metadata": {}, - "outputs": [], - "source": [ - "# Overview of custom curves collection\n", - "# Custom curves are hourly time-series data used to define dynamic behaviour across a year\n", - "\n", - "print(f\"Custom Curves Collection Overview:\")\n", - "print(f\" Collection type: {type(scenario.custom_curves)}\")\n", - "\n", - "# Show attached custom curves\n", - "attached_curves = list(scenario.custom_curves.attached_keys())\n", - "print(f\"\\nAttached custom curves ({len(attached_curves)}):\")\n", - "for i, curve_key in enumerate(attached_curves[:10]):\n", - " print(f\" {i+1}. {curve_key}\")\n", - "if len(attached_curves) > 10:\n", - " print(f\" ... and {len(attached_curves) - 10} more\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f18f67df", - "metadata": {}, - "outputs": [], - "source": [ - "# Example: Display data from a specific curve\n", - "# This shows how to access the actual time-series data from a custom curve\n", - "# The custom_curve_series() method returns the hourly values for the specified curve\n", - "# The curve is stored as a pandas Series\n", - "\n", - "curve_key = 'interconnector_1_import_availability'\n", - "if curve_key in scenario.custom_curves.attached_keys():\n", - " curve_data = scenario.custom_curve_series(curve_key)\n", - " print(f\"Curve data for '{curve_key}':\")\n", - " print(f\" Data points: {len(curve_data)}\")\n", - " print(f\" First 10 values: {curve_data.head(10).tolist()}\")\n", - " print(f\" Data type: {type(curve_data)}\")\n", - " print(f\" Min value: {curve_data.min()}\")\n", - " print(f\" Max value: {curve_data.max()}\")\n", - " print(f\" Mean value: {curve_data.mean():.4f}\")\n", - "else:\n", - " print(f\"Curve '{curve_key}' not found in this scenario.\")\n", - " print(\"Available curves:\", list(scenario.custom_curves.attached_keys()))" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "all_custom_curves_analysis", - "metadata": {}, - "outputs": [], - "source": [ - "# Analyze all custom curves in the scenario\n", - "# This iterates through max 5 attached curves and provides summary statistics\n", - "\n", - "print(\"Analysis of all custom curves in the scenario:\")\n", - "print(\"\\n\" + \"-\"*70)\n", - "\n", - "curve_count = 0\n", - "for curve_series in scenario.custom_curves_series():\n", - " curve_count += 1\n", - " print(f\"\\nCurve {curve_count}:\")\n", - " print(f\" Length: {len(curve_series)}\")\n", - " print(f\" Min: {curve_series.min():.4f}\")\n", - " print(f\" Max: {curve_series.max():.4f}\")\n", - " print(f\" Mean: {curve_series.mean():.4f}\")\n", - " print(f\" Standard deviation: {curve_series.std():.4f}\")\n", - "\n", - " # Stop after first 5 to avoid overwhelming output\n", - " if curve_count >= 5:\n", - " total_curves = len(list(scenario.custom_curves.attached_keys()))\n", - " if total_curves > 5:\n", - " print(f\"\\n... {total_curves - 5} more curves\")\n", - " break\n", - "\n", - "if curve_count == 0:\n", - " print(\"No custom curves found in this scenario.\")" - ] - }, - { - "cell_type": "markdown", - "id": "output_curves_section", - "metadata": {}, - "source": [ - "### Working with Output Curves\n", - "\n", - "Output curves represent time-series data for energy carriers (electricity, heat, gas, etc.) within the energy system. \n", - "\n", - "Each output curve represents an export from your scenario, so they are actually sets of curves, stored as a dataframe where each column is a curve and the index is a time series for each hour." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "output_curves_overview", - "metadata": {}, - "outputs": [], - "source": [ - "# Overview of output curves collection\n", - "# Output curves represent energy flows and storage for different energy carriers\n", - "\n", - "print(f\"Output Curves Collection Overview:\")\n", - "print(f\" Collection type: {type(scenario.output_curves)}\")\n", - "\n", - "# Show first 10 available output curve types\n", - "attached_output_curves = list(scenario.output_curves.attached_keys())\n", - "print(f\"\\nAttached output curves ({len(attached_output_curves)}):\")\n", - "for i, curve_key in enumerate(attached_output_curves[:10]):\n", - " print(f\" {i+1}. {curve_key}\")\n", - "if len(attached_output_curves) > 10:\n", - " print(f\" ... {len(attached_output_curves) - 10} more\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "all_output_curves_analysis", - "metadata": {}, - "outputs": [], - "source": [ - "# Analyze all output curves in the scenario\n", - "# This provides a comprehensive overview of output curve behaviour and format\n", - "\n", - "print(\"Analysis of all output curves in the scenario:\")\n", - "print(\"\\n\" + \"-\"*70)\n", - "\n", - "curve_count = 0\n", - "attached_curve_keys = list(scenario.output_curves.attached_keys())\n", - "for curve_data in scenario.all_output_curves():\n", - " curve_name = attached_curve_keys[curve_count] if curve_count < len(attached_curve_keys) else f\"Unknown Curve {curve_count + 1}\"\n", - " curve_count += 1\n", - " print(f\"\\n{curve_name}:\")\n", - "\n", - " if curve_data is not None and not curve_data.empty:\n", - " print(f\" Shape (rows × columns): {curve_data.shape}\")\n", - " print(f\" Columns: {list(curve_data.columns)}\")\n", - "\n", - " # For DataFrames, show summary stats differently\n", - " numeric_cols = curve_data.select_dtypes(include=[float, int]).columns\n", - " if len(numeric_cols) > 0:\n", - " print(f\" Summary for numeric columns:\")\n", - " for col in numeric_cols[:3]: # Show first 3 columns to avoid clutter\n", - " col_data = curve_data[col]\n", - " print(f\" {col}:\")\n", - " print(f\" Min: {float(col_data.min()):.4f}\")\n", - " print(f\" Max: {float(col_data.max()):.4f}\")\n", - " print(f\" Mean: {float(col_data.mean()):.4f}\")\n", - " print(f\" Std: {float(col_data.std()):.4f}\")\n", - " if len(numeric_cols) > 3:\n", - " print(f\" ... and {len(numeric_cols) - 3} more columns\")\n", - " else:\n", - " print(f\" No numeric data available\")\n", - " else:\n", - " print(f\" No data available\")\n", - "\n", - " # Stop after first 5 to avoid overwhelming output\n", - " if curve_count >= 5:\n", - " total_curves = len(attached_curve_keys)\n", - " if total_curves > 5:\n", - " print(f\"\\n... and {total_curves - 5} more output curve exports\")\n", - " break\n", - "\n", - "if curve_count == 0:\n", - " print(\"No output curves found in this scenario.\")" - ] - }, - { - "cell_type": "markdown", - "id": "sortables_section", - "metadata": {}, - "source": [ - "### Exploring Sortables\n", - "\n", - "Sortables represent ordered lists of technologies or components within the energy system. They define priority orders for:\n", - "- Merit order\n", - "- Forecast order\n", - "- Heat network order\n", - "- Hydrogen supply/demand\n", - "\n", - "The order of items in sortables affects how the energy system model calculates results." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "sortables_overview", - "metadata": {}, - "outputs": [], - "source": [ - "# Overview of sortables collection\n", - "# Sortables define ordering and priority for various energy system components\n", - "\n", - "print(f\"Sortables Overview:\")\n", - "print(f\" Data type: {type(scenario.sortables)}\")\n", - "\n", - "# Show all sortables\n", - "sortable_keys = list(scenario.sortables.as_dict().keys())\n", - "print(f\"\\nSortables ({len(sortable_keys)}):\")\n", - "for i, sortable_key in enumerate(sortable_keys):\n", - " print(f\" {i+1}. {sortable_key}\")" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "4c90688f", - "metadata": {}, - "outputs": [], - "source": [ - "# Display sortable configurations\n", - "# Sortables define the order/priority of different technologies in the energy system\n", - "# For example, merit order determines which power plants are dispatched first\n", - "# The order directly affects energy system calculations and results\n", - "\n", - "sortables_data = scenario.sortables.as_dict()\n", - "print(f\"Found {len(sortables_data)} sortable orders:\")\n", - "print(\"\\n\" + \"-\"*70)\n", - "print(sortables_data)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "sortables_detailed_analysis", - "metadata": {}, - "outputs": [], - "source": [ - "# Analysis of each sortable category\n", - "# This examines the structure and content of each sortable configuration\n", - "\n", - "sortables_data = scenario.sortables.as_dict()\n", - "print(\"Detailed analysis of sortables:\")\n", - "print(\"\\n\" + \"-\"*70)\n", - "\n", - "for category, sortables in sortables_data.items():\n", - " print(f\"\\n{category.upper()}:\")\n", - "\n", - " if sortables:\n", - " print(f\" Number of items: {len(sortables)}\")\n", - " print(f\" Sortables:\")\n", - " for i, order in enumerate(sortables):\n", - " print(f\" {i+1}. {order}\")" - ] - }, - { - "cell_type": "markdown", - "id": "f1f53bd1", - "metadata": {}, - "source": [ - "### Working with Gqueries\n", - "\n", - "Gqueries allow you to extract specific calculated values from the ETM.\n", - "\n", - "You can request multiple queries and execute them together for efficiency." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6942e344", - "metadata": {}, - "outputs": [], - "source": [ - "scenario.add_queries([\n", - " \"dashboard_emissions\",\n", - " \"dashboard_total_costs\",\n", - " \"dashboard_renewability\"\n", - "])\n", - "\n", - "print(f\"Added {len(scenario._queries.query_keys())} queries:\")\n", - "for i, query in enumerate(scenario._queries.query_keys(), 1):\n", - " print(f\" {i}. {query}\")\n", - "\n", - "print(f\"\\nQueries ready: {scenario._queries.is_ready()}\")\n", - "\n", - "print(\"Gqueries Overview:\")\n", - "print(f\" Queries requested: {scenario.queries_requested()}\")\n", - "\n", - "if scenario.queries_requested():\n", - " print(f\" Query keys: {scenario._queries.query_keys()}\")\n", - " print(f\" Queries ready: {scenario._queries.is_ready()}\")\n", - "\n", - " # Get results if available\n", - " results = scenario.results()\n", - " if results is not None and not results.empty:\n", - " print(f\"\\nQuery Results:\")\n", - " print(f\" Results shape: {results.shape}\")\n", - " print(f\" Columns: {list(results.columns)}\")\n", - " print(f\" \")\n", - " print(results.head())\n", - " else:\n", - " print(\"\\nNo query results available\")" - ] - }, - { - "cell_type": "markdown", - "id": "warnings_errors_section", - "metadata": {}, - "source": [ - "### Handling Warnings and Errors\n", - "\n", - "The scenario object can accumulate warnings during data fetching and processing. These warnings provide important information about non-breaking issues with data quality, your API configuration, or service-level issues." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "warnings_analysis", - "metadata": {}, - "outputs": [], - "source": [ - "# Check for warnings and errors in the scenario\n", - "# Warnings can accumulate from API calls, data validation, or processing issues\n", - "\n", - "# Check if the scenario object has any warnings\n", - "if hasattr(scenario, 'warnings') and scenario.warnings:\n", - " print(f\" Total warnings: {len(scenario.warnings)}\")\n", - " print(\"\\nWarnings:\")\n", - " for i, warning in enumerate(scenario.warnings, 1):\n", - " print(f\" {i}. {warning}\")\n", - "else:\n", - " print(f\" No warnings found\")" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "pyetm-qKH2ozgc", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.9" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/examples/create_and_update_a_scenario.ipynb b/examples/create_and_update_a_scenario.ipynb deleted file mode 100644 index 0fa51bd..0000000 --- a/examples/create_and_update_a_scenario.ipynb +++ /dev/null @@ -1,181 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "d9bff682", - "metadata": {}, - "source": [ - "Creating / Updating a scenario flow:\n", - "\n", - "#TODO: Expand descriptions etc, this is just to show the funnctionality" - ] - }, - { - "cell_type": "markdown", - "id": "21347fc1", - "metadata": {}, - "source": [ - "# SETUP" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "3ada4b30", - "metadata": {}, - "outputs": [], - "source": [ - "from example_helpers import setup_notebook\n", - "from pyetm.models import Scenario\n", - "\n", - "setup_notebook()" - ] - }, - { - "cell_type": "markdown", - "id": "84571cab", - "metadata": {}, - "source": [ - "Create a new scenario:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "4770e6a9", - "metadata": {}, - "outputs": [], - "source": [ - "# scenario = Scenario.new(\"nl\", 2050, True)\n", - "\n", - "scenario = Scenario.new(\n", - " area_code=\"nl2019\",\n", - " end_year=2050,\n", - " private=False,\n", - " keep_compatible=False,\n", - " source=\"pyetm\")" - ] - }, - { - "cell_type": "markdown", - "id": "07461117", - "metadata": {}, - "source": [ - "Update inputs for a scenario:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "5a1549ac", - "metadata": {}, - "outputs": [], - "source": [ - "scenario.update_user_values({\n", - " \"co_firing_biocoal_share\": 80.0,\n", - " \"external_coupling_industry_chemical_other_burner_crude_oil_share\": \"hello\"\n", - "})\n" - ] - }, - { - "cell_type": "markdown", - "id": "af9d11bd", - "metadata": {}, - "source": [ - "View the changes (so you know it happened):" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "7fc4dc21", - "metadata": {}, - "outputs": [], - "source": [ - "print(f\"Area: {scenario.area_code}\")\n", - "print(f\"End year: {scenario.end_year}\")\n", - "print(f\"Start year: {scenario.start_year}\")\n", - "print(f\"Version: {scenario.version}\")\n", - "user_vals = scenario.user_values()\n", - "print(f\"Modified inputs: {len(user_vals)}\")\n", - "print(f\"First input: {list(user_vals.keys())[0]} = {list(user_vals.values())[0]}\")\n", - "print(f\"Second input: {list(user_vals.keys())[1]} = {list(user_vals.values())[1]}\")" - ] - }, - { - "cell_type": "markdown", - "id": "4dba3824", - "metadata": {}, - "source": [ - "Update the metadata for the scenario:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "c6a65f6a", - "metadata": {}, - "outputs": [], - "source": [ - "scenario.update_metadata(\n", - " private= True,\n", - " keep_compatible= True,\n", - " source= \"test_change_source\",\n", - " end_year= 2040\n", - ")\n", - "\n", - "# You can also update the metadata attribute\n", - "scenario.update_metadata(\n", - " metadata= {\n", - " \"title\": \"Test scenario!\",\n", - " \"description\": \"Updated scenario description\",\n", - " \"author\": \"Ernie\"\n", - " }\n", - "})\n", - "\n", - "print(scenario.private)" - ] - }, - { - "cell_type": "markdown", - "id": "3cd56ce2", - "metadata": {}, - "source": [ - "You can also remove inputs, which means the default value is then used." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "98ab2f5c", - "metadata": {}, - "outputs": [], - "source": [ - "scenario.remove_user_values([\"co_firing_biocoal_share\"])\n", - "user_vals = scenario.user_values()\n", - "print(f\"Modified inputs: {len(user_vals)}\")" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "pyetm-qKH2ozgc", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.9" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/examples/full_multi_scenario_flow.ipynb b/examples/create_or_query_scenarios.ipynb similarity index 83% rename from examples/full_multi_scenario_flow.ipynb rename to examples/create_or_query_scenarios.ipynb index 4dd758a..a661cee 100644 --- a/examples/full_multi_scenario_flow.ipynb +++ b/examples/create_or_query_scenarios.ipynb @@ -31,9 +31,7 @@ "\n", "In the example, there are two scenarios, with short names scen_a and scen_b. You can use short names in the parameters sheet to specify which inputs belong to which scenario. Because scen_a has no scenario_id, it is being created. It will be created with all the metadata included in the sheet, plus any of the inputs under the column with its short_name and any sortables and curves specified in the sheets named beside the sortables and custom_curves rows. The same goes for scen_b, but because it has a scenario_id (2690555) that scenario will be loaded, and then updated with anything as set in the excel.\n", "\n", - "**TODO**: Figure out how to manage the fact that for this example whatever scenario 2690555 is will be constantly updated etc by everyone who wants to try running the script on pro/beta. At the moment its just a local scenario.\n", - "\n", - "Everything in the ETM is structured via scenarios, and so is pyetm." + "**TODO**: Figure out how to manage the fact that for this example whatever scenario 2690555 is will be constantly updated etc by everyone who wants to try running this script on pro/beta. At the moment its just a local scenario." ] }, { @@ -45,7 +43,8 @@ "source": [ "from pyetm.models.scenarios import Scenarios\n", "\n", - "scenarios = Scenarios.from_excel(\"my_input_excel.xlsx\")" + "scenarios = Scenarios.from_excel(\"example_input_excel.xlsx\")\n", + "#scenario_a = Scenario.load(123456789) #TODO: Also load a scenario" ] }, { @@ -136,7 +135,7 @@ "id": "86643b22", "metadata": {}, "source": [ - "We can directly modify any of the attributes using Pandas, or we can re-export the scenarios to excel and make modifications that way." + "We can directly modify any of the attributes using Pandas, or we can re-export the scenarios to excel and make modifications that way. When exporting to excel, more data will be available than was in the input, because the ETM results will be included by default. The 'output curves' will be stored in a separate excel workbook, separated by carrier type. By default everything is included, but you can also specify what you want." ] }, { @@ -146,7 +145,11 @@ "metadata": {}, "outputs": [], "source": [ - "scenarios.to_excel(\"my_excel.xlsx\")" + "# Export the scenarios to excel\n", + "scenarios.to_excel(\"export.xlsx\") # This will create export.xlsx and export_output_curves.xlsx.\n", + "\n", + "# There are also options - decide whether to include the output_curves, specify where you want them and specify which carriers you're interested in.\n", + "scenarios.to_excel((\"export_with_options.xlsx\"), export_output_curves=True, output_curves_path=\"output_curves.xlsx\", carriers=[\"electricity\", \"heat\", \"hydrogen\"])" ] } ], diff --git a/examples/example.config.yml b/examples/example.config.yml index 75d6259..23a9221 100644 --- a/examples/example.config.yml +++ b/examples/example.config.yml @@ -10,13 +10,19 @@ # etm_api_token: your.token.here +# Select the environment; base_url will be inferred automatically if set. +# Supported: pro (default), beta, local, or a stable tag like 2025-01 +environment: pro + + # Override the API base URL - here you can set which environment of the ETM you want to interact with. # Options include the default (pro), https://2025-01.engine.energytransitionmodel.com/api/v3 (a stable version) or # https://beta.engine.energytransitionmodel.com/api/v3 (the staging environment), or http://localhost:3000/api/v3 # (your local environment). # For more information, see: https://docs.energytransitionmodel.com/api/intro#environments # -BASE_URL: https://engine.energytransitionmodel.com/api/v3 +# Optional override: specify base_url directly instead of using 'environment'. E.g. +# base_url: https://engine.energytransitionmodel.com/api/v3 #TODO: Setup so the below is actually used # URLs of your proxy server addresses (replace the examples below by your own settings) diff --git a/examples/example_input_excel.xlsx b/examples/example_input_excel.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..72484746cb6a0c61a35334e07f63352aef97e9f8 GIT binary patch literal 1370069 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

_tdm_uz|Ihl8wf&zsvff32+V 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

)}e&1Dc<<#ke~{xlhr*`0s& z3Q7PFcuN$`;Xt^Clwmc7q(AL^;$ zc2$`E(#$F5g)L#J&Zh~h*EQpUI44}fXw4qHtyWD1k4x68slF0Dj#r~T_t93!rT(?} z@A{(bGvA|PSdCc>A-3h>1jXx@yDCpVdH|*JOM~SR-{_r{!txg>BHEvpqctU|6E0Ud zjfhgH9m>ccP{CS3J)ig&It-g=Gn2}*?TI6p{uZiF*?opA2unXe#jljftQ^Ige0HvP ze=V!X&CzueF+Qj4WfU&+A{RNeIBh>Waw8}ys>t*28kM&@#;W<<#{0UP2si7N;5p(% zxgS4V{b%_qo|24l5srU;&ZMD?@#Fb<@?@RQ1`XO@+^>k3Pj-@0q^&r-dlc3%G&R4! zdj$sB`8yZ4dhkrq2|LuazjKKQ!zK9FYzwN4@+4U-evl&_T1=dO`I=ERY&9A`T@gfN z1^?ksxT<05Ka;8lK9WgyDjfc%w?@F$tg4=p*F^vPAo&)ezD zZpNC@9?*=h$o%n*Xe21`nK-{z@_n`MG2|-i#PdWnGTiG9dLZ@3h>pY=ZQeVgVlgcm zG185T`zqdm=dB>J9$PJ_KRa>0Y#?pqaYbFIuh7`@TJ8PvR}(J~&LCAB+P4WIjB>+v zIrt`X5U{U?E9J3kwMz8vL9ptHsN1#bCIMis4P3q7UjI8=p@w-^b>oOm*+ZGJoGWx( zL0ol6ky^NO{S6$pNcOmT&QCB<1_udK@!<4v&`>iidUmCra(ZE@#R<#S2nrY(v%aT1 z)+L%o#cvlOQdR_5HU$m)qwB}#A?j2up9G_S9go|@z6gya&q74~0^#_Ay``S;94}XR z$LliXqF;46+ImL;%9PWd?_;L)K)j*4KAy=64?7?eC!96>SPz8bjmq5kFz?;6ZZ|V~ z&#aqVgVgo1<$ny>NwSeK1lax0{TkAvC7Ly(GV0)>!2IB0)WURegnFL+4z{FoC0(tZ z?%IEx-LhDPF4KQZ@`d5{t$3~}MQi2F21?;!BF>$WQVYL_O#rhHhBgk;T>CU~w88NQ zahB%X&#lmKbtfzRPbS*+lfuw0%qDR@dEm8?Arpk`v0>&m3TGwgk7X`G z{@hM0_cPYqvza{ z=NuhU6u>Uz@bUyJ387V;gUF?SYXUT6J7@I~M&&MVPN+qe=S2y7!OV;J+TN27TPMow zzk3L`4-~x`ygkf0a(ae8*nrH)jphHHZpW)rZY;p+U0VqigMUsY@8AmX zs%+!6dr6t;;J2;yy1vPZzg&t-=%<;5CocY90LH%0Ap5i<3y2k}AW}jVOYinG2f}HB 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\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
scen_ascen_b
useruser
inputunit
climate_relevant_co2_biomass_gas_future%30.035.0
climate_relevant_co2_biomass_gas_present%20.0None
climate_relevant_co2_biomass_liquid_future%30.0None
climate_relevant_co2_biomass_liquid_present%20.0None
climate_relevant_co2_biomass_solid_future%30.0None
............
capacity_of_energy_battery_wind_turbine_inlandMWNaN0.0
capacity_of_energy_power_hybrid_wind_turbine_offshoreMWNaNNone
capacity_of_energy_power_wind_turbine_coastalMWNaN0.0
capacity_of_energy_power_wind_turbine_inlandMWNaN20000.0
capacity_of_energy_power_wind_turbine_offshoreMWNaN52000.0
\n", - "

1318 rows × 2 columns

\n", - "" - ], - "text/plain": [ - " scen_a scen_b\n", - " user user\n", - "input unit \n", - "climate_relevant_co2_biomass_gas_future % 30.0 35.0\n", - "climate_relevant_co2_biomass_gas_present % 20.0 None\n", - "climate_relevant_co2_biomass_liquid_future % 30.0 None\n", - "climate_relevant_co2_biomass_liquid_present % 20.0 None\n", - "climate_relevant_co2_biomass_solid_future % 30.0 None\n", - "... ... ...\n", - "capacity_of_energy_battery_wind_turbine_inland MW NaN 0.0\n", - "capacity_of_energy_power_hybrid_wind_turbine_of... MW NaN None\n", - "capacity_of_energy_power_wind_turbine_coastal MW NaN 0.0\n", - "capacity_of_energy_power_wind_turbine_inland MW NaN 20000.0\n", - "capacity_of_energy_power_wind_turbine_offshore MW NaN 52000.0\n", - "\n", - "[1318 rows x 2 columns]" - ] - }, - "execution_count": 6, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "packer.inputs()" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "cd08ff26", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
A: Create from excelB: Load a scenario by id
forecast_storagehydrogen_supplyhydrogen_demandspace_heatingheat_network_ltheat_network_mtheat_network_htforecast_storagehydrogen_supplyhydrogen_demandspace_heatingheat_network_ltheat_network_mtheat_network_ht
sortables
0households_flexibility_p2p_electricityenergy_hydrogen_storage_depleted_gas_fieldenergy_hydrogen_storage_depleted_gas_fieldhouseholds_space_heater_district_heating_lt_st...energy_heat_network_storage_lt_steam_hot_waterenergy_heat_network_storage_mt_steam_hot_waterenergy_heat_network_storage_ht_steam_hot_waterenergy_flexibility_pumped_storage_electricityenergy_hydrogen_storage_depleted_gas_fieldenergy_hydrogen_storage_depleted_gas_fieldhouseholds_space_heater_district_heating_lt_st...energy_heat_network_storage_lt_steam_hot_waterenergy_heat_network_storage_mt_steam_hot_waterenergy_heat_network_storage_ht_steam_hot_water
1energy_flexibility_mv_batteries_electricityenergy_hydrogen_storage_salt_cavernenergy_hydrogen_storage_salt_cavernhouseholds_space_heater_heatpump_surface_water...energy_heat_boiler_lt_electricityenergy_heat_boiler_mt_electricityenergy_heat_boiler_ht_electricitytransport_van_flexibility_p2p_electricityenergy_hydrogen_storage_salt_cavernenergy_hydrogen_storage_salt_cavernhouseholds_space_heater_heatpump_surface_water...energy_heat_boiler_lt_electricityenergy_heat_boiler_mt_electricityenergy_heat_boiler_ht_electricity
2transport_car_flexibility_p2p_electricityenergy_hydrogen_autothermal_reformer_dispatchableNonehouseholds_space_heater_heatpump_air_water_ele...energy_heat_burner_lt_hydrogenenergy_heat_burner_mt_coalenergy_heat_burner_ht_coaltransport_truck_flexibility_p2p_electricityenergy_hydrogen_autothermal_reformer_dispatchableNonehouseholds_space_heater_heatpump_air_water_ele...energy_heat_burner_lt_hydrogenenergy_heat_burner_mt_coalenergy_heat_burner_ht_coal
3energy_flexibility_flow_batteries_electricityenergy_hydrogen_steam_methane_reformer_dispatc...Nonehouseholds_space_heater_heatpump_ground_water_...energy_heat_heatpump_water_water_lt_electricityenergy_heat_burner_mt_crude_oilenergy_heat_burner_ht_crude_oiltransport_bus_flexibility_p2p_electricityenergy_hydrogen_steam_methane_reformer_dispatc...Nonehouseholds_space_heater_heatpump_ground_water_...energy_heat_heatpump_water_water_lt_electricityenergy_heat_burner_mt_crude_oilenergy_heat_burner_ht_crude_oil
4energy_flexibility_hv_opac_electricityenergy_hydrogen_ammonia_reformer_dispatchableNonehouseholds_space_heater_heatpump_pvt_electricityenergy_heat_heatpump_surface_water_water_ts_lt...energy_heat_burner_mt_hydrogenenergy_heat_burner_ht_hydrogenenergy_flexibility_hv_opac_electricityenergy_hydrogen_ammonia_reformer_dispatchableNonehouseholds_space_heater_heatpump_pvt_electricityenergy_heat_heatpump_surface_water_water_ts_lt...energy_heat_burner_mt_hydrogenenergy_heat_burner_ht_hydrogen
5transport_bus_flexibility_p2p_electricityNoneNonehouseholds_space_heater_district_heating_mt_st...energy_heat_heatpump_waste_water_water_ts_lt_e...energy_heat_burner_mt_network_gasenergy_heat_burner_ht_network_gasenergy_flexibility_flow_batteries_electricityNoneNonehouseholds_space_heater_district_heating_mt_st...energy_heat_heatpump_waste_water_water_ts_lt_e...energy_heat_burner_mt_network_gasenergy_heat_burner_ht_network_gas
6transport_truck_flexibility_p2p_electricityNoneNonehouseholds_space_heater_hybrid_heatpump_air_wa...energy_heat_heatpump_drink_water_water_ts_lt_e...energy_heat_burner_mt_waste_mixenergy_heat_burner_ht_waste_mixtransport_car_flexibility_p2p_electricityNoneNonehouseholds_space_heater_hybrid_heatpump_air_wa...energy_heat_heatpump_drink_water_water_ts_lt_e...energy_heat_burner_mt_waste_mixenergy_heat_burner_ht_waste_mix
7transport_van_flexibility_p2p_electricityNoneNonehouseholds_space_heater_hybrid_hydrogen_heatpu...Noneenergy_heat_burner_mt_wood_pelletsenergy_heat_burner_ht_wood_pelletsenergy_flexibility_mv_batteries_electricityNoneNonehouseholds_space_heater_hybrid_hydrogen_heatpu...Noneenergy_heat_burner_mt_wood_pelletsenergy_heat_burner_ht_wood_pellets
8energy_flexibility_pumped_storage_electricityNoneNonehouseholds_space_heater_hybrid_crude_oil_heatp...Noneenergy_heat_heatpump_water_water_mt_electricityenergy_heat_heatpump_water_water_ht_electricityhouseholds_flexibility_p2p_electricityNoneNonehouseholds_space_heater_hybrid_crude_oil_heatp...Noneenergy_heat_heatpump_water_water_mt_electricityenergy_heat_heatpump_water_water_ht_electricity
9NoneNoneNonehouseholds_space_heater_district_heating_ht_st...Noneenergy_heat_heatpump_surface_water_water_ts_mt...NoneNoneNoneNonehouseholds_space_heater_district_heating_ht_st...Noneenergy_heat_heatpump_surface_water_water_ts_mt...None
10NoneNoneNonehouseholds_space_heater_electricityNoneenergy_heat_heatpump_waste_water_water_ts_mt_e...NoneNoneNoneNonehouseholds_space_heater_electricityNoneenergy_heat_heatpump_waste_water_water_ts_mt_e...None
11NoneNoneNonehouseholds_space_heater_combined_network_gasNoneenergy_heat_heatpump_drink_water_water_ts_mt_e...NoneNoneNoneNonehouseholds_space_heater_combined_network_gasNoneenergy_heat_heatpump_drink_water_water_ts_mt_e...None
12NoneNoneNonehouseholds_space_heater_combined_hydrogenNoneNoneNoneNoneNoneNonehouseholds_space_heater_combined_hydrogenNoneNoneNone
13NoneNoneNonehouseholds_space_heater_wood_pelletsNoneNoneNoneNoneNoneNonehouseholds_space_heater_wood_pelletsNoneNoneNone
14NoneNoneNonehouseholds_space_heater_network_gasNoneNoneNoneNoneNoneNonehouseholds_space_heater_network_gasNoneNoneNone
15NoneNoneNonehouseholds_space_heater_coalNoneNoneNoneNoneNoneNonehouseholds_space_heater_coalNoneNoneNone
16NoneNoneNonehouseholds_space_heater_crude_oilNoneNoneNoneNoneNoneNonehouseholds_space_heater_crude_oilNoneNoneNone
\n", - "
" - ], - "text/plain": [ - " A: Create from excel \\\n", - " forecast_storage \n", - "sortables \n", - "0 households_flexibility_p2p_electricity \n", - "1 energy_flexibility_mv_batteries_electricity \n", - "2 transport_car_flexibility_p2p_electricity \n", - "3 energy_flexibility_flow_batteries_electricity \n", - "4 energy_flexibility_hv_opac_electricity \n", - "5 transport_bus_flexibility_p2p_electricity \n", - "6 transport_truck_flexibility_p2p_electricity \n", - "7 transport_van_flexibility_p2p_electricity \n", - "8 energy_flexibility_pumped_storage_electricity \n", - "9 None \n", - "10 None \n", - "11 None \n", - "12 None \n", - "13 None \n", - "14 None \n", - "15 None \n", - "16 None \n", - "\n", - " \\\n", - " hydrogen_supply \n", - "sortables \n", - "0 energy_hydrogen_storage_depleted_gas_field \n", - "1 energy_hydrogen_storage_salt_cavern \n", - "2 energy_hydrogen_autothermal_reformer_dispatchable \n", - "3 energy_hydrogen_steam_methane_reformer_dispatc... \n", - "4 energy_hydrogen_ammonia_reformer_dispatchable \n", - "5 None \n", - "6 None \n", - "7 None \n", - "8 None \n", - "9 None \n", - "10 None \n", - "11 None \n", - "12 None \n", - "13 None \n", - "14 None \n", - "15 None \n", - "16 None \n", - "\n", - " \\\n", - " hydrogen_demand \n", - "sortables \n", - "0 energy_hydrogen_storage_depleted_gas_field \n", - "1 energy_hydrogen_storage_salt_cavern \n", - "2 None \n", - "3 None \n", - "4 None \n", - "5 None \n", - "6 None \n", - "7 None \n", - "8 None \n", - "9 None \n", - "10 None \n", - "11 None \n", - "12 None \n", - "13 None \n", - "14 None \n", - "15 None \n", - "16 None \n", - "\n", - " \\\n", - " space_heating \n", - "sortables \n", - "0 households_space_heater_district_heating_lt_st... \n", - "1 households_space_heater_heatpump_surface_water... \n", - "2 households_space_heater_heatpump_air_water_ele... \n", - "3 households_space_heater_heatpump_ground_water_... \n", - "4 households_space_heater_heatpump_pvt_electricity \n", - "5 households_space_heater_district_heating_mt_st... \n", - "6 households_space_heater_hybrid_heatpump_air_wa... \n", - "7 households_space_heater_hybrid_hydrogen_heatpu... \n", - "8 households_space_heater_hybrid_crude_oil_heatp... \n", - "9 households_space_heater_district_heating_ht_st... \n", - "10 households_space_heater_electricity \n", - "11 households_space_heater_combined_network_gas \n", - "12 households_space_heater_combined_hydrogen \n", - "13 households_space_heater_wood_pellets \n", - "14 households_space_heater_network_gas \n", - "15 households_space_heater_coal \n", - "16 households_space_heater_crude_oil \n", - "\n", - " \\\n", - " heat_network_lt \n", - "sortables \n", - "0 energy_heat_network_storage_lt_steam_hot_water \n", - "1 energy_heat_boiler_lt_electricity \n", - "2 energy_heat_burner_lt_hydrogen \n", - "3 energy_heat_heatpump_water_water_lt_electricity \n", - "4 energy_heat_heatpump_surface_water_water_ts_lt... \n", - "5 energy_heat_heatpump_waste_water_water_ts_lt_e... \n", - "6 energy_heat_heatpump_drink_water_water_ts_lt_e... \n", - "7 None \n", - "8 None \n", - "9 None \n", - "10 None \n", - "11 None \n", - "12 None \n", - "13 None \n", - "14 None \n", - "15 None \n", - "16 None \n", - "\n", - " \\\n", - " heat_network_mt \n", - "sortables \n", - "0 energy_heat_network_storage_mt_steam_hot_water \n", - "1 energy_heat_boiler_mt_electricity \n", - "2 energy_heat_burner_mt_coal \n", - "3 energy_heat_burner_mt_crude_oil \n", - "4 energy_heat_burner_mt_hydrogen \n", - "5 energy_heat_burner_mt_network_gas \n", - "6 energy_heat_burner_mt_waste_mix \n", - "7 energy_heat_burner_mt_wood_pellets \n", - "8 energy_heat_heatpump_water_water_mt_electricity \n", - "9 energy_heat_heatpump_surface_water_water_ts_mt... \n", - "10 energy_heat_heatpump_waste_water_water_ts_mt_e... \n", - "11 energy_heat_heatpump_drink_water_water_ts_mt_e... \n", - "12 None \n", - "13 None \n", - "14 None \n", - "15 None \n", - "16 None \n", - "\n", - " \\\n", - " heat_network_ht \n", - "sortables \n", - "0 energy_heat_network_storage_ht_steam_hot_water \n", - "1 energy_heat_boiler_ht_electricity \n", - "2 energy_heat_burner_ht_coal \n", - "3 energy_heat_burner_ht_crude_oil \n", - "4 energy_heat_burner_ht_hydrogen \n", - "5 energy_heat_burner_ht_network_gas \n", - "6 energy_heat_burner_ht_waste_mix \n", - "7 energy_heat_burner_ht_wood_pellets \n", - "8 energy_heat_heatpump_water_water_ht_electricity \n", - "9 None \n", - "10 None \n", - "11 None \n", - "12 None \n", - "13 None \n", - "14 None \n", - "15 None \n", - "16 None \n", - "\n", - " B: Load a scenario by id \\\n", - " forecast_storage \n", - "sortables \n", - "0 energy_flexibility_pumped_storage_electricity \n", - "1 transport_van_flexibility_p2p_electricity \n", - "2 transport_truck_flexibility_p2p_electricity \n", - "3 transport_bus_flexibility_p2p_electricity \n", - "4 energy_flexibility_hv_opac_electricity \n", - "5 energy_flexibility_flow_batteries_electricity \n", - "6 transport_car_flexibility_p2p_electricity \n", - "7 energy_flexibility_mv_batteries_electricity \n", - "8 households_flexibility_p2p_electricity \n", - "9 None \n", - "10 None \n", - "11 None \n", - "12 None \n", - "13 None \n", - "14 None \n", - "15 None \n", - "16 None \n", - "\n", - " \\\n", - " hydrogen_supply \n", - "sortables \n", - "0 energy_hydrogen_storage_depleted_gas_field \n", - "1 energy_hydrogen_storage_salt_cavern \n", - "2 energy_hydrogen_autothermal_reformer_dispatchable \n", - "3 energy_hydrogen_steam_methane_reformer_dispatc... \n", - "4 energy_hydrogen_ammonia_reformer_dispatchable \n", - "5 None \n", - "6 None \n", - "7 None \n", - "8 None \n", - "9 None \n", - "10 None \n", - "11 None \n", - "12 None \n", - "13 None \n", - "14 None \n", - "15 None \n", - "16 None \n", - "\n", - " \\\n", - " hydrogen_demand \n", - "sortables \n", - "0 energy_hydrogen_storage_depleted_gas_field \n", - "1 energy_hydrogen_storage_salt_cavern \n", - "2 None \n", - "3 None \n", - "4 None \n", - "5 None \n", - "6 None \n", - "7 None \n", - "8 None \n", - "9 None \n", - "10 None \n", - "11 None \n", - "12 None \n", - "13 None \n", - "14 None \n", - "15 None \n", - "16 None \n", - "\n", - " \\\n", - " space_heating \n", - "sortables \n", - "0 households_space_heater_district_heating_lt_st... \n", - "1 households_space_heater_heatpump_surface_water... \n", - "2 households_space_heater_heatpump_air_water_ele... \n", - "3 households_space_heater_heatpump_ground_water_... \n", - "4 households_space_heater_heatpump_pvt_electricity \n", - "5 households_space_heater_district_heating_mt_st... \n", - "6 households_space_heater_hybrid_heatpump_air_wa... \n", - "7 households_space_heater_hybrid_hydrogen_heatpu... \n", - "8 households_space_heater_hybrid_crude_oil_heatp... \n", - "9 households_space_heater_district_heating_ht_st... \n", - "10 households_space_heater_electricity \n", - "11 households_space_heater_combined_network_gas \n", - "12 households_space_heater_combined_hydrogen \n", - "13 households_space_heater_wood_pellets \n", - "14 households_space_heater_network_gas \n", - "15 households_space_heater_coal \n", - "16 households_space_heater_crude_oil \n", - "\n", - " \\\n", - " heat_network_lt \n", - "sortables \n", - "0 energy_heat_network_storage_lt_steam_hot_water \n", - "1 energy_heat_boiler_lt_electricity \n", - "2 energy_heat_burner_lt_hydrogen \n", - "3 energy_heat_heatpump_water_water_lt_electricity \n", - "4 energy_heat_heatpump_surface_water_water_ts_lt... \n", - "5 energy_heat_heatpump_waste_water_water_ts_lt_e... \n", - "6 energy_heat_heatpump_drink_water_water_ts_lt_e... \n", - "7 None \n", - "8 None \n", - "9 None \n", - "10 None \n", - "11 None \n", - "12 None \n", - "13 None \n", - "14 None \n", - "15 None \n", - "16 None \n", - "\n", - " \\\n", - " heat_network_mt \n", - "sortables \n", - "0 energy_heat_network_storage_mt_steam_hot_water \n", - "1 energy_heat_boiler_mt_electricity \n", - "2 energy_heat_burner_mt_coal \n", - "3 energy_heat_burner_mt_crude_oil \n", - "4 energy_heat_burner_mt_hydrogen \n", - "5 energy_heat_burner_mt_network_gas \n", - "6 energy_heat_burner_mt_waste_mix \n", - "7 energy_heat_burner_mt_wood_pellets \n", - "8 energy_heat_heatpump_water_water_mt_electricity \n", - "9 energy_heat_heatpump_surface_water_water_ts_mt... \n", - "10 energy_heat_heatpump_waste_water_water_ts_mt_e... \n", - "11 energy_heat_heatpump_drink_water_water_ts_mt_e... \n", - "12 None \n", - "13 None \n", - "14 None \n", - "15 None \n", - "16 None \n", - "\n", - " \n", - " heat_network_ht \n", - "sortables \n", - "0 energy_heat_network_storage_ht_steam_hot_water \n", - "1 energy_heat_boiler_ht_electricity \n", - "2 energy_heat_burner_ht_coal \n", - "3 energy_heat_burner_ht_crude_oil \n", - "4 energy_heat_burner_ht_hydrogen \n", - "5 energy_heat_burner_ht_network_gas \n", - "6 energy_heat_burner_ht_waste_mix \n", - "7 energy_heat_burner_ht_wood_pellets \n", - "8 energy_heat_heatpump_water_water_ht_electricity \n", - "9 None \n", - "10 None \n", - "11 None \n", - "12 None \n", - "13 None \n", - "14 None \n", - "15 None \n", - "16 None " - ] - }, - "execution_count": 7, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "packer.sortables()" - ] - }, - { - "cell_type": "code", - "execution_count": 8, - "id": "0d3e771e", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
A: Create from excelB: Load a scenario by id
interconnector_1_priceinterconnector_1_import_availabilityinterconnector_1_export_availabilityinterconnector_2_priceinterconnector_2_import_availabilityinterconnector_2_export_availabilityinterconnector_3_priceinterconnector_1_priceinterconnector_1_import_availabilityinterconnector_1_export_availability...households_hot_waterindustry_ictindustry_other_electricityweather/solar_pv_profile_1weather/solar_thermalweather/air_temperatureweather/agriculture_heatingweather/wind_offshore_baselineweather/wind_coastal_baselineweather/wind_inland_baseline
00.011.00.026.001.01.00.019.09.09.0...9.09.09.09.09.09.09.09.09.09.0
10.011.00.026.001.01.00.009.09.09.0...9.09.09.09.09.09.09.09.09.09.0
20.011.00.014.481.01.00.009.09.09.0...9.09.09.09.09.09.09.09.09.09.0
30.011.00.00.011.00.00.009.09.09.0...9.09.09.09.09.09.09.09.09.09.0
40.011.00.00.021.00.00.009.09.09.0...9.09.09.09.09.09.09.09.09.09.0
..................................................................
87550.011.00.00.011.00.00.009.09.09.0...9.09.09.09.09.09.09.09.09.09.0
87560.011.00.00.011.00.00.009.09.09.0...9.09.09.09.09.09.09.09.09.09.0
87570.011.00.00.011.00.00.009.09.09.0...9.09.09.09.09.09.09.09.09.09.0
87580.011.00.00.021.00.00.009.09.09.0...9.09.09.09.09.09.09.09.09.09.0
87590.011.00.00.001.00.00.009.09.09.0...9.09.09.09.09.09.09.09.09.09.0
\n", - "

8760 rows × 52 columns

\n", - "
" - ], - "text/plain": [ - " A: Create from excel \\\n", - " interconnector_1_price interconnector_1_import_availability \n", - "0 0.01 1.0 \n", - "1 0.01 1.0 \n", - "2 0.01 1.0 \n", - "3 0.01 1.0 \n", - "4 0.01 1.0 \n", - "... ... ... \n", - "8755 0.01 1.0 \n", - "8756 0.01 1.0 \n", - "8757 0.01 1.0 \n", - "8758 0.01 1.0 \n", - "8759 0.01 1.0 \n", - "\n", - " \\\n", - " interconnector_1_export_availability interconnector_2_price \n", - "0 0.0 26.00 \n", - "1 0.0 26.00 \n", - "2 0.0 14.48 \n", - "3 0.0 0.01 \n", - "4 0.0 0.02 \n", - "... ... ... \n", - "8755 0.0 0.01 \n", - "8756 0.0 0.01 \n", - "8757 0.0 0.01 \n", - "8758 0.0 0.02 \n", - "8759 0.0 0.00 \n", - "\n", - " \\\n", - " interconnector_2_import_availability \n", - "0 1.0 \n", - "1 1.0 \n", - "2 1.0 \n", - "3 1.0 \n", - "4 1.0 \n", - "... ... \n", - "8755 1.0 \n", - "8756 1.0 \n", - "8757 1.0 \n", - "8758 1.0 \n", - "8759 1.0 \n", - "\n", - " \\\n", - " interconnector_2_export_availability interconnector_3_price \n", - "0 1.0 0.01 \n", - "1 1.0 0.00 \n", - "2 1.0 0.00 \n", - "3 0.0 0.00 \n", - "4 0.0 0.00 \n", - "... ... ... \n", - "8755 0.0 0.00 \n", - "8756 0.0 0.00 \n", - "8757 0.0 0.00 \n", - "8758 0.0 0.00 \n", - "8759 0.0 0.00 \n", - "\n", - " B: Load a scenario by id \\\n", - " interconnector_1_price interconnector_1_import_availability \n", - "0 9.0 9.0 \n", - "1 9.0 9.0 \n", - "2 9.0 9.0 \n", - "3 9.0 9.0 \n", - "4 9.0 9.0 \n", - "... ... ... \n", - "8755 9.0 9.0 \n", - "8756 9.0 9.0 \n", - "8757 9.0 9.0 \n", - "8758 9.0 9.0 \n", - "8759 9.0 9.0 \n", - "\n", - " ... \\\n", - " interconnector_1_export_availability ... households_hot_water \n", - "0 9.0 ... 9.0 \n", - "1 9.0 ... 9.0 \n", - "2 9.0 ... 9.0 \n", - "3 9.0 ... 9.0 \n", - "4 9.0 ... 9.0 \n", - "... ... ... ... \n", - "8755 9.0 ... 9.0 \n", - "8756 9.0 ... 9.0 \n", - "8757 9.0 ... 9.0 \n", - "8758 9.0 ... 9.0 \n", - "8759 9.0 ... 9.0 \n", - "\n", - " \\\n", - " industry_ict industry_other_electricity weather/solar_pv_profile_1 \n", - "0 9.0 9.0 9.0 \n", - "1 9.0 9.0 9.0 \n", - "2 9.0 9.0 9.0 \n", - "3 9.0 9.0 9.0 \n", - "4 9.0 9.0 9.0 \n", - "... ... ... ... \n", - "8755 9.0 9.0 9.0 \n", - "8756 9.0 9.0 9.0 \n", - "8757 9.0 9.0 9.0 \n", - "8758 9.0 9.0 9.0 \n", - "8759 9.0 9.0 9.0 \n", - "\n", - " \\\n", - " weather/solar_thermal weather/air_temperature \n", - "0 9.0 9.0 \n", - "1 9.0 9.0 \n", - "2 9.0 9.0 \n", - "3 9.0 9.0 \n", - "4 9.0 9.0 \n", - "... ... ... \n", - "8755 9.0 9.0 \n", - "8756 9.0 9.0 \n", - "8757 9.0 9.0 \n", - "8758 9.0 9.0 \n", - "8759 9.0 9.0 \n", - "\n", - " \\\n", - " weather/agriculture_heating weather/wind_offshore_baseline \n", - "0 9.0 9.0 \n", - "1 9.0 9.0 \n", - "2 9.0 9.0 \n", - "3 9.0 9.0 \n", - "4 9.0 9.0 \n", - "... ... ... \n", - "8755 9.0 9.0 \n", - "8756 9.0 9.0 \n", - "8757 9.0 9.0 \n", - "8758 9.0 9.0 \n", - "8759 9.0 9.0 \n", - "\n", - " \n", - " weather/wind_coastal_baseline weather/wind_inland_baseline \n", - "0 9.0 9.0 \n", - "1 9.0 9.0 \n", - "2 9.0 9.0 \n", - "3 9.0 9.0 \n", - "4 9.0 9.0 \n", - "... ... ... \n", - "8755 9.0 9.0 \n", - "8756 9.0 9.0 \n", - "8757 9.0 9.0 \n", - "8758 9.0 9.0 \n", - "8759 9.0 9.0 \n", - "\n", - "[8760 rows x 52 columns]" - ] - }, - "execution_count": 8, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "packer.custom_curves()" - ] - }, - { - "cell_type": "code", - "execution_count": 9, - "id": "54cc3f61", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
A: Create from excelB: Load a scenario by id
futurefuture
gqueryunit
dashboard_emissionsfactor0.024027-0.947929
dashboard_co2_emissions_versus_start_yearfactor0.028299-0.997037
dashboard_total_costsbln_euro39.30029356.46303
\n", - "
" - ], - "text/plain": [ - " A: Create from excel \\\n", - " future \n", - "gquery unit \n", - "dashboard_emissions factor 0.024027 \n", - "dashboard_co2_emissions_versus_start_year factor 0.028299 \n", - "dashboard_total_costs bln_euro 39.300293 \n", - "\n", - " B: Load a scenario by id \n", - " future \n", - "gquery unit \n", - "dashboard_emissions factor -0.947929 \n", - "dashboard_co2_emissions_versus_start_year factor -0.997037 \n", - "dashboard_total_costs bln_euro 56.46303 " - ] - }, - "execution_count": 9, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "packer.gquery_results()" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "pyetm-qKH2ozgc", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.9" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/examples/exploring_a_scenario.ipynb b/examples/exploring_a_scenario.ipynb deleted file mode 100644 index 5fd681c..0000000 --- a/examples/exploring_a_scenario.ipynb +++ /dev/null @@ -1,211 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "ddbe7ab2", - "metadata": {}, - "source": [ - "# Scenario Examples\n", - "\n", - "This notebook demonstrates how to use the `Scenario` object within the pyetm package to retrieve and \n", - "inspect data from an ETM scenario.\n", - "\n", - "Make sure you have a valid `ETM_API_TOKEN` set in your environment.\n", - "\n", - "## Structure\n", - "\n", - "This notebook is organized into two main sections:\n", - "1. **Setup** - Run these cells first to set up your environment and load a scenario\n", - "2. **Examples** - After setup is complete, these cells can be run in any order to explore different aspects of scenario data\n", - "\n", - "## Setup:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "59514b1f", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Environment setup complete\n", - " Using ETM API at http://localhost:3000/api/v3\n", - " Token loaded? True\n", - "API connection ready\n" - ] - }, - { - "ename": "ScenarioError", - "evalue": "Could not load scenario 2690288: [\"HTTPConnectionPool(host='localhost', port=3000): Max retries exceeded with url: /api/v3/scenarios/2690288 (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 61] Connection refused'))\"]", - "output_type": "error", - "traceback": [ - "\u001b[31mScenarioError\u001b[39m\u001b[31m:\u001b[39m Could not load scenario 2690288: [\"HTTPConnectionPool(host='localhost', port=3000): Max retries exceeded with url: /api/v3/scenarios/2690288 (Caused by NewConnectionError(': Failed to establish a new connection: [Errno 61] Connection refused'))\"]\n" - ] - } - ], - "source": [ - "from example_helpers import setup_notebook\n", - "from pyetm.models import Scenario\n", - "\n", - "setup_notebook()\n", - "\n", - "# Change the scenario id to anything you want! This is a scenario on pro.\n", - "scenario = Scenario.load(2690555)" - ] - }, - { - "cell_type": "markdown", - "id": "4056266c", - "metadata": {}, - "source": [ - "## Examples\n", - "\n", - "Basic scenario info:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "aca02e6c", - "metadata": {}, - "outputs": [], - "source": [ - "print(f\"Area: {scenario.area_code}\")\n", - "print(f\"End year: {scenario.end_year}\")\n", - "print(f\"Version: {scenario.version}\")" - ] - }, - { - "cell_type": "markdown", - "id": "b3026722", - "metadata": {}, - "source": [ - "User inputs" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "7b529ffa", - "metadata": {}, - "outputs": [], - "source": [ - "user_vals = scenario.user_values()\n", - "print(f\"Modified inputs: {len(user_vals)}\")\n", - "print(f\"First input: {list(user_vals.keys())[0]} = {list(user_vals.values())[0]}\")" - ] - }, - { - "cell_type": "markdown", - "id": "625977af", - "metadata": {}, - "source": [ - "Example Input" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "f9c453cf", - "metadata": {}, - "outputs": [], - "source": [ - "first_input = next(iter(scenario.inputs))\n", - "print(f\"Key: {first_input.key}\")\n", - "print(f\"Unit: {first_input.unit}\")\n", - "print(f\"Default: {first_input.default}\")" - ] - }, - { - "cell_type": "markdown", - "id": "50ef3d36", - "metadata": {}, - "source": [ - "Output curve (an export from the scenario)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "4289f9c4", - "metadata": {}, - "outputs": [], - "source": [ - "carrier_keys = list(scenario.output_curves.attached_keys())\n", - "if carrier_keys:\n", - " first_carrier = carrier_keys[0]\n", - " carrier_data = list(scenario.all_output_curves())[0]\n", - " print(f\"Carrier curve: {first_carrier}\")\n", - " print(f\"Shape: {carrier_data.shape}\")" - ] - }, - { - "cell_type": "markdown", - "id": "af75d6e6", - "metadata": {}, - "source": [ - "Sortables" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "411ce7e1", - "metadata": {}, - "outputs": [], - "source": [ - "sortables = scenario.sortables.as_dict()\n", - "if sortables:\n", - " first_sortable = list(sortables.keys())[0]\n", - " print(f\"Sortable: {first_sortable}\")\n", - " print(f\"Items: {len(sortables[first_sortable])}\")" - ] - }, - { - "cell_type": "markdown", - "id": "73192cdf", - "metadata": {}, - "source": [ - "Gqueries" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "1dbe4e91", - "metadata": {}, - "outputs": [], - "source": [ - "scenario.add_queries([\"dashboard_emissions\"])\n", - "results = scenario.results()\n", - "if results is not None:\n", - " print(f\"Query present result: {results['present'].iloc[0]:.2f}\")\n", - " print(f\"Query future result: {results['future'].iloc[0]:.2f}\")" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "pyetm-qKH2ozgc", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.9" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/examples/myc_notebook_for_tim.ipynb b/examples/myc_notebook_for_tim.ipynb deleted file mode 100644 index 6545857..0000000 --- a/examples/myc_notebook_for_tim.ipynb +++ /dev/null @@ -1,1631 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "8128efd6", - "metadata": {}, - "source": [ - "This notebook mimics the myc_notebook from pyetm v1 to demonstrate how functionalities remain the same, despite being dressed up differently." - ] - }, - { - "cell_type": "markdown", - "id": "53e5210e", - "metadata": {}, - "source": [ - "**Multi-year charts**\n", - "\n", - "The MYC function within the ETM allows users to view and edit multiple scenarios at once. This \n", - "feature is useful to compare different scenarios or to built a transition path that contains \n", - "scenarios with different end years, see https://myc.energytransitionmodel.com/\n" - ] - }, - { - "cell_type": "markdown", - "id": "205371e8", - "metadata": {}, - "source": [ - "**Model Initialisation**\n", - "\n", - "Where you used to initialize the 'model' with the `model.from_excel()` function, now we work with a 'scenario' or 'scenarios' (TBC - what will we call the multiple scenario object?).\n", - "\n", - "You need to run the setup_notebook() command to get the API ready - this will also validate that you've set your API token correctly. You determine whether you connect with the beta, stable or live version of the ETM via the ETM_URL in the config." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e3d108b6", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Environment setup complete\n", - " Using ETM API at https://beta.engine.energytransitionmodel.com/api/v3\n", - " Token loaded? True\n", - "API connection ready\n" - ] - } - ], - "source": [ - "from example_helpers import setup_notebook\n", - "from pyetm.models import Scenario\n", - "\n", - "setup_notebook()\n", - "# put a comment how to make the setup" - ] - }, - { - "cell_type": "markdown", - "id": "f87a2eef", - "metadata": {}, - "source": [ - "Then, you can create a scenario (or scenarios) with the Scenario.from_excel. For now this functionality is not implemented, so the example will continue by loading an individual scenario. Note that when multi-scenario functionality has been implemented, these same steps should work exactly the same way, but on the Scenarios object, rather than the Scenario object." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "76dce178", - "metadata": {}, - "outputs": [ - { - "data": { - "text/html": [ - "
\n", - "\n", - "\n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - " \n", - "
2690499
scenario
end_year2040
privateFalse
area_codenl2019
template2402157
\n", - "
" - ], - "text/plain": [ - " 2690499\n", - "scenario \n", - "end_year 2040\n", - "private False\n", - "area_code nl2019\n", - "template 2402157" - ] - }, - "execution_count": 13, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "scenario = Scenario.load(2690499)\n", - "scenario.to_dataframe()" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "5c8a7628", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " max min user\n", - "input unit \n", - "climate_relevant_co2_biomass_gas_future % 100.0 0.0 0.0\n", - "climate_relevant_co2_biomass_gas_present % 100.0 0.0 0.0\n", - "climate_relevant_co2_biomass_liquid_future % 100.0 0.0 0.0\n", - "climate_relevant_co2_biomass_liquid_present % 100.0 0.0 0.0\n", - "climate_relevant_co2_biomass_solid_future % 100.0 0.0 0.0\n" - ] - } - ], - "source": [ - "# Get scenario input parameters (incl. units)\n", - "inputs = scenario.inputs\n", - "# Give an explanation of available columns\n", - "print(inputs.to_dataframe(columns=['max', 'min', 'user']).head())" - ] - }, - { - "cell_type": "markdown", - "id": "ba56a5f2", - "metadata": {}, - "source": [ - "You will notice that in the original pyetm this call was:\n", - "```\n", - "inputs = model.get_parameters(exclude=True)\n", - "inputs.head()\n", - "```\n", - "Pyetm v2 is more developer friendly, which means that each of the 'objects' on the model (for example the inputs) are still python objects until you call **to_dataframe()** on them. This is one of the more significant changes - you will have to specify (in the notebooks) what format you want the data in. For the flows from Excel --> ETM and ETM --> Excel, this is all taken care of internally." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "e3a3bfab", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'climate_relevant_co2_biomass_gas_future': 0.0,\n", - " 'climate_relevant_co2_biomass_gas_present': 0.0,\n", - " 'climate_relevant_co2_biomass_liquid_future': 0.0,\n", - " 'climate_relevant_co2_biomass_liquid_present': 0.0,\n", - " 'climate_relevant_co2_biomass_solid_future': 0.0,\n", - " 'climate_relevant_co2_biomass_solid_present': 0.0,\n", - " 'capacity_costs_energy_flexibility_flow_batteries_electricity': 0.0,\n", - " 'costs_bio_ethanol': 0.9482455192,\n", - " 'costs_biodiesel': 0.9588091368,\n", - " 'costs_biogas': 58.0,\n", - " 'costs_captured_biogenic_co2': 0.0,\n", - " 'costs_co2': 123.0,\n", - " 'costs_co2_free_allocation': 0.0,\n", - " 'costs_coal': 56.0,\n", - " 'costs_electricity_fallback_price': 3000.0,\n", - " 'costs_gas': 15.0,\n", - " 'costs_greengas': 61.0,\n", - " 'costs_heat_infra_indoors': 100.0,\n", - " 'costs_heat_infra_outdoors': 100.0,\n", - " 'costs_heat_network_storage_ht_steam_hot_water': 43.2,\n", - " 'costs_hydrogen': 30.0,\n", - " 'costs_hydrogen_transport_compressed_trucks': 50.0822647794,\n", - " 'costs_hydrogen_transport_pipelines': 1.5706418062,\n", - " 'costs_imported_ammonia': 43.2145152,\n", - " 'costs_imported_heat': 11.569444,\n", - " 'costs_industry_residual_heat': 0.0,\n", - " 'costs_infrastructure_electricity_hv_net': 364.0,\n", - " 'costs_infrastructure_electricity_interconnector_net': 364.0,\n", - " 'costs_infrastructure_electricity_lv_mv_trafo': 200.0,\n", - " 'costs_infrastructure_electricity_lv_net': 916.0,\n", - " 'costs_infrastructure_electricity_mv_hv_trafo': 250.0,\n", - " 'costs_infrastructure_electricity_mv_net': 690.0,\n", - " 'costs_infrastructure_electricity_offshore_net': 1159.0,\n", - " 'costs_oil': 61.0,\n", - " 'costs_uranium': 69.100026,\n", - " 'costs_wacc_households': 2.0,\n", - " 'costs_wacc_proven_technologies': 4.0,\n", - " 'costs_wacc_public_infrastructure': 3.0,\n", - " 'costs_wacc_unproven_technologies': 7.0,\n", - " 'costs_wood': 149.7799980001,\n", - " 'efficiency_agriculture_heatpump_water_water_electricity': 4.5,\n", - " 'efficiency_agriculture_heatpump_water_water_ts_electricity': 23.0000000001,\n", - " 'efficiency_ammonia_reforming': 68.5,\n", - " 'efficiency_buildings_space_heater_collective_heatpump_water_water_ts_electricity': 3.76,\n", - " 'efficiency_buildings_space_heater_combined_hydrogen': 108.6956522,\n", - " 'efficiency_buildings_space_heater_crude_oil': 85.0,\n", - " 'efficiency_buildings_space_heater_electricity': 100.0,\n", - " 'efficiency_buildings_space_heater_heatpump_air_water_electricity': 100.0,\n", - " 'efficiency_buildings_space_heater_hybrid_heatpump_air_water_electricity': 100.0,\n", - " 'efficiency_buildings_space_heater_hybrid_hydrogen_heatpump_air_water_electricity': 100.0,\n", - " 'efficiency_buildings_space_heater_network_gas': 106.7,\n", - " 'efficiency_buildings_space_heater_wood_pellets': 82.0,\n", - " 'efficiency_energy_chp_combined_cycle_network_gas_electricity': 43.3,\n", - " 'efficiency_energy_chp_combined_cycle_network_gas_heat': 30.5,\n", - " 'efficiency_energy_chp_local_engine_biogas_electricity': 42.0,\n", - " 'efficiency_energy_chp_local_engine_biogas_heat': 39.0,\n", - " 'efficiency_energy_chp_local_engine_network_gas_electricity': 42.0,\n", - " 'efficiency_energy_chp_local_engine_network_gas_heat': 50.0,\n", - " 'efficiency_energy_chp_local_wood_pellets_electricity': 18.3,\n", - " 'efficiency_energy_chp_local_wood_pellets_heat': 47.0,\n", - " 'efficiency_energy_chp_supercritical_waste_mix_electricity': 20.45,\n", - " 'efficiency_energy_chp_supercritical_waste_mix_heat': 19.9500000001,\n", - " 'efficiency_energy_chp_ultra_supercritical_coal_electricity': 44.0,\n", - " 'efficiency_energy_chp_ultra_supercritical_coal_heat': 13.0,\n", - " 'efficiency_energy_chp_ultra_supercritical_cofiring_coal_electricity': 40.0,\n", - " 'efficiency_energy_chp_ultra_supercritical_cofiring_coal_heat': 15.0,\n", - " 'efficiency_energy_power_combined_cycle_coal': 45.3000000001,\n", - " 'efficiency_energy_power_combined_cycle_hydrogen': 60.0,\n", - " 'efficiency_energy_power_combined_cycle_network_gas': 60.0,\n", - " 'efficiency_energy_power_engine_diesel': 38.0,\n", - " 'efficiency_energy_power_engine_network_gas': 48.0,\n", - " 'efficiency_energy_power_nuclear_gen2_uranium_oxide': 36.93,\n", - " 'efficiency_energy_power_nuclear_gen3_uranium_oxide': 36.93,\n", - " 'efficiency_energy_power_nuclear_small_modular_reactor_uranium_oxide': 28.0000000001,\n", - " 'efficiency_energy_power_solar_pv_solar_radiation': 23.0,\n", - " 'efficiency_energy_power_supercritical_coal': 36.0,\n", - " 'efficiency_energy_power_supercritical_waste_mix': 25.0,\n", - " 'efficiency_energy_power_turbine_hydrogen': 34.0,\n", - " 'efficiency_energy_power_turbine_network_gas': 34.0,\n", - " 'efficiency_energy_power_ultra_supercritical_coal': 46.0,\n", - " 'efficiency_energy_power_ultra_supercritical_cofiring_coal': 42.0,\n", - " 'efficiency_energy_power_ultra_supercritical_crude_oil': 45.0,\n", - " 'efficiency_energy_power_ultra_supercritical_network_gas': 40.0,\n", - " 'efficiency_households_space_heater_combined_hydrogen': 110.0000000001,\n", - " 'efficiency_households_space_heater_combined_network_gas': 107.0,\n", - " 'efficiency_households_space_heater_crude_oil': 85.0,\n", - " 'efficiency_households_space_heater_electricity': 100.0,\n", - " 'efficiency_households_space_heater_heatpump_air_water_electricity': 100.0,\n", - " 'efficiency_households_space_heater_heatpump_ground_water_electricity': 4.8000000001,\n", - " 'efficiency_households_space_heater_hybrid_heatpump_air_water_electricity': 100.0,\n", - " 'efficiency_households_space_heater_hybrid_hydrogen_heatpump_air_water_electricity': 100.0,\n", - " 'efficiency_households_space_heater_network_gas': 80.0,\n", - " 'efficiency_households_space_heater_wood_pellets': 82.0,\n", - " 'efficiency_hydrogen_electrolysis': 66.0,\n", - " 'efficiency_industry_chp_turbine_hydrogen_electricity': 33.4448160536,\n", - " 'efficiency_industry_chp_turbine_hydrogen_heat': 41.4715719064,\n", - " 'investment_costs_ammonia_reforming': 0.0,\n", - " 'investment_costs_co2_capture_industry': 0.0,\n", - " 'investment_costs_co2_ccs': 0.0,\n", - " 'investment_costs_co2_storage': 0.0,\n", - " 'investment_costs_co2_transport': 0.0,\n", - " 'investment_costs_co2_utilisation': 0.0,\n", - " 'investment_costs_combustion_biomass_plants': 0.0,\n", - " 'investment_costs_combustion_coal_plant': 0.0,\n", - " 'investment_costs_combustion_gas_plant': 0.0,\n", - " 'investment_costs_combustion_hydrogen_plant': 0.0,\n", - " 'investment_costs_combustion_oil_plant': 0.0,\n", - " 'investment_costs_combustion_waste_incinerator': 0.0,\n", - " 'investment_costs_electric_heat_pumps': 0.0,\n", - " 'investment_costs_electrolyzers': 0.0,\n", - " 'investment_costs_energy_flexibility_hv_opac_electricity': 0.0,\n", - " 'investment_costs_energy_flexibility_mv_batteries_electricity': 0.0,\n", - " 'investment_costs_flexibility_p2h_electricity': 0.0,\n", - " 'investment_costs_gas_heat_pumps': 0.0,\n", - " 'investment_costs_geothermal': 0.0,\n", - " 'investment_costs_households_flexibility_p2p_electricity': 0.0,\n", - " 'investment_costs_households_storage_space_heating': 154.7368,\n", - " 'investment_costs_households_storage_water_heating': 50.71375,\n", - " 'investment_costs_hydrogen_electrolysis': 0.0,\n", - " 'investment_costs_nuclear_nuclear_plant': 0.0,\n", - " 'investment_costs_nuclear_small_modular_reactor': 0.0,\n", - " 'investment_costs_solar_concentrated_solar_power': 0.0,\n", - " 'investment_costs_solar_solar_panels': 0.0,\n", - " 'investment_costs_solar_thermal': 0.0,\n", - " 'investment_costs_water_river': 0.0,\n", - " 'investment_costs_wind_offshore': 0.0,\n", - " 'investment_costs_wind_onshore': 0.0,\n", - " 'om_costs_co2_capture_industry': 0.0,\n", - " 'om_costs_co2_ccs': 0.0,\n", - " 'om_costs_co2_storage': 0.0,\n", - " 'om_costs_co2_transport': 0.0,\n", - " 'om_costs_co2_utilisation': 0.0,\n", - " 'om_costs_combustion_biomass_plant': 0.0,\n", - " 'om_costs_combustion_coal_plant': 0.0,\n", - " 'om_costs_combustion_gas_plant': 0.0,\n", - " 'om_costs_combustion_hydrogen_plant': 0.0,\n", - " 'om_costs_combustion_oil_plant': 0.0,\n", - " 'om_costs_combustion_waste_incinerator': 0.0,\n", - " 'om_costs_geothermal': 0.0,\n", - " 'om_costs_nuclear_nuclear_plant': 0.0,\n", - " 'om_costs_nuclear_small_modular_reactor': 0.0,\n", - " 'om_costs_solar_thermal': 0.0,\n", - " 'om_costs_water_river': 0.0,\n", - " 'om_costs_wind_offshore': 0.0,\n", - " 'om_costs_wind_onshore': 0.0,\n", - " 'volume_costs_energy_flexibility_flow_batteries_electricity': 0.0,\n", - " 'agriculture_burner_crude_oil_share': 0.0,\n", - " 'agriculture_burner_hydrogen_share': 0.0,\n", - " 'agriculture_burner_network_gas_share': 0.0,\n", - " 'agriculture_burner_wood_pellets_share': 10.0,\n", - " 'agriculture_final_demand_ht_central_steam_hot_water_share': 48.0,\n", - " 'agriculture_final_demand_local_steam_hot_water_share': 0.0,\n", - " 'agriculture_geothermal_share': 20.0,\n", - " 'agriculture_heatpump_water_water_electricity_share': 5.0,\n", - " 'agriculture_heatpump_water_water_ts_electricity_share': 17.0,\n", - " 'agriculture_useful_demand_electricity': 0.6,\n", - " 'agriculture_useful_demand_useable_heat': -1.7,\n", - " 'capacity_of_agriculture_flexibility_p2h_electricity': 0.0,\n", - " 'buildings_cooling_airconditioning_share': 82.0,\n", - " 'buildings_cooling_collective_heatpump_water_water_ts_electricity_share': 18.0,\n", - " 'buildings_cooling_heatpump_air_water_electricity_share': 0.0,\n", - " 'buildings_cooling_heatpump_air_water_network_gas_share': 0.0,\n", - " 'buildings_space_heater_coal_share': 0.0,\n", - " 'buildings_space_heater_collective_heatpump_water_water_ts_electricity_share': 4.56,\n", - " 'buildings_space_heater_combined_hydrogen_share': 0.0,\n", - " 'buildings_space_heater_crude_oil_share': 0.0,\n", - " 'buildings_space_heater_district_heating_ht_steam_hot_water_share': 18.05,\n", - " 'buildings_space_heater_electricity_share': 0.0,\n", - " 'buildings_space_heater_heatpump_air_water_electricity_share': 41.8,\n", - " 'buildings_space_heater_heatpump_air_water_network_gas_share': 0.0,\n", - " 'buildings_space_heater_hybrid_heatpump_air_water_electricity_share': 19.45,\n", - " 'buildings_space_heater_hybrid_hydrogen_heatpump_air_water_electricity_share': 0.0,\n", - " 'buildings_space_heater_network_gas_share': 14.75,\n", - " 'buildings_space_heater_solar_thermal_share': 40.0,\n", - " 'buildings_space_heater_wood_pellets_share': 1.39,\n", - " 'buildings_insulation_level_buildings_future': 169.44532976497808,\n", - " 'buildings_insulation_level_buildings_present': 217.2208864009762,\n", - " 'buildings_lighting_efficient_fluorescent_electricity_share': 2.0,\n", - " 'buildings_lighting_led_electricity_share': 98.0,\n", - " 'buildings_lighting_standard_fluorescent_electricity_share': 0.0,\n", - " 'buildings_lighting_savings_from_daylight_control_light': 45.0,\n", - " 'buildings_lighting_savings_from_motion_detection_light': 49.0,\n", - " 'buildings_useful_demand_cooling': -0.2972159969666939,\n", - " 'buildings_useful_demand_electricity': 0.0,\n", - " 'buildings_useful_demand_for_appliances': 1.1,\n", - " 'buildings_number_of_buildings_future': 122142.46602400357,\n", - " 'bunkers_allocated_percentage_aviation': 0.0,\n", - " 'bunkers_allocated_percentage_shipping': 0.0,\n", - " 'bunkers_plane_using_bio_kerosene_share': 42.67,\n", - " 'bunkers_plane_using_kerosene_share': 57.33,\n", - " 'bunkers_ship_using_ammonia_share': 0.0,\n", - " 'bunkers_ship_using_heavy_fuel_oil_share': 67.0,\n", - " 'bunkers_ship_using_hydrogen_share': 0.0,\n", - " 'bunkers_ship_using_lng_share': 33.0,\n", - " 'bunkers_useful_demand_planes': 0.0,\n", - " 'bunkers_useful_demand_ships': 0.0,\n", - " 'volume_of_baseload_export_hydrogen': 134.63050808711347,\n", - " 'households_cooker_halogen_electricity_share': 0.0,\n", - " 'households_cooker_induction_electricity_share': 88.35,\n", - " 'households_cooker_network_gas_share': 9.5,\n", - " 'households_cooker_resistive_electricity_share': 2.15,\n", - " 'households_cooker_wood_pellets_share': 0.0,\n", - " 'households_cooling_airconditioning_electricity_share': 81.9300000001,\n", - " 'households_cooling_heatpump_air_water_electricity_share': 9.67,\n", - " 'households_cooling_heatpump_ground_water_electricity_share': 8.4,\n", - " 'households_useful_demand_for_cooling': 0.0,\n", - " 'households_useful_demand_cooking_per_person': 0.0,\n", - " 'households_useful_demand_electric_appliances': 0.0,\n", - " 'households_useful_demand_lighting': 0.0,\n", - " 'households_appliances_electricity_efficiency': 13.770491803278606,\n", - " 'households_heater_coal_share': 0.0,\n", - " 'households_heater_combined_hydrogen_share': 0.0,\n", - " 'households_heater_combined_network_gas_share': 15.0,\n", - " 'households_heater_crude_oil_share': 0.0,\n", - " 'households_heater_district_heating_ht_steam_hot_water_share': 18.0,\n", - " 'households_heater_electricity_share': 2.8,\n", - " 'households_heater_heatpump_air_water_electricity_share': 33.6,\n", - " 'households_heater_heatpump_ground_water_electricity_share': 8.2,\n", - " 'households_heater_heatpump_pvt_electricity_share': 0.0,\n", - " 'households_heater_hybrid_heatpump_air_water_electricity_share': 19.5,\n", - " 'households_heater_hybrid_hydrogen_heatpump_air_water_electricity_share': 0.0,\n", - " 'households_heater_network_gas_share': 0.0,\n", - " 'households_heater_wood_pellets_share': 2.9,\n", - " 'households_useful_demand_hot_water_share': 0.0,\n", - " 'households_water_heater_solar_thermal_share': 32.5,\n", - " 'households_insulation_level_apartments_1945_1964': 187.26134107628562,\n", - " 'households_insulation_level_apartments_1965_1984': 160.57671114919341,\n", - " 'households_insulation_level_apartments_1985_2004': 128.26307690023407,\n", - " 'households_insulation_level_apartments_2005_present': 96.18100458657419,\n", - " 'households_insulation_level_apartments_before_1945': 256.6002436636793,\n", - " 'households_insulation_level_apartments_future': 53.92879181106722,\n", - " 'households_insulation_level_detached_houses_1945_1964': 194.75462565741475,\n", - " 'households_insulation_level_detached_houses_1965_1984': 162.1440300736066,\n", - " 'households_insulation_level_detached_houses_1985_2004': 128.41872640805985,\n", - " 'households_insulation_level_detached_houses_2005_present': 93.16911568453558,\n", - " 'households_insulation_level_detached_houses_before_1945': 237.0837495697443,\n", - " 'households_insulation_level_detached_houses_future': 44.03429181614837,\n", - " 'households_insulation_level_semi_detached_houses_1945_1964': 180.82152900785633,\n", - " 'households_insulation_level_semi_detached_houses_1965_1984': 156.09290631617938,\n", - " 'households_insulation_level_semi_detached_houses_1985_2004': 128.38268907671798,\n", - " 'households_insulation_level_semi_detached_houses_2005_present': 95.1754172419351,\n", - " 'households_insulation_level_semi_detached_houses_before_1945': 224.08322620338217,\n", - " 'households_insulation_level_semi_detached_houses_future': 45.8219794702538,\n", - " 'households_insulation_level_terraced_houses_1945_1964': 244.77387685870463,\n", - " 'households_insulation_level_terraced_houses_1965_1984': 190.10073010677155,\n", - " 'households_insulation_level_terraced_houses_1985_2004': 131.53138563876874,\n", - " 'households_insulation_level_terraced_houses_2005_present': 101.4220246175114,\n", - " 'households_insulation_level_terraced_houses_before_1945': 266.01945785021763,\n", - " 'households_insulation_level_terraced_houses_future': 47.969841149677144,\n", - " 'households_lighting_efficient_fluorescent_electricity_share': 8.25,\n", - " 'households_lighting_incandescent_electricity_share': 0.0,\n", - " 'households_lighting_led_electricity_share': 91.75,\n", - " 'households_number_of_apartments_future': 407270.7379999999,\n", - " 'households_number_of_detached_houses_future': 141946.5721,\n", - " 'households_number_of_inhabitants': 19.1,\n", - " 'households_number_of_semi_detached_houses_future': 246876.06719999993,\n", - " 'households_number_of_terraced_houses_future': 334197.6226999997,\n", - " 'capacity_of_industry_chemicals_fertilizers_flexibility_p2h_electricity': 0.0,\n", - " 'capacity_of_industry_chemicals_other_flexibility_p2h_electricity': 0.0,\n", - " 'capacity_of_industry_chemicals_refineries_flexibility_p2h_electricity': 0.0,\n", - " 'capacity_of_industry_other_food_flexibility_p2h_electricity': 700.0,\n", - " 'capacity_of_industry_other_paper_flexibility_p2h_electricity': 175.0,\n", - " 'industry_aggregated_other_industry_coal_share_energetic': 0.0,\n", - " 'industry_aggregated_other_industry_cokes_share_energetic': 0.0,\n", - " 'industry_aggregated_other_industry_crude_oil_share_energetic': 0.0,\n", - " 'industry_aggregated_other_industry_electricity_share': 80.0,\n", - " 'industry_aggregated_other_industry_hydrogen_share_energetic': 3.0,\n", - " 'industry_aggregated_other_industry_hydrogen_share_non_energetic': 0.0,\n", - " 'industry_aggregated_other_industry_network_gas_share_energetic': 17.0,\n", - " 'industry_aggregated_other_industry_useable_heat_share': 0.0,\n", - " 'industry_aggregated_other_industry_wood_pellets_share_energetic': 0.0,\n", - " 'industry_aluminium_carbothermalreduction_electricity_share': 0.0,\n", - " 'industry_aluminium_electrolysis_bat_electricity_share': 16.66666667,\n", - " 'industry_aluminium_electrolysis_current_electricity_share': 42.8571428601,\n", - " 'industry_aluminium_production': 0.0,\n", - " 'industry_aluminium_smeltoven_electricity_share': 40.47619048,\n", - " 'industry_chemicals_fertilizers_burner_coal_share': 0.0,\n", - " 'industry_chemicals_fertilizers_burner_crude_oil_share': 0.0,\n", - " 'industry_chemicals_fertilizers_burner_hydrogen_share': 0.0,\n", - " 'industry_chemicals_fertilizers_burner_network_gas_share': 78.7151702787,\n", - " 'industry_chemicals_fertilizers_burner_wood_pellets_share': 0.0,\n", - " 'industry_chemicals_fertilizers_central_ammonia_share': 0.0,\n", - " 'industry_chemicals_fertilizers_hydrogen_network_share': 0.0,\n", - " 'industry_chemicals_fertilizers_local_ammonia_central_hydrogen_share': 0.0,\n", - " 'industry_chemicals_fertilizers_local_ammonia_local_hydrogen_share': 100.0,\n", - " 'industry_chemicals_fertilizers_steam_methane_reformer_hydrogen_share': 100.0,\n", - " 'industry_chemicals_other_burner_coal_share': 0.0,\n", - " 'industry_chemicals_other_burner_crude_oil_share': 45.3258609475,\n", - " 'industry_chemicals_other_burner_hydrogen_share': 0.0,\n", - " 'industry_chemicals_other_burner_network_gas_share': 24.2727467215,\n", - " 'industry_chemicals_other_burner_wood_pellets_share': 0.0,\n", - " 'industry_chemicals_other_coal_non_energetic_share': 0.0,\n", - " 'industry_chemicals_other_crude_oil_non_energetic_share': 88.8015390165,\n", - " 'industry_chemicals_other_heater_electricity_share': 0.0,\n", - " 'industry_chemicals_other_heatpump_water_water_electricity_share': 0.0,\n", - " 'industry_chemicals_other_hydrogen_non_energetic_share': 0.0,\n", - " 'industry_chemicals_other_network_gas_non_energetic_share': 11.1984609836,\n", - " 'industry_chemicals_other_steam_recompression_electricity_share': 0.0,\n", - " 'industry_chemicals_other_wood_pellets_non_energetic_share': 0.0,\n", - " 'industry_chemicals_refineries_burner_coal_share': 0.0,\n", - " 'industry_chemicals_refineries_burner_crude_oil_share': 64.2192843659,\n", - " 'industry_chemicals_refineries_burner_hydrogen_share': 0.0,\n", - " 'industry_chemicals_refineries_burner_network_gas_share': 27.8138338165,\n", - " 'industry_chemicals_refineries_burner_wood_pellets_share': 0.0,\n", - " 'industry_final_demand_for_chemical_fertilizers_steam_hot_water_share': 21.2848297214,\n", - " 'industry_final_demand_for_chemical_other_steam_hot_water_share': 30.4013923311,\n", - " 'industry_final_demand_for_chemical_refineries_steam_hot_water_share': 7.9668818178,\n", - " 'industry_final_demand_for_other_food_steam_hot_water_share': 0.0,\n", - " 'industry_final_demand_for_other_paper_steam_hot_water_share': 0.0,\n", - " 'industry_other_food_burner_coal_share': 0.0,\n", - " 'industry_other_food_burner_crude_oil_share': 0.0,\n", - " 'industry_other_food_burner_hydrogen_share': 0.0,\n", - " 'industry_other_food_burner_network_gas_share': 57.6,\n", - " 'industry_other_food_burner_wood_pellets_share': 0.0,\n", - " 'industry_other_food_heater_electricity_share': 42.4,\n", - " 'industry_other_metals_process_electricity_efficiency': 0.0,\n", - " 'industry_other_metals_process_heat_useable_heat_efficiency': 13.023776445487979,\n", - " 'industry_other_metals_production': 0.0,\n", - " 'industry_other_paper_burner_coal_share': 0.0,\n", - " 'industry_other_paper_burner_crude_oil_share': 0.0,\n", - " 'industry_other_paper_burner_hydrogen_share': 0.0,\n", - " 'industry_other_paper_burner_network_gas_share': 60.0,\n", - " 'industry_other_paper_burner_wood_pellets_share': 0.0,\n", - " 'industry_other_paper_heater_electricity_share': 40.0,\n", - " 'industry_steel_blastfurnace_bof_share': 100.0,\n", - " 'industry_steel_cyclonefurnace_bof_share': 0.0,\n", - " 'industry_steel_cyclonefurnace_bof_wood_pellets_share': 0.0,\n", - " 'industry_steel_dri_hydrogen_share': 0.0,\n", - " 'industry_steel_dri_network_gas_share': 0.0,\n", - " 'industry_steel_production': 100.0,\n", - " 'industry_steel_scrap_hbi_eaf_share': 0.0,\n", - " 'industry_useful_demand_for_aggregated_other_energetic': 89.0,\n", - " 'industry_useful_demand_for_aggregated_other_non_energetic': 89.0,\n", - " 'industry_useful_demand_for_chemical_fertilizers': 100.0,\n", - " 'industry_useful_demand_for_chemical_fertilizers_electricity_efficiency': 0.0,\n", - " 'industry_useful_demand_for_chemical_fertilizers_useable_heat_efficiency': 0.0,\n", - " 'industry_useful_demand_for_chemical_other': 100.0,\n", - " 'industry_useful_demand_for_chemical_other_electricity_efficiency': 0.0,\n", - " 'industry_useful_demand_for_chemical_other_useable_heat_efficiency': 0.0,\n", - " 'industry_useful_demand_for_chemical_refineries': 100.0,\n", - " 'industry_useful_demand_for_chemical_refineries_electricity_efficiency': 0.0,\n", - " 'industry_useful_demand_for_chemical_refineries_useable_heat_efficiency': 0.0,\n", - " 'industry_useful_demand_for_other_food': 100.0,\n", - " 'industry_useful_demand_for_other_food_electricity_efficiency': 25.320234587005388,\n", - " 'industry_useful_demand_for_other_food_useable_heat_efficiency': 25.320234587005388,\n", - " 'industry_useful_demand_for_other_ict': 329.0,\n", - " 'industry_useful_demand_for_other_ict_efficiency': 0.0,\n", - " 'industry_useful_demand_for_other_paper': 100.0,\n", - " 'industry_useful_demand_for_other_paper_electricity_efficiency': 31.246207044055573,\n", - " 'industry_useful_demand_for_other_paper_useable_heat_efficiency': 31.246207044055573,\n", - " 'other_useful_demand_electricity': 0.0,\n", - " 'other_useful_demand_non_energetic': 0.0,\n", - " 'other_useful_demand_useable_heat': 0.0,\n", - " 'transport_planes_efficiency': 0.0,\n", - " 'transport_ships_efficiency': 0.4,\n", - " 'transport_trains_efficiency': 0.1,\n", - " 'transport_vehicle_combustion_engine_efficiency': 0.4,\n", - " 'transport_vehicle_using_electricity_efficiency': 0.3,\n", - " 'transport_vehicle_using_hydrogen_efficiency': 0.3,\n", - " 'transport_freight_train_using_coal_share': 0.0,\n", - " 'transport_freight_train_using_diesel_mix_share': 0.66,\n", - " 'transport_freight_train_using_electricity_share': 98.68,\n", - " 'transport_freight_train_using_hydrogen_share': 0.66,\n", - " 'transport_freight_trains_share': 1.7501397973,\n", - " 'transport_ship_using_ammonia_share': 0.0,\n", - " 'transport_ship_using_diesel_mix_share': 64.68,\n", - " 'transport_ship_using_electricity_share': 9.93,\n", - " 'transport_ship_using_hydrogen_share': 16.66,\n", - " 'transport_ship_using_lng_mix_share': 8.73,\n", - " 'transport_ships_share': 19.9593814327,\n", - " 'transport_truck_using_compressed_natural_gas_share': 2.33,\n", - " 'transport_truck_using_diesel_mix_share': 29.15,\n", - " 'transport_truck_using_electricity_share': 45.07,\n", - " 'transport_truck_using_gasoline_mix_share': 0.0,\n", - " 'transport_truck_using_hydrogen_share': 19.12,\n", - " 'transport_truck_using_lng_mix_share': 4.33,\n", - " 'transport_trucks_share': 77.6037449859,\n", - " 'transport_useful_demand_freight_tonne_kms': 0.5,\n", - " 'transport_van_using_compressed_natural_gas_share': 0.0,\n", - " 'transport_van_using_diesel_mix_share': 23.2,\n", - " 'transport_van_using_electricity_share': 74.81,\n", - " 'transport_van_using_gasoline_mix_share': 0.44,\n", - " 'transport_van_using_hydrogen_share': 0.0,\n", - " 'transport_van_using_lpg_share': 1.55,\n", - " 'transport_vans_share': 0.6867337843,\n", - " 'transport_rail_mixer_diesel_diesel_share': 55.24,\n", - " 'transport_road_mixer_diesel_biodiesel_share': 44.81,\n", - " 'transport_road_mixer_diesel_diesel_share': 55.19,\n", - " 'transport_road_mixer_gasoline_ethanol_share': 45.69,\n", - " 'transport_road_mixer_gasoline_gasoline_share': 54.31,\n", - " 'transport_road_mixer_lng_bio_lng_share': 33.0,\n", - " 'transport_road_mixer_lng_lng_share': 67.0,\n", - " 'transport_shipping_mixer_diesel_bio_ethanol_share': 0.0,\n", - " 'transport_shipping_mixer_diesel_bio_lng_share': 33.0,\n", - " 'transport_shipping_mixer_diesel_biodiesel_share': 14.7,\n", - " 'transport_shipping_mixer_diesel_diesel_share': 52.3,\n", - " 'transport_shipping_mixer_diesel_heavy_fuel_oil_share': 0.0,\n", - " 'transport_shipping_mixer_diesel_lng_share': 0.0,\n", - " 'transport_shipping_mixer_lng_bio_lng_share': 42.67,\n", - " 'transport_shipping_mixer_lng_lng_share': 57.33,\n", - " 'transport_bicycle_using_electricity_share': 40.67,\n", - " 'transport_bicycle_using_human_power_share': 59.33,\n", - " 'transport_bicycles_share': 8.5,\n", - " 'transport_bus_using_compressed_natural_gas_share': 0.0,\n", - " 'transport_bus_using_diesel_mix_share': 0.0,\n", - " 'transport_bus_using_electricity_share': 96.67,\n", - " 'transport_bus_using_gasoline_mix_share': 0.0,\n", - " 'transport_bus_using_hydrogen_share': 3.33,\n", - " 'transport_bus_using_lng_share': 0.0,\n", - " 'transport_busses_share': 7.34,\n", - " 'transport_car_using_compressed_natural_gas_share': 0.0,\n", - " 'transport_car_using_diesel_mix_share': 0.0,\n", - " 'transport_car_using_electricity_share': 67.97,\n", - " 'transport_car_using_gasoline_mix_share': 28.27,\n", - " 'transport_car_using_hydrogen_share': 3.76,\n", - " 'transport_car_using_lpg_share': 0.0,\n", - " 'transport_cars_share': 69.0717377,\n", - " 'transport_motorcycle_using_electricity_share': 63.0,\n", - " 'transport_motorcycle_using_gasoline_mix_share': 37.0,\n", - " 'transport_motorcycles_share': 2.9115407598,\n", - " 'transport_passenger_train_using_coal_share': 0.0,\n", - " 'transport_passenger_train_using_diesel_mix_share': 0.7,\n", - " 'transport_passenger_train_using_electricity_share': 98.6,\n", - " 'transport_passenger_train_using_hydrogen_share': 0.7,\n", - " 'transport_passenger_trains_share': 12.0,\n", - " 'transport_rail_mixer_diesel_biodiesel_share': 44.76,\n", - " 'transport_plane_using_bio_ethanol_share': 0.0,\n", - " 'transport_plane_using_electricity_share': 16.7,\n", - " 'transport_plane_using_gasoline_share': 3.28,\n", - " 'transport_plane_using_hydrogen_share': 16.7,\n", - " 'transport_plane_using_kerosene_share': 63.32,\n", - " 'transport_planes_share': 0.0787128481,\n", - " 'transport_trams_share': 0.0980087341,\n", - " 'transport_useful_demand_passenger_kms': 1.0,\n", - " 'demand_of_molecules_direct_air_capture_co2': 0.0,\n", - " 'share_of_energy_chp_supercritical_ccs_ht_waste_mix': 0.0,\n", - " 'share_of_energy_hydrogen_autothermal_reformer_ccs_must_run': 0.0,\n", - " 'share_of_energy_hydrogen_biomass_gasification_ccs': 100.0,\n", - " 'share_of_energy_hydrogen_steam_methane_reformer_ccs_must_run': 100.0,\n", - " 'share_of_energy_power_combined_cycle_ccs_coal': 0.0,\n", - " 'share_of_energy_power_combined_cycle_ccs_network_gas': 0.0,\n", - " 'share_of_energy_power_supercritical_ccs_waste_mix': 0.0,\n", - " 'share_of_energy_power_ultra_supercritical_ccs_coal': 0.0,\n", - " 'share_of_energy_power_ultra_supercritical_oxyfuel_ccs_lignite': 0.0,\n", - " 'share_of_industry_chemicals_fertilizers_captured_combustion_co2': 0.0,\n", - " 'share_of_industry_chemicals_fertilizers_captured_processes_co2': 65.0,\n", - " 'share_of_industry_chemicals_other_captured_co2': 0.0,\n", - " 'share_of_industry_chemicals_refineries_captured_co2': 0.0,\n", - " 'share_of_industry_other_food_captured_co2': 0.0,\n", - " 'share_of_industry_other_paper_captured_co2': 0.0,\n", - " 'share_of_industry_steel_captured_co2': 0.0,\n", - " 'share_of_energy_steel_chemical_feedstock_coal_gas': 0.0,\n", - " 'share_of_energy_steel_energy_production_coal_gas': 100.0,\n", - " 'share_of_molecules_transport_pipelines_co2': 50.0,\n", - " 'share_of_molecules_transport_ships_co2': 50.0,\n", - " 'demand_of_molecules_offshore_sequestration_co2': 5.9,\n", - " 'demand_of_molecules_other_utilisation_co2': 2.342574,\n", - " 'output_of_energy_production_synthetic_methanol': 0.0,\n", - " 'share_of_molecules_other_utilisation_delayed_emitted_co2': 100.0,\n", - " 'share_of_molecules_other_utilisation_delayed_indefinitely_co2': 0.0,\n", - " 'co2_emissions_of_imported_ammonia_future': 348.3870984,\n", - " 'co2_emissions_of_imported_hydrogen_future': 0.0,\n", - " 'change_in_energetic_emissions_other_ghg_agriculture': 117.0,\n", - " 'change_in_energetic_emissions_other_ghg_buildings': 100.0,\n", - " 'change_in_energetic_emissions_other_ghg_energy': 100.0,\n", - " 'change_in_energetic_emissions_other_ghg_households': 100.0,\n", - " 'change_in_energetic_emissions_other_ghg_industry': 34.0,\n", - " 'change_in_energetic_emissions_other_ghg_transport': 20.0,\n", - " 'change_in_indirect_emissions_co2': 100.0,\n", - " 'change_in_non_energetic_emissions_co2_agriculture_manure': 50.0,\n", - " 'change_in_non_energetic_emissions_co2_agriculture_soil_cultivation': 50.0,\n", - " 'change_in_non_energetic_emissions_co2_chemical_industry': 66.66666667,\n", - " 'change_in_non_energetic_emissions_co2_other_industry': 40.0,\n", - " 'change_in_non_energetic_emissions_co2_waste_management': 50.0,\n", - " 'change_in_non_energetic_emissions_other_ghg_agriculture_fermentation': 48.0,\n", - " 'change_in_non_energetic_emissions_other_ghg_agriculture_manure': 102.0,\n", - " 'change_in_non_energetic_emissions_other_ghg_agriculture_other': 48.0,\n", - " 'change_in_non_energetic_emissions_other_ghg_agriculture_soil_cultivation': 64.0,\n", - " 'change_in_non_energetic_emissions_other_ghg_chemical_industry': 34.0,\n", - " 'change_in_non_energetic_emissions_other_ghg_other_industry': 34.0,\n", - " 'change_in_non_energetic_emissions_other_ghg_waste_management': 34.0,\n", - " 'battery_capacity_always_on_solar_pv_solar_radiation': 100.0,\n", - " 'battery_capacity_always_on_wind_turbine_inland': 100.0,\n", - " 'capacity_of_energy_flexibility_flow_batteries_electricity': 6500.0,\n", - " 'capacity_of_energy_flexibility_hv_opac_electricity': 0.0,\n", - " 'capacity_of_energy_flexibility_mv_batteries_electricity': 18500.0,\n", - " 'capacity_of_energy_flexibility_pumped_storage_electricity': 0.0,\n", - " 'capacity_of_energy_heat_flexibility_p2h_boiler_electricity': 4500.0,\n", - " 'capacity_of_energy_heat_flexibility_p2h_heatpump_electricity': 3500.0,\n", - " 'capacity_of_energy_hydrogen_flexibility_p2g_electricity': 14475.0,\n", - " 'connection_capacity_always_on_solar_pv_solar_radiation': 25.0,\n", - " 'connection_capacity_always_on_wind_turbine_inland': 75.0,\n", - " 'settings_enable_storage_optimisation_energy_flexibility_flow_batteries_electricity': 1.0,\n", - " 'settings_enable_storage_optimisation_energy_flexibility_hv_opac_electricity': 0.0,\n", - " 'settings_enable_storage_optimisation_energy_flexibility_mv_batteries_electricity': 1.0,\n", - " 'settings_enable_storage_optimisation_energy_flexibility_pumped_storage_electricity': 0.0,\n", - " 'volume_of_energy_flexibility_flow_batteries_electricity': 41.052631579,\n", - " 'wta_of_energy_flexibility_flow_batteries_electricity': 6.4285714286,\n", - " 'wta_of_energy_flexibility_hv_opac_electricity': 5.375,\n", - " 'wta_of_energy_flexibility_mv_batteries_electricity': 4.9411764706,\n", - " 'wta_of_energy_flexibility_pumped_storage_electricity': 5.5,\n", - " 'wtp_of_agriculture_flexibility_p2h_electricity': 22.0,\n", - " 'wtp_of_energy_flexibility_flow_batteries_electricity': 4.5,\n", - " 'wtp_of_energy_flexibility_hv_opac_electricity': 4.3,\n", - " 'wtp_of_energy_flexibility_mv_batteries_electricity': 4.2,\n", - " 'wtp_of_energy_flexibility_pumped_storage_electricity': 4.4,\n", - " 'wtp_of_energy_heat_flexibility_p2h_boiler_electricity': 25.0,\n", - " 'wtp_of_energy_heat_flexibility_p2h_heatpump_electricity': 25.0,\n", - " 'wtp_of_energy_hydrogen_flexibility_p2g_electricity': 30.0,\n", - " 'flexibility_heat_pump_space_heating_cop_cutoff_gas': 2.6,\n", - " 'flexibility_heat_pump_water_heating_cop_cutoff': 6.0,\n", - " 'households_flexibility_consumer_electricity_price': 22.5,\n", - " 'households_flexibility_consumer_gas_price': 81.4,\n", - " 'households_flexibility_p2p_electricity_market_penetration': 30.0,\n", - " 'settings_enable_storage_optimisation_households_flexibility_p2p_electricity': 'optimizing_storage',\n", - " 'wta_of_households_flexibility_p2p_electricity': 10.0,\n", - " 'wtp_of_households_flexibility_p2p_electricity': 5.0,\n", - " 'electricity_interconnector_1_capacity': 4400.0,\n", - " 'electricity_interconnector_1_co2_emissions_future': 0.0,\n", - " 'electricity_interconnector_1_co2_emissions_present': 0.0,\n", - " 'electricity_interconnector_1_export_availability': 100.0,\n", - " 'electricity_interconnector_1_import_availability': 100.0,\n", - " 'electricity_interconnector_1_marginal_costs': 37.5999984001,\n", - " 'electricity_interconnector_10_capacity': 0.0,\n", - " 'electricity_interconnector_10_co2_emissions_future': 370.0000008,\n", - " 'electricity_interconnector_10_co2_emissions_present': 370.0000008,\n", - " 'electricity_interconnector_10_export_availability': 100.0,\n", - " 'electricity_interconnector_10_import_availability': 100.0,\n", - " 'electricity_interconnector_10_marginal_costs': 37.5999984001,\n", - " 'electricity_interconnector_11_capacity': 0.0,\n", - " 'electricity_interconnector_11_co2_emissions_future': 370.0000008,\n", - " 'electricity_interconnector_11_co2_emissions_present': 370.0000008,\n", - " 'electricity_interconnector_11_export_availability': 100.0,\n", - " 'electricity_interconnector_11_import_availability': 100.0,\n", - " 'electricity_interconnector_11_marginal_costs': 37.5999984001,\n", - " 'electricity_interconnector_12_capacity': 0.0,\n", - " 'electricity_interconnector_12_co2_emissions_future': 370.0000008,\n", - " 'electricity_interconnector_12_co2_emissions_present': 370.0000008,\n", - " 'electricity_interconnector_12_export_availability': 100.0,\n", - " 'electricity_interconnector_12_import_availability': 100.0,\n", - " 'electricity_interconnector_12_marginal_costs': 37.5999984001,\n", - " 'electricity_interconnector_2_capacity': 6000.0,\n", - " 'electricity_interconnector_2_co2_emissions_future': 369.0,\n", - " 'electricity_interconnector_2_co2_emissions_present': 370.0000008,\n", - " 'electricity_interconnector_2_export_availability': 100.0,\n", - " 'electricity_interconnector_2_import_availability': 100.0,\n", - " 'electricity_interconnector_2_marginal_costs': 37.5999984001,\n", - " 'electricity_interconnector_3_capacity': 700.0,\n", - " 'electricity_interconnector_3_co2_emissions_future': 0.0,\n", - " 'electricity_interconnector_3_co2_emissions_present': 370.0000008,\n", - " 'electricity_interconnector_3_export_availability': 100.0,\n", - " 'electricity_interconnector_3_import_availability': 100.0,\n", - " 'electricity_interconnector_3_marginal_costs': 37.5999984001,\n", - " 'electricity_interconnector_4_capacity': 0.0,\n", - " 'electricity_interconnector_4_co2_emissions_future': 0.0,\n", - " 'electricity_interconnector_4_co2_emissions_present': 370.0000008,\n", - " 'electricity_interconnector_4_export_availability': 100.0,\n", - " 'electricity_interconnector_4_import_availability': 100.0,\n", - " 'electricity_interconnector_4_marginal_costs': 37.5999984001,\n", - " 'electricity_interconnector_5_capacity': 700.0,\n", - " 'electricity_interconnector_5_co2_emissions_future': 0.0,\n", - " 'electricity_interconnector_5_co2_emissions_present': 370.0000008,\n", - " 'electricity_interconnector_5_export_availability': 100.0,\n", - " 'electricity_interconnector_5_import_availability': 100.0,\n", - " 'electricity_interconnector_5_marginal_costs': 37.5999984001,\n", - " 'electricity_interconnector_6_capacity': 0.0,\n", - " 'electricity_interconnector_6_co2_emissions_future': 0.0,\n", - " 'electricity_interconnector_6_co2_emissions_present': 370.0000008,\n", - " 'electricity_interconnector_6_export_availability': 100.0,\n", - " 'electricity_interconnector_6_import_availability': 100.0,\n", - " 'electricity_interconnector_6_marginal_costs': 37.5999984001,\n", - " 'electricity_interconnector_7_capacity': 1000.0,\n", - " 'electricity_interconnector_7_co2_emissions_future': 0.0,\n", - " 'electricity_interconnector_7_co2_emissions_present': 370.0000008,\n", - " 'electricity_interconnector_7_export_availability': 100.0,\n", - " 'electricity_interconnector_7_import_availability': 100.0,\n", - " 'electricity_interconnector_7_marginal_costs': 37.5999984001,\n", - " 'electricity_interconnector_8_capacity': 2000.0,\n", - " 'electricity_interconnector_8_co2_emissions_future': 0.0,\n", - " 'electricity_interconnector_8_co2_emissions_present': 370.0000008,\n", - " 'electricity_interconnector_8_export_availability': 100.0,\n", - " 'electricity_interconnector_8_import_availability': 100.0,\n", - " 'electricity_interconnector_8_marginal_costs': 37.5999984001,\n", - " 'electricity_interconnector_9_capacity': 0.0,\n", - " 'electricity_interconnector_9_co2_emissions_future': 370.0000008,\n", - " 'electricity_interconnector_9_co2_emissions_present': 370.0000008,\n", - " 'electricity_interconnector_9_export_availability': 100.0,\n", - " 'electricity_interconnector_9_import_availability': 100.0,\n", - " 'electricity_interconnector_9_marginal_costs': 37.5999984001,\n", - " 'capacity_of_industry_chemical_flexibility_load_shifting_electricity': 35.0,\n", - " 'capacity_of_industry_metal_flexibility_load_shifting_electricity': 35.0,\n", - " 'capacity_of_industry_other_flexibility_load_shifting_electricity': 35.0,\n", - " 'capacity_of_industry_other_ict_flexibility_load_shifting_electricity': 30.0,\n", - " 'deficit_limit_of_industry_chemical_flexibility_load_shifting_electricity': 72.0,\n", - " 'deficit_limit_of_industry_metal_flexibility_load_shifting_electricity': 72.0,\n", - " 'deficit_limit_of_industry_other_flexibility_load_shifting_electricity': 72.0,\n", - " 'deficit_limit_of_industry_other_ict_flexibility_load_shifting_electricity': 24.0,\n", - " 'input_capacity_of_industry_chemical_flexibility_load_shifting_electricity': 35.0,\n", - " 'input_capacity_of_industry_metal_flexibility_load_shifting_electricity': 35.0,\n", - " 'input_capacity_of_industry_other_flexibility_load_shifting_electricity': 35.0,\n", - " 'input_capacity_of_industry_other_ict_flexibility_load_shifting_electricity': 30.0,\n", - " 'wta_of_industry_chemical_flexibility_load_shifting_electricity': 100.0,\n", - " 'wta_of_industry_metal_flexibility_load_shifting_electricity': 100.0,\n", - " 'wta_of_industry_other_flexibility_load_shifting_electricity': 100.0,\n", - " 'wta_of_industry_other_ict_flexibility_load_shifting_electricity': 100.0,\n", - " 'wtp_of_industry_chemicals_fertilizers_flexibility_p2h_electricity': 22.0,\n", - " 'wtp_of_industry_chemicals_other_flexibility_p2h_electricity': 22.0,\n", - " 'wtp_of_industry_chemicals_refineries_flexibility_p2h_electricity': 22.0,\n", - " 'wtp_of_industry_other_food_flexibility_p2h_electricity': 22.0,\n", - " 'wtp_of_industry_other_paper_flexibility_p2h_electricity': 22.0,\n", - " 'flexibility_residual_load_curve_moving_average': 72.0,\n", - " 'curtailment_of_buildings_solar_pv_solar_radiation': 55.0,\n", - " 'curtailment_of_energy_power_solar_pv_offshore': 55.0,\n", - " 'curtailment_of_energy_power_solar_pv_solar_radiation': 55.0,\n", - " 'curtailment_of_households_solar_pv_solar_radiation': 45.0,\n", - " 'settings_enable_storage_optimisation_transport_car_flexibility_p2p_electricity': 1.0,\n", - " 'transport_bus_using_electricity_availability': 0.0,\n", - " 'transport_car_using_electricity_availability': 17.5,\n", - " 'transport_car_using_electricity_custom_profile_charging_share': 100.0,\n", - " 'transport_car_using_electricity_fast_charging_share': 0.0,\n", - " 'transport_car_using_electricity_home_charging_share': 0.0,\n", - " 'transport_car_using_electricity_public_charging_share': 0.0,\n", - " 'transport_car_using_electricity_work_charging_share': 0.0,\n", - " 'transport_truck_using_electricity_availability': 0.0,\n", - " 'transport_van_using_electricity_availability': 0.0,\n", - " 'wta_of_transport_car_flexibility_p2p_electricity': 10.0,\n", - " 'wtp_of_transport_car_flexibility_p2p_electricity': 5.0,\n", - " 'flexibility_outdoor_temperature': 0.2125175493,\n", - " 'settings_weather_curve_set': 'default',\n", - " 'flh_of_energy_hydrogen_wind_turbine_offshore': 4000.0,\n", - " 'flh_of_energy_power_wind_turbine_coastal': 3200.000003,\n", - " 'flh_of_energy_power_wind_turbine_coastal_user_curve': 3200.000003,\n", - " 'flh_of_energy_power_wind_turbine_inland': 3200.000003,\n", - " 'flh_of_energy_power_wind_turbine_inland_user_curve': 3200.000003,\n", - " 'flh_of_energy_power_wind_turbine_offshore': 4750.000003461496,\n", - " 'flh_of_energy_power_wind_turbine_offshore_user_curve': 4750.000003461496,\n", - " 'flh_of_solar_pv_solar_radiation': 1012.334936,\n", - " 'flh_of_solar_pv_solar_radiation_user_curve': 1012.334936,\n", - " 'initial_updates_interconnector_curves': 0.0,\n", - " 'initial_updates_interconnector_prices': 0.0,\n", - " 'settings_enable_merit_order': 1.0,\n", - " 'energy_mix_capacity_per_unit_wind_turbine_inland': 3.0,\n", - " 'external_coupling_energy_production_synthetic_kerosene_demand': 0.0,\n", - " 'external_coupling_energy_production_synthetic_methanol_demand': 0.0,\n", - " 'external_coupling_molecules_other_utilisation_demand': 3.29209488358461,\n", - " 'external_coupling_industry_chemical_fertilizers_burner_coal_share': 0.0,\n", - " 'external_coupling_industry_chemical_fertilizers_burner_crude_oil_share': 0.0,\n", - " 'external_coupling_industry_chemical_fertilizers_burner_hydrogen_share': 50.6732983222066,\n", - " 'external_coupling_industry_chemical_fertilizers_burner_network_gas_share': 46.3963051101963,\n", - " 'external_coupling_industry_chemical_fertilizers_burner_wood_pellets_share': 0.0,\n", - " 'external_coupling_industry_chemical_fertilizers_combustion_ccus_capture_potential': 100.0,\n", - " 'external_coupling_industry_chemical_fertilizers_combustion_ccus_captured_co2': 0.0,\n", - " 'external_coupling_industry_chemical_fertilizers_combustion_ccus_electricity_use': 0.229514968527056,\n", - " 'external_coupling_industry_chemical_fertilizers_electricity': 475.351855618162,\n", - " 'external_coupling_industry_chemical_fertilizers_non_energetic_coal_share': 0.0,\n", - " 'external_coupling_industry_chemical_fertilizers_non_energetic_crude_oil_share': 0.0,\n", - " 'external_coupling_industry_chemical_fertilizers_non_energetic_hydrogen_share': 83.584159630957,\n", - " 'external_coupling_industry_chemical_fertilizers_non_energetic_network_gas_share': 16.415840369043,\n", - " 'external_coupling_industry_chemical_fertilizers_non_energetic_wood_pellets_share': 0.0,\n", - " 'external_coupling_industry_chemical_fertilizers_p2h_capacity': 0.0,\n", - " 'external_coupling_industry_chemical_fertilizers_processes_ccus_capture_potential': 100.0,\n", - " 'external_coupling_industry_chemical_fertilizers_processes_ccus_captured_co2': 100.0,\n", - " 'external_coupling_industry_chemical_fertilizers_processes_ccus_electricity_use': 0.229514968527056,\n", - " 'external_coupling_industry_chemical_fertilizers_residual_heat_share': 18.520027186658,\n", - " 'external_coupling_industry_chemical_fertilizers_steam_hot_water_share': 2.93039656759714,\n", - " 'external_coupling_industry_chemical_fertilizers_total_excluding_electricity': 94.05517289851,\n", - " 'external_coupling_industry_chemical_fertilizers_total_useable_heat_share': 15.4869053374752,\n", - " 'external_coupling_energy_chemical_other_transformation_external_coupling_node_ammonia_input_share': 0.0,\n", - " 'external_coupling_energy_chemical_other_transformation_external_coupling_node_ammonia_output_share': 0.0,\n", - " 'external_coupling_energy_chemical_other_transformation_external_coupling_node_crude_oil_input_share': 0.0,\n", - " 'external_coupling_energy_chemical_other_transformation_external_coupling_node_diesel_output_share': 0.0,\n", - " 'external_coupling_energy_chemical_other_transformation_external_coupling_node_electricity_input_share': 0.0,\n", - " 'external_coupling_energy_chemical_other_transformation_external_coupling_node_gasoline_output_share': 0.0,\n", - " 'external_coupling_energy_chemical_other_transformation_external_coupling_node_greengas_input_share': 0.0,\n", - " 'external_coupling_energy_chemical_other_transformation_external_coupling_node_greengas_output_share': 2.5662122493785073,\n", - " 'external_coupling_energy_chemical_other_transformation_external_coupling_node_heavy_fuel_oil_output_share': 0.0,\n", - " 'external_coupling_energy_chemical_other_transformation_external_coupling_node_hydrogen_input_share': 0.0,\n", - " 'external_coupling_energy_chemical_other_transformation_external_coupling_node_hydrogen_output_share': 28.3253720842459,\n", - " 'external_coupling_energy_chemical_other_transformation_external_coupling_node_kerosene_output_share': 0.0,\n", - " 'external_coupling_energy_chemical_other_transformation_external_coupling_node_loss_output_share': 0.0,\n", - " 'external_coupling_energy_chemical_other_transformation_external_coupling_node_lpg_output_share': 0.0,\n", - " 'external_coupling_energy_chemical_other_transformation_external_coupling_node_methanol_input_share': 0.0,\n", - " 'external_coupling_energy_chemical_other_transformation_external_coupling_node_methanol_output_share': 0.0,\n", - " 'external_coupling_energy_chemical_other_transformation_external_coupling_node_natural_gas_input_share': 0.0,\n", - " 'external_coupling_energy_chemical_other_transformation_external_coupling_node_natural_gas_output_share': 69.10841566637559,\n", - " 'external_coupling_energy_chemical_other_transformation_external_coupling_node_not_defined_input_share': 100.0,\n", - " 'external_coupling_energy_chemical_other_transformation_external_coupling_node_steam_hot_water_input_share': 0.0,\n", - " 'external_coupling_energy_chemical_other_transformation_external_coupling_node_total_demand': 145.02798773572636,\n", - " 'external_coupling_energy_chemical_other_transformation_external_coupling_node_waste_mix_input_share': 0.0,\n", - " 'external_coupling_energy_chemical_other_transformation_external_coupling_node_wood_pellets_input_share': 0.0,\n", - " 'external_coupling_industry_chemical_other_burner_coal_share': 0.0,\n", - " 'external_coupling_industry_chemical_other_burner_crude_oil_share': 4.15140444622588,\n", - " 'external_coupling_industry_chemical_other_burner_hydrogen_share': 38.163121847451,\n", - " 'external_coupling_industry_chemical_other_burner_network_gas_share': 44.1422501321988,\n", - " 'external_coupling_industry_chemical_other_burner_wood_pellets_share': 0.0,\n", - " 'external_coupling_industry_chemical_other_ccus_capture_potential': 100.0,\n", - " 'external_coupling_industry_chemical_other_ccus_captured_co2': 6.11129600882643,\n", - " 'external_coupling_industry_chemical_other_ccus_electricity_use': 0.124294429762498,\n", - " 'external_coupling_industry_chemical_other_electricity': 277.599988376699,\n", - " 'external_coupling_industry_chemical_other_heater_electricity_share': 0.0,\n", - " 'external_coupling_industry_chemical_other_heatpump_water_water_electricity_share': 0.0,\n", - " 'external_coupling_industry_chemical_other_non_energetic_coal_share': 0.0,\n", - " 'external_coupling_industry_chemical_other_non_energetic_crude_oil_share': 56.6568218227432,\n", - " 'external_coupling_industry_chemical_other_non_energetic_hydrogen_share': 6.74856929748537,\n", - " 'external_coupling_industry_chemical_other_non_energetic_network_gas_share': 11.3846995406033,\n", - " 'external_coupling_industry_chemical_other_non_energetic_wood_pellets_share': 25.2099093391682,\n", - " 'external_coupling_industry_chemical_other_p2h_capacity': 522.183604084003,\n", - " 'external_coupling_industry_chemical_other_residual_heat_share': 15.4433084571522,\n", - " 'external_coupling_industry_chemical_other_steam_hot_water_share': 13.5432235741243,\n", - " 'external_coupling_industry_chemical_other_steam_recompression_electricity_share': 0.0,\n", - " 'external_coupling_industry_chemical_other_total_non_energetic': 45.7297367916897,\n", - " 'external_coupling_industry_chemical_other_useable_heat': 33.9923944655155,\n", - " 'external_coupling_energy_chemical_refineries_transformation_external_coupling_node_ammonia_input_share': 0.0,\n", - " 'external_coupling_energy_chemical_refineries_transformation_external_coupling_node_ammonia_output_share': 0.0,\n", - " 'external_coupling_energy_chemical_refineries_transformation_external_coupling_node_crude_oil_input_share': 100.0,\n", - " 'external_coupling_energy_chemical_refineries_transformation_external_coupling_node_diesel_output_share': 28.8754407902916,\n", - " 'external_coupling_energy_chemical_refineries_transformation_external_coupling_node_electricity_input_share': 0.0,\n", - " 'external_coupling_energy_chemical_refineries_transformation_external_coupling_node_gasoline_output_share': 6.23530119017238,\n", - " 'external_coupling_energy_chemical_refineries_transformation_external_coupling_node_greengas_input_share': 0.0,\n", - " 'external_coupling_energy_chemical_refineries_transformation_external_coupling_node_greengas_output_share': 0.0,\n", - " 'external_coupling_energy_chemical_refineries_transformation_external_coupling_node_heavy_fuel_oil_output_share': 14.7654523402727,\n", - " 'external_coupling_energy_chemical_refineries_transformation_external_coupling_node_hydrogen_input_share': 0.0,\n", - " 'external_coupling_energy_chemical_refineries_transformation_external_coupling_node_hydrogen_output_share': 0.0,\n", - " 'external_coupling_energy_chemical_refineries_transformation_external_coupling_node_kerosene_output_share': 14.7523934475443,\n", - " 'external_coupling_energy_chemical_refineries_transformation_external_coupling_node_loss_output_share': 0.0,\n", - " 'external_coupling_energy_chemical_refineries_transformation_external_coupling_node_lpg_output_share': 2.25239174447402,\n", - " 'external_coupling_energy_chemical_refineries_transformation_external_coupling_node_methanol_input_share': 0.0,\n", - " 'external_coupling_energy_chemical_refineries_transformation_external_coupling_node_methanol_output_share': 0.0,\n", - " 'external_coupling_energy_chemical_refineries_transformation_external_coupling_node_natural_gas_input_share': 0.0,\n", - " 'external_coupling_energy_chemical_refineries_transformation_external_coupling_node_natural_gas_output_share': 0.0,\n", - " 'external_coupling_energy_chemical_refineries_transformation_external_coupling_node_not_defined_input_share': 0.0,\n", - " 'external_coupling_energy_chemical_refineries_transformation_external_coupling_node_not_defined_output_share': 3.58796542047281,\n", - " 'external_coupling_energy_chemical_refineries_transformation_external_coupling_node_steam_hot_water_input_share': 0.0,\n", - " 'external_coupling_energy_chemical_refineries_transformation_external_coupling_node_total_demand': 1889.958629148879,\n", - " 'external_coupling_energy_chemical_refineries_transformation_external_coupling_node_waste_mix_input_share': 0.0,\n", - " 'external_coupling_energy_chemical_refineries_transformation_external_coupling_node_wood_pellets_input_share': 0.0,\n", - " 'external_coupling_industry_chemical_refineries_burner_coal_share': 0.0,\n", - " 'external_coupling_industry_chemical_refineries_burner_crude_oil_share': 8.55291494528118,\n", - " 'external_coupling_industry_chemical_refineries_burner_hydrogen_share': 80.3160063659157,\n", - " 'external_coupling_industry_chemical_refineries_burner_network_gas_share': 10.7766510976364,\n", - " 'external_coupling_industry_chemical_refineries_burner_wood_pellets_share': 0.0,\n", - " 'external_coupling_industry_chemical_refineries_ccus_capture_potential': 100.0,\n", - " 'external_coupling_industry_chemical_refineries_ccus_captured_co2': 100.0,\n", - " 'external_coupling_industry_chemical_refineries_ccus_electricity_use': 0.030510017109512,\n", - " 'external_coupling_industry_chemical_refineries_electricity': 105.933269100756,\n", - " 'external_coupling_industry_chemical_refineries_p2h_capacity': 455.06386174751,\n", - " 'external_coupling_industry_chemical_refineries_residual_heat_share': 28.7767084382513,\n", - " 'external_coupling_industry_chemical_refineries_steam_hot_water_share': 0.354427591166749,\n", - " 'external_coupling_industry_chemical_refineries_useable_heat': 62.5640162386857,\n", - " 'external_coupling_energy_distribution_coal_gas_chemical_feedstock_share': 0.0,\n", - " 'external_coupling_energy_distribution_coal_gas_energy_production_share': 99.99,\n", - " 'external_coupling_energy_distribution_coal_gas_final_demand_share': 0.010000000000005116,\n", - " 'external_coupling_industry_metal_steel_blastfurnace_bof_share': 0.0,\n", - " 'external_coupling_industry_metal_steel_ccus_capture_potential': 100.0,\n", - " 'external_coupling_industry_metal_steel_ccus_captured_co2': 52.5547546810199,\n", - " 'external_coupling_industry_metal_steel_ccus_electricity_use': 0.57,\n", - " 'external_coupling_industry_metal_steel_cyclonefurnace_bof_share': 0.0,\n", - " 'external_coupling_industry_metal_steel_dri_hydrogen_share': 0.0,\n", - " 'external_coupling_industry_metal_steel_dri_network_gas_share': 0.0,\n", - " 'external_coupling_industry_metal_steel_efficiency': 7.31410052617644,\n", - " 'external_coupling_industry_metal_steel_energetic_coal_gas_share': 0.0,\n", - " 'external_coupling_industry_metal_steel_energetic_coal_share': 7.76726831346224,\n", - " 'external_coupling_industry_metal_steel_energetic_cokes_share': 0.0,\n", - " 'external_coupling_industry_metal_steel_energetic_crude_oil_share': 0.0,\n", - " 'external_coupling_industry_metal_steel_energetic_electricity_share': 22.7926669333398,\n", - " 'external_coupling_industry_metal_steel_energetic_hydrogen_share': 23.6267669198569,\n", - " 'external_coupling_industry_metal_steel_energetic_network_gas_share': 45.813297833341,\n", - " 'external_coupling_industry_metal_steel_energetic_steam_hot_water_share': 0.0,\n", - " 'external_coupling_industry_metal_steel_energetic_wood_pellets_share': 0.0,\n", - " 'external_coupling_industry_metal_steel_external_coupling_share': 100.0,\n", - " 'external_coupling_industry_metal_steel_fixed_om_costs': 316684316.043427,\n", - " 'external_coupling_industry_metal_steel_investment_costs': 4309820685.96129,\n", - " 'external_coupling_industry_metal_steel_scrap_hbi_eaf_share': 0.0,\n", - " 'external_coupling_industry_metal_steel_technical_lifetime': 19.0,\n", - " 'external_coupling_industry_metal_steel_total_demand': 97.33,\n", - " 'external_coupling_industry_metal_steel_wacc': 0.08,\n", - " 'external_coupling_biogenic_waste_max_demand': 27.8493698855199,\n", - " 'external_coupling_energy_chp_supercritical_ccs_waste_mix_captured_co2': 58.8235294117647,\n", - " 'external_coupling_energy_chp_supercritical_ccs_waste_mix_electrical_efficiency': 15.3827945040516,\n", - " 'external_coupling_energy_chp_supercritical_ccs_waste_mix_heat_efficiency': 1.23427917997262,\n", - " 'external_coupling_energy_chp_supercritical_waste_mix_capacity': 133.04294558354,\n", - " 'external_coupling_energy_chp_supercritical_waste_mix_electrical_efficiency': 15.3827945040516,\n", - " 'external_coupling_energy_chp_supercritical_waste_mix_heat_efficiency': 1.23427917997262,\n", - " 'external_coupling_non_biogenic_waste_max_demand': 23.3679305603854,\n", - " 'external_coupling_waste_mix_biogenic_waste_share': 54.9694458639823,\n", - " 'external_coupling_waste_mix_non_biogenic_waste_share': 45.0305541360177,\n", - " 'capacity_of_energy_imported_ammonia_baseload': 0.0,\n", - " 'max_demand_of_biogenic_waste': 21.38166,\n", - " 'max_demand_of_dry_biomass': 62.16023,\n", - " 'max_demand_of_oily_biomass': 10.5,\n", - " 'max_demand_of_wet_biomass': 109.873,\n", - " 'co_firing_biocoal_share': 0.0,\n", - " 'co_firing_coal_share': 100.0,\n", - " 'capacity_of_energy_chp_ultra_supercritical_coal': 0.0,\n", - " 'capacity_of_energy_chp_ultra_supercritical_cofiring_coal': 0.0,\n", - " 'capacity_of_energy_power_combined_cycle_coal': 0.0,\n", - " 'capacity_of_energy_power_supercritical_coal': 0.0,\n", - " 'capacity_of_energy_power_ultra_supercritical_coal': 0.0,\n", - " 'capacity_of_energy_power_ultra_supercritical_cofiring_coal': 0.0,\n", - " 'capacity_of_energy_power_ultra_supercritical_lignite': 0.0,\n", - " 'capacity_of_energy_chp_combined_cycle_network_gas': 56.0,\n", - " 'capacity_of_energy_chp_local_engine_network_gas': 0.0,\n", - " 'capacity_of_energy_power_combined_cycle_network_gas': 5280.0,\n", - " 'capacity_of_energy_power_engine_network_gas': 0.0,\n", - " 'capacity_of_energy_power_turbine_network_gas': 9.0,\n", - " 'capacity_of_energy_power_ultra_supercritical_network_gas': 11.0,\n", - " 'capacity_of_energy_power_nuclear_gen2_uranium_oxide': 0.0,\n", - " 'capacity_of_energy_power_nuclear_gen3_uranium_oxide': 0.0,\n", - " 'capacity_of_energy_power_nuclear_small_modular_reactor_uranium_oxide': 0.0,\n", - " 'merit_order_subtype_of_energy_power_nuclear_uranium_oxide': 0.0,\n", - " 'capacity_of_energy_power_engine_diesel': 0.0,\n", - " 'capacity_of_energy_power_ultra_supercritical_crude_oil': 0.0,\n", - " 'energy_mixer_for_gas_power_fuel_bio_oil_share': 0.0,\n", - " 'energy_mixer_for_gas_power_fuel_crude_oil_share': 7.9728731956,\n", - " 'energy_mixer_for_gas_power_fuel_natural_gas_share': 92.0271268045,\n", - " 'fuel_production_coal': 0.0,\n", - " 'fuel_production_crude_oil': 0.0,\n", - " 'fuel_production_lignite': 0.0,\n", - " 'fuel_production_natural_gas': 26.0,\n", - " 'fuel_production_uranium_oxide': 0.0,\n", - " 'green_gas_total_share': 37.7,\n", - " 'natural_gas_total_share': 62.3,\n", - " 'energy_biogas_fermentation_share': 50.0,\n", - " 'energy_greengas_gasification_dry_biomass_share': 25.0259259,\n", - " 'energy_greengas_gasification_wet_biomass_share': 24.9740741,\n", - " 'energy_regasification_lng_share': 1.4544312017,\n", - " 'energy_treatment_natural_gas_share': 98.5455687984,\n", - " 'capacity_of_agriculture_chp_engine_biogas': 0.0,\n", - " 'capacity_of_agriculture_chp_engine_network_gas_dispatchable': 207.0,\n", - " 'capacity_of_agriculture_chp_engine_network_gas_must_run': 0.0,\n", - " 'capacity_of_agriculture_chp_wood_pellets': 0.0,\n", - " 'capacity_of_energy_heat_burner_ht_coal': 0.0,\n", - " 'capacity_of_energy_heat_burner_ht_crude_oil': 0.0,\n", - " 'capacity_of_energy_heat_burner_ht_hydrogen': 0.0,\n", - " 'capacity_of_energy_heat_burner_ht_network_gas': 1000.0,\n", - " 'capacity_of_energy_heat_burner_ht_waste_mix': 0.0,\n", - " 'capacity_of_energy_heat_burner_ht_wood_pellets': 200.0,\n", - " 'capacity_of_energy_heat_heatpump_water_water_ht_electricity': 1500.0,\n", - " 'capacity_of_energy_heat_solar_ht_solar_thermal': 2500.0,\n", - " 'capacity_of_energy_heat_well_deep_ht_geothermal': 1400.0,\n", - " 'volume_of_ht_imported_heat': 0.0,\n", - " 'volume_of_ht_residual_heat': 25.714236461457922,\n", - " 'energy_heat_network_storage_ht_loss_share': 30.0000068049,\n", - " 'energy_heat_network_storage_ht_steam_hot_water_output_capacity_share': 200.0,\n", - " 'heat_storage_enabled_ht': 1.0,\n", - " 'energy_heat_distribution_ht_loss_share': 15.0,\n", - " 'co2_emissions_of_imported_heat': 35.97,\n", - " 'capacity_of_industry_chp_combined_cycle_gas_power_fuelmix': 478.0,\n", - " 'capacity_of_industry_chp_engine_gas_power_fuelmix': 62.0,\n", - " 'capacity_of_industry_chp_turbine_gas_power_fuelmix': 647.0,\n", - " 'capacity_of_industry_chp_turbine_hydrogen': 0.0,\n", - " 'capacity_of_industry_chp_ultra_supercritical_coal': 0.0,\n", - " 'capacity_of_industry_chp_wood_pellets': 0.0,\n", - " 'capacity_of_industry_heat_burner_coal': 0.0,\n", - " 'capacity_of_industry_heat_burner_crude_oil': 0.0,\n", - " 'capacity_of_industry_heat_burner_hydrogen': 0.0,\n", - " 'capacity_of_industry_heat_burner_lignite': 0.0,\n", - " 'capacity_of_industry_heat_well_geothermal': 0.0,\n", - " 'capacity_of_energy_hydrogen_ammonia_reformer_must_run': 0.0,\n", - " 'capacity_of_energy_hydrogen_autothermal_reformer_must_run': 0.0,\n", - " 'capacity_of_energy_hydrogen_biomass_gasification': 201.59999999999997,\n", - " 'capacity_of_energy_hydrogen_solar_pv_solar_radiation': 0.0,\n", - " 'capacity_of_energy_hydrogen_steam_methane_reformer_must_run': 2422.711775504852,\n", - " 'capacity_of_energy_hydrogen_wind_turbine_offshore': 2640.0,\n", - " 'capacity_of_energy_imported_hydrogen_baseload': 5459.0,\n", - " 'capacity_of_energy_hydrogen_storage_salt_cavern': 428.64444379753854,\n", - " 'volume_of_energy_hydrogen_storage_salt_cavern': 11.151657026441995,\n", - " 'energy_hydrogen_distribution_compressed_trucks_share': 1.0,\n", - " 'energy_hydrogen_transport_pipelines_share': 99.0,\n", - " 'agriculture_bio_kerosene_in_crude_oil_share': 0.0,\n", - " 'agriculture_biodiesel_in_crude_oil_share': 53.5628368135,\n", - " 'agriculture_diesel_in_crude_oil_share': 42.975430639,\n", - " 'agriculture_kerosene_in_crude_oil_share': 0.0,\n", - " 'agriculture_lpg_in_crude_oil_share': 3.4617325477,\n", - " 'agriculture_other_bio_oil_in_crude_oil_share': 0.0,\n", - " 'agriculture_other_oil_in_crude_oil_share': 0.0,\n", - " 'buildings_bio_kerosene_in_crude_oil_share': 0.0,\n", - " 'buildings_biodiesel_in_crude_oil_share': 0.0,\n", - " 'buildings_diesel_in_crude_oil_share': 54.3798623065,\n", - " 'buildings_kerosene_in_crude_oil_share': 0.114329433,\n", - " 'buildings_lpg_in_crude_oil_share': 42.7920472269,\n", - " 'buildings_other_bio_oil_in_crude_oil_share': 2.3839238021,\n", - " 'buildings_other_oil_in_crude_oil_share': 0.3298372318,\n", - " 'households_bio_kerosene_in_crude_oil_share': 0.0,\n", - " 'households_biodiesel_in_crude_oil_share': 0.0,\n", - " 'households_diesel_in_crude_oil_share': 20.1462563364,\n", - " 'households_kerosene_in_crude_oil_share': 15.5535857733,\n", - " 'households_lpg_in_crude_oil_share': 64.3001578904,\n", - " 'households_other_bio_oil_in_crude_oil_share': 0.0,\n", - " 'households_other_oil_in_crude_oil_share': 0.0,\n", - " 'industry_bio_kerosene_in_crude_oil_share': 0.0,\n", - " 'industry_biodiesel_in_crude_oil_share': 0.035695073,\n", - " 'industry_diesel_in_crude_oil_share': 0.006797406,\n", - " 'industry_kerosene_in_crude_oil_share': 0.0,\n", - " 'industry_lpg_in_crude_oil_share': 0.526530287,\n", - " 'industry_other_bio_oil_in_crude_oil_share': 33.70284273,\n", - " 'industry_other_oil_in_crude_oil_share': 65.72813451,\n", - " 'capacity_of_energy_chp_local_engine_biogas': 105.2173341123,\n", - " 'capacity_of_energy_chp_local_wood_pellets_dispatchable': 49.4967396253,\n", - " 'capacity_of_energy_power_geothermal': 0.0,\n", - " 'capacity_of_energy_power_hydro_river': 37.0013815462,\n", - " 'capacity_of_energy_power_combined_cycle_hydrogen': 3520.0,\n", - " 'capacity_of_energy_power_turbine_hydrogen': 7040.0,\n", - " 'capacity_of_buildings_solar_pv_solar_radiation': 44300.0,\n", - " 'capacity_of_energy_battery_solar_pv_solar_radiation': 0.0,\n", - " 'capacity_of_energy_power_solar_pv_offshore': 0.0,\n", - " 'capacity_of_energy_power_solar_pv_solar_radiation': 41800.0,\n", - " 'capacity_of_households_solar_pv_solar_radiation': 40000.0,\n", - " 'capacity_of_energy_chp_supercritical_waste_mix': 894.6490091117,\n", - " 'capacity_of_energy_power_supercritical_waste_mix': 0.0,\n", - " 'capacity_of_energy_battery_wind_turbine_inland': 0.0,\n", - " 'capacity_of_energy_power_wind_turbine_coastal': 4000.0,\n", - " 'capacity_of_energy_power_wind_turbine_inland': 8100.0,\n", - " 'capacity_of_energy_power_wind_turbine_offshore': 32000.0}" - ] - }, - "execution_count": 18, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# We also distinguish between inputs and user_values. Usually user values are more interesting:\n", - "user_values = scenario.user_values()\n", - "# Check if we can make this also to_dataframe\n", - "user_values" - ] - }, - { - "cell_type": "code", - "execution_count": 19, - "id": "fca99519", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Empty DataFrame\n", - "Columns: []\n", - "Index: []\n" - ] - } - ], - "source": [ - "# Execute gqueries to fetch data from ETM (incl. units)\n", - "gqueries = scenario.results()\n", - "print(gqueries)" - ] - }, - { - "cell_type": "markdown", - "id": "fd5267db", - "metadata": {}, - "source": [ - "There are no default gqueries, you need to specify them yourself - hence the empty dataframe ." - ] - }, - { - "cell_type": "code", - "execution_count": 20, - "id": "ed984767", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - " future\n", - "gquery unit \n", - "dashboard_emissions factor -0.780545\n" - ] - } - ], - "source": [ - "scenario.add_queries([\"dashboard_emissions\"])\n", - "gqueries = scenario.results()\n", - "print(gqueries)" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "5b0d61ec", - "metadata": {}, - "outputs": [], - "source": [ - "# Optional: Fetch hourly electricity price profiles from ETM\n", - "custom_curves = scenario.custom_curves_series()\n", - "for key in custom_curves: print(key)" - ] - }, - { - "cell_type": "markdown", - "id": "ddd8fa69", - "metadata": {}, - "source": [ - "#TODO: Discuss\n", - "\n", - "Do you want a convenient way to only get the custom curves related to electricity price? Or are you more interested in the carrier curves? " - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "6a57a5bf", - "metadata": {}, - "outputs": [ - { - "data": { - "text/plain": [ - "{'merit_order': agriculture_chp_engine_biogas.output (MW) \\\n", - " 0 0.0 \n", - " 1 0.0 \n", - " 2 0.0 \n", - " 3 0.0 \n", - " 4 0.0 \n", - " ... ... \n", - " 8755 0.0 \n", - " 8756 0.0 \n", - " 8757 0.0 \n", - " 8758 0.0 \n", - " 8759 0.0 \n", - " \n", - " agriculture_chp_engine_network_gas_dispatchable.output (MW) \\\n", - " 0 0.0 \n", - " 1 0.0 \n", - " 2 0.0 \n", - " 3 0.0 \n", - " 4 0.0 \n", - " ... ... \n", - " 8755 0.0 \n", - " 8756 0.0 \n", - " 8757 0.0 \n", - " 8758 0.0 \n", - " 8759 0.0 \n", - " \n", - " agriculture_chp_engine_network_gas_must_run.output (MW) \\\n", - " 0 0.0 \n", - " 1 0.0 \n", - " 2 0.0 \n", - " 3 0.0 \n", - " 4 0.0 \n", - " ... ... \n", - " 8755 0.0 \n", - " 8756 0.0 \n", - " 8757 0.0 \n", - " 8758 0.0 \n", - " 8759 0.0 \n", - " \n", - " agriculture_chp_wood_pellets.output (MW) \\\n", - " 0 0.0 \n", - " 1 0.0 \n", - " 2 0.0 \n", - " 3 0.0 \n", - " 4 0.0 \n", - " ... ... \n", - " 8755 0.0 \n", - " 8756 0.0 \n", - " 8757 0.0 \n", - " 8758 0.0 \n", - " 8759 0.0 \n", - " \n", - " agriculture_flexibility_p2h_hydrogen_electricity.output (MW) \\\n", - " 0 0.0 \n", - " 1 0.0 \n", - " 2 0.0 \n", - " 3 0.0 \n", - " 4 0.0 \n", - " ... ... \n", - " 8755 0.0 \n", - " 8756 0.0 \n", - " 8757 0.0 \n", - " 8758 0.0 \n", - " 8759 0.0 \n", - " \n", - " agriculture_flexibility_p2h_network_gas_electricity.output (MW) \\\n", - " 0 0.0 \n", - " 1 0.0 \n", - " 2 0.0 \n", - " 3 0.0 \n", - " 4 0.0 \n", - " ... ... \n", - " 8755 0.0 \n", - " 8756 0.0 \n", - " 8757 0.0 \n", - " 8758 0.0 \n", - " 8759 0.0 \n", - " \n", - " buildings_solar_pv_solar_radiation.output (MW) \\\n", - " 0 0.0 \n", - " 1 0.0 \n", - " 2 0.0 \n", - " 3 0.0 \n", - " 4 0.0 \n", - " ... ... \n", - " 8755 0.0 \n", - " 8756 0.0 \n", - " 8757 0.0 \n", - " 8758 0.0 \n", - " 8759 0.0 \n", - " \n", - " energy_battery_solar_electricity.output (MW) \\\n", - " 0 0.0 \n", - " 1 0.0 \n", - " 2 0.0 \n", - " 3 0.0 \n", - " 4 0.0 \n", - " ... ... \n", - " 8755 0.0 \n", - " 8756 0.0 \n", - " 8757 0.0 \n", - " 8758 0.0 \n", - " 8759 0.0 \n", - " \n", - " energy_battery_wind_electricity.output (MW) \\\n", - " 0 0.0 \n", - " 1 0.0 \n", - " 2 0.0 \n", - " 3 0.0 \n", - " 4 0.0 \n", - " ... ... \n", - " 8755 0.0 \n", - " 8756 0.0 \n", - " 8757 0.0 \n", - " 8758 0.0 \n", - " 8759 0.0 \n", - " \n", - " energy_chp_coal_gas.output (MW) ... \\\n", - " 0 0.0 ... \n", - " 1 0.0 ... \n", - " 2 0.0 ... \n", - " 3 0.0 ... \n", - " 4 0.0 ... \n", - " ... ... ... \n", - " 8755 0.0 ... \n", - " 8756 0.0 ... \n", - " 8757 0.0 ... \n", - " 8758 0.0 ... \n", - " 8759 0.0 ... \n", - " \n", - " transport_motorcycle_using_electricity.input (MW) \\\n", - " 0 6.0868 \n", - " 1 2.2664 \n", - " 2 1.0671 \n", - " 3 0.7418 \n", - " 4 0.7422 \n", - " ... ... \n", - " 8755 29.4081 \n", - " 8756 19.4375 \n", - " 8757 11.9942 \n", - " 8758 10.6178 \n", - " 8759 9.7232 \n", - " \n", - " transport_passenger_train_using_electricity.input (MW) \\\n", - " 0 100.6524 \n", - " 1 37.4773 \n", - " 2 17.6460 \n", - " 3 12.2670 \n", - " 4 12.2725 \n", - " ... ... \n", - " 8755 486.2939 \n", - " 8756 321.4203 \n", - " 8757 198.3364 \n", - " 8758 175.5763 \n", - " 8759 160.7839 \n", - " \n", - " transport_plane_using_electricity.input (MW) \\\n", - " 0 2.0642 \n", - " 1 2.0642 \n", - " 2 2.0642 \n", - " 3 2.0642 \n", - " 4 2.0642 \n", - " ... ... \n", - " 8755 2.0642 \n", - " 8756 2.0642 \n", - " 8757 2.0642 \n", - " 8758 2.0642 \n", - " 8759 2.0642 \n", - " \n", - " transport_ship_using_electricity.input (MW) \\\n", - " 0 29.8321 \n", - " 1 30.9370 \n", - " 2 30.9370 \n", - " 3 30.9370 \n", - " 4 30.9370 \n", - " ... ... \n", - " 8755 33.7494 \n", - " 8756 31.9414 \n", - " 8757 26.5174 \n", - " 8758 26.5174 \n", - " 8759 26.5174 \n", - " \n", - " transport_tram_using_electricity.input (MW) \\\n", - " 0 1.8122 \n", - " 1 0.6748 \n", - " 2 0.3177 \n", - " 3 0.2209 \n", - " 4 0.2210 \n", - " ... ... \n", - " 8755 8.7557 \n", - " 8756 5.7871 \n", - " 8757 3.5710 \n", - " 8758 3.1612 \n", - " 8759 2.8949 \n", - " \n", - " transport_truck_flexibility_p2p_electricity.input (MW) \\\n", - " 0 0.0 \n", - " 1 0.0 \n", - " 2 0.0 \n", - " 3 0.0 \n", - " 4 0.0 \n", - " ... ... \n", - " 8755 0.0 \n", - " 8756 0.0 \n", - " 8757 0.0 \n", - " 8758 0.0 \n", - " 8759 0.0 \n", - " \n", - " transport_truck_using_electricity.input (MW) \\\n", - " 0 301.1724 \n", - " 1 255.8993 \n", - " 2 255.7102 \n", - " 3 255.7102 \n", - " 4 255.7562 \n", - " ... ... \n", - " 8755 3632.1744 \n", - " 8756 3654.7956 \n", - " 8757 3290.3259 \n", - " 8758 2912.0708 \n", - " 8759 2633.8673 \n", - " \n", - " transport_van_flexibility_p2p_electricity.input (MW) \\\n", - " 0 0.0 \n", - " 1 0.0 \n", - " 2 0.0 \n", - " 3 0.0 \n", - " 4 0.0 \n", - " ... ... \n", - " 8755 0.0 \n", - " 8756 0.0 \n", - " 8757 0.0 \n", - " 8758 0.0 \n", - " 8759 0.0 \n", - " \n", - " transport_van_using_electricity.input (MW) deficit \n", - " 0 225.7143 0.0 \n", - " 1 183.4868 0.0 \n", - " 2 164.2823 0.0 \n", - " 3 152.3737 0.0 \n", - " 4 145.7294 0.0 \n", - " ... ... ... \n", - " 8755 1951.6292 0.0 \n", - " 8756 1756.9386 0.0 \n", - " 8757 1423.4249 0.0 \n", - " 8758 1141.5322 0.0 \n", - " 8759 1016.2915 0.0 \n", - " \n", - " [8760 rows x 284 columns],\n", - " 'electricity_price': Price (Euros)\n", - " 0 22.00\n", - " 1 22.00\n", - " 2 14.48\n", - " 3 0.01\n", - " 4 0.02\n", - " ... ...\n", - " 8755 0.01\n", - " 8756 0.01\n", - " 8757 0.01\n", - " 8758 0.02\n", - " 8759 0.00\n", - " \n", - " [8760 rows x 1 columns],\n", - " 'residual_load': Electricity imbalance (MW) Heat network imbalance (MW) \\\n", - " 0 -13983.316952 -7650.762461 \n", - " 1 -15074.662973 -2063.605451 \n", - " 2 -16392.624827 -236.749238 \n", - " 3 -18084.064350 -7257.637108 \n", - " 4 -18698.295084 -6777.697551 \n", - " ... ... ... \n", - " 8755 -10461.245439 -2908.084718 \n", - " 8756 -12120.991687 -3196.334417 \n", - " 8757 -14277.783965 -3698.939229 \n", - " 8758 -12769.564116 -4265.195281 \n", - " 8759 -14036.141852 -5382.621751 \n", - " \n", - " Network gas imbalance (MW) Hydrogen imbalance (MW) \\\n", - " 0 -4781.342416 -10122.196681 \n", - " 1 -3483.696797 -9409.232452 \n", - " 2 -3475.263835 -9413.765713 \n", - " 3 -4570.081283 -10137.602583 \n", - " 4 -4175.876527 -10138.862839 \n", - " ... ... ... \n", - " 8755 -1895.359218 -10120.066139 \n", - " 8756 -2098.834088 -10121.282579 \n", - " 8757 -2551.241935 -10122.752998 \n", - " 8758 -2865.165589 -10123.043235 \n", - " 8759 -3823.803492 -10123.672193 \n", - " \n", - " Network gas imbalance (short timescale) (MW) \\\n", - " 0 -1833.873449 \n", - " 1 -574.860579 \n", - " 2 -605.611833 \n", - " 3 -1739.687791 \n", - " 4 -1383.891692 \n", - " ... ... \n", - " 8755 1241.238351 \n", - " 8756 1013.073005 \n", - " 8757 519.009108 \n", - " 8758 160.843578 \n", - " 8759 -837.070806 \n", - " \n", - " Network gas imbalance (long timescale) (MW) \\\n", - " 0 -2947.468967 \n", - " 1 -2908.836218 \n", - " 2 -2869.652003 \n", - " 3 -2830.393493 \n", - " 4 -2791.984835 \n", - " ... ... \n", - " 8755 -3136.597568 \n", - " 8756 -3111.907093 \n", - " 8757 -3070.251043 \n", - " 8758 -3026.009167 \n", - " 8759 -2986.732687 \n", - " \n", - " Hydrogen imblanace (short timescale) (MW) \\\n", - " 0 -171.967531 \n", - " 1 529.822127 \n", - " 2 514.208089 \n", - " 3 -220.919672 \n", - " 4 -232.647398 \n", - " ... ... \n", - " 8755 -83.391025 \n", - " 8756 -103.105800 \n", - " 8757 -122.762259 \n", - " 8758 -140.510517 \n", - " 8759 -159.955285 \n", - " \n", - " Hydrogen imblanace (long timescale) (MW) \n", - " 0 -9950.229150 \n", - " 1 -9939.054580 \n", - " 2 -9927.973802 \n", - " 3 -9916.682911 \n", - " 4 -9906.215441 \n", - " ... ... \n", - " 8755 -10036.675114 \n", - " 8756 -10018.176778 \n", - " 8757 -9999.990739 \n", - " 8758 -9982.532718 \n", - " 8759 -9963.716908 \n", - " \n", - " [8760 rows x 8 columns]}" - ] - }, - "execution_count": 21, - "metadata": {}, - "output_type": "execute_result" - } - ], - "source": [ - "# Optional: Fetch hourly carrier profiles from ETM\n", - "output_curves = scenario.get_output_curves(carrier_type='electricity')\n", - "# Also serval carriers at ones. One carrier per sheet, with carrier name as sheet name\n", - "output_curves" - ] - }, - { - "cell_type": "markdown", - "id": "f29ee72f", - "metadata": {}, - "source": [ - "As you can see, this returns a dictionary of dataframes, including the merit_order, electricity_price and residual_load dataframes. If you want a specific output, just request it:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "5366a81c", - "metadata": {}, - "outputs": [], - "source": [ - "electricity_price = scenario.output_curve(curve_name='electricity_price')\n", - "# Also in it's own sheet\n", - "# Hydrogen price also in it's own sheet\n", - "\n", - "# Nice to have: also make other downloads like sankey and energy_flows available\n", - "electricity_price" - ] - }, - { - "cell_type": "markdown", - "id": "638116c5", - "metadata": {}, - "source": [ - "**Export scenarios to Excel**\n", - "\n", - "Just like with the original implementation, everything in the scenario can be exported to an excel file. This is done via a \"Scenario Packer\" which organises the data usefully to display via excel.\n", - "\n", - "This example is simplified in the sense that we just add everything in the scenario to the packer, but you can also add specific inputs, gqueries curves etc to a packer (see more examples in the scenario_to_excel notebook)." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "4266f27d", - "metadata": {}, - "outputs": [], - "source": [ - "from pyetm.models import ScenarioPacker\n", - "\n", - "packer = ScenarioPacker()\n", - "packer.add(scenario, scenario2, scenario3)\n", - "packer.to_excel('folder/my_excel.xlsx')\n", - "\n", - "# Specify explicitly what to export in to_excel\n", - "packer.to_excel('folder/my_excel.xlsx', include_curves=True)" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "pyetm-qKH2ozgc", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.9" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/examples/scenario_to_excel.ipynb b/examples/scenario_to_excel.ipynb deleted file mode 100644 index 6071b68..0000000 --- a/examples/scenario_to_excel.ipynb +++ /dev/null @@ -1,215 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "930300db", - "metadata": {}, - "source": [ - "## Preamble" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "4e9a9e7c", - "metadata": {}, - "outputs": [], - "source": [ - "from example_helpers import setup_notebook\n", - "from pyetm.models import Scenario\n", - "\n", - "setup_notebook()" - ] - }, - { - "cell_type": "markdown", - "id": "1f4414c0", - "metadata": {}, - "source": [ - "## Picking my scenario" - ] - }, - { - "cell_type": "markdown", - "id": "c3cd461f", - "metadata": {}, - "source": [ - "Use an API session ID to load up one of your scenarios.\n" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "c4f42def", - "metadata": {}, - "outputs": [], - "source": [ - "# Example beta scenario\n", - "scenario = Scenario.load(2690456)\n", - "\n", - "# Example pro scenario\n", - "# scenario = Scenario.load(1340415)" - ] - }, - { - "cell_type": "markdown", - "id": "8d946757", - "metadata": {}, - "source": [ - "## Create a Packer\n", - "\n", - "The scenario packer allows you to collect scenarios and define what information you want to extract from all of them. It helps to collect all info into dataframes or Excel.\n", - "\n", - "- **Main info** with `main_info()` you display all meta information about the scenarios, like area code and end years;\n", - "\n", - "- Input settings\n", - " - **Inputs** `inputs()` displays all inputs for the scenario including their unit, default and user-set values;\n", - " - **Custom curves** using `custom_curves()` you can retrieve and display the curves uploaded to the scenario;\n", - " - **Sortables** `sortables()` shows all user sortables set for the scenario, like heat network orders, etc;\n", - "- Outputs:\n", - " - **GQuery results** with `gquery_results()` you can retrieve the queries that were prepared for the scenarios;\n", - " - **Output curves** `output_curves()` downloads and shows the carreir curves requested for the scenarios.\n", - "\n", - "\n", - "Scenarios can be added to a packer in multiple ways:\n", - "\n", - "- `add(*scenarios)` will ready the scenario for all 6 packs (or Excel tabs) described above\n", - "- `add_inputs(*scenarios)` will only ready the scenarios for the inputs dataframe or Excel tab\n", - "- `add_sortables(*scenarios)` will only ready the scenarios for the sortables dataframe or Excel tab\n", - "- `add_custom_curves(*scenarios)` will only ready the scenarios for the custom_curves dataframe or Excel tab\n", - "- `add_output_curves(*scenarios)` will only ready the scenarios for the output_curves dataframe or Excel tab\n", - "\n", - "If a scenario is added in any of the individual packs, it will be automatically added for main info and prepared gqueries." - ] - }, - { - "cell_type": "markdown", - "id": "a9d9214a", - "metadata": {}, - "source": [ - "-----------------\n", - "\n", - "NOTE: the packer currently only works for a single scenario!\n", - "\n", - "-----------------" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "fa8ac6ab", - "metadata": {}, - "outputs": [], - "source": [ - "from pyetm.models import ScenarioPacker\n", - "\n", - "packer = ScenarioPacker()\n", - "\n", - "scenario = Scenario.load(2690456)\n", - "scenario2 = Scenario.load(2690455)\n", - "# Ready the scenario for inputs\n", - "packer.add_inputs(scenario)\n", - "packer.add_inputs(scenario2)\n", - "\n", - "# Main info is automatically readied\n", - "print(packer.inputs())\n", - "print(packer.main_info())\n" - ] - }, - { - "cell_type": "markdown", - "id": "ed1cefd4", - "metadata": {}, - "source": [ - "When you add gqueries to a scenario which is connected to the packer, these queries will be readied for the pack." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "739e2a12", - "metadata": {}, - "outputs": [], - "source": [ - "scenario.add_queries(\n", - " [\"dashboard_total_costs\", \"dashboard_co2_emissions_versus_start_year\"]\n", - ")\n", - "\n", - "print(packer.gquery_results())" - ] - }, - { - "cell_type": "markdown", - "id": "c924ac3d", - "metadata": {}, - "source": [ - "Queries can be added on-the-go. When the packer is exported to Excel, all requested queries will show up." - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "ce5e2bdb", - "metadata": {}, - "outputs": [], - "source": [ - "scenario.add_queries(\n", - " [\"dashboard_emissions\"]\n", - ")\n", - "\n", - "scenario2.add_queries(\n", - " [\"dashboard_emissions\"]\n", - ")\n", - "\n", - "packer.to_excel('my_excel.xlsx')" - ] - }, - { - "cell_type": "markdown", - "id": "68ce86c3", - "metadata": {}, - "source": [ - "Output curves:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "bffd54b8", - "metadata": {}, - "outputs": [], - "source": [ - "packer.add_output_curves(scenario)\n", - "packer.add_output_curves(scenario2)\n", - "packer.add_custom_curves(scenario)\n", - "packer.add_custom_curves(scenario2)\n", - "packer.add_sortables(scenario)\n", - "packer.add_sortables(scenario2)\n", - "\n", - "\n", - "# packer.to_excel('testing_output_curves.xlsx')" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "pyetm-qKH2ozgc", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.9" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/examples/serialization_deserialization.ipynb b/examples/serialization_deserialization.ipynb deleted file mode 100644 index b2b130a..0000000 --- a/examples/serialization_deserialization.ipynb +++ /dev/null @@ -1,241 +0,0 @@ -{ - "cells": [ - { - "cell_type": "markdown", - "id": "a1b2c3d4", - "metadata": {}, - "source": [ - "# Input Serialization/Deserialization\n", - "\n", - "This notebook demonstrates the serialization and deserialization capabilities of the `Inputs` model.\n", - "We'll load a scenario, serialize its inputs to a DataFrame, deserialize them back to objects,\n", - "and verify with some stats.\n", - "\n", - "## Setup" - ] - }, - { - "cell_type": "code", - "execution_count": 6, - "id": "setup_cell", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Environment setup complete\n", - " Using ETM API at https://beta.engine.energytransitionmodel.com/api/v3\n", - " Token loaded? True\n", - "API connection ready\n" - ] - } - ], - "source": [ - "from example_helpers import setup_notebook\n", - "from pyetm.models import Scenario\n", - "\n", - "setup_notebook()\n", - "scenario = Scenario.load(2690288)\n", - "scenario.update_user_values({\n", - " \"climate_relevant_co2_biomass_gas_future\": 20.0\n", - "})" - ] - }, - { - "cell_type": "markdown", - "id": "original_data", - "metadata": {}, - "source": [ - "## Step 1: Examine Original Inputs\n", - "\n", - "Let's look at the original inputs and collect some basic statistics:" - ] - }, - { - "cell_type": "code", - "execution_count": 7, - "id": "examine_original", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Some inputs:\n", - " climate_relevant_co2_biomass_gas_future (%): default=0.0, user=20.0\n", - " climate_relevant_co2_biomass_gas_present (%): default=0.0, user=None\n", - " climate_relevant_co2_biomass_liquid_future (%): default=0.0, user=None\n" - ] - } - ], - "source": [ - "original_inputs = scenario.inputs\n", - "\n", - "print(\"Some inputs:\")\n", - "for i, input in enumerate(original_inputs):\n", - " if i < 3:\n", - " print(f\" {input.key} ({input.unit}): default={input.default}, user={input.user}\")\n", - " elif i == 3:\n", - " break" - ] - }, - { - "cell_type": "markdown", - "id": "serialization", - "metadata": {}, - "source": [ - "## Step 2: Serialize to DataFrame\n", - "\n", - "Convert the inputs to a DataFrame for inspection and storage:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "serialize", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "DataFrame shape: (1318, 5)\n", - "DataFrame index: ['input', 'unit']\n", - "DataFrame columns: ['user', 'default', 'min', 'max', 'disabled']\n", - " user default min max \\\n", - "input unit \n", - "climate_relevant_co2_biomass_gas_future % 20.0 0.0 0.0 100.0 \n", - "climate_relevant_co2_biomass_gas_present % NaN 0.0 0.0 100.0 \n", - "climate_relevant_co2_biomass_liquid_future % NaN 0.0 0.0 100.0 \n", - "climate_relevant_co2_biomass_liquid_present % NaN 0.0 0.0 100.0 \n", - "climate_relevant_co2_biomass_solid_future % NaN 0.0 0.0 100.0 \n", - "\n", - " disabled \n", - "input unit \n", - "climate_relevant_co2_biomass_gas_future % False \n", - "climate_relevant_co2_biomass_gas_present % False \n", - "climate_relevant_co2_biomass_liquid_future % False \n", - "climate_relevant_co2_biomass_liquid_present % False \n", - "climate_relevant_co2_biomass_solid_future % False \n" - ] - } - ], - "source": [ - "# Serialize to DataFrame with multiple columns\n", - "df = original_inputs.to_dataframe(columns=[\"user\", \"default\", \"min\", \"max\", \"disabled\"])\n", - "\n", - "print(f\"DataFrame shape: {df.shape}\")\n", - "print(f\"DataFrame index: {df.index.names}\")\n", - "print(f\"DataFrame columns: {list(df.columns)}\")\n", - "\n", - "print(df.head())" - ] - }, - { - "cell_type": "markdown", - "id": "deserialization", - "metadata": {}, - "source": [ - "## Step 3: Deserialize from DataFrame\n", - "\n", - "Convert the DataFrame back to Input objects:" - ] - }, - { - "cell_type": "code", - "execution_count": null, - "id": "deserialize", - "metadata": {}, - "outputs": [ - { - "name": "stdout", - "output_type": "stream", - "text": [ - "DataFrame shape: (1318, 1)\n", - "DataFrame index: ['input', 'unit']\n", - "DataFrame columns: ['user']\n", - " user\n", - "input unit \n", - "climate_relevant_co2_biomass_gas_future % 20.0\n", - "climate_relevant_co2_biomass_gas_present % NaN\n", - "climate_relevant_co2_biomass_liquid_future % NaN\n", - "climate_relevant_co2_biomass_liquid_present % NaN\n", - "climate_relevant_co2_biomass_solid_future % NaN\n", - " user default min max \\\n", - "input unit \n", - "climate_relevant_co2_biomass_gas_future % 20.0 0.0 0.0 100.0 \n", - "climate_relevant_co2_biomass_gas_present % NaN 0.0 0.0 100.0 \n", - "climate_relevant_co2_biomass_liquid_future % NaN 0.0 0.0 100.0 \n", - "climate_relevant_co2_biomass_liquid_present % NaN 0.0 0.0 100.0 \n", - "climate_relevant_co2_biomass_solid_future % NaN 0.0 0.0 100.0 \n", - "\n", - " disabled \n", - "input unit \n", - "climate_relevant_co2_biomass_gas_future % False \n", - "climate_relevant_co2_biomass_gas_present % False \n", - "climate_relevant_co2_biomass_liquid_future % False \n", - "climate_relevant_co2_biomass_liquid_present % False \n", - "climate_relevant_co2_biomass_solid_future % False \n", - "\n", - "No deserialization warnings!\n", - "Same inputs:\n", - " climate_relevant_co2_biomass_gas_future (%): default=0.0, user=20.0\n", - " climate_relevant_co2_biomass_gas_present (%): default=0.0, user=None\n", - " climate_relevant_co2_biomass_liquid_future (%): default=0.0, user=None\n" - ] - } - ], - "source": [ - "scenario.set_user_values_from_dataframe(df)\n", - "reconstructed_inputs = scenario.inputs\n", - "\n", - "print(f\"DataFrame shape: {reconstructed_inputs.to_dataframe().shape}\")\n", - "print(f\"DataFrame index: {reconstructed_inputs.to_dataframe().index.names}\")\n", - "print(f\"DataFrame columns: {list(reconstructed_inputs.to_dataframe().columns)}\")\n", - "\n", - "print(reconstructed_inputs.to_dataframe().head())\n", - "\n", - "df_again = reconstructed_inputs.to_dataframe(columns=[\"user\", \"default\", \"min\", \"max\", \"disabled\"])\n", - "\n", - "print(df_again.head())\n", - "\n", - "# Check for warnings during deserialization\n", - "if reconstructed_inputs.warnings:\n", - " print(f\"\\nDeserialization warnings ({len(reconstructed_inputs.warnings)}):\")\n", - " reconstructed_inputs.show_warnings()\n", - "else:\n", - " print(\"\\nNo deserialization warnings!\")\n", - "\n", - "\n", - "print(\"Same inputs:\")\n", - "for i, input in enumerate(reconstructed_inputs):\n", - " if i < 3:\n", - " print(f\" {input.key} ({input.unit}): default={input.default}, user={input.user}\")\n", - " elif i == 3:\n", - " break" - ] - } - ], - "metadata": { - "kernelspec": { - "display_name": "pyetm-FWBOHxp3", - "language": "python", - "name": "python3" - }, - "language_info": { - "codemirror_mode": { - "name": "ipython", - "version": 3 - }, - "file_extension": ".py", - "mimetype": "text/x-python", - "name": "python", - "nbconvert_exporter": "python", - "pygments_lexer": "ipython3", - "version": "3.12.11" - } - }, - "nbformat": 4, - "nbformat_minor": 5 -} diff --git a/poetry.lock b/poetry.lock new file mode 100644 index 0000000..19a8b5d --- /dev/null +++ b/poetry.lock @@ -0,0 +1,3036 @@ +# This file is automatically @generated by Poetry 2.1.4 and should not be changed by hand. + +[[package]] +name = "annotated-types" +version = "0.7.0" +description = "Reusable constraint types to use with typing.Annotated" +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, + {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, +] + +[[package]] +name = "anyio" +version = "4.10.0" +description = "High-level concurrency and networking framework on top of asyncio or Trio" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "anyio-4.10.0-py3-none-any.whl", hash = "sha256:60e474ac86736bbfd6f210f7a61218939c318f43f9972497381f1c5e930ed3d1"}, + {file = "anyio-4.10.0.tar.gz", hash = "sha256:3f3fae35c96039744587aa5b8371e7e8e603c0702999535961dd336026973ba6"}, +] + +[package.dependencies] +idna = ">=2.8" +sniffio = ">=1.1" +typing_extensions = {version = ">=4.5", markers = "python_version < \"3.13\""} + +[package.extras] +trio = ["trio (>=0.26.1)"] + +[[package]] +name = "appnope" +version = "0.1.4" +description = "Disable App Nap on macOS >= 10.9" +optional = false +python-versions = ">=3.6" +groups = ["dev"] +markers = "platform_system == \"Darwin\"" +files = [ + {file = "appnope-0.1.4-py2.py3-none-any.whl", hash = "sha256:502575ee11cd7a28c0205f379b525beefebab9d161b7c964670864014ed7213c"}, + {file = "appnope-0.1.4.tar.gz", hash = "sha256:1de3860566df9caf38f01f86f65e0e13e379af54f9e4bee1e66b48f2efffd1ee"}, +] + +[[package]] +name = "argon2-cffi" +version = "25.1.0" +description = "Argon2 for Python" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "argon2_cffi-25.1.0-py3-none-any.whl", hash = "sha256:fdc8b074db390fccb6eb4a3604ae7231f219aa669a2652e0f20e16ba513d5741"}, + {file = "argon2_cffi-25.1.0.tar.gz", hash = "sha256:694ae5cc8a42f4c4e2bf2ca0e64e51e23a040c6a517a85074683d3959e1346c1"}, +] + +[package.dependencies] +argon2-cffi-bindings = "*" + +[[package]] +name = "argon2-cffi-bindings" +version = "21.2.0" +description = "Low-level CFFI bindings for Argon2" +optional = false +python-versions = ">=3.6" +groups = ["dev"] +markers = "python_version >= \"3.14\"" +files = [ + {file = "argon2-cffi-bindings-21.2.0.tar.gz", hash = "sha256:bb89ceffa6c791807d1305ceb77dbfacc5aa499891d2c55661c6459651fc39e3"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:ccb949252cb2ab3a08c02024acb77cfb179492d5701c7cbdbfd776124d4d2367"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9524464572e12979364b7d600abf96181d3541da11e23ddf565a32e70bd4dc0d"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b746dba803a79238e925d9046a63aa26bf86ab2a2fe74ce6b009a1c3f5c8f2ae"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:58ed19212051f49a523abb1dbe954337dc82d947fb6e5a0da60f7c8471a8476c"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:bd46088725ef7f58b5a1ef7ca06647ebaf0eb4baff7d1d0d177c6cc8744abd86"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-musllinux_1_1_i686.whl", hash = "sha256:8cd69c07dd875537a824deec19f978e0f2078fdda07fd5c42ac29668dda5f40f"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:f1152ac548bd5b8bcecfb0b0371f082037e47128653df2e8ba6e914d384f3c3e"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-win32.whl", hash = "sha256:603ca0aba86b1349b147cab91ae970c63118a0f30444d4bc80355937c950c082"}, + {file = "argon2_cffi_bindings-21.2.0-cp36-abi3-win_amd64.whl", hash = "sha256:b2ef1c30440dbbcba7a5dc3e319408b59676e2e039e2ae11a8775ecf482b192f"}, + {file = "argon2_cffi_bindings-21.2.0-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:e415e3f62c8d124ee16018e491a009937f8cf7ebf5eb430ffc5de21b900dad93"}, + {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3e385d1c39c520c08b53d63300c3ecc28622f076f4c2b0e6d7e796e9f6502194"}, + {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c3e3cc67fdb7d82c4718f19b4e7a87123caf8a93fde7e23cf66ac0337d3cb3f"}, + {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6a22ad9800121b71099d0fb0a65323810a15f2e292f2ba450810a7316e128ee5"}, + {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f9f8b450ed0547e3d473fdc8612083fd08dd2120d6ac8f73828df9b7d45bb351"}, + {file = "argon2_cffi_bindings-21.2.0-pp37-pypy37_pp73-win_amd64.whl", hash = "sha256:93f9bf70084f97245ba10ee36575f0c3f1e7d7724d67d8e5b08e61787c320ed7"}, + {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:3b9ef65804859d335dc6b31582cad2c5166f0c3e7975f324d9ffaa34ee7e6583"}, + {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d4966ef5848d820776f5f562a7d45fdd70c2f330c961d0d745b784034bd9f48d"}, + {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20ef543a89dee4db46a1a6e206cd015360e5a75822f76df533845c3cbaf72670"}, + {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ed2937d286e2ad0cc79a7087d3c272832865f779430e0cc2b4f3718d3159b0cb"}, + {file = "argon2_cffi_bindings-21.2.0-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:5e00316dabdaea0b2dd82d141cc66889ced0cdcbfa599e8b471cf22c620c329a"}, +] + +[package.dependencies] +cffi = ">=1.0.1" + +[package.extras] +dev = ["cogapp", "pre-commit", "pytest", "wheel"] +tests = ["pytest"] + +[[package]] +name = "argon2-cffi-bindings" +version = "25.1.0" +description = "Low-level CFFI bindings for Argon2" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +markers = "python_version < \"3.14\"" +files = [ + {file = "argon2_cffi_bindings-25.1.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:3d3f05610594151994ca9ccb3c771115bdb4daef161976a266f0dd8aa9996b8f"}, + {file = "argon2_cffi_bindings-25.1.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:8b8efee945193e667a396cbc7b4fb7d357297d6234d30a489905d96caabde56b"}, + {file = "argon2_cffi_bindings-25.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:3c6702abc36bf3ccba3f802b799505def420a1b7039862014a65db3205967f5a"}, + {file = "argon2_cffi_bindings-25.1.0-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a1c70058c6ab1e352304ac7e3b52554daadacd8d453c1752e547c76e9c99ac44"}, + {file = "argon2_cffi_bindings-25.1.0-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e2fd3bfbff3c5d74fef31a722f729bf93500910db650c925c2d6ef879a7e51cb"}, + {file = "argon2_cffi_bindings-25.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c4f9665de60b1b0e99bcd6be4f17d90339698ce954cfd8d9cf4f91c995165a92"}, + {file = "argon2_cffi_bindings-25.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ba92837e4a9aa6a508c8d2d7883ed5a8f6c308c89a4790e1e447a220deb79a85"}, + {file = "argon2_cffi_bindings-25.1.0-cp314-cp314t-win32.whl", hash = "sha256:84a461d4d84ae1295871329b346a97f68eade8c53b6ed9a7ca2d7467f3c8ff6f"}, + {file = "argon2_cffi_bindings-25.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:b55aec3565b65f56455eebc9b9f34130440404f27fe21c3b375bf1ea4d8fbae6"}, + {file = "argon2_cffi_bindings-25.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:87c33a52407e4c41f3b70a9c2d3f6056d88b10dad7695be708c5021673f55623"}, + {file = "argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:aecba1723ae35330a008418a91ea6cfcedf6d31e5fbaa056a166462ff066d500"}, + {file = "argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:2630b6240b495dfab90aebe159ff784d08ea999aa4b0d17efa734055a07d2f44"}, + {file = "argon2_cffi_bindings-25.1.0-cp39-abi3-macosx_11_0_arm64.whl", hash = "sha256:7aef0c91e2c0fbca6fc68e7555aa60ef7008a739cbe045541e438373bc54d2b0"}, + {file = "argon2_cffi_bindings-25.1.0-cp39-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1e021e87faa76ae0d413b619fe2b65ab9a037f24c60a1e6cc43457ae20de6dc6"}, + {file = "argon2_cffi_bindings-25.1.0-cp39-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d3e924cfc503018a714f94a49a149fdc0b644eaead5d1f089330399134fa028a"}, + {file = "argon2_cffi_bindings-25.1.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:c87b72589133f0346a1cb8d5ecca4b933e3c9b64656c9d175270a000e73b288d"}, + {file = "argon2_cffi_bindings-25.1.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:1db89609c06afa1a214a69a462ea741cf735b29a57530478c06eb81dd403de99"}, + {file = "argon2_cffi_bindings-25.1.0-cp39-abi3-win32.whl", hash = "sha256:473bcb5f82924b1becbb637b63303ec8d10e84c8d241119419897a26116515d2"}, + {file = "argon2_cffi_bindings-25.1.0-cp39-abi3-win_amd64.whl", hash = "sha256:a98cd7d17e9f7ce244c0803cad3c23a7d379c301ba618a5fa76a67d116618b98"}, + {file = "argon2_cffi_bindings-25.1.0-cp39-abi3-win_arm64.whl", hash = "sha256:b0fdbcf513833809c882823f98dc2f931cf659d9a1429616ac3adebb49f5db94"}, + {file = "argon2_cffi_bindings-25.1.0-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:6dca33a9859abf613e22733131fc9194091c1fa7cb3e131c143056b4856aa47e"}, + {file = "argon2_cffi_bindings-25.1.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:21378b40e1b8d1655dd5310c84a40fc19a9aa5e6366e835ceb8576bf0fea716d"}, + {file = "argon2_cffi_bindings-25.1.0-pp310-pypy310_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5d588dec224e2a83edbdc785a5e6f3c6cd736f46bfd4b441bbb5aa1f5085e584"}, + {file = "argon2_cffi_bindings-25.1.0-pp310-pypy310_pp73-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5acb4e41090d53f17ca1110c3427f0a130f944b896fc8c83973219c97f57b690"}, + {file = "argon2_cffi_bindings-25.1.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:da0c79c23a63723aa5d782250fbf51b768abca630285262fb5144ba5ae01e520"}, + {file = "argon2_cffi_bindings-25.1.0.tar.gz", hash = "sha256:b957f3e6ea4d55d820e40ff76f450952807013d361a65d7f28acc0acbf29229d"}, +] + +[package.dependencies] +cffi = {version = ">=1.0.1", markers = "python_version < \"3.14\""} + +[[package]] +name = "arrow" +version = "1.3.0" +description = "Better dates & times for Python" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "arrow-1.3.0-py3-none-any.whl", hash = "sha256:c728b120ebc00eb84e01882a6f5e7927a53960aa990ce7dd2b10f39005a67f80"}, + {file = "arrow-1.3.0.tar.gz", hash = "sha256:d4540617648cb5f895730f1ad8c82a65f2dad0166f57b75f3ca54759c4d67a85"}, +] + +[package.dependencies] +python-dateutil = ">=2.7.0" +types-python-dateutil = ">=2.8.10" + +[package.extras] +doc = ["doc8", "sphinx (>=7.0.0)", "sphinx-autobuild", "sphinx-autodoc-typehints", "sphinx_rtd_theme (>=1.3.0)"] +test = ["dateparser (==1.*)", "pre-commit", "pytest", "pytest-cov", "pytest-mock", "pytz (==2021.1)", "simplejson (==3.*)"] + +[[package]] +name = "astroid" +version = "3.3.11" +description = "An abstract syntax tree for Python with inference support." +optional = false +python-versions = ">=3.9.0" +groups = ["dev"] +files = [ + {file = "astroid-3.3.11-py3-none-any.whl", hash = "sha256:54c760ae8322ece1abd213057c4b5bba7c49818853fc901ef09719a60dbf9dec"}, + {file = "astroid-3.3.11.tar.gz", hash = "sha256:1e5a5011af2920c7c67a53f65d536d65bfa7116feeaf2354d8b94f29573bb0ce"}, +] + +[[package]] +name = "asttokens" +version = "3.0.0" +description = "Annotate AST trees with source code positions" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "asttokens-3.0.0-py3-none-any.whl", hash = "sha256:e3078351a059199dd5138cb1c706e6430c05eff2ff136af5eb4790f9d28932e2"}, + {file = "asttokens-3.0.0.tar.gz", hash = "sha256:0dcd8baa8d62b0c1d118b399b2ddba3c4aff271d0d7a9e0d4c1681c79035bbc7"}, +] + +[package.extras] +astroid = ["astroid (>=2,<4)"] +test = ["astroid (>=2,<4)", "pytest", "pytest-cov", "pytest-xdist"] + +[[package]] +name = "async-lru" +version = "2.0.5" +description = "Simple LRU cache for asyncio" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "async_lru-2.0.5-py3-none-any.whl", hash = "sha256:ab95404d8d2605310d345932697371a5f40def0487c03d6d0ad9138de52c9943"}, + {file = "async_lru-2.0.5.tar.gz", hash = "sha256:481d52ccdd27275f42c43a928b4a50c3bfb2d67af4e78b170e3e0bb39c66e5bb"}, +] + +[[package]] +name = "attrs" +version = "25.3.0" +description = "Classes Without Boilerplate" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "attrs-25.3.0-py3-none-any.whl", hash = "sha256:427318ce031701fea540783410126f03899a97ffc6f61596ad581ac2e40e3bc3"}, + {file = "attrs-25.3.0.tar.gz", hash = "sha256:75d7cefc7fb576747b2c81b4442d4d4a1ce0900973527c011d1030fd3bf4af1b"}, +] + +[package.extras] +benchmark = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-codspeed", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] +cov = ["cloudpickle ; platform_python_implementation == \"CPython\"", "coverage[toml] (>=5.3)", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] +dev = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pre-commit-uv", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] +docs = ["cogapp", "furo", "myst-parser", "sphinx", "sphinx-notfound-page", "sphinxcontrib-towncrier", "towncrier"] +tests = ["cloudpickle ; platform_python_implementation == \"CPython\"", "hypothesis", "mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pympler", "pytest (>=4.3.0)", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-xdist[psutil]"] +tests-mypy = ["mypy (>=1.11.1) ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\"", "pytest-mypy-plugins ; platform_python_implementation == \"CPython\" and python_version >= \"3.10\""] + +[[package]] +name = "babel" +version = "2.17.0" +description = "Internationalization utilities" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "babel-2.17.0-py3-none-any.whl", hash = "sha256:4d0b53093fdfb4b21c92b5213dba5a1b23885afa8383709427046b21c366e5f2"}, + {file = "babel-2.17.0.tar.gz", hash = "sha256:0c54cffb19f690cdcc52a3b50bcbf71e07a808d1c80d549f2459b9d2cf0afb9d"}, +] + +[package.extras] +dev = ["backports.zoneinfo ; python_version < \"3.9\"", "freezegun (>=1.0,<2.0)", "jinja2 (>=3.0)", "pytest (>=6.0)", "pytest-cov", "pytz", "setuptools", "tzdata ; sys_platform == \"win32\""] + +[[package]] +name = "beautifulsoup4" +version = "4.13.4" +description = "Screen-scraping library" +optional = false +python-versions = ">=3.7.0" +groups = ["dev"] +files = [ + {file = "beautifulsoup4-4.13.4-py3-none-any.whl", hash = "sha256:9bbbb14bfde9d79f38b8cd5f8c7c85f4b8f2523190ebed90e950a8dea4cb1c4b"}, + {file = "beautifulsoup4-4.13.4.tar.gz", hash = "sha256:dbb3c4e1ceae6aefebdaf2423247260cd062430a410e38c66f2baa50a8437195"}, +] + +[package.dependencies] +soupsieve = ">1.2" +typing-extensions = ">=4.0.0" + +[package.extras] +cchardet = ["cchardet"] +chardet = ["chardet"] +charset-normalizer = ["charset-normalizer"] +html5lib = ["html5lib"] +lxml = ["lxml"] + +[[package]] +name = "bleach" +version = "6.2.0" +description = "An easy safelist-based HTML-sanitizing tool." +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "bleach-6.2.0-py3-none-any.whl", hash = "sha256:117d9c6097a7c3d22fd578fcd8d35ff1e125df6736f554da4e432fdd63f31e5e"}, + {file = "bleach-6.2.0.tar.gz", hash = "sha256:123e894118b8a599fd80d3ec1a6d4cc7ce4e5882b1317a7e1ba69b56e95f991f"}, +] + +[package.dependencies] +tinycss2 = {version = ">=1.1.0,<1.5", optional = true, markers = "extra == \"css\""} +webencodings = "*" + +[package.extras] +css = ["tinycss2 (>=1.1.0,<1.5)"] + +[[package]] +name = "certifi" +version = "2025.8.3" +description = "Python package for providing Mozilla's CA Bundle." +optional = false +python-versions = ">=3.7" +groups = ["main", "dev"] +files = [ + {file = "certifi-2025.8.3-py3-none-any.whl", hash = "sha256:f6c12493cfb1b06ba2ff328595af9350c65d6644968e5d3a2ffd78699af217a5"}, + {file = "certifi-2025.8.3.tar.gz", hash = "sha256:e564105f78ded564e3ae7c923924435e1daa7463faeab5bb932bc53ffae63407"}, +] + +[[package]] +name = "cffi" +version = "1.17.1" +description = "Foreign Function Interface for Python calling C code." +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "cffi-1.17.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:df8b1c11f177bc2313ec4b2d46baec87a5f3e71fc8b45dab2ee7cae86d9aba14"}, + {file = "cffi-1.17.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8f2cdc858323644ab277e9bb925ad72ae0e67f69e804f4898c070998d50b1a67"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:edae79245293e15384b51f88b00613ba9f7198016a5948b5dddf4917d4d26382"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45398b671ac6d70e67da8e4224a065cec6a93541bb7aebe1b198a61b58c7b702"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ad9413ccdeda48c5afdae7e4fa2192157e991ff761e7ab8fdd8926f40b160cc3"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5da5719280082ac6bd9aa7becb3938dc9f9cbd57fac7d2871717b1feb0902ab6"}, + {file = "cffi-1.17.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bb1a08b8008b281856e5971307cc386a8e9c5b625ac297e853d36da6efe9c17"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:045d61c734659cc045141be4bae381a41d89b741f795af1dd018bfb532fd0df8"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:6883e737d7d9e4899a8a695e00ec36bd4e5e4f18fabe0aca0efe0a4b44cdb13e"}, + {file = "cffi-1.17.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:6b8b4a92e1c65048ff98cfe1f735ef8f1ceb72e3d5f0c25fdb12087a23da22be"}, + {file = "cffi-1.17.1-cp310-cp310-win32.whl", hash = "sha256:c9c3d058ebabb74db66e431095118094d06abf53284d9c81f27300d0e0d8bc7c"}, + {file = "cffi-1.17.1-cp310-cp310-win_amd64.whl", hash = "sha256:0f048dcf80db46f0098ccac01132761580d28e28bc0f78ae0d58048063317e15"}, + {file = "cffi-1.17.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a45e3c6913c5b87b3ff120dcdc03f6131fa0065027d0ed7ee6190736a74cd401"}, + {file = "cffi-1.17.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:30c5e0cb5ae493c04c8b42916e52ca38079f1b235c2f8ae5f4527b963c401caf"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f75c7ab1f9e4aca5414ed4d8e5c0e303a34f4421f8a0d47a4d019ceff0ab6af4"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a1ed2dd2972641495a3ec98445e09766f077aee98a1c896dcb4ad0d303628e41"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:46bf43160c1a35f7ec506d254e5c890f3c03648a4dbac12d624e4490a7046cd1"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a24ed04c8ffd54b0729c07cee15a81d964e6fee0e3d4d342a27b020d22959dc6"}, + {file = "cffi-1.17.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:610faea79c43e44c71e1ec53a554553fa22321b65fae24889706c0a84d4ad86d"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:a9b15d491f3ad5d692e11f6b71f7857e7835eb677955c00cc0aefcd0669adaf6"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:de2ea4b5833625383e464549fec1bc395c1bdeeb5f25c4a3a82b5a8c756ec22f"}, + {file = "cffi-1.17.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:fc48c783f9c87e60831201f2cce7f3b2e4846bf4d8728eabe54d60700b318a0b"}, + {file = "cffi-1.17.1-cp311-cp311-win32.whl", hash = "sha256:85a950a4ac9c359340d5963966e3e0a94a676bd6245a4b55bc43949eee26a655"}, + {file = "cffi-1.17.1-cp311-cp311-win_amd64.whl", hash = "sha256:caaf0640ef5f5517f49bc275eca1406b0ffa6aa184892812030f04c2abf589a0"}, + {file = "cffi-1.17.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:805b4371bf7197c329fcb3ead37e710d1bca9da5d583f5073b799d5c5bd1eee4"}, + {file = "cffi-1.17.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:733e99bc2df47476e3848417c5a4540522f234dfd4ef3ab7fafdf555b082ec0c"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1257bdabf294dceb59f5e70c64a3e2f462c30c7ad68092d01bbbfb1c16b1ba36"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:da95af8214998d77a98cc14e3a3bd00aa191526343078b530ceb0bd710fb48a5"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d63afe322132c194cf832bfec0dc69a99fb9bb6bbd550f161a49e9e855cc78ff"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f79fc4fc25f1c8698ff97788206bb3c2598949bfe0fef03d299eb1b5356ada99"}, + {file = "cffi-1.17.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b62ce867176a75d03a665bad002af8e6d54644fad99a3c70905c543130e39d93"}, + {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:386c8bf53c502fff58903061338ce4f4950cbdcb23e2902d86c0f722b786bbe3"}, + {file = "cffi-1.17.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4ceb10419a9adf4460ea14cfd6bc43d08701f0835e979bf821052f1805850fe8"}, + {file = "cffi-1.17.1-cp312-cp312-win32.whl", hash = "sha256:a08d7e755f8ed21095a310a693525137cfe756ce62d066e53f502a83dc550f65"}, + {file = "cffi-1.17.1-cp312-cp312-win_amd64.whl", hash = "sha256:51392eae71afec0d0c8fb1a53b204dbb3bcabcb3c9b807eedf3e1e6ccf2de903"}, + {file = "cffi-1.17.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:f3a2b4222ce6b60e2e8b337bb9596923045681d71e5a082783484d845390938e"}, + {file = "cffi-1.17.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:0984a4925a435b1da406122d4d7968dd861c1385afe3b45ba82b750f229811e2"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d01b12eeeb4427d3110de311e1774046ad344f5b1a7403101878976ecd7a10f3"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:706510fe141c86a69c8ddc029c7910003a17353970cff3b904ff0686a5927683"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de55b766c7aa2e2a3092c51e0483d700341182f08e67c63630d5b6f200bb28e5"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c59d6e989d07460165cc5ad3c61f9fd8f1b4796eacbd81cee78957842b834af4"}, + {file = "cffi-1.17.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd398dbc6773384a17fe0d3e7eeb8d1a21c2200473ee6806bb5e6a8e62bb73dd"}, + {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:3edc8d958eb099c634dace3c7e16560ae474aa3803a5df240542b305d14e14ed"}, + {file = "cffi-1.17.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:72e72408cad3d5419375fc87d289076ee319835bdfa2caad331e377589aebba9"}, + {file = "cffi-1.17.1-cp313-cp313-win32.whl", hash = "sha256:e03eab0a8677fa80d646b5ddece1cbeaf556c313dcfac435ba11f107ba117b5d"}, + {file = "cffi-1.17.1-cp313-cp313-win_amd64.whl", hash = "sha256:f6a16c31041f09ead72d69f583767292f750d24913dadacf5756b966aacb3f1a"}, + {file = "cffi-1.17.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:636062ea65bd0195bc012fea9321aca499c0504409f413dc88af450b57ffd03b"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7eac2ef9b63c79431bc4b25f1cd649d7f061a28808cbc6c47b534bd789ef964"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e221cf152cff04059d011ee126477f0d9588303eb57e88923578ace7baad17f9"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:31000ec67d4221a71bd3f67df918b1f88f676f1c3b535a7eb473255fdc0b83fc"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6f17be4345073b0a7b8ea599688f692ac3ef23ce28e5df79c04de519dbc4912c"}, + {file = "cffi-1.17.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0e2b1fac190ae3ebfe37b979cc1ce69c81f4e4fe5746bb401dca63a9062cdaf1"}, + {file = "cffi-1.17.1-cp38-cp38-win32.whl", hash = "sha256:7596d6620d3fa590f677e9ee430df2958d2d6d6de2feeae5b20e82c00b76fbf8"}, + {file = "cffi-1.17.1-cp38-cp38-win_amd64.whl", hash = "sha256:78122be759c3f8a014ce010908ae03364d00a1f81ab5c7f4a7a5120607ea56e1"}, + {file = "cffi-1.17.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b2ab587605f4ba0bf81dc0cb08a41bd1c0a5906bd59243d56bad7668a6fc6c16"}, + {file = "cffi-1.17.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:28b16024becceed8c6dfbc75629e27788d8a3f9030691a1dbf9821a128b22c36"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1d599671f396c4723d016dbddb72fe8e0397082b0a77a4fab8028923bec050e8"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ca74b8dbe6e8e8263c0ffd60277de77dcee6c837a3d0881d8c1ead7268c9e576"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f7f5baafcc48261359e14bcd6d9bff6d4b28d9103847c9e136694cb0501aef87"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:98e3969bcff97cae1b2def8ba499ea3d6f31ddfdb7635374834cf89a1a08ecf0"}, + {file = "cffi-1.17.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cdf5ce3acdfd1661132f2a9c19cac174758dc2352bfe37d98aa7512c6b7178b3"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9755e4345d1ec879e3849e62222a18c7174d65a6a92d5b346b1863912168b595"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f1e22e8c4419538cb197e4dd60acc919d7696e5ef98ee4da4e01d3f8cfa4cc5a"}, + {file = "cffi-1.17.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c03e868a0b3bc35839ba98e74211ed2b05d2119be4e8a0f224fba9384f1fe02e"}, + {file = "cffi-1.17.1-cp39-cp39-win32.whl", hash = "sha256:e31ae45bc2e29f6b2abd0de1cc3b9d5205aa847cafaecb8af1476a609a2f6eb7"}, + {file = "cffi-1.17.1-cp39-cp39-win_amd64.whl", hash = "sha256:d016c76bdd850f3c626af19b0542c9677ba156e4ee4fccfdd7848803533ef662"}, + {file = "cffi-1.17.1.tar.gz", hash = "sha256:1c39c6016c32bc48dd54561950ebd6836e1670f2ae46128f67cf49e789c52824"}, +] + +[package.dependencies] +pycparser = "*" + +[[package]] +name = "charset-normalizer" +version = "3.4.3" +description = "The Real First Universal Charset Detector. Open, modern and actively maintained alternative to Chardet." +optional = false +python-versions = ">=3.7" +groups = ["main", "dev"] +files = [ + {file = "charset_normalizer-3.4.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:fb7f67a1bfa6e40b438170ebdc8158b78dc465a5a67b6dde178a46987b244a72"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cc9370a2da1ac13f0153780040f465839e6cccb4a1e44810124b4e22483c93fe"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:07a0eae9e2787b586e129fdcbe1af6997f8d0e5abaa0bc98c0e20e124d67e601"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:74d77e25adda8581ffc1c720f1c81ca082921329452eba58b16233ab1842141c"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d0e909868420b7049dafd3a31d45125b31143eec59235311fc4c57ea26a4acd2"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c6f162aabe9a91a309510d74eeb6507fab5fff92337a15acbe77753d88d9dcf0"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:4ca4c094de7771a98d7fbd67d9e5dbf1eb73efa4f744a730437d8a3a5cf994f0"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:02425242e96bcf29a49711b0ca9f37e451da7c70562bc10e8ed992a5a7a25cc0"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:78deba4d8f9590fe4dae384aeff04082510a709957e968753ff3c48399f6f92a"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-win32.whl", hash = "sha256:d79c198e27580c8e958906f803e63cddb77653731be08851c7df0b1a14a8fc0f"}, + {file = "charset_normalizer-3.4.3-cp310-cp310-win_amd64.whl", hash = "sha256:c6e490913a46fa054e03699c70019ab869e990270597018cef1d8562132c2669"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:b256ee2e749283ef3ddcff51a675ff43798d92d746d1a6e4631bf8c707d22d0b"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:13faeacfe61784e2559e690fc53fa4c5ae97c6fcedb8eb6fb8d0a15b475d2c64"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:00237675befef519d9af72169d8604a067d92755e84fe76492fef5441db05b91"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:585f3b2a80fbd26b048a0be90c5aae8f06605d3c92615911c3a2b03a8a3b796f"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0e78314bdc32fa80696f72fa16dc61168fda4d6a0c014e0380f9d02f0e5d8a07"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:96b2b3d1a83ad55310de8c7b4a2d04d9277d5591f40761274856635acc5fcb30"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:939578d9d8fd4299220161fdd76e86c6a251987476f5243e8864a7844476ba14"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:fd10de089bcdcd1be95a2f73dbe6254798ec1bda9f450d5828c96f93e2536b9c"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1e8ac75d72fa3775e0b7cb7e4629cec13b7514d928d15ef8ea06bca03ef01cae"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-win32.whl", hash = "sha256:6cf8fd4c04756b6b60146d98cd8a77d0cdae0e1ca20329da2ac85eed779b6849"}, + {file = "charset_normalizer-3.4.3-cp311-cp311-win_amd64.whl", hash = "sha256:31a9a6f775f9bcd865d88ee350f0ffb0e25936a7f930ca98995c05abf1faf21c"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e28e334d3ff134e88989d90ba04b47d84382a828c061d0d1027b1b12a62b39b1"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0cacf8f7297b0c4fcb74227692ca46b4a5852f8f4f24b3c766dd94a1075c4884"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:c6fd51128a41297f5409deab284fecbe5305ebd7e5a1f959bee1c054622b7018"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3cfb2aad70f2c6debfbcb717f23b7eb55febc0bb23dcffc0f076009da10c6392"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1606f4a55c0fd363d754049cdf400175ee96c992b1f8018b993941f221221c5f"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:027b776c26d38b7f15b26a5da1044f376455fb3766df8fc38563b4efbc515154"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:42e5088973e56e31e4fa58eb6bd709e42fc03799c11c42929592889a2e54c491"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:cc34f233c9e71701040d772aa7490318673aa7164a0efe3172b2981218c26d93"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:320e8e66157cc4e247d9ddca8e21f427efc7a04bbd0ac8a9faf56583fa543f9f"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-win32.whl", hash = "sha256:fb6fecfd65564f208cbf0fba07f107fb661bcd1a7c389edbced3f7a493f70e37"}, + {file = "charset_normalizer-3.4.3-cp312-cp312-win_amd64.whl", hash = "sha256:86df271bf921c2ee3818f0522e9a5b8092ca2ad8b065ece5d7d9d0e9f4849bcc"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:14c2a87c65b351109f6abfc424cab3927b3bdece6f706e4d12faaf3d52ee5efe"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:41d1fc408ff5fdfb910200ec0e74abc40387bccb3252f3f27c0676731df2b2c8"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:1bb60174149316da1c35fa5233681f7c0f9f514509b8e399ab70fea5f17e45c9"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:30d006f98569de3459c2fc1f2acde170b7b2bd265dc1943e87e1a4efe1b67c31"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:416175faf02e4b0810f1f38bcb54682878a4af94059a1cd63b8747244420801f"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6aab0f181c486f973bc7262a97f5aca3ee7e1437011ef0c2ec04b5a11d16c927"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:fdabf8315679312cfa71302f9bd509ded4f2f263fb5b765cf1433b39106c3cc9"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:bd28b817ea8c70215401f657edef3a8aa83c29d447fb0b622c35403780ba11d5"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:18343b2d246dc6761a249ba1fb13f9ee9a2bcd95decc767319506056ea4ad4dc"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-win32.whl", hash = "sha256:6fb70de56f1859a3f71261cbe41005f56a7842cc348d3aeb26237560bfa5e0ce"}, + {file = "charset_normalizer-3.4.3-cp313-cp313-win_amd64.whl", hash = "sha256:cf1ebb7d78e1ad8ec2a8c4732c7be2e736f6e5123a4146c5b89c9d1f585f8cef"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:3cd35b7e8aedeb9e34c41385fda4f73ba609e561faedfae0a9e75e44ac558a15"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b89bc04de1d83006373429975f8ef9e7932534b8cc9ca582e4db7d20d91816db"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2001a39612b241dae17b4687898843f254f8748b796a2e16f1051a17078d991d"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8dcfc373f888e4fb39a7bc57e93e3b845e7f462dacc008d9749568b1c4ece096"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:18b97b8404387b96cdbd30ad660f6407799126d26a39ca65729162fd810a99aa"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:ccf600859c183d70eb47e05a44cd80a4ce77394d1ac0f79dbd2dd90a69a3a049"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:53cd68b185d98dde4ad8990e56a58dea83a4162161b1ea9272e5c9182ce415e0"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:30a96e1e1f865f78b030d65241c1ee850cdf422d869e9028e2fc1d5e4db73b92"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d716a916938e03231e86e43782ca7878fb602a125a91e7acb8b5112e2e96ac16"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-win32.whl", hash = "sha256:c6dbd0ccdda3a2ba7c2ecd9d77b37f3b5831687d8dc1b6ca5f56a4880cc7b7ce"}, + {file = "charset_normalizer-3.4.3-cp314-cp314-win_amd64.whl", hash = "sha256:73dc19b562516fc9bcf6e5d6e596df0b4eb98d87e4f79f3ae71840e6ed21361c"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:0f2be7e0cf7754b9a30eb01f4295cc3d4358a479843b31f328afd210e2c7598c"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c60e092517a73c632ec38e290eba714e9627abe9d301c8c8a12ec32c314a2a4b"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:252098c8c7a873e17dd696ed98bbe91dbacd571da4b87df3736768efa7a792e4"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:3653fad4fe3ed447a596ae8638b437f827234f01a8cd801842e43f3d0a6b281b"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8999f965f922ae054125286faf9f11bc6932184b93011d138925a1773830bbe9"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:d95bfb53c211b57198bb91c46dd5a2d8018b3af446583aab40074bf7988401cb"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:5b413b0b1bfd94dbf4023ad6945889f374cd24e3f62de58d6bb102c4d9ae534a"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:b5e3b2d152e74e100a9e9573837aba24aab611d39428ded46f4e4022ea7d1942"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:a2d08ac246bb48479170408d6c19f6385fa743e7157d716e144cad849b2dd94b"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-win32.whl", hash = "sha256:ec557499516fc90fd374bf2e32349a2887a876fbf162c160e3c01b6849eaf557"}, + {file = "charset_normalizer-3.4.3-cp38-cp38-win_amd64.whl", hash = "sha256:5d8d01eac18c423815ed4f4a2ec3b439d654e55ee4ad610e153cf02faf67ea40"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:70bfc5f2c318afece2f5838ea5e4c3febada0be750fcf4775641052bbba14d05"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:23b6b24d74478dc833444cbd927c338349d6ae852ba53a0d02a2de1fce45b96e"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:34a7f768e3f985abdb42841e20e17b330ad3aaf4bb7e7aeeb73db2e70f077b99"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:fb731e5deb0c7ef82d698b0f4c5bb724633ee2a489401594c5c88b02e6cb15f7"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:257f26fed7d7ff59921b78244f3cd93ed2af1800ff048c33f624c87475819dd7"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1ef99f0456d3d46a50945c98de1774da86f8e992ab5c77865ea8b8195341fc19"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:2c322db9c8c89009a990ef07c3bcc9f011a3269bc06782f916cd3d9eed7c9312"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:511729f456829ef86ac41ca78c63a5cb55240ed23b4b737faca0eb1abb1c41bc"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:88ab34806dea0671532d3f82d82b85e8fc23d7b2dd12fa837978dad9bb392a34"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-win32.whl", hash = "sha256:16a8770207946ac75703458e2c743631c79c59c5890c80011d536248f8eaa432"}, + {file = "charset_normalizer-3.4.3-cp39-cp39-win_amd64.whl", hash = "sha256:d22dbedd33326a4a5190dd4fe9e9e693ef12160c77382d9e87919bce54f3d4ca"}, + {file = "charset_normalizer-3.4.3-py3-none-any.whl", hash = "sha256:ce571ab16d890d23b5c278547ba694193a45011ff86a9162a71307ed9f86759a"}, + {file = "charset_normalizer-3.4.3.tar.gz", hash = "sha256:6fce4b8500244f6fcb71465d4a4930d132ba9ab8e71a7859e6a5d59851068d14"}, +] + +[[package]] +name = "colorama" +version = "0.4.6" +description = "Cross-platform colored terminal text." +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" +groups = ["dev"] +markers = "sys_platform == \"win32\"" +files = [ + {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"}, + {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"}, +] + +[[package]] +name = "comm" +version = "0.2.3" +description = "Jupyter Python Comm implementation, for usage in ipykernel, xeus-python etc." +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "comm-0.2.3-py3-none-any.whl", hash = "sha256:c615d91d75f7f04f095b30d1c1711babd43bdc6419c1be9886a85f2f4e489417"}, + {file = "comm-0.2.3.tar.gz", hash = "sha256:2dc8048c10962d55d7ad693be1e7045d891b7ce8d999c97963a5e3e99c055971"}, +] + +[package.extras] +test = ["pytest"] + +[[package]] +name = "coverage" +version = "7.10.3" +description = "Code coverage measurement for Python" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "coverage-7.10.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:53808194afdf948c462215e9403cca27a81cf150d2f9b386aee4dab614ae2ffe"}, + {file = "coverage-7.10.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f4d1b837d1abf72187a61645dbf799e0d7705aa9232924946e1f57eb09a3bf00"}, + {file = "coverage-7.10.3-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:2a90dd4505d3cc68b847ab10c5ee81822a968b5191664e8a0801778fa60459fa"}, + {file = "coverage-7.10.3-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:d52989685ff5bf909c430e6d7f6550937bc6d6f3e6ecb303c97a86100efd4596"}, + {file = "coverage-7.10.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bdb558a1d97345bde3a9f4d3e8d11c9e5611f748646e9bb61d7d612a796671b5"}, + {file = "coverage-7.10.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c9e6331a8f09cb1fc8bda032752af03c366870b48cce908875ba2620d20d0ad4"}, + {file = "coverage-7.10.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:992f48bf35b720e174e7fae916d943599f1a66501a2710d06c5f8104e0756ee1"}, + {file = "coverage-7.10.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c5595fc4ad6a39312c786ec3326d7322d0cf10e3ac6a6df70809910026d67cfb"}, + {file = "coverage-7.10.3-cp310-cp310-win32.whl", hash = "sha256:9e92fa1f2bd5a57df9d00cf9ce1eb4ef6fccca4ceabec1c984837de55329db34"}, + {file = "coverage-7.10.3-cp310-cp310-win_amd64.whl", hash = "sha256:b96524d6e4a3ce6a75c56bb15dbd08023b0ae2289c254e15b9fbdddf0c577416"}, + {file = "coverage-7.10.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f2ff2e2afdf0d51b9b8301e542d9c21a8d084fd23d4c8ea2b3a1b3c96f5f7397"}, + {file = "coverage-7.10.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:18ecc5d1b9a8c570f6c9b808fa9a2b16836b3dd5414a6d467ae942208b095f85"}, + {file = "coverage-7.10.3-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:1af4461b25fe92889590d438905e1fc79a95680ec2a1ff69a591bb3fdb6c7157"}, + {file = "coverage-7.10.3-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:3966bc9a76b09a40dc6063c8b10375e827ea5dfcaffae402dd65953bef4cba54"}, + {file = "coverage-7.10.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:205a95b87ef4eb303b7bc5118b47b6b6604a644bcbdb33c336a41cfc0a08c06a"}, + {file = "coverage-7.10.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:5b3801b79fb2ad61e3c7e2554bab754fc5f105626056980a2b9cf3aef4f13f84"}, + {file = "coverage-7.10.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:b0dc69c60224cda33d384572da945759756e3f06b9cdac27f302f53961e63160"}, + {file = "coverage-7.10.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a83d4f134bab2c7ff758e6bb1541dd72b54ba295ced6a63d93efc2e20cb9b124"}, + {file = "coverage-7.10.3-cp311-cp311-win32.whl", hash = "sha256:54e409dd64e5302b2a8fdf44ec1c26f47abd1f45a2dcf67bd161873ee05a59b8"}, + {file = "coverage-7.10.3-cp311-cp311-win_amd64.whl", hash = "sha256:30c601610a9b23807c5e9e2e442054b795953ab85d525c3de1b1b27cebeb2117"}, + {file = "coverage-7.10.3-cp311-cp311-win_arm64.whl", hash = "sha256:dabe662312a97958e932dee056f2659051d822552c0b866823e8ba1c2fe64770"}, + {file = "coverage-7.10.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:449c1e2d3a84d18bd204258a897a87bc57380072eb2aded6a5b5226046207b42"}, + {file = "coverage-7.10.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:1d4f9ce50b9261ad196dc2b2e9f1fbbee21651b54c3097a25ad783679fd18294"}, + {file = "coverage-7.10.3-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:4dd4564207b160d0d45c36a10bc0a3d12563028e8b48cd6459ea322302a156d7"}, + {file = "coverage-7.10.3-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:5ca3c9530ee072b7cb6a6ea7b640bcdff0ad3b334ae9687e521e59f79b1d0437"}, + {file = "coverage-7.10.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b6df359e59fa243c9925ae6507e27f29c46698359f45e568fd51b9315dbbe587"}, + {file = "coverage-7.10.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a181e4c2c896c2ff64c6312db3bda38e9ade2e1aa67f86a5628ae85873786cea"}, + {file = "coverage-7.10.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a374d4e923814e8b72b205ef6b3d3a647bb50e66f3558582eda074c976923613"}, + {file = "coverage-7.10.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:daeefff05993e5e8c6e7499a8508e7bd94502b6b9a9159c84fd1fe6bce3151cb"}, + {file = "coverage-7.10.3-cp312-cp312-win32.whl", hash = "sha256:187ecdcac21f9636d570e419773df7bd2fda2e7fa040f812e7f95d0bddf5f79a"}, + {file = "coverage-7.10.3-cp312-cp312-win_amd64.whl", hash = "sha256:4a50ad2524ee7e4c2a95e60d2b0b83283bdfc745fe82359d567e4f15d3823eb5"}, + {file = "coverage-7.10.3-cp312-cp312-win_arm64.whl", hash = "sha256:c112f04e075d3495fa3ed2200f71317da99608cbb2e9345bdb6de8819fc30571"}, + {file = "coverage-7.10.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:b99e87304ffe0eb97c5308447328a584258951853807afdc58b16143a530518a"}, + {file = "coverage-7.10.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:4af09c7574d09afbc1ea7da9dcea23665c01f3bc1b1feb061dac135f98ffc53a"}, + {file = "coverage-7.10.3-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:488e9b50dc5d2aa9521053cfa706209e5acf5289e81edc28291a24f4e4488f46"}, + {file = "coverage-7.10.3-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:913ceddb4289cbba3a310704a424e3fb7aac2bc0c3a23ea473193cb290cf17d4"}, + {file = "coverage-7.10.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b1f91cbc78c7112ab84ed2a8defbccd90f888fcae40a97ddd6466b0bec6ae8a"}, + {file = "coverage-7.10.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:b0bac054d45af7cd938834b43a9878b36ea92781bcb009eab040a5b09e9927e3"}, + {file = "coverage-7.10.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:fe72cbdd12d9e0f4aca873fa6d755e103888a7f9085e4a62d282d9d5b9f7928c"}, + {file = "coverage-7.10.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c1e2e927ab3eadd7c244023927d646e4c15c65bb2ac7ae3c3e9537c013700d21"}, + {file = "coverage-7.10.3-cp313-cp313-win32.whl", hash = "sha256:24d0c13de473b04920ddd6e5da3c08831b1170b8f3b17461d7429b61cad59ae0"}, + {file = "coverage-7.10.3-cp313-cp313-win_amd64.whl", hash = "sha256:3564aae76bce4b96e2345cf53b4c87e938c4985424a9be6a66ee902626edec4c"}, + {file = "coverage-7.10.3-cp313-cp313-win_arm64.whl", hash = "sha256:f35580f19f297455f44afcd773c9c7a058e52eb6eb170aa31222e635f2e38b87"}, + {file = "coverage-7.10.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:07009152f497a0464ffdf2634586787aea0e69ddd023eafb23fc38267db94b84"}, + {file = "coverage-7.10.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:8dd2ba5f0c7e7e8cc418be2f0c14c4d9e3f08b8fb8e4c0f83c2fe87d03eb655e"}, + {file = "coverage-7.10.3-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:1ae22b97003c74186e034a93e4f946c75fad8c0ce8d92fbbc168b5e15ee2841f"}, + {file = "coverage-7.10.3-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:eb329f1046888a36b1dc35504d3029e1dd5afe2196d94315d18c45ee380f67d5"}, + {file = "coverage-7.10.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ce01048199a91f07f96ca3074b0c14021f4fe7ffd29a3e6a188ac60a5c3a4af8"}, + {file = "coverage-7.10.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:08b989a06eb9dfacf96d42b7fb4c9a22bafa370d245dc22fa839f2168c6f9fa1"}, + {file = "coverage-7.10.3-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:669fe0d4e69c575c52148511029b722ba8d26e8a3129840c2ce0522e1452b256"}, + {file = "coverage-7.10.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:3262d19092771c83f3413831d9904b1ccc5f98da5de4ffa4ad67f5b20c7aaf7b"}, + {file = "coverage-7.10.3-cp313-cp313t-win32.whl", hash = "sha256:cc0ee4b2ccd42cab7ee6be46d8a67d230cb33a0a7cd47a58b587a7063b6c6b0e"}, + {file = "coverage-7.10.3-cp313-cp313t-win_amd64.whl", hash = "sha256:03db599f213341e2960430984e04cf35fb179724e052a3ee627a068653cf4a7c"}, + {file = "coverage-7.10.3-cp313-cp313t-win_arm64.whl", hash = "sha256:46eae7893ba65f53c71284585a262f083ef71594f05ec5c85baf79c402369098"}, + {file = "coverage-7.10.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:bce8b8180912914032785850d8f3aacb25ec1810f5f54afc4a8b114e7a9b55de"}, + {file = "coverage-7.10.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:07790b4b37d56608536f7c1079bd1aa511567ac2966d33d5cec9cf520c50a7c8"}, + {file = "coverage-7.10.3-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:e79367ef2cd9166acedcbf136a458dfe9a4a2dd4d1ee95738fb2ee581c56f667"}, + {file = "coverage-7.10.3-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:419d2a0f769f26cb1d05e9ccbc5eab4cb5d70231604d47150867c07822acbdf4"}, + {file = "coverage-7.10.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee221cf244757cdc2ac882e3062ab414b8464ad9c884c21e878517ea64b3fa26"}, + {file = "coverage-7.10.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c2079d8cdd6f7373d628e14b3357f24d1db02c9dc22e6a007418ca7a2be0435a"}, + {file = "coverage-7.10.3-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:bd8df1f83c0703fa3ca781b02d36f9ec67ad9cb725b18d486405924f5e4270bd"}, + {file = "coverage-7.10.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:6b4e25e0fa335c8aa26e42a52053f3786a61cc7622b4d54ae2dad994aa754fec"}, + {file = "coverage-7.10.3-cp314-cp314-win32.whl", hash = "sha256:d7c3d02c2866deb217dce664c71787f4b25420ea3eaf87056f44fb364a3528f5"}, + {file = "coverage-7.10.3-cp314-cp314-win_amd64.whl", hash = "sha256:9c8916d44d9e0fe6cdb2227dc6b0edd8bc6c8ef13438bbbf69af7482d9bb9833"}, + {file = "coverage-7.10.3-cp314-cp314-win_arm64.whl", hash = "sha256:1007d6a2b3cf197c57105cc1ba390d9ff7f0bee215ced4dea530181e49c65ab4"}, + {file = "coverage-7.10.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:ebc8791d346410d096818788877d675ca55c91db87d60e8f477bd41c6970ffc6"}, + {file = "coverage-7.10.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:1f4e4d8e75f6fd3c6940ebeed29e3d9d632e1f18f6fb65d33086d99d4d073241"}, + {file = "coverage-7.10.3-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:24581ed69f132b6225a31b0228ae4885731cddc966f8a33fe5987288bdbbbd5e"}, + {file = "coverage-7.10.3-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:ec151569ddfccbf71bac8c422dce15e176167385a00cd86e887f9a80035ce8a5"}, + {file = "coverage-7.10.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2ae8e7c56290b908ee817200c0b65929b8050bc28530b131fe7c6dfee3e7d86b"}, + {file = "coverage-7.10.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5fb742309766d7e48e9eb4dc34bc95a424707bc6140c0e7d9726e794f11b92a0"}, + {file = "coverage-7.10.3-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:c65e2a5b32fbe1e499f1036efa6eb9cb4ea2bf6f7168d0e7a5852f3024f471b1"}, + {file = "coverage-7.10.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:d48d2cb07d50f12f4f18d2bb75d9d19e3506c26d96fffabf56d22936e5ed8f7c"}, + {file = "coverage-7.10.3-cp314-cp314t-win32.whl", hash = "sha256:dec0d9bc15ee305e09fe2cd1911d3f0371262d3cfdae05d79515d8cb712b4869"}, + {file = "coverage-7.10.3-cp314-cp314t-win_amd64.whl", hash = "sha256:424ea93a323aa0f7f01174308ea78bde885c3089ec1bef7143a6d93c3e24ef64"}, + {file = "coverage-7.10.3-cp314-cp314t-win_arm64.whl", hash = "sha256:f5983c132a62d93d71c9ef896a0b9bf6e6828d8d2ea32611f58684fba60bba35"}, + {file = "coverage-7.10.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:da749daa7e141985487e1ff90a68315b0845930ed53dc397f4ae8f8bab25b551"}, + {file = "coverage-7.10.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f3126fb6a47d287f461d9b1aa5d1a8c97034d1dffb4f452f2cf211289dae74ef"}, + {file = "coverage-7.10.3-cp39-cp39-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3da794db13cc27ca40e1ec8127945b97fab78ba548040047d54e7bfa6d442dca"}, + {file = "coverage-7.10.3-cp39-cp39-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:4e27bebbd184ef8d1c1e092b74a2b7109dcbe2618dce6e96b1776d53b14b3fe8"}, + {file = "coverage-7.10.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8fd4ee2580b9fefbd301b4f8f85b62ac90d1e848bea54f89a5748cf132782118"}, + {file = "coverage-7.10.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:6999920bdd73259ce11cabfc1307484f071ecc6abdb2ca58d98facbcefc70f16"}, + {file = "coverage-7.10.3-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:c3623f929db885fab100cb88220a5b193321ed37e03af719efdbaf5d10b6e227"}, + {file = "coverage-7.10.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:25b902c5e15dea056485d782e420bb84621cc08ee75d5131ecb3dbef8bd1365f"}, + {file = "coverage-7.10.3-cp39-cp39-win32.whl", hash = "sha256:f930a4d92b004b643183451fe9c8fe398ccf866ed37d172ebaccfd443a097f61"}, + {file = "coverage-7.10.3-cp39-cp39-win_amd64.whl", hash = "sha256:08e638a93c8acba13c7842953f92a33d52d73e410329acd472280d2a21a6c0e1"}, + {file = "coverage-7.10.3-py3-none-any.whl", hash = "sha256:416a8d74dc0adfd33944ba2f405897bab87b7e9e84a391e09d241956bd953ce1"}, + {file = "coverage-7.10.3.tar.gz", hash = "sha256:812ba9250532e4a823b070b0420a36499859542335af3dca8f47fc6aa1a05619"}, +] + +[package.extras] +toml = ["tomli ; python_full_version <= \"3.11.0a6\""] + +[[package]] +name = "debugpy" +version = "1.8.16" +description = "An implementation of the Debug Adapter Protocol for Python" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "debugpy-1.8.16-cp310-cp310-macosx_14_0_x86_64.whl", hash = "sha256:2a3958fb9c2f40ed8ea48a0d34895b461de57a1f9862e7478716c35d76f56c65"}, + {file = "debugpy-1.8.16-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e5ca7314042e8a614cc2574cd71f6ccd7e13a9708ce3c6d8436959eae56f2378"}, + {file = "debugpy-1.8.16-cp310-cp310-win32.whl", hash = "sha256:8624a6111dc312ed8c363347a0b59c5acc6210d897e41a7c069de3c53235c9a6"}, + {file = "debugpy-1.8.16-cp310-cp310-win_amd64.whl", hash = "sha256:fee6db83ea5c978baf042440cfe29695e1a5d48a30147abf4c3be87513609817"}, + {file = "debugpy-1.8.16-cp311-cp311-macosx_14_0_universal2.whl", hash = "sha256:67371b28b79a6a12bcc027d94a06158f2fde223e35b5c4e0783b6f9d3b39274a"}, + {file = "debugpy-1.8.16-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b2abae6dd02523bec2dee16bd6b0781cccb53fd4995e5c71cc659b5f45581898"}, + {file = "debugpy-1.8.16-cp311-cp311-win32.whl", hash = "sha256:f8340a3ac2ed4f5da59e064aa92e39edd52729a88fbde7bbaa54e08249a04493"}, + {file = "debugpy-1.8.16-cp311-cp311-win_amd64.whl", hash = "sha256:70f5fcd6d4d0c150a878d2aa37391c52de788c3dc680b97bdb5e529cb80df87a"}, + {file = "debugpy-1.8.16-cp312-cp312-macosx_14_0_universal2.whl", hash = "sha256:b202e2843e32e80b3b584bcebfe0e65e0392920dc70df11b2bfe1afcb7a085e4"}, + {file = "debugpy-1.8.16-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:64473c4a306ba11a99fe0bb14622ba4fbd943eb004847d9b69b107bde45aa9ea"}, + {file = "debugpy-1.8.16-cp312-cp312-win32.whl", hash = "sha256:833a61ed446426e38b0dd8be3e9d45ae285d424f5bf6cd5b2b559c8f12305508"}, + {file = "debugpy-1.8.16-cp312-cp312-win_amd64.whl", hash = "sha256:75f204684581e9ef3dc2f67687c3c8c183fde2d6675ab131d94084baf8084121"}, + {file = "debugpy-1.8.16-cp313-cp313-macosx_14_0_universal2.whl", hash = "sha256:85df3adb1de5258dca910ae0bb185e48c98801ec15018a263a92bb06be1c8787"}, + {file = "debugpy-1.8.16-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bee89e948bc236a5c43c4214ac62d28b29388453f5fd328d739035e205365f0b"}, + {file = "debugpy-1.8.16-cp313-cp313-win32.whl", hash = "sha256:cf358066650439847ec5ff3dae1da98b5461ea5da0173d93d5e10f477c94609a"}, + {file = "debugpy-1.8.16-cp313-cp313-win_amd64.whl", hash = "sha256:b5aea1083f6f50023e8509399d7dc6535a351cc9f2e8827d1e093175e4d9fa4c"}, + {file = "debugpy-1.8.16-cp38-cp38-macosx_14_0_x86_64.whl", hash = "sha256:2801329c38f77c47976d341d18040a9ac09d0c71bf2c8b484ad27c74f83dc36f"}, + {file = "debugpy-1.8.16-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:687c7ab47948697c03b8f81424aa6dc3f923e6ebab1294732df1ca9773cc67bc"}, + {file = "debugpy-1.8.16-cp38-cp38-win32.whl", hash = "sha256:a2ba6fc5d7c4bc84bcae6c5f8edf5988146e55ae654b1bb36fecee9e5e77e9e2"}, + {file = "debugpy-1.8.16-cp38-cp38-win_amd64.whl", hash = "sha256:d58c48d8dbbbf48a3a3a638714a2d16de537b0dace1e3432b8e92c57d43707f8"}, + {file = "debugpy-1.8.16-cp39-cp39-macosx_14_0_x86_64.whl", hash = "sha256:135ccd2b1161bade72a7a099c9208811c137a150839e970aeaf121c2467debe8"}, + {file = "debugpy-1.8.16-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:211238306331a9089e253fd997213bc4a4c65f949271057d6695953254095376"}, + {file = "debugpy-1.8.16-cp39-cp39-win32.whl", hash = "sha256:88eb9ffdfb59bf63835d146c183d6dba1f722b3ae2a5f4b9fc03e925b3358922"}, + {file = "debugpy-1.8.16-cp39-cp39-win_amd64.whl", hash = "sha256:c2c47c2e52b40449552843b913786499efcc3dbc21d6c49287d939cd0dbc49fd"}, + {file = "debugpy-1.8.16-py2.py3-none-any.whl", hash = "sha256:19c9521962475b87da6f673514f7fd610328757ec993bf7ec0d8c96f9a325f9e"}, + {file = "debugpy-1.8.16.tar.gz", hash = "sha256:31e69a1feb1cf6b51efbed3f6c9b0ef03bc46ff050679c4be7ea6d2e23540870"}, +] + +[[package]] +name = "decorator" +version = "5.2.1" +description = "Decorators for Humans" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "decorator-5.2.1-py3-none-any.whl", hash = "sha256:d316bb415a2d9e2d2b3abcc4084c6502fc09240e292cd76a76afc106a1c8e04a"}, + {file = "decorator-5.2.1.tar.gz", hash = "sha256:65f266143752f734b0a7cc83c46f4618af75b8c5911b00ccb61d0ac9b6da0360"}, +] + +[[package]] +name = "defusedxml" +version = "0.7.1" +description = "XML bomb protection for Python stdlib modules" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +groups = ["dev"] +files = [ + {file = "defusedxml-0.7.1-py2.py3-none-any.whl", hash = "sha256:a352e7e428770286cc899e2542b6cdaedb2b4953ff269a210103ec58f6198a61"}, + {file = "defusedxml-0.7.1.tar.gz", hash = "sha256:1bb3032db185915b62d7c6209c5a8792be6a32ab2fedacc84e01b52c51aa3e69"}, +] + +[[package]] +name = "dill" +version = "0.4.0" +description = "serialize all of Python" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "dill-0.4.0-py3-none-any.whl", hash = "sha256:44f54bf6412c2c8464c14e8243eb163690a9800dbe2c367330883b19c7561049"}, + {file = "dill-0.4.0.tar.gz", hash = "sha256:0633f1d2df477324f53a895b02c901fb961bdbf65a17122586ea7019292cbcf0"}, +] + +[package.extras] +graph = ["objgraph (>=1.7.2)"] +profile = ["gprof2dot (>=2022.7.29)"] + +[[package]] +name = "et-xmlfile" +version = "2.0.0" +description = "An implementation of lxml.xmlfile for the standard library" +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "et_xmlfile-2.0.0-py3-none-any.whl", hash = "sha256:7a91720bc756843502c3b7504c77b8fe44217c85c537d85037f0f536151b2caa"}, + {file = "et_xmlfile-2.0.0.tar.gz", hash = "sha256:dab3f4764309081ce75662649be815c4c9081e88f0837825f90fd28317d4da54"}, +] + +[[package]] +name = "executing" +version = "2.2.0" +description = "Get the currently executing AST node of a frame, and other information" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "executing-2.2.0-py2.py3-none-any.whl", hash = "sha256:11387150cad388d62750327a53d3339fad4888b39a6fe233c3afbb54ecffd3aa"}, + {file = "executing-2.2.0.tar.gz", hash = "sha256:5d108c028108fe2551d1a7b2e8b713341e2cb4fc0aa7dcf966fa4327a5226755"}, +] + +[package.extras] +tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipython", "littleutils", "pytest", "rich ; python_version >= \"3.11\""] + +[[package]] +name = "fastjsonschema" +version = "2.21.1" +description = "Fastest Python implementation of JSON schema" +optional = false +python-versions = "*" +groups = ["dev"] +files = [ + {file = "fastjsonschema-2.21.1-py3-none-any.whl", hash = "sha256:c9e5b7e908310918cf494a434eeb31384dd84a98b57a30bcb1f535015b554667"}, + {file = "fastjsonschema-2.21.1.tar.gz", hash = "sha256:794d4f0a58f848961ba16af7b9c85a3e88cd360df008c59aac6fc5ae9323b5d4"}, +] + +[package.extras] +devel = ["colorama", "json-spec", "jsonschema", "pylint", "pytest", "pytest-benchmark", "pytest-cache", "validictory"] + +[[package]] +name = "fqdn" +version = "1.5.1" +description = "Validates fully-qualified domain names against RFC 1123, so that they are acceptable to modern bowsers" +optional = false +python-versions = ">=2.7, !=3.0, !=3.1, !=3.2, !=3.3, !=3.4, <4" +groups = ["dev"] +files = [ + {file = "fqdn-1.5.1-py3-none-any.whl", hash = "sha256:3a179af3761e4df6eb2e026ff9e1a3033d3587bf980a0b1b2e1e5d08d7358014"}, + {file = "fqdn-1.5.1.tar.gz", hash = "sha256:105ed3677e767fb5ca086a0c1f4bb66ebc3c100be518f0e0d755d9eae164d89f"}, +] + +[[package]] +name = "h11" +version = "0.16.0" +description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "h11-0.16.0-py3-none-any.whl", hash = "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86"}, + {file = "h11-0.16.0.tar.gz", hash = "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1"}, +] + +[[package]] +name = "httpcore" +version = "1.0.9" +description = "A minimal low-level HTTP client." +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "httpcore-1.0.9-py3-none-any.whl", hash = "sha256:2d400746a40668fc9dec9810239072b40b4484b640a8c38fd654a024c7a1bf55"}, + {file = "httpcore-1.0.9.tar.gz", hash = "sha256:6e34463af53fd2ab5d807f399a9b45ea31c3dfa2276f15a2c3f00afff6e176e8"}, +] + +[package.dependencies] +certifi = "*" +h11 = ">=0.16" + +[package.extras] +asyncio = ["anyio (>=4.0,<5.0)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] +trio = ["trio (>=0.22.0,<1.0)"] + +[[package]] +name = "httpx" +version = "0.28.1" +description = "The next generation HTTP client." +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "httpx-0.28.1-py3-none-any.whl", hash = "sha256:d909fcccc110f8c7faf814ca82a9a4d816bc5a6dbfea25d6591d6985b8ba59ad"}, + {file = "httpx-0.28.1.tar.gz", hash = "sha256:75e98c5f16b0f35b567856f597f06ff2270a374470a5c2392242528e3e3e42fc"}, +] + +[package.dependencies] +anyio = "*" +certifi = "*" +httpcore = "==1.*" +idna = "*" + +[package.extras] +brotli = ["brotli ; platform_python_implementation == \"CPython\"", "brotlicffi ; platform_python_implementation != \"CPython\""] +cli = ["click (==8.*)", "pygments (==2.*)", "rich (>=10,<14)"] +http2 = ["h2 (>=3,<5)"] +socks = ["socksio (==1.*)"] +zstd = ["zstandard (>=0.18.0)"] + +[[package]] +name = "idna" +version = "3.10" +description = "Internationalized Domain Names in Applications (IDNA)" +optional = false +python-versions = ">=3.6" +groups = ["main", "dev"] +files = [ + {file = "idna-3.10-py3-none-any.whl", hash = "sha256:946d195a0d259cbba61165e88e65941f16e9b36ea6ddb97f00452bae8b1287d3"}, + {file = "idna-3.10.tar.gz", hash = "sha256:12f65c9b470abda6dc35cf8e63cc574b1c52b11df2c86030af0ac09b01b13ea9"}, +] + +[package.extras] +all = ["flake8 (>=7.1.1)", "mypy (>=1.11.2)", "pytest (>=8.3.2)", "ruff (>=0.6.2)"] + +[[package]] +name = "iniconfig" +version = "2.1.0" +description = "brain-dead simple config-ini parsing" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760"}, + {file = "iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7"}, +] + +[[package]] +name = "ipykernel" +version = "6.30.1" +description = "IPython Kernel for Jupyter" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "ipykernel-6.30.1-py3-none-any.whl", hash = "sha256:aa6b9fb93dca949069d8b85b6c79b2518e32ac583ae9c7d37c51d119e18b3fb4"}, + {file = "ipykernel-6.30.1.tar.gz", hash = "sha256:6abb270161896402e76b91394fcdce5d1be5d45f456671e5080572f8505be39b"}, +] + +[package.dependencies] +appnope = {version = ">=0.1.2", markers = "platform_system == \"Darwin\""} +comm = ">=0.1.1" +debugpy = ">=1.6.5" +ipython = ">=7.23.1" +jupyter-client = ">=8.0.0" +jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" +matplotlib-inline = ">=0.1" +nest-asyncio = ">=1.4" +packaging = ">=22" +psutil = ">=5.7" +pyzmq = ">=25" +tornado = ">=6.2" +traitlets = ">=5.4.0" + +[package.extras] +cov = ["coverage[toml]", "matplotlib", "pytest-cov", "trio"] +docs = ["intersphinx-registry", "myst-parser", "pydata-sphinx-theme", "sphinx", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling", "trio"] +pyqt5 = ["pyqt5"] +pyside6 = ["pyside6"] +test = ["flaky", "ipyparallel", "pre-commit", "pytest (>=7.0,<9)", "pytest-asyncio (>=0.23.5)", "pytest-cov", "pytest-timeout"] + +[[package]] +name = "ipython" +version = "9.4.0" +description = "IPython: Productive Interactive Computing" +optional = false +python-versions = ">=3.11" +groups = ["dev"] +files = [ + {file = "ipython-9.4.0-py3-none-any.whl", hash = "sha256:25850f025a446d9b359e8d296ba175a36aedd32e83ca9b5060430fe16801f066"}, + {file = "ipython-9.4.0.tar.gz", hash = "sha256:c033c6d4e7914c3d9768aabe76bbe87ba1dc66a92a05db6bfa1125d81f2ee270"}, +] + +[package.dependencies] +colorama = {version = "*", markers = "sys_platform == \"win32\""} +decorator = "*" +ipython-pygments-lexers = "*" +jedi = ">=0.16" +matplotlib-inline = "*" +pexpect = {version = ">4.3", markers = "sys_platform != \"win32\" and sys_platform != \"emscripten\""} +prompt_toolkit = ">=3.0.41,<3.1.0" +pygments = ">=2.4.0" +stack_data = "*" +traitlets = ">=5.13.0" + +[package.extras] +all = ["ipython[doc,matplotlib,test,test-extra]"] +black = ["black"] +doc = ["docrepr", "exceptiongroup", "intersphinx_registry", "ipykernel", "ipython[test]", "matplotlib", "setuptools (>=18.5)", "sphinx (>=1.3)", "sphinx-rtd-theme", "sphinx_toml (==0.0.4)", "typing_extensions"] +matplotlib = ["matplotlib"] +test = ["packaging", "pytest", "pytest-asyncio (<0.22)", "testpath"] +test-extra = ["curio", "ipykernel", "ipython[test]", "jupyter_ai", "matplotlib (!=3.2.0)", "nbclient", "nbformat", "numpy (>=1.23)", "pandas", "trio"] + +[[package]] +name = "ipython-pygments-lexers" +version = "1.1.1" +description = "Defines a variety of Pygments lexers for highlighting IPython code." +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "ipython_pygments_lexers-1.1.1-py3-none-any.whl", hash = "sha256:a9462224a505ade19a605f71f8fa63c2048833ce50abc86768a0d81d876dc81c"}, + {file = "ipython_pygments_lexers-1.1.1.tar.gz", hash = "sha256:09c0138009e56b6854f9535736f4171d855c8c08a563a0dcd8022f78355c7e81"}, +] + +[package.dependencies] +pygments = "*" + +[[package]] +name = "isoduration" +version = "20.11.0" +description = "Operations with ISO 8601 durations" +optional = false +python-versions = ">=3.7" +groups = ["dev"] +files = [ + {file = "isoduration-20.11.0-py3-none-any.whl", hash = "sha256:b2904c2a4228c3d44f409c8ae8e2370eb21a26f7ac2ec5446df141dde3452042"}, + {file = "isoduration-20.11.0.tar.gz", hash = "sha256:ac2f9015137935279eac671f94f89eb00584f940f5dc49462a0c4ee692ba1bd9"}, +] + +[package.dependencies] +arrow = ">=0.15.0" + +[[package]] +name = "isort" +version = "6.0.1" +description = "A Python utility / library to sort Python imports." +optional = false +python-versions = ">=3.9.0" +groups = ["dev"] +files = [ + {file = "isort-6.0.1-py3-none-any.whl", hash = "sha256:2dc5d7f65c9678d94c88dfc29161a320eec67328bc97aad576874cb4be1e9615"}, + {file = "isort-6.0.1.tar.gz", hash = "sha256:1cb5df28dfbc742e490c5e41bad6da41b805b0a8be7bc93cd0fb2a8a890ac450"}, +] + +[package.extras] +colors = ["colorama"] +plugins = ["setuptools"] + +[[package]] +name = "jedi" +version = "0.19.2" +description = "An autocompletion tool for Python that can be used for text editors." +optional = false +python-versions = ">=3.6" +groups = ["dev"] +files = [ + {file = "jedi-0.19.2-py2.py3-none-any.whl", hash = "sha256:a8ef22bde8490f57fe5c7681a3c83cb58874daf72b4784de3cce5b6ef6edb5b9"}, + {file = "jedi-0.19.2.tar.gz", hash = "sha256:4770dc3de41bde3966b02eb84fbcf557fb33cce26ad23da12c742fb50ecb11f0"}, +] + +[package.dependencies] +parso = ">=0.8.4,<0.9.0" + +[package.extras] +docs = ["Jinja2 (==2.11.3)", "MarkupSafe (==1.1.1)", "Pygments (==2.8.1)", "alabaster (==0.7.12)", "babel (==2.9.1)", "chardet (==4.0.0)", "commonmark (==0.8.1)", "docutils (==0.17.1)", "future (==0.18.2)", "idna (==2.10)", "imagesize (==1.2.0)", "mock (==1.0.1)", "packaging (==20.9)", "pyparsing (==2.4.7)", "pytz (==2021.1)", "readthedocs-sphinx-ext (==2.1.4)", "recommonmark (==0.5.0)", "requests (==2.25.1)", "six (==1.15.0)", "snowballstemmer (==2.1.0)", "sphinx (==1.8.5)", "sphinx-rtd-theme (==0.4.3)", "sphinxcontrib-serializinghtml (==1.1.4)", "sphinxcontrib-websupport (==1.2.4)", "urllib3 (==1.26.4)"] +qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"] +testing = ["Django", "attrs", "colorama", "docopt", "pytest (<9.0.0)"] + +[[package]] +name = "jinja2" +version = "3.1.6" +description = "A very fast and expressive template engine." +optional = false +python-versions = ">=3.7" +groups = ["dev"] +files = [ + {file = "jinja2-3.1.6-py3-none-any.whl", hash = "sha256:85ece4451f492d0c13c5dd7c13a64681a86afae63a5f347908daf103ce6d2f67"}, + {file = "jinja2-3.1.6.tar.gz", hash = "sha256:0137fb05990d35f1275a587e9aee6d56da821fc83491a0fb838183be43f66d6d"}, +] + +[package.dependencies] +MarkupSafe = ">=2.0" + +[package.extras] +i18n = ["Babel (>=2.7)"] + +[[package]] +name = "json5" +version = "0.12.1" +description = "A Python implementation of the JSON5 data format." +optional = false +python-versions = ">=3.8.0" +groups = ["dev"] +files = [ + {file = "json5-0.12.1-py3-none-any.whl", hash = "sha256:d9c9b3bc34a5f54d43c35e11ef7cb87d8bdd098c6ace87117a7b7e83e705c1d5"}, + {file = "json5-0.12.1.tar.gz", hash = "sha256:b2743e77b3242f8d03c143dd975a6ec7c52e2f2afe76ed934e53503dd4ad4990"}, +] + +[package.extras] +dev = ["build (==1.2.2.post1)", "coverage (==7.5.4) ; python_version < \"3.9\"", "coverage (==7.8.0) ; python_version >= \"3.9\"", "mypy (==1.14.1) ; python_version < \"3.9\"", "mypy (==1.15.0) ; python_version >= \"3.9\"", "pip (==25.0.1)", "pylint (==3.2.7) ; python_version < \"3.9\"", "pylint (==3.3.6) ; python_version >= \"3.9\"", "ruff (==0.11.2)", "twine (==6.1.0)", "uv (==0.6.11)"] + +[[package]] +name = "jsonpointer" +version = "3.0.0" +description = "Identify specific nodes in a JSON document (RFC 6901)" +optional = false +python-versions = ">=3.7" +groups = ["dev"] +files = [ + {file = "jsonpointer-3.0.0-py2.py3-none-any.whl", hash = "sha256:13e088adc14fca8b6aa8177c044e12701e6ad4b28ff10e65f2267a90109c9942"}, + {file = "jsonpointer-3.0.0.tar.gz", hash = "sha256:2b2d729f2091522d61c3b31f82e11870f60b68f43fbc705cb76bf4b832af59ef"}, +] + +[[package]] +name = "jsonschema" +version = "4.25.0" +description = "An implementation of JSON Schema validation for Python" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "jsonschema-4.25.0-py3-none-any.whl", hash = "sha256:24c2e8da302de79c8b9382fee3e76b355e44d2a4364bb207159ce10b517bd716"}, + {file = "jsonschema-4.25.0.tar.gz", hash = "sha256:e63acf5c11762c0e6672ffb61482bdf57f0876684d8d249c0fe2d730d48bc55f"}, +] + +[package.dependencies] +attrs = ">=22.2.0" +fqdn = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} +idna = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} +isoduration = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} +jsonpointer = {version = ">1.13", optional = true, markers = "extra == \"format-nongpl\""} +jsonschema-specifications = ">=2023.03.6" +referencing = ">=0.28.4" +rfc3339-validator = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} +rfc3986-validator = {version = ">0.1.0", optional = true, markers = "extra == \"format-nongpl\""} +rfc3987-syntax = {version = ">=1.1.0", optional = true, markers = "extra == \"format-nongpl\""} +rpds-py = ">=0.7.1" +uri-template = {version = "*", optional = true, markers = "extra == \"format-nongpl\""} +webcolors = {version = ">=24.6.0", optional = true, markers = "extra == \"format-nongpl\""} + +[package.extras] +format = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3987", "uri-template", "webcolors (>=1.11)"] +format-nongpl = ["fqdn", "idna", "isoduration", "jsonpointer (>1.13)", "rfc3339-validator", "rfc3986-validator (>0.1.0)", "rfc3987-syntax (>=1.1.0)", "uri-template", "webcolors (>=24.6.0)"] + +[[package]] +name = "jsonschema-specifications" +version = "2025.4.1" +description = "The JSON Schema meta-schemas and vocabularies, exposed as a Registry" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "jsonschema_specifications-2025.4.1-py3-none-any.whl", hash = "sha256:4653bffbd6584f7de83a67e0d620ef16900b390ddc7939d56684d6c81e33f1af"}, + {file = "jsonschema_specifications-2025.4.1.tar.gz", hash = "sha256:630159c9f4dbea161a6a2205c3011cc4f18ff381b189fff48bb39b9bf26ae608"}, +] + +[package.dependencies] +referencing = ">=0.31.0" + +[[package]] +name = "jupyter-client" +version = "8.6.3" +description = "Jupyter protocol implementation and client libraries" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "jupyter_client-8.6.3-py3-none-any.whl", hash = "sha256:e8a19cc986cc45905ac3362915f410f3af85424b4c0905e94fa5f2cb08e8f23f"}, + {file = "jupyter_client-8.6.3.tar.gz", hash = "sha256:35b3a0947c4a6e9d589eb97d7d4cd5e90f910ee73101611f01283732bd6d9419"}, +] + +[package.dependencies] +jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" +python-dateutil = ">=2.8.2" +pyzmq = ">=23.0" +tornado = ">=6.2" +traitlets = ">=5.3" + +[package.extras] +docs = ["ipykernel", "myst-parser", "pydata-sphinx-theme", "sphinx (>=4)", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-spelling"] +test = ["coverage", "ipykernel (>=6.14)", "mypy", "paramiko ; sys_platform == \"win32\"", "pre-commit", "pytest (<8.2.0)", "pytest-cov", "pytest-jupyter[client] (>=0.4.1)", "pytest-timeout"] + +[[package]] +name = "jupyter-core" +version = "5.8.1" +description = "Jupyter core package. A base package on which Jupyter projects rely." +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "jupyter_core-5.8.1-py3-none-any.whl", hash = "sha256:c28d268fc90fb53f1338ded2eb410704c5449a358406e8a948b75706e24863d0"}, + {file = "jupyter_core-5.8.1.tar.gz", hash = "sha256:0a5f9706f70e64786b75acba995988915ebd4601c8a52e534a40b51c95f59941"}, +] + +[package.dependencies] +platformdirs = ">=2.5" +pywin32 = {version = ">=300", markers = "sys_platform == \"win32\" and platform_python_implementation != \"PyPy\""} +traitlets = ">=5.3" + +[package.extras] +docs = ["intersphinx-registry", "myst-parser", "pydata-sphinx-theme", "sphinx-autodoc-typehints", "sphinxcontrib-spelling", "traitlets"] +test = ["ipykernel", "pre-commit", "pytest (<9)", "pytest-cov", "pytest-timeout"] + +[[package]] +name = "jupyter-events" +version = "0.12.0" +description = "Jupyter Event System library" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "jupyter_events-0.12.0-py3-none-any.whl", hash = "sha256:6464b2fa5ad10451c3d35fabc75eab39556ae1e2853ad0c0cc31b656731a97fb"}, + {file = "jupyter_events-0.12.0.tar.gz", hash = "sha256:fc3fce98865f6784c9cd0a56a20644fc6098f21c8c33834a8d9fe383c17e554b"}, +] + +[package.dependencies] +jsonschema = {version = ">=4.18.0", extras = ["format-nongpl"]} +packaging = "*" +python-json-logger = ">=2.0.4" +pyyaml = ">=5.3" +referencing = "*" +rfc3339-validator = "*" +rfc3986-validator = ">=0.1.1" +traitlets = ">=5.3" + +[package.extras] +cli = ["click", "rich"] +docs = ["jupyterlite-sphinx", "myst-parser", "pydata-sphinx-theme (>=0.16)", "sphinx (>=8)", "sphinxcontrib-spelling"] +test = ["click", "pre-commit", "pytest (>=7.0)", "pytest-asyncio (>=0.19.0)", "pytest-console-scripts", "rich"] + +[[package]] +name = "jupyter-lsp" +version = "2.2.6" +description = "Multi-Language Server WebSocket proxy for Jupyter Notebook/Lab server" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "jupyter_lsp-2.2.6-py3-none-any.whl", hash = "sha256:283783752bf0b459ee7fa88effa72104d87dd343b82d5c06cf113ef755b15b6d"}, + {file = "jupyter_lsp-2.2.6.tar.gz", hash = "sha256:0566bd9bb04fd9e6774a937ed01522b555ba78be37bebef787c8ab22de4c0361"}, +] + +[package.dependencies] +jupyter_server = ">=1.1.2" + +[[package]] +name = "jupyter-server" +version = "2.16.0" +description = "The backend—i.e. core services, APIs, and REST endpoints—to Jupyter web applications." +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "jupyter_server-2.16.0-py3-none-any.whl", hash = "sha256:3d8db5be3bc64403b1c65b400a1d7f4647a5ce743f3b20dbdefe8ddb7b55af9e"}, + {file = "jupyter_server-2.16.0.tar.gz", hash = "sha256:65d4b44fdf2dcbbdfe0aa1ace4a842d4aaf746a2b7b168134d5aaed35621b7f6"}, +] + +[package.dependencies] +anyio = ">=3.1.0" +argon2-cffi = ">=21.1" +jinja2 = ">=3.0.3" +jupyter-client = ">=7.4.4" +jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" +jupyter-events = ">=0.11.0" +jupyter-server-terminals = ">=0.4.4" +nbconvert = ">=6.4.4" +nbformat = ">=5.3.0" +overrides = ">=5.0" +packaging = ">=22.0" +prometheus-client = ">=0.9" +pywinpty = {version = ">=2.0.1", markers = "os_name == \"nt\""} +pyzmq = ">=24" +send2trash = ">=1.8.2" +terminado = ">=0.8.3" +tornado = ">=6.2.0" +traitlets = ">=5.6.0" +websocket-client = ">=1.7" + +[package.extras] +docs = ["ipykernel", "jinja2", "jupyter-client", "myst-parser", "nbformat", "prometheus-client", "pydata-sphinx-theme", "send2trash", "sphinx-autodoc-typehints", "sphinxcontrib-github-alt", "sphinxcontrib-openapi (>=0.8.0)", "sphinxcontrib-spelling", "sphinxemoji", "tornado", "typing-extensions"] +test = ["flaky", "ipykernel", "pre-commit", "pytest (>=7.0,<9)", "pytest-console-scripts", "pytest-jupyter[server] (>=0.7)", "pytest-timeout", "requests"] + +[[package]] +name = "jupyter-server-terminals" +version = "0.5.3" +description = "A Jupyter Server Extension Providing Terminals." +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "jupyter_server_terminals-0.5.3-py3-none-any.whl", hash = "sha256:41ee0d7dc0ebf2809c668e0fc726dfaf258fcd3e769568996ca731b6194ae9aa"}, + {file = "jupyter_server_terminals-0.5.3.tar.gz", hash = "sha256:5ae0295167220e9ace0edcfdb212afd2b01ee8d179fe6f23c899590e9b8a5269"}, +] + +[package.dependencies] +pywinpty = {version = ">=2.0.3", markers = "os_name == \"nt\""} +terminado = ">=0.8.3" + +[package.extras] +docs = ["jinja2", "jupyter-server", "mistune (<4.0)", "myst-parser", "nbformat", "packaging", "pydata-sphinx-theme", "sphinxcontrib-github-alt", "sphinxcontrib-openapi", "sphinxcontrib-spelling", "sphinxemoji", "tornado"] +test = ["jupyter-server (>=2.0.0)", "pytest (>=7.0)", "pytest-jupyter[server] (>=0.5.3)", "pytest-timeout"] + +[[package]] +name = "jupyterlab" +version = "4.4.5" +description = "JupyterLab computational environment" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "jupyterlab-4.4.5-py3-none-any.whl", hash = "sha256:e76244cceb2d1fb4a99341f3edc866f2a13a9e14c50368d730d75d8017be0863"}, + {file = "jupyterlab-4.4.5.tar.gz", hash = "sha256:0bd6c18e6a3c3d91388af6540afa3d0bb0b2e76287a7b88ddf20ab41b336e595"}, +] + +[package.dependencies] +async-lru = ">=1.0.0" +httpx = ">=0.25.0" +ipykernel = ">=6.5.0" +jinja2 = ">=3.0.3" +jupyter-core = "*" +jupyter-lsp = ">=2.0.0" +jupyter-server = ">=2.4.0,<3" +jupyterlab-server = ">=2.27.1,<3" +notebook-shim = ">=0.2" +packaging = "*" +setuptools = ">=41.1.0" +tornado = ">=6.2.0" +traitlets = "*" + +[package.extras] +dev = ["build", "bump2version", "coverage", "hatch", "pre-commit", "pytest-cov", "ruff (==0.11.4)"] +docs = ["jsx-lexer", "myst-parser", "pydata-sphinx-theme (>=0.13.0)", "pytest", "pytest-check-links", "pytest-jupyter", "sphinx (>=1.8,<8.2.0)", "sphinx-copybutton"] +docs-screenshots = ["altair (==5.5.0)", "ipython (==8.16.1)", "ipywidgets (==8.1.5)", "jupyterlab-geojson (==3.4.0)", "jupyterlab-language-pack-zh-cn (==4.3.post1)", "matplotlib (==3.10.0)", "nbconvert (>=7.0.0)", "pandas (==2.2.3)", "scipy (==1.15.1)", "vega-datasets (==0.9.0)"] +test = ["coverage", "pytest (>=7.0)", "pytest-check-links (>=0.7)", "pytest-console-scripts", "pytest-cov", "pytest-jupyter (>=0.5.3)", "pytest-timeout", "pytest-tornasync", "requests", "requests-cache", "virtualenv"] +upgrade-extension = ["copier (>=9,<10)", "jinja2-time (<0.3)", "pydantic (<3.0)", "pyyaml-include (<3.0)", "tomli-w (<2.0)"] + +[[package]] +name = "jupyterlab-pygments" +version = "0.3.0" +description = "Pygments theme using JupyterLab CSS variables" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "jupyterlab_pygments-0.3.0-py3-none-any.whl", hash = "sha256:841a89020971da1d8693f1a99997aefc5dc424bb1b251fd6322462a1b8842780"}, + {file = "jupyterlab_pygments-0.3.0.tar.gz", hash = "sha256:721aca4d9029252b11cfa9d185e5b5af4d54772bb8072f9b7036f4170054d35d"}, +] + +[[package]] +name = "jupyterlab-server" +version = "2.27.3" +description = "A set of server components for JupyterLab and JupyterLab like applications." +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "jupyterlab_server-2.27.3-py3-none-any.whl", hash = "sha256:e697488f66c3db49df675158a77b3b017520d772c6e1548c7d9bcc5df7944ee4"}, + {file = "jupyterlab_server-2.27.3.tar.gz", hash = "sha256:eb36caca59e74471988f0ae25c77945610b887f777255aa21f8065def9e51ed4"}, +] + +[package.dependencies] +babel = ">=2.10" +jinja2 = ">=3.0.3" +json5 = ">=0.9.0" +jsonschema = ">=4.18.0" +jupyter-server = ">=1.21,<3" +packaging = ">=21.3" +requests = ">=2.31" + +[package.extras] +docs = ["autodoc-traits", "jinja2 (<3.2.0)", "mistune (<4)", "myst-parser", "pydata-sphinx-theme", "sphinx", "sphinx-copybutton", "sphinxcontrib-openapi (>0.8)"] +openapi = ["openapi-core (>=0.18.0,<0.19.0)", "ruamel-yaml"] +test = ["hatch", "ipykernel", "openapi-core (>=0.18.0,<0.19.0)", "openapi-spec-validator (>=0.6.0,<0.8.0)", "pytest (>=7.0,<8)", "pytest-console-scripts", "pytest-cov", "pytest-jupyter[server] (>=0.6.2)", "pytest-timeout", "requests-mock", "ruamel-yaml", "sphinxcontrib-spelling", "strict-rfc3339", "werkzeug"] + +[[package]] +name = "lark" +version = "1.2.2" +description = "a modern parsing library" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "lark-1.2.2-py3-none-any.whl", hash = "sha256:c2276486b02f0f1b90be155f2c8ba4a8e194d42775786db622faccd652d8e80c"}, + {file = "lark-1.2.2.tar.gz", hash = "sha256:ca807d0162cd16cef15a8feecb862d7319e7a09bdb13aef927968e45040fed80"}, +] + +[package.extras] +atomic-cache = ["atomicwrites"] +interegular = ["interegular (>=0.3.1,<0.4.0)"] +nearley = ["js2py"] +regex = ["regex"] + +[[package]] +name = "markupsafe" +version = "3.0.2" +description = "Safely add untrusted strings to HTML/XML markup." +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7e94c425039cde14257288fd61dcfb01963e658efbc0ff54f5306b06054700f8"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9e2d922824181480953426608b81967de705c3cef4d1af983af849d7bd619158"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38a9ef736c01fccdd6600705b09dc574584b89bea478200c5fbf112a6b0d5579"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bbcb445fa71794da8f178f0f6d66789a28d7319071af7a496d4d507ed566270d"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:57cb5a3cf367aeb1d316576250f65edec5bb3be939e9247ae594b4bcbc317dfb"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:3809ede931876f5b2ec92eef964286840ed3540dadf803dd570c3b7e13141a3b"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e07c3764494e3776c602c1e78e298937c3315ccc9043ead7e685b7f2b8d47b3c"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b424c77b206d63d500bcb69fa55ed8d0e6a3774056bdc4839fc9298a7edca171"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-win32.whl", hash = "sha256:fcabf5ff6eea076f859677f5f0b6b5c1a51e70a376b0579e0eadef8db48c6b50"}, + {file = "MarkupSafe-3.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:6af100e168aa82a50e186c82875a5893c5597a0c1ccdb0d8b40240b1f28b969a"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:9025b4018f3a1314059769c7bf15441064b2207cb3f065e6ea1e7359cb46db9d"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:93335ca3812df2f366e80509ae119189886b0f3c2b81325d39efdb84a1e2ae93"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2cb8438c3cbb25e220c2ab33bb226559e7afb3baec11c4f218ffa7308603c832"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a123e330ef0853c6e822384873bef7507557d8e4a082961e1defa947aa59ba84"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e084f686b92e5b83186b07e8a17fc09e38fff551f3602b249881fec658d3eca"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d8213e09c917a951de9d09ecee036d5c7d36cb6cb7dbaece4c71a60d79fb9798"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:5b02fb34468b6aaa40dfc198d813a641e3a63b98c2b05a16b9f80b7ec314185e"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:0bff5e0ae4ef2e1ae4fdf2dfd5b76c75e5c2fa4132d05fc1b0dabcd20c7e28c4"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-win32.whl", hash = "sha256:6c89876f41da747c8d3677a2b540fb32ef5715f97b66eeb0c6b66f5e3ef6f59d"}, + {file = "MarkupSafe-3.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:70a87b411535ccad5ef2f1df5136506a10775d267e197e4cf531ced10537bd6b"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:9778bd8ab0a994ebf6f84c2b949e65736d5575320a17ae8984a77fab08db94cf"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846ade7b71e3536c4e56b386c2a47adf5741d2d8b94ec9dc3e92e5e1ee1e2225"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1c99d261bd2d5f6b59325c92c73df481e05e57f19837bdca8413b9eac4bd8028"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e17c96c14e19278594aa4841ec148115f9c7615a47382ecb6b82bd8fea3ab0c8"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88416bd1e65dcea10bc7569faacb2c20ce071dd1f87539ca2ab364bf6231393c"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:2181e67807fc2fa785d0592dc2d6206c019b9502410671cc905d132a92866557"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:52305740fe773d09cffb16f8ed0427942901f00adedac82ec8b67752f58a1b22"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad10d3ded218f1039f11a75f8091880239651b52e9bb592ca27de44eed242a48"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-win32.whl", hash = "sha256:0f4ca02bea9a23221c0182836703cbf8930c5e9454bacce27e767509fa286a30"}, + {file = "MarkupSafe-3.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:8e06879fc22a25ca47312fbe7c8264eb0b662f6db27cb2d3bbbc74b1df4b9b87"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba9527cdd4c926ed0760bc301f6728ef34d841f405abf9d4f959c478421e4efd"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f8b3d067f2e40fe93e1ccdd6b2e1d16c43140e76f02fb1319a05cf2b79d99430"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:569511d3b58c8791ab4c2e1285575265991e6d8f8700c7be0e88f86cb0672094"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:15ab75ef81add55874e7ab7055e9c397312385bd9ced94920f2802310c930396"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f3818cb119498c0678015754eba762e0d61e5b52d34c8b13d770f0719f7b1d79"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:cdb82a876c47801bb54a690c5ae105a46b392ac6099881cdfb9f6e95e4014c6a"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:cabc348d87e913db6ab4aa100f01b08f481097838bdddf7c7a84b7575b7309ca"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:444dcda765c8a838eaae23112db52f1efaf750daddb2d9ca300bcae1039adc5c"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-win32.whl", hash = "sha256:bcf3e58998965654fdaff38e58584d8937aa3096ab5354d493c77d1fdd66d7a1"}, + {file = "MarkupSafe-3.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:e6a2a455bd412959b57a172ce6328d2dd1f01cb2135efda2e4576e8a23fa3b0f"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:b5a6b3ada725cea8a5e634536b1b01c30bcdcd7f9c6fff4151548d5bf6b3a36c"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:a904af0a6162c73e3edcb969eeeb53a63ceeb5d8cf642fade7d39e7963a22ddb"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa4e5faecf353ed117801a068ebab7b7e09ffb6e1d5e412dc852e0da018126c"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0ef13eaeee5b615fb07c9a7dadb38eac06a0608b41570d8ade51c56539e509d"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d16a81a06776313e817c951135cf7340a3e91e8c1ff2fac444cfd75fffa04afe"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:6381026f158fdb7c72a168278597a5e3a5222e83ea18f543112b2662a9b699c5"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3d79d162e7be8f996986c064d1c7c817f6df3a77fe3d6859f6f9e7be4b8c213a"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:131a3c7689c85f5ad20f9f6fb1b866f402c445b220c19fe4308c0b147ccd2ad9"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-win32.whl", hash = "sha256:ba8062ed2cf21c07a9e295d5b8a2a5ce678b913b45fdf68c32d95d6c1291e0b6"}, + {file = "MarkupSafe-3.0.2-cp313-cp313t-win_amd64.whl", hash = "sha256:e444a31f8db13eb18ada366ab3cf45fd4b31e4db1236a4448f68778c1d1a5a2f"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:eaa0a10b7f72326f1372a713e73c3f739b524b3af41feb43e4921cb529f5929a"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:48032821bbdf20f5799ff537c7ac3d1fba0ba032cfc06194faffa8cda8b560ff"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a9d3f5f0901fdec14d8d2f66ef7d035f2157240a433441719ac9a3fba440b13"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:88b49a3b9ff31e19998750c38e030fc7bb937398b1f78cfa599aaef92d693144"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cfad01eed2c2e0c01fd0ecd2ef42c492f7f93902e39a42fc9ee1692961443a29"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:1225beacc926f536dc82e45f8a4d68502949dc67eea90eab715dea3a21c1b5f0"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:3169b1eefae027567d1ce6ee7cae382c57fe26e82775f460f0b2778beaad66c0"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:eb7972a85c54febfb25b5c4b4f3af4dcc731994c7da0d8a0b4a6eb0640e1d178"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-win32.whl", hash = "sha256:8c4e8c3ce11e1f92f6536ff07154f9d49677ebaaafc32db9db4620bc11ed480f"}, + {file = "MarkupSafe-3.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:6e296a513ca3d94054c2c881cc913116e90fd030ad1c656b3869762b754f5f8a"}, + {file = "markupsafe-3.0.2.tar.gz", hash = "sha256:ee55d3edf80167e48ea11a923c7386f4669df67d7994554387f84e7d8b0a2bf0"}, +] + +[[package]] +name = "matplotlib-inline" +version = "0.1.7" +description = "Inline Matplotlib backend for Jupyter" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "matplotlib_inline-0.1.7-py3-none-any.whl", hash = "sha256:df192d39a4ff8f21b1895d72e6a13f5fcc5099f00fa84384e0ea28c2cc0653ca"}, + {file = "matplotlib_inline-0.1.7.tar.gz", hash = "sha256:8423b23ec666be3d16e16b60bdd8ac4e86e840ebd1dd11a30b9f117f2fa0ab90"}, +] + +[package.dependencies] +traitlets = "*" + +[[package]] +name = "mccabe" +version = "0.7.0" +description = "McCabe checker, plugin for flake8" +optional = false +python-versions = ">=3.6" +groups = ["dev"] +files = [ + {file = "mccabe-0.7.0-py2.py3-none-any.whl", hash = "sha256:6c2d30ab6be0e4a46919781807b4f0d834ebdd6c6e3dca0bda5a15f863427b6e"}, + {file = "mccabe-0.7.0.tar.gz", hash = "sha256:348e0240c33b60bbdf4e523192ef919f28cb2c3d7d5c7794f74009290f236325"}, +] + +[[package]] +name = "mistune" +version = "3.1.3" +description = "A sane and fast Markdown parser with useful plugins and renderers" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "mistune-3.1.3-py3-none-any.whl", hash = "sha256:1a32314113cff28aa6432e99e522677c8587fd83e3d51c29b82a52409c842bd9"}, + {file = "mistune-3.1.3.tar.gz", hash = "sha256:a7035c21782b2becb6be62f8f25d3df81ccb4d6fa477a6525b15af06539f02a0"}, +] + +[[package]] +name = "nbclient" +version = "0.10.2" +description = "A client library for executing notebooks. Formerly nbconvert's ExecutePreprocessor." +optional = false +python-versions = ">=3.9.0" +groups = ["dev"] +files = [ + {file = "nbclient-0.10.2-py3-none-any.whl", hash = "sha256:4ffee11e788b4a27fabeb7955547e4318a5298f34342a4bfd01f2e1faaeadc3d"}, + {file = "nbclient-0.10.2.tar.gz", hash = "sha256:90b7fc6b810630db87a6d0c2250b1f0ab4cf4d3c27a299b0cde78a4ed3fd9193"}, +] + +[package.dependencies] +jupyter-client = ">=6.1.12" +jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" +nbformat = ">=5.1" +traitlets = ">=5.4" + +[package.extras] +dev = ["pre-commit"] +docs = ["autodoc-traits", "flaky", "ipykernel (>=6.19.3)", "ipython", "ipywidgets", "mock", "moto", "myst-parser", "nbconvert (>=7.1.0)", "pytest (>=7.0,<8)", "pytest-asyncio", "pytest-cov (>=4.0)", "sphinx (>=1.7)", "sphinx-book-theme", "sphinxcontrib-spelling", "testpath", "xmltodict"] +test = ["flaky", "ipykernel (>=6.19.3)", "ipython", "ipywidgets", "nbconvert (>=7.1.0)", "pytest (>=7.0,<8)", "pytest-asyncio", "pytest-cov (>=4.0)", "testpath", "xmltodict"] + +[[package]] +name = "nbconvert" +version = "7.16.6" +description = "Converting Jupyter Notebooks (.ipynb files) to other formats. Output formats include asciidoc, html, latex, markdown, pdf, py, rst, script. nbconvert can be used both as a Python library (`import nbconvert`) or as a command line tool (invoked as `jupyter nbconvert ...`)." +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "nbconvert-7.16.6-py3-none-any.whl", hash = "sha256:1375a7b67e0c2883678c48e506dc320febb57685e5ee67faa51b18a90f3a712b"}, + {file = "nbconvert-7.16.6.tar.gz", hash = "sha256:576a7e37c6480da7b8465eefa66c17844243816ce1ccc372633c6b71c3c0f582"}, +] + +[package.dependencies] +beautifulsoup4 = "*" +bleach = {version = "!=5.0.0", extras = ["css"]} +defusedxml = "*" +jinja2 = ">=3.0" +jupyter-core = ">=4.7" +jupyterlab-pygments = "*" +markupsafe = ">=2.0" +mistune = ">=2.0.3,<4" +nbclient = ">=0.5.0" +nbformat = ">=5.7" +packaging = "*" +pandocfilters = ">=1.4.1" +pygments = ">=2.4.1" +traitlets = ">=5.1" + +[package.extras] +all = ["flaky", "ipykernel", "ipython", "ipywidgets (>=7.5)", "myst-parser", "nbsphinx (>=0.2.12)", "playwright", "pydata-sphinx-theme", "pyqtwebengine (>=5.15)", "pytest (>=7)", "sphinx (==5.0.2)", "sphinxcontrib-spelling", "tornado (>=6.1)"] +docs = ["ipykernel", "ipython", "myst-parser", "nbsphinx (>=0.2.12)", "pydata-sphinx-theme", "sphinx (==5.0.2)", "sphinxcontrib-spelling"] +qtpdf = ["pyqtwebengine (>=5.15)"] +qtpng = ["pyqtwebengine (>=5.15)"] +serve = ["tornado (>=6.1)"] +test = ["flaky", "ipykernel", "ipywidgets (>=7.5)", "pytest (>=7)"] +webpdf = ["playwright"] + +[[package]] +name = "nbformat" +version = "5.10.4" +description = "The Jupyter Notebook format" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "nbformat-5.10.4-py3-none-any.whl", hash = "sha256:3b48d6c8fbca4b299bf3982ea7db1af21580e4fec269ad087b9e81588891200b"}, + {file = "nbformat-5.10.4.tar.gz", hash = "sha256:322168b14f937a5d11362988ecac2a4952d3d8e3a2cbeb2319584631226d5b3a"}, +] + +[package.dependencies] +fastjsonschema = ">=2.15" +jsonschema = ">=2.6" +jupyter-core = ">=4.12,<5.0.dev0 || >=5.1.dev0" +traitlets = ">=5.1" + +[package.extras] +docs = ["myst-parser", "pydata-sphinx-theme", "sphinx", "sphinxcontrib-github-alt", "sphinxcontrib-spelling"] +test = ["pep440", "pre-commit", "pytest", "testpath"] + +[[package]] +name = "nest-asyncio" +version = "1.6.0" +description = "Patch asyncio to allow nested event loops" +optional = false +python-versions = ">=3.5" +groups = ["dev"] +files = [ + {file = "nest_asyncio-1.6.0-py3-none-any.whl", hash = "sha256:87af6efd6b5e897c81050477ef65c62e2b2f35d51703cae01aff2905b1852e1c"}, + {file = "nest_asyncio-1.6.0.tar.gz", hash = "sha256:6f172d5449aca15afd6c646851f4e31e02c598d553a667e38cafa997cfec55fe"}, +] + +[[package]] +name = "notebook" +version = "7.4.5" +description = "Jupyter Notebook - A web-based notebook environment for interactive computing" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "notebook-7.4.5-py3-none-any.whl", hash = "sha256:351635461aca9dad08cf8946a4216f963e2760cc1bf7b1aaaecb23afc33ec046"}, + {file = "notebook-7.4.5.tar.gz", hash = "sha256:7c2c4ea245913c3ad8ab3e5d36b34a842c06e524556f5c2e1f5d7d08c986615e"}, +] + +[package.dependencies] +jupyter-server = ">=2.4.0,<3" +jupyterlab = ">=4.4.5,<4.5" +jupyterlab-server = ">=2.27.1,<3" +notebook-shim = ">=0.2,<0.3" +tornado = ">=6.2.0" + +[package.extras] +dev = ["hatch", "pre-commit"] +docs = ["myst-parser", "nbsphinx", "pydata-sphinx-theme", "sphinx (>=1.3.6)", "sphinxcontrib-github-alt", "sphinxcontrib-spelling"] +test = ["importlib-resources (>=5.0) ; python_version < \"3.10\"", "ipykernel", "jupyter-server[test] (>=2.4.0,<3)", "jupyterlab-server[test] (>=2.27.1,<3)", "nbval", "pytest (>=7.0)", "pytest-console-scripts", "pytest-timeout", "pytest-tornasync", "requests"] + +[[package]] +name = "notebook-shim" +version = "0.2.4" +description = "A shim layer for notebook traits and config" +optional = false +python-versions = ">=3.7" +groups = ["dev"] +files = [ + {file = "notebook_shim-0.2.4-py3-none-any.whl", hash = "sha256:411a5be4e9dc882a074ccbcae671eda64cceb068767e9a3419096986560e1cef"}, + {file = "notebook_shim-0.2.4.tar.gz", hash = "sha256:b4b2cfa1b65d98307ca24361f5b30fe785b53c3fd07b7a47e89acb5e6ac638cb"}, +] + +[package.dependencies] +jupyter-server = ">=1.8,<3" + +[package.extras] +test = ["pytest", "pytest-console-scripts", "pytest-jupyter", "pytest-tornasync"] + +[[package]] +name = "numpy" +version = "2.3.2" +description = "Fundamental package for array computing in Python" +optional = false +python-versions = ">=3.11" +groups = ["main"] +files = [ + {file = "numpy-2.3.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:852ae5bed3478b92f093e30f785c98e0cb62fa0a939ed057c31716e18a7a22b9"}, + {file = "numpy-2.3.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7a0e27186e781a69959d0230dd9909b5e26024f8da10683bd6344baea1885168"}, + {file = "numpy-2.3.2-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:f0a1a8476ad77a228e41619af2fa9505cf69df928e9aaa165746584ea17fed2b"}, + {file = "numpy-2.3.2-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:cbc95b3813920145032412f7e33d12080f11dc776262df1712e1638207dde9e8"}, + {file = "numpy-2.3.2-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f75018be4980a7324edc5930fe39aa391d5734531b1926968605416ff58c332d"}, + {file = "numpy-2.3.2-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:20b8200721840f5621b7bd03f8dcd78de33ec522fc40dc2641aa09537df010c3"}, + {file = "numpy-2.3.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1f91e5c028504660d606340a084db4b216567ded1056ea2b4be4f9d10b67197f"}, + {file = "numpy-2.3.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:fb1752a3bb9a3ad2d6b090b88a9a0ae1cd6f004ef95f75825e2f382c183b2097"}, + {file = "numpy-2.3.2-cp311-cp311-win32.whl", hash = "sha256:4ae6863868aaee2f57503c7a5052b3a2807cf7a3914475e637a0ecd366ced220"}, + {file = "numpy-2.3.2-cp311-cp311-win_amd64.whl", hash = "sha256:240259d6564f1c65424bcd10f435145a7644a65a6811cfc3201c4a429ba79170"}, + {file = "numpy-2.3.2-cp311-cp311-win_arm64.whl", hash = "sha256:4209f874d45f921bde2cff1ffcd8a3695f545ad2ffbef6d3d3c6768162efab89"}, + {file = "numpy-2.3.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:bc3186bea41fae9d8e90c2b4fb5f0a1f5a690682da79b92574d63f56b529080b"}, + {file = "numpy-2.3.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2f4f0215edb189048a3c03bd5b19345bdfa7b45a7a6f72ae5945d2a28272727f"}, + {file = "numpy-2.3.2-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:8b1224a734cd509f70816455c3cffe13a4f599b1bf7130f913ba0e2c0b2006c0"}, + {file = "numpy-2.3.2-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:3dcf02866b977a38ba3ec10215220609ab9667378a9e2150615673f3ffd6c73b"}, + {file = "numpy-2.3.2-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:572d5512df5470f50ada8d1972c5f1082d9a0b7aa5944db8084077570cf98370"}, + {file = "numpy-2.3.2-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8145dd6d10df13c559d1e4314df29695613575183fa2e2d11fac4c208c8a1f73"}, + {file = "numpy-2.3.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:103ea7063fa624af04a791c39f97070bf93b96d7af7eb23530cd087dc8dbe9dc"}, + {file = "numpy-2.3.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:fc927d7f289d14f5e037be917539620603294454130b6de200091e23d27dc9be"}, + {file = "numpy-2.3.2-cp312-cp312-win32.whl", hash = "sha256:d95f59afe7f808c103be692175008bab926b59309ade3e6d25009e9a171f7036"}, + {file = "numpy-2.3.2-cp312-cp312-win_amd64.whl", hash = "sha256:9e196ade2400c0c737d93465327d1ae7c06c7cb8a1756121ebf54b06ca183c7f"}, + {file = "numpy-2.3.2-cp312-cp312-win_arm64.whl", hash = "sha256:ee807923782faaf60d0d7331f5e86da7d5e3079e28b291973c545476c2b00d07"}, + {file = "numpy-2.3.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c8d9727f5316a256425892b043736d63e89ed15bbfe6556c5ff4d9d4448ff3b3"}, + {file = "numpy-2.3.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:efc81393f25f14d11c9d161e46e6ee348637c0a1e8a54bf9dedc472a3fae993b"}, + {file = "numpy-2.3.2-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:dd937f088a2df683cbb79dda9a772b62a3e5a8a7e76690612c2737f38c6ef1b6"}, + {file = "numpy-2.3.2-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:11e58218c0c46c80509186e460d79fbdc9ca1eb8d8aee39d8f2dc768eb781089"}, + {file = "numpy-2.3.2-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5ad4ebcb683a1f99f4f392cc522ee20a18b2bb12a2c1c42c3d48d5a1adc9d3d2"}, + {file = "numpy-2.3.2-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:938065908d1d869c7d75d8ec45f735a034771c6ea07088867f713d1cd3bbbe4f"}, + {file = "numpy-2.3.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:66459dccc65d8ec98cc7df61307b64bf9e08101f9598755d42d8ae65d9a7a6ee"}, + {file = "numpy-2.3.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:a7af9ed2aa9ec5950daf05bb11abc4076a108bd3c7db9aa7251d5f107079b6a6"}, + {file = "numpy-2.3.2-cp313-cp313-win32.whl", hash = "sha256:906a30249315f9c8e17b085cc5f87d3f369b35fedd0051d4a84686967bdbbd0b"}, + {file = "numpy-2.3.2-cp313-cp313-win_amd64.whl", hash = "sha256:c63d95dc9d67b676e9108fe0d2182987ccb0f11933c1e8959f42fa0da8d4fa56"}, + {file = "numpy-2.3.2-cp313-cp313-win_arm64.whl", hash = "sha256:b05a89f2fb84d21235f93de47129dd4f11c16f64c87c33f5e284e6a3a54e43f2"}, + {file = "numpy-2.3.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:4e6ecfeddfa83b02318f4d84acf15fbdbf9ded18e46989a15a8b6995dfbf85ab"}, + {file = "numpy-2.3.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:508b0eada3eded10a3b55725b40806a4b855961040180028f52580c4729916a2"}, + {file = "numpy-2.3.2-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:754d6755d9a7588bdc6ac47dc4ee97867271b17cee39cb87aef079574366db0a"}, + {file = "numpy-2.3.2-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:a9f66e7d2b2d7712410d3bc5684149040ef5f19856f20277cd17ea83e5006286"}, + {file = "numpy-2.3.2-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:de6ea4e5a65d5a90c7d286ddff2b87f3f4ad61faa3db8dabe936b34c2275b6f8"}, + {file = "numpy-2.3.2-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a3ef07ec8cbc8fc9e369c8dcd52019510c12da4de81367d8b20bc692aa07573a"}, + {file = "numpy-2.3.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:27c9f90e7481275c7800dc9c24b7cc40ace3fdb970ae4d21eaff983a32f70c91"}, + {file = "numpy-2.3.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:07b62978075b67eee4065b166d000d457c82a1efe726cce608b9db9dd66a73a5"}, + {file = "numpy-2.3.2-cp313-cp313t-win32.whl", hash = "sha256:c771cfac34a4f2c0de8e8c97312d07d64fd8f8ed45bc9f5726a7e947270152b5"}, + {file = "numpy-2.3.2-cp313-cp313t-win_amd64.whl", hash = "sha256:72dbebb2dcc8305c431b2836bcc66af967df91be793d63a24e3d9b741374c450"}, + {file = "numpy-2.3.2-cp313-cp313t-win_arm64.whl", hash = "sha256:72c6df2267e926a6d5286b0a6d556ebe49eae261062059317837fda12ddf0c1a"}, + {file = "numpy-2.3.2-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:448a66d052d0cf14ce9865d159bfc403282c9bc7bb2a31b03cc18b651eca8b1a"}, + {file = "numpy-2.3.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:546aaf78e81b4081b2eba1d105c3b34064783027a06b3ab20b6eba21fb64132b"}, + {file = "numpy-2.3.2-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:87c930d52f45df092f7578889711a0768094debf73cfcde105e2d66954358125"}, + {file = "numpy-2.3.2-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:8dc082ea901a62edb8f59713c6a7e28a85daddcb67454c839de57656478f5b19"}, + {file = "numpy-2.3.2-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:af58de8745f7fa9ca1c0c7c943616c6fe28e75d0c81f5c295810e3c83b5be92f"}, + {file = "numpy-2.3.2-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fed5527c4cf10f16c6d0b6bee1f89958bccb0ad2522c8cadc2efd318bcd545f5"}, + {file = "numpy-2.3.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:095737ed986e00393ec18ec0b21b47c22889ae4b0cd2d5e88342e08b01141f58"}, + {file = "numpy-2.3.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b5e40e80299607f597e1a8a247ff8d71d79c5b52baa11cc1cce30aa92d2da6e0"}, + {file = "numpy-2.3.2-cp314-cp314-win32.whl", hash = "sha256:7d6e390423cc1f76e1b8108c9b6889d20a7a1f59d9a60cac4a050fa734d6c1e2"}, + {file = "numpy-2.3.2-cp314-cp314-win_amd64.whl", hash = "sha256:b9d0878b21e3918d76d2209c924ebb272340da1fb51abc00f986c258cd5e957b"}, + {file = "numpy-2.3.2-cp314-cp314-win_arm64.whl", hash = "sha256:2738534837c6a1d0c39340a190177d7d66fdf432894f469728da901f8f6dc910"}, + {file = "numpy-2.3.2-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:4d002ecf7c9b53240be3bb69d80f86ddbd34078bae04d87be81c1f58466f264e"}, + {file = "numpy-2.3.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:293b2192c6bcce487dbc6326de5853787f870aeb6c43f8f9c6496db5b1781e45"}, + {file = "numpy-2.3.2-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:0a4f2021a6da53a0d580d6ef5db29947025ae8b35b3250141805ea9a32bbe86b"}, + {file = "numpy-2.3.2-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:9c144440db4bf3bb6372d2c3e49834cc0ff7bb4c24975ab33e01199e645416f2"}, + {file = "numpy-2.3.2-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f92d6c2a8535dc4fe4419562294ff957f83a16ebdec66df0805e473ffaad8bd0"}, + {file = "numpy-2.3.2-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:cefc2219baa48e468e3db7e706305fcd0c095534a192a08f31e98d83a7d45fb0"}, + {file = "numpy-2.3.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:76c3e9501ceb50b2ff3824c3589d5d1ab4ac857b0ee3f8f49629d0de55ecf7c2"}, + {file = "numpy-2.3.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:122bf5ed9a0221b3419672493878ba4967121514b1d7d4656a7580cd11dddcbf"}, + {file = "numpy-2.3.2-cp314-cp314t-win32.whl", hash = "sha256:6f1ae3dcb840edccc45af496f312528c15b1f79ac318169d094e85e4bb35fdf1"}, + {file = "numpy-2.3.2-cp314-cp314t-win_amd64.whl", hash = "sha256:087ffc25890d89a43536f75c5fe8770922008758e8eeeef61733957041ed2f9b"}, + {file = "numpy-2.3.2-cp314-cp314t-win_arm64.whl", hash = "sha256:092aeb3449833ea9c0bf0089d70c29ae480685dd2377ec9cdbbb620257f84631"}, + {file = "numpy-2.3.2-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:14a91ebac98813a49bc6aa1a0dfc09513dcec1d97eaf31ca21a87221a1cdcb15"}, + {file = "numpy-2.3.2-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:71669b5daae692189540cffc4c439468d35a3f84f0c88b078ecd94337f6cb0ec"}, + {file = "numpy-2.3.2-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:69779198d9caee6e547adb933941ed7520f896fd9656834c300bdf4dd8642712"}, + {file = "numpy-2.3.2-pp311-pypy311_pp73-macosx_14_0_x86_64.whl", hash = "sha256:2c3271cc4097beb5a60f010bcc1cc204b300bb3eafb4399376418a83a1c6373c"}, + {file = "numpy-2.3.2-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8446acd11fe3dc1830568c941d44449fd5cb83068e5c70bd5a470d323d448296"}, + {file = "numpy-2.3.2-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:aa098a5ab53fa407fded5870865c6275a5cd4101cfdef8d6fafc48286a96e981"}, + {file = "numpy-2.3.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:6936aff90dda378c09bea075af0d9c675fe3a977a9d2402f95a87f440f59f619"}, + {file = "numpy-2.3.2.tar.gz", hash = "sha256:e0486a11ec30cdecb53f184d496d1c6a20786c81e55e41640270130056f8ee48"}, +] + +[[package]] +name = "openpyxl" +version = "3.1.5" +description = "A Python library to read/write Excel 2010 xlsx/xlsm files" +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "openpyxl-3.1.5-py2.py3-none-any.whl", hash = "sha256:5282c12b107bffeef825f4617dc029afaf41d0ea60823bbb665ef3079dc79de2"}, + {file = "openpyxl-3.1.5.tar.gz", hash = "sha256:cf0e3cf56142039133628b5acffe8ef0c12bc902d2aadd3e0fe5878dc08d1050"}, +] + +[package.dependencies] +et-xmlfile = "*" + +[[package]] +name = "overrides" +version = "7.7.0" +description = "A decorator to automatically detect mismatch when overriding a method." +optional = false +python-versions = ">=3.6" +groups = ["dev"] +files = [ + {file = "overrides-7.7.0-py3-none-any.whl", hash = "sha256:c7ed9d062f78b8e4c1a7b70bd8796b35ead4d9f510227ef9c5dc7626c60d7e49"}, + {file = "overrides-7.7.0.tar.gz", hash = "sha256:55158fa3d93b98cc75299b1e67078ad9003ca27945c76162c1c0766d6f91820a"}, +] + +[[package]] +name = "packaging" +version = "25.0" +description = "Core utilities for Python packages" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484"}, + {file = "packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f"}, +] + +[[package]] +name = "pandas" +version = "2.3.1" +description = "Powerful data structures for data analysis, time series, and statistics" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "pandas-2.3.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:22c2e866f7209ebc3a8f08d75766566aae02bcc91d196935a1d9e59c7b990ac9"}, + {file = "pandas-2.3.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:3583d348546201aff730c8c47e49bc159833f971c2899d6097bce68b9112a4f1"}, + {file = "pandas-2.3.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0f951fbb702dacd390561e0ea45cdd8ecfa7fb56935eb3dd78e306c19104b9b0"}, + {file = "pandas-2.3.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cd05b72ec02ebfb993569b4931b2e16fbb4d6ad6ce80224a3ee838387d83a191"}, + {file = "pandas-2.3.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1b916a627919a247d865aed068eb65eb91a344b13f5b57ab9f610b7716c92de1"}, + {file = "pandas-2.3.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:fe67dc676818c186d5a3d5425250e40f179c2a89145df477dd82945eaea89e97"}, + {file = "pandas-2.3.1-cp310-cp310-win_amd64.whl", hash = "sha256:2eb789ae0274672acbd3c575b0598d213345660120a257b47b5dafdc618aec83"}, + {file = "pandas-2.3.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:2b0540963d83431f5ce8870ea02a7430adca100cec8a050f0811f8e31035541b"}, + {file = "pandas-2.3.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fe7317f578c6a153912bd2292f02e40c1d8f253e93c599e82620c7f69755c74f"}, + {file = "pandas-2.3.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e6723a27ad7b244c0c79d8e7007092d7c8f0f11305770e2f4cd778b3ad5f9f85"}, + {file = "pandas-2.3.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3462c3735fe19f2638f2c3a40bd94ec2dc5ba13abbb032dd2fa1f540a075509d"}, + {file = "pandas-2.3.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:98bcc8b5bf7afed22cc753a28bc4d9e26e078e777066bc53fac7904ddef9a678"}, + {file = "pandas-2.3.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:4d544806b485ddf29e52d75b1f559142514e60ef58a832f74fb38e48d757b299"}, + {file = "pandas-2.3.1-cp311-cp311-win_amd64.whl", hash = "sha256:b3cd4273d3cb3707b6fffd217204c52ed92859533e31dc03b7c5008aa933aaab"}, + {file = "pandas-2.3.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:689968e841136f9e542020698ee1c4fbe9caa2ed2213ae2388dc7b81721510d3"}, + {file = "pandas-2.3.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:025e92411c16cbe5bb2a4abc99732a6b132f439b8aab23a59fa593eb00704232"}, + {file = "pandas-2.3.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9b7ff55f31c4fcb3e316e8f7fa194566b286d6ac430afec0d461163312c5841e"}, + {file = "pandas-2.3.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7dcb79bf373a47d2a40cf7232928eb7540155abbc460925c2c96d2d30b006eb4"}, + {file = "pandas-2.3.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:56a342b231e8862c96bdb6ab97170e203ce511f4d0429589c8ede1ee8ece48b8"}, + {file = "pandas-2.3.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ca7ed14832bce68baef331f4d7f294411bed8efd032f8109d690df45e00c4679"}, + {file = "pandas-2.3.1-cp312-cp312-win_amd64.whl", hash = "sha256:ac942bfd0aca577bef61f2bc8da8147c4ef6879965ef883d8e8d5d2dc3e744b8"}, + {file = "pandas-2.3.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9026bd4a80108fac2239294a15ef9003c4ee191a0f64b90f170b40cfb7cf2d22"}, + {file = "pandas-2.3.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:6de8547d4fdb12421e2d047a2c446c623ff4c11f47fddb6b9169eb98ffba485a"}, + {file = "pandas-2.3.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:782647ddc63c83133b2506912cc6b108140a38a37292102aaa19c81c83db2928"}, + {file = "pandas-2.3.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2ba6aff74075311fc88504b1db890187a3cd0f887a5b10f5525f8e2ef55bfdb9"}, + {file = "pandas-2.3.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e5635178b387bd2ba4ac040f82bc2ef6e6b500483975c4ebacd34bec945fda12"}, + {file = "pandas-2.3.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6f3bf5ec947526106399a9e1d26d40ee2b259c66422efdf4de63c848492d91bb"}, + {file = "pandas-2.3.1-cp313-cp313-win_amd64.whl", hash = "sha256:1c78cf43c8fde236342a1cb2c34bcff89564a7bfed7e474ed2fffa6aed03a956"}, + {file = "pandas-2.3.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:8dfc17328e8da77be3cf9f47509e5637ba8f137148ed0e9b5241e1baf526e20a"}, + {file = "pandas-2.3.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:ec6c851509364c59a5344458ab935e6451b31b818be467eb24b0fe89bd05b6b9"}, + {file = "pandas-2.3.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:911580460fc4884d9b05254b38a6bfadddfcc6aaef856fb5859e7ca202e45275"}, + {file = "pandas-2.3.1-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2f4d6feeba91744872a600e6edbbd5b033005b431d5ae8379abee5bcfa479fab"}, + {file = "pandas-2.3.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:fe37e757f462d31a9cd7580236a82f353f5713a80e059a29753cf938c6775d96"}, + {file = "pandas-2.3.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:5db9637dbc24b631ff3707269ae4559bce4b7fd75c1c4d7e13f40edc42df4444"}, + {file = "pandas-2.3.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:4645f770f98d656f11c69e81aeb21c6fca076a44bed3dcbb9396a4311bc7f6d8"}, + {file = "pandas-2.3.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:342e59589cc454aaff7484d75b816a433350b3d7964d7847327edda4d532a2e3"}, + {file = "pandas-2.3.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d12f618d80379fde6af007f65f0c25bd3e40251dbd1636480dfffce2cf1e6da"}, + {file = "pandas-2.3.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dd71c47a911da120d72ef173aeac0bf5241423f9bfea57320110a978457e069e"}, + {file = "pandas-2.3.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:09e3b1587f0f3b0913e21e8b32c3119174551deb4a4eba4a89bc7377947977e7"}, + {file = "pandas-2.3.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:2323294c73ed50f612f67e2bf3ae45aea04dce5690778e08a09391897f35ff88"}, + {file = "pandas-2.3.1-cp39-cp39-win_amd64.whl", hash = "sha256:b4b0de34dc8499c2db34000ef8baad684cfa4cbd836ecee05f323ebfba348c7d"}, + {file = "pandas-2.3.1.tar.gz", hash = "sha256:0a95b9ac964fe83ce317827f80304d37388ea77616b1425f0ae41c9d2d0d7bb2"}, +] + +[package.dependencies] +numpy = {version = ">=1.26.0", markers = "python_version >= \"3.12\""} +python-dateutil = ">=2.8.2" +pytz = ">=2020.1" +tzdata = ">=2022.7" + +[package.extras] +all = ["PyQt5 (>=5.15.9)", "SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)", "beautifulsoup4 (>=4.11.2)", "bottleneck (>=1.3.6)", "dataframe-api-compat (>=0.1.7)", "fastparquet (>=2022.12.0)", "fsspec (>=2022.11.0)", "gcsfs (>=2022.11.0)", "html5lib (>=1.1)", "hypothesis (>=6.46.1)", "jinja2 (>=3.1.2)", "lxml (>=4.9.2)", "matplotlib (>=3.6.3)", "numba (>=0.56.4)", "numexpr (>=2.8.4)", "odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "pandas-gbq (>=0.19.0)", "psycopg2 (>=2.9.6)", "pyarrow (>=10.0.1)", "pymysql (>=1.0.2)", "pyreadstat (>=1.2.0)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "qtpy (>=2.3.0)", "s3fs (>=2022.11.0)", "scipy (>=1.10.0)", "tables (>=3.8.0)", "tabulate (>=0.9.0)", "xarray (>=2022.12.0)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)", "zstandard (>=0.19.0)"] +aws = ["s3fs (>=2022.11.0)"] +clipboard = ["PyQt5 (>=5.15.9)", "qtpy (>=2.3.0)"] +compression = ["zstandard (>=0.19.0)"] +computation = ["scipy (>=1.10.0)", "xarray (>=2022.12.0)"] +consortium-standard = ["dataframe-api-compat (>=0.1.7)"] +excel = ["odfpy (>=1.4.1)", "openpyxl (>=3.1.0)", "python-calamine (>=0.1.7)", "pyxlsb (>=1.0.10)", "xlrd (>=2.0.1)", "xlsxwriter (>=3.0.5)"] +feather = ["pyarrow (>=10.0.1)"] +fss = ["fsspec (>=2022.11.0)"] +gcp = ["gcsfs (>=2022.11.0)", "pandas-gbq (>=0.19.0)"] +hdf5 = ["tables (>=3.8.0)"] +html = ["beautifulsoup4 (>=4.11.2)", "html5lib (>=1.1)", "lxml (>=4.9.2)"] +mysql = ["SQLAlchemy (>=2.0.0)", "pymysql (>=1.0.2)"] +output-formatting = ["jinja2 (>=3.1.2)", "tabulate (>=0.9.0)"] +parquet = ["pyarrow (>=10.0.1)"] +performance = ["bottleneck (>=1.3.6)", "numba (>=0.56.4)", "numexpr (>=2.8.4)"] +plot = ["matplotlib (>=3.6.3)"] +postgresql = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "psycopg2 (>=2.9.6)"] +pyarrow = ["pyarrow (>=10.0.1)"] +spss = ["pyreadstat (>=1.2.0)"] +sql-other = ["SQLAlchemy (>=2.0.0)", "adbc-driver-postgresql (>=0.8.0)", "adbc-driver-sqlite (>=0.8.0)"] +test = ["hypothesis (>=6.46.1)", "pytest (>=7.3.2)", "pytest-xdist (>=2.2.0)"] +xml = ["lxml (>=4.9.2)"] + +[[package]] +name = "pandocfilters" +version = "1.5.1" +description = "Utilities for writing pandoc filters in python" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*" +groups = ["dev"] +files = [ + {file = "pandocfilters-1.5.1-py2.py3-none-any.whl", hash = "sha256:93be382804a9cdb0a7267585f157e5d1731bbe5545a85b268d6f5fe6232de2bc"}, + {file = "pandocfilters-1.5.1.tar.gz", hash = "sha256:002b4a555ee4ebc03f8b66307e287fa492e4a77b4ea14d3f934328297bb4939e"}, +] + +[[package]] +name = "parso" +version = "0.8.4" +description = "A Python Parser" +optional = false +python-versions = ">=3.6" +groups = ["dev"] +files = [ + {file = "parso-0.8.4-py2.py3-none-any.whl", hash = "sha256:a418670a20291dacd2dddc80c377c5c3791378ee1e8d12bffc35420643d43f18"}, + {file = "parso-0.8.4.tar.gz", hash = "sha256:eb3a7b58240fb99099a345571deecc0f9540ea5f4dd2fe14c2a99d6b281ab92d"}, +] + +[package.extras] +qa = ["flake8 (==5.0.4)", "mypy (==0.971)", "types-setuptools (==67.2.0.1)"] +testing = ["docopt", "pytest"] + +[[package]] +name = "pexpect" +version = "4.9.0" +description = "Pexpect allows easy control of interactive console applications." +optional = false +python-versions = "*" +groups = ["dev"] +markers = "sys_platform != \"win32\" and sys_platform != \"emscripten\"" +files = [ + {file = "pexpect-4.9.0-py2.py3-none-any.whl", hash = "sha256:7236d1e080e4936be2dc3e326cec0af72acf9212a7e1d060210e70a47e253523"}, + {file = "pexpect-4.9.0.tar.gz", hash = "sha256:ee7d41123f3c9911050ea2c2dac107568dc43b2d3b0c7557a33212c398ead30f"}, +] + +[package.dependencies] +ptyprocess = ">=0.5" + +[[package]] +name = "platformdirs" +version = "4.3.8" +description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "platformdirs-4.3.8-py3-none-any.whl", hash = "sha256:ff7059bb7eb1179e2685604f4aaf157cfd9535242bd23742eadc3c13542139b4"}, + {file = "platformdirs-4.3.8.tar.gz", hash = "sha256:3d512d96e16bcb959a814c9f348431070822a6496326a4be0911c40b5a74c2bc"}, +] + +[package.extras] +docs = ["furo (>=2024.8.6)", "proselint (>=0.14)", "sphinx (>=8.1.3)", "sphinx-autodoc-typehints (>=3)"] +test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=8.3.4)", "pytest-cov (>=6)", "pytest-mock (>=3.14)"] +type = ["mypy (>=1.14.1)"] + +[[package]] +name = "pluggy" +version = "1.6.0" +description = "plugin and hook calling mechanisms for python" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746"}, + {file = "pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3"}, +] + +[package.extras] +dev = ["pre-commit", "tox"] +testing = ["coverage", "pytest", "pytest-benchmark"] + +[[package]] +name = "prometheus-client" +version = "0.22.1" +description = "Python client for the Prometheus monitoring system." +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "prometheus_client-0.22.1-py3-none-any.whl", hash = "sha256:cca895342e308174341b2cbf99a56bef291fbc0ef7b9e5412a0f26d653ba7094"}, + {file = "prometheus_client-0.22.1.tar.gz", hash = "sha256:190f1331e783cf21eb60bca559354e0a4d4378facecf78f5428c39b675d20d28"}, +] + +[package.extras] +twisted = ["twisted"] + +[[package]] +name = "prompt-toolkit" +version = "3.0.51" +description = "Library for building powerful interactive command lines in Python" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "prompt_toolkit-3.0.51-py3-none-any.whl", hash = "sha256:52742911fde84e2d423e2f9a4cf1de7d7ac4e51958f648d9540e0fb8db077b07"}, + {file = "prompt_toolkit-3.0.51.tar.gz", hash = "sha256:931a162e3b27fc90c86f1b48bb1fb2c528c2761475e57c9c06de13311c7b54ed"}, +] + +[package.dependencies] +wcwidth = "*" + +[[package]] +name = "psutil" +version = "7.0.0" +description = "Cross-platform lib for process and system monitoring in Python. NOTE: the syntax of this script MUST be kept compatible with Python 2.7." +optional = false +python-versions = ">=3.6" +groups = ["dev"] +files = [ + {file = "psutil-7.0.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:101d71dc322e3cffd7cea0650b09b3d08b8e7c4109dd6809fe452dfd00e58b25"}, + {file = "psutil-7.0.0-cp36-abi3-macosx_11_0_arm64.whl", hash = "sha256:39db632f6bb862eeccf56660871433e111b6ea58f2caea825571951d4b6aa3da"}, + {file = "psutil-7.0.0-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1fcee592b4c6f146991ca55919ea3d1f8926497a713ed7faaf8225e174581e91"}, + {file = "psutil-7.0.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4b1388a4f6875d7e2aff5c4ca1cc16c545ed41dd8bb596cefea80111db353a34"}, + {file = "psutil-7.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a5f098451abc2828f7dc6b58d44b532b22f2088f4999a937557b603ce72b1993"}, + {file = "psutil-7.0.0-cp36-cp36m-win32.whl", hash = "sha256:84df4eb63e16849689f76b1ffcb36db7b8de703d1bc1fe41773db487621b6c17"}, + {file = "psutil-7.0.0-cp36-cp36m-win_amd64.whl", hash = "sha256:1e744154a6580bc968a0195fd25e80432d3afec619daf145b9e5ba16cc1d688e"}, + {file = "psutil-7.0.0-cp37-abi3-win32.whl", hash = "sha256:ba3fcef7523064a6c9da440fc4d6bd07da93ac726b5733c29027d7dc95b39d99"}, + {file = "psutil-7.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:4cf3d4eb1aa9b348dec30105c55cd9b7d4629285735a102beb4441e38db90553"}, + {file = "psutil-7.0.0.tar.gz", hash = "sha256:7be9c3eba38beccb6495ea33afd982a44074b78f28c434a1f51cc07fd315c456"}, +] + +[package.extras] +dev = ["abi3audit", "black (==24.10.0)", "check-manifest", "coverage", "packaging", "pylint", "pyperf", "pypinfo", "pytest", "pytest-cov", "pytest-xdist", "requests", "rstcheck", "ruff", "setuptools", "sphinx", "sphinx_rtd_theme", "toml-sort", "twine", "virtualenv", "vulture", "wheel"] +test = ["pytest", "pytest-xdist", "setuptools"] + +[[package]] +name = "ptyprocess" +version = "0.7.0" +description = "Run a subprocess in a pseudo terminal" +optional = false +python-versions = "*" +groups = ["dev"] +markers = "sys_platform != \"win32\" and sys_platform != \"emscripten\" or os_name != \"nt\"" +files = [ + {file = "ptyprocess-0.7.0-py2.py3-none-any.whl", hash = "sha256:4b41f3967fce3af57cc7e94b888626c18bf37a083e3651ca8feeb66d492fef35"}, + {file = "ptyprocess-0.7.0.tar.gz", hash = "sha256:5c5d0a3b48ceee0b48485e0c26037c0acd7d29765ca3fbb5cb3831d347423220"}, +] + +[[package]] +name = "pure-eval" +version = "0.2.3" +description = "Safely evaluate AST nodes without side effects" +optional = false +python-versions = "*" +groups = ["dev"] +files = [ + {file = "pure_eval-0.2.3-py3-none-any.whl", hash = "sha256:1db8e35b67b3d218d818ae653e27f06c3aa420901fa7b081ca98cbedc874e0d0"}, + {file = "pure_eval-0.2.3.tar.gz", hash = "sha256:5f4e983f40564c576c7c8635ae88db5956bb2229d7e9237d03b3c0b0190eaf42"}, +] + +[package.extras] +tests = ["pytest"] + +[[package]] +name = "pycparser" +version = "2.22" +description = "C parser in Python" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "pycparser-2.22-py3-none-any.whl", hash = "sha256:c3702b6d3dd8c7abc1afa565d7e63d53a1d0bd86cdc24edd75470f4de499cfcc"}, + {file = "pycparser-2.22.tar.gz", hash = "sha256:491c8be9c040f5390f5bf44a5b07752bd07f56edf992381b05c701439eec10f6"}, +] + +[[package]] +name = "pydantic" +version = "2.11.7" +description = "Data validation using Python type hints" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "pydantic-2.11.7-py3-none-any.whl", hash = "sha256:dde5df002701f6de26248661f6835bbe296a47bf73990135c7d07ce741b9623b"}, + {file = "pydantic-2.11.7.tar.gz", hash = "sha256:d989c3c6cb79469287b1569f7447a17848c998458d49ebe294e975b9baf0f0db"}, +] + +[package.dependencies] +annotated-types = ">=0.6.0" +pydantic-core = "2.33.2" +typing-extensions = ">=4.12.2" +typing-inspection = ">=0.4.0" + +[package.extras] +email = ["email-validator (>=2.0.0)"] +timezone = ["tzdata ; python_version >= \"3.9\" and platform_system == \"Windows\""] + +[[package]] +name = "pydantic-core" +version = "2.33.2" +description = "Core functionality for Pydantic validation and serialization" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "pydantic_core-2.33.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:2b3d326aaef0c0399d9afffeb6367d5e26ddc24d351dbc9c636840ac355dc5d8"}, + {file = "pydantic_core-2.33.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0e5b2671f05ba48b94cb90ce55d8bdcaaedb8ba00cc5359f6810fc918713983d"}, + {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0069c9acc3f3981b9ff4cdfaf088e98d83440a4c7ea1bc07460af3d4dc22e72d"}, + {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d53b22f2032c42eaaf025f7c40c2e3b94568ae077a606f006d206a463bc69572"}, + {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:0405262705a123b7ce9f0b92f123334d67b70fd1f20a9372b907ce1080c7ba02"}, + {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4b25d91e288e2c4e0662b8038a28c6a07eaac3e196cfc4ff69de4ea3db992a1b"}, + {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6bdfe4b3789761f3bcb4b1ddf33355a71079858958e3a552f16d5af19768fef2"}, + {file = "pydantic_core-2.33.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:efec8db3266b76ef9607c2c4c419bdb06bf335ae433b80816089ea7585816f6a"}, + {file = "pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:031c57d67ca86902726e0fae2214ce6770bbe2f710dc33063187a68744a5ecac"}, + {file = "pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_armv7l.whl", hash = "sha256:f8de619080e944347f5f20de29a975c2d815d9ddd8be9b9b7268e2e3ef68605a"}, + {file = "pydantic_core-2.33.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:73662edf539e72a9440129f231ed3757faab89630d291b784ca99237fb94db2b"}, + {file = "pydantic_core-2.33.2-cp310-cp310-win32.whl", hash = "sha256:0a39979dcbb70998b0e505fb1556a1d550a0781463ce84ebf915ba293ccb7e22"}, + {file = "pydantic_core-2.33.2-cp310-cp310-win_amd64.whl", hash = "sha256:b0379a2b24882fef529ec3b4987cb5d003b9cda32256024e6fe1586ac45fc640"}, + {file = "pydantic_core-2.33.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:4c5b0a576fb381edd6d27f0a85915c6daf2f8138dc5c267a57c08a62900758c7"}, + {file = "pydantic_core-2.33.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e799c050df38a639db758c617ec771fd8fb7a5f8eaaa4b27b101f266b216a246"}, + {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dc46a01bf8d62f227d5ecee74178ffc448ff4e5197c756331f71efcc66dc980f"}, + {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:a144d4f717285c6d9234a66778059f33a89096dfb9b39117663fd8413d582dcc"}, + {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:73cf6373c21bc80b2e0dc88444f41ae60b2f070ed02095754eb5a01df12256de"}, + {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3dc625f4aa79713512d1976fe9f0bc99f706a9dee21dfd1810b4bbbf228d0e8a"}, + {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:881b21b5549499972441da4758d662aeea93f1923f953e9cbaff14b8b9565aef"}, + {file = "pydantic_core-2.33.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bdc25f3681f7b78572699569514036afe3c243bc3059d3942624e936ec93450e"}, + {file = "pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:fe5b32187cbc0c862ee201ad66c30cf218e5ed468ec8dc1cf49dec66e160cc4d"}, + {file = "pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_armv7l.whl", hash = "sha256:bc7aee6f634a6f4a95676fcb5d6559a2c2a390330098dba5e5a5f28a2e4ada30"}, + {file = "pydantic_core-2.33.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:235f45e5dbcccf6bd99f9f472858849f73d11120d76ea8707115415f8e5ebebf"}, + {file = "pydantic_core-2.33.2-cp311-cp311-win32.whl", hash = "sha256:6368900c2d3ef09b69cb0b913f9f8263b03786e5b2a387706c5afb66800efd51"}, + {file = "pydantic_core-2.33.2-cp311-cp311-win_amd64.whl", hash = "sha256:1e063337ef9e9820c77acc768546325ebe04ee38b08703244c1309cccc4f1bab"}, + {file = "pydantic_core-2.33.2-cp311-cp311-win_arm64.whl", hash = "sha256:6b99022f1d19bc32a4c2a0d544fc9a76e3be90f0b3f4af413f87d38749300e65"}, + {file = "pydantic_core-2.33.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:a7ec89dc587667f22b6a0b6579c249fca9026ce7c333fc142ba42411fa243cdc"}, + {file = "pydantic_core-2.33.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:3c6db6e52c6d70aa0d00d45cdb9b40f0433b96380071ea80b09277dba021ddf7"}, + {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4e61206137cbc65e6d5256e1166f88331d3b6238e082d9f74613b9b765fb9025"}, + {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:eb8c529b2819c37140eb51b914153063d27ed88e3bdc31b71198a198e921e011"}, + {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c52b02ad8b4e2cf14ca7b3d918f3eb0ee91e63b3167c32591e57c4317e134f8f"}, + {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:96081f1605125ba0855dfda83f6f3df5ec90c61195421ba72223de35ccfb2f88"}, + {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f57a69461af2a5fa6e6bbd7a5f60d3b7e6cebb687f55106933188e79ad155c1"}, + {file = "pydantic_core-2.33.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:572c7e6c8bb4774d2ac88929e3d1f12bc45714ae5ee6d9a788a9fb35e60bb04b"}, + {file = "pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:db4b41f9bd95fbe5acd76d89920336ba96f03e149097365afe1cb092fceb89a1"}, + {file = "pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_armv7l.whl", hash = "sha256:fa854f5cf7e33842a892e5c73f45327760bc7bc516339fda888c75ae60edaeb6"}, + {file = "pydantic_core-2.33.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:5f483cfb75ff703095c59e365360cb73e00185e01aaea067cd19acffd2ab20ea"}, + {file = "pydantic_core-2.33.2-cp312-cp312-win32.whl", hash = "sha256:9cb1da0f5a471435a7bc7e439b8a728e8b61e59784b2af70d7c169f8dd8ae290"}, + {file = "pydantic_core-2.33.2-cp312-cp312-win_amd64.whl", hash = "sha256:f941635f2a3d96b2973e867144fde513665c87f13fe0e193c158ac51bfaaa7b2"}, + {file = "pydantic_core-2.33.2-cp312-cp312-win_arm64.whl", hash = "sha256:cca3868ddfaccfbc4bfb1d608e2ccaaebe0ae628e1416aeb9c4d88c001bb45ab"}, + {file = "pydantic_core-2.33.2-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:1082dd3e2d7109ad8b7da48e1d4710c8d06c253cbc4a27c1cff4fbcaa97a9e3f"}, + {file = "pydantic_core-2.33.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f517ca031dfc037a9c07e748cefd8d96235088b83b4f4ba8939105d20fa1dcd6"}, + {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0a9f2c9dd19656823cb8250b0724ee9c60a82f3cdf68a080979d13092a3b0fef"}, + {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2b0a451c263b01acebe51895bfb0e1cc842a5c666efe06cdf13846c7418caa9a"}, + {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1ea40a64d23faa25e62a70ad163571c0b342b8bf66d5fa612ac0dec4f069d916"}, + {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0fb2d542b4d66f9470e8065c5469ec676978d625a8b7a363f07d9a501a9cb36a"}, + {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9fdac5d6ffa1b5a83bca06ffe7583f5576555e6c8b3a91fbd25ea7780f825f7d"}, + {file = "pydantic_core-2.33.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:04a1a413977ab517154eebb2d326da71638271477d6ad87a769102f7c2488c56"}, + {file = "pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:c8e7af2f4e0194c22b5b37205bfb293d166a7344a5b0d0eaccebc376546d77d5"}, + {file = "pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_armv7l.whl", hash = "sha256:5c92edd15cd58b3c2d34873597a1e20f13094f59cf88068adb18947df5455b4e"}, + {file = "pydantic_core-2.33.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:65132b7b4a1c0beded5e057324b7e16e10910c106d43675d9bd87d4f38dde162"}, + {file = "pydantic_core-2.33.2-cp313-cp313-win32.whl", hash = "sha256:52fb90784e0a242bb96ec53f42196a17278855b0f31ac7c3cc6f5c1ec4811849"}, + {file = "pydantic_core-2.33.2-cp313-cp313-win_amd64.whl", hash = "sha256:c083a3bdd5a93dfe480f1125926afcdbf2917ae714bdb80b36d34318b2bec5d9"}, + {file = "pydantic_core-2.33.2-cp313-cp313-win_arm64.whl", hash = "sha256:e80b087132752f6b3d714f041ccf74403799d3b23a72722ea2e6ba2e892555b9"}, + {file = "pydantic_core-2.33.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:61c18fba8e5e9db3ab908620af374db0ac1baa69f0f32df4f61ae23f15e586ac"}, + {file = "pydantic_core-2.33.2-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95237e53bb015f67b63c91af7518a62a8660376a6a0db19b89acc77a4d6199f5"}, + {file = "pydantic_core-2.33.2-cp313-cp313t-win_amd64.whl", hash = "sha256:c2fc0a768ef76c15ab9238afa6da7f69895bb5d1ee83aeea2e3509af4472d0b9"}, + {file = "pydantic_core-2.33.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:a2b911a5b90e0374d03813674bf0a5fbbb7741570dcd4b4e85a2e48d17def29d"}, + {file = "pydantic_core-2.33.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6fa6dfc3e4d1f734a34710f391ae822e0a8eb8559a85c6979e14e65ee6ba2954"}, + {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c54c939ee22dc8e2d545da79fc5381f1c020d6d3141d3bd747eab59164dc89fb"}, + {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:53a57d2ed685940a504248187d5685e49eb5eef0f696853647bf37c418c538f7"}, + {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09fb9dd6571aacd023fe6aaca316bd01cf60ab27240d7eb39ebd66a3a15293b4"}, + {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0e6116757f7959a712db11f3e9c0a99ade00a5bbedae83cb801985aa154f071b"}, + {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d55ab81c57b8ff8548c3e4947f119551253f4e3787a7bbc0b6b3ca47498a9d3"}, + {file = "pydantic_core-2.33.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:c20c462aa4434b33a2661701b861604913f912254e441ab8d78d30485736115a"}, + {file = "pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:44857c3227d3fb5e753d5fe4a3420d6376fa594b07b621e220cd93703fe21782"}, + {file = "pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_armv7l.whl", hash = "sha256:eb9b459ca4df0e5c87deb59d37377461a538852765293f9e6ee834f0435a93b9"}, + {file = "pydantic_core-2.33.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:9fcd347d2cc5c23b06de6d3b7b8275be558a0c90549495c699e379a80bf8379e"}, + {file = "pydantic_core-2.33.2-cp39-cp39-win32.whl", hash = "sha256:83aa99b1285bc8f038941ddf598501a86f1536789740991d7d8756e34f1e74d9"}, + {file = "pydantic_core-2.33.2-cp39-cp39-win_amd64.whl", hash = "sha256:f481959862f57f29601ccced557cc2e817bce7533ab8e01a797a48b49c9692b3"}, + {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5c4aa4e82353f65e548c476b37e64189783aa5384903bfea4f41580f255fddfa"}, + {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:d946c8bf0d5c24bf4fe333af284c59a19358aa3ec18cb3dc4370080da1e8ad29"}, + {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:87b31b6846e361ef83fedb187bb5b4372d0da3f7e28d85415efa92d6125d6e6d"}, + {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa9d91b338f2df0508606f7009fde642391425189bba6d8c653afd80fd6bb64e"}, + {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2058a32994f1fde4ca0480ab9d1e75a0e8c87c22b53a3ae66554f9af78f2fe8c"}, + {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:0e03262ab796d986f978f79c943fc5f620381be7287148b8010b4097f79a39ec"}, + {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:1a8695a8d00c73e50bff9dfda4d540b7dee29ff9b8053e38380426a85ef10052"}, + {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:fa754d1850735a0b0e03bcffd9d4b4343eb417e47196e4485d9cca326073a42c"}, + {file = "pydantic_core-2.33.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:a11c8d26a50bfab49002947d3d237abe4d9e4b5bdc8846a63537b6488e197808"}, + {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:dd14041875d09cc0f9308e37a6f8b65f5585cf2598a53aa0123df8b129d481f8"}, + {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:d87c561733f66531dced0da6e864f44ebf89a8fba55f31407b00c2f7f9449593"}, + {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2f82865531efd18d6e07a04a17331af02cb7a651583c418df8266f17a63c6612"}, + {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2bfb5112df54209d820d7bf9317c7a6c9025ea52e49f46b6a2060104bba37de7"}, + {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:64632ff9d614e5eecfb495796ad51b0ed98c453e447a76bcbeeb69615079fc7e"}, + {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:f889f7a40498cc077332c7ab6b4608d296d852182211787d4f3ee377aaae66e8"}, + {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:de4b83bb311557e439b9e186f733f6c645b9417c84e2eb8203f3f820a4b988bf"}, + {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:82f68293f055f51b51ea42fafc74b6aad03e70e191799430b90c13d643059ebb"}, + {file = "pydantic_core-2.33.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:329467cecfb529c925cf2bbd4d60d2c509bc2fb52a20c1045bf09bb70971a9c1"}, + {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:87acbfcf8e90ca885206e98359d7dca4bcbb35abdc0ff66672a293e1d7a19101"}, + {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:7f92c15cd1e97d4b12acd1cc9004fa092578acfa57b67ad5e43a197175d01a64"}, + {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d3f26877a748dc4251cfcfda9dfb5f13fcb034f5308388066bcfe9031b63ae7d"}, + {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dac89aea9af8cd672fa7b510e7b8c33b0bba9a43186680550ccf23020f32d535"}, + {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:970919794d126ba8645f3837ab6046fb4e72bbc057b3709144066204c19a455d"}, + {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:3eb3fe62804e8f859c49ed20a8451342de53ed764150cb14ca71357c765dc2a6"}, + {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_armv7l.whl", hash = "sha256:3abcd9392a36025e3bd55f9bd38d908bd17962cc49bc6da8e7e96285336e2bca"}, + {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:3a1c81334778f9e3af2f8aeb7a960736e5cab1dfebfb26aabca09afd2906c039"}, + {file = "pydantic_core-2.33.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:2807668ba86cb38c6817ad9bc66215ab8584d1d304030ce4f0887336f28a5e27"}, + {file = "pydantic_core-2.33.2.tar.gz", hash = "sha256:7cb8bc3605c29176e1b105350d2e6474142d7c1bd1d9327c4a9bdb46bf827acc"}, +] + +[package.dependencies] +typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" + +[[package]] +name = "pydantic-settings" +version = "2.10.1" +description = "Settings management using Pydantic" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "pydantic_settings-2.10.1-py3-none-any.whl", hash = "sha256:a60952460b99cf661dc25c29c0ef171721f98bfcb52ef8d9ea4c943d7c8cc796"}, + {file = "pydantic_settings-2.10.1.tar.gz", hash = "sha256:06f0062169818d0f5524420a360d632d5857b83cffd4d42fe29597807a1614ee"}, +] + +[package.dependencies] +pydantic = ">=2.7.0" +python-dotenv = ">=0.21.0" +typing-inspection = ">=0.4.0" + +[package.extras] +aws-secrets-manager = ["boto3 (>=1.35.0)", "boto3-stubs[secretsmanager]"] +azure-key-vault = ["azure-identity (>=1.16.0)", "azure-keyvault-secrets (>=4.8.0)"] +gcp-secret-manager = ["google-cloud-secret-manager (>=2.23.1)"] +toml = ["tomli (>=2.0.1)"] +yaml = ["pyyaml (>=6.0.1)"] + +[[package]] +name = "pydeps" +version = "3.0.1" +description = "Display module dependencies" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "pydeps-3.0.1-py3-none-any.whl", hash = "sha256:7c86ee63c9ee6ddd088c840364981c5aa214a994d323bb7fa4724fca30829bee"}, + {file = "pydeps-3.0.1.tar.gz", hash = "sha256:a57415a8fae2ff6840a199b7dfcfecb90c37e4b9b54b58a111808a3440bc03bc"}, +] + +[package.dependencies] +stdlib_list = "*" + +[[package]] +name = "pygments" +version = "2.19.2" +description = "Pygments is a syntax highlighting package written in Python." +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b"}, + {file = "pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887"}, +] + +[package.extras] +windows-terminal = ["colorama (>=0.4.6)"] + +[[package]] +name = "pylint" +version = "3.3.8" +description = "python code static checker" +optional = false +python-versions = ">=3.9.0" +groups = ["dev"] +files = [ + {file = "pylint-3.3.8-py3-none-any.whl", hash = "sha256:7ef94aa692a600e82fabdd17102b73fc226758218c97473c7ad67bd4cb905d83"}, + {file = "pylint-3.3.8.tar.gz", hash = "sha256:26698de19941363037e2937d3db9ed94fb3303fdadf7d98847875345a8bb6b05"}, +] + +[package.dependencies] +astroid = ">=3.3.8,<=3.4.0.dev0" +colorama = {version = ">=0.4.5", markers = "sys_platform == \"win32\""} +dill = {version = ">=0.3.7", markers = "python_version >= \"3.12\""} +isort = ">=4.2.5,<5.13 || >5.13,<7" +mccabe = ">=0.6,<0.8" +platformdirs = ">=2.2" +tomlkit = ">=0.10.1" + +[package.extras] +spelling = ["pyenchant (>=3.2,<4.0)"] +testutils = ["gitpython (>3)"] + +[[package]] +name = "pytest" +version = "8.4.1" +description = "pytest: simple powerful testing with Python" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "pytest-8.4.1-py3-none-any.whl", hash = "sha256:539c70ba6fcead8e78eebbf1115e8b589e7565830d7d006a8723f19ac8a0afb7"}, + {file = "pytest-8.4.1.tar.gz", hash = "sha256:7c67fd69174877359ed9371ec3af8a3d2b04741818c51e5e99cc1742251fa93c"}, +] + +[package.dependencies] +colorama = {version = ">=0.4", markers = "sys_platform == \"win32\""} +iniconfig = ">=1" +packaging = ">=20" +pluggy = ">=1.5,<2" +pygments = ">=2.7.2" + +[package.extras] +dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "requests", "setuptools", "xmlschema"] + +[[package]] +name = "pytest-cov" +version = "6.2.1" +description = "Pytest plugin for measuring coverage." +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "pytest_cov-6.2.1-py3-none-any.whl", hash = "sha256:f5bc4c23f42f1cdd23c70b1dab1bbaef4fc505ba950d53e0081d0730dd7e86d5"}, + {file = "pytest_cov-6.2.1.tar.gz", hash = "sha256:25cc6cc0a5358204b8108ecedc51a9b57b34cc6b8c967cc2c01a4e00d8a67da2"}, +] + +[package.dependencies] +coverage = {version = ">=7.5", extras = ["toml"]} +pluggy = ">=1.2" +pytest = ">=6.2.5" + +[package.extras] +testing = ["fields", "hunter", "process-tests", "pytest-xdist", "virtualenv"] + +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +description = "Extensions to the standard Python datetime module" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +groups = ["main", "dev"] +files = [ + {file = "python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3"}, + {file = "python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427"}, +] + +[package.dependencies] +six = ">=1.5" + +[[package]] +name = "python-dotenv" +version = "1.1.1" +description = "Read key-value pairs from a .env file and set them as environment variables" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "python_dotenv-1.1.1-py3-none-any.whl", hash = "sha256:31f23644fe2602f88ff55e1f5c79ba497e01224ee7737937930c448e4d0e24dc"}, + {file = "python_dotenv-1.1.1.tar.gz", hash = "sha256:a8a6399716257f45be6a007360200409fce5cda2661e3dec71d23dc15f6189ab"}, +] + +[package.extras] +cli = ["click (>=5.0)"] + +[[package]] +name = "python-json-logger" +version = "3.3.0" +description = "JSON Log Formatter for the Python Logging Package" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "python_json_logger-3.3.0-py3-none-any.whl", hash = "sha256:dd980fae8cffb24c13caf6e158d3d61c0d6d22342f932cb6e9deedab3d35eec7"}, + {file = "python_json_logger-3.3.0.tar.gz", hash = "sha256:12b7e74b17775e7d565129296105bbe3910842d9d0eb083fc83a6a617aa8df84"}, +] + +[package.extras] +dev = ["backports.zoneinfo ; python_version < \"3.9\"", "black", "build", "freezegun", "mdx_truly_sane_lists", "mike", "mkdocs", "mkdocs-awesome-pages-plugin", "mkdocs-gen-files", "mkdocs-literate-nav", "mkdocs-material (>=8.5)", "mkdocstrings[python]", "msgspec ; implementation_name != \"pypy\"", "mypy", "orjson ; implementation_name != \"pypy\"", "pylint", "pytest", "tzdata", "validate-pyproject[all]"] + +[[package]] +name = "pytz" +version = "2025.2" +description = "World timezone definitions, modern and historical" +optional = false +python-versions = "*" +groups = ["main"] +files = [ + {file = "pytz-2025.2-py2.py3-none-any.whl", hash = "sha256:5ddf76296dd8c44c26eb8f4b6f35488f3ccbf6fbbd7adee0b7262d43f0ec2f00"}, + {file = "pytz-2025.2.tar.gz", hash = "sha256:360b9e3dbb49a209c21ad61809c7fb453643e048b38924c765813546746e81c3"}, +] + +[[package]] +name = "pywin32" +version = "311" +description = "Python for Window Extensions" +optional = false +python-versions = "*" +groups = ["dev"] +markers = "sys_platform == \"win32\" and platform_python_implementation != \"PyPy\"" +files = [ + {file = "pywin32-311-cp310-cp310-win32.whl", hash = "sha256:d03ff496d2a0cd4a5893504789d4a15399133fe82517455e78bad62efbb7f0a3"}, + {file = "pywin32-311-cp310-cp310-win_amd64.whl", hash = "sha256:797c2772017851984b97180b0bebe4b620bb86328e8a884bb626156295a63b3b"}, + {file = "pywin32-311-cp310-cp310-win_arm64.whl", hash = "sha256:0502d1facf1fed4839a9a51ccbcc63d952cf318f78ffc00a7e78528ac27d7a2b"}, + {file = "pywin32-311-cp311-cp311-win32.whl", hash = "sha256:184eb5e436dea364dcd3d2316d577d625c0351bf237c4e9a5fabbcfa5a58b151"}, + {file = "pywin32-311-cp311-cp311-win_amd64.whl", hash = "sha256:3ce80b34b22b17ccbd937a6e78e7225d80c52f5ab9940fe0506a1a16f3dab503"}, + {file = "pywin32-311-cp311-cp311-win_arm64.whl", hash = "sha256:a733f1388e1a842abb67ffa8e7aad0e70ac519e09b0f6a784e65a136ec7cefd2"}, + {file = "pywin32-311-cp312-cp312-win32.whl", hash = "sha256:750ec6e621af2b948540032557b10a2d43b0cee2ae9758c54154d711cc852d31"}, + {file = "pywin32-311-cp312-cp312-win_amd64.whl", hash = "sha256:b8c095edad5c211ff31c05223658e71bf7116daa0ecf3ad85f3201ea3190d067"}, + {file = "pywin32-311-cp312-cp312-win_arm64.whl", hash = "sha256:e286f46a9a39c4a18b319c28f59b61de793654af2f395c102b4f819e584b5852"}, + {file = "pywin32-311-cp313-cp313-win32.whl", hash = "sha256:f95ba5a847cba10dd8c4d8fefa9f2a6cf283b8b88ed6178fa8a6c1ab16054d0d"}, + {file = "pywin32-311-cp313-cp313-win_amd64.whl", hash = "sha256:718a38f7e5b058e76aee1c56ddd06908116d35147e133427e59a3983f703a20d"}, + {file = "pywin32-311-cp313-cp313-win_arm64.whl", hash = "sha256:7b4075d959648406202d92a2310cb990fea19b535c7f4a78d3f5e10b926eeb8a"}, + {file = "pywin32-311-cp314-cp314-win32.whl", hash = "sha256:b7a2c10b93f8986666d0c803ee19b5990885872a7de910fc460f9b0c2fbf92ee"}, + {file = "pywin32-311-cp314-cp314-win_amd64.whl", hash = "sha256:3aca44c046bd2ed8c90de9cb8427f581c479e594e99b5c0bb19b29c10fd6cb87"}, + {file = "pywin32-311-cp314-cp314-win_arm64.whl", hash = "sha256:a508e2d9025764a8270f93111a970e1d0fbfc33f4153b388bb649b7eec4f9b42"}, + {file = "pywin32-311-cp38-cp38-win32.whl", hash = "sha256:6c6f2969607b5023b0d9ce2541f8d2cbb01c4f46bc87456017cf63b73f1e2d8c"}, + {file = "pywin32-311-cp38-cp38-win_amd64.whl", hash = "sha256:c8015b09fb9a5e188f83b7b04de91ddca4658cee2ae6f3bc483f0b21a77ef6cd"}, + {file = "pywin32-311-cp39-cp39-win32.whl", hash = "sha256:aba8f82d551a942cb20d4a83413ccbac30790b50efb89a75e4f586ac0bb8056b"}, + {file = "pywin32-311-cp39-cp39-win_amd64.whl", hash = "sha256:e0c4cfb0621281fe40387df582097fd796e80430597cb9944f0ae70447bacd91"}, + {file = "pywin32-311-cp39-cp39-win_arm64.whl", hash = "sha256:62ea666235135fee79bb154e695f3ff67370afefd71bd7fea7512fc70ef31e3d"}, +] + +[[package]] +name = "pywinpty" +version = "3.0.0" +description = "" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +markers = "os_name == \"nt\"" +files = [ + {file = "pywinpty-3.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:327b6034e0dc38352c1c99a7c0b3e54941b4e506a5f21acce63609cd2ab6cce2"}, + {file = "pywinpty-3.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:29daa71ac5dcbe1496ef99f4cde85a732b1f0a3b71405d42177dbcf9ee405e5a"}, + {file = "pywinpty-3.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:1e0c4b01e5b03b1531d7c5d0e044b8c66dd0288c6d2b661820849f2a8d91aec3"}, + {file = "pywinpty-3.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:828cbe756b7e3d25d886fbd5691a1d523cd59c5fb79286bb32bb75c5221e7ba1"}, + {file = "pywinpty-3.0.0-cp313-cp313t-win_amd64.whl", hash = "sha256:de0cbe27b96e5a2cebd86c4a6b8b4139f978d9c169d44a8edc7e30e88e5d7a69"}, + {file = "pywinpty-3.0.0-cp39-cp39-win_amd64.whl", hash = "sha256:007735316170ec1b6e773deadab5fe9ec4074dfdc06f27513fe87b8cfe45237d"}, + {file = "pywinpty-3.0.0.tar.gz", hash = "sha256:68f70e68a9f0766ffdea3fc500351cb7b9b012bcb8239a411f7ff0fc8f86dcb1"}, +] + +[[package]] +name = "pyyaml" +version = "6.0.2" +description = "YAML parser and emitter for Python" +optional = false +python-versions = ">=3.8" +groups = ["main", "dev"] +files = [ + {file = "PyYAML-6.0.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0a9a2848a5b7feac301353437eb7d5957887edbf81d56e903999a75a3d743086"}, + {file = "PyYAML-6.0.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:29717114e51c84ddfba879543fb232a6ed60086602313ca38cce623c1d62cfbf"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8824b5a04a04a047e72eea5cec3bc266db09e35de6bdfe34c9436ac5ee27d237"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c36280e6fb8385e520936c3cb3b8042851904eba0e58d277dca80a5cfed590b"}, + {file = "PyYAML-6.0.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ec031d5d2feb36d1d1a24380e4db6d43695f3748343d99434e6f5f9156aaa2ed"}, + {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:936d68689298c36b53b29f23c6dbb74de12b4ac12ca6cfe0e047bedceea56180"}, + {file = "PyYAML-6.0.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:23502f431948090f597378482b4812b0caae32c22213aecf3b55325e049a6c68"}, + {file = "PyYAML-6.0.2-cp310-cp310-win32.whl", hash = "sha256:2e99c6826ffa974fe6e27cdb5ed0021786b03fc98e5ee3c5bfe1fd5015f42b99"}, + {file = "PyYAML-6.0.2-cp310-cp310-win_amd64.whl", hash = "sha256:a4d3091415f010369ae4ed1fc6b79def9416358877534caf6a0fdd2146c87a3e"}, + {file = "PyYAML-6.0.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:cc1c1159b3d456576af7a3e4d1ba7e6924cb39de8f67111c735f6fc832082774"}, + {file = "PyYAML-6.0.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1e2120ef853f59c7419231f3bf4e7021f1b936f6ebd222406c3b60212205d2ee"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d225db5a45f21e78dd9358e58a98702a0302f2659a3c6cd320564b75b86f47c"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5ac9328ec4831237bec75defaf839f7d4564be1e6b25ac710bd1a96321cc8317"}, + {file = "PyYAML-6.0.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ad2a3decf9aaba3d29c8f537ac4b243e36bef957511b4766cb0057d32b0be85"}, + {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ff3824dc5261f50c9b0dfb3be22b4567a6f938ccce4587b38952d85fd9e9afe4"}, + {file = "PyYAML-6.0.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:797b4f722ffa07cc8d62053e4cff1486fa6dc094105d13fea7b1de7d8bf71c9e"}, + {file = "PyYAML-6.0.2-cp311-cp311-win32.whl", hash = "sha256:11d8f3dd2b9c1207dcaf2ee0bbbfd5991f571186ec9cc78427ba5bd32afae4b5"}, + {file = "PyYAML-6.0.2-cp311-cp311-win_amd64.whl", hash = "sha256:e10ce637b18caea04431ce14fabcf5c64a1c61ec9c56b071a4b7ca131ca52d44"}, + {file = "PyYAML-6.0.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:c70c95198c015b85feafc136515252a261a84561b7b1d51e3384e0655ddf25ab"}, + {file = "PyYAML-6.0.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ce826d6ef20b1bc864f0a68340c8b3287705cae2f8b4b1d932177dcc76721725"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f71ea527786de97d1a0cc0eacd1defc0985dcf6b3f17bb77dcfc8c34bec4dc5"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b22676e8097e9e22e36d6b7bda33190d0d400f345f23d4065d48f4ca7ae0425"}, + {file = "PyYAML-6.0.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:80bab7bfc629882493af4aa31a4cfa43a4c57c83813253626916b8c7ada83476"}, + {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:0833f8694549e586547b576dcfaba4a6b55b9e96098b36cdc7ebefe667dfed48"}, + {file = "PyYAML-6.0.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8b9c7197f7cb2738065c481a0461e50ad02f18c78cd75775628afb4d7137fb3b"}, + {file = "PyYAML-6.0.2-cp312-cp312-win32.whl", hash = "sha256:ef6107725bd54b262d6dedcc2af448a266975032bc85ef0172c5f059da6325b4"}, + {file = "PyYAML-6.0.2-cp312-cp312-win_amd64.whl", hash = "sha256:7e7401d0de89a9a855c839bc697c079a4af81cf878373abd7dc625847d25cbd8"}, + {file = "PyYAML-6.0.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:efdca5630322a10774e8e98e1af481aad470dd62c3170801852d752aa7a783ba"}, + {file = "PyYAML-6.0.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:50187695423ffe49e2deacb8cd10510bc361faac997de9efef88badc3bb9e2d1"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ffe8360bab4910ef1b9e87fb812d8bc0a308b0d0eef8c8f44e0254ab3b07133"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:17e311b6c678207928d649faa7cb0d7b4c26a0ba73d41e99c4fff6b6c3276484"}, + {file = "PyYAML-6.0.2-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:70b189594dbe54f75ab3a1acec5f1e3faa7e8cf2f1e08d9b561cb41b845f69d5"}, + {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:41e4e3953a79407c794916fa277a82531dd93aad34e29c2a514c2c0c5fe971cc"}, + {file = "PyYAML-6.0.2-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:68ccc6023a3400877818152ad9a1033e3db8625d899c72eacb5a668902e4d652"}, + {file = "PyYAML-6.0.2-cp313-cp313-win32.whl", hash = "sha256:bc2fa7c6b47d6bc618dd7fb02ef6fdedb1090ec036abab80d4681424b84c1183"}, + {file = "PyYAML-6.0.2-cp313-cp313-win_amd64.whl", hash = "sha256:8388ee1976c416731879ac16da0aff3f63b286ffdd57cdeb95f3f2e085687563"}, + {file = "PyYAML-6.0.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:24471b829b3bf607e04e88d79542a9d48bb037c2267d7927a874e6c205ca7e9a"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7fded462629cfa4b685c5416b949ebad6cec74af5e2d42905d41e257e0869f5"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d84a1718ee396f54f3a086ea0a66d8e552b2ab2017ef8b420e92edbc841c352d"}, + {file = "PyYAML-6.0.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9056c1ecd25795207ad294bcf39f2db3d845767be0ea6e6a34d856f006006083"}, + {file = "PyYAML-6.0.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:82d09873e40955485746739bcb8b4586983670466c23382c19cffecbf1fd8706"}, + {file = "PyYAML-6.0.2-cp38-cp38-win32.whl", hash = "sha256:43fa96a3ca0d6b1812e01ced1044a003533c47f6ee8aca31724f78e93ccc089a"}, + {file = "PyYAML-6.0.2-cp38-cp38-win_amd64.whl", hash = "sha256:01179a4a8559ab5de078078f37e5c1a30d76bb88519906844fd7bdea1b7729ff"}, + {file = "PyYAML-6.0.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:688ba32a1cffef67fd2e9398a2efebaea461578b0923624778664cc1c914db5d"}, + {file = "PyYAML-6.0.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:a8786accb172bd8afb8be14490a16625cbc387036876ab6ba70912730faf8e1f"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d8e03406cac8513435335dbab54c0d385e4a49e4945d2909a581c83647ca0290"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f753120cb8181e736c57ef7636e83f31b9c0d1722c516f7e86cf15b7aa57ff12"}, + {file = "PyYAML-6.0.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b1fdb9dc17f5a7677423d508ab4f243a726dea51fa5e70992e59a7411c89d19"}, + {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0b69e4ce7a131fe56b7e4d770c67429700908fc0752af059838b1cfb41960e4e"}, + {file = "PyYAML-6.0.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:a9f8c2e67970f13b16084e04f134610fd1d374bf477b17ec1599185cf611d725"}, + {file = "PyYAML-6.0.2-cp39-cp39-win32.whl", hash = "sha256:6395c297d42274772abc367baaa79683958044e5d3835486c16da75d2a694631"}, + {file = "PyYAML-6.0.2-cp39-cp39-win_amd64.whl", hash = "sha256:39693e1f8320ae4f43943590b49779ffb98acb81f788220ea932a6b6c51004d8"}, + {file = "pyyaml-6.0.2.tar.gz", hash = "sha256:d584d9ec91ad65861cc08d42e834324ef890a082e591037abe114850ff7bbc3e"}, +] + +[[package]] +name = "pyzmq" +version = "27.0.1" +description = "Python bindings for 0MQ" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "pyzmq-27.0.1-cp310-cp310-macosx_10_15_universal2.whl", hash = "sha256:90a4da42aa322de8a3522461e3b5fe999935763b27f69a02fced40f4e3cf9682"}, + {file = "pyzmq-27.0.1-cp310-cp310-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:e648dca28178fc879c814cf285048dd22fd1f03e1104101106505ec0eea50a4d"}, + {file = "pyzmq-27.0.1-cp310-cp310-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4bca8abc31799a6f3652d13f47e0b0e1cab76f9125f2283d085a3754f669b607"}, + {file = "pyzmq-27.0.1-cp310-cp310-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:092f4011b26d6b0201002f439bd74b38f23f3aefcb358621bdc3b230afc9b2d5"}, + {file = "pyzmq-27.0.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:6f02f30a4a6b3efe665ab13a3dd47109d80326c8fd286311d1ba9f397dc5f247"}, + {file = "pyzmq-27.0.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:f293a1419266e3bf3557d1f8778f9e1ffe7e6b2c8df5c9dca191caf60831eb74"}, + {file = "pyzmq-27.0.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ce181dd1a7c6c012d0efa8ab603c34b5ee9d86e570c03415bbb1b8772eeb381c"}, + {file = "pyzmq-27.0.1-cp310-cp310-win32.whl", hash = "sha256:f65741cc06630652e82aa68ddef4986a3ab9073dd46d59f94ce5f005fa72037c"}, + {file = "pyzmq-27.0.1-cp310-cp310-win_amd64.whl", hash = "sha256:44909aa3ed2234d69fe81e1dade7be336bcfeab106e16bdaa3318dcde4262b93"}, + {file = "pyzmq-27.0.1-cp310-cp310-win_arm64.whl", hash = "sha256:4401649bfa0a38f0f8777f8faba7cd7eb7b5b8ae2abc7542b830dd09ad4aed0d"}, + {file = "pyzmq-27.0.1-cp311-cp311-macosx_10_15_universal2.whl", hash = "sha256:9729190bd770314f5fbba42476abf6abe79a746eeda11d1d68fd56dd70e5c296"}, + {file = "pyzmq-27.0.1-cp311-cp311-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:696900ef6bc20bef6a242973943574f96c3f97d2183c1bd3da5eea4f559631b1"}, + {file = "pyzmq-27.0.1-cp311-cp311-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f96a63aecec22d3f7fdea3c6c98df9e42973f5856bb6812c3d8d78c262fee808"}, + {file = "pyzmq-27.0.1-cp311-cp311-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c512824360ea7490390566ce00bee880e19b526b312b25cc0bc30a0fe95cb67f"}, + {file = "pyzmq-27.0.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:dfb2bb5e0f7198eaacfb6796fb0330afd28f36d985a770745fba554a5903595a"}, + {file = "pyzmq-27.0.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4f6886c59ba93ffde09b957d3e857e7950c8fe818bd5494d9b4287bc6d5bc7f1"}, + {file = "pyzmq-27.0.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b99ea9d330e86ce1ff7f2456b33f1bf81c43862a5590faf4ef4ed3a63504bdab"}, + {file = "pyzmq-27.0.1-cp311-cp311-win32.whl", hash = "sha256:571f762aed89025ba8cdcbe355fea56889715ec06d0264fd8b6a3f3fa38154ed"}, + {file = "pyzmq-27.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:ee16906c8025fa464bea1e48128c048d02359fb40bebe5333103228528506530"}, + {file = "pyzmq-27.0.1-cp311-cp311-win_arm64.whl", hash = "sha256:ba068f28028849da725ff9185c24f832ccf9207a40f9b28ac46ab7c04994bd41"}, + {file = "pyzmq-27.0.1-cp312-abi3-macosx_10_15_universal2.whl", hash = "sha256:af7ebce2a1e7caf30c0bb64a845f63a69e76a2fadbc1cac47178f7bb6e657bdd"}, + {file = "pyzmq-27.0.1-cp312-abi3-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:8f617f60a8b609a13099b313e7e525e67f84ef4524b6acad396d9ff153f6e4cd"}, + {file = "pyzmq-27.0.1-cp312-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1d59dad4173dc2a111f03e59315c7bd6e73da1a9d20a84a25cf08325b0582b1a"}, + {file = "pyzmq-27.0.1-cp312-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f5b6133c8d313bde8bd0d123c169d22525300ff164c2189f849de495e1344577"}, + {file = "pyzmq-27.0.1-cp312-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:58cca552567423f04d06a075f4b473e78ab5bdb906febe56bf4797633f54aa4e"}, + {file = "pyzmq-27.0.1-cp312-abi3-musllinux_1_2_i686.whl", hash = "sha256:4b9d8e26fb600d0d69cc9933e20af08552e97cc868a183d38a5c0d661e40dfbb"}, + {file = "pyzmq-27.0.1-cp312-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:2329f0c87f0466dce45bba32b63f47018dda5ca40a0085cc5c8558fea7d9fc55"}, + {file = "pyzmq-27.0.1-cp312-abi3-win32.whl", hash = "sha256:57bb92abdb48467b89c2d21da1ab01a07d0745e536d62afd2e30d5acbd0092eb"}, + {file = "pyzmq-27.0.1-cp312-abi3-win_amd64.whl", hash = "sha256:ff3f8757570e45da7a5bedaa140489846510014f7a9d5ee9301c61f3f1b8a686"}, + {file = "pyzmq-27.0.1-cp312-abi3-win_arm64.whl", hash = "sha256:df2c55c958d3766bdb3e9d858b911288acec09a9aab15883f384fc7180df5bed"}, + {file = "pyzmq-27.0.1-cp313-cp313-android_24_arm64_v8a.whl", hash = "sha256:497bd8af534ae55dc4ef67eebd1c149ff2a0b0f1e146db73c8b5a53d83c1a5f5"}, + {file = "pyzmq-27.0.1-cp313-cp313-android_24_x86_64.whl", hash = "sha256:a066ea6ad6218b4c233906adf0ae67830f451ed238419c0db609310dd781fbe7"}, + {file = "pyzmq-27.0.1-cp313-cp313t-macosx_10_15_universal2.whl", hash = "sha256:72d235d6365ca73d8ce92f7425065d70f5c1e19baa458eb3f0d570e425b73a96"}, + {file = "pyzmq-27.0.1-cp313-cp313t-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:313a7b374e3dc64848644ca348a51004b41726f768b02e17e689f1322366a4d9"}, + {file = "pyzmq-27.0.1-cp313-cp313t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:119ce8590409702394f959c159d048002cbed2f3c0645ec9d6a88087fc70f0f1"}, + {file = "pyzmq-27.0.1-cp313-cp313t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:45c3e00ce16896ace2cd770ab9057a7cf97d4613ea5f2a13f815141d8b6894b9"}, + {file = "pyzmq-27.0.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:678e50ec112bdc6df5a83ac259a55a4ba97a8b314c325ab26b3b5b071151bc61"}, + {file = "pyzmq-27.0.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:d0b96c30be9f9387b18b18b6133c75a7b1b0065da64e150fe1feb5ebf31ece1c"}, + {file = "pyzmq-27.0.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:88dc92d9eb5ea4968123e74db146d770b0c8d48f0e2bfb1dbc6c50a8edb12d64"}, + {file = "pyzmq-27.0.1-cp313-cp313t-win32.whl", hash = "sha256:6dcbcb34f5c9b0cefdfc71ff745459241b7d3cda5b27c7ad69d45afc0821d1e1"}, + {file = "pyzmq-27.0.1-cp313-cp313t-win_amd64.whl", hash = "sha256:b9fd0fda730461f510cfd9a40fafa5355d65f5e3dbdd8d6dfa342b5b3f5d1949"}, + {file = "pyzmq-27.0.1-cp313-cp313t-win_arm64.whl", hash = "sha256:56a3b1853f3954ec1f0e91085f1350cc57d18f11205e4ab6e83e4b7c414120e0"}, + {file = "pyzmq-27.0.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:f98f6b7787bd2beb1f0dde03f23a0621a0c978edf673b7d8f5e7bc039cbe1b60"}, + {file = "pyzmq-27.0.1-cp314-cp314t-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:351bf5d8ca0788ca85327fda45843b6927593ff4c807faee368cc5aaf9f809c2"}, + {file = "pyzmq-27.0.1-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5268a5a9177afff53dc6d70dffe63114ba2a6e7b20d9411cc3adeba09eeda403"}, + {file = "pyzmq-27.0.1-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a4aca06ba295aa78bec9b33ec028d1ca08744c36294338c41432b7171060c808"}, + {file = "pyzmq-27.0.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:1c363c6dc66352331d5ad64bb838765c6692766334a6a02fdb05e76bd408ae18"}, + {file = "pyzmq-27.0.1-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:87aebf4acd7249bdff8d3df03aed4f09e67078e6762cfe0aecf8d0748ff94cde"}, + {file = "pyzmq-27.0.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:e4f22d67756518d71901edf73b38dc0eb4765cce22c8fe122cc81748d425262b"}, + {file = "pyzmq-27.0.1-cp314-cp314t-win32.whl", hash = "sha256:8c62297bc7aea2147b472ca5ca2b4389377ad82898c87cabab2a94aedd75e337"}, + {file = "pyzmq-27.0.1-cp314-cp314t-win_amd64.whl", hash = "sha256:bee5248d5ec9223545f8cc4f368c2d571477ae828c99409125c3911511d98245"}, + {file = "pyzmq-27.0.1-cp314-cp314t-win_arm64.whl", hash = "sha256:0fc24bf45e4a454e55ef99d7f5c8b8712539200ce98533af25a5bfa954b6b390"}, + {file = "pyzmq-27.0.1-cp38-cp38-macosx_10_15_universal2.whl", hash = "sha256:9d16fdfd7d70a6b0ca45d36eb19f7702fa77ef6256652f17594fc9ce534c9da6"}, + {file = "pyzmq-27.0.1-cp38-cp38-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:d0356a21e58c3e99248930ff73cc05b1d302ff50f41a8a47371aefb04327378a"}, + {file = "pyzmq-27.0.1-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a27fa11ebaccc099cac4309c799aa33919671a7660e29b3e465b7893bc64ec81"}, + {file = "pyzmq-27.0.1-cp38-cp38-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b25e72e115399a4441aad322258fa8267b873850dc7c276e3f874042728c2b45"}, + {file = "pyzmq-27.0.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:f8c3b74f1cd577a5a9253eae7ed363f88cbb345a990ca3027e9038301d47c7f4"}, + {file = "pyzmq-27.0.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:19dce6c93656f9c469540350d29b128cd8ba55b80b332b431b9a1e9ff74cfd01"}, + {file = "pyzmq-27.0.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:da81512b83032ed6cdf85ca62e020b4c23dda87f1b6c26b932131222ccfdbd27"}, + {file = "pyzmq-27.0.1-cp38-cp38-win32.whl", hash = "sha256:7418fb5736d0d39b3ecc6bec4ff549777988feb260f5381636d8bd321b653038"}, + {file = "pyzmq-27.0.1-cp38-cp38-win_amd64.whl", hash = "sha256:af2ee67b3688b067e20fea3fe36b823a362609a1966e7e7a21883ae6da248804"}, + {file = "pyzmq-27.0.1-cp39-cp39-macosx_10_15_universal2.whl", hash = "sha256:05a94233fdde585eb70924a6e4929202a747eea6ed308a6171c4f1c715bbe39e"}, + {file = "pyzmq-27.0.1-cp39-cp39-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:c96702e1082eab62ae583d64c4e19c9b848359196697e536a0c57ae9bd165bd5"}, + {file = "pyzmq-27.0.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c9180d1f5b4b73e28b64e63cc6c4c097690f102aa14935a62d5dd7426a4e5b5a"}, + {file = "pyzmq-27.0.1-cp39-cp39-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e971d8680003d0af6020713e52f92109b46fedb463916e988814e04c8133578a"}, + {file = "pyzmq-27.0.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:fe632fa4501154d58dfbe1764a0495734d55f84eaf1feda4549a1f1ca76659e9"}, + {file = "pyzmq-27.0.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:4c3874344fd5fa6d58bb51919708048ac4cab21099f40a227173cddb76b4c20b"}, + {file = "pyzmq-27.0.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:0ec09073ed67ae236785d543df3b322282acc0bdf6d1b748c3e81f3043b21cb5"}, + {file = "pyzmq-27.0.1-cp39-cp39-win32.whl", hash = "sha256:f44e7ea288d022d4bf93b9e79dafcb4a7aea45a3cbeae2116792904931cefccf"}, + {file = "pyzmq-27.0.1-cp39-cp39-win_amd64.whl", hash = "sha256:ffe6b809a97ac6dea524b3b837d5b28743d8c2f121141056d168ff0ba8f614ef"}, + {file = "pyzmq-27.0.1-cp39-cp39-win_arm64.whl", hash = "sha256:fde26267416c8478c95432c81489b53f57b0b5d24cd5c8bfaebf5bbaac4dc90c"}, + {file = "pyzmq-27.0.1-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:544b995a6a1976fad5d7ff01409b4588f7608ccc41be72147700af91fd44875d"}, + {file = "pyzmq-27.0.1-pp310-pypy310_pp73-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:0f772eea55cccce7f45d6ecdd1d5049c12a77ec22404f6b892fae687faa87bee"}, + {file = "pyzmq-27.0.1-pp310-pypy310_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c9d63d66059114a6756d09169c9209ffceabacb65b9cb0f66e6fc344b20b73e6"}, + {file = "pyzmq-27.0.1-pp310-pypy310_pp73-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1da8e645c655d86f0305fb4c65a0d848f461cd90ee07d21f254667287b5dbe50"}, + {file = "pyzmq-27.0.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:1843fd0daebcf843fe6d4da53b8bdd3fc906ad3e97d25f51c3fed44436d82a49"}, + {file = "pyzmq-27.0.1-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:7fb0ee35845bef1e8c4a152d766242164e138c239e3182f558ae15cb4a891f94"}, + {file = "pyzmq-27.0.1-pp311-pypy311_pp73-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:f379f11e138dfd56c3f24a04164f871a08281194dd9ddf656a278d7d080c8ad0"}, + {file = "pyzmq-27.0.1-pp311-pypy311_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b978c0678cffbe8860ec9edc91200e895c29ae1ac8a7085f947f8e8864c489fb"}, + {file = "pyzmq-27.0.1-pp311-pypy311_pp73-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7ebccf0d760bc92a4a7c751aeb2fef6626144aace76ee8f5a63abeb100cae87f"}, + {file = "pyzmq-27.0.1-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:77fed80e30fa65708546c4119840a46691290efc231f6bfb2ac2a39b52e15811"}, + {file = "pyzmq-27.0.1-pp38-pypy38_pp73-macosx_10_15_x86_64.whl", hash = "sha256:9d7b6b90da7285642f480b48c9efd1d25302fd628237d8f6f6ee39ba6b2d2d34"}, + {file = "pyzmq-27.0.1-pp38-pypy38_pp73-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:d2976b7079f09f48d59dc123293ed6282fca6ef96a270f4ea0364e4e54c8e855"}, + {file = "pyzmq-27.0.1-pp38-pypy38_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:2852f67371918705cc18b321695f75c5d653d5d8c4a9b946c1eec4dab2bd6fdf"}, + {file = "pyzmq-27.0.1-pp38-pypy38_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:be45a895f98877271e8a0b6cf40925e0369121ce423421c20fa6d7958dc753c2"}, + {file = "pyzmq-27.0.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:64ca3c7c614aefcdd5e358ecdd41d1237c35fe1417d01ec0160e7cdb0a380edc"}, + {file = "pyzmq-27.0.1-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:d97b59cbd8a6c8b23524a8ce237ff9504d987dc07156258aa68ae06d2dd5f34d"}, + {file = "pyzmq-27.0.1-pp39-pypy39_pp73-manylinux2014_i686.manylinux_2_17_i686.whl", hash = "sha256:27a78bdd384dbbe7b357af95f72efe8c494306b5ec0a03c31e2d53d6763e5307"}, + {file = "pyzmq-27.0.1-pp39-pypy39_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b007e5dcba684e888fbc90554cb12a2f4e492927c8c2761a80b7590209821743"}, + {file = "pyzmq-27.0.1-pp39-pypy39_pp73-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:95594b2ceeaa94934e3e94dd7bf5f3c3659cf1a26b1fb3edcf6e42dad7e0eaf2"}, + {file = "pyzmq-27.0.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:70b719a130b81dd130a57ac0ff636dc2c0127c5b35ca5467d1b67057e3c7a4d2"}, + {file = "pyzmq-27.0.1.tar.gz", hash = "sha256:45c549204bc20e7484ffd2555f6cf02e572440ecf2f3bdd60d4404b20fddf64b"}, +] + +[package.dependencies] +cffi = {version = "*", markers = "implementation_name == \"pypy\""} + +[[package]] +name = "referencing" +version = "0.36.2" +description = "JSON Referencing + Python" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "referencing-0.36.2-py3-none-any.whl", hash = "sha256:e8699adbbf8b5c7de96d8ffa0eb5c158b3beafce084968e2ea8bb08c6794dcd0"}, + {file = "referencing-0.36.2.tar.gz", hash = "sha256:df2e89862cd09deabbdba16944cc3f10feb6b3e6f18e902f7cc25609a34775aa"}, +] + +[package.dependencies] +attrs = ">=22.2.0" +rpds-py = ">=0.7.0" +typing-extensions = {version = ">=4.4.0", markers = "python_version < \"3.13\""} + +[[package]] +name = "requests" +version = "2.32.4" +description = "Python HTTP for Humans." +optional = false +python-versions = ">=3.8" +groups = ["main", "dev"] +files = [ + {file = "requests-2.32.4-py3-none-any.whl", hash = "sha256:27babd3cda2a6d50b30443204ee89830707d396671944c998b5975b031ac2b2c"}, + {file = "requests-2.32.4.tar.gz", hash = "sha256:27d0316682c8a29834d3264820024b62a36942083d52caf2f14c0591336d3422"}, +] + +[package.dependencies] +certifi = ">=2017.4.17" +charset_normalizer = ">=2,<4" +idna = ">=2.5,<4" +urllib3 = ">=1.21.1,<3" + +[package.extras] +socks = ["PySocks (>=1.5.6,!=1.5.7)"] +use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] + +[[package]] +name = "requests-mock" +version = "1.12.1" +description = "Mock out responses from the requests package" +optional = false +python-versions = ">=3.5" +groups = ["dev"] +files = [ + {file = "requests-mock-1.12.1.tar.gz", hash = "sha256:e9e12e333b525156e82a3c852f22016b9158220d2f47454de9cae8a77d371401"}, + {file = "requests_mock-1.12.1-py2.py3-none-any.whl", hash = "sha256:b1e37054004cdd5e56c84454cc7df12b25f90f382159087f4b6915aaeef39563"}, +] + +[package.dependencies] +requests = ">=2.22,<3" + +[package.extras] +fixture = ["fixtures"] + +[[package]] +name = "rfc3339-validator" +version = "0.1.4" +description = "A pure python RFC3339 validator" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +groups = ["dev"] +files = [ + {file = "rfc3339_validator-0.1.4-py2.py3-none-any.whl", hash = "sha256:24f6ec1eda14ef823da9e36ec7113124b39c04d50a4d3d3a3c2859577e7791fa"}, + {file = "rfc3339_validator-0.1.4.tar.gz", hash = "sha256:138a2abdf93304ad60530167e51d2dfb9549521a836871b88d7f4695d0022f6b"}, +] + +[package.dependencies] +six = "*" + +[[package]] +name = "rfc3986-validator" +version = "0.1.1" +description = "Pure python rfc3986 validator" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*" +groups = ["dev"] +files = [ + {file = "rfc3986_validator-0.1.1-py2.py3-none-any.whl", hash = "sha256:2f235c432ef459970b4306369336b9d5dbdda31b510ca1e327636e01f528bfa9"}, + {file = "rfc3986_validator-0.1.1.tar.gz", hash = "sha256:3d44bde7921b3b9ec3ae4e3adca370438eccebc676456449b145d533b240d055"}, +] + +[[package]] +name = "rfc3987-syntax" +version = "1.1.0" +description = "Helper functions to syntactically validate strings according to RFC 3987." +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "rfc3987_syntax-1.1.0-py3-none-any.whl", hash = "sha256:6c3d97604e4c5ce9f714898e05401a0445a641cfa276432b0a648c80856f6a3f"}, + {file = "rfc3987_syntax-1.1.0.tar.gz", hash = "sha256:717a62cbf33cffdd16dfa3a497d81ce48a660ea691b1ddd7be710c22f00b4a0d"}, +] + +[package.dependencies] +lark = ">=1.2.2" + +[package.extras] +testing = ["pytest (>=8.3.5)"] + +[[package]] +name = "rpds-py" +version = "0.27.0" +description = "Python bindings to Rust's persistent data structures (rpds)" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "rpds_py-0.27.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:130c1ffa5039a333f5926b09e346ab335f0d4ec393b030a18549a7c7e7c2cea4"}, + {file = "rpds_py-0.27.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a4cf32a26fa744101b67bfd28c55d992cd19438aff611a46cac7f066afca8fd4"}, + {file = "rpds_py-0.27.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:64a0fe3f334a40b989812de70160de6b0ec7e3c9e4a04c0bbc48d97c5d3600ae"}, + {file = "rpds_py-0.27.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:9a0ff7ee28583ab30a52f371b40f54e7138c52ca67f8ca17ccb7ccf0b383cb5f"}, + {file = "rpds_py-0.27.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:15ea4d2e182345dd1b4286593601d766411b43f868924afe297570658c31a62b"}, + {file = "rpds_py-0.27.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:36184b44bf60a480863e51021c26aca3dfe8dd2f5eeabb33622b132b9d8b8b54"}, + {file = "rpds_py-0.27.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9b78430703cfcf5f5e86eb74027a1ed03a93509273d7c705babb547f03e60016"}, + {file = "rpds_py-0.27.0-cp310-cp310-manylinux_2_31_riscv64.whl", hash = "sha256:dbd749cff1defbde270ca346b69b3baf5f1297213ef322254bf2a28537f0b046"}, + {file = "rpds_py-0.27.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6bde37765564cd22a676dd8101b657839a1854cfaa9c382c5abf6ff7accfd4ae"}, + {file = "rpds_py-0.27.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1d66f45b9399036e890fb9c04e9f70c33857fd8f58ac8db9f3278cfa835440c3"}, + {file = "rpds_py-0.27.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:d85d784c619370d9329bbd670f41ff5f2ae62ea4519761b679d0f57f0f0ee267"}, + {file = "rpds_py-0.27.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:5df559e9e7644d9042f626f2c3997b555f347d7a855a15f170b253f6c5bfe358"}, + {file = "rpds_py-0.27.0-cp310-cp310-win32.whl", hash = "sha256:b8a4131698b6992b2a56015f51646711ec5d893a0b314a4b985477868e240c87"}, + {file = "rpds_py-0.27.0-cp310-cp310-win_amd64.whl", hash = "sha256:cbc619e84a5e3ab2d452de831c88bdcad824414e9c2d28cd101f94dbdf26329c"}, + {file = "rpds_py-0.27.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:dbc2ab5d10544eb485baa76c63c501303b716a5c405ff2469a1d8ceffaabf622"}, + {file = "rpds_py-0.27.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7ec85994f96a58cf7ed288caa344b7fe31fd1d503bdf13d7331ead5f70ab60d5"}, + {file = "rpds_py-0.27.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:190d7285cd3bb6d31d37a0534d7359c1ee191eb194c511c301f32a4afa5a1dd4"}, + {file = "rpds_py-0.27.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c10d92fb6d7fd827e44055fcd932ad93dac6a11e832d51534d77b97d1d85400f"}, + {file = "rpds_py-0.27.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dd2c1d27ebfe6a015cfa2005b7fe8c52d5019f7bbdd801bc6f7499aab9ae739e"}, + {file = "rpds_py-0.27.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4790c9d5dd565ddb3e9f656092f57268951398cef52e364c405ed3112dc7c7c1"}, + {file = "rpds_py-0.27.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4300e15e7d03660f04be84a125d1bdd0e6b2f674bc0723bc0fd0122f1a4585dc"}, + {file = "rpds_py-0.27.0-cp311-cp311-manylinux_2_31_riscv64.whl", hash = "sha256:59195dc244fc183209cf8a93406889cadde47dfd2f0a6b137783aa9c56d67c85"}, + {file = "rpds_py-0.27.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fae4a01ef8c4cb2bbe92ef2063149596907dc4a881a8d26743b3f6b304713171"}, + {file = "rpds_py-0.27.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:e3dc8d4ede2dbae6c0fc2b6c958bf51ce9fd7e9b40c0f5b8835c3fde44f5807d"}, + {file = "rpds_py-0.27.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:c3782fb753aa825b4ccabc04292e07897e2fd941448eabf666856c5530277626"}, + {file = "rpds_py-0.27.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:887ab1f12b0d227e9260558a4a2320024b20102207ada65c43e1ffc4546df72e"}, + {file = "rpds_py-0.27.0-cp311-cp311-win32.whl", hash = "sha256:5d6790ff400254137b81b8053b34417e2c46921e302d655181d55ea46df58cf7"}, + {file = "rpds_py-0.27.0-cp311-cp311-win_amd64.whl", hash = "sha256:e24d8031a2c62f34853756d9208eeafa6b940a1efcbfe36e8f57d99d52bb7261"}, + {file = "rpds_py-0.27.0-cp311-cp311-win_arm64.whl", hash = "sha256:08680820d23df1df0a0260f714d12966bc6c42d02e8055a91d61e03f0c47dda0"}, + {file = "rpds_py-0.27.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:19c990fdf5acecbf0623e906ae2e09ce1c58947197f9bced6bbd7482662231c4"}, + {file = "rpds_py-0.27.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6c27a7054b5224710fcfb1a626ec3ff4f28bcb89b899148c72873b18210e446b"}, + {file = "rpds_py-0.27.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:09965b314091829b378b60607022048953e25f0b396c2b70e7c4c81bcecf932e"}, + {file = "rpds_py-0.27.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:14f028eb47f59e9169bfdf9f7ceafd29dd64902141840633683d0bad5b04ff34"}, + {file = "rpds_py-0.27.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6168af0be75bba990a39f9431cdfae5f0ad501f4af32ae62e8856307200517b8"}, + {file = "rpds_py-0.27.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ab47fe727c13c09d0e6f508e3a49e545008e23bf762a245b020391b621f5b726"}, + {file = "rpds_py-0.27.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fa01b3d5e3b7d97efab65bd3d88f164e289ec323a8c033c5c38e53ee25c007e"}, + {file = "rpds_py-0.27.0-cp312-cp312-manylinux_2_31_riscv64.whl", hash = "sha256:6c135708e987f46053e0a1246a206f53717f9fadfba27174a9769ad4befba5c3"}, + {file = "rpds_py-0.27.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:fc327f4497b7087d06204235199daf208fd01c82d80465dc5efa4ec9df1c5b4e"}, + {file = "rpds_py-0.27.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:7e57906e38583a2cba67046a09c2637e23297618dc1f3caddbc493f2be97c93f"}, + {file = "rpds_py-0.27.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:0f4f69d7a4300fbf91efb1fb4916421bd57804c01ab938ab50ac9c4aa2212f03"}, + {file = "rpds_py-0.27.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b4c4fbbcff474e1e5f38be1bf04511c03d492d42eec0babda5d03af3b5589374"}, + {file = "rpds_py-0.27.0-cp312-cp312-win32.whl", hash = "sha256:27bac29bbbf39601b2aab474daf99dbc8e7176ca3389237a23944b17f8913d97"}, + {file = "rpds_py-0.27.0-cp312-cp312-win_amd64.whl", hash = "sha256:8a06aa1197ec0281eb1d7daf6073e199eb832fe591ffa329b88bae28f25f5fe5"}, + {file = "rpds_py-0.27.0-cp312-cp312-win_arm64.whl", hash = "sha256:e14aab02258cb776a108107bd15f5b5e4a1bbaa61ef33b36693dfab6f89d54f9"}, + {file = "rpds_py-0.27.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:443d239d02d9ae55b74015234f2cd8eb09e59fbba30bf60baeb3123ad4c6d5ff"}, + {file = "rpds_py-0.27.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:b8a7acf04fda1f30f1007f3cc96d29d8cf0a53e626e4e1655fdf4eabc082d367"}, + {file = "rpds_py-0.27.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9d0f92b78cfc3b74a42239fdd8c1266f4715b573204c234d2f9fc3fc7a24f185"}, + {file = "rpds_py-0.27.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ce4ed8e0c7dbc5b19352b9c2c6131dd23b95fa8698b5cdd076307a33626b72dc"}, + {file = "rpds_py-0.27.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:fde355b02934cc6b07200cc3b27ab0c15870a757d1a72fd401aa92e2ea3c6bfe"}, + {file = "rpds_py-0.27.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:13bbc4846ae4c993f07c93feb21a24d8ec637573d567a924b1001e81c8ae80f9"}, + {file = "rpds_py-0.27.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:be0744661afbc4099fef7f4e604e7f1ea1be1dd7284f357924af12a705cc7d5c"}, + {file = "rpds_py-0.27.0-cp313-cp313-manylinux_2_31_riscv64.whl", hash = "sha256:069e0384a54f427bd65d7fda83b68a90606a3835901aaff42185fcd94f5a9295"}, + {file = "rpds_py-0.27.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4bc262ace5a1a7dc3e2eac2fa97b8257ae795389f688b5adf22c5db1e2431c43"}, + {file = "rpds_py-0.27.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:2fe6e18e5c8581f0361b35ae575043c7029d0a92cb3429e6e596c2cdde251432"}, + {file = "rpds_py-0.27.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:d93ebdb82363d2e7bec64eecdc3632b59e84bd270d74fe5be1659f7787052f9b"}, + {file = "rpds_py-0.27.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:0954e3a92e1d62e83a54ea7b3fdc9efa5d61acef8488a8a3d31fdafbfb00460d"}, + {file = "rpds_py-0.27.0-cp313-cp313-win32.whl", hash = "sha256:2cff9bdd6c7b906cc562a505c04a57d92e82d37200027e8d362518df427f96cd"}, + {file = "rpds_py-0.27.0-cp313-cp313-win_amd64.whl", hash = "sha256:dc79d192fb76fc0c84f2c58672c17bbbc383fd26c3cdc29daae16ce3d927e8b2"}, + {file = "rpds_py-0.27.0-cp313-cp313-win_arm64.whl", hash = "sha256:5b3a5c8089eed498a3af23ce87a80805ff98f6ef8f7bdb70bd1b7dae5105f6ac"}, + {file = "rpds_py-0.27.0-cp313-cp313t-macosx_10_12_x86_64.whl", hash = "sha256:90fb790138c1a89a2e58c9282fe1089638401f2f3b8dddd758499041bc6e0774"}, + {file = "rpds_py-0.27.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:010c4843a3b92b54373e3d2291a7447d6c3fc29f591772cc2ea0e9f5c1da434b"}, + {file = "rpds_py-0.27.0-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9ce7a9e967afc0a2af7caa0d15a3e9c1054815f73d6a8cb9225b61921b419bd"}, + {file = "rpds_py-0.27.0-cp313-cp313t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:aa0bf113d15e8abdfee92aa4db86761b709a09954083afcb5bf0f952d6065fdb"}, + {file = "rpds_py-0.27.0-cp313-cp313t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eb91d252b35004a84670dfeafadb042528b19842a0080d8b53e5ec1128e8f433"}, + {file = "rpds_py-0.27.0-cp313-cp313t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:db8a6313dbac934193fc17fe7610f70cd8181c542a91382531bef5ed785e5615"}, + {file = "rpds_py-0.27.0-cp313-cp313t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ce96ab0bdfcef1b8c371ada2100767ace6804ea35aacce0aef3aeb4f3f499ca8"}, + {file = "rpds_py-0.27.0-cp313-cp313t-manylinux_2_31_riscv64.whl", hash = "sha256:7451ede3560086abe1aa27dcdcf55cd15c96b56f543fb12e5826eee6f721f858"}, + {file = "rpds_py-0.27.0-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:32196b5a99821476537b3f7732432d64d93a58d680a52c5e12a190ee0135d8b5"}, + {file = "rpds_py-0.27.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:a029be818059870664157194e46ce0e995082ac49926f1423c1f058534d2aaa9"}, + {file = "rpds_py-0.27.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:3841f66c1ffdc6cebce8aed64e36db71466f1dc23c0d9a5592e2a782a3042c79"}, + {file = "rpds_py-0.27.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:42894616da0fc0dcb2ec08a77896c3f56e9cb2f4b66acd76fc8992c3557ceb1c"}, + {file = "rpds_py-0.27.0-cp313-cp313t-win32.whl", hash = "sha256:b1fef1f13c842a39a03409e30ca0bf87b39a1e2a305a9924deadb75a43105d23"}, + {file = "rpds_py-0.27.0-cp313-cp313t-win_amd64.whl", hash = "sha256:183f5e221ba3e283cd36fdfbe311d95cd87699a083330b4f792543987167eff1"}, + {file = "rpds_py-0.27.0-cp314-cp314-macosx_10_12_x86_64.whl", hash = "sha256:f3cd110e02c5bf17d8fb562f6c9df5c20e73029d587cf8602a2da6c5ef1e32cb"}, + {file = "rpds_py-0.27.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:8d0e09cf4863c74106b5265c2c310f36146e2b445ff7b3018a56799f28f39f6f"}, + {file = "rpds_py-0.27.0-cp314-cp314-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:64f689ab822f9b5eb6dfc69893b4b9366db1d2420f7db1f6a2adf2a9ca15ad64"}, + {file = "rpds_py-0.27.0-cp314-cp314-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e36c80c49853b3ffda7aa1831bf175c13356b210c73128c861f3aa93c3cc4015"}, + {file = "rpds_py-0.27.0-cp314-cp314-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:6de6a7f622860af0146cb9ee148682ff4d0cea0b8fd3ad51ce4d40efb2f061d0"}, + {file = "rpds_py-0.27.0-cp314-cp314-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:4045e2fc4b37ec4b48e8907a5819bdd3380708c139d7cc358f03a3653abedb89"}, + {file = "rpds_py-0.27.0-cp314-cp314-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9da162b718b12c4219eeeeb68a5b7552fbc7aadedf2efee440f88b9c0e54b45d"}, + {file = "rpds_py-0.27.0-cp314-cp314-manylinux_2_31_riscv64.whl", hash = "sha256:0665be515767dc727ffa5f74bd2ef60b0ff85dad6bb8f50d91eaa6b5fb226f51"}, + {file = "rpds_py-0.27.0-cp314-cp314-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:203f581accef67300a942e49a37d74c12ceeef4514874c7cede21b012613ca2c"}, + {file = "rpds_py-0.27.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:7873b65686a6471c0037139aa000d23fe94628e0daaa27b6e40607c90e3f5ec4"}, + {file = "rpds_py-0.27.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:249ab91ceaa6b41abc5f19513cb95b45c6f956f6b89f1fe3d99c81255a849f9e"}, + {file = "rpds_py-0.27.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d2f184336bc1d6abfaaa1262ed42739c3789b1e3a65a29916a615307d22ffd2e"}, + {file = "rpds_py-0.27.0-cp314-cp314-win32.whl", hash = "sha256:d3c622c39f04d5751408f5b801ecb527e6e0a471b367f420a877f7a660d583f6"}, + {file = "rpds_py-0.27.0-cp314-cp314-win_amd64.whl", hash = "sha256:cf824aceaeffff029ccfba0da637d432ca71ab21f13e7f6f5179cd88ebc77a8a"}, + {file = "rpds_py-0.27.0-cp314-cp314-win_arm64.whl", hash = "sha256:86aca1616922b40d8ac1b3073a1ead4255a2f13405e5700c01f7c8d29a03972d"}, + {file = "rpds_py-0.27.0-cp314-cp314t-macosx_10_12_x86_64.whl", hash = "sha256:341d8acb6724c0c17bdf714319c393bb27f6d23d39bc74f94221b3e59fc31828"}, + {file = "rpds_py-0.27.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:6b96b0b784fe5fd03beffff2b1533dc0d85e92bab8d1b2c24ef3a5dc8fac5669"}, + {file = "rpds_py-0.27.0-cp314-cp314t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0c431bfb91478d7cbe368d0a699978050d3b112d7f1d440a41e90faa325557fd"}, + {file = "rpds_py-0.27.0-cp314-cp314t-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:20e222a44ae9f507d0f2678ee3dd0c45ec1e930f6875d99b8459631c24058aec"}, + {file = "rpds_py-0.27.0-cp314-cp314t-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:184f0d7b342967f6cda94a07d0e1fae177d11d0b8f17d73e06e36ac02889f303"}, + {file = "rpds_py-0.27.0-cp314-cp314t-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a00c91104c173c9043bc46f7b30ee5e6d2f6b1149f11f545580f5d6fdff42c0b"}, + {file = "rpds_py-0.27.0-cp314-cp314t-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f7a37dd208f0d658e0487522078b1ed68cd6bce20ef4b5a915d2809b9094b410"}, + {file = "rpds_py-0.27.0-cp314-cp314t-manylinux_2_31_riscv64.whl", hash = "sha256:92f3b3ec3e6008a1fe00b7c0946a170f161ac00645cde35e3c9a68c2475e8156"}, + {file = "rpds_py-0.27.0-cp314-cp314t-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a1b3db5fae5cbce2131b7420a3f83553d4d89514c03d67804ced36161fe8b6b2"}, + {file = "rpds_py-0.27.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:5355527adaa713ab693cbce7c1e0ec71682f599f61b128cf19d07e5c13c9b1f1"}, + {file = "rpds_py-0.27.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:fcc01c57ce6e70b728af02b2401c5bc853a9e14eb07deda30624374f0aebfe42"}, + {file = "rpds_py-0.27.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3001013dae10f806380ba739d40dee11db1ecb91684febb8406a87c2ded23dae"}, + {file = "rpds_py-0.27.0-cp314-cp314t-win32.whl", hash = "sha256:0f401c369186a5743694dd9fc08cba66cf70908757552e1f714bfc5219c655b5"}, + {file = "rpds_py-0.27.0-cp314-cp314t-win_amd64.whl", hash = "sha256:8a1dca5507fa1337f75dcd5070218b20bc68cf8844271c923c1b79dfcbc20391"}, + {file = "rpds_py-0.27.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:e0d7151a1bd5d0a203a5008fc4ae51a159a610cb82ab0a9b2c4d80241745582e"}, + {file = "rpds_py-0.27.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:42ccc57ff99166a55a59d8c7d14f1a357b7749f9ed3584df74053fd098243451"}, + {file = "rpds_py-0.27.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e377e4cf8795cdbdff75b8f0223d7b6c68ff4fef36799d88ccf3a995a91c0112"}, + {file = "rpds_py-0.27.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:79af163a4b40bbd8cfd7ca86ec8b54b81121d3b213b4435ea27d6568bcba3e9d"}, + {file = "rpds_py-0.27.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b2eff8ee57c5996b0d2a07c3601fb4ce5fbc37547344a26945dd9e5cbd1ed27a"}, + {file = "rpds_py-0.27.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7cf9bc4508efb18d8dff6934b602324eb9f8c6644749627ce001d6f38a490889"}, + {file = "rpds_py-0.27.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:05284439ebe7d9f5f5a668d4d8a0a1d851d16f7d47c78e1fab968c8ad30cab04"}, + {file = "rpds_py-0.27.0-cp39-cp39-manylinux_2_31_riscv64.whl", hash = "sha256:1321bce595ad70e80f97f998db37356b2e22cf98094eba6fe91782e626da2f71"}, + {file = "rpds_py-0.27.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:737005088449ddd3b3df5a95476ee1c2c5c669f5c30eed909548a92939c0e12d"}, + {file = "rpds_py-0.27.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:9b2a4e17bfd68536c3b801800941c95a1d4a06e3cada11c146093ba939d9638d"}, + {file = "rpds_py-0.27.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:dc6b0d5a1ea0318ef2def2b6a55dccf1dcaf77d605672347271ed7b829860765"}, + {file = "rpds_py-0.27.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:4c3f8a0d4802df34fcdbeb3dfe3a4d8c9a530baea8fafdf80816fcaac5379d83"}, + {file = "rpds_py-0.27.0-cp39-cp39-win32.whl", hash = "sha256:699c346abc73993962cac7bb4f02f58e438840fa5458a048d3a178a7a670ba86"}, + {file = "rpds_py-0.27.0-cp39-cp39-win_amd64.whl", hash = "sha256:be806e2961cd390a89d6c3ce8c2ae34271cfcd05660f716257838bb560f1c3b6"}, + {file = "rpds_py-0.27.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:46f48482c1a4748ab2773f75fffbdd1951eb59794e32788834b945da857c47a8"}, + {file = "rpds_py-0.27.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:419dd9c98bcc9fb0242be89e0c6e922df333b975d4268faa90d58499fd9c9ebe"}, + {file = "rpds_py-0.27.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55d42a0ef2bdf6bc81e1cc2d49d12460f63c6ae1423c4f4851b828e454ccf6f1"}, + {file = "rpds_py-0.27.0-pp310-pypy310_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2e39169ac6aae06dd79c07c8a69d9da867cef6a6d7883a0186b46bb46ccfb0c3"}, + {file = "rpds_py-0.27.0-pp310-pypy310_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:935afcdea4751b0ac918047a2df3f720212892347767aea28f5b3bf7be4f27c0"}, + {file = "rpds_py-0.27.0-pp310-pypy310_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8de567dec6d451649a781633d36f5c7501711adee329d76c095be2178855b042"}, + {file = "rpds_py-0.27.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:555ed147cbe8c8f76e72a4c6cd3b7b761cbf9987891b9448808148204aed74a5"}, + {file = "rpds_py-0.27.0-pp310-pypy310_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:d2cc2b34f9e1d31ce255174da82902ad75bd7c0d88a33df54a77a22f2ef421ee"}, + {file = "rpds_py-0.27.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cb0702c12983be3b2fab98ead349ac63a98216d28dda6f518f52da5498a27a1b"}, + {file = "rpds_py-0.27.0-pp310-pypy310_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:ba783541be46f27c8faea5a6645e193943c17ea2f0ffe593639d906a327a9bcc"}, + {file = "rpds_py-0.27.0-pp310-pypy310_pp73-musllinux_1_2_i686.whl", hash = "sha256:2406d034635d1497c596c40c85f86ecf2bf9611c1df73d14078af8444fe48031"}, + {file = "rpds_py-0.27.0-pp310-pypy310_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:dea0808153f1fbbad772669d906cddd92100277533a03845de6893cadeffc8be"}, + {file = "rpds_py-0.27.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d2a81bdcfde4245468f7030a75a37d50400ac2455c3a4819d9d550c937f90ab5"}, + {file = "rpds_py-0.27.0-pp311-pypy311_pp73-macosx_10_12_x86_64.whl", hash = "sha256:e6491658dd2569f05860bad645569145c8626ac231877b0fb2d5f9bcb7054089"}, + {file = "rpds_py-0.27.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:bec77545d188f8bdd29d42bccb9191682a46fb2e655e3d1fb446d47c55ac3b8d"}, + {file = "rpds_py-0.27.0-pp311-pypy311_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:25a4aebf8ca02bbb90a9b3e7a463bbf3bee02ab1c446840ca07b1695a68ce424"}, + {file = "rpds_py-0.27.0-pp311-pypy311_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:44524b96481a4c9b8e6c46d6afe43fa1fb485c261e359fbe32b63ff60e3884d8"}, + {file = "rpds_py-0.27.0-pp311-pypy311_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:45d04a73c54b6a5fd2bab91a4b5bc8b426949586e61340e212a8484919183859"}, + {file = "rpds_py-0.27.0-pp311-pypy311_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:343cf24de9ed6c728abefc5d5c851d5de06497caa7ac37e5e65dd572921ed1b5"}, + {file = "rpds_py-0.27.0-pp311-pypy311_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7aed8118ae20515974650d08eb724150dc2e20c2814bcc307089569995e88a14"}, + {file = "rpds_py-0.27.0-pp311-pypy311_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:af9d4fd79ee1cc8e7caf693ee02737daabfc0fcf2773ca0a4735b356c8ad6f7c"}, + {file = "rpds_py-0.27.0-pp311-pypy311_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f0396e894bd1e66c74ecbc08b4f6a03dc331140942c4b1d345dd131b68574a60"}, + {file = "rpds_py-0.27.0-pp311-pypy311_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:59714ab0a5af25d723d8e9816638faf7f4254234decb7d212715c1aa71eee7be"}, + {file = "rpds_py-0.27.0-pp311-pypy311_pp73-musllinux_1_2_i686.whl", hash = "sha256:88051c3b7d5325409f433c5a40328fcb0685fc04e5db49ff936e910901d10114"}, + {file = "rpds_py-0.27.0-pp311-pypy311_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:181bc29e59e5e5e6e9d63b143ff4d5191224d355e246b5a48c88ce6b35c4e466"}, + {file = "rpds_py-0.27.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:9ad08547995a57e74fea6abaf5940d399447935faebbd2612b3b0ca6f987946b"}, + {file = "rpds_py-0.27.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:61490d57e82e23b45c66f96184237994bfafa914433b8cd1a9bb57fecfced59d"}, + {file = "rpds_py-0.27.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7cf5e726b6fa977e428a61880fb108a62f28b6d0c7ef675b117eaff7076df49"}, + {file = "rpds_py-0.27.0-pp39-pypy39_pp73-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:dc662bc9375a6a394b62dfd331874c434819f10ee3902123200dbcf116963f89"}, + {file = "rpds_py-0.27.0-pp39-pypy39_pp73-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:299a245537e697f28a7511d01038c310ac74e8ea213c0019e1fc65f52c0dcb23"}, + {file = "rpds_py-0.27.0-pp39-pypy39_pp73-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:be3964f7312ea05ed283b20f87cb533fdc555b2e428cc7be64612c0b2124f08c"}, + {file = "rpds_py-0.27.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:33ba649a6e55ae3808e4c39e01580dc9a9b0d5b02e77b66bb86ef117922b1264"}, + {file = "rpds_py-0.27.0-pp39-pypy39_pp73-manylinux_2_31_riscv64.whl", hash = "sha256:81f81bbd7cdb4bdc418c09a73809abeda8f263a6bf8f9c7f93ed98b5597af39d"}, + {file = "rpds_py-0.27.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:11e8e28c0ba0373d052818b600474cfee2fafa6c9f36c8587d217b13ee28ca7d"}, + {file = "rpds_py-0.27.0-pp39-pypy39_pp73-musllinux_1_2_aarch64.whl", hash = "sha256:e3acb9c16530362aeaef4e84d57db357002dc5cbfac9a23414c3e73c08301ab2"}, + {file = "rpds_py-0.27.0-pp39-pypy39_pp73-musllinux_1_2_i686.whl", hash = "sha256:2e307cb5f66c59ede95c00e93cd84190a5b7f3533d7953690b2036780622ba81"}, + {file = "rpds_py-0.27.0-pp39-pypy39_pp73-musllinux_1_2_x86_64.whl", hash = "sha256:f09c9d4c26fa79c1bad927efb05aca2391350b8e61c38cbc0d7d3c814e463124"}, + {file = "rpds_py-0.27.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:af22763a0a1eff106426a6e1f13c4582e0d0ad89c1493ab6c058236174cd6c6a"}, + {file = "rpds_py-0.27.0.tar.gz", hash = "sha256:8b23cf252f180cda89220b378d917180f29d313cd6a07b2431c0d3b776aae86f"}, +] + +[[package]] +name = "send2trash" +version = "1.8.3" +description = "Send file to trash natively under Mac OS X, Windows and Linux" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" +groups = ["dev"] +files = [ + {file = "Send2Trash-1.8.3-py3-none-any.whl", hash = "sha256:0c31227e0bd08961c7665474a3d1ef7193929fedda4233843689baa056be46c9"}, + {file = "Send2Trash-1.8.3.tar.gz", hash = "sha256:b18e7a3966d99871aefeb00cfbcfdced55ce4871194810fc71f4aa484b953abf"}, +] + +[package.extras] +nativelib = ["pyobjc-framework-Cocoa ; sys_platform == \"darwin\"", "pywin32 ; sys_platform == \"win32\""] +objc = ["pyobjc-framework-Cocoa ; sys_platform == \"darwin\""] +win32 = ["pywin32 ; sys_platform == \"win32\""] + +[[package]] +name = "setuptools" +version = "80.9.0" +description = "Easily download, build, install, upgrade, and uninstall Python packages" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "setuptools-80.9.0-py3-none-any.whl", hash = "sha256:062d34222ad13e0cc312a4c02d73f059e86a4acbfbdea8f8f76b28c99f306922"}, + {file = "setuptools-80.9.0.tar.gz", hash = "sha256:f36b47402ecde768dbfafc46e8e4207b4360c654f1f3bb84475f0a28628fb19c"}, +] + +[package.extras] +check = ["pytest-checkdocs (>=2.4)", "pytest-ruff (>=0.2.1) ; sys_platform != \"cygwin\"", "ruff (>=0.8.0) ; sys_platform != \"cygwin\""] +core = ["importlib_metadata (>=6) ; python_version < \"3.10\"", "jaraco.functools (>=4)", "jaraco.text (>=3.7)", "more_itertools", "more_itertools (>=8.8)", "packaging (>=24.2)", "platformdirs (>=4.2.2)", "tomli (>=2.0.1) ; python_version < \"3.11\"", "wheel (>=0.43.0)"] +cover = ["pytest-cov"] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier", "towncrier (<24.7)"] +enabler = ["pytest-enabler (>=2.2)"] +test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21) ; python_version >= \"3.9\" and sys_platform != \"cygwin\"", "jaraco.envs (>=2.2)", "jaraco.path (>=3.7.2)", "jaraco.test (>=5.5)", "packaging (>=24.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-home (>=0.5)", "pytest-perf ; sys_platform != \"cygwin\"", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel (>=0.44.0)"] +type = ["importlib_metadata (>=7.0.2) ; python_version < \"3.10\"", "jaraco.develop (>=7.21) ; sys_platform != \"cygwin\"", "mypy (==1.14.*)", "pytest-mypy"] + +[[package]] +name = "six" +version = "1.17.0" +description = "Python 2 and 3 compatibility utilities" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +groups = ["main", "dev"] +files = [ + {file = "six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274"}, + {file = "six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81"}, +] + +[[package]] +name = "sniffio" +version = "1.3.1" +description = "Sniff out which async library your code is running under" +optional = false +python-versions = ">=3.7" +groups = ["dev"] +files = [ + {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"}, + {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"}, +] + +[[package]] +name = "soupsieve" +version = "2.7" +description = "A modern CSS selector implementation for Beautiful Soup." +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "soupsieve-2.7-py3-none-any.whl", hash = "sha256:6e60cc5c1ffaf1cebcc12e8188320b72071e922c2e897f737cadce79ad5d30c4"}, + {file = "soupsieve-2.7.tar.gz", hash = "sha256:ad282f9b6926286d2ead4750552c8a6142bc4c783fd66b0293547c8fe6ae126a"}, +] + +[[package]] +name = "stack-data" +version = "0.6.3" +description = "Extract data from python stack frames and tracebacks for informative displays" +optional = false +python-versions = "*" +groups = ["dev"] +files = [ + {file = "stack_data-0.6.3-py3-none-any.whl", hash = "sha256:d5558e0c25a4cb0853cddad3d77da9891a08cb85dd9f9f91b9f8cd66e511e695"}, + {file = "stack_data-0.6.3.tar.gz", hash = "sha256:836a778de4fec4dcd1dcd89ed8abff8a221f58308462e1c4aa2a3cf30148f0b9"}, +] + +[package.dependencies] +asttokens = ">=2.1.0" +executing = ">=1.2.0" +pure-eval = "*" + +[package.extras] +tests = ["cython", "littleutils", "pygments", "pytest", "typeguard"] + +[[package]] +name = "stdlib-list" +version = "0.11.1" +description = "A list of Python Standard Libraries (2.7 through 3.13)." +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "stdlib_list-0.11.1-py3-none-any.whl", hash = "sha256:9029ea5e3dfde8cd4294cfd4d1797be56a67fc4693c606181730148c3fd1da29"}, + {file = "stdlib_list-0.11.1.tar.gz", hash = "sha256:95ebd1d73da9333bba03ccc097f5bac05e3aa03e6822a0c0290f87e1047f1857"}, +] + +[package.extras] +dev = ["build", "stdlib-list[doc,lint,test]"] +doc = ["furo", "sphinx"] +lint = ["mypy", "ruff"] +support = ["sphobjinv"] +test = ["coverage[toml]", "pytest", "pytest-cov"] + +[[package]] +name = "terminado" +version = "0.18.1" +description = "Tornado websocket backend for the Xterm.js Javascript terminal emulator library." +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "terminado-0.18.1-py3-none-any.whl", hash = "sha256:a4468e1b37bb318f8a86514f65814e1afc977cf29b3992a4500d9dd305dcceb0"}, + {file = "terminado-0.18.1.tar.gz", hash = "sha256:de09f2c4b85de4765f7714688fff57d3e75bad1f909b589fde880460c753fd2e"}, +] + +[package.dependencies] +ptyprocess = {version = "*", markers = "os_name != \"nt\""} +pywinpty = {version = ">=1.1.0", markers = "os_name == \"nt\""} +tornado = ">=6.1.0" + +[package.extras] +docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"] +test = ["pre-commit", "pytest (>=7.0)", "pytest-timeout"] +typing = ["mypy (>=1.6,<2.0)", "traitlets (>=5.11.1)"] + +[[package]] +name = "tinycss2" +version = "1.4.0" +description = "A tiny CSS parser" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "tinycss2-1.4.0-py3-none-any.whl", hash = "sha256:3a49cf47b7675da0b15d0c6e1df8df4ebd96e9394bb905a5775adb0d884c5289"}, + {file = "tinycss2-1.4.0.tar.gz", hash = "sha256:10c0972f6fc0fbee87c3edb76549357415e94548c1ae10ebccdea16fb404a9b7"}, +] + +[package.dependencies] +webencodings = ">=0.4" + +[package.extras] +doc = ["sphinx", "sphinx_rtd_theme"] +test = ["pytest", "ruff"] + +[[package]] +name = "tomlkit" +version = "0.13.3" +description = "Style preserving TOML library" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "tomlkit-0.13.3-py3-none-any.whl", hash = "sha256:c89c649d79ee40629a9fda55f8ace8c6a1b42deb912b2a8fd8d942ddadb606b0"}, + {file = "tomlkit-0.13.3.tar.gz", hash = "sha256:430cf247ee57df2b94ee3fbe588e71d362a941ebb545dec29b53961d61add2a1"}, +] + +[[package]] +name = "tornado" +version = "6.5.2" +description = "Tornado is a Python web framework and asynchronous networking library, originally developed at FriendFeed." +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "tornado-6.5.2-cp39-abi3-macosx_10_9_universal2.whl", hash = "sha256:2436822940d37cde62771cff8774f4f00b3c8024fe482e16ca8387b8a2724db6"}, + {file = "tornado-6.5.2-cp39-abi3-macosx_10_9_x86_64.whl", hash = "sha256:583a52c7aa94ee046854ba81d9ebb6c81ec0fd30386d96f7640c96dad45a03ef"}, + {file = "tornado-6.5.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b0fe179f28d597deab2842b86ed4060deec7388f1fd9c1b4a41adf8af058907e"}, + {file = "tornado-6.5.2-cp39-abi3-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b186e85d1e3536d69583d2298423744740986018e393d0321df7340e71898882"}, + {file = "tornado-6.5.2-cp39-abi3-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e792706668c87709709c18b353da1f7662317b563ff69f00bab83595940c7108"}, + {file = "tornado-6.5.2-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:06ceb1300fd70cb20e43b1ad8aaee0266e69e7ced38fa910ad2e03285009ce7c"}, + {file = "tornado-6.5.2-cp39-abi3-musllinux_1_2_i686.whl", hash = "sha256:74db443e0f5251be86cbf37929f84d8c20c27a355dd452a5cfa2aada0d001ec4"}, + {file = "tornado-6.5.2-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b5e735ab2889d7ed33b32a459cac490eda71a1ba6857b0118de476ab6c366c04"}, + {file = "tornado-6.5.2-cp39-abi3-win32.whl", hash = "sha256:c6f29e94d9b37a95013bb669616352ddb82e3bfe8326fccee50583caebc8a5f0"}, + {file = "tornado-6.5.2-cp39-abi3-win_amd64.whl", hash = "sha256:e56a5af51cc30dd2cae649429af65ca2f6571da29504a07995175df14c18f35f"}, + {file = "tornado-6.5.2-cp39-abi3-win_arm64.whl", hash = "sha256:d6c33dc3672e3a1f3618eb63b7ef4683a7688e7b9e6e8f0d9aa5726360a004af"}, + {file = "tornado-6.5.2.tar.gz", hash = "sha256:ab53c8f9a0fa351e2c0741284e06c7a45da86afb544133201c5cc8578eb076a0"}, +] + +[[package]] +name = "traitlets" +version = "5.14.3" +description = "Traitlets Python configuration system" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "traitlets-5.14.3-py3-none-any.whl", hash = "sha256:b74e89e397b1ed28cc831db7aea759ba6640cb3de13090ca145426688ff1ac4f"}, + {file = "traitlets-5.14.3.tar.gz", hash = "sha256:9ed0579d3502c94b4b3732ac120375cda96f923114522847de4b3bb98b96b6b7"}, +] + +[package.extras] +docs = ["myst-parser", "pydata-sphinx-theme", "sphinx"] +test = ["argcomplete (>=3.0.3)", "mypy (>=1.7.0)", "pre-commit", "pytest (>=7.0,<8.2)", "pytest-mock", "pytest-mypy-testing"] + +[[package]] +name = "types-python-dateutil" +version = "2.9.0.20250809" +description = "Typing stubs for python-dateutil" +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "types_python_dateutil-2.9.0.20250809-py3-none-any.whl", hash = "sha256:768890cac4f2d7fd9e0feb6f3217fce2abbfdfc0cadd38d11fba325a815e4b9f"}, + {file = "types_python_dateutil-2.9.0.20250809.tar.gz", hash = "sha256:69cbf8d15ef7a75c3801d65d63466e46ac25a0baa678d89d0a137fc31a608cc1"}, +] + +[[package]] +name = "typing-extensions" +version = "4.14.1" +description = "Backported and Experimental Type Hints for Python 3.9+" +optional = false +python-versions = ">=3.9" +groups = ["main", "dev"] +files = [ + {file = "typing_extensions-4.14.1-py3-none-any.whl", hash = "sha256:d1e1e3b58374dc93031d6eda2420a48ea44a36c2b4766a4fdeb3710755731d76"}, + {file = "typing_extensions-4.14.1.tar.gz", hash = "sha256:38b39f4aeeab64884ce9f74c94263ef78f3c22467c8724005483154c26648d36"}, +] + +[[package]] +name = "typing-inspection" +version = "0.4.1" +description = "Runtime typing introspection tools" +optional = false +python-versions = ">=3.9" +groups = ["main"] +files = [ + {file = "typing_inspection-0.4.1-py3-none-any.whl", hash = "sha256:389055682238f53b04f7badcb49b989835495a96700ced5dab2d8feae4b26f51"}, + {file = "typing_inspection-0.4.1.tar.gz", hash = "sha256:6ae134cc0203c33377d43188d4064e9b357dba58cff3185f22924610e70a9d28"}, +] + +[package.dependencies] +typing-extensions = ">=4.12.0" + +[[package]] +name = "tzdata" +version = "2025.2" +description = "Provider of IANA time zone data" +optional = false +python-versions = ">=2" +groups = ["main"] +files = [ + {file = "tzdata-2025.2-py2.py3-none-any.whl", hash = "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8"}, + {file = "tzdata-2025.2.tar.gz", hash = "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9"}, +] + +[[package]] +name = "uri-template" +version = "1.3.0" +description = "RFC 6570 URI Template Processor" +optional = false +python-versions = ">=3.7" +groups = ["dev"] +files = [ + {file = "uri-template-1.3.0.tar.gz", hash = "sha256:0e00f8eb65e18c7de20d595a14336e9f337ead580c70934141624b6d1ffdacc7"}, + {file = "uri_template-1.3.0-py3-none-any.whl", hash = "sha256:a44a133ea12d44a0c0f06d7d42a52d71282e77e2f937d8abd5655b8d56fc1363"}, +] + +[package.extras] +dev = ["flake8", "flake8-annotations", "flake8-bandit", "flake8-bugbear", "flake8-commas", "flake8-comprehensions", "flake8-continuation", "flake8-datetimez", "flake8-docstrings", "flake8-import-order", "flake8-literal", "flake8-modern-annotations", "flake8-noqa", "flake8-pyproject", "flake8-requirements", "flake8-typechecking-import", "flake8-use-fstring", "mypy", "pep8-naming", "types-PyYAML"] + +[[package]] +name = "urllib3" +version = "2.5.0" +description = "HTTP library with thread-safe connection pooling, file post, and more." +optional = false +python-versions = ">=3.9" +groups = ["main", "dev"] +files = [ + {file = "urllib3-2.5.0-py3-none-any.whl", hash = "sha256:e6b01673c0fa6a13e374b50871808eb3bf7046c4b125b216f6bf1cc604cff0dc"}, + {file = "urllib3-2.5.0.tar.gz", hash = "sha256:3fc47733c7e419d4bc3f6b3dc2b4f890bb743906a30d56ba4a5bfa4bbff92760"}, +] + +[package.extras] +brotli = ["brotli (>=1.0.9) ; platform_python_implementation == \"CPython\"", "brotlicffi (>=0.8.0) ; platform_python_implementation != \"CPython\""] +h2 = ["h2 (>=4,<5)"] +socks = ["pysocks (>=1.5.6,!=1.5.7,<2.0)"] +zstd = ["zstandard (>=0.18.0)"] + +[[package]] +name = "wcwidth" +version = "0.2.13" +description = "Measures the displayed width of unicode strings in a terminal" +optional = false +python-versions = "*" +groups = ["dev"] +files = [ + {file = "wcwidth-0.2.13-py2.py3-none-any.whl", hash = "sha256:3da69048e4540d84af32131829ff948f1e022c1c6bdb8d6102117aac784f6859"}, + {file = "wcwidth-0.2.13.tar.gz", hash = "sha256:72ea0c06399eb286d978fdedb6923a9eb47e1c486ce63e9b4e64fc18303972b5"}, +] + +[[package]] +name = "webcolors" +version = "24.11.1" +description = "A library for working with the color formats defined by HTML and CSS." +optional = false +python-versions = ">=3.9" +groups = ["dev"] +files = [ + {file = "webcolors-24.11.1-py3-none-any.whl", hash = "sha256:515291393b4cdf0eb19c155749a096f779f7d909f7cceea072791cb9095b92e9"}, + {file = "webcolors-24.11.1.tar.gz", hash = "sha256:ecb3d768f32202af770477b8b65f318fa4f566c22948673a977b00d589dd80f6"}, +] + +[[package]] +name = "webencodings" +version = "0.5.1" +description = "Character encoding aliases for legacy web content" +optional = false +python-versions = "*" +groups = ["dev"] +files = [ + {file = "webencodings-0.5.1-py2.py3-none-any.whl", hash = "sha256:a0af1213f3c2226497a97e2b3aa01a7e4bee4f403f95be16fc9acd2947514a78"}, + {file = "webencodings-0.5.1.tar.gz", hash = "sha256:b36a1c245f2d304965eb4e0a82848379241dc04b865afcc4aab16748587e1923"}, +] + +[[package]] +name = "websocket-client" +version = "1.8.0" +description = "WebSocket client for Python with low level API options" +optional = false +python-versions = ">=3.8" +groups = ["dev"] +files = [ + {file = "websocket_client-1.8.0-py3-none-any.whl", hash = "sha256:17b44cc997f5c498e809b22cdf2d9c7a9e71c02c8cc2b6c56e7c2d1239bfa526"}, + {file = "websocket_client-1.8.0.tar.gz", hash = "sha256:3239df9f44da632f96012472805d40a23281a991027ce11d2f45a6f24ac4c3da"}, +] + +[package.extras] +docs = ["Sphinx (>=6.0)", "myst-parser (>=2.0.0)", "sphinx-rtd-theme (>=1.1.0)"] +optional = ["python-socks", "wsaccel"] +test = ["websockets"] + +[[package]] +name = "xlsxwriter" +version = "3.2.5" +description = "A Python module for creating Excel XLSX files." +optional = false +python-versions = ">=3.8" +groups = ["main"] +files = [ + {file = "xlsxwriter-3.2.5-py3-none-any.whl", hash = "sha256:4f4824234e1eaf9d95df9a8fe974585ff91d0f5e3d3f12ace5b71e443c1c6abd"}, + {file = "xlsxwriter-3.2.5.tar.gz", hash = "sha256:7e88469d607cdc920151c0ab3ce9cf1a83992d4b7bc730c5ffdd1a12115a7dbe"}, +] + +[metadata] +lock-version = "2.1" +python-versions = ">=3.12,<4.0" +content-hash = "abe3b5271081c3ad44b715ed68207041ce87d3e9fee9512f9c14d93248e21a5d" diff --git a/pyproject.toml b/pyproject.toml index 4c3d1cb..6a76a4f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,58 +1,50 @@ [build-system] -requires = ["setuptools", "wheel"] -build-backend = "setuptools.build_meta" +requires = ["poetry-core>=1.0.0"] +build-backend = "poetry.core.masonry.api" -[project] +[tool.poetry] name = "pyetm" -version = "2.0-beta" - -description = "Python-ETM Connector" -authors = [] # TODO: add us! +version = "2.0" +description = "A Python package for energy transition modeling." +authors = ["Your Name "] +license = "MIT" readme = "README.md" -requires-python = ">=3.12" -license = {file = "LICENSE"} -dependencies = [ - # 'requests>=2.26', - # 'pandas[parquet]>=2.2', - # 'openpyxl>=3.0', - # 'xlsxwriter>=3.0', -] -keywords = ["ETM", "Energy Transition Model"] -classifiers = [ - 'Development Status :: 4 - Beta', - 'Intended Audience :: Developers', - 'Intended Audience :: Education', - 'Intended Audience :: Science/Research', - # 'License :: OSI Approved :: European Union Public Licence 1.2 (EUPL 1.2)', - 'Natural Language :: English', - 'Operating System :: OS Independent', - 'Programming Language :: Python', - # 'Programming Language :: Python :: 3', - # 'Programming Language :: Python :: 3.10', - # 'Programming Language :: Python :: 3.11', - # 'Programming Language :: Python :: 3.12', -] +homepage = "https://github.com/quintel/pyetm" +repository = "https://github.com/quintel/pyetm" +documentation = "https://docs.energytransitionmodel.com/main/pyetm/introduction" +keywords = ["energy", "transition", "modeling", "api"] +packages = [{ include = "pyetm", from = "src" }] -[project.urls] -repository = "https://github.com/robcalon/pyetm" +[tool.poetry.dependencies] +python = ">=3.12,<4.0" +pydantic = "*" +pandas = "*" +requests = "*" +python-dotenv = "*" +pyyaml = "*" +pydantic-settings = "*" +xlsxwriter = "*" +openpyxl = "*" -[project.optional-dependencies] -async = ["aiohttp>=3.8"] -dev = [ - "pytest>=7.0", - "pylint>=3.0", - "requests-mock>=1.11" -] +[tool.poetry.group.dev.dependencies] +pytest = "*" +pylint = "*" +requests-mock = "*" +ipykernel = "*" +notebook = "*" +pytest-cov = "*" +pydeps = "*" -[tool.setuptools.package-data] -"pyetm.data" = ["*.csv"] +[tool.poetry.scripts] +pyetm = "pyetm.__main__:main" -[tool.pylint] -max-args = 15 -max-local = 20 +[tool.poetry.urls] +"Bug Tracker" = "https://github.com/quintel/pyetm/issues" +"Documentation" = "https://docs.energytransitionmodel.com/main/pyetm/introduction" [tool.pytest.ini_options] -minversion = "7.0" -addopts = [ - "--import-mode=importlib", -] +addopts = "--cov=pyetm --cov-report=term-missing" +testpaths = ["tests"] + +[tool.pylint.main] +fail-under = 8.0 diff --git a/running_notebooks.md b/running_notebooks.md index e9af4a6..8fa45ba 100644 --- a/running_notebooks.md +++ b/running_notebooks.md @@ -1,9 +1,10 @@ # Running Notebooks This guide will help you install everything you need to open and run our Jupyter notebooks in VS Code, -even if you don’t have Python, Jupyter, or any VS Code extensions installed yet. If you'd like some -additional guidance or you're having trouble, check out [this helpful guide from vscode](https://www.youtube.com/watch?v=suAkMeWJ1yE&ab_channel=VisualStudioCode). -Just note that in the video they use venv, whereas we use pipenv (these are practically interchangable). +even if you don’t have Python, Jupyter, or any VS Code extensions installed yet. + +If you'd like some additional guidance or you're having trouble, check out [this helpful guide from VS Code](https://www.youtube.com/watch?v=suAkMeWJ1yE&ab_channel=VisualStudioCode). +Just note: in the video they use `venv`, whereas we use [Poetry](https://python-poetry.org/) for dependency management and virtual environments. --- @@ -17,17 +18,20 @@ Just note that in the video they use venv, whereas we use pipenv (these are prac ## 2. Install Python Go to the [official Python download page](https://www.python.org/downloads/) and download the latest -**Python 3.x** installer for your OS. -- **Windows:** Run the installer, **check** "Add Python to PATH", and click **Install Now**. -- **macOS/Linux:** Follow the on-screen instructions. On Linux, you can also use your package manager: - - ```bash - # Ubuntu/Debian - sudo apt update && sudo apt install python3 python3-venv python3-pip - ``` +**Python 3.12+** installer for your OS. + +- **Windows:** Run the installer, **check** "Add Python to PATH", and click **Install Now**. +- **macOS/Linux:** Follow the on-screen instructions. On macOS you can also use [Homebrew](https://brew.sh/): + ```bash + brew install python@3.12 + ``` + On Linux, you can use your package manager: + ```bash + # Ubuntu/Debian + sudo apt update && sudo apt install python3 python3-pip + ``` Verify installation by opening a terminal and running: - ```bash python3 --version # or on Windows @@ -43,7 +47,6 @@ python --version 3. (Optional) Check "Add to PATH" during installation for easier command-line use. Verify by running: - ```bash code --version ``` @@ -53,39 +56,39 @@ code --version ## 4. Install Necessary VS Code Extensions 1. Open VS Code. -2. Click the **Extensions** icon (or press Ctrl+Shift+X). +2. Click the **Extensions** icon (or press `Ctrl+Shift+X` / `Cmd+Shift+X` on macOS). 3. Install: - * **Python** (by Microsoft) * **Jupyter** (by Microsoft) --- -## 5. Set Up a Python Environment (using Pipenv) +## 5. Set Up a Python Environment (using Poetry) -If you'd like to learn more about pipenv, [check out the docs here.](https://pipenv.pypa.io/en/latest/index.html) - -In your project folder: - -1. **Install Pipenv** (if you don’t have it already): +We use [Poetry](https://python-poetry.org/) to manage dependencies and virtual environments. +1. **Install Poetry** (if you don’t have it already): ```bash - pip install pipenv + curl -sSL https://install.python-poetry.org | python3 - + ``` + Or on Windows (PowerShell): + ```powershell + (Invoke-WebRequest -Uri https://install.python-poetry.org -UseBasicParsing).Content | py - ``` -2. **Install dependencies** from `Pipfile`: +2. **Install dependencies** from `pyproject.toml`: ```bash - pipenv install + poetry install --with dev ``` -3. **Activate** the Pipenv environment: +3. **Activate** the Poetry environment: ```bash - pipenv shell + eval $(poetry env activate) ``` -4. When adding new packages: +4. When adding new packages: ```bash - pipenv install + poetry add ``` --- @@ -93,13 +96,13 @@ In your project folder: ## 6. Open & Run the Notebook 1. In VS Code, go to **File → Open Folder** and select this project’s root folder. -2. Locate a `.ipynb` file in the Examples folder, and click to open it. -3. At the top right of the notebook editor, click **Select Kernel** and choose the interpreter from -your Pipenv environment (it will mention `Pipenv`). -4. Run cells by clicking the ▶️ icon or pressing Shift+Enter. +2. Locate a `.ipynb` file in the `examples` folder, and click to open it. +3. At the top right of the notebook editor, click **Select Kernel** and choose the interpreter from your Poetry environment (it will mention `.venv` or the Poetry-managed path). +4. Run cells by clicking the ▶️ icon or pressing `Shift+Enter`. --- ## 7. Important Notes -After this setup you will be *almost* ready to run the Jupyter notebooks in the examples folder. You -still need to configure your settings as [outlined in the main readme.](README.md) + +After this setup you will be *almost* ready to run the Jupyter notebooks in the examples folder. +You still need to configure your settings as [outlined in the main README](README.md). diff --git a/src/pyetm/config/settings.py b/src/pyetm/config/settings.py index 3119b40..a04ed36 100644 --- a/src/pyetm/config/settings.py +++ b/src/pyetm/config/settings.py @@ -1,4 +1,5 @@ from pathlib import Path +import re import yaml, os from typing import Optional, ClassVar, List, Annotated from pydantic import Field, ValidationError, HttpUrl, field_validator @@ -7,6 +8,7 @@ PROJECT_ROOT = Path(__file__).resolve().parents[3] CONFIG_FILE = PROJECT_ROOT / "config.yml" + class AppConfig(BaseSettings): """ Application configuration loaded from YAML. @@ -23,6 +25,13 @@ class AppConfig(BaseSettings): "https://engine.energytransitionmodel.com/api/v3", description="Base URL for the ETM API", ) + environment: Optional[str] = Field( + None, + description=( + "ETM environment to target. One of: 'pro' (default), 'beta', 'local', or a stable tag 'YYYY-MM'. " + "When set and base_url is not provided, base_url will be inferred." + ), + ) log_level: Optional[str] = Field( "INFO", description="App logging level", @@ -32,7 +41,7 @@ class AppConfig(BaseSettings): env_file=None, extra="ignore", case_sensitive=False ) - temp_folder: Optional[Path] = PROJECT_ROOT / 'tmp' + temp_folder: Optional[Path] = PROJECT_ROOT / "tmp" @field_validator("etm_api_token") @classmethod @@ -84,10 +93,17 @@ def from_yaml(cls, path: Path) -> "AppConfig": data = {k.lower(): v for k, v in raw.items()} - for field in ("etm_api_token", "base_url", "log_level"): + # Collect environment variables overriding YAML + for field in ("etm_api_token", "base_url", "log_level", "environment"): if val := os.getenv(field.upper()): data[field] = val + # If base_url wasn't explicitly provided, infer it from environment if present + if "base_url" not in data or not data["base_url"]: + env = (data.get("environment") or "").strip().lower() + if env: + data["base_url"] = _infer_base_url_from_env(env) + return cls(**data) @@ -111,3 +127,32 @@ def get_settings() -> AppConfig: f"{detail}\n\n" f"Please set them via environment variables or in `{CONFIG_FILE}`." ) from exc + + +def _infer_base_url_from_env(environment: str) -> str: + """ + Infers the ETM API base URL from an environment string. + + Supported values (case-insensitive): + - 'pro'/'prod' (default): https://engine.energytransitionmodel.com/api/v3 + - 'beta'/'staging': https://beta.engine.energytransitionmodel.com/api/v3 + - 'local'/'dev'/'development': http://localhost:3000/api/v3 + - stable tags 'YYYY-MM': https://{YYYY-MM}.engine.energytransitionmodel.com/api/v3 + + Falls back to the 'pro' URL if the input is empty or unrecognized. + """ + env = (environment or "").strip().lower() + + if env in ("", "pro", "prod"): # default + return "https://engine.energytransitionmodel.com/api/v3" + if env in ("beta", "staging"): + return "https://beta.engine.energytransitionmodel.com/api/v3" + if env in ("local", "dev", "development"): + return "http://localhost:3000/api/v3" + + # Stable tagged environments e.g., '2025-01' + if re.fullmatch(r"\d{4}-\d{2}", env): + return f"https://{env}.engine.energytransitionmodel.com/api/v3" + + # Unrecognized: be conservative and return production + return "https://engine.energytransitionmodel.com/api/v3" diff --git a/src/pyetm/models/packables/output_curves_pack.py b/src/pyetm/models/packables/output_curves_pack.py index ff90d49..58b0a60 100644 --- a/src/pyetm/models/packables/output_curves_pack.py +++ b/src/pyetm/models/packables/output_curves_pack.py @@ -1,9 +1,10 @@ import logging -from typing import ClassVar, Any - +from typing import ClassVar, Any, Optional, Sequence, Tuple +from xlsxwriter import Workbook +from pyetm.models.output_curves import OutputCurves import pandas as pd - from pyetm.models.packables.packable import Packable +from pyetm.utils.excel import add_frame logger = logging.getLogger(__name__) @@ -26,3 +27,97 @@ def _build_dataframe_for_scenario(self, scenario: Any, columns: str = "", **kwar def _to_dataframe(self, columns="", **kwargs) -> pd.DataFrame: return self.build_pack_dataframe(columns=columns, **kwargs) + + def to_excel_per_carrier( + self, path: str, carriers: Optional[Sequence[str]] = None + ) -> None: + + # Determine carrier selection + carrier_map = OutputCurves._load_carrier_mappings() + valid_carriers = list(carrier_map.keys()) + selected = list(valid_carriers if carriers is None else carriers) + selected = [c for c in selected if c in valid_carriers] + if not selected: + selected = valid_carriers + + # Nothing to do without scenarios + if not self.scenarios: + return + + wrote_any = False + workbook = None + try: + # Sort scenarios for deterministic sheet layout + scenarios_sorted = sorted(self.scenarios, key=lambda s: s.id) + + for carrier in selected: + series_entries: list[Tuple[Tuple[str, str], pd.Series]] = [] + + for scenario in scenarios_sorted: + # Scenario label + try: + scenario_name = str(scenario.identifier()) + except Exception: + scenario_name = str(getattr(scenario, "id", "scenario")) + + # Fetch curves mapping safely + curves = None + if hasattr(scenario, "get_output_curves") and callable( + getattr(scenario, "get_output_curves") + ): + try: + curves = scenario.get_output_curves(carrier) + except Exception: + curves = None + if not isinstance(curves, dict) or not curves: + continue + + for curve_name, df in curves.items(): + if df is None: + continue + try: + if isinstance(df, pd.Series): + s = df.copy() + series_entries.append(((scenario_name, curve_name), s)) + elif isinstance(df, pd.DataFrame): + if df.empty: + continue + if df.shape[1] == 1: + s = df.iloc[:, 0].copy() + series_entries.append( + ((scenario_name, curve_name), s) + ) + else: + for col in df.columns: + s = df[col].copy() + sub_curve = f"{curve_name}:{col}" + series_entries.append( + ((scenario_name, sub_curve), s) + ) + except Exception: + continue + + if not series_entries: + continue + + cols: list[Tuple[str, str]] = [key for key, _ in series_entries] + frames = [s for _, s in series_entries] + combined = pd.concat(frames, axis=1) + combined.columns = pd.MultiIndex.from_tuples( + cols, names=["Scenario", "Curve"] + ) + + # Lazily create the workbook on first real data + if workbook is None: + workbook = Workbook(str(path)) + add_frame( + name=carrier.upper(), + frame=combined, + workbook=workbook, + column_width=18, + scenario_styling=True, + ) + wrote_any = True + finally: + if workbook is not None and wrote_any: + workbook.close() diff --git a/src/pyetm/models/scenario.py b/src/pyetm/models/scenario.py index 36ab2ee..c87e6e4 100644 --- a/src/pyetm/models/scenario.py +++ b/src/pyetm/models/scenario.py @@ -111,15 +111,43 @@ def from_excel(cls, xlsx_path: PathLike | str) -> List["Scenario"]: scenarios.sort(key=lambda s: s.id) return scenarios - def to_excel(self, path: PathLike | str, *others: "Scenario") -> None: + def to_excel( + self, + path: PathLike | str, + *others: "Scenario", + export_output_curves: bool = True, + output_curves_path: str | None = None, + carriers: list[str] | None = None, + ) -> None: """ Export this scenario – and optionally additional scenarios – to an Excel file. + Output curves are exported to a separate workbook by default, with one sheet + per carrier. Use carriers to filter which carriers to include. """ - from pyetm.models.scenario_packer import ScenarioPacker + from pyetm.models.scenarios import Scenarios + + Scenarios(items=[self, *others]).to_excel( + path, + export_output_curves=export_output_curves, + output_curves_path=output_curves_path, + carriers=carriers, + ) - packer = ScenarioPacker() - packer.add(self, *others) - packer.to_excel(str(path)) + # Deprecated helper retained for backwards compatibility: route to main to_excel + def to_output_curves_excel( + self, + path: PathLike | str, + *others: "Scenario", + carriers: list[str] | None = None, + ) -> None: + from pyetm.models.scenarios import Scenarios + + Scenarios(items=[self, *others]).to_excel( + path, + export_output_curves=True, + output_curves_path=str(path), + carriers=carriers, + ) def update_metadata(self, **kwargs) -> Dict[str, Any]: """ diff --git a/src/pyetm/models/scenario_packer.py b/src/pyetm/models/scenario_packer.py index c024c5b..eef48c1 100644 --- a/src/pyetm/models/scenario_packer.py +++ b/src/pyetm/models/scenario_packer.py @@ -1,8 +1,9 @@ import pandas as pd import logging +from pathlib import Path from os import PathLike from pydantic import BaseModel -from typing import Optional, Dict, Any +from typing import Optional, Dict, Any, Sequence from xlsxwriter import Workbook from pyetm.models.packables.custom_curves_pack import CustomCurvesPack @@ -55,7 +56,7 @@ def add_output_curves(self, *scenarios): # DataFrame outputs def main_info(self) -> pd.DataFrame: - """Create main info DataFrame""" + """Create main info DataFrame by concatenating scenario dataframes.""" if len(self._scenarios()) == 0: return pd.DataFrame() @@ -78,25 +79,35 @@ def custom_curves(self) -> pd.DataFrame: def output_curves(self) -> pd.DataFrame: return self._output_curves.to_dataframe() - def to_excel(self, path: str): + def to_excel( + self, + path: str, + *, + export_output_curves: bool = True, + output_curves_path: Optional[str] = None, + carriers: Optional[Sequence[str]] = None, + ): if len(self._scenarios()) == 0: raise ValueError("Packer was empty, nothing to export") workbook = Workbook(path) - # Main info sheet (handled separately as it doesn't use a pack) - df = self.main_info() - if not df.empty: - df_filled = df.fillna("").infer_objects(copy=False) + # Main info sheet: enrich with metadata and friendly headers for Excel only + df_main = self._build_excel_main_dataframe() + if not df_main.empty: + df_main = self._sanitize_dataframe_for_excel(df_main) add_frame( name="MAIN", - frame=df_filled, + frame=df_main, workbook=workbook, column_width=18, scenario_styling=True, ) for pack in self.all_pack_data(): + # Skip output curves in the main workbook; exported separately + if getattr(pack, "key", None) == OutputCurvesPack.key: + continue df = pack.to_dataframe() if not df.empty: df_filled = df.fillna("").infer_objects(copy=False) @@ -110,12 +121,37 @@ def to_excel(self, path: str): workbook.close() + # Export output curves to a separate workbook with one sheet per carrier + if export_output_curves: + oc_path = output_curves_path + if oc_path is None: + base = Path(path) + oc_path = str(base.with_name(f"{base.stem}_output_curves{base.suffix}")) + try: + self._output_curves.to_excel_per_carrier(oc_path, carriers) + except Exception as e: + logger.warning("Failed exporting output curves workbook: %s", e) + def _scenarios(self) -> set["Scenario"]: """ - All scenarios we are packing info for: for these we need to insert - their metadata + All scenarios we are packing info for across all packs. """ - return set.union(*map(set, (pack.scenarios for pack in self.all_pack_data()))) + all_scenarios: set["Scenario"] = set() + for pack in self.all_pack_data(): + try: + items = getattr(pack, "scenarios", None) + if not items: + continue + if isinstance(items, set): + all_scenarios.update(items) + else: + try: + all_scenarios.update(list(items)) + except TypeError: + continue + except Exception: + continue + return all_scenarios def all_pack_data(self): """Yields each subpack""" @@ -503,3 +539,115 @@ def _setup_scenario_from_main_column( self._apply_metadata(scenario, meta_updates) return scenario + + def _build_excel_main_dataframe(self) -> pd.DataFrame: + """Build a MAIN sheet DataFrame with rich metadata for Excel export only.""" + scenarios = list(self._scenarios()) + if not scenarios: + return pd.DataFrame() + + def id_or_title(s): + try: + return s.identifier() + except Exception: + return getattr(s, "id", None) + + columns: dict[Any, dict[str, Any]] = {} + all_keys: list[str] = [] + + def add_key(k: str): + if k not in all_keys: + all_keys.append(k) + + for s in scenarios: + info: dict[str, Any] = {} + + # Core identifiers and common fields + info["scenario_id"] = getattr(s, "id", None) + info["area_code"] = getattr(s, "area_code", None) + info["end_year"] = getattr(s, "end_year", None) + info["start_year"] = getattr(s, "start_year", None) + info["keep_compatible"] = getattr(s, "keep_compatible", None) + info["private"] = getattr(s, "private", None) + info["template"] = getattr(s, "template", None) + info["source"] = getattr(s, "source", None) + try: + info["title"] = s.title + except Exception: + info["title"] = None + meta = getattr(s, "metadata", None) + if isinstance(meta, dict): + desc = meta.get("description") + if desc is not None: + info["description"] = desc + info["url"] = getattr(s, "url", None) + try: + info["version"] = s.version + except Exception: + info["version"] = None + info["created_at"] = getattr(s, "created_at", None) + info["updated_at"] = getattr(s, "updated_at", None) + + # Flatten all other metadata keys + if isinstance(meta, dict): + for k, v in meta.items(): + if k in ("title", "description"): + continue + info[f"metadata.{k}"] = v + + label = id_or_title(s) + columns[label] = info + for k in info.keys(): + add_key(k) + + # Preferred key order at top + preferred = [ + "title", + "description", + "scenario_id", + "template", + "area_code", + "start_year", + "end_year", + "keep_compatible", + "private", + "source", + "url", + "version", + "created_at", + "updated_at", + ] + remaining = [k for k in all_keys if k not in preferred] + index_order = preferred + remaining + + df = pd.DataFrame( + {col: {k: columns[col].get(k) for k in index_order} for col in columns} + ) + df.index.name = "scenario" + return df + + def _sanitize_dataframe_for_excel(self, df: pd.DataFrame) -> pd.DataFrame: + """Convert DataFrame values into Excel-safe primitives (str/number/bool/None).""" + import datetime as _dt + + def _safe(v: Any): + if v is None: + return "" + if isinstance(v, (str, int, float, bool)): + return v + # Pandas Timestamp / datetime + if isinstance(v, (pd.Timestamp, _dt.datetime, _dt.date)): + try: + return str(v) + except Exception: + return "" + # Convert everything else to string + try: + return str(v) + except Exception: + return "" + + out = df.copy() + out.index = out.index.map(lambda x: str(x) if x is not None else "") + out.columns = [str(c) if c is not None else "" for c in out.columns] + return out.map(_safe) diff --git a/src/pyetm/models/scenarios.py b/src/pyetm/models/scenarios.py index 94abc60..082b9f7 100644 --- a/src/pyetm/models/scenarios.py +++ b/src/pyetm/models/scenarios.py @@ -1,6 +1,6 @@ from __future__ import annotations from os import PathLike -from typing import Iterable, Iterator, List +from typing import Iterable, Iterator, List, Optional, Sequence from pydantic import BaseModel, Field from .scenario import Scenario @@ -28,21 +28,34 @@ def add(self, *scenarios: Scenario) -> None: def extend(self, scenarios: Iterable[Scenario]) -> None: self.items.extend(list(scenarios)) - def to_excel(self, path: PathLike | str) -> None: + def to_excel( + self, + path: PathLike | str, + *, + export_output_curves: bool = True, + output_curves_path: Optional[str] = None, + carriers: Optional[Sequence[str]] = None, + ) -> None: """ Export all scenarios in this collection to an Excel workbook. + Output curves are written to a separate workbook by default (one sheet per carrier). """ from .scenario_packer import ScenarioPacker packer = ScenarioPacker() if self.items: packer.add(*self.items) - packer.to_excel(str(path)) + packer.to_excel( + str(path), + export_output_curves=export_output_curves, + output_curves_path=output_curves_path, + carriers=carriers, + ) @classmethod def from_excel(cls, xlsx_path: PathLike | str) -> "Scenarios": """ Load or create scenarios from an Excel workbook and wrap them in Scenarios. """ - scenarios = Scenario.load_from_excel(xlsx_path) + scenarios = Scenario.from_excel(xlsx_path) return cls(items=scenarios) diff --git a/src/pyetm/services/scenario_runners/update_metadata.py b/src/pyetm/services/scenario_runners/update_metadata.py index bb1b2b8..0794a26 100644 --- a/src/pyetm/services/scenario_runners/update_metadata.py +++ b/src/pyetm/services/scenario_runners/update_metadata.py @@ -17,20 +17,19 @@ class UpdateMetadataRunner(BaseRunner[Dict[str, Any]]): **kwargs: Additional arguments passed to the request """ - # TODO: Investigate why end_year is not setting correctly META_KEYS = [ "keep_compatible", "private", "source", "metadata", "end_year", + "title", ] UNSETTABLE_META_KEYS = [ "id", "created_at", "updated_at", "area_code", - "title", "start_year", "scaling", "template", diff --git a/src/pyetm/utils/excel.py b/src/pyetm/utils/excel.py index a0d6be5..5e1f86b 100644 --- a/src/pyetm/utils/excel.py +++ b/src/pyetm/utils/excel.py @@ -78,8 +78,12 @@ def create_scenario_formats(workbook: Workbook) -> dict: "grey_header": workbook.add_format( {"bold": True, "bg_color": "#D9D9D9", "border": 1, "align": "center"} ), - "white_data": workbook.add_format({"bg_color": "#FFFFFF", "border": 1}), - "grey_data": workbook.add_format({"bg_color": "#D9D9D9", "border": 1}), + "white_data": workbook.add_format( + {"bg_color": "#FFFFFF", "border": 1, "align": "left"} + ), + "grey_data": workbook.add_format( + {"bg_color": "#D9D9D9", "border": 1, "align": "left"} + ), "bold": workbook.add_format({"bold": True}), "default": None, } @@ -150,10 +154,6 @@ def add_frame( col_offset = frame.index.nlevels if index else 0 row_offset = frame.columns.nlevels - # Adjust row offset if index has names - if index and frame.index.names != [None] * frame.index.nlevels: - row_offset += 1 - # Handle multi-index columns with scenario styling if isinstance(frame.columns, pd.MultiIndex) and scenario_styling: # Get scenario blocks for alternating colors diff --git a/tests/services/scenario_runners/test_update_metadata.py b/tests/services/scenario_runners/test_update_metadata.py index da6a652..10bb5b0 100644 --- a/tests/services/scenario_runners/test_update_metadata.py +++ b/tests/services/scenario_runners/test_update_metadata.py @@ -108,7 +108,7 @@ def test_update_metadata_runner_unsettable_keys_generate_warnings(): metadata = { "id": 456, # Unsettable - "title": "New Title", # Unsettable + "title": "New Title", # Settable "end_year": 2050, # Settable } @@ -121,7 +121,8 @@ def test_update_metadata_runner_unsettable_keys_generate_warnings(): expected_payload = { "scenario": { "end_year": 2050, - "metadata": {"existing": "value", "id": 456, "title": "New Title"}, + "title": "New Title", + "metadata": {"existing": "value", "id": 456}, } } mock_request.assert_called_once_with( @@ -293,6 +294,7 @@ def test_update_metadata_runner_meta_keys_constants(): "source", "metadata", "end_year", + "title", ] expected_unsettable_keys = [ @@ -300,7 +302,6 @@ def test_update_metadata_runner_meta_keys_constants(): "created_at", "updated_at", "area_code", - "title", "start_year", "scaling", "template", From 3e94434ed93e5f305d8f4f0fd957f98ef13454cb Mon Sep 17 00:00:00 2001 From: louispt1 <81332401+louispt1@users.noreply.github.com> Date: Wed, 13 Aug 2025 15:44:31 +0200 Subject: [PATCH 11/19] Updating how title is handled in meta * Updating how you handle title in meta --- examples/create_or_query_scenarios.ipynb | 5 +++-- src/pyetm/models/scenario.py | 18 +++++------------- .../scenario_runners/create_scenario.py | 1 + .../scenario_runners/update_metadata.py | 9 +++++++++ 4 files changed, 18 insertions(+), 15 deletions(-) diff --git a/examples/create_or_query_scenarios.ipynb b/examples/create_or_query_scenarios.ipynb index a661cee..7da8767 100644 --- a/examples/create_or_query_scenarios.ipynb +++ b/examples/create_or_query_scenarios.ipynb @@ -44,7 +44,8 @@ "from pyetm.models.scenarios import Scenarios\n", "\n", "scenarios = Scenarios.from_excel(\"example_input_excel.xlsx\")\n", - "#scenario_a = Scenario.load(123456789) #TODO: Also load a scenario" + "#scenario_a = Scenario.load(123456789) #TODO: Also load a scenario and include it in the array" + ] }, { @@ -155,7 +156,7 @@ ], "metadata": { "kernelspec": { - "display_name": "pyetm-qKH2ozgc", + "display_name": "pyetm-Rh4Np-o3-py3.12", "language": "python", "name": "python3" }, diff --git a/src/pyetm/models/scenario.py b/src/pyetm/models/scenario.py index c87e6e4..071b63f 100644 --- a/src/pyetm/models/scenario.py +++ b/src/pyetm/models/scenario.py @@ -46,6 +46,7 @@ class Scenario(Base): private: Optional[bool] = None area_code: str = Field(..., description="Area code") source: Optional[str] = None + title: Optional[str] = None metadata: Optional[Dict[str, Any]] = None start_year: Optional[int] = None scaling: Optional[Any] = None @@ -169,6 +170,10 @@ def update_metadata(self, **kwargs) -> Dict[str, Any]: if hasattr(self, field): setattr(self, field, value) + for field, value in kwargs.items(): + if hasattr(self, field) and field not in scenario_data: + setattr(self, field, value) + return result.data def __eq__(self, other: "Scenario"): @@ -184,19 +189,6 @@ def _to_dataframe(self, **kwargs) -> pd.DataFrame: columns=[self.id], ) - @property - def title(self): - if not self.metadata is None: - return self.metadata.get("title", None) - return None - - @title.setter - def title(self, title: str): - if not self.metadata is None: - self.metadata["title"] = title - else: - self.metadata = {"title": title} - def identifier(self): if self.title: return self.title diff --git a/src/pyetm/services/scenario_runners/create_scenario.py b/src/pyetm/services/scenario_runners/create_scenario.py index 1696539..98d6606 100644 --- a/src/pyetm/services/scenario_runners/create_scenario.py +++ b/src/pyetm/services/scenario_runners/create_scenario.py @@ -27,6 +27,7 @@ class CreateScenarioRunner(BaseRunner[Dict[str, Any]]): "keep_compatible", "private", "source", + "title", "metadata", "start_year", "scaling", diff --git a/src/pyetm/services/scenario_runners/update_metadata.py b/src/pyetm/services/scenario_runners/update_metadata.py index 0794a26..4bbbc87 100644 --- a/src/pyetm/services/scenario_runners/update_metadata.py +++ b/src/pyetm/services/scenario_runners/update_metadata.py @@ -77,6 +77,15 @@ def run( if hasattr(scenario, "metadata") and isinstance(scenario.metadata, dict): existing_metadata = scenario.metadata.copy() + legacy_title = None + if isinstance(existing_metadata, dict): + legacy_title = existing_metadata.pop("title", None) + if "metadata" in direct_fields and isinstance(direct_fields["metadata"], dict): + direct_fields["metadata"].pop("title", None) + nested_metadata.pop("title", None) + if legacy_title is not None and "title" not in direct_fields: + direct_fields["title"] = legacy_title + final_metadata = existing_metadata.copy() if nested_metadata: final_metadata.update(nested_metadata) From 0cab81a21e39a46abe36539252e61f7741e22216 Mon Sep 17 00:00:00 2001 From: louispt1 <81332401+louispt1@users.noreply.github.com> Date: Fri, 15 Aug 2025 11:24:47 +0200 Subject: [PATCH 12/19] Handle new input structure * Clearing notebooks, updating poetry and handling setting environment not base url * Update readme and input excel * Tidying output format in Jupyter Notebooks * PARAMETERS to SLIDER_SETTINGS * Min max once at the start of slider_settings * Fix metadata output and refine scenario to_dataframe * Fix custom curve handling and avoid double caching issue --- .DS_Store | Bin 8196 -> 8196 bytes README.md | 10 +- examples/create_or_query_scenarios.ipynb | 29 +- examples/example_helpers.py | 78 +- examples/example_input_excel.xlsx | Bin 1370069 -> 1377026 bytes pyproject.toml | 2 +- pytest.ini | 1 + src/pyetm/models/base.py | 25 +- src/pyetm/models/custom_curves.py | 50 +- src/pyetm/models/export_config.py | 25 + src/pyetm/models/packables/inputs_pack.py | 230 ++++-- .../models/packables/output_curves_pack.py | 11 + src/pyetm/models/packables/query_pack.py | 26 +- src/pyetm/models/scenario.py | 91 ++- src/pyetm/models/scenario_packer.py | 679 ++++++++++++------ src/pyetm/models/scenarios.py | 18 +- .../scenario_runners/update_custom_curves.py | 3 +- tests/models/packables/test_inputs_pack.py | 2 +- tests/models/test_scenario_packer.py | 22 +- 19 files changed, 967 insertions(+), 335 deletions(-) create mode 100644 src/pyetm/models/export_config.py diff --git a/.DS_Store b/.DS_Store index b3afbf130ae27a0d94931b35e5798dd9920f4b2b..a9bcd6a1cbe0d1fe4c65c58cb7baf8450e8016f2 100644 GIT binary patch literal 8196 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 diff --git a/README.md b/README.md index b0a1ca4..b88d4b1 100644 --- a/README.md +++ b/README.md @@ -68,7 +68,6 @@ poetry --version Navigate to the `pyetm` folder and install all dependencies: ```bash -cd pyetm poetry install ``` @@ -79,7 +78,7 @@ If you want development dependencies (testing, linting, etc.) then append the "--with dev" flag to the install command. -#### Activating the Environment +#### How to use the environment: You can either: - Run commands inside Poetry’s environment: ```bash @@ -90,10 +89,9 @@ You can either: ```bash eval $(poetry env activate) ``` - Then run commands normally: + Then run you can commands normally (e.g.): ```bash pytest - pyetm ``` @@ -127,7 +125,7 @@ BASE_URL= --- -## Cross-Platform Notes +### Notes - **Windows**: - Use `py` instead of `python3` if `python3` is not recognized. - In PowerShell, set environment variables with: @@ -139,5 +137,5 @@ BASE_URL= - Set environment variables with: ```bash export ETM_API_TOKEN="your-token" - export ENVIRONMENT=beta # or pro/local/2025-01 + export ENVIRONMENT=beta ``` diff --git a/examples/create_or_query_scenarios.ipynb b/examples/create_or_query_scenarios.ipynb index 7da8767..57aa529 100644 --- a/examples/create_or_query_scenarios.ipynb +++ b/examples/create_or_query_scenarios.ipynb @@ -27,11 +27,11 @@ "id": "2884d014", "metadata": {}, "source": [ - "For the purposes of this demonstration workbook, we will use the pre-filled template 'my_input_excel.xlsx' which demonstrated a few of the possibilities afforded by the pyetm package. If it's your first time using the tool, have a look at the excel to get a sense of the structure.\n", + "For the purposes of this demonstration workbook, we will use the pre-filled template 'my_input_excel.xlsx' which demonstrates a few of the possibilities afforded by the pyetm package. If it's your first time using the tool, have a look at the excel to get a sense of the structure.\n", "\n", - "In the example, there are two scenarios, with short names scen_a and scen_b. You can use short names in the parameters sheet to specify which inputs belong to which scenario. Because scen_a has no scenario_id, it is being created. It will be created with all the metadata included in the sheet, plus any of the inputs under the column with its short_name and any sortables and curves specified in the sheets named beside the sortables and custom_curves rows. The same goes for scen_b, but because it has a scenario_id (2690555) that scenario will be loaded, and then updated with anything as set in the excel.\n", + "In the example, there are two scenarios, with short names scen_a and scen_b. You can use short names in the slider_settings sheet to specify which inputs belong to which scenario. Because scen_b has no scenario_id, it is being created. It will be created with all the metadata included in the sheet, plus any of the inputs under the column with its short_name and any sortables and curves specified in the sheets named beside the sortables and custom_curves rows. The same goes for scen_a, but because it has a scenario_id (1357395) that scenario will be loaded, and then updated with anything as set in the excel.\n", "\n", - "**TODO**: Figure out how to manage the fact that for this example whatever scenario 2690555 is will be constantly updated etc by everyone who wants to try running this script on pro/beta. At the moment its just a local scenario." + "**TODO**: Figure out how to manage the fact that for this example whatever scenario 1357395 is will be constantly updated etc by everyone who wants to try running this script on pro/beta. At the moment its just a local scenario." ] }, { @@ -45,7 +45,6 @@ "\n", "scenarios = Scenarios.from_excel(\"example_input_excel.xlsx\")\n", "#scenario_a = Scenario.load(123456789) #TODO: Also load a scenario and include it in the array" - ] }, { @@ -99,7 +98,7 @@ "source": [ "# Sortables\n", "for scenario in scenarios:\n", - " sortables = scenario.sortables.to_dataframe().head(20)\n", + " sortables = scenario.sortables.to_dataframe()\n", " print(sortables)\n", " print(\"\")" ] @@ -131,12 +130,25 @@ " print(\"\")" ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "9a63a0a6", + "metadata": {}, + "outputs": [], + "source": [ + "# Warnings - did anything go wrong?\n", + "for scenario in scenarios:\n", + " print(scenario.show_all_warnings())\n", + " print()" + ] + }, { "cell_type": "markdown", "id": "86643b22", "metadata": {}, "source": [ - "We can directly modify any of the attributes using Pandas, or we can re-export the scenarios to excel and make modifications that way. When exporting to excel, more data will be available than was in the input, because the ETM results will be included by default. The 'output curves' will be stored in a separate excel workbook, separated by carrier type. By default everything is included, but you can also specify what you want." + "We can directly modify any of the attributes using Pandas, or we can re-export the scenarios to excel and make modifications that way. When exporting to excel, more data will be available than was in the input, because the ETM results will be included by default. The 'output curves' or 'exports' will be stored in a separate excel workbook, separated by carrier type. By default everything is included, but you can also specify what you want." ] }, { @@ -147,10 +159,7 @@ "outputs": [], "source": [ "# Export the scenarios to excel\n", - "scenarios.to_excel(\"export.xlsx\") # This will create export.xlsx and export_output_curves.xlsx.\n", - "\n", - "# There are also options - decide whether to include the output_curves, specify where you want them and specify which carriers you're interested in.\n", - "scenarios.to_excel((\"export_with_options.xlsx\"), export_output_curves=True, output_curves_path=\"output_curves.xlsx\", carriers=[\"electricity\", \"heat\", \"hydrogen\"])" + "scenarios.to_excel(\"scenarios.xlsx\") # This will create scenarios.xlsx and scenarios_exports.xlsx (if you've set exports to true in the output config)." ] } ], diff --git a/examples/example_helpers.py b/examples/example_helpers.py index af9c768..edd84eb 100644 --- a/examples/example_helpers.py +++ b/examples/example_helpers.py @@ -3,11 +3,12 @@ def setup_notebook(): import sys + import builtins from pyetm.config.settings import get_settings from IPython import get_ipython + from IPython.display import display, HTML - # Hide the trackback for now - + # Hide the traceback for a cleaner demo experience ipython = get_ipython() def hide_traceback( @@ -24,6 +25,79 @@ def hide_traceback( ipython.showtraceback = hide_traceback + try: + import pandas as pd + + pd.set_option("display.max_rows", 60) + pd.set_option("display.max_columns", None) + pd.set_option("display.width", None) + pd.set_option("display.max_colwidth", None) + pd.options.display.float_format = "{:,.3f}".format + + try: + pd.options.styler.render.max_elements = 200000 + except Exception: + pass + + def show(obj, *, index=False): + """Pretty-display DataFrames/Series (HTML) or fall back to normal display.""" + + if isinstance(obj, (pd.DataFrame, pd.Series)): + try: + if getattr(obj, "empty", False): + from html import escape + + if isinstance(obj, pd.DataFrame): + cols = [str(c) for c in obj.columns] + preview = ", ".join(cols[:8]) + ( + "…" if len(cols) > 8 else "" + ) + meta = f" — 0 rows, {obj.shape[1]} columns" + extra = f" (columns: {escape(preview)})" if cols else "" + msg = f"Empty DataFrame{meta}{extra}" + else: + msg = "Empty Series — 0 rows" + display( + HTML( + "
" + + escape(msg) + + "
" + ) + ) + return + + styler = obj.style + styler = styler.format(precision=3) + if not index and isinstance(obj, pd.DataFrame): + try: + styler = styler.hide(axis="index") + except Exception: + pass + display(styler) + except Exception: + display(obj) + else: + display(obj) + + # Make 'show' available in the notebook namespace + ipython.user_ns.setdefault("show", show) + _orig_print = builtins.print + + def _smart_print(*args, **kwargs): + if ( + len(args) == 1 + and not kwargs + and isinstance(args[0], (pd.DataFrame, pd.Series)) + ): + show(args[0]) + else: + _orig_print(*args, **kwargs) + + builtins.print = _smart_print + + except Exception: + pass + print("Environment setup complete") # Check if our API is ready! diff --git a/examples/example_input_excel.xlsx b/examples/example_input_excel.xlsx index 72484746cb6a0c61a35334e07f63352aef97e9f8..a1bbb3f5c641df92ee0f8b6e4393bd478701839c 100644 GIT binary patch delta 143156 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 _YO#m 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 delta 136252 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

dJ+El&3#& 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 None: """Print all warnings to the console.""" self._warning_collector.show_warnings() + def log_warnings( + self, logger, level: str = "warning", prefix: str | None = None + ) -> None: + """ + Log all collected warnings using the provided logger. + """ + try: + collector = getattr(self, "warnings", None) + if collector is None or len(collector) == 0: + return + log_fn = getattr(logger, level, getattr(logger, "warning", None)) + if log_fn is None: + return + for w in collector: + field = getattr(w, "field", "") + msg = getattr(w, "message", str(w)) + if prefix: + log_fn(f"{prefix} [{field}]: {msg}") + else: + log_fn(f"[{field}]: {msg}") + except Exception: + pass + def _clear_warnings_for_attr(self, field: str) -> None: """Remove warnings for a specific field.""" self._warning_collector.clear(field) @@ -145,7 +168,7 @@ def _get_serializable_fields(self) -> List[str]: """ return [ field_name - for field_name in self.model_fields.keys() + for field_name in self.__class__.model_fields.keys() if not field_name.startswith("_") ] diff --git a/src/pyetm/models/custom_curves.py b/src/pyetm/models/custom_curves.py index 6e59e65..da5a6ca 100644 --- a/src/pyetm/models/custom_curves.py +++ b/src/pyetm/models/custom_curves.py @@ -1,10 +1,11 @@ from __future__ import annotations import pandas as pd from pathlib import Path -from typing import Optional +from typing import Optional, Any from pyetm.models.warnings import WarningCollector from pyetm.clients import BaseClient from pyetm.models.base import Base +from pydantic import PrivateAttr from pyetm.services.scenario_runners.fetch_custom_curves import ( DownloadCustomCurveRunner, ) @@ -30,7 +31,7 @@ class CustomCurve(Base): def available(self) -> bool: return bool(self.file_path) - def retrieve(self, client, scenario) -> Optional[pd.DataFrame]: + def retrieve(self, client, scenario) -> Optional[pd.Series]: """Process curve from client, save to file, set file_path""" file_path = ( get_settings().path_to_tmp(str(scenario.id)) @@ -54,9 +55,14 @@ def retrieve(self, client, scenario) -> Optional[pd.DataFrame]: .squeeze("columns") .dropna(how="all") ) + if len(curve) != 8760: + self.add_warning( + self.key, + f"Curve length should be 8760, got {len(curve)}; proceeding with current data", + ) self.file_path = file_path - curve.to_csv(self.file_path, index=False) + curve.to_csv(self.file_path, index=False, header=False) return curve.rename(self.key) except Exception as e: # File processing error - add warning and return None @@ -80,12 +86,17 @@ def contents(self) -> Optional[pd.Series]: return None try: - return ( + series = ( pd.read_csv(self.file_path, header=None, index_col=False, dtype=float) .squeeze("columns") .dropna(how="all") - .rename(self.key) ) + if len(series) != 8760: + self.add_warning( + self.key, + f"Curve length should be 8760, got {len(series)}; using available data", + ) + return series.rename(self.key) except Exception as e: self.add_warning(self.key, f"Failed to read curve file: {e}") return None @@ -112,7 +123,6 @@ def from_json(cls, data: dict) -> CustomCurve: curve = cls.model_validate(data) return curve except Exception as e: - # Create basic curve with warning attached basic_data = { "key": data.get("key", "unknown"), "type": data.get("type", "unknown"), @@ -130,14 +140,8 @@ def _to_dataframe(self, **kwargs) -> pd.DataFrame: if curve_data is None or curve_data.empty: # Return empty DataFrame with proper structure return pd.DataFrame({self.key: pd.Series(dtype=float)}) - - # Create DataFrame with curve key as column name df = pd.DataFrame({self.key: curve_data.values}) - - # TODO: Do we want the hour index? - # Set index to represent hours (0-8759 for a full year) df.index.name = "hour" - return df @classmethod @@ -163,10 +167,8 @@ def _from_dataframe( curve_data = df.iloc[:, 0].dropna() if not curve_data.empty: safe_key = str(curve_key).replace("/", "-") - prefix = f"{scenario_id}_" if scenario_id is not None else "" file_path = ( - get_settings().path_to_tmp("dataframe_import") - / f"{prefix}{safe_key}.csv" + get_settings().path_to_tmp(str(scenario_id)) / f"{safe_key}.csv" ) file_path.parent.mkdir(parents=True, exist_ok=True) try: @@ -181,6 +183,7 @@ def _from_dataframe( class CustomCurves(Base): curves: list[CustomCurve] + _scenario: Any = PrivateAttr(default=None) def __len__(self) -> int: return len(self.curves) @@ -237,10 +240,7 @@ def from_json(cls, data: list[dict]) -> CustomCurves: curves.append(basic_curve) collection = cls.model_validate({"curves": curves}) - - # Merge warnings from individual curves collection._merge_submodel_warnings(*curves, key_attr="key") - return collection def _to_dataframe(self, **kwargs) -> pd.DataFrame: @@ -254,6 +254,14 @@ def _to_dataframe(self, **kwargs) -> pd.DataFrame: for curve in self.curves: try: + if ( + not curve.available() + and getattr(self, "_scenario", None) is not None + ): + try: + curve.retrieve(BaseClient(), self._scenario) + except Exception: + pass curve_df = curve._to_dataframe(**kwargs) if not curve_df.empty: # Get the curve data as a Series @@ -320,9 +328,7 @@ def validate_for_upload(self) -> dict[str, WarningCollector]: validation_errors[curve.key] = curve_warnings continue - # Get curve data and validate try: - # First, try to read the file without forcing dtype to check for non-numeric values try: # Read without dtype conversion to preserve non-numeric values raw_data = pd.read_csv( @@ -340,7 +346,6 @@ def validate_for_upload(self) -> dict[str, WarningCollector]: f"Curve must contain exactly 8,760 values, found {len(raw_data)}", ) else: - # Now check if all values can be converted to float try: # Try to convert to numeric, this will raise if there are non-numeric values pd.to_numeric(raw_data.iloc[:, 0], errors="raise") @@ -352,14 +357,11 @@ def validate_for_upload(self) -> dict[str, WarningCollector]: except pd.errors.EmptyDataError: curve_warnings.add(curve.key, "Curve contains no data") except Exception as e: - # This catches file not found, permission errors, etc. curve_warnings.add(curve.key, f"Error reading curve data: {str(e)}") except Exception as e: - # Catch any other unexpected errors curve_warnings.add(curve.key, f"Error reading curve data: {str(e)}") - # Only add to validation_errors if there are actual warnings if len(curve_warnings) > 0: validation_errors[curve.key] = curve_warnings diff --git a/src/pyetm/models/export_config.py b/src/pyetm/models/export_config.py new file mode 100644 index 0000000..a531a44 --- /dev/null +++ b/src/pyetm/models/export_config.py @@ -0,0 +1,25 @@ +from __future__ import annotations + +from typing import Optional, Sequence +from pydantic import BaseModel + + +class ExportConfig(BaseModel): + """ + Per-scenario export configuration. + + If a value is None, the exporter will use its default/global behavior. + """ + + include_inputs: Optional[bool] = None + include_sortables: Optional[bool] = None + include_custom_curves: Optional[bool] = None + include_gqueries: Optional[bool] = None + inputs_defaults: Optional[bool] = None + inputs_min_max: Optional[bool] = None + + # Select which output carriers to include; None means don't include carriers + output_carriers: Optional[Sequence[str]] = None + + def effective_bool(self, value: Optional[bool], default: bool) -> bool: + return default if value is None else bool(value) diff --git a/src/pyetm/models/packables/inputs_pack.py b/src/pyetm/models/packables/inputs_pack.py index 5680174..0db08ee 100644 --- a/src/pyetm/models/packables/inputs_pack.py +++ b/src/pyetm/models/packables/inputs_pack.py @@ -8,7 +8,7 @@ class InputsPack(Packable): key: ClassVar[str] = "inputs" - sheet_name: ClassVar[str] = "PARAMETERS" + sheet_name: ClassVar[str] = "SLIDER_SETTINGS" def __init__(self, **data): super().__init__(**data) @@ -54,54 +54,81 @@ def resolve_scenario(self, label: Any): pass return None - def _to_dataframe(self, columns: str = "user", **kwargs): - if not self.scenarios: - return pd.DataFrame() + def _extract_map(self, scen, attr: str) -> dict[str, Any] | None: + """Extract a mapping of input key -> attribute value for a scenario's inputs.""" + iter_attr_primary = attr + iter_attr_fallback = None + if attr == "min_max": + iter_attr_primary = "min" + iter_attr_fallback = "max" - def extract_user_map_from_inputs_obj(scen) -> dict[str, Any] | None: - try: - it = iter(scen.inputs) - values = {} - for inp in it: - key = getattr(inp, "key", None) - if key is None: - continue - values[str(key)] = getattr(inp, "user", None) - if values: - return values - except Exception: - pass + # 1) Try iterating input objects first + try: + values: dict[str, Any] = {} + for inp in scen.inputs: + key = getattr(inp, "key", None) + if key is None: + continue + val = getattr(inp, iter_attr_primary, None) + if val is None and iter_attr_fallback is not None: + val = getattr(inp, iter_attr_fallback, None) + values[str(key)] = val if attr != "min_max" else val + if values: + return values + except Exception: + pass - try: - df = scen.inputs.to_dataframe(columns="user") - except Exception: - df = None - if df is None or getattr(df, "empty", False): - return None - - if isinstance(df.index, pd.MultiIndex) and "unit" in (df.index.names or []): - df = df.copy() - df.index = df.index.droplevel("unit") - if isinstance(df, pd.Series): - series = df + # 2) Fallback to DataFrame/Series + try: + df = ( + scen.inputs.to_dataframe(columns=["min", "max"]) + if attr == "min_max" + else scen.inputs.to_dataframe(columns=attr) + ) + except Exception: + df = None + + if df is None or getattr(df, "empty", False): + return None + + # Normalize index (drop 'unit' if present) + if isinstance(df.index, pd.MultiIndex) and "unit" in (df.index.names or []): + df = df.copy() + df.index = df.index.droplevel("unit") + + if isinstance(df, pd.Series): + series = df + else: + cols_lc = {str(c).lower(): c for c in df.columns} + if attr == "min_max": + if "min" in cols_lc: + series = df[cols_lc["min"]] + elif "max" in cols_lc: + series = df[cols_lc["max"]] + else: + series = df.iloc[:, 0] else: - cols_lc = [str(c).lower() for c in df.columns] - chosen = None - for candidate in ("user", "value"): + for candidate in (attr, "user", "value", "default"): if candidate in cols_lc: - chosen = df.columns[cols_lc.index(candidate)] + series = df[cols_lc[candidate]] break - if chosen is None: - chosen = df.columns[0] - series = df[chosen] - series.index = series.index.map(lambda k: str(k)) - return series.to_dict() + else: + series = df.iloc[:, 0] + + series.index = series.index.map(str) + return series.to_dict() + + def _to_dataframe(self, columns: str = "user", **kwargs): + if not self.scenarios: + return pd.DataFrame() + if not isinstance(columns, str) or columns.strip() == "": + columns = "user" all_keys: set[str] = set() per_label_values: dict[Any, dict[str, Any]] = {} for scen in self.scenarios: label = self._key_for(scen) - user_map = extract_user_map_from_inputs_obj(scen) + user_map = self._extract_map(scen, columns) if not user_map: continue per_label_values[label] = user_map @@ -119,6 +146,114 @@ def extract_user_map_from_inputs_obj(scen) -> dict[str, Any] | None: df.index.name = "input" return df + def to_dataframe_per_scenario_fields( + self, fields_map: Dict["Any", list[str]] + ) -> pd.DataFrame: + """Build a DataFrame where each scenario may have different fields (e.g. ['user'], ['user','default'], ['user','min','max']).""" + if not self.scenarios: + return pd.DataFrame() + + scen_set = {s for s in self.scenarios if s in fields_map} + if not scen_set: + return pd.DataFrame() + + all_keys: set[str] = set() + for s in scen_set: + fields = fields_map.get(s, ["user"]) or ["user"] + for f in fields: + m = self._extract_map(s, f) + if m: + all_keys.update(m.keys()) + + if not all_keys: + return pd.DataFrame() + sorted_keys = sorted(all_keys) + + frames: list[pd.DataFrame] = [] + keys: list[Any] = [] + for s in scen_set: + label = self._key_for(s) + fields = fields_map.get(s, ["user"]) or ["user"] + data: dict[str, list[Any]] = {} + for f in fields: + m = self._extract_map(s, f) or {} + data[f] = [m.get(k) for k in sorted_keys] + if not data: + continue + df_s = pd.DataFrame(data, index=sorted_keys) + df_s.index.name = "input" + frames.append(df_s) + keys.append(label) + + if not frames: + return pd.DataFrame() + + return pd.concat(frames, axis=1, keys=keys, names=["scenario", "field"]) + + def to_dataframe_defaults(self) -> pd.DataFrame: + """Build a DataFrame of default values for each input per scenario.""" + if not self.scenarios: + return pd.DataFrame() + + return self._to_dataframe(columns="default") + + def to_dataframe_min_max(self) -> pd.DataFrame: + """Build a DataFrame with min/max once (shared across scenarios). + + Assumes bounds (min/max) are identical across scenarios. If conflicts are + found, the first-seen value is used and no exception is raised. + """ + if not self.scenarios: + return pd.DataFrame() + + # Collect union of keys across scenarios + all_keys: set[str] = set() + for scen in self.scenarios: + try: + it = iter(scen.inputs) + keys = [str(getattr(inp, "key", "")) for inp in it] + except Exception: + try: + df = scen.inputs.to_dataframe(columns=["min", "max"]) + # Drop 'unit' level if present + if isinstance(df.index, pd.MultiIndex) and "unit" in ( + df.index.names or [] + ): + df = df.copy() + df.index = df.index.droplevel("unit") + keys = [str(i) for i in df.index.unique()] + except Exception: + keys = [] + all_keys.update([k for k in keys if k]) + + if not all_keys: + return pd.DataFrame() + + sorted_keys = sorted(all_keys) + + # Choose bounds from the first scenario that provides them; ignore conflicts + min_vals: dict[str, Any] = {} + max_vals: dict[str, Any] = {} + for scen in self.scenarios: + m_min = self._extract_map(scen, "min") or {} + m_max = self._extract_map(scen, "max") or {} + for k in sorted_keys: + if k not in min_vals and k in m_min: + min_vals[k] = m_min.get(k) + if k not in max_vals and k in m_max: + max_vals[k] = m_max.get(k) + if len(min_vals) == len(sorted_keys) and len(max_vals) == len(sorted_keys): + break + + data = { + ("", "min"): [min_vals.get(k) for k in sorted_keys], + ("", "max"): [max_vals.get(k) for k in sorted_keys], + } + df = pd.DataFrame(data, index=sorted_keys) + df.index.name = "input" + df.columns = pd.MultiIndex.from_tuples(df.columns, names=["scenario", "field"]) + return df + def from_dataframe(self, df): if df is None or getattr(df, "empty", False): return @@ -146,7 +281,8 @@ def from_dataframe(self, df): scenario = self.resolve_scenario(col) if scenario is None: logger.warning( - "Could not find scenario for PARAMETERS column label '%s'", col + "Could not find scenario for SLIDER_SETTINGS column label '%s'", + col, ) continue series = data[col] @@ -172,5 +308,17 @@ def _is_blank_val(v: Any) -> bool: col, e, ) + finally: + try: + if ( + hasattr(scenario, "_inputs") + and scenario._inputs is not None + ): + scenario._inputs.log_warnings( + logger, + prefix=f"Inputs warning for '{scenario.identifier()}'", + ) + except Exception: + pass except Exception as e: - logger.warning("Failed to parse simplified PARAMETERS sheet: %s", e) + logger.warning("Failed to parse simplified SLIDER_SETTINGS sheet: %s", e) diff --git a/src/pyetm/models/packables/output_curves_pack.py b/src/pyetm/models/packables/output_curves_pack.py index 58b0a60..7aaf950 100644 --- a/src/pyetm/models/packables/output_curves_pack.py +++ b/src/pyetm/models/packables/output_curves_pack.py @@ -16,6 +16,17 @@ class OutputCurvesPack(Packable): def _build_dataframe_for_scenario(self, scenario: Any, columns: str = "", **kwargs): try: series_list = list(scenario.all_output_curves()) + try: + if ( + hasattr(scenario, "_output_curves") + and scenario._output_curves is not None + ): + scenario._output_curves.log_warnings( + logger, + prefix=f"Output curves warning for '{scenario.identifier()}'", + ) + except Exception: + pass except Exception as e: logger.warning( "Failed extracting output curves for %s: %s", scenario.identifier(), e diff --git a/src/pyetm/models/packables/query_pack.py b/src/pyetm/models/packables/query_pack.py index 608e6eb..b7a0094 100644 --- a/src/pyetm/models/packables/query_pack.py +++ b/src/pyetm/models/packables/query_pack.py @@ -17,7 +17,16 @@ def _build_dataframe_for_scenario( self, scenario: Any, columns: str = "future", **kwargs ): try: - return scenario.results(columns=columns) + df = scenario.results(columns=columns) + try: + if hasattr(scenario, "_queries") and scenario._queries is not None: + scenario._queries.log_warnings( + logger, + prefix=f"Queries warning for '{scenario.identifier()}'", + ) + except Exception: + pass + return df except Exception as e: logger.warning( "Failed building gquery results for %s: %s", scenario.identifier(), e @@ -38,4 +47,17 @@ def from_dataframe(self, df: pd.DataFrame): # Apply unique queries to all scenarios if unique_queries: for scenario in self.scenarios: - scenario.add_queries(unique_queries) + try: + scenario.add_queries(unique_queries) + finally: + try: + if ( + hasattr(scenario, "_queries") + and scenario._queries is not None + ): + scenario._queries.log_warnings( + logger, + prefix=f"Queries warning for '{scenario.identifier()}'", + ) + except Exception: + pass diff --git a/src/pyetm/models/scenario.py b/src/pyetm/models/scenario.py index 071b63f..a4621fb 100644 --- a/src/pyetm/models/scenario.py +++ b/src/pyetm/models/scenario.py @@ -12,6 +12,7 @@ from pyetm.models.custom_curves import CustomCurves from pyetm.models.gqueries import Gqueries from pyetm.models.sortables import Sortables +from pyetm.models.export_config import ExportConfig from pyetm.services.scenario_runners.fetch_inputs import FetchInputsRunner from pyetm.services.scenario_runners.fetch_metadata import FetchMetadataRunner from pyetm.services.scenario_runners.fetch_sortables import FetchSortablesRunner @@ -59,6 +60,7 @@ class Scenario(Base): _custom_curves: Optional[CustomCurves] = PrivateAttr(default=None) _output_curves: Optional[OutputCurves] = PrivateAttr(default=None) _queries: Optional[Gqueries] = PrivateAttr(None) + _export_config: Optional[ExportConfig] = PrivateAttr(default=None) @classmethod def new(cls, area_code: str, end_year: int, **kwargs) -> "Scenario": @@ -116,38 +118,28 @@ def to_excel( self, path: PathLike | str, *others: "Scenario", - export_output_curves: bool = True, - output_curves_path: str | None = None, carriers: list[str] | None = None, + include_inputs: bool | None = None, + include_sortables: bool | None = None, + include_custom_curves: bool | None = None, + include_gqueries: bool | None = None, + include_output_curves: bool | None = None, ) -> None: """ Export this scenario – and optionally additional scenarios – to an Excel file. - Output curves are exported to a separate workbook by default, with one sheet - per carrier. Use carriers to filter which carriers to include. + Output curves are exported to a separate workbook only when enabled, with one + sheet per carrier. Use carriers to filter which carriers to include when exporting. """ from pyetm.models.scenarios import Scenarios Scenarios(items=[self, *others]).to_excel( path, - export_output_curves=export_output_curves, - output_curves_path=output_curves_path, - carriers=carriers, - ) - - # Deprecated helper retained for backwards compatibility: route to main to_excel - def to_output_curves_excel( - self, - path: PathLike | str, - *others: "Scenario", - carriers: list[str] | None = None, - ) -> None: - from pyetm.models.scenarios import Scenarios - - Scenarios(items=[self, *others]).to_excel( - path, - export_output_curves=True, - output_curves_path=str(path), carriers=carriers, + include_inputs=include_inputs, + include_sortables=include_sortables, + include_custom_curves=include_custom_curves, + include_gqueries=include_gqueries, + include_output_curves=include_output_curves, ) def update_metadata(self, **kwargs) -> Dict[str, Any]: @@ -183,11 +175,42 @@ def __hash__(self): return hash((self.id, self.area_code, self.end_year)) def _to_dataframe(self, **kwargs) -> pd.DataFrame: - return pd.DataFrame.from_dict( - self.model_dump(include={"end_year", "area_code", "private", "template"}), - orient="index", - columns=[self.id], - ) + """ + Return a single-column DataFrame describing this scenario + - Column name is the scenario_id for concatenation. + """ + info: Dict[str, Any] = { + "title": self.title, + "scenario_id": self.id, + "template": self.template, + "area_code": self.area_code, + "start_year": self.start_year, + "end_year": self.end_year, + "keep_compatible": self.keep_compatible, + "private": self.private, + "source": self.source, + "url": self.url, + "version": self.version, + "created_at": self.created_at, + "updated_at": self.updated_at, + } + + # Description from metadata (if present) + meta = self.metadata if isinstance(self.metadata, dict) else None + if meta is not None: + desc = meta.get("description") + if desc is not None: + info["description"] = desc + + # Flatten remaining metadata keys + if meta is not None: + for k, v in meta.items(): + if k == "description": + continue + if k not in info: + info[k] = v + + return pd.DataFrame.from_dict(info, orient="index", columns=[self.id]) def identifier(self): if self.title: @@ -384,6 +407,10 @@ def custom_curves(self) -> CustomCurves: raise ScenarioError(f"Could not retrieve custom_curves: {result.errors}") coll = CustomCurves.from_json(result.data) + try: + coll._scenario = self + except Exception: + pass for w in result.errors: self.add_warning("custom_curves", w) self._merge_submodel_warnings(coll, key_attr="custom_curves") @@ -429,6 +456,10 @@ def update_custom_curves(self, custom_curves) -> None: existing_curve.file_path = new_curve.file_path else: self.custom_curves.curves.append(new_curve) + try: + self.custom_curves._scenario = self + except Exception: + pass @property def output_curves(self) -> OutputCurves: @@ -449,6 +480,12 @@ def all_output_curves(self): def get_output_curves(self, carrier_type: str) -> dict[str, pd.DataFrame]: return self.output_curves.get_curves_by_carrier_type(self, carrier_type) + def set_export_config(self, config: ExportConfig | None) -> None: + self._export_config = config + + def get_export_config(self) -> ExportConfig | None: + return self._export_config + def add_queries(self, gquery_keys: list[str]): if self._queries is None: self._queries = Gqueries.from_list(gquery_keys) diff --git a/src/pyetm/models/scenario_packer.py b/src/pyetm/models/scenario_packer.py index eef48c1..8480cca 100644 --- a/src/pyetm/models/scenario_packer.py +++ b/src/pyetm/models/scenario_packer.py @@ -12,6 +12,7 @@ from pyetm.models.packables.query_pack import QueryPack from pyetm.models.packables.sortable_pack import SortablePack from pyetm.models import Scenario +from pyetm.models.export_config import ExportConfig from pyetm.models.custom_curves import CustomCurves from pyetm.utils.excel import add_frame @@ -83,9 +84,12 @@ def to_excel( self, path: str, *, - export_output_curves: bool = True, - output_curves_path: Optional[str] = None, carriers: Optional[Sequence[str]] = None, + include_inputs: bool | None = None, + include_sortables: bool | None = None, + include_custom_curves: bool | None = None, + include_gqueries: bool | None = None, + include_output_curves: bool | None = None, ): if len(self._scenarios()) == 0: raise ValueError("Packer was empty, nothing to export") @@ -104,12 +108,107 @@ def to_excel( scenario_styling=True, ) - for pack in self.all_pack_data(): - # Skip output curves in the main workbook; exported separately - if getattr(pack, "key", None) == OutputCurvesPack.key: - continue - df = pack.to_dataframe() - if not df.empty: + # Decide which packs to include using a single global config (applies to all scenarios) + packs: list[tuple[str, Any]] = [ + ("inputs", self._inputs), + ("sortables", self._sortables), + ("custom_curves", self._custom_curves), + ] + + # Determine a global ExportConfig from the first scenario (if any) + scen_list = list(self._scenarios()) + global_cfg: ExportConfig | None = None + for s in scen_list: + cfg = getattr(s, "_export_config", None) + if cfg is not None: + global_cfg = cfg + break + + def choose_bool( + opt_flag: Optional[bool], cfg_val: Optional[bool], default: bool + ) -> bool: + if opt_flag is not None: + return bool(opt_flag) + if cfg_val is not None: + return bool(cfg_val) + return default + + include_inputs_final = choose_bool( + include_inputs, + getattr(global_cfg, "include_inputs", None) if global_cfg else None, + True, + ) + include_sortables_final = choose_bool( + include_sortables, + getattr(global_cfg, "include_sortables", None) if global_cfg else None, + False, + ) + include_custom_curves_final = choose_bool( + include_custom_curves, + getattr(global_cfg, "include_custom_curves", None) if global_cfg else None, + False, + ) + include_gqueries_final = choose_bool( + include_gqueries, + getattr(global_cfg, "include_gqueries", None) if global_cfg else None, + False, + ) + + inputs_defaults_final = ( + bool(getattr(global_cfg, "inputs_defaults", False)) if global_cfg else False + ) + inputs_min_max_final = ( + bool(getattr(global_cfg, "inputs_min_max", False)) if global_cfg else False + ) + + # Emit sheets based on global flags + for name, pack in packs: + if name == "inputs" and include_inputs_final: + try: + fields: list[str] = ["user"] + if inputs_defaults_final: + fields.append("default") + if inputs_min_max_final: + fields.append("__bounds__") + if fields == ["user"]: + df = self._inputs.to_dataframe(columns="user") + elif fields == ["min", "max"]: + df = self._inputs.to_dataframe_min_max() + elif fields == ["default"]: + df = self._inputs.to_dataframe_defaults() + elif fields == ["user", "default"]: + fm = {s: fields for s in pack.scenarios} + df = self._inputs.to_dataframe_per_scenario_fields(fm) + elif fields == ["user", "min", "max"]: + fm = {s: ["user"] for s in pack.scenarios} + df_user = self._inputs.to_dataframe_per_scenario_fields(fm) + df_bounds = self._inputs.to_dataframe_min_max() + try: + df = pd.concat([df_bounds, df_user], axis=1) + except Exception: + df = df_user + else: + mapped_fields = [f for f in fields if f != "__bounds__"] + fm = {s: mapped_fields for s in pack.scenarios} + df_core = self._inputs.to_dataframe_per_scenario_fields(fm) + if "__bounds__" in fields: + df_bounds = self._inputs.to_dataframe_min_max() + try: + df = pd.concat([df_bounds, df_core], axis=1) + except Exception: + df = df_core + else: + df = df_core + except Exception: + df = pack.to_dataframe() + elif name == "sortables" and include_sortables_final: + df = pack.to_dataframe() + elif name == "custom_curves" and include_custom_curves_final: + df = pack.to_dataframe() + else: + df = pd.DataFrame() + + if df is not None and not df.empty: df_filled = df.fillna("").infer_objects(copy=False) add_frame( name=pack.sheet_name, @@ -119,135 +218,49 @@ def to_excel( scenario_styling=True, ) + if include_gqueries_final: + gq_pack = QueryPack(scenarios=self._scenarios()) + df_gq = gq_pack.to_dataframe(columns="future") + if not df_gq.empty: + add_frame( + name=gq_pack.output_sheet_name, + frame=df_gq.fillna("").infer_objects(copy=False), + workbook=workbook, + column_width=18, + scenario_styling=True, + ) + workbook.close() # Export output curves to a separate workbook with one sheet per carrier - if export_output_curves: - oc_path = output_curves_path - if oc_path is None: - base = Path(path) - oc_path = str(base.with_name(f"{base.stem}_output_curves{base.suffix}")) + include_output_global = False + if include_output_curves is True: + include_output_global = True + elif include_output_curves is None: try: - self._output_curves.to_excel_per_carrier(oc_path, carriers) + include_output_global = bool( + getattr(global_cfg, "output_carriers", None) + ) + except Exception: + include_output_global = False + if include_output_global: + base = Path(path) + oc_path = str(base.with_name(f"{base.stem}_exports{base.suffix}")) + chosen_carriers: Optional[Sequence[str]] = ( + list(carriers) if carriers else None + ) + if chosen_carriers is None and global_cfg is not None: + try: + chosen_carriers = ( + list(getattr(global_cfg, "output_carriers", None) or []) or None + ) + except Exception: + chosen_carriers = None + try: + self._output_curves.to_excel_per_carrier(oc_path, chosen_carriers) except Exception as e: logger.warning("Failed exporting output curves workbook: %s", e) - def _scenarios(self) -> set["Scenario"]: - """ - All scenarios we are packing info for across all packs. - """ - all_scenarios: set["Scenario"] = set() - for pack in self.all_pack_data(): - try: - items = getattr(pack, "scenarios", None) - if not items: - continue - if isinstance(items, set): - all_scenarios.update(items) - else: - try: - all_scenarios.update(list(items)) - except TypeError: - continue - except Exception: - continue - return all_scenarios - - def all_pack_data(self): - """Yields each subpack""" - # TODO: we can also do this with model dump? - yield self._inputs - yield self._sortables - yield self._custom_curves - yield self._output_curves - - def clear(self): - """Clear all scenarios""" - for pack in self.all_pack_data(): - pack.clear() - - def remove_scenario(self, scenario: "Scenario"): - """Remove a specific scenario from all collections""" - for pack in self.all_pack_data(): - pack.discard(scenario) - - def get_summary(self) -> Dict[str, Any]: - """Get a summary of what's in the packer""" - summary = {"total_scenarios": len(self._scenarios())} - - for pack in self.all_pack_data(): - summary.update(pack.summary()) - - summary["scenario_ids"] = sorted([s.id for s in self._scenarios()]) - - return summary - - def _first_non_empty_row_index(self, df: pd.DataFrame) -> Optional[int]: - if df is None: - return None - for idx, (_, row) in enumerate(df.iterrows()): - if not row.isna().all(): - return idx - return None - - def _is_empty_or_helper(self, col_name: Any, helper_names: set[str]) -> bool: - if not isinstance(col_name, str): - return True - name = col_name.strip().lower() - return name in (helper_names or set()) or name in {"", "nan"} - - def _normalize_sheet( - self, - df: pd.DataFrame, - *, - helper_names: set[str], - reset_index: bool = True, - rename_map: Optional[Dict[str, str]] = None, - ) -> pd.DataFrame: - if df is None: - return pd.DataFrame() - df = df.dropna(how="all") - if df.empty: - return df - - header_pos = self._first_non_empty_row_index(df) - if header_pos is None: - return pd.DataFrame() - - header = df.iloc[header_pos].astype(str).map(lambda s: s.strip()) - data = df.iloc[header_pos + 1 :].copy() - data.columns = header.values - - keep_cols = [ - col - for col in data.columns - if not self._is_empty_or_helper(col, helper_names) - ] - data = data[keep_cols] - - if rename_map: - data = data.rename(columns=rename_map) - - if reset_index: - data.reset_index(drop=True, inplace=True) - - return data - - def _coerce_bool(self, v: Any) -> Optional[bool]: - if v is None or (isinstance(v, float) and pd.isna(v)): - return None - if isinstance(v, bool): - return v - if isinstance(v, (int, float)): - return bool(int(v)) - if isinstance(v, str): - s = v.strip().lower() - if s in {"true", "yes", "y", "1"}: - return True - if s in {"false", "no", "n", "0"}: - return False - return None - def _coerce_int(self, v: Any) -> Optional[int]: if v is None or (isinstance(v, float) and pd.isna(v)): return None @@ -328,12 +341,22 @@ def _extract_scenario_sheet_info( ) -> Dict[str, Dict[str, str]]: scenario_sheets = {} + def _value_before_output(series: pd.Series, key: str): + seen_output = False + for label, val in zip(series.index, series.values): + lab = str(label).strip().lower() + if lab == "output": + seen_output = True + if lab == key and not seen_output: + return val + return None + if isinstance(main_df, pd.Series): # Single scenario identifier = str(main_df.name) short_name = main_df.get("short_name") - sortables_sheet = main_df.get("sortables") - custom_curves_sheet = main_df.get("custom_curves") + sortables_sheet = _value_before_output(main_df, "sortables") + custom_curves_sheet = _value_before_output(main_df, "custom_curves") scenario_sheets[identifier] = { "short_name": short_name if pd.notna(short_name) else identifier, @@ -347,8 +370,8 @@ def _extract_scenario_sheet_info( for identifier in main_df.columns: col_data = main_df[identifier] short_name = col_data.get("short_name") - sortables_sheet = col_data.get("sortables") - custom_curves_sheet = col_data.get("custom_curves") + sortables_sheet = _value_before_output(col_data, "sortables") + custom_curves_sheet = _value_before_output(col_data, "custom_curves") scenario_sheets[str(identifier)] = { "short_name": ( @@ -373,7 +396,21 @@ def _process_single_scenario_sortables( ) if data is None or data.empty: return - scenario.set_sortables_from_dataframe(data) + try: + scenario.set_sortables_from_dataframe(data) + except Exception as e: + logger.warning( + "Failed processing sortables for '%s': %s", scenario.identifier(), e + ) + else: + try: + if hasattr(scenario, "_sortables") and scenario._sortables is not None: + scenario._sortables.log_warnings( + logger, + prefix=f"Sortables warning for '{scenario.identifier()}'", + ) + except Exception: + pass def _process_single_scenario_curves(self, scenario: "Scenario", df: pd.DataFrame): data = self._normalize_sheet( @@ -386,8 +423,34 @@ def _process_single_scenario_curves(self, scenario: "Scenario", df: pd.DataFrame # Build CustomCurves collection and apply try: curves = CustomCurves._from_dataframe(data, scenario_id=scenario.id) + curves.log_warnings( + logger, + prefix=f"Custom curves warning for '{scenario.identifier()}'", + ) + try: + validation = curves.validate_for_upload() + for key, collector in (validation or {}).items(): + for w in collector: + logger.warning( + "Custom curve validation for '%s' in '%s' [%s]: %s", + key, + scenario.identifier(), + getattr(w, "field", key), + getattr(w, "message", str(w)), + ) + except Exception: + pass + scenario.update_custom_curves(curves) except Exception as e: + try: + if "curves" in locals(): + curves.log_warnings( + logger, + prefix=f"Custom curves warning for '{scenario.identifier()}'", + ) + except Exception: + pass logger.warning( "Failed processing custom curves for '%s': %s", scenario.identifier(), e ) @@ -415,9 +478,12 @@ def from_excel(cls, xlsx_path: PathLike | str) -> "ScenarioPacker": # Build scenarios per MAIN column scenarios_by_col: Dict[str, Scenario] = {} for col in main_df.columns: + col_str = str(col) if col is not None else "" + if col_str.strip().lower() in {"description", "helper", "notes"}: + continue try: scenario = packer._setup_scenario_from_main_column( - str(col), main_df[col] + str(col_str), main_df[col] ) except Exception as e: logger.warning("Failed to set up scenario for column '%s': %s", col, e) @@ -425,7 +491,108 @@ def from_excel(cls, xlsx_path: PathLike | str) -> "ScenarioPacker": if scenario is not None: packer.add(scenario) - scenarios_by_col[str(col)] = scenario + scenarios_by_col[str(col_str)] = scenario + + # Apply OUTPUT settings globally from the first scenario column, if present + try: + first_col_name: Optional[str] = next(iter(scenarios_by_col.keys()), None) + if first_col_name is not None: + col_data = main_df[first_col_name] + # case-insensitive row access + idx_map = {str(i).strip().lower(): i for i in col_data.index} + + def _cell_ci(name: str): + key = name.strip().lower() + src_key = idx_map.get(key) + if src_key is None: + return None + return col_data.get(src_key) + + def _bool(v) -> Optional[bool]: + if v is None: + return None + if isinstance(v, bool): + return v + try: + if isinstance(v, (int, float)) and not pd.isna(v): + return bool(int(v)) + except Exception: + pass + if isinstance(v, str): + s = v.strip().lower() + if s in {"true", "yes", "y", "1"}: + return True + if s in {"false", "no", "n", "0"}: + return False + return None + + inc_inputs = _bool(_cell_ci("inputs")) + inc_gq = _bool(_cell_ci("gquery_results")) or _bool( + _cell_ci("gqueries") + ) + inc_sortables = _bool(_cell_ci("sortables")) + inc_curves = _bool(_cell_ci("custom_curves")) + inputs_defaults = _bool(_cell_ci("defaults")) + inputs_min_max = _bool(_cell_ci("min_max")) + carriers_raw = _cell_ci("exports") or _cell_ci("output_carriers") + carriers_list = None + if isinstance(carriers_raw, str) and carriers_raw.strip(): + carriers_list = [ + p.strip() for p in carriers_raw.split(",") if p.strip() + ] + + # Legacy column-based include_* support + legacy_inc_inputs = _cell_ci("include_inputs") + legacy_inc_sortables = _cell_ci("include_sortables") + legacy_inc_curves = _cell_ci("include_custom_curves") + legacy_inc_gq = _cell_ci("include_gqueries") + + cfg = ExportConfig( + include_inputs=( + _bool(legacy_inc_inputs) + if legacy_inc_inputs is not None + else inc_inputs + ), + include_sortables=( + _bool(legacy_inc_sortables) + if legacy_inc_sortables is not None + else inc_sortables + ), + include_custom_curves=( + _bool(legacy_inc_curves) + if legacy_inc_curves is not None + else inc_curves + ), + include_gqueries=( + _bool(legacy_inc_gq) if legacy_inc_gq is not None else inc_gq + ), + inputs_defaults=inputs_defaults, + inputs_min_max=inputs_min_max, + output_carriers=carriers_list, + ) + + if any( + getattr(cfg, f) is not None + for f in ( + "include_inputs", + "include_sortables", + "include_custom_curves", + "include_gqueries", + "inputs_defaults", + "inputs_min_max", + "output_carriers", + ) + ): + for scenario in scenarios_by_col.values(): + try: + if hasattr(scenario, "set_export_config"): + scenario.set_export_config(cfg) + else: + setattr(scenario, "_export_config", cfg) + except Exception: + pass + except Exception: + pass if len(scenarios_by_col) == 0: return packer @@ -440,7 +607,7 @@ def from_excel(cls, xlsx_path: PathLike | str) -> "ScenarioPacker": short = str(scenario.identifier()) short_name_map[str(scenario.id)] = str(short) - # PARAMETERS (inputs) sheet + # SLIDER_SETTINGS sheet params_df = None try: params_df = xls.parse(InputsPack.sheet_name, header=None) @@ -452,9 +619,9 @@ def from_excel(cls, xlsx_path: PathLike | str) -> "ScenarioPacker": packer._inputs.set_scenario_short_names(short_name_map) packer._inputs.from_dataframe(params_df) except Exception as e: - logger.warning("Failed to import PARAMETERS: %s", e) + logger.warning("Failed to import SLIDER_SETTINGS: %s", e) - # GQUERIES sheet (keys to attach to scenarios) + # GQUERIES sheet gq_df = None for sheet in ("GQUERIES", QueryPack.sheet_name): if sheet in xls.sheet_names: @@ -541,66 +708,11 @@ def _setup_scenario_from_main_column( return scenario def _build_excel_main_dataframe(self) -> pd.DataFrame: - """Build a MAIN sheet DataFrame with rich metadata for Excel export only.""" - scenarios = list(self._scenarios()) - if not scenarios: + """Build a MAIN sheet DataFrame for Excel export using main_info().""" + df = self.main_info() + if df is None or df.empty: return pd.DataFrame() - def id_or_title(s): - try: - return s.identifier() - except Exception: - return getattr(s, "id", None) - - columns: dict[Any, dict[str, Any]] = {} - all_keys: list[str] = [] - - def add_key(k: str): - if k not in all_keys: - all_keys.append(k) - - for s in scenarios: - info: dict[str, Any] = {} - - # Core identifiers and common fields - info["scenario_id"] = getattr(s, "id", None) - info["area_code"] = getattr(s, "area_code", None) - info["end_year"] = getattr(s, "end_year", None) - info["start_year"] = getattr(s, "start_year", None) - info["keep_compatible"] = getattr(s, "keep_compatible", None) - info["private"] = getattr(s, "private", None) - info["template"] = getattr(s, "template", None) - info["source"] = getattr(s, "source", None) - try: - info["title"] = s.title - except Exception: - info["title"] = None - meta = getattr(s, "metadata", None) - if isinstance(meta, dict): - desc = meta.get("description") - if desc is not None: - info["description"] = desc - info["url"] = getattr(s, "url", None) - try: - info["version"] = s.version - except Exception: - info["version"] = None - info["created_at"] = getattr(s, "created_at", None) - info["updated_at"] = getattr(s, "updated_at", None) - - # Flatten all other metadata keys - if isinstance(meta, dict): - for k, v in meta.items(): - if k in ("title", "description"): - continue - info[f"metadata.{k}"] = v - - label = id_or_title(s) - columns[label] = info - for k in info.keys(): - add_key(k) - - # Preferred key order at top preferred = [ "title", "description", @@ -617,13 +729,42 @@ def add_key(k: str): "created_at", "updated_at", ] - remaining = [k for k in all_keys if k not in preferred] - index_order = preferred + remaining - - df = pd.DataFrame( - {col: {k: columns[col].get(k) for k in index_order} for col in columns} - ) + present = [k for k in preferred if k in df.index] + remaining = [k for k in df.index if k not in present] + ordered = present + remaining + df = df.reindex(index=ordered) df.index.name = "scenario" + + # Rename columns to use an identifier + try: + scen_list = list(self._scenarios()) + rename_map: dict[Any, Any] = {} + by_str_id = {str(getattr(s, "id", "")): s for s in scen_list} + for col in list(df.columns): + matched_s = None + for s in scen_list: + if col == getattr(s, "id", None): + matched_s = s + break + if matched_s is None: + matched_s = by_str_id.get(str(col)) + if matched_s is not None: + try: + label = ( + matched_s.identifier() + if hasattr(matched_s, "identifier") + else getattr(matched_s, "title", None) + or getattr(matched_s, "id", col) + ) + except Exception: + label = getattr(matched_s, "title", None) or getattr( + matched_s, "id", col + ) + rename_map[col] = label + if rename_map: + df = df.rename(columns=rename_map) + except Exception: + pass return df def _sanitize_dataframe_for_excel(self, df: pd.DataFrame) -> pd.DataFrame: @@ -635,13 +776,11 @@ def _safe(v: Any): return "" if isinstance(v, (str, int, float, bool)): return v - # Pandas Timestamp / datetime if isinstance(v, (pd.Timestamp, _dt.datetime, _dt.date)): try: return str(v) except Exception: return "" - # Convert everything else to string try: return str(v) except Exception: @@ -651,3 +790,131 @@ def _safe(v: Any): out.index = out.index.map(lambda x: str(x) if x is not None else "") out.columns = [str(c) if c is not None else "" for c in out.columns] return out.map(_safe) + + def all_pack_data(self): + """Yield each sub-pack collection.""" + yield self._inputs + yield self._sortables + yield self._custom_curves + yield self._output_curves + + def _scenarios(self) -> set["Scenario"]: + """All scenarios we are packing info for across all packs.""" + all_scenarios: set["Scenario"] = set() + for pack in self.all_pack_data(): + try: + items = getattr(pack, "scenarios", None) + if not items: + continue + if isinstance(items, set): + all_scenarios.update(items) + else: + try: + all_scenarios.update(set(items)) + except Exception: + pass + except Exception: + continue + return all_scenarios + + def clear(self): + """Clear all scenarios from all packs.""" + for pack in self.all_pack_data(): + try: + pack.clear() + except Exception: + pass + + def remove_scenario(self, scenario: "Scenario"): + """Remove a specific scenario from all collections.""" + for pack in self.all_pack_data(): + try: + pack.discard(scenario) + except Exception: + pass + + def get_summary(self) -> Dict[str, Any]: + """Get a summary of what's in the packer.""" + summary: Dict[str, Any] = {"total_scenarios": len(self._scenarios())} + for pack in self.all_pack_data(): + try: + summary.update(pack.summary()) + except Exception: + pass + summary["scenario_ids"] = sorted( + [getattr(s, "id", None) for s in self._scenarios()] + ) + return summary + + def _first_non_empty_row_index(self, df: pd.DataFrame) -> Optional[int]: + if df is None: + return None + for idx, (_, row) in enumerate(df.iterrows()): + try: + if not row.isna().all(): + return idx + except Exception: + if any(v not in (None, "", float("nan")) for v in row): + return idx + return None + + def _is_empty_or_helper(self, col_name: Any, helper_names: set[str]) -> bool: + if not isinstance(col_name, str): + return True + name = col_name.strip().lower() + return name in (helper_names or set()) or name in {"", "nan"} + + def _normalize_sheet( + self, + df: pd.DataFrame, + *, + helper_names: set[str], + reset_index: bool = True, + rename_map: Optional[Dict[str, str]] = None, + ) -> pd.DataFrame: + if df is None: + return pd.DataFrame() + df = df.dropna(how="all") + if df.empty: + return df + + header_pos = self._first_non_empty_row_index(df) + if header_pos is None: + return pd.DataFrame() + + header = df.iloc[header_pos].astype(str).map(lambda s: s.strip()) + data = df.iloc[header_pos + 1 :].copy() + data.columns = header.values + + keep_cols = [ + col + for col in data.columns + if not self._is_empty_or_helper(col, helper_names) + ] + data = data[keep_cols] + + if rename_map: + data = data.rename(columns=rename_map) + + if reset_index: + data.reset_index(drop=True, inplace=True) + + return data + + def _coerce_bool(self, v: Any) -> Optional[bool]: + if v is None or (isinstance(v, float) and pd.isna(v)): + return None + if isinstance(v, bool): + return v + if isinstance(v, (int, float)): + try: + return bool(int(v)) + except Exception: + return None + if isinstance(v, str): + s = v.strip().lower() + if s in {"true", "yes", "y", "1"}: + return True + if s in {"false", "no", "n", "0"}: + return False + return None diff --git a/src/pyetm/models/scenarios.py b/src/pyetm/models/scenarios.py index 082b9f7..dc082e2 100644 --- a/src/pyetm/models/scenarios.py +++ b/src/pyetm/models/scenarios.py @@ -32,14 +32,13 @@ def to_excel( self, path: PathLike | str, *, - export_output_curves: bool = True, - output_curves_path: Optional[str] = None, carriers: Optional[Sequence[str]] = None, + include_inputs: bool | None = None, + include_sortables: bool | None = None, + include_custom_curves: bool | None = None, + include_gqueries: bool | None = None, + include_output_curves: bool | None = None, ) -> None: - """ - Export all scenarios in this collection to an Excel workbook. - Output curves are written to a separate workbook by default (one sheet per carrier). - """ from .scenario_packer import ScenarioPacker packer = ScenarioPacker() @@ -47,9 +46,12 @@ def to_excel( packer.add(*self.items) packer.to_excel( str(path), - export_output_curves=export_output_curves, - output_curves_path=output_curves_path, carriers=carriers, + include_inputs=include_inputs, + include_sortables=include_sortables, + include_custom_curves=include_custom_curves, + include_gqueries=include_gqueries, + include_output_curves=include_output_curves, ) @classmethod diff --git a/src/pyetm/services/scenario_runners/update_custom_curves.py b/src/pyetm/services/scenario_runners/update_custom_curves.py index 5e8a9a4..5cc305c 100644 --- a/src/pyetm/services/scenario_runners/update_custom_curves.py +++ b/src/pyetm/services/scenario_runners/update_custom_curves.py @@ -65,7 +65,8 @@ def run( if result.success: successful_uploads.append(curve.key) else: - all_errors.extend(result.errors) + for err in result.errors: + all_errors.append(f"{curve.key}: {err}") except Exception as e: all_errors.append(f"Error uploading {curve.key}: {str(e)}") diff --git a/tests/models/packables/test_inputs_pack.py b/tests/models/packables/test_inputs_pack.py index 222f020..d7c6125 100644 --- a/tests/models/packables/test_inputs_pack.py +++ b/tests/models/packables/test_inputs_pack.py @@ -144,7 +144,7 @@ def test_from_dataframe_parses_and_updates(caplog): s1.update_user_values.assert_called_once_with({"a": 1}) s3.update_user_values.assert_called_once_with({"a": 10}) # Unknown column should produce a warning and not call any scenario - assert "Could not find scenario for PARAMETERS column label" in caplog.text + assert "Could not find scenario for SLIDER_SETTINGS column label" in caplog.text def test_from_dataframe_handles_update_exception(caplog): diff --git a/tests/models/test_scenario_packer.py b/tests/models/test_scenario_packer.py index 919a38f..9ad20f0 100644 --- a/tests/models/test_scenario_packer.py +++ b/tests/models/test_scenario_packer.py @@ -432,6 +432,13 @@ def test_to_excel_with_data(self, scenario_with_inputs): packer = ScenarioPacker() packer.add(scenario_with_inputs) + scenario_with_inputs.to_dataframe = Mock( + return_value=pd.DataFrame( + {scenario_with_inputs.id: ["nl2015", 2050]}, + index=["area_code", "end_year"], + ) + ) + with ( patch.object(ScenarioPacker, "main_info", return_value=dummy_main_df), patch.object(InputsPack, "to_dataframe", return_value=dummy_inputs_df), @@ -922,7 +929,9 @@ def test_from_excel_full_flow(self, tmp_path, monkeypatch): path = tmp_path / "import.xlsx" with pd.ExcelWriter(path, engine="xlsxwriter") as writer: main.to_excel(writer, sheet_name="MAIN") - params.to_excel(writer, sheet_name="PARAMETERS", header=False, index=False) + params.to_excel( + writer, sheet_name="SLIDER_SETTINGS", header=False, index=False + ) gqueries.to_excel(writer, sheet_name="GQUERIES", header=False, index=False) s1_sort.to_excel(writer, sheet_name="S1_SORT", header=False, index=False) s2_sort.to_excel(writer, sheet_name="S2_SORT", header=False, index=False) @@ -988,8 +997,9 @@ def test_from_excel_missing_or_bad_main(self, tmp_path): assert isinstance(packer3, ScenarioPacker) assert len(packer3._scenarios()) == 0 - def test_from_excel_parameters_and_gqueries_errors(self, tmp_path, monkeypatch): - # Prepare a minimal MAIN and both PARAMETERS and GQUERIES sheets + def test_from_excel_slider_settings_and_gqueries_errors( + self, tmp_path, monkeypatch + ): main = pd.DataFrame( { "S": { @@ -1007,7 +1017,9 @@ def test_from_excel_parameters_and_gqueries_errors(self, tmp_path, monkeypatch): path = tmp_path / "errs.xlsx" with pd.ExcelWriter(path, engine="xlsxwriter") as writer: main.to_excel(writer, sheet_name="MAIN") - params.to_excel(writer, sheet_name="PARAMETERS", header=False, index=False) + params.to_excel( + writer, sheet_name="SLIDER_SETTINGS", header=False, index=False + ) gqueries.to_excel(writer, sheet_name="GQUERIES", header=False, index=False) # Create returns a simple scenario @@ -1139,7 +1151,7 @@ def setup(col_name, col_ser): packer2 = ScenarioPacker.from_excel(str(path)) assert len(packer2._scenarios()) == 0 - def test_from_excel_missing_parameters_sheet_parse_error( + def test_from_excel_missing_slider_settings_sheet_parse_error( self, tmp_path, monkeypatch ): main = pd.DataFrame( From e2d94880d812720ae8f993b04df7eb416a327bc2 Mon Sep 17 00:00:00 2001 From: louispt1 Date: Fri, 15 Aug 2025 11:43:18 +0200 Subject: [PATCH 13/19] Refactor Inputs Pack and try fix semaphore --- .semaphore/semaphore.yml | 19 +- examples/example_input_excel.xlsx | Bin 1377026 -> 1377008 bytes src/pyetm/models/packables/inputs_pack.py | 512 ++++--- src/pyetm/models/scenario_packer.py | 1576 +++++++++++--------- tests/models/conftest.py | 57 + tests/models/packables/test_inputs_pack.py | 8 +- tests/models/test_scenario_packer.py | 250 +++- 7 files changed, 1456 insertions(+), 966 deletions(-) diff --git a/.semaphore/semaphore.yml b/.semaphore/semaphore.yml index b759d74..140e6cd 100644 --- a/.semaphore/semaphore.yml +++ b/.semaphore/semaphore.yml @@ -4,23 +4,24 @@ agent: machine: type: e1-standard-2 os_image: ubuntu2004 + blocks: - name: Test task: - env_vars: - - name: PIPENV_VENV_IN_PROJECT - value: 'true' prologue: commands: - sem-version python 3.12 - pip install --upgrade pip - - pip install pipenv - - 'export PATH=$HOME/.local/bin:$PATH' + - pip install poetry + - poetry config virtualenvs.in-project true + - export PATH="$HOME/.local/bin:$PATH" - checkout - - 'cache restore pipenv-$SEMAPHORE_GIT_BRANCH-$(checksum Pipfile.lock),pipenv-$SEMAPHORE_GIT_BRANCH,pipenv-master' - - pipenv install --dev --ignore-pipfile - - cache store pipenv-$SEMAPHORE_GIT_BRANCH-$(checksum Pipfile.lock) .venv + - cache restore poetry-cache-$SEMAPHORE_GIT_BRANCH,poetry-cache-master + - cache restore poetry-venv-$SEMAPHORE_GIT_BRANCH-$(checksum poetry.lock),poetry-venv-$SEMAPHORE_GIT_BRANCH + - poetry install --with dev + - cache store poetry-cache-$SEMAPHORE_GIT_BRANCH ~/.cache/pypoetry + - cache store poetry-venv-$SEMAPHORE_GIT_BRANCH-$(checksum poetry.lock) .venv jobs: - name: Test commands: - - pipenv run test + - poetry run pytest diff --git a/examples/example_input_excel.xlsx b/examples/example_input_excel.xlsx index a1bbb3f5c641df92ee0f8b6e4393bd478701839c..49b1a6cc8e7691241b6e95ccb949ade0a2d35be4 100644 GIT binary patch delta 2851 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 z zI!$0w^w}PQDau5tdWTgbS`yvb<=1N4v9z4CZ@zMWQuU%#JRNBtuYNu+o-z=mo{~C- zNzb+t8c8GJG*DQJY5Qf=-3pxO@(-mkq(ryhqWwqyn~oWLUdig6l$JiQ^Qgh2_N>fdBzcyf zcRN$mReQ5vAj_{Z1MWqkR`b7|E&?o_&oqwBllHixMKnl}4AM`R^*FJIbc)xI50I+s zK=s99vAtAn$iX{hSTbWP%zAXhYW?A_AiftXjToZB9#>rjmk>WY!@qD9!U_Py^8Obb z)!)H+%?u9wzu=%3ytsf8?kt9PgB?O!T!dH7pcgR>L$9j7==MRBB?GP0t$DrnI*5K^RmvB6g5ixv)hMS2Liyur0>9Mv_I-kEBfaDRrkSJp zs0Y>lKg5;WKm+MD&fZ_2lZ<@^(7K=e-JLnB*9~i7|E6ZZ&>%{mA?9&+$e4(PFPM7! zagAB3rF|R9NkByfWOTcU9 z%hQIp=|$t6OZco8{HsrdrFy!c4y#?li2I3}A|ri0Na)0F&>>}5ro0Q*TAh+Klrwz0 zEu~LA-@FC*3-#7}eva??DF zKo2m_a_VEk80pqRyHB>#Qhx!P=G6A~)N%W{9MU9ihy!hRV4BmY@A<}D+Hbm}apC1R zXo^4H730XMX%P{j*hMVz@nfjuF%*yq!~|wyVPa)sV>-rk zoC(6j&ID!RVB%zgF>x_*Gx0F-GVwKyq2Ra?mJ~BXa1(YHjs%hjPsHJg3$%4T^|mI< z;^E9jnb}3EjLcdsp1{GFaV!P8Y%Ne4XF|u4b)I0imx_e5cdhceH3cqu=h86}NI*{m z@}-6mVOOH4tm||Ii+lqaUfe~GxJIIVO%3vQ_YYz1MYw}6Sm%A0Gtyd-OMSGgmHEPW zzO3!>n6c^#g>)rNzIWRX8gAGRHzk@W_YuJy_e)ZS&vi%PLY47QZV>|rZ%!TN=H>mh zQ1?6S*ikufCHl?1@5RG`$$s5hkHWW*5|uBW6uelTu%iL@^+&% zyNWbkTZ^#^R~NjF=M1)w^`X6un_sWRy?U@eqsf|5`S-*|*408%xx%CltHf6oABRu$ zHp)M4-&qHZaq5r(v=jwfFcxmMG~h*D9Es*@ZOvRkABp!;i_BKRWm2NtO4rfd4sOzW z)KNA>Q|lf)5&Y)^NjrZ8w*Ud5w1OizTKLZp0RRM;v*pinqrE+X%ZvPZEdGB(n+)yU z5gd`LjZgyZ$^Wj&%vw(Aciqpd&6Q|+Km>vY10s}wSeh;nVFVJw{_frSw^v0Q1R~A= rsWd1EaT@rBW(-2e{ucyVAP8}Sc_amd&;@qV`alRtw*Esn^M3yWuK+5v diff --git a/src/pyetm/models/packables/inputs_pack.py b/src/pyetm/models/packables/inputs_pack.py index 0db08ee..111e4c9 100644 --- a/src/pyetm/models/packables/inputs_pack.py +++ b/src/pyetm/models/packables/inputs_pack.py @@ -1,5 +1,5 @@ import logging -from typing import ClassVar, Dict, Any +from typing import ClassVar, Dict, Any, List, Set import pandas as pd from pyetm.models.packables.packable import Packable @@ -15,288 +15,336 @@ def __init__(self, **data): self._scenario_short_names: Dict[str, str] = {} def set_scenario_short_names(self, scenario_short_names: Dict[str, str]): + """Set mapping of scenario IDs to short names for display purposes.""" self._scenario_short_names = scenario_short_names or {} - def _key_for(self, scenario: "Any") -> Any: - short = self._scenario_short_names.get(str(scenario.id)) - if short: - return short + def _get_scenario_display_key(self, scenario: "Any") -> Any: + """Get the display key for a scenario (short name, identifier, or ID).""" + short_name = self._scenario_short_names.get(str(scenario.id)) + if short_name: + return short_name - label = None try: - label = scenario.identifier() + identifier = scenario.identifier() + if isinstance(identifier, (str, int)): + return identifier except Exception: - label = None + pass - if not isinstance(label, (str, int)): - return scenario.id - return label + return scenario.id def resolve_scenario(self, label: Any): + """Resolve a scenario from various label formats (short name, identifier, or numeric ID).""" if label is None: return None + label_str = str(label).strip() - # Match short name first + + # Try short name first for scenario in self.scenarios: if self._scenario_short_names.get(str(scenario.id)) == label_str: return scenario - # Fallback to identifier/title - found = super().resolve_scenario(label_str) - if found is not None: - return found - # Fallback to numeric id + + # Identifier/title + found_scenario = super().resolve_scenario(label_str) + if found_scenario is not None: + return found_scenario + + # Try numeric ID as fallback try: - num = int(float(label_str)) + numeric_id = int(float(label_str)) for scenario in self.scenarios: - if scenario.id == num: + if scenario.id == numeric_id: return scenario - except Exception: + except (ValueError, TypeError): pass + return None - def _extract_map(self, scen, attr: str) -> dict[str, Any] | None: - """Extract a mapping of input key -> attribute value for a scenario's inputs.""" - iter_attr_primary = attr - iter_attr_fallback = None - if attr == "min_max": - iter_attr_primary = "min" - iter_attr_fallback = "max" + def _extract_input_values(self, scenario, field_name: str) -> Dict[str, Any]: + """Extract input values for a specific field from a scenario.""" + values = self._extract_from_input_objects(scenario, field_name) + if values: + return values + + return self._extract_from_dataframe(scenario, field_name) - # 1) Try iterating input objects first + def _extract_from_input_objects(self, scenario, field_name: str) -> Dict[str, Any]: + """Extract values by iterating through scenario input objects.""" try: - values: dict[str, Any] = {} - for inp in scen.inputs: - key = getattr(inp, "key", None) + values = {} + for input_obj in scenario.inputs: + key = getattr(input_obj, "key", None) if key is None: continue - val = getattr(inp, iter_attr_primary, None) - if val is None and iter_attr_fallback is not None: - val = getattr(inp, iter_attr_fallback, None) - values[str(key)] = val if attr != "min_max" else val - if values: - return values + + value = getattr(input_obj, field_name, None) + values[str(key)] = value + + return values if values else {} except Exception: - pass + return {} - # 2) Fallback to DataFrame/Series + def _extract_from_dataframe(self, scenario, field_name: str) -> Dict[str, Any]: + """Extract values from scenario inputs DataFrame.""" try: - df = ( - scen.inputs.to_dataframe(columns=["min", "max"]) - if attr == "min_max" - else scen.inputs.to_dataframe(columns=attr) - ) + df = scenario.inputs.to_dataframe(columns=field_name) except Exception: - df = None + return {} if df is None or getattr(df, "empty", False): - return None + return {} - # Normalize index (drop 'unit' if present) + # Handle MultiIndex (drop 'unit' level if present) + df = self._normalize_dataframe_index(df) + series = self._dataframe_to_series(df, field_name) + if series is None: + return {} + + series.index = series.index.map(str) + return series.to_dict() + + def _normalize_dataframe_index(self, df: pd.DataFrame) -> pd.DataFrame: + """Remove 'unit' level from MultiIndex if present.""" if isinstance(df.index, pd.MultiIndex) and "unit" in (df.index.names or []): df = df.copy() df.index = df.index.droplevel("unit") + return df + def _dataframe_to_series(self, df: pd.DataFrame, field_name: str) -> pd.Series: + """Convert DataFrame to Series, selecting appropriate column.""" if isinstance(df, pd.Series): - series = df - else: - cols_lc = {str(c).lower(): c for c in df.columns} - if attr == "min_max": - if "min" in cols_lc: - series = df[cols_lc["min"]] - elif "max" in cols_lc: - series = df[cols_lc["max"]] - else: - series = df.iloc[:, 0] - else: - for candidate in (attr, "user", "value", "default"): - if candidate in cols_lc: - series = df[cols_lc[candidate]] - break - else: - series = df.iloc[:, 0] - - series.index = series.index.map(str) - return series.to_dict() - - def _to_dataframe(self, columns: str = "user", **kwargs): + return df + columns_lower = {str(col).lower(): col for col in df.columns} + for candidate in (field_name, "user", "value", "default"): + if candidate in columns_lower: + return df[columns_lower[candidate]] + return df.iloc[:, 0] + + def _build_consolidated_dataframe( + self, field_mappings: Dict[Any, List[str]] + ) -> pd.DataFrame: + """Build DataFrame with different fields per scenario.""" if not self.scenarios: return pd.DataFrame() - if not isinstance(columns, str) or columns.strip() == "": - columns = "user" + relevant_scenarios = {s for s in self.scenarios if s in field_mappings} + if not relevant_scenarios: + return pd.DataFrame() + all_input_keys = self._collect_all_input_keys( + relevant_scenarios, field_mappings + ) + if not all_input_keys: + return pd.DataFrame() + sorted_keys = sorted(all_input_keys) - all_keys: set[str] = set() - per_label_values: dict[Any, dict[str, Any]] = {} - for scen in self.scenarios: - label = self._key_for(scen) - user_map = self._extract_map(scen, columns) - if not user_map: - continue - per_label_values[label] = user_map - all_keys.update(user_map.keys()) + scenario_frames = [] + scenario_labels = [] - if not all_keys: - return pd.DataFrame() + for scenario in relevant_scenarios: + scenario_label = self._get_scenario_display_key(scenario) + fields = field_mappings.get(scenario, ["user"]) or ["user"] - sorted_keys = sorted(all_keys) - data: dict[Any, list[Any]] = {} - for label, value_map in per_label_values.items(): - data[label] = [value_map.get(k) for k in sorted_keys] + scenario_data = self._build_scenario_data(scenario, fields, sorted_keys) + if not scenario_data: + continue - df = pd.DataFrame(data, index=sorted_keys) - df.index.name = "input" - return df + scenario_df = pd.DataFrame(scenario_data, index=sorted_keys) + scenario_df.index.name = "input" + scenario_frames.append(scenario_df) + scenario_labels.append(scenario_label) - def to_dataframe_per_scenario_fields( - self, fields_map: Dict["Any", list[str]] - ) -> pd.DataFrame: - """Build a DataFrame where each scenario may have different fields (e.g. ['user'], ['user','default'], ['user','min','max']).""" - if not self.scenarios: + if not scenario_frames: return pd.DataFrame() - scen_set = {s for s in self.scenarios if s in fields_map} - if not scen_set: + return pd.concat( + scenario_frames, axis=1, keys=scenario_labels, names=["scenario", "field"] + ) + + def _collect_all_input_keys( + self, scenarios: Set[Any], field_mappings: Dict[Any, List[str]] + ) -> Set[str]: + """Collect all unique input keys across scenarios and fields.""" + all_keys = set() + for scenario in scenarios: + fields = field_mappings.get(scenario, ["user"]) or ["user"] + for field in fields: + input_values = self._extract_input_values(scenario, field) + all_keys.update(input_values.keys()) + return all_keys + + def _build_scenario_data( + self, scenario, fields: List[str], sorted_keys: List[str] + ) -> Dict[str, List[Any]]: + """Build data dictionary for a single scenario across multiple fields.""" + data = {} + for field in fields: + value_mapping = self._extract_input_values(scenario, field) or {} + data[field] = [value_mapping.get(key) for key in sorted_keys] + return data + + def _build_simple_dataframe(self, field_name: str = "user") -> pd.DataFrame: + """Build simple DataFrame with one field per scenario.""" + if not self.scenarios: return pd.DataFrame() - all_keys: set[str] = set() - for s in scen_set: - fields = fields_map.get(s, ["user"]) or ["user"] - for f in fields: - m = self._extract_map(s, f) - if m: - all_keys.update(m.keys()) + all_input_keys = set() + scenario_data = {} - if not all_keys: - return pd.DataFrame() - sorted_keys = sorted(all_keys) - - frames: list[pd.DataFrame] = [] - keys: list[Any] = [] - for s in scen_set: - label = self._key_for(s) - fields = fields_map.get(s, ["user"]) or ["user"] - data: dict[str, list[Any]] = {} - for f in fields: - m = self._extract_map(s, f) or {} - data[f] = [m.get(k) for k in sorted_keys] - if not data: - continue - df_s = pd.DataFrame(data, index=sorted_keys) - df_s.index.name = "input" - frames.append(df_s) - keys.append(label) + # Collect data from all scenarios + for scenario in self.scenarios: + scenario_label = self._get_scenario_display_key(scenario) + input_values = self._extract_input_values(scenario, field_name) - if not frames: - return pd.DataFrame() + if not input_values: + continue - return pd.concat(frames, axis=1, keys=keys, names=["scenario", "field"]) + scenario_data[scenario_label] = input_values + all_input_keys.update(input_values.keys()) - def to_dataframe_defaults(self) -> pd.DataFrame: - """Build a DataFrame of default values for each input per scenario.""" - if not self.scenarios: + if not all_input_keys: return pd.DataFrame() - return self._to_dataframe(columns="default") + # Build DataFrame + sorted_keys = sorted(all_input_keys) + data = {} + for scenario_label, values in scenario_data.items(): + data[scenario_label] = [values.get(key) for key in sorted_keys] - def to_dataframe_min_max(self) -> pd.DataFrame: - """Build a DataFrame with min/max once (shared across scenarios). + df = pd.DataFrame(data, index=sorted_keys) + df.index.name = "input" + return df - Assumes bounds (min/max) are identical across scenarios. If conflicts are - found, the first-seen value is used and no exception is raised. - """ + def _build_bounds_dataframe(self) -> pd.DataFrame: + """Build DataFrame with min/max bounds (assumes identical across scenarios).""" if not self.scenarios: return pd.DataFrame() - # Collect union of keys across scenarios - all_keys: set[str] = set() - for scen in self.scenarios: + # Collect all input keys + all_input_keys = set() + for scenario in self.scenarios: try: - it = iter(scen.inputs) - keys = [str(getattr(inp, "key", "")) for inp in it] + keys = [ + str(getattr(inp, "key", "")) + for inp in scenario.inputs + if getattr(inp, "key", None) + ] except Exception: try: - df = scen.inputs.to_dataframe(columns=["min", "max"]) - # Drop 'unit' level if present - if isinstance(df.index, pd.MultiIndex) and "unit" in ( - df.index.names or [] - ): - df = df.copy() - df.index = df.index.droplevel("unit") - keys = [str(i) for i in df.index.unique()] + df = scenario.inputs.to_dataframe(columns=["min", "max"]) + df = self._normalize_dataframe_index(df) + keys = [str(idx) for idx in df.index.unique()] except Exception: keys = [] - all_keys.update([k for k in keys if k]) - if not all_keys: + all_input_keys.update(key for key in keys if key) + + if not all_input_keys: return pd.DataFrame() - sorted_keys = sorted(all_keys) - - # Choose bounds from the first scenario that provides them; ignore conflicts - min_vals: dict[str, Any] = {} - max_vals: dict[str, Any] = {} - for scen in self.scenarios: - m_min = self._extract_map(scen, "min") or {} - m_max = self._extract_map(scen, "max") or {} - for k in sorted_keys: - if k not in min_vals and k in m_min: - min_vals[k] = m_min.get(k) - if k not in max_vals and k in m_max: - max_vals[k] = m_max.get(k) - if len(min_vals) == len(sorted_keys) and len(max_vals) == len(sorted_keys): + sorted_keys = sorted(all_input_keys) + + min_values = {} + max_values = {} + + for scenario in self.scenarios: + min_mapping = self._extract_input_values(scenario, "min") or {} + max_mapping = self._extract_input_values(scenario, "max") or {} + + for key in sorted_keys: + if key not in min_values and key in min_mapping: + min_values[key] = min_mapping[key] + if key not in max_values and key in max_mapping: + max_values[key] = max_mapping[key] + + if len(min_values) == len(sorted_keys) and len(max_values) == len( + sorted_keys + ): break data = { - ("", "min"): [min_vals.get(k) for k in sorted_keys], - ("", "max"): [max_vals.get(k) for k in sorted_keys], + ("", "min"): [min_values.get(key) for key in sorted_keys], + ("", "max"): [max_values.get(key) for key in sorted_keys], } df = pd.DataFrame(data, index=sorted_keys) df.index.name = "input" df.columns = pd.MultiIndex.from_tuples(df.columns, names=["scenario", "field"]) return df + def _to_dataframe(self, columns: str = "user", **kwargs) -> pd.DataFrame: + """Build DataFrame with specified field for all scenarios.""" + if not isinstance(columns, str) or columns.strip() == "": + columns = "user" + return self._build_simple_dataframe(columns) + + def to_dataframe_per_scenario_fields( + self, fields_map: Dict["Any", List[str]] + ) -> pd.DataFrame: + """Build DataFrame where each scenario may have different fields.""" + return self._build_consolidated_dataframe(fields_map) + + def to_dataframe_defaults(self) -> pd.DataFrame: + """Build DataFrame of default values for each input per scenario.""" + return self._build_simple_dataframe("default") + + def to_dataframe_min_max(self) -> pd.DataFrame: + """Build DataFrame with min/max bounds (shared across scenarios).""" + return self._build_bounds_dataframe() + def from_dataframe(self, df): + """Import input values from DataFrame.""" if df is None or getattr(df, "empty", False): return + try: df = df.dropna(how="all") if df.empty: return - header_pos_list = self.first_non_empty_row_positions(df, 1) - if not header_pos_list: + + header_positions = self.first_non_empty_row_positions(df, 1) + if not header_positions: return - header_pos = header_pos_list[0] - header_row = df.iloc[header_pos].astype(str) - data = df.iloc[header_pos + 1 :].copy() - data.columns = header_row.values - if data.empty or len(data.columns) < 2: + + header_row_index = header_positions[0] + header_row = df.iloc[header_row_index].astype(str) + + # Extract data rows + data_df = df.iloc[header_row_index + 1 :].copy() + data_df.columns = header_row.values + + if data_df.empty or len(data_df.columns) < 2: return - input_col = data.columns[0] - inputs_series = data[input_col].astype(str).str.strip() - mask = inputs_series != "" - data = data.loc[mask] - inputs_series = inputs_series.loc[mask] - data.index = inputs_series - scenario_cols = [c for c in data.columns if c != input_col] - for col in scenario_cols: - scenario = self.resolve_scenario(col) + + # Process input data + input_column = data_df.columns[0] + input_keys = data_df[input_column].astype(str).str.strip() + + # Filter out empty input keys + valid_mask = input_keys != "" + data_df = data_df.loc[valid_mask] + input_keys = input_keys.loc[valid_mask] + data_df.index = input_keys + + # Process each scenario column + scenario_columns = [col for col in data_df.columns if col != input_column] + + for column_name in scenario_columns: + scenario = self.resolve_scenario(column_name) if scenario is None: logger.warning( "Could not find scenario for SLIDER_SETTINGS column label '%s'", - col, + column_name, ) continue - series = data[col] - - def _is_blank_val(v: Any) -> bool: - if v is None: - return True - if isinstance(v, float) and pd.isna(v): - return True - if isinstance(v, str) and v.strip().lower() in {"", "nan"}: - return True - return False - - updates = {k: v for k, v in series.items() if not _is_blank_val(v)} + + column_data = data_df[column_name] + + # Filter out blank values + updates = { + key: value + for key, value in column_data.items() + if not self._is_blank_value(value) + } + if not updates: continue try: @@ -305,20 +353,72 @@ def _is_blank_val(v: Any) -> bool: logger.warning( "Failed updating inputs for scenario '%s' from column '%s': %s", scenario.identifier(), - col, + column_name, e, ) finally: - try: - if ( - hasattr(scenario, "_inputs") - and scenario._inputs is not None - ): - scenario._inputs.log_warnings( - logger, - prefix=f"Inputs warning for '{scenario.identifier()}'", - ) - except Exception: - pass + self._log_scenario_input_warnings(scenario) + except Exception as e: logger.warning("Failed to parse simplified SLIDER_SETTINGS sheet: %s", e) + + def _is_blank_value(self, value: Any) -> bool: + """Check if a value should be considered blank/empty.""" + if value is None: + return True + if isinstance(value, float) and pd.isna(value): + return True + if isinstance(value, str) and value.strip().lower() in {"", "nan"}: + return True + return False + + def build_combined_dataframe( + self, include_defaults: bool = False, include_min_max: bool = False + ) -> pd.DataFrame: + """Build DataFrame with various field combinations based on flags.""" + if not self.scenarios: + return pd.DataFrame() + + # Determine what fields we need + fields = ["user"] + if include_defaults: + fields.append("default") + + if fields == ["user"]: + return self._build_simple_dataframe("user") + elif fields == ["default"]: + return self._build_simple_dataframe("default") + elif include_min_max and not include_defaults: + return self._build_user_with_bounds_dataframe() + elif include_min_max and include_defaults: + return self._build_full_combined_dataframe() + else: + field_map = {scenario: fields for scenario in self.scenarios} + return self._build_consolidated_dataframe(field_map) + + def _build_full_combined_dataframe(self) -> pd.DataFrame: + """Build DataFrame with user values, defaults, and min/max bounds.""" + try: + field_map = {scenario: ["user", "default"] for scenario in self.scenarios} + df_core = self._build_consolidated_dataframe(field_map) + df_bounds = self._build_bounds_dataframe() + + if not df_bounds.empty and not df_core.empty: + return pd.concat([df_bounds, df_core], axis=1) + elif not df_core.empty: + return df_core + else: + return df_bounds + except Exception: + pass + + def _log_scenario_input_warnings(self, scenario): + """Log any warnings from scenario inputs if available.""" + try: + if hasattr(scenario, "_inputs") and scenario._inputs is not None: + scenario._inputs.log_warnings( + logger, + prefix=f"Inputs warning for '{scenario.identifier()}'", + ) + except Exception: + pass diff --git a/src/pyetm/models/scenario_packer.py b/src/pyetm/models/scenario_packer.py index 8480cca..67eb08d 100644 --- a/src/pyetm/models/scenario_packer.py +++ b/src/pyetm/models/scenario_packer.py @@ -3,7 +3,7 @@ from pathlib import Path from os import PathLike from pydantic import BaseModel -from typing import Optional, Dict, Any, Sequence +from typing import Optional, Dict, Any, Sequence, List from xlsxwriter import Workbook from pyetm.models.packables.custom_curves_pack import CustomCurvesPack @@ -19,24 +19,111 @@ logger = logging.getLogger(__name__) +class ExportConfigResolver: + """Handles resolution of export configuration from various sources.""" + + @staticmethod + def resolve_boolean( + explicit_value: Optional[bool], config_value: Optional[bool], default: bool + ) -> bool: + """Resolve boolean value from explicit parameter, config, or default.""" + if explicit_value is not None: + return bool(explicit_value) + if config_value is not None: + return bool(config_value) + return default + + @staticmethod + def extract_from_main_sheet( + main_df: pd.DataFrame, scenarios: List[Scenario] + ) -> Optional[ExportConfig]: + """Extract export configuration from the first scenario column in main sheet.""" + if main_df.empty or not scenarios: + return None + + try: + helper_columns = {"description", "helper", "notes"} + candidate_series = None + + for col in main_df.columns: + name = str(col).strip().lower() + if name in helper_columns or name in {"", "nan"}: + continue + candidate_series = main_df[col] + break + + if candidate_series is None: + candidate_series = main_df.iloc[:, 0] + + return ExportConfigResolver._parse_config_from_series(candidate_series) + except Exception: + return None + + @staticmethod + def _parse_config_from_series(series: pd.Series) -> ExportConfig: + """Parse ExportConfig from a pandas Series (column from main sheet).""" + index_map = {str(idx).strip().lower(): idx for idx in series.index} + + def get_cell_value(name: str) -> Any: + key = name.strip().lower() + original_key = index_map.get(key) + return series.get(original_key) if original_key is not None else None + + def parse_bool(value: Any) -> Optional[bool]: + """Parse boolean from various formats.""" + if value is None or (isinstance(value, float) and pd.isna(value)): + return None + if isinstance(value, bool): + return value + if isinstance(value, (int, float)): + try: + return bool(int(value)) + except Exception: + return None + if isinstance(value, str): + normalized = value.strip().lower() + if normalized in {"true", "yes", "y", "1"}: + return True + if normalized in {"false", "no", "n", "0"}: + return False + return None + + def parse_carriers(value: Any) -> Optional[List[str]]: + """Parse comma-separated carrier list.""" + if not isinstance(value, str) or not value.strip(): + return None + return [carrier.strip() for carrier in value.split(",") if carrier.strip()] + + carriers_raw = get_cell_value("exports") or get_cell_value("output_carriers") + + return ExportConfig( + include_inputs=parse_bool(get_cell_value("inputs")), + include_sortables=parse_bool(get_cell_value("sortables")), + include_custom_curves=parse_bool(get_cell_value("custom_curves")), + include_gqueries=( + parse_bool(get_cell_value("gquery_results")) + or parse_bool(get_cell_value("gqueries")) + ), + inputs_defaults=parse_bool(get_cell_value("defaults")), + inputs_min_max=parse_bool(get_cell_value("min_max")), + output_carriers=parse_carriers(carriers_raw), + ) + + class ScenarioPacker(BaseModel): """ Packs one or multiple scenarios for export to dataframes or excel """ - # To avoid keeping all in memory, the packer only remembers which scenarios - # to pack what info for later - _custom_curves: "CustomCurvesPack" = CustomCurvesPack() - _inputs: "InputsPack" = InputsPack() - _sortables: "SortablePack" = SortablePack() - _output_curves: "OutputCurvesPack" = OutputCurvesPack() - - # Setting up a packer + # Pack collections + _custom_curves: CustomCurvesPack = CustomCurvesPack() + _inputs: InputsPack = InputsPack() + _sortables: SortablePack = SortablePack() + _output_curves: OutputCurvesPack = OutputCurvesPack() + # Scenario management methods def add(self, *scenarios): - """ - Shorthand method for adding all extractions for the scenario - """ + """Add scenarios to all packs.""" self.add_custom_curves(*scenarios) self.add_inputs(*scenarios) self.add_sortables(*scenarios) @@ -54,19 +141,15 @@ def add_sortables(self, *scenarios): def add_output_curves(self, *scenarios): self._output_curves.add(*scenarios) - # DataFrame outputs - def main_info(self) -> pd.DataFrame: """Create main info DataFrame by concatenating scenario dataframes.""" - if len(self._scenarios()) == 0: + scenarios = self._scenarios() + if not scenarios: return pd.DataFrame() - - return pd.concat( - [scenario.to_dataframe() for scenario in self._scenarios()], axis=1 - ) + return pd.concat([scenario.to_dataframe() for scenario in scenarios], axis=1) def inputs(self, columns="user") -> pd.DataFrame: - return self._inputs.to_dataframe(columns=columns) + return self._inputs._to_dataframe(columns=columns) def gquery_results(self, columns="future") -> pd.DataFrame: return QueryPack(scenarios=self._scenarios()).to_dataframe(columns=columns) @@ -85,568 +168,502 @@ def to_excel( path: str, *, carriers: Optional[Sequence[str]] = None, - include_inputs: bool | None = None, - include_sortables: bool | None = None, - include_custom_curves: bool | None = None, - include_gqueries: bool | None = None, - include_output_curves: bool | None = None, + include_inputs: Optional[bool] = None, + include_sortables: Optional[bool] = None, + include_custom_curves: Optional[bool] = None, + include_gqueries: Optional[bool] = None, + include_output_curves: Optional[bool] = None, ): - if len(self._scenarios()) == 0: + """Export scenarios to Excel file.""" + if not self._scenarios(): raise ValueError("Packer was empty, nothing to export") + global_config = self._get_global_export_config() + resolved_flags = self._resolve_export_flags( + global_config, + include_inputs, + include_sortables, + include_custom_curves, + include_gqueries, + include_output_curves, + ) + + # Create and populate workbook workbook = Workbook(path) + try: + self._add_main_sheet(workbook) + self._add_data_sheets(workbook, global_config, resolved_flags) + self._add_gqueries_sheet(workbook, resolved_flags["include_gqueries"]) + finally: + workbook.close() + + # Handle output curves separately + self._export_output_curves_if_needed( + path, carriers, resolved_flags["include_output_curves"], global_config + ) + + def _get_global_export_config(self) -> Optional[ExportConfig]: + """Get global export configuration from first scenario that has one.""" + for scenario in self._scenarios(): + config = getattr(scenario, "_export_config", None) + if config is not None: + return config + return None - # Main info sheet: enrich with metadata and friendly headers for Excel only - df_main = self._build_excel_main_dataframe() - if not df_main.empty: - df_main = self._sanitize_dataframe_for_excel(df_main) + def _resolve_export_flags( + self, + global_config: Optional[ExportConfig], + include_inputs: Optional[bool], + include_sortables: Optional[bool], + include_custom_curves: Optional[bool], + include_gqueries: Optional[bool], + include_output_curves: Optional[bool], + ) -> Dict[str, Any]: + """Resolve all export flags from parameters and configuration.""" + resolver = ExportConfigResolver() + + return { + "include_inputs": resolver.resolve_boolean( + include_inputs, + ( + getattr(global_config, "include_inputs", None) + if global_config + else None + ), + True, + ), + "include_sortables": resolver.resolve_boolean( + include_sortables, + ( + getattr(global_config, "include_sortables", None) + if global_config + else None + ), + False, + ), + "include_custom_curves": resolver.resolve_boolean( + include_custom_curves, + ( + getattr(global_config, "include_custom_curves", None) + if global_config + else None + ), + False, + ), + "include_gqueries": resolver.resolve_boolean( + include_gqueries, + ( + getattr(global_config, "include_gqueries", None) + if global_config + else None + ), + False, + ), + "include_output_curves": resolver.resolve_boolean( + include_output_curves, + ( + getattr(global_config, "output_carriers", None) is not None + if global_config + else None + ), + False, + ), + "inputs_defaults": ( + bool(getattr(global_config, "inputs_defaults", False)) + if global_config + else False + ), + "inputs_min_max": ( + bool(getattr(global_config, "inputs_min_max", False)) + if global_config + else False + ), + } + + def _add_main_sheet(self, workbook: Workbook): + """Add main scenario information sheet to workbook.""" + main_df = self._build_excel_main_dataframe() + if not main_df.empty: + sanitized_df = self._sanitize_dataframe_for_excel(main_df) add_frame( name="MAIN", - frame=df_main, + frame=sanitized_df, workbook=workbook, column_width=18, scenario_styling=True, ) - # Decide which packs to include using a single global config (applies to all scenarios) - packs: list[tuple[str, Any]] = [ - ("inputs", self._inputs), - ("sortables", self._sortables), - ("custom_curves", self._custom_curves), - ] + def _add_data_sheets( + self, + workbook: Workbook, + global_config: Optional[ExportConfig], + flags: Dict[str, Any], + ): + """Add data sheets (inputs, sortables, custom_curves) to workbook.""" + if flags["include_inputs"]: + self._add_inputs_sheet( + workbook, flags["inputs_defaults"], flags["inputs_min_max"] + ) - # Determine a global ExportConfig from the first scenario (if any) - scen_list = list(self._scenarios()) - global_cfg: ExportConfig | None = None - for s in scen_list: - cfg = getattr(s, "_export_config", None) - if cfg is not None: - global_cfg = cfg - break + if flags["include_sortables"]: + self._add_pack_sheet(workbook, self._sortables) - def choose_bool( - opt_flag: Optional[bool], cfg_val: Optional[bool], default: bool - ) -> bool: - if opt_flag is not None: - return bool(opt_flag) - if cfg_val is not None: - return bool(cfg_val) - return default + if flags["include_custom_curves"]: + self._add_pack_sheet(workbook, self._custom_curves) - include_inputs_final = choose_bool( - include_inputs, - getattr(global_cfg, "include_inputs", None) if global_cfg else None, - True, - ) - include_sortables_final = choose_bool( - include_sortables, - getattr(global_cfg, "include_sortables", None) if global_cfg else None, - False, - ) - include_custom_curves_final = choose_bool( - include_custom_curves, - getattr(global_cfg, "include_custom_curves", None) if global_cfg else None, - False, - ) - include_gqueries_final = choose_bool( - include_gqueries, - getattr(global_cfg, "include_gqueries", None) if global_cfg else None, - False, - ) + def _add_inputs_sheet( + self, workbook: Workbook, include_defaults: bool, include_min_max: bool + ): + """Add inputs sheet with proper field handling.""" + try: + df = self._inputs.build_combined_dataframe( + include_defaults=include_defaults, include_min_max=include_min_max + ) + if df is not None and not df.empty: + self._add_dataframe_to_workbook(workbook, self._inputs.sheet_name, df) + except Exception as e: + logger.warning("Failed to build inputs DataFrame: %s", e) + df = self._inputs._to_dataframe(columns="user") + if df is not None and not df.empty: + self._add_dataframe_to_workbook(workbook, self._inputs.sheet_name, df) + + def _add_pack_sheet(self, workbook: Workbook, pack): + """Add a pack's DataFrame to the workbook.""" + df = pack.to_dataframe() + if df is not None and not df.empty: + self._add_dataframe_to_workbook(workbook, pack.sheet_name, df) + + def _add_gqueries_sheet(self, workbook: Workbook, include_gqueries: bool): + """Add gqueries sheet if requested.""" + if not include_gqueries: + return + + gquery_pack = QueryPack(scenarios=self._scenarios()) + gqueries_df = gquery_pack.to_dataframe(columns="future") + if not gqueries_df.empty: + self._add_dataframe_to_workbook( + workbook, gquery_pack.output_sheet_name, gqueries_df + ) + + def _export_output_curves_if_needed( + self, + main_path: str, + carriers: Optional[Sequence[str]], + include_output_curves: bool, + global_config: Optional[ExportConfig], + ): + """Export output curves to separate file if needed.""" + if not include_output_curves: + return - inputs_defaults_final = ( - bool(getattr(global_cfg, "inputs_defaults", False)) if global_cfg else False + # Determine output file path + base_path = Path(main_path) + output_path = str( + base_path.with_name(f"{base_path.stem}_exports{base_path.suffix}") ) - inputs_min_max_final = ( - bool(getattr(global_cfg, "inputs_min_max", False)) if global_cfg else False + + # Determine carriers to export + chosen_carriers = list(carriers) if carriers else None + if chosen_carriers is None and global_config is not None: + config_carriers = getattr(global_config, "output_carriers", None) + chosen_carriers = list(config_carriers) if config_carriers else None + + try: + self._output_curves.to_excel_per_carrier(output_path, chosen_carriers) + except Exception as e: + logger.warning("Failed exporting output curves workbook: %s", e) + + def _add_dataframe_to_workbook( + self, workbook: Workbook, sheet_name: str, df: pd.DataFrame + ): + """Add a DataFrame to the workbook as a new sheet.""" + cleaned_df = df.fillna("").infer_objects(copy=False) + add_frame( + name=sheet_name, + frame=cleaned_df, + workbook=workbook, + column_width=18, + scenario_styling=True, ) - # Emit sheets based on global flags - for name, pack in packs: - if name == "inputs" and include_inputs_final: - try: - fields: list[str] = ["user"] - if inputs_defaults_final: - fields.append("default") - if inputs_min_max_final: - fields.append("__bounds__") - if fields == ["user"]: - df = self._inputs.to_dataframe(columns="user") - elif fields == ["min", "max"]: - df = self._inputs.to_dataframe_min_max() - elif fields == ["default"]: - df = self._inputs.to_dataframe_defaults() - elif fields == ["user", "default"]: - fm = {s: fields for s in pack.scenarios} - df = self._inputs.to_dataframe_per_scenario_fields(fm) - elif fields == ["user", "min", "max"]: - fm = {s: ["user"] for s in pack.scenarios} - df_user = self._inputs.to_dataframe_per_scenario_fields(fm) - df_bounds = self._inputs.to_dataframe_min_max() - try: - df = pd.concat([df_bounds, df_user], axis=1) - except Exception: - df = df_user - else: - mapped_fields = [f for f in fields if f != "__bounds__"] - fm = {s: mapped_fields for s in pack.scenarios} - df_core = self._inputs.to_dataframe_per_scenario_fields(fm) - if "__bounds__" in fields: - df_bounds = self._inputs.to_dataframe_min_max() - try: - df = pd.concat([df_bounds, df_core], axis=1) - except Exception: - df = df_core - else: - df = df_core - except Exception: - df = pack.to_dataframe() - elif name == "sortables" and include_sortables_final: - df = pack.to_dataframe() - elif name == "custom_curves" and include_custom_curves_final: - df = pack.to_dataframe() - else: - df = pd.DataFrame() + @classmethod + def from_excel(cls, xlsx_path: PathLike | str) -> "ScenarioPacker": + """Import scenarios from Excel file.""" + packer = cls() - if df is not None and not df.empty: - df_filled = df.fillna("").infer_objects(copy=False) - add_frame( - name=pack.sheet_name, - frame=df_filled, - workbook=workbook, - column_width=18, - scenario_styling=True, - ) + try: + excel_file = pd.ExcelFile(xlsx_path) + except Exception as e: + logger.warning("Could not open Excel file '%s': %s", xlsx_path, e) + return packer - if include_gqueries_final: - gq_pack = QueryPack(scenarios=self._scenarios()) - df_gq = gq_pack.to_dataframe(columns="future") - if not df_gq.empty: - add_frame( - name=gq_pack.output_sheet_name, - frame=df_gq.fillna("").infer_objects(copy=False), - workbook=workbook, - column_width=18, - scenario_styling=True, - ) + # Import main sheet and create scenarios + main_df = packer._import_main_sheet(excel_file) + if main_df is None: + return packer + + scenarios_by_column = packer._create_scenarios_from_main(main_df) + if not scenarios_by_column: + return packer + + packer._apply_export_configuration(main_df, scenarios_by_column) + packer._import_data_sheets(excel_file, main_df, scenarios_by_column) + + return packer + + def _import_main_sheet(self, excel_file: pd.ExcelFile) -> Optional[pd.DataFrame]: + """Import and validate the main sheet.""" + try: + main_df = excel_file.parse("MAIN", index_col=0) + if main_df is None or getattr(main_df, "empty", False): + return None + return main_df + except Exception as e: + logger.warning("Failed to parse MAIN sheet: %s", e) + return None - workbook.close() + def _create_scenarios_from_main(self, main_df: pd.DataFrame) -> Dict[str, Scenario]: + """Create scenarios from main sheet columns.""" + scenarios_by_column = {} + + for column_name in main_df.columns: + column_str = str(column_name) if column_name is not None else "" + if column_str.strip().lower() in {"description", "helper", "notes"}: + continue - # Export output curves to a separate workbook with one sheet per carrier - include_output_global = False - if include_output_curves is True: - include_output_global = True - elif include_output_curves is None: try: - include_output_global = bool( - getattr(global_cfg, "output_carriers", None) + scenario = self._create_scenario_from_column( + column_str, main_df[column_name] ) - except Exception: - include_output_global = False - if include_output_global: - base = Path(path) - oc_path = str(base.with_name(f"{base.stem}_exports{base.suffix}")) - chosen_carriers: Optional[Sequence[str]] = ( - list(carriers) if carriers else None - ) - if chosen_carriers is None and global_cfg is not None: - try: - chosen_carriers = ( - list(getattr(global_cfg, "output_carriers", None) or []) or None - ) - except Exception: - chosen_carriers = None - try: - self._output_curves.to_excel_per_carrier(oc_path, chosen_carriers) + if scenario is not None: + self.add(scenario) + scenarios_by_column[column_str] = scenario except Exception as e: - logger.warning("Failed exporting output curves workbook: %s", e) + logger.warning( + "Failed to set up scenario for column '%s': %s", column_name, e + ) + + return scenarios_by_column - def _coerce_int(self, v: Any) -> Optional[int]: - if v is None or (isinstance(v, float) and pd.isna(v)): + def _create_scenario_from_column( + self, column_name: str, column_data: pd.Series + ) -> Optional[Scenario]: + """Create a scenario from a main sheet column.""" + scenario_id = self._safe_get_int(column_data.get("scenario_id")) + area_code = column_data.get("area_code") + end_year = self._safe_get_int(column_data.get("end_year")) + scenario = self._load_or_create_scenario( + scenario_id, area_code, end_year, column_name + ) + if scenario is None: + return None + + metadata_updates = self._extract_metadata_updates(column_data) + self._apply_metadata_to_scenario(scenario, metadata_updates) + + return scenario + + def _safe_get_int(self, value: Any) -> Optional[int]: + """Safely convert value to integer.""" + if value is None or (isinstance(value, float) and pd.isna(value)): return None try: - return int(float(v)) + return int(float(value)) except (ValueError, TypeError): return None + def _safe_get_bool(self, value: Any) -> Optional[bool]: + """Safely convert value to boolean.""" + if value is None or (isinstance(value, float) and pd.isna(value)): + return None + if isinstance(value, bool): + return value + if isinstance(value, (int, float)): + try: + return bool(int(value)) + except Exception: + return None + if isinstance(value, str): + normalized = value.strip().lower() + if normalized in {"true", "yes", "y", "1"}: + return True + if normalized in {"false", "no", "n", "0"}: + return False + return None + def _load_or_create_scenario( self, - sid: Optional[int], + scenario_id: Optional[int], area_code: Any, end_year: Optional[int], - col_name: str, - ) -> Optional["Scenario"]: - scenario: Optional[Scenario] = None - if sid is not None: + column_name: str, + ) -> Optional[Scenario]: + """Load existing scenario or create new one.""" + if scenario_id is not None: try: - scenario = Scenario.load(sid) + return Scenario.load(scenario_id) except Exception as e: logger.warning( - "Failed to load scenario %s for column '%s': %s", sid, col_name, e + "Failed to load scenario %s for column '%s': %s", + scenario_id, + column_name, + e, ) - scenario = None - else: - if area_code and end_year is not None: - try: - scenario = Scenario.new(str(area_code), int(end_year)) - except Exception as e: - logger.warning( - "Failed to create scenario for column '%s' (area_code=%s, end_year=%s): %s", - col_name, - area_code, - end_year, - e, - ) - scenario = None - else: + + if area_code and end_year is not None: + try: + return Scenario.new(str(area_code), int(end_year)) + except Exception as e: logger.warning( - "MAIN column '%s' missing required fields for creation (area_code/end_year)", - col_name, + "Failed to create scenario for column '%s' (area_code=%s, end_year=%s): %s", + column_name, + area_code, + end_year, + e, ) - scenario = None - return scenario - def _collect_meta_updates( - self, - private: Optional[bool], - template: Optional[int], - source: Any, - title: Any, - ) -> Dict[str, Any]: - meta_updates: Dict[str, Any] = {} - if private is not None: - meta_updates["private"] = private - if template is not None: - meta_updates["template"] = template - if isinstance(source, str) and source.strip() != "": - meta_updates["source"] = source.strip() - if isinstance(title, str) and title.strip() != "": - meta_updates["title"] = title.strip() - return meta_updates - - def _apply_metadata( - self, scenario: "Scenario", meta_updates: Dict[str, Any] - ) -> None: - if not meta_updates: - return - try: - scenario.update_metadata(**meta_updates) - except Exception as e: - logger.warning( - "Failed to update metadata for '%s': %s", scenario.identifier(), e - ) + logger.warning( + "MAIN column '%s' missing required fields for creation (area_code/end_year)", + column_name, + ) + return None - def _extract_scenario_sheet_info( - self, main_df: pd.DataFrame - ) -> Dict[str, Dict[str, str]]: - scenario_sheets = {} + def _extract_metadata_updates(self, column_data: pd.Series) -> Dict[str, Any]: + """Extract metadata updates from column data.""" + metadata = {} - def _value_before_output(series: pd.Series, key: str): - seen_output = False - for label, val in zip(series.index, series.values): - lab = str(label).strip().lower() - if lab == "output": - seen_output = True - if lab == key and not seen_output: - return val - return None + private = self._safe_get_bool(column_data.get("private")) + if private is not None: + metadata["private"] = private - if isinstance(main_df, pd.Series): - # Single scenario - identifier = str(main_df.name) - short_name = main_df.get("short_name") - sortables_sheet = _value_before_output(main_df, "sortables") - custom_curves_sheet = _value_before_output(main_df, "custom_curves") - - scenario_sheets[identifier] = { - "short_name": short_name if pd.notna(short_name) else identifier, - "sortables": sortables_sheet if pd.notna(sortables_sheet) else None, - "custom_curves": ( - custom_curves_sheet if pd.notna(custom_curves_sheet) else None - ), - } - else: - # Multiple scenarios - for identifier in main_df.columns: - col_data = main_df[identifier] - short_name = col_data.get("short_name") - sortables_sheet = _value_before_output(col_data, "sortables") - custom_curves_sheet = _value_before_output(col_data, "custom_curves") - - scenario_sheets[str(identifier)] = { - "short_name": ( - short_name if pd.notna(short_name) else str(identifier) - ), - "sortables": sortables_sheet if pd.notna(sortables_sheet) else None, - "custom_curves": ( - custom_curves_sheet if pd.notna(custom_curves_sheet) else None - ), - } + template = self._safe_get_int(column_data.get("template")) + if template is not None: + metadata["template"] = template - return scenario_sheets + for field in ["source", "title"]: + value = column_data.get(field) + if isinstance(value, str) and value.strip(): + metadata[field] = value.strip() - def _process_single_scenario_sortables( - self, scenario: "Scenario", df: pd.DataFrame - ): - data = self._normalize_sheet( - df, - helper_names={"sortables", "hour", "index"}, - reset_index=True, - rename_map={"heat_network": "heat_network_lt"}, - ) - if data is None or data.empty: - return - try: - scenario.set_sortables_from_dataframe(data) - except Exception as e: - logger.warning( - "Failed processing sortables for '%s': %s", scenario.identifier(), e - ) - else: - try: - if hasattr(scenario, "_sortables") and scenario._sortables is not None: - scenario._sortables.log_warnings( - logger, - prefix=f"Sortables warning for '{scenario.identifier()}'", - ) - except Exception: - pass + return metadata - def _process_single_scenario_curves(self, scenario: "Scenario", df: pd.DataFrame): - data = self._normalize_sheet( - df, - helper_names={"curves", "custom_curves", "hour", "index"}, - reset_index=True, - ) - if data is None or data.empty: + def _apply_metadata_to_scenario(self, scenario: Scenario, metadata: Dict[str, Any]): + """Apply metadata updates to scenario.""" + if not metadata: return - # Build CustomCurves collection and apply - try: - curves = CustomCurves._from_dataframe(data, scenario_id=scenario.id) - curves.log_warnings( - logger, - prefix=f"Custom curves warning for '{scenario.identifier()}'", - ) - try: - validation = curves.validate_for_upload() - for key, collector in (validation or {}).items(): - for w in collector: - logger.warning( - "Custom curve validation for '%s' in '%s' [%s]: %s", - key, - scenario.identifier(), - getattr(w, "field", key), - getattr(w, "message", str(w)), - ) - except Exception: - pass - scenario.update_custom_curves(curves) + try: + scenario.update_metadata(**metadata) except Exception as e: - try: - if "curves" in locals(): - curves.log_warnings( - logger, - prefix=f"Custom curves warning for '{scenario.identifier()}'", - ) - except Exception: - pass logger.warning( - "Failed processing custom curves for '%s': %s", scenario.identifier(), e + "Failed to update metadata for '%s': %s", scenario.identifier(), e ) - @classmethod - def from_excel(cls, xlsx_path: PathLike | str) -> "ScenarioPacker": - packer = cls() - - try: - xls = pd.ExcelFile(xlsx_path) - except Exception as e: - logger.warning("Could not open Excel file '%s': %s", xlsx_path, e) - return packer - - # MAIN sheet + def _apply_export_configuration( + self, main_df: pd.DataFrame, scenarios_by_column: Dict[str, Scenario] + ): + """Apply export configuration to all scenarios.""" try: - main_df = xls.parse("MAIN", index_col=0) - except Exception as e: - logger.warning("Failed to parse MAIN sheet: %s", e) - return packer - - if main_df is None or getattr(main_df, "empty", False): - return packer - - # Build scenarios per MAIN column - scenarios_by_col: Dict[str, Scenario] = {} - for col in main_df.columns: - col_str = str(col) if col is not None else "" - if col_str.strip().lower() in {"description", "helper", "notes"}: - continue - try: - scenario = packer._setup_scenario_from_main_column( - str(col_str), main_df[col] - ) - except Exception as e: - logger.warning("Failed to set up scenario for column '%s': %s", col, e) - continue + config = ExportConfigResolver.extract_from_main_sheet( + main_df, list(scenarios_by_column.values()) + ) + if config is None: + return - if scenario is not None: - packer.add(scenario) - scenarios_by_col[str(col_str)] = scenario + for scenario in scenarios_by_column.values(): + try: + if hasattr(scenario, "set_export_config"): + scenario.set_export_config(config) + else: + setattr(scenario, "_export_config", config) + except Exception: + pass + except Exception: + pass - # Apply OUTPUT settings globally from the first scenario column, if present - try: - first_col_name: Optional[str] = next(iter(scenarios_by_col.keys()), None) - if first_col_name is not None: - col_data = main_df[first_col_name] - # case-insensitive row access - idx_map = {str(i).strip().lower(): i for i in col_data.index} - - def _cell_ci(name: str): - key = name.strip().lower() - src_key = idx_map.get(key) - if src_key is None: - return None - return col_data.get(src_key) - - def _bool(v) -> Optional[bool]: - if v is None: - return None - if isinstance(v, bool): - return v - try: - if isinstance(v, (int, float)) and not pd.isna(v): - return bool(int(v)) - except Exception: - pass - if isinstance(v, str): - s = v.strip().lower() - if s in {"true", "yes", "y", "1"}: - return True - if s in {"false", "no", "n", "0"}: - return False - return None + def _import_data_sheets( + self, + excel_file: pd.ExcelFile, + main_df: pd.DataFrame, + scenarios_by_column: Dict[str, Scenario], + ): + """Import all data sheets (inputs, gqueries, sortables, custom curves).""" + # Build short name mapping for inputs + short_name_map = self._build_short_name_mapping(main_df, scenarios_by_column) + self._import_inputs_sheet(excel_file, short_name_map) + self._import_gqueries_sheet(excel_file) + self._import_scenario_specific_sheets(excel_file, main_df, scenarios_by_column) + + def _build_short_name_mapping( + self, main_df: pd.DataFrame, scenarios_by_column: Dict[str, Scenario] + ) -> Dict[str, str]: + """Build mapping of scenario IDs to short names.""" + sheet_info = self._extract_scenario_sheet_info(main_df) + short_name_map = {} + + for column_name, scenario in scenarios_by_column.items(): + info = ( + sheet_info.get(column_name, {}) if isinstance(sheet_info, dict) else {} + ) + short_name = info.get("short_name") if isinstance(info, dict) else None - inc_inputs = _bool(_cell_ci("inputs")) - inc_gq = _bool(_cell_ci("gquery_results")) or _bool( - _cell_ci("gqueries") - ) - inc_sortables = _bool(_cell_ci("sortables")) - inc_curves = _bool(_cell_ci("custom_curves")) - inputs_defaults = _bool(_cell_ci("defaults")) - inputs_min_max = _bool(_cell_ci("min_max")) - carriers_raw = _cell_ci("exports") or _cell_ci("output_carriers") - carriers_list = None - if isinstance(carriers_raw, str) and carriers_raw.strip(): - carriers_list = [ - p.strip() for p in carriers_raw.split(",") if p.strip() - ] - - # Legacy column-based include_* support - legacy_inc_inputs = _cell_ci("include_inputs") - legacy_inc_sortables = _cell_ci("include_sortables") - legacy_inc_curves = _cell_ci("include_custom_curves") - legacy_inc_gq = _cell_ci("include_gqueries") - - cfg = ExportConfig( - include_inputs=( - _bool(legacy_inc_inputs) - if legacy_inc_inputs is not None - else inc_inputs - ), - include_sortables=( - _bool(legacy_inc_sortables) - if legacy_inc_sortables is not None - else inc_sortables - ), - include_custom_curves=( - _bool(legacy_inc_curves) - if legacy_inc_curves is not None - else inc_curves - ), - include_gqueries=( - _bool(legacy_inc_gq) if legacy_inc_gq is not None else inc_gq - ), - inputs_defaults=inputs_defaults, - inputs_min_max=inputs_min_max, - output_carriers=carriers_list, - ) + if short_name is None or ( + isinstance(short_name, float) and pd.isna(short_name) + ): + short_name = str(scenario.identifier()) - if any( - getattr(cfg, f) is not None - for f in ( - "include_inputs", - "include_sortables", - "include_custom_curves", - "include_gqueries", - "inputs_defaults", - "inputs_min_max", - "output_carriers", - ) - ): - for scenario in scenarios_by_col.values(): - try: - if hasattr(scenario, "set_export_config"): - scenario.set_export_config(cfg) - else: - setattr(scenario, "_export_config", cfg) - except Exception: - pass - except Exception: - pass + short_name_map[str(scenario.id)] = str(short_name) - if len(scenarios_by_col) == 0: - return packer + return short_name_map - # Extract per-scenario sheet info and short_name mapping - sheet_info = packer._extract_scenario_sheet_info(main_df) - short_name_map: Dict[str, str] = {} - for col_name, scenario in scenarios_by_col.items(): - info = sheet_info.get(col_name, {}) if isinstance(sheet_info, dict) else {} - short = info.get("short_name") if isinstance(info, dict) else None - if short is None or (isinstance(short, float) and pd.isna(short)): - short = str(scenario.identifier()) - short_name_map[str(scenario.id)] = str(short) - - # SLIDER_SETTINGS sheet - params_df = None + def _import_inputs_sheet( + self, excel_file: pd.ExcelFile, short_name_map: Dict[str, str] + ): + """Import inputs sheet - delegate to InputsPack.""" try: - params_df = xls.parse(InputsPack.sheet_name, header=None) - except Exception: - params_df = None - - if params_df is not None and not params_df.empty: - try: - packer._inputs.set_scenario_short_names(short_name_map) - packer._inputs.from_dataframe(params_df) - except Exception as e: - logger.warning("Failed to import SLIDER_SETTINGS: %s", e) + slider_df = excel_file.parse(InputsPack.sheet_name, header=None) + if slider_df is not None and not slider_df.empty: + self._inputs.set_scenario_short_names(short_name_map) + self._inputs.from_dataframe(slider_df) + except Exception as e: + logger.warning("Failed to import SLIDER_SETTINGS: %s", e) - # GQUERIES sheet - gq_df = None - for sheet in ("GQUERIES", QueryPack.sheet_name): - if sheet in xls.sheet_names: + def _import_gqueries_sheet(self, excel_file: pd.ExcelFile): + """Import gqueries sheet - delegate to QueryPack.""" + for sheet_name in ("GQUERIES", QueryPack.sheet_name): + if sheet_name in excel_file.sheet_names: try: - gq_df = xls.parse(sheet, header=None) - break - except Exception: - gq_df = None - if gq_df is not None and not gq_df.empty: - try: - qp = QueryPack(scenarios=packer._scenarios()) - qp.from_dataframe(gq_df) - except Exception as e: - logger.warning("Failed to import GQUERIES: %s", e) + gqueries_df = excel_file.parse(sheet_name, header=None) + if gqueries_df is not None and not gqueries_df.empty: + query_pack = QueryPack(scenarios=self._scenarios()) + query_pack.from_dataframe(gqueries_df) + return + except Exception as e: + logger.warning("Failed to import GQUERIES: %s", e) - # Sortables and Custom Curves - for col_name, scenario in scenarios_by_col.items(): - info = sheet_info.get(col_name, {}) if isinstance(sheet_info, dict) else {} + def _import_scenario_specific_sheets( + self, + excel_file: pd.ExcelFile, + main_df: pd.DataFrame, + scenarios_by_column: Dict[str, Scenario], + ): + """Import scenario-specific sortables and custom curves sheets.""" + sheet_info = self._extract_scenario_sheet_info(main_df) + for column_name, scenario in scenarios_by_column.items(): + info = ( + sheet_info.get(column_name, {}) if isinstance(sheet_info, dict) else {} + ) + + # Import sortables sortables_sheet = info.get("sortables") if isinstance(info, dict) else None - if isinstance(sortables_sheet, str) and sortables_sheet in xls.sheet_names: + if ( + isinstance(sortables_sheet, str) + and sortables_sheet in excel_file.sheet_names + ): try: - s_df = xls.parse(sortables_sheet, header=None) - self_ref = packer # clarity - self_ref._process_single_scenario_sortables(scenario, s_df) + sortables_df = excel_file.parse(sortables_sheet, header=None) + self._process_single_scenario_sortables(scenario, sortables_df) except Exception as e: logger.warning( "Failed to process SORTABLES sheet '%s' for '%s': %s", @@ -655,12 +672,12 @@ def _bool(v) -> Optional[bool]: e, ) + # Import custom curves curves_sheet = info.get("custom_curves") if isinstance(info, dict) else None - if isinstance(curves_sheet, str) and curves_sheet in xls.sheet_names: + if isinstance(curves_sheet, str) and curves_sheet in excel_file.sheet_names: try: - c_df = xls.parse(curves_sheet, header=None) - self_ref = packer - self_ref._process_single_scenario_curves(scenario, c_df) + curves_df = excel_file.parse(curves_sheet, header=None) + self._process_single_scenario_curves(scenario, curves_df) except Exception as e: logger.warning( "Failed to process CUSTOM_CURVES sheet '%s' for '%s': %s", @@ -669,51 +686,72 @@ def _bool(v) -> Optional[bool]: e, ) - return packer + def _scenarios(self) -> set[Scenario]: + """All scenarios we are packing info for across all packs.""" + all_scenarios = set() + for pack in self._get_all_packs(): + scenarios = getattr(pack, "scenarios", None) + if scenarios: + if isinstance(scenarios, set): + all_scenarios.update(scenarios) + else: + try: + all_scenarios.update(set(scenarios)) + except Exception: + pass + return all_scenarios - def _setup_scenario_from_main_column( - self, col_name: str, col_data: pd.Series - ) -> Optional[Scenario]: - scenario_id = ( - col_data.get("scenario_id") if isinstance(col_data, pd.Series) else None - ) - area_code = ( - col_data.get("area_code") if isinstance(col_data, pd.Series) else None - ) - end_year = ( - self._coerce_int(col_data.get("end_year")) - if isinstance(col_data, pd.Series) - else None - ) - private = ( - self._coerce_bool(col_data.get("private")) - if isinstance(col_data, pd.Series) - else None - ) - template = ( - self._coerce_int(col_data.get("template")) - if isinstance(col_data, pd.Series) - else None - ) - source = col_data.get("source") if isinstance(col_data, pd.Series) else None - title = col_data.get("title") if isinstance(col_data, pd.Series) else None - sid = self._coerce_int(scenario_id) - scenario = self._load_or_create_scenario(sid, area_code, end_year, col_name) + def _get_all_packs(self): + """Get all pack instances.""" + return [self._inputs, self._sortables, self._custom_curves, self._output_curves] - if scenario is None: - return None - meta_updates = self._collect_meta_updates(private, template, source, title) - self._apply_metadata(scenario, meta_updates) + def clear(self): + """Clear all scenarios from all packs.""" + for pack in self._get_all_packs(): + try: + pack.clear() + except Exception: + pass - return scenario + def remove_scenario(self, scenario: Scenario): + """Remove a specific scenario from all collections.""" + for pack in self._get_all_packs(): + try: + pack.discard(scenario) + except Exception: + pass + + def get_summary(self) -> Dict[str, Any]: + """Get a summary of what's in the packer.""" + summary = {"total_scenarios": len(self._scenarios())} + for pack in self._get_all_packs(): + try: + summary.update(pack.summary()) + except Exception: + pass + summary["scenario_ids"] = sorted( + [getattr(s, "id", None) for s in self._scenarios()] + ) + return summary + # Excel and DataFrame processing methods - refactored for consistency def _build_excel_main_dataframe(self) -> pd.DataFrame: - """Build a MAIN sheet DataFrame for Excel export using main_info().""" - df = self.main_info() - if df is None or df.empty: + """Build a MAIN sheet DataFrame for Excel export with proper ordering and labeling.""" + main_df = self.main_info() + if main_df is None or main_df.empty: return pd.DataFrame() - preferred = [ + # Apply preferred field ordering + ordered_df = self._apply_field_ordering(main_df) + + # Apply scenario column labeling + labeled_df = self._apply_scenario_column_labels(ordered_df) + + return labeled_df + + def _apply_field_ordering(self, df: pd.DataFrame) -> pd.DataFrame: + """Apply preferred field ordering to DataFrame rows.""" + preferred_fields = [ "title", "description", "scenario_id", @@ -729,140 +767,261 @@ def _build_excel_main_dataframe(self) -> pd.DataFrame: "created_at", "updated_at", ] - present = [k for k in preferred if k in df.index] - remaining = [k for k in df.index if k not in present] - ordered = present + remaining - df = df.reindex(index=ordered) - df.index.name = "scenario" - # Rename columns to use an identifier + present_fields = [field for field in preferred_fields if field in df.index] + remaining_fields = [field for field in df.index if field not in present_fields] + ordered_fields = present_fields + remaining_fields + + ordered_df = df.reindex(index=ordered_fields) + ordered_df.index.name = "scenario" + return ordered_df + + def _apply_scenario_column_labels(self, df: pd.DataFrame) -> pd.DataFrame: + """Apply human-readable labels to scenario columns.""" try: - scen_list = list(self._scenarios()) - rename_map: dict[Any, Any] = {} - by_str_id = {str(getattr(s, "id", "")): s for s in scen_list} - for col in list(df.columns): - matched_s = None - for s in scen_list: - if col == getattr(s, "id", None): - matched_s = s - break - if matched_s is None: - matched_s = by_str_id.get(str(col)) - if matched_s is not None: - try: - label = ( - matched_s.identifier() - if hasattr(matched_s, "identifier") - else getattr(matched_s, "title", None) - or getattr(matched_s, "id", col) - ) - except Exception: - label = getattr(matched_s, "title", None) or getattr( - matched_s, "id", col - ) - rename_map[col] = label - if rename_map: - df = df.rename(columns=rename_map) + scenarios = list(self._scenarios()) + column_rename_map = self._build_column_rename_map(scenarios, df.columns) + + if column_rename_map: + return df.rename(columns=column_rename_map) + return df + except Exception: + # If renaming fails, return original DataFrame + return df + + def _build_column_rename_map( + self, scenarios: List[Scenario], columns + ) -> Dict[Any, str]: + """Build mapping of column IDs to human-readable labels.""" + rename_map = {} + scenarios_by_id = {str(getattr(s, "id", "")): s for s in scenarios} + + for column in columns: + matched_scenario = self._find_matching_scenario( + column, scenarios, scenarios_by_id + ) + if matched_scenario is not None: + label = self._get_scenario_display_label(matched_scenario, column) + rename_map[column] = label + + return rename_map + + def _find_matching_scenario( + self, column, scenarios: List[Scenario], scenarios_by_id: Dict[str, Scenario] + ) -> Optional[Scenario]: + """Find scenario matching the given column identifier.""" + # Try exact ID match first + for scenario in scenarios: + if column == getattr(scenario, "id", None): + return scenario + + # Try string ID match as fallback + return scenarios_by_id.get(str(column)) + + def _get_scenario_display_label(self, scenario: Scenario, fallback_column) -> str: + """Get display label for scenario, with fallbacks.""" + try: + if hasattr(scenario, "identifier"): + return scenario.identifier() except Exception: pass - return df + + # Try title attribute + title = getattr(scenario, "title", None) + if title: + return title + + # Try ID attribute + scenario_id = getattr(scenario, "id", None) + if scenario_id: + return str(scenario_id) + + # Final fallback to original column + return str(fallback_column) def _sanitize_dataframe_for_excel(self, df: pd.DataFrame) -> pd.DataFrame: - """Convert DataFrame values into Excel-safe primitives (str/number/bool/None).""" - import datetime as _dt + """Convert DataFrame to Excel-compatible format.""" + if df is None or df.empty: + return pd.DataFrame() - def _safe(v: Any): - if v is None: - return "" - if isinstance(v, (str, int, float, bool)): - return v - if isinstance(v, (pd.Timestamp, _dt.datetime, _dt.date)): - try: - return str(v) - except Exception: - return "" + sanitized_df = df.copy() + + # Sanitize index and columns + sanitized_df.index = sanitized_df.index.map(self._sanitize_excel_value) + sanitized_df.columns = [ + self._sanitize_excel_value(col) for col in sanitized_df.columns + ] + + # Sanitize cell values + sanitized_df = sanitized_df.map(self._sanitize_excel_value) + + return sanitized_df + + def _sanitize_excel_value(self, value: Any) -> str: + """Convert a single value to Excel-safe format.""" + if value is None: + return "" + + if isinstance(value, (str, int, float, bool)): + return value + + # Handle datetime objects + if self._is_datetime_like(value): try: - return str(v) + return str(value) except Exception: return "" - out = df.copy() - out.index = out.index.map(lambda x: str(x) if x is not None else "") - out.columns = [str(c) if c is not None else "" for c in out.columns] - return out.map(_safe) + # Generic fallback + try: + return str(value) + except Exception: + return "" - def all_pack_data(self): - """Yield each sub-pack collection.""" - yield self._inputs - yield self._sortables - yield self._custom_curves - yield self._output_curves + def _is_datetime_like(self, value: Any) -> bool: + """Check if value is a datetime-like object.""" + import datetime as dt - def _scenarios(self) -> set["Scenario"]: - """All scenarios we are packing info for across all packs.""" - all_scenarios: set["Scenario"] = set() - for pack in self.all_pack_data(): - try: - items = getattr(pack, "scenarios", None) - if not items: - continue - if isinstance(items, set): - all_scenarios.update(items) - else: - try: - all_scenarios.update(set(items)) - except Exception: - pass - except Exception: - continue - return all_scenarios + return isinstance(value, (pd.Timestamp, dt.datetime, dt.date)) - def clear(self): - """Clear all scenarios from all packs.""" - for pack in self.all_pack_data(): - try: - pack.clear() - except Exception: - pass + def _extract_scenario_sheet_info( + self, main_df: pd.DataFrame + ) -> Dict[str, Dict[str, str]]: + """Extract sheet information for each scenario from main DataFrame.""" + if isinstance(main_df, pd.Series): + return self._extract_single_scenario_sheet_info(main_df) + else: + return self._extract_multiple_scenario_sheet_info(main_df) - def remove_scenario(self, scenario: "Scenario"): - """Remove a specific scenario from all collections.""" - for pack in self.all_pack_data(): - try: - pack.discard(scenario) - except Exception: - pass + def _extract_single_scenario_sheet_info( + self, series: pd.Series + ) -> Dict[str, Dict[str, str]]: + """Extract sheet info for single scenario (Series case).""" + identifier = str(series.name) + + return { + identifier: { + "short_name": self._get_safe_value(series, "short_name", identifier), + "sortables": self._get_value_before_output(series, "sortables"), + "custom_curves": self._get_value_before_output(series, "custom_curves"), + } + } - def get_summary(self) -> Dict[str, Any]: - """Get a summary of what's in the packer.""" - summary: Dict[str, Any] = {"total_scenarios": len(self._scenarios())} - for pack in self.all_pack_data(): - try: - summary.update(pack.summary()) - except Exception: - pass - summary["scenario_ids"] = sorted( - [getattr(s, "id", None) for s in self._scenarios()] - ) - return summary + def _extract_multiple_scenario_sheet_info( + self, df: pd.DataFrame + ) -> Dict[str, Dict[str, str]]: + """Extract sheet info for multiple scenarios (DataFrame case).""" + scenario_sheets = {} + + for identifier in df.columns: + column_data = df[identifier] + scenario_sheets[str(identifier)] = { + "short_name": self._get_safe_value( + column_data, "short_name", str(identifier) + ), + "sortables": self._get_value_before_output(column_data, "sortables"), + "custom_curves": self._get_value_before_output( + column_data, "custom_curves" + ), + } + + return scenario_sheets + + def _get_safe_value(self, series: pd.Series, key: str, default: str) -> str: + """Safely get value from series with default fallback.""" + value = series.get(key) + if pd.notna(value): + return str(value) + return default + + def _get_value_before_output(self, series: pd.Series, key: str) -> Optional[str]: + """Get value from series, but only if it appears before 'output' section.""" + seen_output = False + + for label, value in zip(series.index, series.values): + normalized_label = str(label).strip().lower() + + if normalized_label == "output": + seen_output = True + + if normalized_label == key and not seen_output: + return value if pd.notna(value) else None - def _first_non_empty_row_index(self, df: pd.DataFrame) -> Optional[int]: - if df is None: - return None - for idx, (_, row) in enumerate(df.iterrows()): - try: - if not row.isna().all(): - return idx - except Exception: - if any(v not in (None, "", float("nan")) for v in row): - return idx return None - def _is_empty_or_helper(self, col_name: Any, helper_names: set[str]) -> bool: - if not isinstance(col_name, str): - return True - name = col_name.strip().lower() - return name in (helper_names or set()) or name in {"", "nan"} + def _process_single_scenario_sortables(self, scenario: Scenario, df: pd.DataFrame): + """Process sortables data for a single scenario.""" + normalized_data = self._normalize_sheet( + df, + helper_names={"sortables", "hour", "index"}, + reset_index=True, + rename_map={"heat_network": "heat_network_lt"}, + ) + + if normalized_data is None or normalized_data.empty: + return + + self._apply_sortables_to_scenario(scenario, normalized_data) + + def _apply_sortables_to_scenario(self, scenario: Scenario, data: pd.DataFrame): + """Apply sortables data to scenario with error handling.""" + try: + scenario.set_sortables_from_dataframe(data) + self._log_scenario_warnings(scenario, "_sortables", "Sortables") + except Exception as e: + logger.warning( + "Failed processing sortables for '%s': %s", scenario.identifier(), e + ) + + def _process_single_scenario_curves(self, scenario: Scenario, df: pd.DataFrame): + """Process custom curves data for a single scenario.""" + normalized_data = self._normalize_sheet( + df, + helper_names={"curves", "custom_curves", "hour", "index"}, + reset_index=True, + ) + + if normalized_data is None or normalized_data.empty: + return + + self._apply_custom_curves_to_scenario(scenario, normalized_data) + + def _apply_custom_curves_to_scenario(self, scenario: Scenario, data: pd.DataFrame): + """Apply custom curves to scenario with validation and error handling.""" + try: + curves = CustomCurves._from_dataframe(data, scenario_id=scenario.id) + + # Log processing warnings + curves.log_warnings( + logger, + prefix=f"Custom curves warning for '{scenario.identifier()}'", + ) + + # Validate curves and log validation issues + self._validate_and_log_curves(curves, scenario) + + # Apply curves to scenario + scenario.update_custom_curves(curves) + + except Exception as e: + self._handle_curves_processing_error(scenario, e) + + def _validate_and_log_curves(self, curves: CustomCurves, scenario: Scenario): + """Validate curves and log any validation issues.""" + try: + validation_results = curves.validate_for_upload() + for key, issues in (validation_results or {}).items(): + for issue in issues: + logger.warning( + "Custom curve validation for '%s' in '%s' [%s]: %s", + key, + scenario.identifier(), + getattr(issue, "field", key), + getattr(issue, "message", str(issue)), + ) + except Exception: + # Validation errors are not critical, continue processing + pass def _normalize_sheet( self, @@ -872,27 +1031,30 @@ def _normalize_sheet( reset_index: bool = True, rename_map: Optional[Dict[str, str]] = None, ) -> pd.DataFrame: + """Normalize a sheet by finding headers and cleaning data.""" if df is None: return pd.DataFrame() + df = df.dropna(how="all") if df.empty: return df - header_pos = self._first_non_empty_row_index(df) - if header_pos is None: + header_position = self._find_first_non_empty_row(df) + if header_position is None: return pd.DataFrame() - header = df.iloc[header_pos].astype(str).map(lambda s: s.strip()) - data = df.iloc[header_pos + 1 :].copy() + # Extract header and data + header = df.iloc[header_position].astype(str).map(str.strip) + data = df.iloc[header_position + 1 :].copy() data.columns = header.values - keep_cols = [ - col - for col in data.columns - if not self._is_empty_or_helper(col, helper_names) + # Keep only non-helper columns + columns_to_keep = [ + col for col in data.columns if not self._is_helper_column(col, helper_names) ] - data = data[keep_cols] + data = data[columns_to_keep] + # Apply column renaming if provided if rename_map: data = data.rename(columns=rename_map) @@ -901,20 +1063,50 @@ def _normalize_sheet( return data - def _coerce_bool(self, v: Any) -> Optional[bool]: - if v is None or (isinstance(v, float) and pd.isna(v)): + def _handle_curves_processing_error(self, scenario: Scenario, error: Exception): + """Handle errors during curves processing.""" + logger.warning( + "Failed processing custom curves for '%s': %s", scenario.identifier(), error + ) + + def _log_scenario_warnings( + self, scenario: Scenario, attribute_name: str, context: str + ): + """Log warnings from scenario attributes if available.""" + try: + attribute = getattr(scenario, attribute_name, None) + if attribute is not None and hasattr(attribute, "log_warnings"): + attribute.log_warnings( + logger, + prefix=f"{context} warning for '{scenario.identifier()}'", + ) + except Exception: + # Warning logging failures should not interrupt processing + pass + + def _find_first_non_empty_row(self, df: pd.DataFrame) -> Optional[int]: + """Find the first row that contains non-empty data.""" + if df is None: return None - if isinstance(v, bool): - return v - if isinstance(v, (int, float)): + + for index, (_, row) in enumerate(df.iterrows()): try: - return bool(int(v)) + if not row.isna().all(): + return index except Exception: - return None - if isinstance(v, str): - s = v.strip().lower() - if s in {"true", "yes", "y", "1"}: - return True - if s in {"false", "no", "n", "0"}: - return False + # Fallback check for non-standard empty values + if any(value not in (None, "", float("nan")) for value in row): + return index + return None + + def _is_helper_column(self, column_name: Any, helper_names: set[str]) -> bool: + """Check if a column is a helper column that should be ignored.""" + if not isinstance(column_name, str): + return True + + normalized_name = column_name.strip().lower() + return normalized_name in (helper_names or set()) or normalized_name in { + "", + "nan", + } diff --git a/tests/models/conftest.py b/tests/models/conftest.py index cf58d3a..2ca58f9 100644 --- a/tests/models/conftest.py +++ b/tests/models/conftest.py @@ -15,6 +15,63 @@ # --- Scenario Fixtures --- # +@pytest.fixture +def multiple_scenarios(): + """Create multiple scenarios for testing""" + scenarios = [] + for i in range(3): + scenario = Mock(spec=Scenario) + scenario.id = f"scenario_{i}" + scenario.area_code = "nl2015" + scenario.end_year = 2050 + scenario.start_year = 2019 + scenario.identifier = Mock(return_value=scenario.id) + scenarios.append(scenario) + return scenarios + + +@pytest.fixture +def scenario_with_inputs(): + """Create a scenario with mock inputs""" + scenario = Mock(spec=Scenario) + scenario.id = "input_scenario" + scenario.area_code = "nl2015" + scenario.end_year = 2050 + scenario.start_year = 2019 + scenario.identifier = Mock(return_value=scenario.id) + + # Mock inputs + scenario.inputs = Mock() + mock_df = pd.DataFrame( + {"user": [1000, 2000], "unit": ["MW", "MW"], "default": [500, 800]}, + index=["wind_capacity", "solar_capacity"], + ) + mock_df.index.name = "input" + scenario.inputs.to_dataframe = Mock(return_value=mock_df) + + return scenario + + +@pytest.fixture +def scenario_with_queries(): + """Create a scenario with mock queries""" + scenario = Mock(spec=Scenario) + scenario.id = "query_scenario" + scenario.area_code = "nl2015" + scenario.end_year = 2050 + scenario.start_year = 2019 + scenario.identifier = Mock(return_value=scenario.id) + + # Mock queries + mock_results = pd.DataFrame( + {"future": [100, 200], "unit": ["MW", "GWh"]}, + index=["total_demand", "co2_emissions"], + ) + mock_results.index.name = "gquery" + scenario.results = Mock(return_value=mock_results) + scenario.queries_requested = Mock(return_value=True) + + return scenario @pytest.fixture diff --git a/tests/models/packables/test_inputs_pack.py b/tests/models/packables/test_inputs_pack.py index d7c6125..6729308 100644 --- a/tests/models/packables/test_inputs_pack.py +++ b/tests/models/packables/test_inputs_pack.py @@ -32,13 +32,15 @@ def test_key_for_prefers_short_name_and_fallbacks(): pack = InputsPack() pack.set_scenario_short_names({"1": "S1"}) - assert pack._key_for(s1) == "S1" # short name wins - assert pack._key_for(s2) == "id-2" # falls back to identifier + assert pack._get_scenario_display_key(s1) == "S1" # short name wins + assert pack._get_scenario_display_key(s2) == "id-2" # falls back to identifier s3 = make_scenario( 3, identifier=lambda: (_ for _ in ()).throw(RuntimeError("boom")) ) - assert pack._key_for(s3) == 3 # falls back to id when identifier fails + assert ( + pack._get_scenario_display_key(s3) == 3 + ) # falls back to id when identifier fails def test_resolve_scenario_by_short_identifier_and_numeric(): diff --git a/tests/models/test_scenario_packer.py b/tests/models/test_scenario_packer.py index 9ad20f0..ac54fea 100644 --- a/tests/models/test_scenario_packer.py +++ b/tests/models/test_scenario_packer.py @@ -4,14 +4,15 @@ import os from unittest.mock import Mock, patch from pyetm.models.scenario_packer import ( - CustomCurvesPack, - InputsPack, - OutputCurvesPack, - SortablePack, + ScenarioPacker, + ExportConfigResolver, ) -from pyetm.models import ScenarioPacker, Scenario +from pyetm.models.packables.custom_curves_pack import CustomCurvesPack from pyetm.models.packables.inputs_pack import InputsPack +from pyetm.models.packables.output_curves_pack import OutputCurvesPack +from pyetm.models.packables.sortable_pack import SortablePack from pyetm.models.packables.query_pack import QueryPack +from pyetm.models import Scenario from pyetm.models.custom_curves import CustomCurves @@ -33,8 +34,8 @@ def test_add_single_scenario(self, sample_scenario): packer.add(sample_scenario) # Should be added to all collections - for _key, collection in packer.model_dump(): - assert sample_scenario in collection + for pack in packer._get_all_packs(): + assert sample_scenario in pack.scenarios def test_add_multiple_scenarios(self, multiple_scenarios): """Test adding multiple scenarios at once""" @@ -42,10 +43,10 @@ def test_add_multiple_scenarios(self, multiple_scenarios): packer.add(*multiple_scenarios) # All scenarios should be in all collections - for _key, collection in packer.model_dump(): - assert len(collection) == 3 + for pack in packer._get_all_packs(): + assert len(pack.scenarios) == 3 for scenario in multiple_scenarios: - assert scenario in collection + assert scenario in pack.scenarios def test_add_custom_curves(self, sample_scenario): """Test adding scenarios to custom_curves only""" @@ -441,7 +442,9 @@ def test_to_excel_with_data(self, scenario_with_inputs): with ( patch.object(ScenarioPacker, "main_info", return_value=dummy_main_df), - patch.object(InputsPack, "to_dataframe", return_value=dummy_inputs_df), + patch.object( + InputsPack, "build_combined_dataframe", return_value=dummy_inputs_df + ), patch.object(ScenarioPacker, "gquery_results", return_value=dummy_empty_df), patch.object(SortablePack, "to_dataframe", return_value=dummy_empty_df), patch.object(CustomCurvesPack, "to_dataframe", return_value=dummy_empty_df), @@ -524,7 +527,7 @@ def test_clear(self, multiple_scenarios): # Verify all collections are empty assert len(packer._scenarios()) == 0 - for pack in packer.all_pack_data(): + for pack in packer._get_all_packs(): assert len(pack.scenarios) == 0 def test_remove_scenario(self, multiple_scenarios): @@ -591,27 +594,65 @@ def test_from_excel(self): ScenarioPacker.from_excel("tests/fixtures/my_input_excel.xlsx") +class TestExportConfigResolver: + """Test the ExportConfigResolver class""" + + def test_resolve_boolean_explicit_value(self): + """Test resolve_boolean with explicit value provided""" + assert ExportConfigResolver.resolve_boolean(True, False, False) == True + assert ExportConfigResolver.resolve_boolean(False, True, True) == False + assert ExportConfigResolver.resolve_boolean(None, True, False) == True + assert ExportConfigResolver.resolve_boolean(None, None, True) == True + + def test_parse_config_from_series(self): + """Test parsing config from pandas Series""" + series = pd.Series( + { + "inputs": "yes", + "sortables": "no", + "defaults": "1", + "min_max": "0", + "exports": "electricity,gas", + } + ) + + config = ExportConfigResolver._parse_config_from_series(series) + + assert config.include_inputs == True + assert config.include_sortables == False + assert config.inputs_defaults == True + assert config.inputs_min_max == False + assert config.output_carriers == ["electricity", "gas"] + + class TestScenarioPackerHelpers: - def test_first_non_empty_row_index(self): + def test_find_first_non_empty_row(self): + """Test _find_first_non_empty_row method""" packer = ScenarioPacker() - assert packer._first_non_empty_row_index(None) is None + assert packer._find_first_non_empty_row(None) is None empty = pd.DataFrame([[float("nan")], [float("nan")]]) - assert packer._first_non_empty_row_index(empty) is None + assert packer._find_first_non_empty_row(empty) is None - def test_is_empty_or_helper(self): + # Test with actual data + df = pd.DataFrame([[None, None], ["header", "value"], [1, 2]]) + assert packer._find_first_non_empty_row(df) == 1 + + def test_is_helper_column(self): + """Test _is_helper_column method""" packer = ScenarioPacker() helpers = {"sortables", "hour", "index"} - assert packer._is_empty_or_helper(123, helpers) is True - assert packer._is_empty_or_helper(" ", helpers) is True - assert packer._is_empty_or_helper("NaN", helpers) is True - assert packer._is_empty_or_helper("hour", helpers) is True - assert packer._is_empty_or_helper("value", helpers) is False + assert packer._is_helper_column(123, helpers) is True + assert packer._is_helper_column(" ", helpers) is True + assert packer._is_helper_column("NaN", helpers) is True + assert packer._is_helper_column("hour", helpers) is True + assert packer._is_helper_column("value", helpers) is False def test_normalize_sheet(self): + """Test _normalize_sheet method""" packer = ScenarioPacker() # None -> empty @@ -638,31 +679,34 @@ def test_normalize_sheet(self): assert list(norm.columns) == ["heat_network_lt", "value"] assert norm.index.tolist() == [2, 3] # original DataFrame indices kept - def test_coerce_bool(self): + def test_safe_get_bool(self): + """Test _safe_get_bool method""" packer = ScenarioPacker() na = float("nan") - assert packer._coerce_bool(None) is None - assert packer._coerce_bool(na) is None - assert packer._coerce_bool(True) is True - assert packer._coerce_bool(False) is False - assert packer._coerce_bool(1) is True - assert packer._coerce_bool(0.0) is False - assert packer._coerce_bool("yes") is True - assert packer._coerce_bool("No") is False - assert packer._coerce_bool("1") is True - assert packer._coerce_bool("maybe") is None - - def test_coerce_int(self): + assert packer._safe_get_bool(None) is None + assert packer._safe_get_bool(na) is None + assert packer._safe_get_bool(True) is True + assert packer._safe_get_bool(False) is False + assert packer._safe_get_bool(1) is True + assert packer._safe_get_bool(0.0) is False + assert packer._safe_get_bool("yes") is True + assert packer._safe_get_bool("No") is False + assert packer._safe_get_bool("1") is True + assert packer._safe_get_bool("maybe") is None + + def test_safe_get_int(self): + """Test _safe_get_int method""" packer = ScenarioPacker() na = float("nan") - assert packer._coerce_int(None) is None - assert packer._coerce_int(na) is None - assert packer._coerce_int(5) == 5 - assert packer._coerce_int(5.9) == 5 - assert packer._coerce_int("7") == 7 - assert packer._coerce_int("abc") is None + assert packer._safe_get_int(None) is None + assert packer._safe_get_int(na) is None + assert packer._safe_get_int(5) == 5 + assert packer._safe_get_int(5.9) == 5 + assert packer._safe_get_int("7") == 7 + assert packer._safe_get_int("abc") is None def test_load_or_create_scenario_load_new_and_failures(self, monkeypatch): + """Test _load_or_create_scenario method""" packer = ScenarioPacker() loaded = Mock(spec=Scenario) @@ -695,9 +739,16 @@ def boom2(_, __): # Missing fields -> None assert packer._load_or_create_scenario(None, None, None, "C") is None - def test_collect_and_apply_metadata(self): + def test_extract_metadata_updates_and_apply(self): + """Test metadata extraction and application""" packer = ScenarioPacker() - meta = packer._collect_meta_updates(True, 7, " src ", " title ") + + # Test extraction + series = pd.Series( + {"private": True, "template": 7, "source": " src ", "title": " title "} + ) + + meta = packer._extract_metadata_updates(series) assert meta == { "private": True, "template": 7, @@ -706,24 +757,31 @@ def test_collect_and_apply_metadata(self): } # empty strings trimmed out - meta = packer._collect_meta_updates(None, None, " ", "") - assert meta == {} + series_empty = pd.Series( + {"private": None, "template": None, "source": " ", "title": ""} + ) + meta_empty = packer._extract_metadata_updates(series_empty) + assert meta_empty == {} # apply updates scenario = Mock(spec=Scenario) - packer._apply_metadata(scenario, {"private": False}) + packer._apply_metadata_to_scenario(scenario, {"private": False}) scenario.update_metadata.assert_called_once_with(private=False) # swallow exceptions scenario.update_metadata.side_effect = RuntimeError("boom") - packer._apply_metadata(scenario, {"private": True}) # should not raise + packer._apply_metadata_to_scenario( + scenario, {"private": True} + ) # should not raise # no updates does nothing scenario.update_metadata.reset_mock() - packer._apply_metadata(scenario, {}) + scenario.update_metadata.side_effect = None + packer._apply_metadata_to_scenario(scenario, {}) scenario.update_metadata.assert_not_called() def test_extract_scenario_sheet_info_series_and_df(self): + """Test _extract_scenario_sheet_info method""" packer = ScenarioPacker() ser = pd.Series( @@ -753,6 +811,7 @@ def test_extract_scenario_sheet_info_series_and_df(self): assert out2["B"]["custom_curves"] == "C_B" def test_process_single_scenario_sortables(self): + """Test _process_single_scenario_sortables method""" packer = ScenarioPacker() scenario = Mock(spec=Scenario) @@ -773,6 +832,7 @@ def test_process_single_scenario_sortables(self): assert "hour" not in df_arg.columns def test_process_single_scenario_sortables_empty_after_normalize(self): + """Test _process_single_scenario_sortables with empty data after normalization""" packer = ScenarioPacker() scenario = Mock(spec=Scenario) @@ -788,6 +848,7 @@ def test_process_single_scenario_sortables_empty_after_normalize(self): scenario.set_sortables_from_dataframe.assert_not_called() def test_process_single_scenario_curves_success_and_error(self, monkeypatch): + """Test _process_single_scenario_curves method""" packer = ScenarioPacker() scenario = Mock(spec=Scenario) scenario.id = 999 @@ -819,6 +880,7 @@ def boom(_df, scenario_id): scenario.update_custom_curves.assert_not_called() def test_process_single_scenario_curves_empty_after_normalize(self): + """Test _process_single_scenario_curves with empty data after normalization""" packer = ScenarioPacker() scenario = Mock(spec=Scenario) scenario.id = 1 @@ -834,9 +896,10 @@ def test_process_single_scenario_curves_empty_after_normalize(self): scenario.update_custom_curves.assert_not_called() -class TestSetupScenarioFromMainColumn: +class TestCreateScenarioFromColumn: - def test_setup_scenario_from_main_column_loads_and_updates(self, monkeypatch): + def test_create_scenario_from_column_loads_and_updates(self, monkeypatch): + """Test _create_scenario_from_column method with loading existing scenario""" packer = ScenarioPacker() scenario = Mock(spec=Scenario) scenario.identifier = Mock(return_value="SID") @@ -854,11 +917,12 @@ def test_setup_scenario_from_main_column_loads_and_updates(self, monkeypatch): } ) - out = packer._setup_scenario_from_main_column("COL", ser) + out = packer._create_scenario_from_column("COL", ser) assert out is scenario scenario.update_metadata.assert_called_once() - def test_setup_scenario_from_main_column_creates(self, monkeypatch): + def test_create_scenario_from_column_creates(self, monkeypatch): + """Test _create_scenario_from_column method with creating new scenario""" packer = ScenarioPacker() scenario = Mock(spec=Scenario) scenario.identifier = Mock(return_value="NEW") @@ -874,21 +938,23 @@ def test_setup_scenario_from_main_column_creates(self, monkeypatch): } ) - out = packer._setup_scenario_from_main_column("COL", ser) + out = packer._create_scenario_from_column("COL", ser) assert out is scenario - def test_setup_scenario_from_main_column_returns_none_on_fail(self, monkeypatch): + def test_create_scenario_from_column_returns_none_on_fail(self, monkeypatch): + """Test _create_scenario_from_column returns None on failure""" packer = ScenarioPacker() monkeypatch.setattr( ScenarioPacker, "_load_or_create_scenario", lambda self, *a, **k: None ) ser = pd.Series({"scenario_id": None, "area_code": None, "end_year": None}) - assert packer._setup_scenario_from_main_column("COL", ser) is None + assert packer._create_scenario_from_column("COL", ser) is None class TestFromExcelDetailed: def test_from_excel_full_flow(self, tmp_path, monkeypatch): + """Test complete from_excel flow""" # Prepare MAIN with two scenarios: one load, one create main = pd.DataFrame( { @@ -977,6 +1043,7 @@ def test_from_excel_full_flow(self, tmp_path, monkeypatch): proc_curves.assert_called_once() def test_from_excel_missing_or_bad_main(self, tmp_path): + """Test from_excel with missing or bad main sheet""" packer = ScenarioPacker.from_excel(str(tmp_path / "bad.xlsx")) assert isinstance(packer, ScenarioPacker) assert len(packer._scenarios()) == 0 @@ -1000,6 +1067,7 @@ def test_from_excel_missing_or_bad_main(self, tmp_path): def test_from_excel_slider_settings_and_gqueries_errors( self, tmp_path, monkeypatch ): + """Test from_excel with errors in slider settings and gqueries import""" main = pd.DataFrame( { "S": { @@ -1045,6 +1113,7 @@ def test_from_excel_slider_settings_and_gqueries_errors( set_sn.assert_called_once() def test_from_excel_gqueries_sheet_name_fallback(self, tmp_path, monkeypatch): + """Test from_excel with gqueries sheet name fallback""" main = pd.DataFrame( {"S": {"scenario_id": None, "area_code": "nl2015", "end_year": 2050}} ) @@ -1070,6 +1139,7 @@ def test_from_excel_gqueries_sheet_name_fallback(self, tmp_path, monkeypatch): def test_from_excel_processing_sortables_and_curves_errors( self, tmp_path, monkeypatch ): + """Test from_excel with errors in processing sortables and curves""" main = pd.DataFrame( { "S": { @@ -1116,6 +1186,7 @@ def test_from_excel_processing_sortables_and_curves_errors( def test_from_excel_setup_column_exception_and_all_fail( self, tmp_path, monkeypatch ): + """Test from_excel with setup column exceptions""" # Two columns: first raises, second returns scenario main = pd.DataFrame( { @@ -1137,7 +1208,7 @@ def setup(col_name, col_ser): return s with patch.object( - ScenarioPacker, "_setup_scenario_from_main_column", side_effect=setup + ScenarioPacker, "_create_scenario_from_column", side_effect=setup ): packer = ScenarioPacker.from_excel(str(path)) assert any(s.id == "BID" for s in packer._scenarios()) @@ -1145,7 +1216,7 @@ def setup(col_name, col_ser): # All columns fail -> 0 scenarios, early return with patch.object( ScenarioPacker, - "_setup_scenario_from_main_column", + "_create_scenario_from_column", side_effect=RuntimeError("e"), ): packer2 = ScenarioPacker.from_excel(str(path)) @@ -1154,6 +1225,7 @@ def setup(col_name, col_ser): def test_from_excel_missing_slider_settings_sheet_parse_error( self, tmp_path, monkeypatch ): + """Test from_excel with missing slider settings sheet""" main = pd.DataFrame( {"S": {"scenario_id": None, "area_code": "nl2015", "end_year": 2050}} ) @@ -1169,6 +1241,7 @@ def test_from_excel_missing_slider_settings_sheet_parse_error( assert s_created in packer._scenarios() def test_from_excel_gqueries_parse_raises(self, tmp_path, monkeypatch): + """Test from_excel with gqueries parse error""" main = pd.DataFrame( {"S": {"scenario_id": None, "area_code": "nl2015", "end_year": 2050}} ) @@ -1194,3 +1267,68 @@ def parse_proxy(self, sheet_name, *a, **k): with patch.object(pd.ExcelFile, "parse", parse_proxy): packer = ScenarioPacker.from_excel(str(path)) assert s_created in packer._scenarios() + + +class TestInputsPackIntegration: + """Test integration with the new InputsPack.build_combined_dataframe method""" + + def test_inputs_pack_build_combined_dataframe_called(self, sample_scenario): + """Test that to_excel calls the new build_combined_dataframe method""" + packer = ScenarioPacker() + packer.add(sample_scenario) + + sample_scenario.to_dataframe = Mock( + return_value=pd.DataFrame({sample_scenario.id: ["test"]}, index=["row"]) + ) + + with ( + patch.object(InputsPack, "build_combined_dataframe") as mock_build, + patch("xlsxwriter.Workbook") as mock_workbook_class, + ): + mock_build.return_value = pd.DataFrame({"test": [1]}, index=["input1"]) + mock_workbook = Mock() + mock_workbook_class.return_value = mock_workbook + + packer.to_excel("test.xlsx", include_inputs=True) + + # Verify the new method was called with correct parameters + mock_build.assert_called_once_with( + include_defaults=False, include_min_max=False + ) + + def test_inputs_pack_build_combined_dataframe_with_flags(self, sample_scenario): + """Test that flags are passed correctly to build_combined_dataframe""" + packer = ScenarioPacker() + packer.add(sample_scenario) + + sample_scenario.to_dataframe = Mock( + return_value=pd.DataFrame({sample_scenario.id: ["test"]}, index=["row"]) + ) + + # Mock a global config that sets inputs defaults and min_max + mock_config = Mock() + mock_config.inputs_defaults = True + mock_config.inputs_min_max = True + mock_config.include_inputs = True + mock_config.include_sortables = False + mock_config.include_custom_curves = False + mock_config.include_gqueries = False + mock_config.output_carriers = None + + with ( + patch.object(InputsPack, "build_combined_dataframe") as mock_build, + patch.object( + ScenarioPacker, "_get_global_export_config", return_value=mock_config + ), + patch("xlsxwriter.Workbook") as mock_workbook_class, + ): + mock_build.return_value = pd.DataFrame({"test": [1]}, index=["input1"]) + mock_workbook = Mock() + mock_workbook_class.return_value = mock_workbook + + packer.to_excel("test.xlsx") + + # Verify the method was called with the config flags + mock_build.assert_called_once_with( + include_defaults=True, include_min_max=True + ) From 4e826e837f59be173dbf5bdf8769d894af45d5d0 Mon Sep 17 00:00:00 2001 From: louispt1 <81332401+louispt1@users.noreply.github.com> Date: Fri, 15 Aug 2025 17:42:33 +0200 Subject: [PATCH 14/19] Packer tests, updated format, .env * Updated tests * Added fetching a scenario directly in the Jupyter notebook to the example * Convert from yml settings to .env * Separated inputs and outputs into their own folders at root --- .gitignore | 5 +- README.md | 47 +- examples/create_or_query_scenarios.ipynb | 13 +- examples/example.config.env | 36 + examples/example.config.yml | 40 - {examples => inputs}/example_input_excel.xlsx | Bin poetry.lock | 4 +- pyproject.toml | 55 +- src/pyetm/config/settings.py | 89 +- src/pyetm/models/base.py | 1 - src/pyetm/models/custom_curves.py | 9 +- src/pyetm/models/scenario.py | 14 +- src/pyetm/models/scenario_packer.py | 35 +- src/pyetm/models/scenarios.py | 13 +- src/pyetm/models/sortables.py | 1 - src/pyetm/utils/paths.py | 87 ++ tests/conftest.py | 2 +- tests/models/conftest.py | 36 + tests/models/packables/test_inputs_pack.py | 547 +++++++++- .../packables/test_output_curves_pack.py | 330 +++++++ tests/models/test_custom_curves.py | 224 +++++ tests/models/test_scenario_packer.py | 347 +++++++ tests/test_settings.py | 266 +++-- tests/utils/test_excel.py | 935 +++++++++++++++++- tests/utils/test_pyetm_paths.py | 326 ++++++ 25 files changed, 3263 insertions(+), 199 deletions(-) create mode 100644 examples/example.config.env delete mode 100644 examples/example.config.yml rename {examples => inputs}/example_input_excel.xlsx (100%) create mode 100644 src/pyetm/utils/paths.py create mode 100644 tests/utils/test_pyetm_paths.py diff --git a/.gitignore b/.gitignore index 20a694b..7a2aa9f 100644 --- a/.gitignore +++ b/.gitignore @@ -18,5 +18,6 @@ import_graph.svg tmp/ *.xlsx -# Keep the example input -!examples/example_input_excel.xlsx +# Keep the examples +!inputs/example_input_excel.xlsx +!examples/example.config.env diff --git a/README.md b/README.md index b88d4b1..e28284b 100644 --- a/README.md +++ b/README.md @@ -80,7 +80,7 @@ If you want development dependencies (testing, linting, etc.) then append the #### How to use the environment: You can either: -- Run commands inside Poetry’s environment: +- Run commands inside Poetry's environment: ```bash poetry run pytest poetry run pyetm @@ -97,25 +97,40 @@ You can either: ## Configuring Your Settings -You can configure your API token and base URL either with a **config.yml** file or environment variables. You can now simply set an `environment` and the base URL will be inferred for you. +You can configure your API token and base URL either with a **config.env** file or environment variables. You can simply set an `environment` and the base URL will be inferred for you. -### Option 1: `config.yml` -1. Duplicate the example file (`examples/example.config.yml`) and rename it to `config.yml`. -2. Edit `config.yml`: - - **etm_api_token**: Your ETM API token (overridden by `$ETM_API_TOKEN` if set). - - **environment**: pro (default), beta, local, or a stable tag like `2025-01`. When set, `base_url` is inferred automatically. - - (optional) **base_url**: API base URL (overridden by `$BASE_URL` if set). If both `environment` and `base_url` are set, `base_url` wins. - Examples if you need a direct override: - - `https://engine.energytransitionmodel.com/api/v3` (pro) - - `https://beta.engine.energytransitionmodel.com/api/v3` (beta) - - `https://2025-01.engine.energytransitionmodel.com/api/v3` (stable tag) - - **proxy_servers**: (Optional) HTTP/HTTPS proxy URLs. - - **csv_separator** and **decimal_separator**: Defaults are `,` and `.`. +### Option 1: `config.env` (Recommended) +1. Copy the example file (`example.config.env`) and rename it to `config.env`. +2. Edit `config.env`: + ```bash + # Your ETM API token (required) + ETM_API_TOKEN=your.token.here -Place `config.yml` in the project root (`pyetm/` folder). + # Environment (default: pro) + ENVIRONMENT=pro + + # Optional: Override base URL directly + # BASE_URL=https://engine.energytransitionmodel.com/api/v3 + + # Optional: Proxy settings + # PROXY_SERVERS_HTTP=http://user:pass@proxy.example.com:8080 + # PROXY_SERVERS_HTTPS=http://user:pass@secureproxy.example.com:8080 + + # CSV settings (optional) + CSV_SEPARATOR=, + DECIMAL_SEPARATOR=. + ``` + +Place `config.env` in the project root (`pyetm/` folder). + +**Environment Options:** +- `pro` (default): Production environment +- `beta`: Staging environment +- `local`: Local development environment +- `YYYY-MM`: Stable tagged environment (e.g., `2025-01`) ### Option 2: Environment Variables -If you prefer, set these environment variables: +If you prefer, set these environment variables directly: ```bash ETM_API_TOKEN= ENVIRONMENT= diff --git a/examples/create_or_query_scenarios.ipynb b/examples/create_or_query_scenarios.ipynb index 57aa529..8ca6790 100644 --- a/examples/create_or_query_scenarios.ipynb +++ b/examples/create_or_query_scenarios.ipynb @@ -27,11 +27,11 @@ "id": "2884d014", "metadata": {}, "source": [ - "For the purposes of this demonstration workbook, we will use the pre-filled template 'my_input_excel.xlsx' which demonstrates a few of the possibilities afforded by the pyetm package. If it's your first time using the tool, have a look at the excel to get a sense of the structure.\n", + "For the purposes of this demonstration workbook, we will use the pre-filled template 'example_input_excel.xlsx' which demonstrates a few of the possibilities afforded by the pyetm package. If it's your first time using the tool, have a look at the excel to get a sense of the structure. The input excel is available in the /inputs folder. In pyetm, by default files will be read from the /inputs folder and written to the /outputs folder.\n", "\n", "In the example, there are two scenarios, with short names scen_a and scen_b. You can use short names in the slider_settings sheet to specify which inputs belong to which scenario. Because scen_b has no scenario_id, it is being created. It will be created with all the metadata included in the sheet, plus any of the inputs under the column with its short_name and any sortables and curves specified in the sheets named beside the sortables and custom_curves rows. The same goes for scen_a, but because it has a scenario_id (1357395) that scenario will be loaded, and then updated with anything as set in the excel.\n", "\n", - "**TODO**: Figure out how to manage the fact that for this example whatever scenario 1357395 is will be constantly updated etc by everyone who wants to try running this script on pro/beta. At the moment its just a local scenario." + "The example scenario ids are scenarios on pro. It's recommended to change the scenario_ids in the example and experiment with scenarios you own." ] }, { @@ -42,9 +42,14 @@ "outputs": [], "source": [ "from pyetm.models.scenarios import Scenarios\n", + "from pyetm.models.scenario import Scenario\n", + "\n", "\n", "scenarios = Scenarios.from_excel(\"example_input_excel.xlsx\")\n", - "#scenario_a = Scenario.load(123456789) #TODO: Also load a scenario and include it in the array" + "\n", + "# Here we're also loading a scenario directly from the API and adding it to the scenarios loaded/created via the excel\n", + "scenario_a = Scenario.load(1357691)\n", + "scenarios.add(scenario_a)" ] }, { @@ -84,7 +89,7 @@ "source": [ "# Inputs\n", "for scenario in scenarios:\n", - " inputs = scenario.inputs.to_dataframe(columns=[\"user\", \"default\", \"min\", \"max\"]).head(20)\n", + " inputs = scenario.inputs.to_dataframe(columns=[\"user\", \"default\", \"min\", \"max\"]).head(15)\n", " print(inputs)\n", " print(\"\")" ] diff --git a/examples/example.config.env b/examples/example.config.env new file mode 100644 index 0000000..951bebd --- /dev/null +++ b/examples/example.config.env @@ -0,0 +1,36 @@ +# ETM API Configuration +# Copy this file to .env and update with your personal settings +# Never commit your .env file to version control! + +# Your personal ETM API Token (REQUIRED) +# Get your token from: https://docs.energytransitionmodel.com/api/authentication +# Format: etm_ or etm_beta_ +ETM_API_TOKEN=your.token.here + +# ETM Environment (default: pro) +# Options: pro, beta, local, or stable tags like 2025-01 +ENVIRONMENT=pro + +# Override API base URL (optional - will be inferred from ENVIRONMENT if not set) +# Examples: +# BASE_URL=https://engine.energytransitionmodel.com/api/v3 +# BASE_URL=https://beta.engine.energytransitionmodel.com/api/v3 +# BASE_URL=http://localhost:3000/api/v3 +# BASE_URL=https://2025-01.engine.energytransitionmodel.com/api/v3 +# BASE_URL= + +# Logging level (default: INFO) +# Options: DEBUG, INFO, WARNING, ERROR, CRITICAL +LOG_LEVEL=INFO + +# Proxy Settings (optional) +# Never commit authenticated proxy URLs to version control! +# PROXY_SERVERS_HTTP=http://user:pass@proxy.example.com:8080 +# PROXY_SERVERS_HTTPS=http://user:pass@secureproxy.example.com:8080 + +# CSV File Settings +# CSV separator character (default: ,) +CSV_SEPARATOR=, + +# Decimal separator character (default: .) +DECIMAL_SEPARATOR=. diff --git a/examples/example.config.yml b/examples/example.config.yml deleted file mode 100644 index 23a9221..0000000 --- a/examples/example.config.yml +++ /dev/null @@ -1,40 +0,0 @@ -# To update this file with your personal settings, please duplicate this file -# and name it 'config.yml'. This way your personal tokens will be safe. -# Store the config.yml file in the root of the directory (pyetm/config.yml). - -# Paste your personal ETM API Token in this field. Never push this to GitHub! -# will be overridden by $ETM_API_TOKEN if you set that in env. -# The same token will work for beta and pro environments, but if you are interacting with beta or local, -# you will need the correct token for that environment. -# For more information, see: https://docs.energytransitionmodel.com/api/authentication#tokens-are-environment-specific -# -etm_api_token: your.token.here - -# Select the environment; base_url will be inferred automatically if set. -# Supported: pro (default), beta, local, or a stable tag like 2025-01 -environment: pro - - -# Override the API base URL - here you can set which environment of the ETM you want to interact with. -# Options include the default (pro), https://2025-01.engine.energytransitionmodel.com/api/v3 (a stable version) or -# https://beta.engine.energytransitionmodel.com/api/v3 (the staging environment), or http://localhost:3000/api/v3 -# (your local environment). -# For more information, see: https://docs.energytransitionmodel.com/api/intro#environments -# -# Optional override: specify base_url directly instead of using 'environment'. E.g. -# base_url: https://engine.energytransitionmodel.com/api/v3 - -#TODO: Setup so the below is actually used -# URLs of your proxy server addresses (replace the examples below by your own settings) -# Never push authenticated servers (including user name and password) to Github! -proxy_servers: - # http: http://user:pass@proxy.sample.com:8080 - # https: http://user:pass@secureproxy.sample.com:8080 - -# The separator your CSV files are using. The default is ',', but many European computers -# export CSV with a ';' as separator from Excel instead. -csv_separator: ',' - -# The decimal separator your CSV files are using. The default is '.', but depending on the -# national conventions, comma could be used as a decimal seperator instead. -decimal_seperator: '.' diff --git a/examples/example_input_excel.xlsx b/inputs/example_input_excel.xlsx similarity index 100% rename from examples/example_input_excel.xlsx rename to inputs/example_input_excel.xlsx diff --git a/poetry.lock b/poetry.lock index 19a8b5d..8751606 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 2.1.4 and should not be changed by hand. +# This file is automatically @generated by Poetry 2.1.1 and should not be changed by hand. [[package]] name = "annotated-types" @@ -3033,4 +3033,4 @@ files = [ [metadata] lock-version = "2.1" python-versions = ">=3.12,<4.0" -content-hash = "abe3b5271081c3ad44b715ed68207041ce87d3e9fee9512f9c14d93248e21a5d" +content-hash = "043e8657b19858523c1ca7580fc1000f460b8a897b3f8cf041814af49e6bc7ba" diff --git a/pyproject.toml b/pyproject.toml index aa14cfe..74b0cc7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -2,29 +2,43 @@ requires = ["poetry-core>=1.0.0"] build-backend = "poetry.core.masonry.api" -[tool.poetry] + +[project] name = "pyetm" version = "2.0" -description = "A Python package for energy transition modeling." -authors = ["Your Name "] -license = "MIT" +description = "Python-ETM Connector" readme = "README.md" -homepage = "https://github.com/quintel/pyetm" -repository = "https://github.com/quintel/pyetm" -documentation = "https://docs.energytransitionmodel.com/main/pyetm/introduction" -keywords = ["energy", "transition", "modeling", "api"] +license = { text = "MIT" } +authors = [ + { name = "Nora Schinkel", email = "nora.schinkel@quintel.com" }, + { name = "Louis Parkes-Talbo", email = "louis.parkestalbot@quintel.com" } +] +keywords = ["energy", "transition", "modeling", "api", "ETM"] +requires-python = ">=3.12,<4.0" + +dependencies = [ + "pydantic", + "pandas", + "requests", + "python-dotenv", + "pyyaml", + "pydantic-settings", + "xlsxwriter", + "openpyxl" +] + +[project.scripts] +pyetm = "pyetm.__main__:main" + +[project.urls] +"Repository" = "https://github.com/quintel/pyetm" +"Documentation" = "https://docs.energytransitionmodel.com/main/pyetm/introduction" +"Issue tracker" = "https://github.com/quintel/pyetm/issues" + +[tool.poetry] packages = [{ include = "pyetm", from = "src" }] +include = ["LICENSE"] -[tool.poetry.dependencies] -python = ">=3.12,<4.0" -pydantic = "*" -pandas = "*" -requests = "*" -python-dotenv = "*" -pyyaml = "*" -pydantic-settings = "*" -xlsxwriter = "*" -openpyxl = "*" [tool.poetry.group.dev.dependencies] pytest = "*" @@ -35,12 +49,7 @@ notebook = "*" pytest-cov = "*" pydeps = "*" -[tool.poetry.scripts] -pyetm = "pyetm.__main__:main" -[tool.poetry.urls] -"Issue tracker" = "https://github.com/quintel/pyetm/issues" -"Documentation" = "https://docs.energytransitionmodel.com/main/pyetm/introduction" [tool.pytest.ini_options] addopts = "--cov=pyetm --cov-report=term-missing" diff --git a/src/pyetm/config/settings.py b/src/pyetm/config/settings.py index a04ed36..34d36b5 100644 --- a/src/pyetm/config/settings.py +++ b/src/pyetm/config/settings.py @@ -1,32 +1,31 @@ from pathlib import Path import re -import yaml, os from typing import Optional, ClassVar, List, Annotated from pydantic import Field, ValidationError, HttpUrl, field_validator from pydantic_settings import BaseSettings, SettingsConfigDict PROJECT_ROOT = Path(__file__).resolve().parents[3] -CONFIG_FILE = PROJECT_ROOT / "config.yml" +ENV_FILE = PROJECT_ROOT / "config.env" class AppConfig(BaseSettings): """ - Application configuration loaded from YAML. + Application configuration loaded from .env file and environment variables. """ etm_api_token: Annotated[ str, Field( ..., - description="Your ETM API token: must be either `etm_` or `etm_beta_`. If not set please set $ETM_API_TOKEN or config.yml:etm_api_token", + description="Your ETM API token: must be either `etm_` or `etm_beta_`", ), ] - base_url: HttpUrl = Field( - "https://engine.energytransitionmodel.com/api/v3", - description="Base URL for the ETM API", + base_url: Optional[HttpUrl] = Field( + None, + description="Base URL for the ETM API (will be inferred from environment if not provided)", ) environment: Optional[str] = Field( - None, + "pro", description=( "ETM environment to target. One of: 'pro' (default), 'beta', 'local', or a stable tag 'YYYY-MM'. " "When set and base_url is not provided, base_url will be inferred." @@ -37,12 +36,40 @@ class AppConfig(BaseSettings): description="App logging level", ) + proxy_servers_http: Optional[str] = Field( + None, + description="HTTP proxy server URL", + ) + proxy_servers_https: Optional[str] = Field( + None, + description="HTTPS proxy server URL", + ) + csv_separator: str = Field( + ",", + description="CSV file separator character", + ) + decimal_separator: str = Field( + ".", + description="Decimal separator character", + ) + model_config: ClassVar[SettingsConfigDict] = SettingsConfigDict( - env_file=None, extra="ignore", case_sensitive=False + case_sensitive=False, + extra="ignore", ) temp_folder: Optional[Path] = PROJECT_ROOT / "tmp" + def __init__(self, **values): + """ + This ensures tests can monkeypatch `pyetm.config.settings.ENV_FILE` + """ + super().__init__( + _env_file=ENV_FILE, + _env_file_encoding="utf-8", + **values, + ) + @field_validator("etm_api_token") @classmethod def check_jwt(cls, v: str) -> str: @@ -77,43 +104,33 @@ def check_jwt(cls, v: str) -> str: return v + def model_post_init(self, __context) -> None: + """Post-initialization to handle base_url inference.""" + if not self.base_url: + self.base_url = HttpUrl(_infer_base_url_from_env(self.environment)) + def path_to_tmp(self, subfolder: str): folder = self.temp_folder / subfolder folder.mkdir(parents=True, exist_ok=True) return folder - @classmethod - def from_yaml(cls, path: Path) -> "AppConfig": - raw = {} - if path.is_file(): - try: - raw = yaml.safe_load(path.read_text()) or {} - except yaml.YAMLError: - raw = {} - - data = {k.lower(): v for k, v in raw.items()} - - # Collect environment variables overriding YAML - for field in ("etm_api_token", "base_url", "log_level", "environment"): - if val := os.getenv(field.upper()): - data[field] = val - - # If base_url wasn't explicitly provided, infer it from environment if present - if "base_url" not in data or not data["base_url"]: - env = (data.get("environment") or "").strip().lower() - if env: - data["base_url"] = _infer_base_url_from_env(env) - - return cls(**data) + @property + def proxy_servers(self) -> dict[str, str]: + """Return proxy servers as a dictionary for backward compatibility.""" + proxies = {} + if self.proxy_servers_http: + proxies["http"] = self.proxy_servers_http + if self.proxy_servers_https: + proxies["https"] = self.proxy_servers_https + return proxies def get_settings() -> AppConfig: """ - Always re-load AppConfig from disk and ENV on each call, - and raise a clear, aggregated message if anything required is missing. + Load AppConfig from .env file and environment variables. """ try: - return AppConfig.from_yaml(CONFIG_FILE) + return AppConfig() except ValidationError as exc: missing_or_invalid: List[str] = [] for err in exc.errors(): @@ -125,7 +142,7 @@ def get_settings() -> AppConfig: raise RuntimeError( f"\nConfiguration error: one or more required settings are missing or invalid:\n\n" f"{detail}\n\n" - f"Please set them via environment variables or in `{CONFIG_FILE}`." + f"Please set them via environment variables or in `{ENV_FILE}`." ) from exc diff --git a/src/pyetm/models/base.py b/src/pyetm/models/base.py index d33d46a..fbd7c73 100644 --- a/src/pyetm/models/base.py +++ b/src/pyetm/models/base.py @@ -49,7 +49,6 @@ def __init__(self, **data: Any) -> None: def __setattr__(self, name: str, value: Any) -> None: """ Handle assignment with validation error capture. - Simplified from the original complex implementation. """ # Skip validation for private attributes, methods/functions, or existing methods if ( diff --git a/src/pyetm/models/custom_curves.py b/src/pyetm/models/custom_curves.py index da5a6ca..753176b 100644 --- a/src/pyetm/models/custom_curves.py +++ b/src/pyetm/models/custom_curves.py @@ -120,7 +120,14 @@ def from_json(cls, data: dict) -> CustomCurve: Initialize a CustomCurve from JSON data """ try: - curve = cls.model_validate(data) + curve = cls(**data) + missing = [k for k in ("key", "type") if k not in data] + if missing: + curve.add_warning( + "base", + f"Failed to create curve from data: missing required fields: {', '.join(missing)}", + ) + return curve except Exception as e: basic_data = { diff --git a/src/pyetm/models/scenario.py b/src/pyetm/models/scenario.py index a4621fb..a95b951 100644 --- a/src/pyetm/models/scenario.py +++ b/src/pyetm/models/scenario.py @@ -1,6 +1,7 @@ from __future__ import annotations import pandas as pd from datetime import datetime +from pathlib import Path from typing import Any, Dict, List, Optional, Set, Union from urllib.parse import urlparse from pydantic import Field, PrivateAttr @@ -108,8 +109,12 @@ def from_excel(cls, xlsx_path: PathLike | str) -> List["Scenario"]: Load or create one or more scenarios from an Excel workbook. """ from pyetm.models.scenario_packer import ScenarioPacker + from pyetm.utils.paths import PyetmPaths - packer = ScenarioPacker.from_excel(xlsx_path) + resolver = PyetmPaths() + path = resolver.resolve_for_read(xlsx_path, default_dir="inputs") + + packer = ScenarioPacker.from_excel(str(path)) scenarios = list(packer._scenarios()) scenarios.sort(key=lambda s: s.id) return scenarios @@ -130,10 +135,15 @@ def to_excel( Output curves are exported to a separate workbook only when enabled, with one sheet per carrier. Use carriers to filter which carriers to include when exporting. """ + from pyetm.models.scenarios import Scenarios + from pyetm.utils.paths import PyetmPaths + + resolver = PyetmPaths() + out_path = resolver.resolve_for_write(path, default_dir="outputs") Scenarios(items=[self, *others]).to_excel( - path, + str(out_path), carriers=carriers, include_inputs=include_inputs, include_sortables=include_sortables, diff --git a/src/pyetm/models/scenario_packer.py b/src/pyetm/models/scenario_packer.py index 67eb08d..bdc136c 100644 --- a/src/pyetm/models/scenario_packer.py +++ b/src/pyetm/models/scenario_packer.py @@ -188,6 +188,12 @@ def to_excel( include_output_curves, ) + # Ensure destination directory exists + try: + Path(path).parent.mkdir(parents=True, exist_ok=True) + except Exception: + pass + # Create and populate workbook workbook = Workbook(path) try: @@ -356,7 +362,7 @@ def _export_output_curves_if_needed( if not include_output_curves: return - # Determine output file path + # Determine output file path (next to the main workbook) base_path = Path(main_path) output_path = str( base_path.with_name(f"{base_path.stem}_exports{base_path.suffix}") @@ -391,8 +397,31 @@ def from_excel(cls, xlsx_path: PathLike | str) -> "ScenarioPacker": """Import scenarios from Excel file.""" packer = cls() + # Resolve default location: if a relative path/filename is provided and the + # file does not exist at that location, look for it in the project /inputs dir. + path = Path(xlsx_path) + if not path.is_absolute() and not path.exists(): + + def _find_root_with(dir_name: str) -> Path: + for base in [ + Path.cwd(), + *Path.cwd().parents, + Path(__file__).resolve().parent, + *Path(__file__).resolve().parents, + ]: + candidate = base / dir_name + if candidate.exists() and candidate.is_dir(): + return base + return Path.cwd() + + root = _find_root_with("inputs") + relative = path if str(path.parent) != "." else Path(path.name) + candidate = root / "inputs" / relative + if candidate.exists(): + path = candidate + try: - excel_file = pd.ExcelFile(xlsx_path) + excel_file = pd.ExcelFile(str(path)) except Exception as e: logger.warning("Could not open Excel file '%s': %s", xlsx_path, e) return packer @@ -836,7 +865,7 @@ def _get_scenario_display_label(self, scenario: Scenario, fallback_column) -> st if scenario_id: return str(scenario_id) - # Final fallback to original column + # Final fallback return str(fallback_column) def _sanitize_dataframe_for_excel(self, df: pd.DataFrame) -> pd.DataFrame: diff --git a/src/pyetm/models/scenarios.py b/src/pyetm/models/scenarios.py index dc082e2..4153f60 100644 --- a/src/pyetm/models/scenarios.py +++ b/src/pyetm/models/scenarios.py @@ -1,11 +1,13 @@ from __future__ import annotations from os import PathLike +from pathlib import Path from typing import Iterable, Iterator, List, Optional, Sequence -from pydantic import BaseModel, Field +from pydantic import Field +from pyetm.models.base import Base from .scenario import Scenario -class Scenarios(BaseModel): +class Scenarios(Base): """ A simple collection of Scenario objects with convenience utilities. #TODO: Make a nice repr or stats functions @@ -40,12 +42,17 @@ def to_excel( include_output_curves: bool | None = None, ) -> None: from .scenario_packer import ScenarioPacker + from pyetm.utils.paths import PyetmPaths packer = ScenarioPacker() if self.items: packer.add(*self.items) + + resolver = PyetmPaths() + out_path = resolver.resolve_for_write(path, default_dir="outputs") + packer.to_excel( - str(path), + str(out_path), carriers=carriers, include_inputs=include_inputs, include_sortables=include_sortables, diff --git a/src/pyetm/models/sortables.py b/src/pyetm/models/sortables.py index ea46c14..e21d2da 100644 --- a/src/pyetm/models/sortables.py +++ b/src/pyetm/models/sortables.py @@ -213,7 +213,6 @@ def validate_sortables_list(cls, value: List[Sortable]) -> List[Sortable]: @model_validator(mode="after") def validate_sortables_consistency(self) -> "Sortables": """Additional validation for the entire sortables collection""" - # Example: Ensure we don't have conflicting heat_network configurations heat_network_types = [s for s in self.sortables if s.type == "heat_network"] if len(heat_network_types) > 0: # All heat_network sortables should have subtypes diff --git a/src/pyetm/utils/paths.py b/src/pyetm/utils/paths.py new file mode 100644 index 0000000..4527066 --- /dev/null +++ b/src/pyetm/utils/paths.py @@ -0,0 +1,87 @@ +from __future__ import annotations +from pathlib import Path +from typing import Optional, Union + + +PathLikeOrStr = Union[str, Path] + + +class PyetmPaths: + """ + - Reads: if given a relative path that does not exist, try under /inputs. + - Writes: if given a relative path, place it under /outputs. + - Absolute paths are always respected. + - Root discovery: walk upwards from CWD and this file's directory to find a + directory containing the requested subdirectory (e.g., 'inputs' or 'outputs'). + """ + + def __init__(self, start: Optional[Path] = None): + self._start = Path(start) if start else Path.cwd() + + @staticmethod + def _find_root_with(dir_name: str, start: Optional[Path] = None) -> Path: + """Find a root directory that contains the given subdirectory name.""" + candidates = [] + base_from_start = Path.cwd() if start is None else Path(start) + candidates.extend([base_from_start, *base_from_start.parents]) + + here = Path(__file__).resolve().parent + candidates.extend([here, *here.parents]) + + for base in candidates: + probe = base / dir_name + try: + if probe.exists() and probe.is_dir(): + return base + except Exception: + continue + + return base_from_start + + def inputs_dir(self) -> Path: + root = self._find_root_with("inputs", self._start) + return root / "inputs" + + def outputs_dir(self) -> Path: + root = self._find_root_with("outputs", self._start) + return root / "outputs" + + def resolve_for_read( + self, path: PathLikeOrStr, *, default_dir: str = "inputs" + ) -> Path: + p = Path(path) + if p.is_absolute() or p.exists(): + return p + + base = ( + self.inputs_dir() + if default_dir == "inputs" + else self._find_root_with(default_dir, self._start) / default_dir + ) + # Preserve any sub-paths the user provided + relative = p if str(p.parent) != "." else Path(p.name) + candidate = base / relative + return candidate if candidate.exists() else p + + def resolve_for_write( + self, + path: PathLikeOrStr, + *, + default_dir: str = "outputs", + create_parents: bool = True, + ) -> Path: + p = Path(path) + if p.is_absolute(): + if create_parents: + p.parent.mkdir(parents=True, exist_ok=True) + return p + + base = ( + self.outputs_dir() + if default_dir == "outputs" + else self._find_root_with(default_dir, self._start) / default_dir + ) + out = base / p + if create_parents: + out.parent.mkdir(parents=True, exist_ok=True) + return out diff --git a/tests/conftest.py b/tests/conftest.py index 185252a..eebb435 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -5,6 +5,7 @@ from pydantic import HttpUrl import os, sys, pytest +from pathlib import Path # Ensure src/ is on sys.path before any imports of your app code ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__), "..")) @@ -12,7 +13,6 @@ if SRC not in sys.path: sys.path.insert(0, SRC) -# Set the ENV vars at import time so BaseClient picks up the test URL and token os.environ["BASE_URL"] = "https://example.com/api" os.environ["ETM_API_TOKEN"] = "etm_real.looking.token" diff --git a/tests/models/conftest.py b/tests/models/conftest.py index 2ca58f9..b5ce673 100644 --- a/tests/models/conftest.py +++ b/tests/models/conftest.py @@ -12,6 +12,7 @@ from pathlib import Path from pyetm.models.sortables import Sortables from pyetm.models.scenario import Scenario +from pyetm.models.output_curves import OutputCurves # --- Scenario Fixtures --- # @@ -369,3 +370,38 @@ def fixture_path(): def interconnector_csv_path(fixture_path): """Path to the interconnector CSV fixture file""" return fixture_path / "interconnector_2_export_availability.csv" + + +@pytest.fixture +def carrier_mappings(monkeypatch): + mapping = {"electricity": {}, "gas": {}} + monkeypatch.setattr( + OutputCurves, + "_load_carrier_mappings", + staticmethod(lambda: mapping), + raising=True, + ) + return mapping + + +@pytest.fixture +def mock_workbook(monkeypatch): + instance = Mock() + cls = Mock(return_value=instance) + monkeypatch.setattr( + "pyetm.models.packables.output_curves_pack.Workbook", + cls, + raising=True, + ) + return {"cls": cls, "instance": instance} + + +@pytest.fixture +def patch_add_frame(monkeypatch): + m = Mock() + monkeypatch.setattr( + "pyetm.models.packables.output_curves_pack.add_frame", + m, + raising=True, + ) + return m diff --git a/tests/models/packables/test_inputs_pack.py b/tests/models/packables/test_inputs_pack.py index 6729308..4e43cb0 100644 --- a/tests/models/packables/test_inputs_pack.py +++ b/tests/models/packables/test_inputs_pack.py @@ -1,13 +1,17 @@ import pandas as pd -from unittest.mock import Mock +from unittest.mock import Mock, patch +import numpy as np from pyetm.models.packables.inputs_pack import InputsPack class DummyInput: - def __init__(self, key, user): + def __init__(self, key, user, default=None, min_val=None, max_val=None): self.key = key self.user = user + self.default = default + self.min = min_val + self.max = max_val def make_scenario(id_val, identifier=None): @@ -25,6 +29,7 @@ def make_scenario(id_val, identifier=None): return s +# Existing tests def test_key_for_prefers_short_name_and_fallbacks(): s1 = make_scenario(1, identifier="id-1") s2 = make_scenario(2, identifier="id-2") @@ -172,3 +177,541 @@ def test_from_dataframe_early_returns(): pack.from_dataframe(pd.DataFrame([[None], [None]])) # After header but no data columns pack.from_dataframe(pd.DataFrame([["only-one-col"], [1]])) + + +# New tests for 100% coverage + + +def test_class_variables(): + """Test class variables are set correctly.""" + assert InputsPack.key == "inputs" + assert InputsPack.sheet_name == "SLIDER_SETTINGS" + + +def test_init_with_kwargs(): + """Test initialization with kwargs.""" + pack = InputsPack(some_param="value") + assert pack._scenario_short_names == {} + + +def test_set_scenario_short_names_with_none(): + """Test setting short names with None value.""" + pack = InputsPack() + pack.set_scenario_short_names(None) + assert pack._scenario_short_names == {} + + +def test_get_scenario_display_key_with_non_string_identifier(): + """Test _get_scenario_display_key when identifier returns non-string/int.""" + s = make_scenario(1) + s.identifier.return_value = {"complex": "object"} + + pack = InputsPack() + result = pack._get_scenario_display_key(s) + assert result == 1 # Falls back to ID + + +def test_resolve_scenario_with_none(): + """Test resolve_scenario with None input.""" + pack = InputsPack() + assert pack.resolve_scenario(None) is None + + +def test_resolve_scenario_with_whitespace(): + """Test resolve_scenario strips whitespace.""" + s = make_scenario(1, "ID1") + pack = InputsPack() + pack.add(s) + + assert pack.resolve_scenario(" ID1 ") is s + + +def test_resolve_scenario_numeric_conversion_error(): + """Test resolve_scenario when numeric conversion fails.""" + s = make_scenario(1, "ID1") + pack = InputsPack() + pack.add(s) + + # Non-numeric string should not crash + assert pack.resolve_scenario("not_a_number") is None + + +def test_extract_from_input_objects_no_key(): + """Test _extract_from_input_objects with input missing key attribute.""" + s = make_scenario(1) + input_obj = Mock() + input_obj.key = None # Explicitly set key to None + input_obj.user = 10 + s.inputs = [input_obj] + + pack = InputsPack() + result = pack._extract_from_input_objects(s, "user") + assert result == {} # Should skip objects with None key + + +def test_extract_from_input_objects_exception(): + """Test _extract_from_input_objects with iteration exception.""" + s = make_scenario(1) + s.inputs = Mock() + s.inputs.__iter__ = Mock(side_effect=Exception("iteration failed")) + + pack = InputsPack() + result = pack._extract_from_input_objects(s, "user") + assert result == {} + + +def test_extract_from_dataframe_to_dataframe_exception(): + """Test _extract_from_dataframe when to_dataframe raises exception.""" + s = make_scenario(1) + s.inputs = Mock() + s.inputs.to_dataframe = Mock(side_effect=Exception("dataframe failed")) + + pack = InputsPack() + result = pack._extract_from_dataframe(s, "user") + assert result == {} + + +def test_extract_from_dataframe_none_result(): + """Test _extract_from_dataframe when to_dataframe returns None.""" + s = make_scenario(1) + s.inputs = Mock() + s.inputs.to_dataframe = Mock(return_value=None) + + pack = InputsPack() + result = pack._extract_from_dataframe(s, "user") + assert result == {} + + +def test_extract_from_dataframe_empty_result(): + """Test _extract_from_dataframe when to_dataframe returns empty DataFrame.""" + s = make_scenario(1) + s.inputs = Mock() + empty_df = pd.DataFrame() + s.inputs.to_dataframe = Mock(return_value=empty_df) + + pack = InputsPack() + result = pack._extract_from_dataframe(s, "user") + assert result == {} + + +def test_normalize_dataframe_index_no_multiindex(): + """Test _normalize_dataframe_index with regular index.""" + pack = InputsPack() + df = pd.DataFrame({"user": [1, 2]}, index=["a", "b"]) + result = pack._normalize_dataframe_index(df) + assert result.equals(df) + + +def test_normalize_dataframe_index_no_unit_level(): + """Test _normalize_dataframe_index with MultiIndex but no 'unit' level.""" + pack = InputsPack() + df = pd.DataFrame( + {"user": [1, 2]}, + index=pd.MultiIndex.from_tuples( + [("a", "x"), ("b", "y")], names=["key", "other"] + ), + ) + result = pack._normalize_dataframe_index(df) + assert result.equals(df) + + +def test_dataframe_to_series_with_series_input(): + """Test _dataframe_to_series when input is already a Series.""" + pack = InputsPack() + series = pd.Series([1, 2], index=["a", "b"]) + result = pack._dataframe_to_series(series, "user") + assert result.equals(series) + + +def test_dataframe_to_series_with_default_field(): + """Test _dataframe_to_series finding 'default' column.""" + pack = InputsPack() + df = pd.DataFrame({"default": [1, 2], "other": [3, 4]}, index=["a", "b"]) + result = pack._dataframe_to_series(df, "missing_field") + assert result.equals(df["default"]) + + +def test_dataframe_to_series_with_value_field(): + """Test _dataframe_to_series finding 'value' column.""" + pack = InputsPack() + df = pd.DataFrame({"value": [1, 2], "other": [3, 4]}, index=["a", "b"]) + result = pack._dataframe_to_series(df, "missing_field") + assert result.equals(df["value"]) + + +def test_dataframe_to_series_fallback_to_first_column(): + """Test _dataframe_to_series falling back to first column.""" + pack = InputsPack() + df = pd.DataFrame({"col1": [1, 2], "col2": [3, 4]}, index=["a", "b"]) + result = pack._dataframe_to_series(df, "missing_field") + assert result.equals(df.iloc[:, 0]) + + +def test_build_consolidated_dataframe_no_scenarios(): + """Test _build_consolidated_dataframe with no scenarios.""" + pack = InputsPack() + result = pack._build_consolidated_dataframe({}) + assert result.empty + + +def test_build_consolidated_dataframe_no_relevant_scenarios(): + """Test _build_consolidated_dataframe with no relevant scenarios in field_mappings.""" + s = make_scenario(1) + pack = InputsPack() + pack.add(s) + + result = pack._build_consolidated_dataframe({}) # Empty field mappings + assert result.empty + + +def test_build_consolidated_dataframe_no_input_keys(): + """Test _build_consolidated_dataframe when no input keys are found.""" + s = make_scenario(1) + s.inputs = [] + pack = InputsPack() + pack.add(s) + + result = pack._build_consolidated_dataframe({s: ["user"]}) + assert result.empty + + +def test_build_consolidated_dataframe_no_scenario_frames(): + """Test _build_consolidated_dataframe when no scenario frames are built.""" + s = make_scenario(1) + s.inputs = Mock() + s.inputs.__iter__ = Mock(side_effect=Exception()) + s.inputs.to_dataframe = Mock(side_effect=Exception()) + pack = InputsPack() + pack.add(s) + + result = pack._build_consolidated_dataframe({s: ["user"]}) + assert result.empty + + +def test_build_scenario_data_empty_fields(): + """Test _build_scenario_data with empty fields list.""" + s = make_scenario(1) + pack = InputsPack() + + result = pack._build_scenario_data(s, [], ["a", "b"]) + assert result == {} + + +def test_build_simple_dataframe_no_scenarios(): + """Test _build_simple_dataframe with no scenarios.""" + pack = InputsPack() + result = pack._build_simple_dataframe() + assert result.empty + + +def test_build_simple_dataframe_no_input_keys(): + """Test _build_simple_dataframe when no input keys found.""" + s = make_scenario(1) + s.inputs = [] + + pack = InputsPack() + pack.add(s) + + result = pack._build_simple_dataframe() + assert result.empty + + +def test_build_bounds_dataframe_no_scenarios(): + """Test _build_bounds_dataframe with no scenarios.""" + pack = InputsPack() + result = pack._build_bounds_dataframe() + assert result.empty + + +def test_build_bounds_dataframe_no_input_keys(): + """Test _build_bounds_dataframe when no input keys found.""" + s = make_scenario(1) + s.inputs = [] + + pack = InputsPack() + pack.add(s) + + result = pack._build_bounds_dataframe() + assert result.empty + + +def test_build_bounds_dataframe_from_objects(): + """Test _build_bounds_dataframe extracting from input objects.""" + s = make_scenario(1) + s.inputs = [ + DummyInput("a", 10, min_val=0, max_val=100), + DummyInput("b", 20, min_val=5, max_val=50), + ] + pack = InputsPack() + pack.add(s) + + result = pack._build_bounds_dataframe() + assert not result.empty + assert ("", "min") in result.columns + assert ("", "max") in result.columns + + +def test_build_bounds_dataframe_from_dataframe_exception(): + """Test _build_bounds_dataframe when both input iteration and dataframe fail.""" + s = make_scenario(1) + s.inputs = Mock() + s.inputs.__iter__ = Mock(side_effect=Exception()) + s.inputs.to_dataframe = Mock(side_effect=Exception()) + pack = InputsPack() + pack.add(s) + + result = pack._build_bounds_dataframe() + assert result.empty + + +def test_build_bounds_dataframe_early_break(): + """Test _build_bounds_dataframe early break when all values found.""" + s1 = make_scenario(1) + s1.inputs = [DummyInput("a", 10, min_val=0, max_val=100)] + s2 = make_scenario(2) + s2.inputs = [DummyInput("a", 20, min_val=0, max_val=100)] + pack = InputsPack() + pack.add(s1, s2) + + result = pack._build_bounds_dataframe() + assert not result.empty + # Should have values from first scenario due to early break + + +def test_to_dataframe_empty_columns(): + """Test _to_dataframe with empty columns parameter.""" + s = make_scenario(1) + s.inputs = [DummyInput("a", 10)] + pack = InputsPack() + pack.add(s) + + result = pack._to_dataframe(columns="") + assert not result.empty + + +def test_to_dataframe_non_string_columns(): + """Test _to_dataframe with non-string columns parameter.""" + s = make_scenario(1) + s.inputs = [DummyInput("a", 10)] + pack = InputsPack() + pack.add(s) + + result = pack._to_dataframe(columns=123) + assert not result.empty + + +def test_to_dataframe_per_scenario_fields(): + """Test to_dataframe_per_scenario_fields.""" + s1 = make_scenario(1) + s1.inputs = [DummyInput("a", 10, default=5)] + s2 = make_scenario(2) + s2.inputs = [DummyInput("a", 20)] + pack = InputsPack() + pack.add(s1, s2) + + fields_map = {s1: ["user", "default"], s2: ["user"]} + result = pack.to_dataframe_per_scenario_fields(fields_map) + assert not result.empty + + +def test_to_dataframe_defaults(): + """Test to_dataframe_defaults.""" + s = make_scenario(1) + s.inputs = [DummyInput("a", 10, default=5)] + pack = InputsPack() + pack.add(s) + + result = pack.to_dataframe_defaults() + assert not result.empty + + +def test_to_dataframe_min_max(): + """Test to_dataframe_min_max.""" + s = make_scenario(1) + s.inputs = [DummyInput("a", 10, min_val=0, max_val=100)] + pack = InputsPack() + pack.add(s) + + result = pack.to_dataframe_min_max() + assert not result.empty + + +def test_from_dataframe_exception_handling(caplog): + """Test from_dataframe general exception handling.""" + pack = InputsPack() + df = Mock() + df.empty = False + df.dropna = Mock(side_effect=Exception("processing failed")) + + with caplog.at_level("WARNING"): + pack.from_dataframe(df) + assert "Failed to parse simplified SLIDER_SETTINGS sheet" in caplog.text + + +def test_from_dataframe_empty_after_dropna(): + """Test from_dataframe when DataFrame is empty after dropna.""" + pack = InputsPack() + df = pd.DataFrame([[None, None], [None, None]]) + pack.from_dataframe(df) # Should return early + + +def test_is_blank_value(): + """Test _is_blank_value method.""" + pack = InputsPack() + + assert pack._is_blank_value(None) is True + assert pack._is_blank_value(np.nan) is True + assert pack._is_blank_value("") is True + assert pack._is_blank_value(" ") is True + assert pack._is_blank_value("nan") is True + assert pack._is_blank_value("NaN") is True + assert pack._is_blank_value(0) is False + assert pack._is_blank_value("0") is False + assert pack._is_blank_value("value") is False + + +def test_build_combined_dataframe_no_scenarios(): + """Test build_combined_dataframe with no scenarios.""" + pack = InputsPack() + result = pack.build_combined_dataframe() + assert result.empty + + +def test_build_combined_dataframe_defaults_only(): + """Test build_combined_dataframe with defaults only.""" + s = make_scenario(1) + s.inputs = [DummyInput("a", 10, default=5)] + pack = InputsPack() + pack.add(s) + result = pack.build_combined_dataframe(include_defaults=True, include_min_max=False) + assert not result.empty + + +def test_build_combined_dataframe_user_with_bounds(): + """Test build_combined_dataframe with user values and bounds but no defaults.""" + s = make_scenario(1) + s.inputs = [DummyInput("a", 10, min_val=0, max_val=100)] + pack = InputsPack() + pack.add(s) + result = pack.build_combined_dataframe(include_defaults=False, include_min_max=True) + assert isinstance(result, pd.DataFrame) + + +def test_build_combined_dataframe_full(): + """Test build_combined_dataframe with all options.""" + s = make_scenario(1) + s.inputs = [DummyInput("a", 10, default=5, min_val=0, max_val=100)] + pack = InputsPack() + pack.add(s) + result = pack.build_combined_dataframe(include_defaults=True, include_min_max=True) + + +def test_build_full_combined_dataframe_exception(): + """Test _build_full_combined_dataframe exception handling.""" + pack = InputsPack() + with patch.object(pack, "_build_consolidated_dataframe", side_effect=Exception()): + with patch.object(pack, "_build_bounds_dataframe", return_value=pd.DataFrame()): + result = pack._build_full_combined_dataframe() + + +def test_build_full_combined_dataframe_empty_core(): + """Test _build_full_combined_dataframe with empty core DataFrame.""" + s = make_scenario(1) + s.inputs = [DummyInput("a", 10, min_val=0, max_val=100)] + + pack = InputsPack() + pack.add(s) + + with patch.object( + pack, "_build_consolidated_dataframe", return_value=pd.DataFrame() + ): + result = pack._build_full_combined_dataframe() + + +def test_build_full_combined_dataframe_empty_bounds(): + """Test _build_full_combined_dataframe with empty bounds DataFrame.""" + s = make_scenario(1) + s.inputs = [DummyInput("a", 10, default=5)] + + pack = InputsPack() + pack.add(s) + + with patch.object(pack, "_build_bounds_dataframe", return_value=pd.DataFrame()): + result = pack._build_full_combined_dataframe() + + +def test_log_scenario_input_warnings(): + """Test _log_scenario_input_warnings with scenario having _inputs.""" + s = make_scenario(1) + mock_inputs = Mock() + mock_inputs.log_warnings = Mock() + s._inputs = mock_inputs + pack = InputsPack() + pack._log_scenario_input_warnings(s) + mock_inputs.log_warnings.assert_called_once() + + +def test_log_scenario_input_warnings_no_inputs(): + """Test _log_scenario_input_warnings with scenario missing _inputs.""" + s = make_scenario(1) + pack = InputsPack() + pack._log_scenario_input_warnings(s) + + +def test_log_scenario_input_warnings_none_inputs(): + """Test _log_scenario_input_warnings with _inputs = None.""" + s = make_scenario(1) + s._inputs = None + pack = InputsPack() + pack._log_scenario_input_warnings(s) + + +def test_log_scenario_input_warnings_exception(): + """Test _log_scenario_input_warnings with exception during logging.""" + s = make_scenario(1) + mock_inputs = Mock() + mock_inputs.log_warnings = Mock(side_effect=Exception("logging failed")) + s._inputs = mock_inputs + pack = InputsPack() + pack._log_scenario_input_warnings(s) + + +def test_from_dataframe_calls_log_warnings(): + """Test from_dataframe calls _log_scenario_input_warnings.""" + s = make_scenario(1, "S1") + pack = InputsPack() + pack.add(s) + + with patch.object(pack, "_log_scenario_input_warnings") as mock_log: + with patch( + "pyetm.models.packables.inputs_pack.InputsPack.first_non_empty_row_positions", + return_value=[0], + ): + df = pd.DataFrame([["input", "S1"], ["a", 10]]) + pack.from_dataframe(df) + mock_log.assert_called_once_with(s) + + +def test_extract_input_values_prefers_objects(): + """Test _extract_input_values prefers input objects over dataframe.""" + s = make_scenario(1) + s.inputs = [DummyInput("a", 10)] + + pack = InputsPack() + + with patch.object(pack, "_extract_from_dataframe") as mock_df: + result = pack._extract_input_values(s, "user") + mock_df.assert_not_called() + assert result == {"a": 10} + + +def test_extract_input_values_fallback_to_dataframe(): + """Test _extract_input_values falls back to dataframe.""" + s = make_scenario(1) + s.inputs = Mock() + s.inputs.__iter__ = Mock(side_effect=Exception()) + s.inputs.to_dataframe = Mock(return_value=pd.DataFrame({"user": [10]}, index=["a"])) + + pack = InputsPack() + result = pack._extract_input_values(s, "user") + assert result == {"a": 10} diff --git a/tests/models/packables/test_output_curves_pack.py b/tests/models/packables/test_output_curves_pack.py index 160682d..e9ad086 100644 --- a/tests/models/packables/test_output_curves_pack.py +++ b/tests/models/packables/test_output_curves_pack.py @@ -1,5 +1,7 @@ import pandas as pd from unittest.mock import Mock +import tempfile +import os from pyetm.models.packables.output_curves_pack import OutputCurvesPack @@ -7,6 +9,7 @@ def make_scenario(id_val="S"): s = Mock() s.identifier = Mock(return_value=str(id_val)) + s.id = id_val return s @@ -41,3 +44,330 @@ def test_to_dataframe_handles_exception_and_empty(caplog): s.all_output_curves.return_value = [] df2 = pack.to_dataframe() assert df2.empty + + +def test_build_dataframe_with_warnings(caplog): + """Test the warning logging branch when scenario has _output_curves.""" + s = make_scenario() + s.all_output_curves.return_value = [pd.Series([1, 2], name="test")] + + # Mock _output_curves with log_warnings method + mock_output_curves = Mock() + mock_output_curves.log_warnings = Mock() + s._output_curves = mock_output_curves + + pack = OutputCurvesPack() + pack.add(s) + + df = pack._build_dataframe_for_scenario(s) + + # Verify log_warnings was called + mock_output_curves.log_warnings.assert_called_once() + assert not df.empty + + +def test_build_dataframe_warning_logging_exception(): + """Test exception handling in warning logging branch.""" + s = make_scenario() + s.all_output_curves.return_value = [pd.Series([1, 2], name="test")] + + # Mock _output_curves that raises exception during log_warnings + mock_output_curves = Mock() + mock_output_curves.log_warnings.side_effect = Exception("logging failed") + s._output_curves = mock_output_curves + + pack = OutputCurvesPack() + df = pack._build_dataframe_for_scenario(s) + + # Should still return dataframe despite logging exception + assert not df.empty + + +def test_build_dataframe_no_output_curves_attr(): + """Test scenario without _output_curves attribute.""" + s = make_scenario() + s.all_output_curves.return_value = [pd.Series([1, 2], name="test")] + # Don't set _output_curves attribute + + pack = OutputCurvesPack() + df = pack._build_dataframe_for_scenario(s) + + assert not df.empty + + +def test_build_dataframe_output_curves_none(): + """Test scenario with _output_curves = None.""" + s = make_scenario() + s.all_output_curves.return_value = [pd.Series([1, 2], name="test")] + s._output_curves = None + + pack = OutputCurvesPack() + df = pack._build_dataframe_for_scenario(s) + + assert not df.empty + + +def test_to_excel_per_carrier_no_scenarios(carrier_mappings): + """Test to_excel_per_carrier with no scenarios.""" + + pack = OutputCurvesPack() + # Don't add any scenarios + + with tempfile.NamedTemporaryFile(suffix=".xlsx", delete=False) as tmp: + pack.to_excel_per_carrier(tmp.name) + # Should return early, file shouldn't be created with content + assert os.path.getsize(tmp.name) == 0 + os.unlink(tmp.name) + + +def test_to_excel_per_carrier_full_flow( + carrier_mappings, mock_workbook, patch_add_frame +): + """Test full flow of to_excel_per_carrier.""" + # Setup mocks + mock_wb = mock_workbook["instance"] + + # Create scenario with output curves + s1 = make_scenario("scenario1") + s1.get_output_curves = Mock( + return_value={ + "demand": pd.Series([100, 200, 300], name="hourly_demand"), + "supply": pd.DataFrame({"wind": [50, 60, 70], "solar": [30, 40, 50]}), + } + ) + + s2 = make_scenario("scenario2") + s2.get_output_curves = Mock( + return_value={"demand": pd.Series([150, 250, 350], name="hourly_demand")} + ) + + pack = OutputCurvesPack() + pack.add(s1) + pack.add(s2) + + with tempfile.NamedTemporaryFile(suffix=".xlsx") as tmp: + pack.to_excel_per_carrier(tmp.name, carriers=["electricity"]) + + # Verify workbook creation and closing + mock_workbook["cls"].assert_called_once_with(str(tmp.name)) + mock_wb.close.assert_called_once() + + assert patch_add_frame.call_count >= 1 + + +def test_to_excel_invalid_carriers(carrier_mappings): + """Test to_excel_per_carrier with invalid carriers.""" + + s = make_scenario() + s.get_output_curves = Mock(return_value={"demand": pd.Series([1, 2, 3])}) + + pack = OutputCurvesPack() + pack.add(s) + + with tempfile.NamedTemporaryFile(suffix=".xlsx", delete=False) as tmp: + # Pass invalid carriers - should fall back to valid ones + pack.to_excel_per_carrier(tmp.name, carriers=["invalid_carrier"]) + os.unlink(tmp.name) + + +def test_to_excel_scenario_without_get_output_curves(mock_workbook, carrier_mappings): + """Test scenario without get_output_curves method.""" + mock_wb = mock_workbook["instance"] + + s = make_scenario() + # Don't add get_output_curves method + + pack = OutputCurvesPack() + pack.add(s) + + with tempfile.NamedTemporaryFile(suffix=".xlsx") as tmp: + pack.to_excel_per_carrier(tmp.name) + # Should not create workbook since no valid curves + mock_workbook["cls"].assert_not_called() + + +def test_to_excel_get_output_curves_exception(mock_workbook, carrier_mappings): + """Test exception in get_output_curves method.""" + + s = make_scenario() + s.get_output_curves = Mock(side_effect=Exception("curves failed")) + + pack = OutputCurvesPack() + pack.add(s) + + with tempfile.NamedTemporaryFile(suffix=".xlsx") as tmp: + pack.to_excel_per_carrier(tmp.name) + # Should handle exception gracefully + mock_workbook["cls"].assert_not_called() + + +def test_to_excel_empty_curves_dict(mock_workbook, carrier_mappings): + """Test scenario with empty curves dictionary.""" + s = make_scenario() + s.get_output_curves = Mock(return_value={}) + + pack = OutputCurvesPack() + pack.add(s) + + with tempfile.NamedTemporaryFile(suffix=".xlsx") as tmp: + pack.to_excel_per_carrier(tmp.name) + mock_workbook["cls"].assert_not_called() + + +def test_to_excel_none_curves(mock_workbook, carrier_mappings): + """Test scenario returning None for curves.""" + s = make_scenario() + s.get_output_curves = Mock(return_value=None) + + pack = OutputCurvesPack() + pack.add(s) + + with tempfile.NamedTemporaryFile(suffix=".xlsx") as tmp: + pack.to_excel_per_carrier(tmp.name) + mock_workbook["cls"].assert_not_called() + + +def test_to_excel_none_dataframe_values(mock_workbook, carrier_mappings): + """Test scenario with None values in curves dictionary.""" + s = make_scenario() + s.get_output_curves = Mock(return_value={"demand": None, "supply": None}) + + pack = OutputCurvesPack() + pack.add(s) + + with tempfile.NamedTemporaryFile(suffix=".xlsx") as tmp: + pack.to_excel_per_carrier(tmp.name) + mock_workbook["cls"].assert_not_called() + + +def test_to_excel_empty_dataframe(mock_workbook, carrier_mappings): + """Test scenario with empty DataFrame.""" + s = make_scenario() + empty_df = pd.DataFrame() # Empty DataFrame + s.get_output_curves = Mock(return_value={"demand": empty_df}) + + pack = OutputCurvesPack() + pack.add(s) + + with tempfile.NamedTemporaryFile(suffix=".xlsx") as tmp: + pack.to_excel_per_carrier(tmp.name) + # Should not create workbook due to empty DataFrame + mock_workbook["cls"].assert_not_called() + + +def test_to_excel_multi_column_dataframe( + mock_workbook, carrier_mappings, patch_add_frame +): + """Test scenario with multi-column DataFrame.""" + mock_wb = mock_workbook["instance"] + + s = make_scenario() + multi_df = pd.DataFrame( + {"wind": [10, 20, 30], "solar": [5, 15, 25], "hydro": [2, 4, 6]} + ) + s.get_output_curves = Mock(return_value={"supply": multi_df}) + + pack = OutputCurvesPack() + pack.add(s) + + with tempfile.NamedTemporaryFile(suffix=".xlsx") as tmp: + pack.to_excel_per_carrier(tmp.name) + mock_workbook["cls"].assert_called_once() + mock_wb.close.assert_called_once() + + +def test_to_excel_single_column_dataframe( + mock_workbook, carrier_mappings, patch_add_frame +): + """Test scenario with single-column DataFrame.""" + mock_wb = mock_workbook["instance"] + + s = make_scenario() + single_df = pd.DataFrame({"demand": [100, 200, 300]}) + s.get_output_curves = Mock(return_value={"hourly": single_df}) + + pack = OutputCurvesPack() + pack.add(s) + + with tempfile.NamedTemporaryFile(suffix=".xlsx") as tmp: + pack.to_excel_per_carrier(tmp.name) + mock_workbook["cls"].assert_called_once() + mock_wb.close.assert_called_once() + + +def test_to_excel_dataframe_processing_exception(mock_workbook, carrier_mappings): + """Test exception during DataFrame processing.""" + s = make_scenario() + # Create a DataFrame that will cause an exception during processing + bad_df = Mock(spec=pd.DataFrame) + bad_df.empty = False + bad_df.shape = (10, 1) + bad_df.iloc = Mock() + bad_df.iloc.__getitem__ = Mock(side_effect=Exception("processing failed")) + + s.get_output_curves = Mock(return_value={"bad_data": bad_df}) + + pack = OutputCurvesPack() + pack.add(s) + + with tempfile.NamedTemporaryFile(suffix=".xlsx") as tmp: + pack.to_excel_per_carrier(tmp.name) + # Should handle exception and not create workbook + mock_workbook["cls"].assert_not_called() + + +def test_to_excel_scenario_identifier_exception(mock_workbook, carrier_mappings): + """Test scenario where identifier() raises exception.""" + s = make_scenario() + s.identifier.side_effect = Exception("identifier failed") + s.get_output_curves = Mock(return_value={"demand": pd.Series([1, 2, 3])}) + + pack = OutputCurvesPack() + pack.add(s) + + with tempfile.NamedTemporaryFile(suffix=".xlsx") as tmp: + pack.to_excel_per_carrier(tmp.name) + # Should use fallback naming and still work + mock_workbook["cls"].assert_called_once() + + +def test_to_excel_empty_carrier_selection(carrier_mappings): + """Test when carrier selection results in empty list.""" + s = make_scenario() + s.get_output_curves = Mock(return_value={"demand": pd.Series([1, 2, 3])}) + + pack = OutputCurvesPack() + pack.add(s) + + with tempfile.NamedTemporaryFile(suffix=".xlsx") as tmp: + pack.to_excel_per_carrier(tmp.name, carriers=["nonexistent1", "nonexistent2"]) + + +def test_class_variables(): + """Test class variables are set correctly.""" + assert OutputCurvesPack.key == "output_curves" + assert OutputCurvesPack.sheet_name == "OUTPUT_CURVES" + + +def test_to_dataframe_with_kwargs(): + """Test _to_dataframe passes kwargs correctly by checking it calls the base implementation.""" + s = make_scenario() + s.all_output_curves.return_value = [pd.Series([1, 2], name="test")] + + pack = OutputCurvesPack() + pack.add(s) + + # Test that _to_dataframe works with additional kwargs + df = pack._to_dataframe(columns="test", extra_param="value") + assert isinstance(df, pd.DataFrame) + + +def test_build_dataframe_with_columns_kwargs(): + """Test _build_dataframe_for_scenario with columns parameter.""" + s = make_scenario() + s.all_output_curves.return_value = [pd.Series([1, 2], name="test")] + + pack = OutputCurvesPack() + df = pack._build_dataframe_for_scenario(s, columns="test_columns", extra="param") + + assert not df.empty diff --git a/tests/models/test_custom_curves.py b/tests/models/test_custom_curves.py index db76634..0cbb2a1 100644 --- a/tests/models/test_custom_curves.py +++ b/tests/models/test_custom_curves.py @@ -159,6 +159,21 @@ def test_custom_curve_remove_file_error(): assert "Failed to remove curve file" in key_warnings[0].message +def test_custom_curve_remove_success(tmp_path): + """Remove should delete file and clear file_path when available.""" + temp_file = tmp_path / "curve.csv" + temp_file.write_text("1\n2\n3\n") + + curve = CustomCurve(key="test_curve", type="custom", file_path=temp_file) + assert curve.available() is True + + result = curve.remove() + + assert result is True + assert curve.file_path is None + assert not temp_file.exists() + + def test_custom_curves_from_json_with_invalid_curve(): """Test from_json with some invalid curve data""" data = [{"key": "valid_curve", "type": "custom"}, {"invalid": "data"}] @@ -184,6 +199,27 @@ def test_custom_curves_from_json_with_invalid_curve(): assert "Skipped invalid curve data" in fallback_curve_warnings[0].message +def test_custom_curve_from_json_success(): + data = {"key": "abc", "type": "custom"} + curve = CustomCurve.from_json(data) + assert curve.key == "abc" + assert curve.type == "custom" + # No warnings on success + assert len(curve.warnings) == 0 + + +def test_custom_curve_from_json_failure_adds_warning(): + """Missing required fields should fall back and add a warning.""" + # Missing both key and type triggers ValidationError path + curve = CustomCurve.from_json({"unexpected": 123}) + # Fallback returns a constructed model; ensure a warning was recorded + assert len(curve.warnings) > 0 + base_warnings = curve.warnings.get_by_field("base") + assert ( + base_warnings and "Failed to create curve from data" in base_warnings[0].message + ) + + def test_custom_curve_from_dataframe_basic_roundtrip(): """Test basic serialization and deserialization of a CustomCurve.""" import numpy as np @@ -269,6 +305,27 @@ def test_custom_curve_from_dataframe_alternative_structure(): restored.file_path.unlink() +def test_custom_curve_from_dataframe_save_error(tmp_path): + """Saving data during from_dataframe should warn on failure.""" + import numpy as np + + df = pd.DataFrame({"foo": np.array([1.0, 2.0, 3.0])}) + + with ( + patch("pyetm.models.custom_curves.get_settings") as mock_settings, + patch("pandas.Series.to_csv", side_effect=OSError("disk full")), + ): + mock_settings.return_value.path_to_tmp.return_value = tmp_path + curve = CustomCurve.from_dataframe(df) + assert isinstance(curve, CustomCurve) + assert curve.key == "foo" + # Save failed so file_path not set + assert curve.file_path is None + # Warning recorded on curve + warnings = curve.warnings.get_by_field("foo") + assert warnings and "Failed to save curve data to file" in warnings[0].message + + def test_custom_curve_from_dataframe_invalid_multiple_rows(): """Test error handling when DataFrame has multiple rows.""" df = pd.DataFrame( @@ -423,6 +480,113 @@ def test_custom_curves_from_dataframe_preserves_warnings(): assert len(restored.curves) == 2 +def test_custom_curves_len_iter_and_attachment_helpers(): + """Covers __len__, __iter__, is_attached, attached_keys.""" + c1 = CustomCurve(key="a", type="custom") + c2 = CustomCurve(key="b", type="custom") + col = CustomCurves(curves=[c1, c2]) + + assert len(col) == 2 + assert [c.key for c in iter(col)] == ["a", "b"] + assert col.is_attached("a") is True + assert col.is_attached("z") is False + assert list(col.attached_keys()) == ["a", "b"] + + +def test_custom_curves_get_contents_not_found_adds_warning(): + col = CustomCurves(curves=[]) + mock_scenario = Mock() + res = col.get_contents(mock_scenario, "nope") + assert res is None + warnings = col.warnings.get_by_field("curves") + assert warnings and "not found in collection" in warnings[0].message + + +def test_custom_curves_get_contents_available_reads_file(tmp_path): + key = "my_curve" + data_file = tmp_path / f"{key}.csv" + data_file.write_text("1\n2\n3\n") + curve = CustomCurve(key=key, type="custom", file_path=data_file) + col = CustomCurves(curves=[curve]) + mock_scenario = Mock() + + res = col.get_contents(mock_scenario, key) + assert isinstance(res, pd.Series) + assert res.name == key + # Curve warned about non-8760 values, and warnings merged into collection + # Warnings are merged with a prefixed field name; just check the message exists + any_msg = any("Curve length should be 8760" in w.message for w in col.warnings) + assert any_msg + + +def test_custom_curves_get_contents_retrieves_when_unavailable(tmp_path): + key = "remote_curve" + curve = CustomCurve(key=key, type="custom") + col = CustomCurves(curves=[curve]) + mock_scenario = Mock() + mock_scenario.id = 999 + + csv_data = io.StringIO("10\n20\n30\n") + with ( + patch( + "pyetm.models.custom_curves.DownloadCustomCurveRunner.run", + return_value=ServiceResult.ok(data=csv_data), + ), + patch("pyetm.models.custom_curves.get_settings") as mock_settings, + patch("pandas.Series.to_csv") as mock_to_csv, + ): + mock_settings.return_value.path_to_tmp.return_value = tmp_path / "999" + res = col.get_contents(mock_scenario, key) + assert isinstance(res, pd.Series) + assert res.name == key + assert curve.file_path is not None + + +def test_custom_curves_to_dataframe_attempts_retrieve_and_suppresses_errors(): + """Hit branch where retrieve raises but is suppressed when _scenario is set.""" + curve = CustomCurve(key="x", type="custom") + col = CustomCurves(curves=[curve]) + # Setting the private attr is fine here + col._scenario = object() + with patch.object(curve, "retrieve", side_effect=RuntimeError("boom")): + df = col.to_dataframe() + # Column exists, index named 'hour' + assert df.index.name == "hour" + assert "x" in df.columns + + +def test_custom_curves_to_dataframe_curve_to_dataframe_raises_adds_warning(): + curve = CustomCurve(key="y", type="custom") + col = CustomCurves(curves=[curve]) + with patch.object(CustomCurve, "_to_dataframe", side_effect=ValueError("bad")): + df = col.to_dataframe() + # Column created as empty series + assert "y" in df.columns + warnings = col.warnings.get_by_field("curves") + assert warnings and "Failed to serialize curve y" in warnings[0].message + + +def test_custom_curves_from_dataframe_handles_per_column_error(): + import numpy as np + + df = pd.DataFrame({"ok": np.array([1.0, 2.0]), "bad": np.array([3.0, 4.0])}) + + def fake_from_df(inner_df, **kwargs): + name = inner_df.columns[0] + if name == "bad": + raise ValueError("oops") + return CustomCurve(key=name, type="custom") + + with patch.object(CustomCurve, "_from_dataframe", side_effect=fake_from_df): + col = CustomCurves.from_dataframe(df) + assert len(col.curves) == 2 + # Warning for the bad column on collection + # Field names are prefixed; check presence by message + assert any( + "Failed to create curve from column bad" in w.message for w in col.warnings + ) + + # --- Validate for Upload Tests --- # @@ -613,6 +777,66 @@ def test_validate_for_upload_file_read_error(): assert "Error reading curve data:" in warnings_list[0].message +def test_validate_for_upload_empty_dataframe_branch(tmp_path): + """Force pd.read_csv to return an empty DataFrame to hit raw_data.empty path.""" + f = tmp_path / "empty_data.csv" + f.write_text("\n\n") + curves = CustomCurves(curves=[CustomCurve(key="k", type="profile", file_path=f)]) + + def fake_read_csv(path, header=None, index_col=False): + return pd.DataFrame() + + with patch("pyetm.models.custom_curves.pd.read_csv", side_effect=fake_read_csv): + validation_errors = curves.validate_for_upload() + assert "k" in validation_errors + warnings = list(validation_errors["k"]) + assert warnings and "Curve contains no data" in warnings[0].message + + +def test_validate_for_upload_outer_except_path(tmp_path): + """Trigger outer exception handler by failing once inside inner except block.""" + f = tmp_path / "raise_once.csv" + f.write_text("") + curves = CustomCurves(curves=[CustomCurve(key="zz", type="profile", file_path=f)]) + + # Make read_csv raise EmptyDataError to go into that except branch + def raise_empty(*args, **kwargs): + raise pd.errors.EmptyDataError("no data") + + class AddOnceFailCollector: + def __init__(self): + self._count = 0 + self._records = [] + + def add(self, field, message, severity="warning"): + if self._count == 0: + self._count += 1 + raise RuntimeError("collector add failed once") + self._records.append((field, str(message), severity)) + + def __len__(self): + return len(self._records) + + def __iter__(self): + class W: + def __init__(self, field, message, severity): + self.field = field + self.message = message + self.severity = severity + + return (W(f, m, s) for (f, m, s) in self._records) + + with ( + patch("pyetm.models.custom_curves.pd.read_csv", side_effect=raise_empty), + patch("pyetm.models.custom_curves.WarningCollector", AddOnceFailCollector), + ): + errors = curves.validate_for_upload() + # Should have captured via outer except and still recorded a warning + assert "zz" in errors + items = list(errors["zz"]) # iter must work + assert items and "Error reading curve data:" in items[0].message + + def test_validate_for_upload_multiple_curves_mixed_validity(): """Test validate_for_upload with mix of valid and invalid curves""" import numpy as np diff --git a/tests/models/test_scenario_packer.py b/tests/models/test_scenario_packer.py index ac54fea..b8577c9 100644 --- a/tests/models/test_scenario_packer.py +++ b/tests/models/test_scenario_packer.py @@ -14,6 +14,7 @@ from pyetm.models.packables.query_pack import QueryPack from pyetm.models import Scenario from pyetm.models.custom_curves import CustomCurves +from pyetm.models.export_config import ExportConfig class TestScenarioPackerInit: @@ -1332,3 +1333,349 @@ def test_inputs_pack_build_combined_dataframe_with_flags(self, sample_scenario): mock_build.assert_called_once_with( include_defaults=True, include_min_max=True ) + + +class TestExportConfigResolverExtras: + + def test_extract_from_main_sheet_skips_helper_and_parses(self): + # First column is a helper and must be skipped + main = pd.DataFrame( + { + "helper": {"inputs": "no"}, + "S1": { + "inputs": "yes", + "sortables": 0, + "custom_curves": 1, + "gqueries": "1", + "defaults": "1", + "min_max": "0", + "exports": "electricity, gas ", + }, + } + ) + + scenarios = [Mock(spec=Scenario)] + cfg = ExportConfigResolver.extract_from_main_sheet(main, scenarios) + assert cfg.include_inputs is True + assert cfg.include_sortables is False + assert cfg.include_custom_curves is True + assert cfg.include_gqueries is True + assert cfg.inputs_defaults is True + assert cfg.inputs_min_max is False + assert cfg.output_carriers == ["electricity", "gas"] + + def test_extract_from_main_sheet_empty_or_error(self): + assert ExportConfigResolver.extract_from_main_sheet(pd.DataFrame(), []) is None + + +class TestScenarioPackerExtras: + + def test_get_global_export_config_first_available(self): + packer = ScenarioPacker() + + s1 = Mock(spec=Scenario) + s1.id = "1" + s1.identifier = Mock(return_value="1") + s1._export_config = ExportConfig(include_inputs=True) + + s2 = Mock(spec=Scenario) + s2.id = "2" + s2.identifier = Mock(return_value="2") + s2._export_config = ExportConfig(include_inputs=False) + + # Ensure deterministic order by patching _scenarios + with patch.object(ScenarioPacker, "_scenarios", return_value={s1, s2}): + cfg = packer._get_global_export_config() + assert isinstance(cfg, ExportConfig) + + def test_apply_export_configuration_sets_on_scenarios(self): + packer = ScenarioPacker() + s = Mock(spec=Scenario) + s.id = "X" + s.identifier = Mock(return_value="X") + packer.add(s) + + main = pd.DataFrame( + { + "X": { + "inputs": "1", + "sortables": "0", + "custom_curves": None, + "gquery_results": "yes", + "defaults": 1, + "min_max": 0, + "exports": "hydrogen", + } + } + ) + packer._apply_export_configuration(main, {"X": s}) + if hasattr(s, "set_export_config") and s.set_export_config.called: + assert s.set_export_config.call_count == 1 + else: + assert hasattr(s, "_export_config") + + def test_add_inputs_sheet_fallback_on_error(self, monkeypatch): + packer = ScenarioPacker() + s = Mock(spec=Scenario) + s.id = "SID" + s.identifier = Mock(return_value="SID") + s.to_dataframe = Mock(return_value=pd.DataFrame({"SID": [1]}, index=["row"])) + packer.add(s) + + # Force build_combined_dataframe to raise, and _to_dataframe to return data + monkeypatch.setattr( + InputsPack, + "build_combined_dataframe", + staticmethod(lambda **k: (_ for _ in ()).throw(RuntimeError("bad"))), + ) + monkeypatch.setattr( + InputsPack, + "_to_dataframe", + staticmethod(lambda **k: pd.DataFrame({"v": [1]}, index=["i"])), + ) + + with patch("pyetm.models.scenario_packer.Workbook") as mock_wb: + mock_wb.return_value = Mock() + # Should not raise + file_path = os.path.join(tempfile.gettempdir(), "inputs_fallback.xlsx") + packer.to_excel(file_path, include_inputs=True) + + def test_add_pack_and_gqueries_sheets(self): + packer = ScenarioPacker() + s = Mock(spec=Scenario) + s.id = "S" + s.identifier = Mock(return_value="S") + s.to_dataframe = Mock(return_value=pd.DataFrame({"S": [1]}, index=["row"])) + packer.add(s) + + # Make packs return non-empty DataFrames + with ( + patch.object( + SortablePack, "to_dataframe", return_value=pd.DataFrame({"v": [1]}) + ), + patch.object( + CustomCurvesPack, "to_dataframe", return_value=pd.DataFrame({"v": [1]}) + ), + patch.object( + QueryPack, + "to_dataframe", + return_value=pd.DataFrame({"future": [1]}, index=["q"]), + ), + patch.object(QueryPack, "output_sheet_name", "GQUERIES_OUT"), + patch.object( + InputsPack, + "build_combined_dataframe", + return_value=pd.DataFrame({"v": [1]}), + ), + patch("pyetm.models.scenario_packer.add_frame") as add_frame, + patch("pyetm.models.scenario_packer.Workbook") as mock_wb, + ): + mock_wb.return_value = Mock() + tmp = os.path.join(tempfile.gettempdir(), "with_packs.xlsx") + packer.to_excel( + tmp, + include_sortables=True, + include_custom_curves=True, + include_gqueries=True, + ) + + # MAIN + INPUTS + SORTABLES + CUSTOM_CURVES + GQUERIES + sheet_names = [call.kwargs.get("name") for call in add_frame.call_args_list] + assert "MAIN" in sheet_names + assert "SLIDER_SETTINGS" in sheet_names + assert "SORTABLES" in sheet_names + assert "CUSTOM_CURVES" in sheet_names + assert "GQUERIES_OUT" in sheet_names + + def test_export_output_curves_with_params_and_config(self): + packer = ScenarioPacker() + s = Mock(spec=Scenario) + s.id = "S" + s.identifier = Mock(return_value="S") + s.to_dataframe = Mock(return_value=pd.DataFrame({"S": [1]}, index=["row"])) + packer.add(s) + + # Case 1: carriers explicitly provided + with ( + patch.object(OutputCurvesPack, "to_excel_per_carrier") as toe, + patch("pyetm.models.scenario_packer.Workbook") as mock_wb, + ): + mock_wb.return_value = Mock() + tmp = os.path.join(tempfile.gettempdir(), "export1.xlsx") + packer.to_excel(tmp, include_output_curves=True, carriers=["el", "gas"]) + args, _ = toe.call_args + assert args[0].endswith("_exports.xlsx") + assert args[1] == ["el", "gas"] + + # Case 2: carriers from global config + cfg = ExportConfig(output_carriers=["h2"]) # minimal + s2 = Mock(spec=Scenario) + s2.id = "S2" + s2.identifier = Mock(return_value="S2") + s2.to_dataframe = Mock(return_value=pd.DataFrame({"S2": [1]}, index=["row"])) + setattr(s2, "_export_config", cfg) + packer2 = ScenarioPacker() + packer2.add(s2) + with ( + patch.object(OutputCurvesPack, "to_excel_per_carrier") as toe2, + patch("pyetm.models.scenario_packer.Workbook") as mock_wb2, + ): + mock_wb2.return_value = Mock() + tmp2 = os.path.join(tempfile.gettempdir(), "export2.xlsx") + packer2.to_excel(tmp2, include_output_curves=True) + args2, _ = toe2.call_args + assert args2[1] == ["h2"] + + def test_build_excel_main_dataframe_applies_labels_and_order(self): + packer = ScenarioPacker() + s1 = Mock(spec=Scenario) + s1.id = "1" + s1.identifier = Mock(return_value="Label 1") + s2 = Mock(spec=Scenario) + s2.id = "2" + s2.identifier = Mock(return_value="Label 2") + packer.add(s1, s2) + + df = pd.DataFrame( + {"1": ["A", 2050], "2": ["B", 2040]}, index=["area_code", "end_year"] + ) + + with patch.object(ScenarioPacker, "main_info", return_value=df): + out = packer._build_excel_main_dataframe() + # Columns should be relabeled using identifier + assert list(out.columns) == ["Label 1", "Label 2"] + # Preferred ordering keeps known fields order among those present + assert out.index.tolist()[0:2] == ["area_code", "end_year"] + + def test_sanitize_dataframe_for_excel_handles_datetime_and_objects(self): + packer = ScenarioPacker() + import datetime as dt + + class Foo: + def __str__(self): + return "foo" + + frame = pd.DataFrame( + { + "col": [dt.datetime(2020, 1, 1), Foo()], + }, + index=["when", "obj"], + ) + out = packer._sanitize_dataframe_for_excel(frame) + assert out.loc["obj", "col"] == "foo" + + def test_log_scenario_warnings_helper(self): + packer = ScenarioPacker() + s = Mock(spec=Scenario) + s.identifier = Mock(return_value="SID") + helper_attr = Mock() + s._sortables = helper_attr + packer._log_scenario_warnings(s, "_sortables", "Sortables") + helper_attr.log_warnings.assert_called_once() + + +def test_apply_scenario_column_labels_no_matches(): + packer = ScenarioPacker() + # No scenarios added; rename map should be empty and df unchanged + df = pd.DataFrame({"X": [1]}, index=["row"]) + out = packer._apply_scenario_column_labels(df) + assert list(out.columns) == ["X"] + + +def test_build_column_rename_map_both_match_str_and_exact(): + packer = ScenarioPacker() + s1 = Mock(spec=Scenario) + s1.id = "1" + s2 = Mock(spec=Scenario) + s2.id = 2 # int id for exact match case + # Columns include string '1' and int 2 + cols = ["1", 2, "nope"] + rename = packer._build_column_rename_map([s1, s2], cols) + assert "1" in rename and 2 in rename + # 'nope' should not be in rename map + assert "nope" not in rename + + +def test_get_scenario_display_label_fallbacks(): + packer = ScenarioPacker() + # 1) identifier raises -> title used + sc = Mock(spec=Scenario) + sc.identifier = Mock(side_effect=RuntimeError("bad")) + sc.title = "T" + assert packer._get_scenario_display_label(sc, "FALL") == "T" + + # 2) no title -> id used + sc2 = Mock(spec=Scenario) + sc2.identifier = Mock(side_effect=RuntimeError("bad")) + sc2.title = None + sc2.id = 42 + assert packer._get_scenario_display_label(sc2, "FALL") == "42" + + # 3) no id -> fallback to column + sc3 = Mock(spec=Scenario) + sc3.identifier = Mock(side_effect=RuntimeError("bad")) + sc3.title = None + sc3.id = None + assert packer._get_scenario_display_label(sc3, "COLX") == "COLX" + + +def test_get_value_before_output_respects_output_boundary(): + packer = ScenarioPacker() + series = pd.Series(["S1", None, "S2"], index=["sortables", "output", "sortables"]) + assert packer._get_value_before_output(series, "sortables") == "S1" + + +def test_export_output_curves_if_needed_false(): + packer = ScenarioPacker() + s = Mock(spec=Scenario) + s.id = "S" + s.identifier = Mock(return_value="S") + s.to_dataframe = Mock(return_value=pd.DataFrame({"S": [1]}, index=["row"])) + packer.add(s) + + with ( + patch.object(OutputCurvesPack, "to_excel_per_carrier") as toe, + patch("pyetm.models.scenario_packer.Workbook") as wb, + ): + wb.return_value = Mock() + packer.to_excel("/tmp/x.xlsx", include_output_curves=False) + toe.assert_not_called() + + +def test_add_gqueries_sheet_disabled(): + packer = ScenarioPacker() + with ( + patch("pyetm.models.scenario_packer.add_frame") as add_frame, + patch("pyetm.models.scenario_packer.Workbook") as wb, + patch.object(ScenarioPacker, "_scenarios", return_value={Mock(spec=Scenario)}), + patch.object(ScenarioPacker, "_add_data_sheets"), + ): + wb.return_value = Mock() + # Make main_info non-empty to create MAIN + with patch.object( + ScenarioPacker, + "main_info", + return_value=pd.DataFrame({"A": [1]}, index=["i"]), + ): + packer.to_excel("/tmp/y.xlsx", include_gqueries=False) + sheet_names = [call.kwargs.get("name") for call in add_frame.call_args_list] + assert "MAIN" in sheet_names + assert "GQUERIES" not in sheet_names and "GQUERIES_OUT" not in sheet_names + + +def test_clear_and_remove_scenario_swallow_errors(): + packer = ScenarioPacker() + fake_pack1 = Mock() + fake_pack2 = Mock() + fake_pack1.clear.side_effect = RuntimeError("bad") + fake_pack2.clear.return_value = None + + fake_pack1.discard.side_effect = RuntimeError("bad") + fake_pack2.discard.return_value = None + + with patch.object( + ScenarioPacker, "_get_all_packs", return_value=[fake_pack1, fake_pack2] + ): + packer.clear() # should not raise + sc = Mock(spec=Scenario) + packer.remove_scenario(sc) # should not raise diff --git a/tests/test_settings.py b/tests/test_settings.py index 4d0caab..c8d71f9 100644 --- a/tests/test_settings.py +++ b/tests/test_settings.py @@ -1,5 +1,3 @@ -import os -import yaml import pytest from pathlib import Path import pyetm.config.settings as settings_module @@ -9,83 +7,136 @@ get_settings = settings_module.get_settings -# Fixture: clear any ENV vars -@pytest.fixture(autouse=True) -def clear_env(monkeypatch): - for var in ("ETM_API_TOKEN", "BASE_URL", "LOG_LEVEL"): +# Settings-specific fixture for clean environment +@pytest.fixture +def clean_settings_env(monkeypatch, tmp_path): + """Create a completely clean environment for settings tests""" + # Clear all ETM environment variables + etm_vars = [ + "ETM_API_TOKEN", + "BASE_URL", + "LOG_LEVEL", + "ENVIRONMENT", + "CSV_SEPARATOR", + "DECIMAL_SEPARATOR", + "PROXY_SERVERS_HTTP", + "PROXY_SERVERS_HTTPS", + ] + for var in etm_vars: monkeypatch.delenv(var, raising=False) - -# Helper to write a YAML file -def write_yaml(path: Path, data: dict): - path.write_text(yaml.safe_dump(data)) - - -# File has all values → use them -def test_from_yaml_loads_file_values(tmp_path): - cfg_file = tmp_path / "config.yml" - payload = { - "etm_api_token": "etm_valid.looking.token", - "base_url": "https://custom.local/api", - "log_level": "DEBUG", + # Create isolated config file path + test_config_file = tmp_path / "isolated_config.env" + monkeypatch.setattr(settings_module, "ENV_FILE", test_config_file) + + return test_config_file + + +# Helper to write a .env file +def write_env_file(path: Path, data: dict): + lines = [] + for key, value in data.items(): + # Quote values with spaces + if isinstance(value, str) and (" " in value or "#" in value): + value = f'"{value}"' + lines.append(f"{key}={value}") + path.write_text("\n".join(lines)) + + +# Test basic .env file loading +def test_config_loads_env_file_values(clean_settings_env): + env_file = clean_settings_env + env_data = { + "ETM_API_TOKEN": "etm_valid.looking.token", + "BASE_URL": "https://custom.local/api", + "LOG_LEVEL": "DEBUG", + "ENVIRONMENT": "beta", + "CSV_SEPARATOR": ";", + "DECIMAL_SEPARATOR": ",", } - write_yaml(cfg_file, payload) + write_env_file(env_file, env_data) - config = AppConfig.from_yaml(cfg_file) + config = AppConfig() assert config.etm_api_token == "etm_valid.looking.token" assert config.base_url == HttpUrl("https://custom.local/api") assert config.log_level == "DEBUG" + assert config.environment == "beta" + assert config.csv_separator == ";" + assert config.decimal_separator == "," -# File only has token; ENV overrides log_level; base_url uses default -def test_from_yaml_env_overrides_and_defaults(tmp_path, monkeypatch): - cfg_file = tmp_path / "config.yml" - write_yaml(cfg_file, {"etm_api_token": "etm_valid.looking.token"}) +# Test environment variables override .env file +def test_env_vars_override_env_file(clean_settings_env, monkeypatch): + env_file = clean_settings_env + write_env_file( + env_file, {"ETM_API_TOKEN": "etm_from.env.file", "LOG_LEVEL": "DEBUG"} + ) - # only override LOG_LEVEL + # ENV var should override file monkeypatch.setenv("LOG_LEVEL", "WARNING") - config = AppConfig.from_yaml(cfg_file) + config = AppConfig() - assert config.etm_api_token == "etm_valid.looking.token" - assert config.log_level == "WARNING" - # default from the class - assert config.base_url == HttpUrl("https://engine.energytransitionmodel.com/api/v3") + assert config.etm_api_token == "etm_from.env.file" # from file + assert config.log_level == "WARNING" # from env var (overrides file) -# No file; ENV provides token; others default -def test_from_yaml_no_file_uses_env_and_defaults(tmp_path, monkeypatch): - cfg_file = tmp_path / "does_not_exist.yml" - monkeypatch.setenv("ETM_API_TOKEN", "etm_valid.looking.token") +# Test base_url inference from environment +def test_base_url_inference_from_environment(clean_settings_env): + env_file = clean_settings_env + write_env_file( + env_file, {"ETM_API_TOKEN": "etm_valid.looking.token", "ENVIRONMENT": "beta"} + ) - config = AppConfig.from_yaml(cfg_file) + config = AppConfig() - assert config.etm_api_token == "etm_valid.looking.token" - assert config.base_url == HttpUrl("https://engine.energytransitionmodel.com/api/v3") - assert config.log_level == "INFO" + assert config.environment == "beta" + assert config.base_url == HttpUrl( + "https://beta.engine.energytransitionmodel.com/api/v3" + ) -# Invalid YAML is swallowed; ENV+defaults apply -def test_from_yaml_invalid_yaml_is_swallowed(tmp_path, monkeypatch): - cfg_file = tmp_path / "config.yml" - cfg_file.write_text(":\t not valid yaml :::") +# Test proxy servers configuration +def test_proxy_servers_configuration(clean_settings_env): + env_file = clean_settings_env + write_env_file( + env_file, + { + "ETM_API_TOKEN": "etm_valid.looking.token", + "PROXY_SERVERS_HTTP": "http://proxy.example.com:8080", + "PROXY_SERVERS_HTTPS": "https://secure.proxy.com:8080", + }, + ) + + config = AppConfig() + + assert config.proxy_servers_http == "http://proxy.example.com:8080" + assert config.proxy_servers_https == "https://secure.proxy.com:8080" + # Test backward compatibility property + proxy_dict = config.proxy_servers + assert proxy_dict["http"] == "http://proxy.example.com:8080" + assert proxy_dict["https"] == "https://secure.proxy.com:8080" + + +# Test no .env file, only environment variables +def test_no_env_file_uses_env_vars_and_defaults(clean_settings_env, monkeypatch): + # Don't create the env_file, just set environment variable monkeypatch.setenv("ETM_API_TOKEN", "etm_valid.looking.token") - config = AppConfig.from_yaml(cfg_file) + config = AppConfig() assert config.etm_api_token == "etm_valid.looking.token" assert config.base_url == HttpUrl("https://engine.energytransitionmodel.com/api/v3") assert config.log_level == "INFO" + assert config.environment == "pro" -# Empty file + no ENV → get_settings() raises RuntimeError with helpful message -def test_get_settings_missing_token_raises_runtime_error(tmp_path, monkeypatch): - cfg_file = tmp_path / "config.yml" - write_yaml(cfg_file, {}) - - monkeypatch.setattr(settings_module, "CONFIG_FILE", cfg_file) +# Test missing required token raises helpful error +def test_get_settings_missing_token_raises_runtime_error(clean_settings_env): + env_file = clean_settings_env + write_env_file(env_file, {}) with pytest.raises(RuntimeError) as excinfo: get_settings() @@ -96,7 +147,66 @@ def test_get_settings_missing_token_raises_runtime_error(tmp_path, monkeypatch): in msg ) assert "• etm_api_token: Field required" in msg - assert str(cfg_file) in msg + assert str(env_file) in msg + + +# Test defaults when no configuration provided +def test_default_values(clean_settings_env): + env_file = clean_settings_env + write_env_file(env_file, {"ETM_API_TOKEN": "etm_valid.looking.token"}) + + config = AppConfig() + + assert config.etm_api_token == "etm_valid.looking.token" + assert config.environment == "pro" + assert config.log_level == "INFO" + assert config.csv_separator == "," + assert config.decimal_separator == "." + assert config.proxy_servers_http is None + assert config.proxy_servers_https is None + assert config.base_url == HttpUrl("https://engine.energytransitionmodel.com/api/v3") + + +# Test environment inference for different values +@pytest.mark.parametrize( + "env,expected_url", + [ + ("pro", "https://engine.energytransitionmodel.com/api/v3"), + ("beta", "https://beta.engine.energytransitionmodel.com/api/v3"), + ("local", "http://localhost:3000/api/v3"), + ("2025-01", "https://2025-01.engine.energytransitionmodel.com/api/v3"), + ("", "https://engine.energytransitionmodel.com/api/v3"), # default + ("unknown", "https://engine.energytransitionmodel.com/api/v3"), # fallback + ], +) +def test_environment_inference(clean_settings_env, env, expected_url): + env_file = clean_settings_env + env_data = {"ETM_API_TOKEN": "etm_valid.looking.token"} + if env: # Don't add environment key if it's empty string + env_data["ENVIRONMENT"] = env + + write_env_file(env_file, env_data) + + config = AppConfig() + assert config.base_url == HttpUrl(expected_url) + + +# Test explicit base_url overrides environment inference +def test_explicit_base_url_overrides_environment(clean_settings_env): + env_file = clean_settings_env + write_env_file( + env_file, + { + "ETM_API_TOKEN": "etm_valid.looking.token", + "ENVIRONMENT": "beta", + "BASE_URL": "https://custom.override.com/api/v3", + }, + ) + + config = AppConfig() + + assert config.environment == "beta" + assert config.base_url == HttpUrl("https://custom.override.com/api/v3") # VALID TOKENS @@ -111,13 +221,13 @@ def test_get_settings_missing_token_raises_runtime_error(tmp_path, monkeypatch): "IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c", ], ) -def test_valid_etm_api_token_regex(tmp_path, token): - # Write a minimal config.yml with only the token - cfg = tmp_path / "config.yml" - write_yaml(cfg, {"etm_api_token": token}) +def test_valid_etm_api_token_regex(clean_settings_env, token): + env_file = clean_settings_env + write_env_file(env_file, {"ETM_API_TOKEN": token}) + # Should not raise - conf = AppConfig.from_yaml(cfg) - assert conf.etm_api_token == token + config = AppConfig() + assert config.etm_api_token == token # INVALID TOKENS @@ -134,12 +244,46 @@ def test_valid_etm_api_token_regex(tmp_path, token): "etm_beta_eyJhbGci.eyJ zdWIi.abc", ], ) -def test_invalid_etm_api_token_raises(tmp_path, token): - cfg = tmp_path / "config.yml" - write_yaml(cfg, {"etm_api_token": token}) +def test_invalid_etm_api_token_raises(clean_settings_env, token): + env_file = clean_settings_env + write_env_file(env_file, {"ETM_API_TOKEN": token}) + with pytest.raises(ValidationError) as excinfo: - AppConfig.from_yaml(cfg) + AppConfig() errs = excinfo.value.errors() # Should have exactly one error, on the token field assert any(err["loc"] == ("etm_api_token",) for err in errs) assert any("Invalid ETM API token" in err["msg"] for err in errs) + + +# Test temp folder functionality +def test_path_to_tmp_creates_directory(clean_settings_env): + env_file = clean_settings_env + write_env_file(env_file, {"ETM_API_TOKEN": "etm_valid.looking.token"}) + + config = AppConfig() + config.temp_folder = env_file.parent / "custom_tmp" + + result_path = config.path_to_tmp("test_subfolder") + + assert result_path.exists() + assert result_path.is_dir() + assert result_path.name == "test_subfolder" + assert result_path.parent == config.temp_folder + + +# Test quoted values in .env file +def test_quoted_values_in_env_file(clean_settings_env): + env_file = clean_settings_env + content = '''ETM_API_TOKEN=etm_valid.looking.token +LOG_LEVEL="DEBUG WITH SPACES" +CSV_SEPARATOR=";" +PROXY_SERVERS_HTTP="http://user:pass@proxy.example.com:8080"''' + env_file.write_text(content) + + config = AppConfig() + + assert config.etm_api_token == "etm_valid.looking.token" + assert config.log_level == "DEBUG WITH SPACES" + assert config.csv_separator == ";" + assert config.proxy_servers_http == "http://user:pass@proxy.example.com:8080" diff --git a/tests/utils/test_excel.py b/tests/utils/test_excel.py index 4226249..cb074fd 100644 --- a/tests/utils/test_excel.py +++ b/tests/utils/test_excel.py @@ -3,7 +3,7 @@ import numpy as np import tempfile import os -from unittest.mock import Mock +from unittest.mock import Mock, patch, call from xlsxwriter.workbook import Workbook from xlsxwriter.worksheet import Worksheet @@ -13,6 +13,8 @@ set_column_widths, write_index, add_series, + create_scenario_formats, + get_scenario_blocks, ) @@ -66,6 +68,93 @@ def test_handle_zero(self): result = handle_numeric_value(self.mock_worksheet, 0, 0, 0.0, None) self.mock_worksheet.write_number.assert_called_once_with(0, 0, 0.0, None) + def test_handle_negative_number(self): + """Test negative number handling""" + result = handle_numeric_value(self.mock_worksheet, 0, 0, -5.5, None) + self.mock_worksheet.write_number.assert_called_once_with(0, 0, -5.5, None) + + def test_handle_number_with_cell_format(self): + """Test number handling with cell format""" + mock_format = Mock() + result = handle_numeric_value(self.mock_worksheet, 1, 1, 42.0, mock_format) + self.mock_worksheet.write_number.assert_called_once_with( + 1, 1, 42.0, mock_format + ) + + def test_handle_nan_with_cell_format(self): + """Test NaN handling with cell format""" + mock_format = Mock() + result = handle_numeric_value( + self.mock_worksheet, 1, 1, np.nan, mock_format, nan_as_formula=True + ) + self.mock_worksheet.write_formula.assert_called_once_with( + 1, 1, "=NA()", mock_format, "#N/A" + ) + + def test_decimal_precision_edge_cases(self): + """Test decimal precision with edge cases""" + # Test precision = 0 + result = handle_numeric_value( + self.mock_worksheet, 0, 0, 3.14159, None, decimal_precision=0 + ) + args = self.mock_worksheet.write_number.call_args[0] + assert args[2] == 4.0 # Should ceil to 4 + + # Test very high precision + result = handle_numeric_value( + self.mock_worksheet, 0, 0, 1.23456789, None, decimal_precision=15 + ) + self.mock_worksheet.write_number.assert_called_with(0, 0, 1.23456789, None) + + def test_handle_positive_infinity(self): + """Test handling positive infinity""" + # Infinity will cause OverflowError in math.ceil, so it should be handled + # The function should still try to process it, but the math.ceil will fail + with pytest.raises(OverflowError): + handle_numeric_value(self.mock_worksheet, 0, 0, float("inf"), None) + + def test_handle_negative_infinity(self): + """Test handling negative infinity""" + # Negative infinity will cause OverflowError in math.ceil + with pytest.raises(OverflowError): + handle_numeric_value(self.mock_worksheet, 0, 0, float("-inf"), None) + + def test_handle_very_small_number(self): + """Test handling very small numbers""" + very_small = 1e-10 # Use a less extreme small number + result = handle_numeric_value( + self.mock_worksheet, 0, 0, very_small, None, decimal_precision=10 + ) + + # Should write the small number (may be rounded by precision) + args = self.mock_worksheet.write_number.call_args[0] + # Check that it's close to the expected value + assert abs(args[2] - very_small) < 1e-15 + + def test_handle_very_large_number(self): + """Test handling very large numbers""" + very_large = 1e10 # Large but not infinity + result = handle_numeric_value( + self.mock_worksheet, 0, 0, very_large, None, decimal_precision=10 + ) + + # Should write the large number + args = self.mock_worksheet.write_number.call_args[0] + assert args[2] == very_large + + def test_handle_positive_infinity(self): + """Test handling positive infinity""" + # Infinity will cause OverflowError in math.ceil, so it should be handled + # The function should still try to process it, but the math.ceil will fail + with pytest.raises(OverflowError): + handle_numeric_value(self.mock_worksheet, 0, 0, float("inf"), None) + + def test_handle_negative_infinity(self): + """Test handling negative infinity""" + # Negative infinity will cause OverflowError in math.ceil + with pytest.raises(OverflowError): + handle_numeric_value(self.mock_worksheet, 0, 0, float("-inf"), None) + class TestSetColumnWidths: def setup_method(self): @@ -99,6 +188,16 @@ def test_set_list_widths_wrong_length(self): with pytest.raises(ValueError, match="Expected 3 widths, got 2"): set_column_widths(self.mock_worksheet, 0, 3, [10, 15]) + def test_set_single_width_zero_columns(self): + """Test with zero columns""" + set_column_widths(self.mock_worksheet, 5, 0, 10) + self.mock_worksheet.set_column.assert_called_once_with(5, 4, 10) + + def test_set_list_widths_empty_list(self): + """Test with empty list""" + with pytest.raises(ValueError, match="Expected 2 widths, got 0"): + set_column_widths(self.mock_worksheet, 0, 2, []) + class TestWriteIndex: def setup_method(self): @@ -153,6 +252,115 @@ def test_write_index_no_names(self): ] # row_offset - 1 assert len(name_calls) == 0 + def test_write_multiindex_partial_names(self): + """Test writing MultiIndex with some None names""" + index = pd.MultiIndex.from_tuples([("A", 1), ("B", 2)], names=["letter", None]) + + write_index(self.mock_worksheet, index, 1, self.bold_format) + + # Should write only non-None names + name_calls = [ + call for call in self.mock_worksheet.write.call_args_list if call[0][0] == 0 + ] + assert len(name_calls) == 1 + assert name_calls[0][0][2] == "letter" + + def test_write_multiindex_all_none_names(self): + """Test writing MultiIndex with all None names""" + index = pd.MultiIndex.from_tuples([("A", 1), ("B", 2)], names=[None, None]) + + write_index(self.mock_worksheet, index, 1, None) + + # Should not write any names + name_calls = [ + call for call in self.mock_worksheet.write.call_args_list if call[0][0] == 0 + ] + assert len(name_calls) == 0 + + def test_write_empty_index(self): + """Test writing empty index""" + index = pd.Index([], name="empty") + + write_index(self.mock_worksheet, index, 1, self.bold_format) + + # Should write name but no values + name_calls = [ + call for call in self.mock_worksheet.write.call_args_list if call[0][0] == 0 + ] + assert len(name_calls) == 1 + + # Should have no value calls since index is empty + value_calls = [ + call for call in self.mock_worksheet.write.call_args_list if call[0][0] >= 1 + ] + assert len(value_calls) == 0 # No values, only the name + + +class TestCreateScenarioFormats: + def test_create_scenario_formats(self): + """Test scenario format creation""" + mock_workbook = Mock(spec=Workbook) + mock_format = Mock() + mock_workbook.add_format.return_value = mock_format + + formats = create_scenario_formats(mock_workbook) + + # Check all expected formats are created + expected_formats = [ + "white_header", + "grey_header", + "white_data", + "grey_data", + "bold", + ] + for fmt in expected_formats: + assert fmt in formats + assert formats[fmt] == mock_format + + assert formats["default"] is None + assert mock_workbook.add_format.call_count == 5 + + +class TestGetScenarioBlocks: + def test_get_scenario_blocks_simple(self): + """Test scenario block identification""" + columns = pd.MultiIndex.from_tuples( + [ + ("Scenario1", "A"), + ("Scenario1", "B"), + ("Scenario2", "C"), + ("Scenario2", "D"), + ("Scenario3", "E"), + ] + ) + + blocks = get_scenario_blocks(columns) + + expected = [("Scenario1", 0, 1), ("Scenario2", 2, 3), ("Scenario3", 4, 4)] + assert blocks == expected + + def test_get_scenario_blocks_single_index(self): + """Test with single-level index""" + columns = pd.Index(["A", "B", "C"]) + blocks = get_scenario_blocks(columns) + assert blocks == [] + + def test_get_scenario_blocks_empty(self): + """Test with empty MultiIndex""" + columns = pd.MultiIndex.from_tuples([], names=["scenario", "variable"]) + blocks = get_scenario_blocks(columns) + assert blocks == [] + + def test_get_scenario_blocks_single_scenario(self): + """Test with single scenario""" + columns = pd.MultiIndex.from_tuples( + [("OnlyScenario", "A"), ("OnlyScenario", "B"), ("OnlyScenario", "C")] + ) + + blocks = get_scenario_blocks(columns) + expected = [("OnlyScenario", 0, 2)] + assert blocks == expected + class TestAddSeries: """Test add_series function""" @@ -223,6 +431,310 @@ def test_add_series_multiindex(self): assert worksheet is not None workbook.close() + def test_add_series_no_index(self): + """Test adding Series without writing index""" + series = pd.Series([1, 2, 3], name="values") + + file_path = os.path.join(self.temp_dir, "test_series_no_index.xlsx") + workbook = Workbook(file_path, {"nan_inf_to_errors": True}) + + worksheet = add_series("NoIndex", series, workbook, index=False) + + assert worksheet is not None + workbook.close() + + def test_add_series_custom_widths(self): + """Test adding Series with custom column widths""" + series = pd.Series([1, 2, 3], index=["A", "B", "C"], name="values") + + file_path = os.path.join(self.temp_dir, "test_series_widths.xlsx") + workbook = Workbook(file_path, {"nan_inf_to_errors": True}) + + worksheet = add_series( + "CustomWidths", series, workbook, column_width=20, index_width=10 + ) + + assert worksheet is not None + workbook.close() + + def test_add_series_no_freeze_panes(self): + """Test adding Series without freezing panes""" + series = pd.Series([1, 2, 3], name="values") + + file_path = os.path.join(self.temp_dir, "test_series_no_freeze.xlsx") + workbook = Workbook(file_path, {"nan_inf_to_errors": True}) + + worksheet = add_series("NoFreeze", series, workbook, freeze_panes=False) + + assert worksheet is not None + workbook.close() + + def test_add_series_no_bold_headers(self): + """Test adding Series without bold headers""" + series = pd.Series([1, 2, 3], name="values") + + file_path = os.path.join(self.temp_dir, "test_series_no_bold.xlsx") + workbook = Workbook(file_path, {"nan_inf_to_errors": True}) + + worksheet = add_series("NoBold", series, workbook, bold_headers=False) + + assert worksheet is not None + workbook.close() + + def test_add_series_list_name(self): + """Test adding Series with tuple name (lists aren't hashable for Series names)""" + # Series names must be hashable, so use tuple instead of list + series = pd.Series([1, 2, 3], name=("part1", "part2", "part3")) + + file_path = os.path.join(self.temp_dir, "test_series_tuple_name.xlsx") + workbook = Workbook(file_path, {"nan_inf_to_errors": True}) + + worksheet = add_series("TupleName", series, workbook) + + assert worksheet is not None + workbook.close() + + def test_add_series_multiindex_with_index_width_list(self): + """Test adding Series with MultiIndex and list of index widths""" + index = pd.MultiIndex.from_tuples( + [("A", 1), ("B", 2)], names=["letter", "number"] + ) + series = pd.Series([10, 20], index=index, name="values") + + file_path = os.path.join(self.temp_dir, "test_series_multi_widths.xlsx") + workbook = Workbook(file_path, {"nan_inf_to_errors": True}) + + worksheet = add_series("MultiWidths", series, workbook, index_width=[15, 10]) + + assert worksheet is not None + workbook.close() + + +class TestAddFrame: + """Test add_frame function with comprehensive coverage""" + + def setup_method(self): + """Setup test data""" + self.temp_dir = tempfile.mkdtemp() + + def teardown_method(self): + """Clean up temp files""" + import shutil + + shutil.rmtree(self.temp_dir, ignore_errors=True) + + def test_add_frame_multiindex_scenario_styling(self): + """Test DataFrame with MultiIndex columns and scenario styling""" + columns = pd.MultiIndex.from_tuples( + [ + ("Scenario1", "A"), + ("Scenario1", "B"), + ("Scenario2", "C"), + ("Scenario2", "D"), + ], + names=["scenario", "variable"], + ) + + df = pd.DataFrame( + [[1, 2, 3, 4], [5, 6, 7, 8]], columns=columns, index=["row1", "row2"] + ) + + file_path = os.path.join(self.temp_dir, "test_multiindex_scenario.xlsx") + workbook = Workbook(file_path, {"nan_inf_to_errors": True}) + + worksheet = add_frame("MultiScenario", df, workbook, scenario_styling=True) + + assert worksheet is not None + workbook.close() + + def test_add_frame_multiindex_no_scenario_styling(self): + """Test DataFrame with MultiIndex columns but no scenario styling""" + columns = pd.MultiIndex.from_tuples( + [("Level1", "A"), ("Level1", "B"), ("Level2", "C")], + names=["level1", "level2"], + ) + + df = pd.DataFrame([[1, 2, 3]], columns=columns) + + file_path = os.path.join(self.temp_dir, "test_multiindex_no_scenario.xlsx") + workbook = Workbook(file_path, {"nan_inf_to_errors": True}) + + worksheet = add_frame("MultiNoScenario", df, workbook, scenario_styling=False) + + assert worksheet is not None + workbook.close() + + def test_add_frame_single_index_scenario_styling(self): + """Test DataFrame with single-level columns and scenario styling""" + df = pd.DataFrame( + {"Col1": [1, 2], "Col2": [3, 4], "Col3": [5, 6], "Col4": [7, 8]} + ) + + file_path = os.path.join(self.temp_dir, "test_single_scenario.xlsx") + workbook = Workbook(file_path, {"nan_inf_to_errors": True}) + + worksheet = add_frame("SingleScenario", df, workbook, scenario_styling=True) + + assert worksheet is not None + workbook.close() + + def test_add_frame_single_index_no_scenario_styling(self): + """Test DataFrame with single-level columns and no scenario styling""" + df = pd.DataFrame({"A": [1, 2], "B": [3, 4]}) + + file_path = os.path.join(self.temp_dir, "test_single_no_scenario.xlsx") + workbook = Workbook(file_path, {"nan_inf_to_errors": True}) + + worksheet = add_frame("SingleNoScenario", df, workbook, scenario_styling=False) + + assert worksheet is not None + workbook.close() + + def test_add_frame_no_index(self): + """Test DataFrame without writing index""" + df = pd.DataFrame({"A": [1, 2], "B": [3, 4]}) + + file_path = os.path.join(self.temp_dir, "test_no_index.xlsx") + workbook = Workbook(file_path, {"nan_inf_to_errors": True}) + + worksheet = add_frame("NoIndex", df, workbook, index=False) + + assert worksheet is not None + workbook.close() + + def test_add_frame_multiindex_data_index(self): + """Test DataFrame with MultiIndex for rows""" + index = pd.MultiIndex.from_tuples([("A", 1), ("A", 2), ("B", 1)]) + df = pd.DataFrame({"col1": [1, 2, 3], "col2": [4, 5, 6]}, index=index) + + file_path = os.path.join(self.temp_dir, "test_multiindex_rows.xlsx") + workbook = Workbook(file_path, {"nan_inf_to_errors": True}) + + worksheet = add_frame("MultiRows", df, workbook) + + assert worksheet is not None + workbook.close() + + def test_add_frame_index_widths_list(self): + """Test DataFrame with list of index widths""" + index = pd.MultiIndex.from_tuples([("A", 1), ("B", 2)]) + df = pd.DataFrame({"col": [1, 2]}, index=index) + + file_path = os.path.join(self.temp_dir, "test_index_widths_list.xlsx") + workbook = Workbook(file_path, {"nan_inf_to_errors": True}) + + worksheet = add_frame("IndexWidthsList", df, workbook, index_width=[15, 10]) + + assert worksheet is not None + workbook.close() + + def test_add_frame_no_freeze_panes(self): + """Test DataFrame without freezing panes""" + df = pd.DataFrame({"A": [1, 2], "B": [3, 4]}) + + file_path = os.path.join(self.temp_dir, "test_no_freeze_panes.xlsx") + workbook = Workbook(file_path, {"nan_inf_to_errors": True}) + + worksheet = add_frame("NoFreeze", df, workbook, freeze_panes=False) + + assert worksheet is not None + workbook.close() + + def test_add_frame_no_bold_headers(self): + """Test DataFrame without bold headers""" + df = pd.DataFrame({"A": [1, 2], "B": [3, 4]}) + + file_path = os.path.join(self.temp_dir, "test_no_bold.xlsx") + workbook = Workbook(file_path, {"nan_inf_to_errors": True}) + + worksheet = add_frame("NoBold", df, workbook, bold_headers=False) + + assert worksheet is not None + workbook.close() + + def test_add_frame_custom_precision(self): + """Test DataFrame with custom decimal precision""" + df = pd.DataFrame({"A": [1.123456789], "B": [2.987654321]}) + + file_path = os.path.join(self.temp_dir, "test_precision.xlsx") + workbook = Workbook(file_path, {"nan_inf_to_errors": True}) + + worksheet = add_frame("Precision", df, workbook, decimal_precision=3) + + assert worksheet is not None + workbook.close() + + def test_add_frame_nan_as_text(self): + """Test DataFrame with NaN values as text""" + df = pd.DataFrame({"A": [1, np.nan], "B": [np.nan, 2]}) + + file_path = os.path.join(self.temp_dir, "test_nan_text.xlsx") + workbook = Workbook(file_path, {"nan_inf_to_errors": True}) + + worksheet = add_frame("NaNText", df, workbook, nan_as_formula=False) + + assert worksheet is not None + workbook.close() + + def test_add_frame_multiindex_columns_no_names(self): + """Test DataFrame with MultiIndex columns having no names""" + columns = pd.MultiIndex.from_tuples([("A", 1), ("B", 2)]) + df = pd.DataFrame([[1, 2]], columns=columns) + + file_path = os.path.join(self.temp_dir, "test_multiindex_no_col_names.xlsx") + workbook = Workbook(file_path, {"nan_inf_to_errors": True}) + + worksheet = add_frame("MultiNoColNames", df, workbook) + + assert worksheet is not None + workbook.close() + + def test_add_frame_multiindex_columns_partial_names(self): + """Test DataFrame with MultiIndex columns having partial names""" + columns = pd.MultiIndex.from_tuples( + [("A", 1), ("B", 2)], names=["level1", None] + ) + df = pd.DataFrame([[1, 2]], columns=columns) + + file_path = os.path.join( + self.temp_dir, "test_multiindex_partial_col_names.xlsx" + ) + workbook = Workbook(file_path, {"nan_inf_to_errors": True}) + + worksheet = add_frame("MultiPartialColNames", df, workbook) + + assert worksheet is not None + workbook.close() + + def test_add_frame_single_scenario_block(self): + """Test DataFrame with single scenario in MultiIndex""" + columns = pd.MultiIndex.from_tuples( + [("OnlyScenario", "A"), ("OnlyScenario", "B")] + ) + df = pd.DataFrame([[1, 2]], columns=columns) + + file_path = os.path.join(self.temp_dir, "test_single_scenario_block.xlsx") + workbook = Workbook(file_path, {"nan_inf_to_errors": True}) + + worksheet = add_frame( + "SingleScenarioBlock", df, workbook, scenario_styling=True + ) + + assert worksheet is not None + workbook.close() + + def test_add_frame_empty_dataframe(self): + """Test with empty DataFrame""" + df = pd.DataFrame() + + file_path = os.path.join(self.temp_dir, "test_empty.xlsx") + workbook = Workbook(file_path, {"nan_inf_to_errors": True}) + + worksheet = add_frame("Empty", df, workbook) + + assert worksheet is not None + workbook.close() + class TestIntegration: @@ -289,3 +801,424 @@ def test_edge_cases(self): workbook.close() assert os.path.exists(file_path) + + def test_complex_multiindex_scenario(self): + """Test complex scenario with multiple MultiIndex features""" + # Create complex MultiIndex for both rows and columns + row_index = pd.MultiIndex.from_tuples( + [ + ("Region1", "City1"), + ("Region1", "City2"), + ("Region2", "City3"), + ("Region2", "City4"), + ], + names=["Region", "City"], + ) + + col_index = pd.MultiIndex.from_tuples( + [ + ("Scenario1", "Metric1"), + ("Scenario1", "Metric2"), + ("Scenario2", "Metric1"), + ("Scenario2", "Metric2"), + ("Scenario3", "Metric1"), + ], + names=["Scenario", "Metric"], + ) + + df = pd.DataFrame(np.random.rand(4, 5), index=row_index, columns=col_index) + + # Add some NaN values + df.iloc[1, 2] = np.nan + df.iloc[3, 4] = np.nan + + file_path = os.path.join(self.temp_dir, "complex_multiindex.xlsx") + workbook = Workbook(file_path, {"nan_inf_to_errors": True}) + + worksheet = add_frame( + "ComplexMulti", + df, + workbook, + scenario_styling=True, + column_width=[12, 15, 10, 8, 20], + index_width=[15, 12], + decimal_precision=4, + ) + + assert worksheet is not None + workbook.close() + + def test_all_formatting_options(self): + """Test all formatting and styling options together""" + df = pd.DataFrame( + { + "A": [1.123456789, np.nan, 3.987654321], + "B": [np.nan, 2.555555555, 4.111111111], + "C": [5.999999999, 6.000000001, np.nan], + }, + index=["row1", "row2", "row3"], + ) + + file_path = os.path.join(self.temp_dir, "all_formatting.xlsx") + workbook = Workbook(file_path, {"nan_inf_to_errors": True}) + + # Test with all options enabled + worksheet = add_frame( + "AllFormatting", + df, + workbook, + index=True, + column_width=15, + index_width=12, + freeze_panes=True, + bold_headers=True, + nan_as_formula=True, + decimal_precision=6, + scenario_styling=True, + ) + + assert worksheet is not None + workbook.close() + + def test_mixed_data_types(self): + """Test DataFrame with mixed data types""" + df = pd.DataFrame( + { + "integers": [1, 2, 3], + "floats": [1.1, 2.2, np.nan], + "strings": ["a", "b", "c"], + "booleans": [True, False, True], + "dates": pd.date_range("2024-01-01", periods=3), + } + ) + + file_path = os.path.join(self.temp_dir, "mixed_types.xlsx") + workbook = Workbook(file_path, {"nan_inf_to_errors": True}) + + worksheet = add_frame("MixedTypes", df, workbook) + + assert worksheet is not None + workbook.close() + + def test_very_large_precision_values(self): + """Test with very large numbers and high precision""" + df = pd.DataFrame( + { + "large_numbers": [1234567890.123456789, 9876543210.987654321], + "small_numbers": [0.000000001, 0.000000002], + } + ) + + file_path = os.path.join(self.temp_dir, "large_precision.xlsx") + workbook = Workbook(file_path, {"nan_inf_to_errors": True}) + + worksheet = add_frame("LargePrecision", df, workbook, decimal_precision=15) + + assert worksheet is not None + workbook.close() + + +class TestErrorConditions: + """Test error conditions and edge cases""" + + def setup_method(self): + """Setup test data""" + self.temp_dir = tempfile.mkdtemp() + + def teardown_method(self): + """Clean up temp files""" + import shutil + + shutil.rmtree(self.temp_dir, ignore_errors=True) + + def test_column_width_list_mismatch(self): + """Test error when column width list doesn't match column count""" + df = pd.DataFrame({"A": [1], "B": [2], "C": [3]}) + + file_path = os.path.join(self.temp_dir, "width_mismatch.xlsx") + workbook = Workbook(file_path, {"nan_inf_to_errors": True}) + + with pytest.raises(ValueError, match="Expected 3 widths, got 2"): + add_frame("WidthMismatch", df, workbook, column_width=[10, 15]) + + workbook.close() + + def test_index_width_list_mismatch(self): + """Test error when index width list doesn't match index levels""" + index = pd.MultiIndex.from_tuples([("A", 1), ("B", 2)]) + df = pd.DataFrame({"col": [1, 2]}, index=index) + + file_path = os.path.join(self.temp_dir, "index_width_mismatch.xlsx") + workbook = Workbook(file_path, {"nan_inf_to_errors": True}) + + with pytest.raises(ValueError, match="Expected 2 widths, got 1"): + add_frame("IndexWidthMismatch", df, workbook, index_width=[10]) + + workbook.close() + + def test_series_index_width_mismatch(self): + """Test error when series index width list doesn't match index levels""" + index = pd.MultiIndex.from_tuples([("A", 1), ("B", 2)]) + series = pd.Series([1, 2], index=index) + + file_path = os.path.join(self.temp_dir, "series_width_mismatch.xlsx") + workbook = Workbook(file_path, {"nan_inf_to_errors": True}) + + with pytest.raises(ValueError, match="Expected 2 widths, got 3"): + add_series( + "SeriesWidthMismatch", series, workbook, index_width=[10, 15, 20] + ) + + workbook.close() + + +class TestScenarioStylingEdgeCases: + """Test edge cases in scenario styling""" + + def setup_method(self): + """Setup test data""" + self.temp_dir = tempfile.mkdtemp() + + def teardown_method(self): + """Clean up temp files""" + import shutil + + shutil.rmtree(self.temp_dir, ignore_errors=True) + + def test_odd_number_of_scenario_blocks(self): + """Test scenario styling with odd number of blocks""" + columns = pd.MultiIndex.from_tuples( + [("Scenario1", "A"), ("Scenario2", "B"), ("Scenario3", "C")] + ) + df = pd.DataFrame([[1, 2, 3]], columns=columns) + + file_path = os.path.join(self.temp_dir, "odd_scenarios.xlsx") + workbook = Workbook(file_path, {"nan_inf_to_errors": True}) + + worksheet = add_frame("OddScenarios", df, workbook, scenario_styling=True) + + assert worksheet is not None + workbook.close() + + def test_single_column_per_scenario(self): + """Test scenario styling with single column per scenario""" + columns = pd.MultiIndex.from_tuples( + [ + ("Scenario1", "A"), + ("Scenario2", "B"), + ("Scenario3", "C"), + ("Scenario4", "D"), + ] + ) + df = pd.DataFrame([[1, 2, 3, 4]], columns=columns) + + file_path = os.path.join(self.temp_dir, "single_col_scenarios.xlsx") + workbook = Workbook(file_path, {"nan_inf_to_errors": True}) + + worksheet = add_frame("SingleColScenarios", df, workbook, scenario_styling=True) + + assert worksheet is not None + workbook.close() + + def test_uneven_scenario_blocks(self): + """Test scenario styling with uneven block sizes""" + columns = pd.MultiIndex.from_tuples( + [ + ("Scenario1", "A"), + ("Scenario1", "B"), + ("Scenario1", "C"), # 3 columns + ("Scenario2", "D"), # 1 column + ("Scenario3", "E"), + ("Scenario3", "F"), # 2 columns + ] + ) + df = pd.DataFrame([[1, 2, 3, 4, 5, 6]], columns=columns) + + file_path = os.path.join(self.temp_dir, "uneven_scenarios.xlsx") + workbook = Workbook(file_path, {"nan_inf_to_errors": True}) + + worksheet = add_frame("UnevenScenarios", df, workbook, scenario_styling=True) + + assert worksheet is not None + workbook.close() + + +class TestWorksheetNameHandling: + """Test worksheet name handling edge cases""" + + def setup_method(self): + """Setup test data""" + self.temp_dir = tempfile.mkdtemp() + + def teardown_method(self): + """Clean up temp files""" + import shutil + + shutil.rmtree(self.temp_dir, ignore_errors=True) + + def test_numeric_worksheet_name(self): + """Test with numeric worksheet name""" + df = pd.DataFrame({"A": [1, 2]}) + + file_path = os.path.join(self.temp_dir, "numeric_name.xlsx") + workbook = Workbook(file_path, {"nan_inf_to_errors": True}) + + worksheet = add_frame(123, df, workbook) + + assert worksheet is not None + assert worksheet.name == "123" + workbook.close() + + def test_float_worksheet_name(self): + """Test with float worksheet name""" + df = pd.DataFrame({"A": [1, 2]}) + + file_path = os.path.join(self.temp_dir, "float_name.xlsx") + workbook = Workbook(file_path, {"nan_inf_to_errors": True}) + + worksheet = add_frame(45.67, df, workbook) + + assert worksheet is not None + assert worksheet.name == "45.67" + workbook.close() + + def test_none_worksheet_name(self): + """Test with None worksheet name""" + df = pd.DataFrame({"A": [1, 2]}) + + file_path = os.path.join(self.temp_dir, "none_name.xlsx") + workbook = Workbook(file_path, {"nan_inf_to_errors": True}) + + worksheet = add_frame(None, df, workbook) + + assert worksheet is not None + assert worksheet.name == "None" + workbook.close() + + def test_series_numeric_worksheet_name(self): + """Test Series with numeric worksheet name""" + series = pd.Series([1, 2, 3], name="values") + + file_path = os.path.join(self.temp_dir, "series_numeric_name.xlsx") + workbook = Workbook(file_path, {"nan_inf_to_errors": True}) + + worksheet = add_series(999, series, workbook) + + assert worksheet is not None + assert worksheet.name == "999" + workbook.close() + + +class TestAdditionalCoverageEdgeCases: + """Additional tests to ensure 100% coverage""" + + def setup_method(self): + """Setup test data""" + self.temp_dir = tempfile.mkdtemp() + + def teardown_method(self): + """Clean up temp files""" + import shutil + + shutil.rmtree(self.temp_dir, ignore_errors=True) + + def test_add_frame_multiindex_no_scenario_data_writing(self): + """Test MultiIndex DataFrame data writing without scenario styling""" + columns = pd.MultiIndex.from_tuples( + [("Level1", "A"), ("Level1", "B"), ("Level2", "C")], + names=["level1", "level2"], + ) + + df = pd.DataFrame( + [[1.1, 2.2, 3.3], [4.4, 5.5, 6.6]], columns=columns, index=["row1", "row2"] + ) + + file_path = os.path.join(self.temp_dir, "test_multiindex_data_writing.xlsx") + workbook = Workbook(file_path, {"nan_inf_to_errors": True}) + + worksheet = add_frame("MultiData", df, workbook, scenario_styling=False) + + assert worksheet is not None + workbook.close() + + def test_scenario_blocks_next_function_edge_case(self): + """Test the next() function edge case in scenario block detection""" + columns = pd.MultiIndex.from_tuples( + [ + ("Scenario1", "A"), + ("Scenario1", "B"), + ("Scenario2", "C"), + ("Scenario2", "D"), + ] + ) + df = pd.DataFrame([[1, 2, 3, 4]], columns=columns) + + file_path = os.path.join(self.temp_dir, "test_scenario_next.xlsx") + workbook = Workbook(file_path, {"nan_inf_to_errors": True}) + + # This should exercise the scenario_idx calculation in both header and data writing + worksheet = add_frame("ScenarioNext", df, workbook, scenario_styling=True) + + assert worksheet is not None + workbook.close() + + def test_column_width_fallback_to_default(self): + """Test when index_width falls back to column_width""" + df = pd.DataFrame({"A": [1, 2]}, index=["x", "y"]) + + file_path = os.path.join(self.temp_dir, "test_width_fallback.xlsx") + workbook = Workbook(file_path, {"nan_inf_to_errors": True}) + + # index_width=None should fall back to column_width + worksheet = add_frame( + "WidthFallback", df, workbook, column_width=20, index_width=None + ) + + assert worksheet is not None + workbook.close() + + def test_series_column_width_setting(self): + """Test series column width setting when column_width is None""" + series = pd.Series([1, 2, 3], name="test") + + file_path = os.path.join(self.temp_dir, "test_series_no_width.xlsx") + workbook = Workbook(file_path, {"nan_inf_to_errors": True}) + + worksheet = add_series("SeriesNoWidth", series, workbook, column_width=None) + + assert worksheet is not None + workbook.close() + + def test_series_index_width_fallback(self): + """Test series index width fallback to column width""" + series = pd.Series([1, 2, 3], index=["a", "b", "c"], name="test") + + file_path = os.path.join(self.temp_dir, "test_series_index_fallback.xlsx") + workbook = Workbook(file_path, {"nan_inf_to_errors": True}) + + # index_width=None should fall back to column_width + worksheet = add_series( + "SeriesIndexFallback", series, workbook, column_width=15, index_width=None + ) + + assert worksheet is not None + workbook.close() + + def test_get_scenario_blocks_edge_coverage(self): + """Test get_scenario_blocks function edge cases for complete coverage""" + # Test completely empty MultiIndex + empty_columns = pd.MultiIndex.from_tuples([], names=["scenario", "variable"]) + blocks = get_scenario_blocks(empty_columns) + assert blocks == [] + + # Test with repeating scenario changes + columns = pd.MultiIndex.from_tuples( + [("A", "1"), ("B", "1"), ("A", "2"), ("B", "2"), ("A", "3")] + ) + blocks = get_scenario_blocks(columns) + expected = [("A", 0, 0), ("B", 1, 1), ("A", 2, 2), ("B", 3, 3), ("A", 4, 4)] + assert blocks == expected + + +if __name__ == "__main__": + pytest.main([__file__, "-v", "--tb=short"]) diff --git a/tests/utils/test_pyetm_paths.py b/tests/utils/test_pyetm_paths.py new file mode 100644 index 0000000..966d711 --- /dev/null +++ b/tests/utils/test_pyetm_paths.py @@ -0,0 +1,326 @@ +import pytest +from pathlib import Path +import tempfile +import shutil +from unittest.mock import patch + +from pyetm.utils.paths import PyetmPaths + + +class TestPyetmPaths: + + @pytest.fixture + def temp_project_structure(self): + """Create a temporary project structure for testing.""" + with tempfile.TemporaryDirectory() as temp_dir: + temp_path = Path(temp_dir) + + # Create project structure + project_root = temp_path / "project" + project_root.mkdir() + + inputs_dir = project_root / "inputs" + outputs_dir = project_root / "outputs" + inputs_dir.mkdir() + outputs_dir.mkdir() + + # Create some test files + (inputs_dir / "test_file.txt").write_text("test content") + (inputs_dir / "subdir").mkdir() + (inputs_dir / "subdir" / "nested_file.txt").write_text("nested content") + + yield { + "temp_dir": temp_path, + "project_root": project_root, + "inputs_dir": inputs_dir, + "outputs_dir": outputs_dir, + } + + def test_init_default(self): + """Test PyetmPaths initialization with default parameters.""" + paths = PyetmPaths() + assert paths._start == Path.cwd() + + def test_init_with_start_path(self): + """Test PyetmPaths initialization with custom start path.""" + start_path = Path("/custom/start") + paths = PyetmPaths(start=start_path) + assert paths._start == start_path + + def test_init_with_string_start(self): + """Test PyetmPaths initialization with string start path.""" + start_str = "/custom/start" + paths = PyetmPaths(start=start_str) + assert paths._start == Path(start_str) + + def test_find_root_with_existing_dir(self, temp_project_structure): + """Test _find_root_with when the directory exists.""" + project_root = temp_project_structure["project_root"] + + result = PyetmPaths._find_root_with("inputs", project_root) + assert result == project_root + + def test_find_root_with_nonexistent_dir(self): + """Test _find_root_with when directory doesn't exist.""" + with tempfile.TemporaryDirectory() as temp_dir: + temp_path = Path(temp_dir) + result = PyetmPaths._find_root_with("nonexistent", temp_path) + # Should return the start directory when nothing is found + assert result == temp_path + + def test_find_root_with_parent_search(self, temp_project_structure): + """Test _find_root_with searches parent directories.""" + project_root = temp_project_structure["project_root"] + subdir = project_root / "deep" / "nested" / "path" + subdir.mkdir(parents=True) + + result = PyetmPaths._find_root_with("inputs", subdir) + assert result == project_root + + def test_find_root_with_permission_error(self): + """Test _find_root_with handles permission errors gracefully.""" + with tempfile.TemporaryDirectory() as temp_dir: + temp_path = Path(temp_dir) + + # Mock Path.exists to raise an exception + with patch.object( + Path, "exists", side_effect=PermissionError("Access denied") + ): + result = PyetmPaths._find_root_with("inputs", temp_path) + assert result == temp_path + + def test_inputs_dir(self, temp_project_structure): + """Test inputs_dir method.""" + project_root = temp_project_structure["project_root"] + paths = PyetmPaths(start=project_root) + + result = paths.inputs_dir() + assert result == project_root / "inputs" + assert result.exists() + + def test_outputs_dir(self, temp_project_structure): + """Test outputs_dir method.""" + project_root = temp_project_structure["project_root"] + paths = PyetmPaths(start=project_root) + + result = paths.outputs_dir() + assert result == project_root / "outputs" + assert result.exists() + + def test_resolve_for_read_absolute_path(self): + """Test resolve_for_read with absolute path.""" + paths = PyetmPaths() + abs_path = Path("/absolute/path/file.txt") + + result = paths.resolve_for_read(abs_path) + assert result == abs_path + + def test_resolve_for_read_existing_relative_path(self, temp_project_structure): + """Test resolve_for_read with existing relative path.""" + project_root = temp_project_structure["project_root"] + paths = PyetmPaths(start=project_root) + + # Create a file in the current directory relative to project_root + test_file = project_root / "local_file.txt" + test_file.write_text("local content") + + with patch("pathlib.Path.cwd", return_value=project_root): + result = paths.resolve_for_read("local_file.txt") + assert result == Path("local_file.txt") + + def test_resolve_for_read_nonexistent_relative_path_found_in_inputs( + self, temp_project_structure + ): + """Test resolve_for_read with nonexistent relative path that exists in inputs.""" + project_root = temp_project_structure["project_root"] + paths = PyetmPaths(start=project_root) + + result = paths.resolve_for_read("test_file.txt") + assert result == project_root / "inputs" / "test_file.txt" + assert result.exists() + + def test_resolve_for_read_nonexistent_relative_path_not_found( + self, temp_project_structure + ): + """Test resolve_for_read with nonexistent relative path that doesn't exist anywhere.""" + project_root = temp_project_structure["project_root"] + paths = PyetmPaths(start=project_root) + + result = paths.resolve_for_read("nonexistent.txt") + # Should return the original path when not found + assert result == Path("nonexistent.txt") + + def test_resolve_for_read_with_subdirectory(self, temp_project_structure): + """Test resolve_for_read with subdirectory paths.""" + project_root = temp_project_structure["project_root"] + paths = PyetmPaths(start=project_root) + + result = paths.resolve_for_read("subdir/nested_file.txt") + assert result == project_root / "inputs" / "subdir" / "nested_file.txt" + assert result.exists() + + def test_resolve_for_read_custom_default_dir(self, temp_project_structure): + """Test resolve_for_read with custom default directory.""" + project_root = temp_project_structure["project_root"] + custom_dir = project_root / "custom" + custom_dir.mkdir() + (custom_dir / "custom_file.txt").write_text("custom content") + + paths = PyetmPaths(start=project_root) + result = paths.resolve_for_read("custom_file.txt", default_dir="custom") + assert result == custom_dir / "custom_file.txt" + assert result.exists() + + def test_resolve_for_read_string_input(self, temp_project_structure): + """Test resolve_for_read with string input.""" + project_root = temp_project_structure["project_root"] + paths = PyetmPaths(start=project_root) + + result = paths.resolve_for_read("test_file.txt") + assert result == project_root / "inputs" / "test_file.txt" + assert result.exists() + + def test_resolve_for_write_absolute_path(self): + """Test resolve_for_write with absolute path.""" + with tempfile.TemporaryDirectory() as temp_dir: + paths = PyetmPaths() + abs_path = Path(temp_dir) / "output.txt" + + result = paths.resolve_for_write(abs_path) + assert result == abs_path + # Parent should be created + assert result.parent.exists() + + def test_resolve_for_write_absolute_path_no_create_parents(self): + """Test resolve_for_write with absolute path and create_parents=False.""" + with tempfile.TemporaryDirectory() as temp_dir: + paths = PyetmPaths() + abs_path = Path(temp_dir) / "nested" / "deep" / "output.txt" + + result = paths.resolve_for_write(abs_path, create_parents=False) + assert result == abs_path + # Parent should NOT be created + assert not result.parent.exists() + + def test_resolve_for_write_relative_path(self, temp_project_structure): + """Test resolve_for_write with relative path.""" + project_root = temp_project_structure["project_root"] + paths = PyetmPaths(start=project_root) + + result = paths.resolve_for_write("output.txt") + assert result == project_root / "outputs" / "output.txt" + assert result.parent.exists() + + def test_resolve_for_write_relative_path_with_subdirs(self, temp_project_structure): + """Test resolve_for_write with relative path containing subdirectories.""" + project_root = temp_project_structure["project_root"] + paths = PyetmPaths(start=project_root) + + result = paths.resolve_for_write("subdir/nested/output.txt") + expected = project_root / "outputs" / "subdir" / "nested" / "output.txt" + assert result == expected + assert result.parent.exists() + + def test_resolve_for_write_custom_default_dir(self, temp_project_structure): + """Test resolve_for_write with custom default directory.""" + project_root = temp_project_structure["project_root"] + paths = PyetmPaths(start=project_root) + + result = paths.resolve_for_write("output.txt", default_dir="custom") + expected = project_root / "custom" / "output.txt" + assert result == expected + assert result.parent.exists() + + def test_resolve_for_write_string_input(self, temp_project_structure): + """Test resolve_for_write with string input.""" + project_root = temp_project_structure["project_root"] + paths = PyetmPaths(start=project_root) + + result = paths.resolve_for_write("output.txt") + assert result == project_root / "outputs" / "output.txt" + assert result.parent.exists() + + def test_pathlike_type_annotation(self): + """Test that PathLikeOrStr type annotation works correctly.""" + paths = PyetmPaths() + + # Test with string + result1 = paths.resolve_for_read("test.txt") + assert isinstance(result1, Path) + + # Test with Path + result2 = paths.resolve_for_read(Path("test.txt")) + assert isinstance(result2, Path) + + def test_edge_case_empty_string(self, temp_project_structure): + """Test edge case with empty string path.""" + project_root = temp_project_structure["project_root"] + paths = PyetmPaths(start=project_root) + + result = paths.resolve_for_read("") + # Empty string should be treated as current directory + assert result == Path("") + + def test_edge_case_dot_path(self, temp_project_structure): + """Test edge case with dot (current directory) path.""" + project_root = temp_project_structure["project_root"] + paths = PyetmPaths(start=project_root) + + with patch("pathlib.Path.cwd", return_value=project_root): + result = paths.resolve_for_read(".") + assert result == Path(".") + + def test_complex_project_structure(self): + """Test with a more complex, realistic project structure.""" + with tempfile.TemporaryDirectory() as temp_dir: + temp_path = Path(temp_dir) + + # Create nested project structure + project = temp_path / "my_project" + project.mkdir() + (project / "inputs").mkdir() + (project / "outputs").mkdir() + + src = project / "src" / "deep" / "nested" + src.mkdir(parents=True) + + # Test from deep nested location + paths = PyetmPaths(start=src) + + inputs_dir = paths.inputs_dir() + outputs_dir = paths.outputs_dir() + + assert inputs_dir == project / "inputs" + assert outputs_dir == project / "outputs" + + @pytest.mark.parametrize( + "path_input,expected_type", + [ + ("string_path.txt", str), + (Path("path_object.txt"), Path), + ], + ) + def test_path_input_types(self, path_input, expected_type, temp_project_structure): + """Test that both string and Path inputs are handled correctly.""" + project_root = temp_project_structure["project_root"] + paths = PyetmPaths(start=project_root) + + result_read = paths.resolve_for_read(path_input) + result_write = paths.resolve_for_write(path_input) + + assert isinstance(result_read, Path) + assert isinstance(result_write, Path) + + def test_concurrent_access_safety(self, temp_project_structure): + """Test that the class behaves correctly with multiple instances.""" + project_root = temp_project_structure["project_root"] + + paths1 = PyetmPaths(start=project_root) + paths2 = PyetmPaths(start=project_root / "inputs") + + result1 = paths1.resolve_for_read("test_file.txt") + result2 = paths2.resolve_for_read("test_file.txt") + + # Both should work independently + assert isinstance(result1, Path) + assert isinstance(result2, Path) From 54e7cf796571cbc1cff6eb65e4146419e0ba582d Mon Sep 17 00:00:00 2001 From: louispt1 Date: Mon, 18 Aug 2025 10:42:39 +0200 Subject: [PATCH 15/19] Inprovements to caching and DRY --- examples/create_or_query_scenarios.ipynb | 2 +- inputs/example_input_excel.xlsx | Bin 1377008 -> 1377033 bytes src/pyetm/models/inputs.py | 25 ++++---- src/pyetm/models/output_curves.py | 59 +++++++++++++------ src/pyetm/models/scenario.py | 39 ++++++------ src/pyetm/models/scenario_packer.py | 72 ++++++++++++++++++----- 6 files changed, 130 insertions(+), 67 deletions(-) diff --git a/examples/create_or_query_scenarios.ipynb b/examples/create_or_query_scenarios.ipynb index 8ca6790..b956058 100644 --- a/examples/create_or_query_scenarios.ipynb +++ b/examples/create_or_query_scenarios.ipynb @@ -48,7 +48,7 @@ "scenarios = Scenarios.from_excel(\"example_input_excel.xlsx\")\n", "\n", "# Here we're also loading a scenario directly from the API and adding it to the scenarios loaded/created via the excel\n", - "scenario_a = Scenario.load(1357691)\n", + "scenario_a = Scenario.load(2690439)\n", "scenarios.add(scenario_a)" ] }, diff --git a/inputs/example_input_excel.xlsx b/inputs/example_input_excel.xlsx index 49b1a6cc8e7691241b6e95ccb949ade0a2d35be4..b952403730fee21b5f5039973c507ca949a1bbfd 100644 GIT binary patch delta 7762 zcmch6c{tSV+qao4Axq3y#+rRgwuEA`E9=St`Ih3JSHuod2vs5f~U9No}l`NG^RG5fhg zw@+F5=1P!|PImh;W=R1mFtH(=9}#&ilI-d9@uljgD_y58JI|QdUC63YlNZq@h45cW zDSsQ2A=~3{N}H59{1rcQzsJxl|@_NbbzYf`>jUVC`Cqxm{D|)hr5) z+dahKF9SEM7T8bv5#w?1iGIMQB%g0fKNq5|NcMtkh$vysfQ}rFvm-&OOcbN# z_X8K@4!apLaB?{0C64ge+F_mxA#W$);sx8M&O41={<%IKe^9N&VQgK83p_xqp*xrHoO47c_nGRa`CPiKs-)Jf!iM&UHS*XfRATWh^VzI?LhYU% z61*YE_KmM^e+H(tM+|G47#re7nRg? zLuO>^X0O(%?2x2Qn+hAJG7=bH=2eC+jb@^o^R+FiuX0DY0HtS^Ph^AeuqNwdB_b!n)-&2G5$$_JK)QOwR?9L5UW~3WtaY#Bk zIx2M^omKrN%Oxnwa%v~PCO;irNj(mtzz--ZhN685I4A755@#$?o`f`rl1|j$FA23* zazgJPI(M5}hxu{2B z_ws!FV$SEj45sdw$&lfS`xCzP3(A6>YC`Pk4r^Gm?#!p`O?C{3ugqC*uC2$i%O)1P zBlVCBi?1pcp4NThR(pE*E}LYu-K2LZ8e)FqTLwLlk#0$N95P7n8X(?mdvVqTz?LSy zc^4WJ3*u!MqrvPWSl?yg0AelcLbbNDJGo$JFv0lB!mvbNJFlMC95vJF9xM zds`V$RMH>@>z^!pHA4hZj_>0-_ZU@rEoWxE11s*c{>bjF&PF&h=3IgC4z+!2LL+Fu92ew&*gwmd458~wJoX*pnfCw`sY)&z5`L4 z3nLu8@vg1p@4d*@d4Rm6N8KLbI3^OcNp>Z+Qa3lKJKyiO0h_JKJ1dtdpElaa8`MdF zyuLjGB;@XN&&LyW$gQm%OIti`Q3JO++Y%|;ji0`K80rS7>+`cKma6%hL4MN9>xrL= zfSd*VpV+NP0N5EUS;tfKkw5kB1EfZ0*Y6AQ6_lmd{&B?1`Hz>qs}WHdGt}a(2U)3yka&CT(?5f`WChseDInfESl z6l(JLCmre(1By4oNZg~Ziz(Ly>d4KOqps9&jrZ&P5s%oE-$$sP>6n@8b5^9xgluwq zk8B~feUh0bblmVlQ9VtOT?!GJgku{7{_3L~Q%%i;Kj(tpm8eEl_a^rDok5P03_H>^ zosHL-fr#@hH(T=0Zkt_o*13W2{j#cw3_hal^o1$e$r;n~3P7xZ7{lITvk(L zvC{|s%B#^sxLY#`z?ZpKj88tB`PZ~|`6&s?-IJyQy5d>t%s;s(k6=Y6uDI^p!B zX&=`@3#;)^!TiWd-atyJ?(J4n>^PnI>EKpiMLh0v0C5&b816L2P% zvqx_F3t#Mwx^%2@s$%Wis+z|!L5{|fLrpWO@5m8x!chm@I`RW=b*A0wUGpNTJ)nH# zMLj|2^Id$A)cC5>N!FbzGVJFxkTE9$i2Mo!Z* zT`q9zgVjWQxLa(}viObU*3wvVC(y;t^Yz(f<@Y;CB-9eSvUTBBPEcE~=9wDddS&i#EVH8ThHt|0-|d1hIv~KY7D)Wr%!gfV;^Y zcnwh1n-`8W<28;&`F)>DrbM+|U66b09~8WTTv{QoOnF7T`*{XIk(p$eA$^~l&pp?) ze}``~aO%f%O5`MQj@XubHDBa)&QRo+Wc2!McQqE-Go2^-=OOba?G9o-i zR<6t~k^bbNJr4YSy_gg&hFVT@0bqAWjzk8e4W-ei{&kmQXzOH}%*KmqBw}b`0c)u$ zY+=lGlFI~ACdy{8fJK@u>@zHQFWy8cJ$wH?$AqTPDY{dl3`H?&oK;AQQWXa+tG+Go zLR<^w>9vtciqE=9`+72P!B-8{d zD+(`)z7XjsvIoP`fyiI^?{55uE~qTzgCW!{(86nfrSrH&Jp8Xbov30B$8=KZ(oeFO zF!+c%<_{b1NyBFND*M8|-@5RLG}x<*XXIzx8(wbV#jXE8M^5x@@!AYGnhX3!^EU;9 z9tv=;>hHz+TR~WH2jSepA!ONwrtAOvM>PL2&~O`}t`$9gR>b6&UQ;KI7a0Gg8`Iw~ zZ~g)O}|5AAd$>pC! z{y)0_{O^bOhY0l)QU(dFIMnsKS>I0`)aKf2V=%#v-;Te!7{`I&MSw%;|KS$ibyrdA zvLoL^eowTat%TiSh)d(=MU0V3DpwH0O#j{u{G;1}>h*G~!N)yP6e1A~OJx~6>9>*~ zoVYh-UvByR@!Ro0rwS{>^+|a5EyjNr3iziB00{1XcH=*L0r>A(WRdVV*`WDS+Y3<1!<1@W|ny)}uKW$BZ} zq=5OAeY_0C|KIuP$g#-X`<>r|%bL+=xMVSbr%_2@$lY~P63##xbi+V{Fa_@VFdNKc z!c*l$Sf|E48Ka_K>ux3{rhHz>Fj~{_jWQq*E9)2fU4+?XE97QXuRa?3vjm#B$GAyD zqDa{Gmzpm%z92^g^!ibj*Qlh^ygX*IEaOtC1$WWVDwIaUsbU$yi4%%3qmDdzrodF7 z?ezR?%p9Yk?gafHYWLsFs8m)8m>NsBI`)!eLw{VN%!Ql_aaOPg=C}`nT!5+EZOw`I zT}!UTCowS%%tfI0B&NOAT!n^lX4LC-+$Au)mL%-oy5|CYx`xrpfiVN>`QysxD4Pzn z(AMDNqTpqzEU?N20lxL#9Vlh*oXCmJ??N87T7N%+dm_ZW@5_)CjwlERdUYD)l4%m07Em)MfQjJo z(*#W+c>HViMmg+;tGpFsfsE0;A&^NAALf$anANf3A*c3Q5`CcWP?@4~&~92Xj3`*) zAgwH{W?-#<`VP%2&5R;q-E%CG6SHWT%rkDvU{Lcg1~kr7ieL@9)-eAgE5J7yq`749 zc^@09PkX|^EdeOt%d|iZs5|(!%NjoO&ar4@?j8o~8~oM0?>$Wf1t$zZ_gG-Ntc$u& zPNn9|+wigAJhYa%bU#5chlU!Fn%FCa#$AzS-L^=e#mkf?I2HzgXR5$61sc~H9^1v3 z8G!kadfJz{#XyEV$jl|fG6XOjun(hJBEz1K?$5ldAj20X%3_dM%4t^ss+XVwi#Lq- z>{xtwzJeu;ii)l~NJF@2uty+Itj#4@f4zALe`l5rES^~8|L_nutpW=up7lab8aMLR z8V`+TMvI5iKY)FvKk;79K#EqLAL(D{|3ud*#M)>9x)*XRTv@tA284H&)c;cI)QVNy;cT^6{ z`?`Z1sG3|kxau(jP=CHQ4rfdBz*gk91xwI#8g5aA`t?i|_)Gx+R!Y4>q0;`4HLOrn z4g|em_X~8*hrW5ozzaD}kQMvaDomV$s6a3Ahu*t3mg zQLj~~JP(4{k;+9YfO?@Zn@VH0zy4K+#cj_D`K$ymwBv2ExjC6}E^s)I$9}oybp1Y2gnQ`oQ^DVbCy>;*I?25sqmr~q; z0+d^=X!09tFFQ)(ZJ5W~!q{+Qe8!PRo}a_nNxh;=pr)1%69yl)Z%R$d1_aIp+iDPt zL_!`ZIJNXVM?Lc&beOGcn-8!Bb^5WLSB~X#PH;)zF7{*d@sWzX_E%I6c76%t*gif= z-5-;yNEl?+oA9V&Eg9wpo`d}`)|oZLd>LeVsmB1E0mDrSi&sG^9+=xV2VC6km`}SJ z1BHBd7yG;3_G;c;Ay0yj(AovzO3*X}ixqV52&uaRrOlUiJ#~zyveBKr)!SOl! zdo%+4IauZ06N0P2&`0BJv~)q(7{RE3tPzPV_cXeRz<#zu- zS~VObvNzyji#<)Uy}u;;buZQ(hf!rfe^;|vzcf3vn--{9UoW?b1Ao_S|DI;iK@}e0 zJa{&j75h$gw;|T~Eoiek7mD}=RJY!jq_7KAzrL-k#kVd2Ojr(VbzZjaAEeqLqgf?z z5p7t$I!YMy90H}++?6#1 z2Y0VJDA}GBAz2zA$jTa80dQD}AV9$DNRAV{kJg`43YE>f@f)TBPSd&{Mg*w@$9V|x z+Rl3S$bI5U+coO93GmC~e|_s$Y3pLyt^^~?n~NN1e#D`k`uOm(WJ!thNk6AA#rmlw zJ-mI3rESWI+3Sv*#Om9ri64Xs+z_{g=TUA^kIt87UnPNkoOZhQ{@I@o3O({u3Jnft zPww!cJW$k(PX2JPN#Pj zvM`WUcVejm>bEp7E)qA)PT^%^A9?|>Tn=#>;8r%(`|@r>~P_5P7#WYDK7V6jB}A~LmAzwD(E;;DzzwZZ2e3Qp_856?*InT~7yAl|>O!V@{_ z9??$@?>EP7*2=Z`4-{Le7)tCSO|b$&Axok zt;&vVoac`d#_4h2v<#15x`e5nIbM2)nV_!~SQy+{c^vq9xSF3>e|Y*7pUyOk0(YOv zdnh?vv_RE*72+TgJO-ifw$fu5M3_NifEJ!$Pe1nHmoFUP>$Xi6pC7q5Ot)w}!WQ!- znGeywdT?vz8~0AFV{3>VS+Ak#!}U6YfR{&=DuNqqt2pL&$V}DHU4O*rbqE zE8ns8=JOavHO1i5Q{%Wg;_wz_&ZeC zVS(Sj#n935f#0hC{&T`lQ(=bCms0o{Dh!@^0)7MvQP|tZfP1AQd;1sQ-sT7%34z1$ z>=5`72okRYfg3_aHTOQtrhQg}e+hw~gk<4ap>Qq82fPs!E-kQIZ}8jvt57<+gTLc~ YJ0v~<3fF;j;k%)5amLpa82H(L0kmI&NdN!< delta 7831 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 dict[str, WarningCollector]: """ Returns a dict mapping input keys to their WarningCollectors when errors were found. """ - warnings = {} + warnings: dict[str, WarningCollector] = {} - # Check each input that has an update - for input_obj in self.inputs: - if input_obj.key in key_vals: - input_warnings = input_obj.is_valid_update(key_vals[input_obj.key]) - if len(input_warnings) > 0: - warnings[input_obj.key] = input_warnings - - # Check for non-existent keys - non_existent_keys = set(key_vals.keys()) - set(self.keys()) - for key in non_existent_keys: - warnings[key] = WarningCollector.with_warning(key, "Key does not exist") + input_map = {inp.key: inp for inp in self.inputs} + + for key, value in key_vals.items(): + input_obj = input_map.get(key) + if input_obj is None: + warnings[key] = WarningCollector.with_warning(key, "Key does not exist") + continue + + input_warnings = input_obj.is_valid_update(value) + if len(input_warnings) > 0: + warnings[key] = input_warnings return warnings diff --git a/src/pyetm/models/output_curves.py b/src/pyetm/models/output_curves.py index dec1bc8..31b9bcb 100644 --- a/src/pyetm/models/output_curves.py +++ b/src/pyetm/models/output_curves.py @@ -3,6 +3,7 @@ import pandas as pd from pathlib import Path from typing import Optional +import os import yaml from pyetm.clients import BaseClient @@ -15,6 +16,18 @@ ) +# Small LRU cache for reading CSVs from disk. Uses mtime to invalidate when file changes. +def _read_csv_cached(path: Path) -> pd.DataFrame: + return _read_csv_cached_impl(str(path), os.path.getmtime(path)) + + +# TODO determine appropriate maxsize +@lru_cache(maxsize=64) +def _read_csv_cached_impl(path_str: str, mtime: float) -> pd.DataFrame: + df = pd.read_csv(path_str, index_col=0) + return df.dropna(how="all") + + class OutputCurveError(Exception): """Base carrier curve error""" @@ -34,18 +47,26 @@ class OutputCurve(Base): def available(self) -> bool: return bool(self.file_path) - def retrieve(self, client, scenario) -> Optional[pd.DataFrame]: + def retrieve( + self, client, scenario, force_refresh: bool = False + ) -> Optional[pd.DataFrame]: """Process curve from client, save to file, set file_path""" file_path = ( get_settings().path_to_tmp(str(scenario.id)) / f"{self.key.replace('/','-')}.csv" ) - # TODO: Examine the caching situation in the future if time permits: could be particularly - # relevant for bulk processing - # if file_path.is_file(): - # self.file_path = file_path - # return self.contents() + # Reuse a cached file if present unless explicitly refreshing. + if not force_refresh and file_path.is_file(): + self.file_path = file_path + try: + return _read_csv_cached(self.file_path) + except Exception as e: + # Fall through to re-download on cache read failure + self.add_warning( + "file_path", + f"Failed to read cached curve file for {self.key}: {e}; refetching", + ) try: result = DownloadOutputCurveRunner.run(client, scenario, self.key) if result.success: @@ -80,8 +101,7 @@ def contents(self) -> Optional[pd.DataFrame]: return None try: - df = pd.read_csv(self.file_path, index_col=0) - return df.dropna(how="all") + return _read_csv_cached(self.file_path) except Exception as e: self.add_warning( "file_path", f"Failed to read curve file for {self.key}: {e}" @@ -147,6 +167,17 @@ def get_contents(self, scenario, curve_name: str) -> Optional[pd.DataFrame]: return None if not curve.available(): + # Try to attach a cached file from disk first + expected_path = ( + get_settings().path_to_tmp(str(scenario.id)) + / f"{curve.key.replace('/', '-')}.csv" + ) + if expected_path.is_file(): + curve.file_path = expected_path + contents = curve.contents() + self._merge_submodel_warnings(curve, key_attr="key") + return contents + result = curve.retrieve(BaseClient(), scenario) self._merge_submodel_warnings(curve, key_attr="key") return result @@ -193,17 +224,7 @@ def get_curves_by_carrier_type( Returns: Dictionary mapping curve names to DataFrames """ - carrier_mapping = { - "electricity": ["merit_order", "electricity_price", "residual_load"], - "heat": [ - "heat_network", - "agriculture_heat", - "household_heat", - "buildings_heat", - ], - "hydrogen": ["hydrogen", "hydrogen_integral_cost"], - "methane": ["network_gas"], - } + carrier_mapping = self._load_carrier_mappings() if carrier_type not in carrier_mapping: valid_types = ", ".join(carrier_mapping.keys()) diff --git a/src/pyetm/models/scenario.py b/src/pyetm/models/scenario.py index a95b951..01a8302 100644 --- a/src/pyetm/models/scenario.py +++ b/src/pyetm/models/scenario.py @@ -288,12 +288,7 @@ def update_user_values(self, update_inputs: Dict[str, Any]) -> None: """ # Update them in the Inputs object, and check validation validity_errors = self.inputs.is_valid_update(update_inputs) - if validity_errors: - error_summary = [] - for key, warning_collector in validity_errors.items(): - warnings_list = [w.message for w in warning_collector] - error_summary.append(f"{key}: {warnings_list}") - raise ScenarioError(f"Could not update user values: {error_summary}") + self._handle_validity_errors(validity_errors, "user values") result = UpdateInputsRunner.run(BaseClient(), self, update_inputs) @@ -357,12 +352,7 @@ def update_sortables(self, update_sortables: Dict[str, List[Any]]) -> None: """ # Validate the updates first validity_errors = self.sortables.is_valid_update(update_sortables) - if validity_errors: - error_summary = [] - for key, warning_collector in validity_errors.items(): - warnings_list = [w.message for w in warning_collector] - error_summary.append(f"{key}: {warnings_list}") - raise ScenarioError(f"Could not update sortables: {error_summary}") + self._handle_validity_errors(validity_errors, "sortables") # Make individual API calls for each sortable as there is no bulk endpoint for name, order in update_sortables.items(): @@ -443,16 +433,9 @@ def update_custom_curves(self, custom_curves) -> None: Args: custom_curves: CustomCurves object containing curves to upload """ - # Validate curves before uploading validity_errors = custom_curves.validate_for_upload() - # TODO: Extract all these validity_errors thingys to a single util or something, lots of repetition at the moment - if validity_errors: - error_summary = [] - for key, warning_collector in validity_errors.items(): - warnings_list = [w.message for w in warning_collector] - error_summary.append(f"{key}: {warnings_list}") - raise ScenarioError(f"Could not update custom curves: {error_summary}") + self._handle_validity_errors(validity_errors, "custom curves") # Upload curves result = UpdateCustomCurvesRunner.run(BaseClient(), self, custom_curves) @@ -556,3 +539,19 @@ def show_all_warnings(self) -> None: if submodel is not None and len(submodel.warnings) > 0: print(f"\n{name} warnings:") submodel.show_warnings() + + def _handle_validity_errors( + self, validity_errors: Dict[str, Any], context: str + ) -> None: + """ + Helper method to format and raise ScenarioError for validity errors. + """ + if not validity_errors: + return + + error_summary = [] + for key, warning_collector in validity_errors.items(): + warnings_list = [w.message for w in warning_collector] + error_summary.append(f"{key}: {warnings_list}") + + raise ScenarioError(f"Could not update {context}: {error_summary}") diff --git a/src/pyetm/models/scenario_packer.py b/src/pyetm/models/scenario_packer.py index bdc136c..bc0bd9e 100644 --- a/src/pyetm/models/scenario_packer.py +++ b/src/pyetm/models/scenario_packer.py @@ -56,18 +56,41 @@ def extract_from_main_sheet( candidate_series = main_df.iloc[:, 0] return ExportConfigResolver._parse_config_from_series(candidate_series) - except Exception: + except Exception as e: + logger.exception("Error extracting from main sheet: %s", e) return None @staticmethod - def _parse_config_from_series(series: pd.Series) -> ExportConfig: + def _parse_config_from_series(series: pd.Series) -> "ExportConfig": """Parse ExportConfig from a pandas Series (column from main sheet).""" - index_map = {str(idx).strip().lower(): idx for idx in series.index} + + def _iter_rows(): + for label, value in zip(series.index, series.values): + yield str(label).strip().lower(), value + + def _value_after_output(name: str) -> Any: + target = name.strip().lower() + seen_output = False + chosen: Any = None + for lbl, val in _iter_rows(): + if lbl == "output": + seen_output = True + continue + if seen_output and lbl == target: + chosen = val + return chosen + + def _value_any(name: str) -> Any: + target = name.strip().lower() + chosen: Any = None + for lbl, val in _iter_rows(): + if lbl == target: + chosen = val + return chosen def get_cell_value(name: str) -> Any: - key = name.strip().lower() - original_key = index_map.get(key) - return series.get(original_key) if original_key is not None else None + val = _value_after_output(name) + return val if val is not None else _value_any(name) def parse_bool(value: Any) -> Optional[bool]: """Parse boolean from various formats.""" @@ -88,26 +111,47 @@ def parse_bool(value: Any) -> Optional[bool]: return False return None + def parse_bool_field(*names: str) -> Optional[bool]: + """Return the first non-None boolean parsed from the provided field names.""" + for n in names: + val = parse_bool(get_cell_value(n)) + if val is not None: + return val + return None + def parse_carriers(value: Any) -> Optional[List[str]]: """Parse comma-separated carrier list.""" if not isinstance(value, str) or not value.strip(): return None return [carrier.strip() for carrier in value.split(",") if carrier.strip()] - carriers_raw = get_cell_value("exports") or get_cell_value("output_carriers") + exports_val = get_cell_value("exports") + carriers_val = get_cell_value("output_carriers") - return ExportConfig( - include_inputs=parse_bool(get_cell_value("inputs")), - include_sortables=parse_bool(get_cell_value("sortables")), - include_custom_curves=parse_bool(get_cell_value("custom_curves")), + exports_bool = parse_bool(exports_val) + if exports_bool is True: + output_carriers = ["electricity", "hydrogen", "heat", "methane"] + elif exports_bool is False: + output_carriers = None + else: + output_carriers = parse_carriers(carriers_val) or parse_carriers( + exports_val + ) + + config = ExportConfig( + include_inputs=parse_bool_field("include_inputs", "inputs"), + include_sortables=parse_bool_field("include_sortables", "sortables"), + include_custom_curves=parse_bool_field( + "include_custom_curves", "custom_curves" + ), include_gqueries=( - parse_bool(get_cell_value("gquery_results")) - or parse_bool(get_cell_value("gqueries")) + parse_bool_field("include_gqueries", "gquery_results", "gqueries") ), inputs_defaults=parse_bool(get_cell_value("defaults")), inputs_min_max=parse_bool(get_cell_value("min_max")), - output_carriers=parse_carriers(carriers_raw), + output_carriers=output_carriers, ) + return config class ScenarioPacker(BaseModel): From 3a2c4e0d84074f6aceed029b3ac36a46cef32508 Mon Sep 17 00:00:00 2001 From: louispt1 Date: Mon, 18 Aug 2025 15:54:13 +0200 Subject: [PATCH 16/19] Add couplings and information workbook --- examples/create_or_query_scenarios.ipynb | 14 +++ examples/get_info.ipynb | 113 ++++++++++++++++++++ inputs/example_input_excel.xlsx | Bin 1377033 -> 1377090 bytes src/pyetm/clients/session.py | 4 + src/pyetm/models/inputs.py | 127 +++++++++++++++++++++-- src/pyetm/models/scenario.py | 11 +- src/pyetm/models/warnings.py | 1 - 7 files changed, 254 insertions(+), 16 deletions(-) create mode 100644 examples/get_info.ipynb diff --git a/examples/create_or_query_scenarios.ipynb b/examples/create_or_query_scenarios.ipynb index b956058..2b222e8 100644 --- a/examples/create_or_query_scenarios.ipynb +++ b/examples/create_or_query_scenarios.ipynb @@ -94,6 +94,20 @@ " print(\"\")" ] }, + { + "cell_type": "code", + "execution_count": null, + "id": "b493a801", + "metadata": {}, + "outputs": [], + "source": [ + "# The example includes a coupled input in the parameters for scen_b\n", + "for scenario in scenarios:\n", + " inputs = scenario.inputs\n", + " print(f\"Active Couplings for scenario {scenario.title}: {inputs.get_active_coupling_groups()}\")\n", + " print(\"\")" + ] + }, { "cell_type": "code", "execution_count": null, diff --git a/examples/get_info.ipynb b/examples/get_info.ipynb new file mode 100644 index 0000000..ea016f3 --- /dev/null +++ b/examples/get_info.ipynb @@ -0,0 +1,113 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "id": "e1993731", + "metadata": {}, + "source": [ + "# Fetch available info\n", + "\n", + "This workbook shows how to:\n", + "\n", + "- Fetch inputs\n", + "- Fetch couplings and coupling inputs\n", + "- Fetch sortables" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "38024f5a", + "metadata": {}, + "outputs": [], + "source": [ + "# Check the environment is properly configured.\n", + "from example_helpers import setup_notebook\n", + "setup_notebook()\n", + "from pyetm.models.scenario import Scenario\n", + "\n", + "scenario = Scenario.load(2690439)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "5aa1b657", + "metadata": {}, + "outputs": [], + "source": [ + "# Total available inputs, their min, max and default values\n", + "inputs = scenario.inputs\n", + "print(inputs.to_dataframe(columns=[\"key\", \"default\", \"min\", \"max\"]))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "17ed6ba8", + "metadata": {}, + "outputs": [], + "source": [ + "import pandas as pd\n", + "# Available, active and inactive coupling groups and all coupling inputs\n", + "print(f\"All couplings: {inputs.get_all_coupling_groups()}\")\n", + "print(f\"Active: {inputs.get_active_coupling_groups()}\")\n", + "print(f\"Inactive: {inputs.get_inactive_coupling_groups()}\")\n", + "print(f\"Coupling inputs:\")\n", + "print(pd.DataFrame([vars(obj) for obj in inputs.get_coupling_inputs()]))" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c2b47fc3", + "metadata": {}, + "outputs": [], + "source": [ + "# Available Sortables and their current order\n", + "sortables = scenario.sortables\n", + "print(\"Sortable groups:\", sortables.names())\n", + "\n", + "# Show sortables as dataframe if available\n", + "try:\n", + " df_sortables = sortables.to_dataframe()\n", + " display(df_sortables.head(10))\n", + "except Exception as e:\n", + " print(\"Failed to build sortables dataframe:\", e)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "id": "c553c572", + "metadata": {}, + "outputs": [], + "source": [ + "# Output curves: sample access by carrier type\n", + "from pyetm.models.scenario import OutputCurves\n", + "OutputCurves._load_carrier_mappings()" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "pyetm-Rh4Np-o3-py3.12", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.12.9" + } + }, + "nbformat": 4, + "nbformat_minor": 5 +} diff --git a/inputs/example_input_excel.xlsx b/inputs/example_input_excel.xlsx index b952403730fee21b5f5039973c507ca949a1bbfd..6e6973eb4e5a4bff7d34036920af885f5854a231 100644 GIT binary patch delta 6304 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 N7%{LOpXN2de*rA8{h$B< delta 6240 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 J5C2qN{|9y)rZ@lq diff --git a/src/pyetm/clients/session.py b/src/pyetm/clients/session.py index b57d726..c7a011f 100644 --- a/src/pyetm/clients/session.py +++ b/src/pyetm/clients/session.py @@ -25,6 +25,10 @@ def __init__(self, base_url: Optional[str] = None, token: Optional[str] = None): } ) + proxies = get_settings().proxy_servers + if proxies: + self.proxies.update(proxies) + def request(self, method: str, url: str, **kwargs) -> requests.Response: # Ensure we only pass a path to `url`; prefix with base_url full_url = ( diff --git a/src/pyetm/models/inputs.py b/src/pyetm/models/inputs.py index 883d9f0..76037e4 100644 --- a/src/pyetm/models/inputs.py +++ b/src/pyetm/models/inputs.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import Optional, Union -from pydantic import field_validator, model_validator +from typing import Optional, Union, Set +from pydantic import field_validator, model_validator, PrivateAttr import pandas as pd from pyetm.models.warnings import WarningCollector from pyetm.models.base import Base @@ -30,6 +30,18 @@ def is_valid_update(self, value) -> WarningCollector: warnings_obj = self.__class__(**new_obj_dict) return warnings_obj.warnings + def has_coupling_groups(self) -> bool: + """Check if this input has any coupling groups""" + return any( + isinstance(g, str) and g.startswith("external") + for g in (self.coupling_groups or []) + ) + + def get_coupling_groups(self) -> list[str]: + """Get the coupling groups for this input which must start with 'external'""" + groups = self.coupling_groups or [] + return [g for g in groups if isinstance(g, str) and g.startswith("external")] + @classmethod def from_json(cls, data: tuple[str, dict]) -> "Input": """ @@ -86,9 +98,6 @@ def is_bool_float(cls, value: Optional[float]) -> Optional[float]: f"{value} should be 1.0 or 0.0 representing True/False, or On/Off" ) - # NOTE: I need a lot of validation, and I need my own update method that - # will cast true/false into 1.0 and 0.0 - class EnumInput(Input): """Input representing an enumeration""" @@ -100,7 +109,6 @@ class EnumInput(Input): def _get_serializable_fields(self) -> list[str]: """Include permitted_values in serialization for EnumInput""" base_fields = super()._get_serializable_fields() - # Ensure permitted_values is included if "permitted_values" not in base_fields: base_fields.append("permitted_values") return base_fields @@ -138,7 +146,6 @@ def _get_serializable_fields(self) -> list[str]: @model_validator(mode="after") def check_min_max(self) -> FloatInput: if not isinstance(self.user, float): - # We let pydantic handle the field validation return self if self.user is None or (self.user <= self.max and self.user >= self.min): return self @@ -150,8 +157,38 @@ def check_min_max(self) -> FloatInput: ) +class CouplingState: + """Helper class to track coupling state""" + + def __init__(self): + self.active_groups: Set[str] = set() + self.inactive_groups: Set[str] = set() + + def activate_group(self, group: str): + """Activate a coupling group""" + self.active_groups.add(group) + self.inactive_groups.discard(group) + + def deactivate_group(self, group: str): + """Deactivate a coupling group""" + self.inactive_groups.add(group) + self.active_groups.discard(group) + + def is_active(self, group: str) -> bool: + """Check if a coupling group is active""" + return group in self.active_groups + + def is_inactive(self, group: str) -> bool: + """Check if a coupling group is inactive""" + return group in self.inactive_groups + + class Inputs(Base): inputs: list[Input] + _coupling_state: CouplingState = PrivateAttr(default_factory=CouplingState) + + def __init__(self, **data): + super().__init__(**data) def __len__(self): return len(self.inputs) @@ -162,12 +199,74 @@ def __iter__(self): def keys(self): return [input.key for input in self.inputs] + def get_all_coupling_groups(self) -> Set[str]: + """Get all possible coupling groups from all inputs""" + all_groups = set() + for input_obj in self.inputs: + all_groups.update(input_obj.get_coupling_groups()) + return all_groups + + def get_coupling_groups_for_input(self, key: str) -> list[str]: + """Get coupling groups for a specific input key""" + input_obj = self.get_input_by_key(key) + if input_obj: + return input_obj.get_coupling_groups() + return [] + + def get_input_by_key(self, key: str) -> Optional[Input]: + """Get input by its key""" + for input_obj in self.inputs: + if input_obj.key == key: + return input_obj + return None + + def get_coupling_inputs(self) -> list[Input]: + """List all coupling inputs whose keys start with 'external_coupling'""" + return [ + inp + for inp in self.inputs + if isinstance(inp.key, str) and inp.key.startswith("external_coupling") + ] + + def activate_coupling_group(self, group: str): + """Activate a coupling group""" + if self._coupling_state: + self._coupling_state.activate_group(group) + + def deactivate_coupling_group(self, group: str): + """Deactivate a coupling group""" + if self._coupling_state: + self._coupling_state.deactivate_group(group) + + def get_active_coupling_groups(self) -> Set[str]: + """Get all active coupling groups""" + return self._coupling_state.active_groups if self._coupling_state else set() + + def get_inactive_coupling_groups(self) -> Set[str]: + """Get all inactive coupling groups""" + return self._coupling_state.inactive_groups if self._coupling_state else set() + + def activate_coupling_groups_for_updates(self, key_vals: dict): + """ + Activate coupling groups based on input updates. + """ + if not self._coupling_state: + return + + for key, value in key_vals.items(): + if isinstance(value, str) and value == "reset": + continue + + groups = self.get_coupling_groups_for_input(key) + for group in groups: + if not self._coupling_state.is_inactive(group): + self.activate_coupling_group(group) + def is_valid_update(self, key_vals: dict) -> dict[str, WarningCollector]: """ Returns a dict mapping input keys to their WarningCollectors when errors were found. """ warnings: dict[str, WarningCollector] = {} - input_map = {inp.key: inp for inp in self.inputs} for key, value in key_vals.items(): @@ -184,13 +283,20 @@ def is_valid_update(self, key_vals: dict) -> dict[str, WarningCollector]: def update(self, key_vals: dict): """ - Update the values of certain inputs. + Update the values of certain inputs and activate coupling groups. """ + self.activate_coupling_groups_for_updates(key_vals) for input_obj in self.inputs: if input_obj.key in key_vals: - # Use assignment which goes through __setattr__ validation input_obj.user = key_vals[input_obj.key] + def force_uncouple_all(self): + """Force uncouple all coupling groups""" + if self._coupling_state: + all_groups = self.get_all_coupling_groups() + for group in all_groups: + self.deactivate_coupling_group(group) + def _to_dataframe(self, columns="user", **kwargs) -> pd.DataFrame: """ Serialize the Inputs collection to DataFrame. @@ -199,7 +305,6 @@ def _to_dataframe(self, columns="user", **kwargs) -> pd.DataFrame: columns = [columns] columns = ["unit"] + columns - # Create DataFrame from inputs df = pd.DataFrame.from_dict( { input.key: [getattr(input, key, None) for key in columns] diff --git a/src/pyetm/models/scenario.py b/src/pyetm/models/scenario.py index 01a8302..8294752 100644 --- a/src/pyetm/models/scenario.py +++ b/src/pyetm/models/scenario.py @@ -263,7 +263,8 @@ def inputs(self) -> Inputs: # merge runner warnings and any item‐level warnings for w in result.errors: self.add_warning("inputs", w) - self._merge_submodel_warnings(coll, key_attr="inputs") + # Merge submodel warnings with a simple, clean prefix + self._merge_submodel_warnings(coll) self._inputs = coll return coll @@ -325,7 +326,8 @@ def sortables(self) -> Sortables: coll = Sortables.from_json(result.data) for w in result.errors: self.add_warning("sortables", w) - self._merge_submodel_warnings(coll, key_attr="sortables") + # Merge submodel warnings with a simple, clean prefix + self._merge_submodel_warnings(coll) self._sortables = coll return coll @@ -413,7 +415,8 @@ def custom_curves(self) -> CustomCurves: pass for w in result.errors: self.add_warning("custom_curves", w) - self._merge_submodel_warnings(coll, key_attr="custom_curves") + # Merge submodel warnings with a simple, clean prefix + self._merge_submodel_warnings(coll) self._custom_curves = coll return coll @@ -491,7 +494,7 @@ def execute_queries(self): ready collecting all of them """ self._queries.execute(BaseClient(), self) - self._merge_submodel_warnings(self._queries, key_attr="queries") + self._merge_submodel_warnings(self._queries) def results(self, columns="future") -> pd.DataFrame: """ diff --git a/src/pyetm/models/warnings.py b/src/pyetm/models/warnings.py index 794c2f8..8c68774 100644 --- a/src/pyetm/models/warnings.py +++ b/src/pyetm/models/warnings.py @@ -41,7 +41,6 @@ def with_warning( ) -> "WarningCollector": """ Convenience method to create a WarningCollector with a single warning. - E.g: WarningCollector.with_warning("field", "message") """ collector = cls() collector.add(field, message, severity) From 7d03a634e01ca26823044fa17b10ada7c499584a Mon Sep 17 00:00:00 2001 From: louispt1 Date: Mon, 18 Aug 2025 19:55:09 +0200 Subject: [PATCH 17/19] Fix metadata issue on scenario create --- examples/create_or_query_scenarios.ipynb | 3 +- examples/example_helpers.py | 79 ++++++++++++++++-------- src/pyetm/models/scenario_packer.py | 10 +-- tests/models/test_scenario_packer.py | 13 +++- 4 files changed, 70 insertions(+), 35 deletions(-) diff --git a/examples/create_or_query_scenarios.ipynb b/examples/create_or_query_scenarios.ipynb index 2b222e8..4bd7e1f 100644 --- a/examples/create_or_query_scenarios.ipynb +++ b/examples/create_or_query_scenarios.ipynb @@ -19,7 +19,7 @@ "source": [ "# Check the environment is properly configured.\n", "from example_helpers import setup_notebook\n", - "setup_notebook()" + "setup_notebook(debug=True)" ] }, { @@ -72,6 +72,7 @@ "# Metadata\n", "for scenario in scenarios:\n", " print(f\"Title: {scenario.title}\")\n", + " print(f\"ID: {scenario.id}\")\n", " print(f\"Area: {scenario.area_code}\")\n", " print(f\"End year: {scenario.end_year}\")\n", " print(f\"Version: {scenario.version}\")\n", diff --git a/examples/example_helpers.py b/examples/example_helpers.py index edd84eb..21cfdfa 100644 --- a/examples/example_helpers.py +++ b/examples/example_helpers.py @@ -1,29 +1,42 @@ # Setting up everything for you! -def setup_notebook(): +def setup_notebook(debug=False): + """ + Set up the notebook environment for ETM API usage. + + Args: + debug (bool): If True, shows full tracebacks. If False, hides them for cleaner output. + """ import sys import builtins from pyetm.config.settings import get_settings from IPython import get_ipython from IPython.display import display, HTML - # Hide the traceback for a cleaner demo experience + # Handle traceback display based on debug mode ipython = get_ipython() - def hide_traceback( - exc_tuple=None, - filename=None, - tb_offset=None, - exception_only=False, - running_compiled_code=False, - ): - etype, value, tb = sys.exc_info() - return ipython._showtraceback( - etype, value, ipython.InteractiveTB.get_exception_only(etype, value) - ) - - ipython.showtraceback = hide_traceback + if not debug: + # Hide the traceback for a cleaner demo experience + def hide_traceback( + exc_tuple=None, + filename=None, + tb_offset=None, + exception_only=False, + running_compiled_code=False, + ): + etype, value, tb = sys.exc_info() + return ipython._showtraceback( + etype, value, ipython.InteractiveTB.get_exception_only(etype, value) + ) + + ipython.showtraceback = hide_traceback + else: + if hasattr(ipython, "_original_showtraceback"): + ipython.showtraceback = ipython._original_showtraceback + else: + ipython._original_showtraceback = ipython.showtraceback try: import pandas as pd @@ -95,19 +108,31 @@ def _smart_print(*args, **kwargs): builtins.print = _smart_print - except Exception: - pass + except Exception as e: + if debug: + print(f"Error setting up pandas features: {e}") + import traceback + + traceback.print_exc() print("Environment setup complete") # Check if our API is ready! - - print(" Using ETM API at ", get_settings().base_url) - print(" Token loaded? ", bool(get_settings().etm_api_token)) - - if not get_settings().etm_api_token: - print( - " Warning: No ETM_API_TOKEN found. Please set your token in the environment." - ) - else: - print("API connection ready") + try: + print(" Using ETM API at ", get_settings().base_url) + print(" Token loaded? ", bool(get_settings().etm_api_token)) + + if not get_settings().etm_api_token: + print( + " Warning: No ETM_API_TOKEN found. Please set your token in the environment." + ) + else: + print("API connection ready") + except Exception as e: + if debug: + print(f"Error checking API settings: {e}") + import traceback + + traceback.print_exc() + else: + print("Error checking API settings. Run with debug=True for details.") diff --git a/src/pyetm/models/scenario_packer.py b/src/pyetm/models/scenario_packer.py index bc0bd9e..2ba1e55 100644 --- a/src/pyetm/models/scenario_packer.py +++ b/src/pyetm/models/scenario_packer.py @@ -525,13 +525,14 @@ def _create_scenario_from_column( scenario_id = self._safe_get_int(column_data.get("scenario_id")) area_code = column_data.get("area_code") end_year = self._safe_get_int(column_data.get("end_year")) + metadata_updates = self._extract_metadata_updates(column_data) scenario = self._load_or_create_scenario( - scenario_id, area_code, end_year, column_name + scenario_id, area_code, end_year, column_name, **metadata_updates ) if scenario is None: return None - metadata_updates = self._extract_metadata_updates(column_data) + # Metadata already applied in creation, but if needed, can update again here self._apply_metadata_to_scenario(scenario, metadata_updates) return scenario @@ -570,8 +571,9 @@ def _load_or_create_scenario( area_code: Any, end_year: Optional[int], column_name: str, + **kwargs, ) -> Optional[Scenario]: - """Load existing scenario or create new one.""" + """Load existing scenario or create new one. Passes all available kwargs to Scenario.new for full metadata.""" if scenario_id is not None: try: return Scenario.load(scenario_id) @@ -585,7 +587,7 @@ def _load_or_create_scenario( if area_code and end_year is not None: try: - return Scenario.new(str(area_code), int(end_year)) + return Scenario.new(str(area_code), int(end_year), **kwargs) except Exception as e: logger.warning( "Failed to create scenario for column '%s' (area_code=%s, end_year=%s): %s", diff --git a/tests/models/test_scenario_packer.py b/tests/models/test_scenario_packer.py index b8577c9..23b3525 100644 --- a/tests/models/test_scenario_packer.py +++ b/tests/models/test_scenario_packer.py @@ -927,7 +927,10 @@ def test_create_scenario_from_column_creates(self, monkeypatch): packer = ScenarioPacker() scenario = Mock(spec=Scenario) scenario.identifier = Mock(return_value="NEW") - monkeypatch.setattr(Scenario, "new", staticmethod(lambda a, y: scenario)) + # Accept *args, **kwargs for compatibility with production code + monkeypatch.setattr( + Scenario, "new", staticmethod(lambda *args, **kwargs: scenario) + ) ser = pd.Series( { @@ -1014,8 +1017,12 @@ def test_from_excel_full_flow(self, tmp_path, monkeypatch): s_created.id = "created" s_created.identifier = Mock(return_value="created") - monkeypatch.setattr(Scenario, "load", staticmethod(lambda sid: s_loaded)) - monkeypatch.setattr(Scenario, "new", staticmethod(lambda a, y: s_created)) + monkeypatch.setattr( + Scenario, "load", staticmethod(lambda *args, **kwargs: s_loaded) + ) + monkeypatch.setattr( + Scenario, "new", staticmethod(lambda *args, **kwargs: s_created) + ) # Spy on inputs and queries imports with ( From d6f4887989a5a89b4064932497756c51922738da Mon Sep 17 00:00:00 2001 From: louispt1 Date: Thu, 21 Aug 2025 15:23:50 +0200 Subject: [PATCH 18/19] Simplify couplings --- examples/create_or_query_scenarios.ipynb | 4 +- examples/get_info.ipynb | 8 +- src/pyetm/models/couplings.py | 42 +++++++ src/pyetm/models/inputs.py | 111 +----------------- src/pyetm/models/scenario.py | 43 ++++++- .../scenario_runners/fetch_couplings.py | 45 +++++++ .../scenario_runners/update_couplings.py | 73 ++++++++++++ tests/models/test_inputs.py | 2 - 8 files changed, 208 insertions(+), 120 deletions(-) create mode 100644 src/pyetm/models/couplings.py create mode 100644 src/pyetm/services/scenario_runners/fetch_couplings.py create mode 100644 src/pyetm/services/scenario_runners/update_couplings.py diff --git a/examples/create_or_query_scenarios.ipynb b/examples/create_or_query_scenarios.ipynb index 4bd7e1f..dfaaa58 100644 --- a/examples/create_or_query_scenarios.ipynb +++ b/examples/create_or_query_scenarios.ipynb @@ -104,8 +104,8 @@ "source": [ "# The example includes a coupled input in the parameters for scen_b\n", "for scenario in scenarios:\n", - " inputs = scenario.inputs\n", - " print(f\"Active Couplings for scenario {scenario.title}: {inputs.get_active_coupling_groups()}\")\n", + " couplings = scenario.couplings\n", + " print(couplings)\n", " print(\"\")" ] }, diff --git a/examples/get_info.ipynb b/examples/get_info.ipynb index ea016f3..05ad606 100644 --- a/examples/get_info.ipynb +++ b/examples/get_info.ipynb @@ -48,13 +48,7 @@ "metadata": {}, "outputs": [], "source": [ - "import pandas as pd\n", - "# Available, active and inactive coupling groups and all coupling inputs\n", - "print(f\"All couplings: {inputs.get_all_coupling_groups()}\")\n", - "print(f\"Active: {inputs.get_active_coupling_groups()}\")\n", - "print(f\"Inactive: {inputs.get_inactive_coupling_groups()}\")\n", - "print(f\"Coupling inputs:\")\n", - "print(pd.DataFrame([vars(obj) for obj in inputs.get_coupling_inputs()]))" + "# What are the available couplings? curves?" ] }, { diff --git a/src/pyetm/models/couplings.py b/src/pyetm/models/couplings.py new file mode 100644 index 0000000..5879a82 --- /dev/null +++ b/src/pyetm/models/couplings.py @@ -0,0 +1,42 @@ +from __future__ import annotations +from typing import List, Set +from pyetm.models.base import Base + + +class Couplings(Base): + + active_couplings: List[str] = [] + inactive_couplings: List[str] = [] + + def __init__(self, **data): + super().__init__(**data) + + def active_groups(self) -> List[str]: + """Get active coupling groups""" + return self.active_couplings + + def inactive_groups(self) -> List[str]: + """Get inactive coupling groups""" + return self.inactive_couplings + + def all_groups(self) -> Set[str]: + """Get all coupling groups (active and inactive)""" + return set(self.active_couplings + self.inactive_couplings) + + @classmethod + def from_json(cls, data: dict) -> Couplings: + """ + Create Couplings from JSON data. + + Expected format: + { + "active_couplings": ["external_group1"], + "inactive_couplings": ["external_group2"] + } + """ + return cls.model_validate( + { + "active_couplings": data.get("active_couplings", []), + "inactive_couplings": data.get("inactive_couplings", []), + } + ) diff --git a/src/pyetm/models/inputs.py b/src/pyetm/models/inputs.py index 76037e4..c800403 100644 --- a/src/pyetm/models/inputs.py +++ b/src/pyetm/models/inputs.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import Optional, Union, Set -from pydantic import field_validator, model_validator, PrivateAttr +from typing import Optional, Union +from pydantic import field_validator, model_validator import pandas as pd from pyetm.models.warnings import WarningCollector from pyetm.models.base import Base @@ -16,8 +16,6 @@ class Input(Base): default: Optional[Union[float, str]] = None user: Optional[Union[float, str]] = None disabled: Optional[bool] = False - coupling_disabled: Optional[bool] = False - coupling_groups: Optional[list[str]] = [] disabled_by: Optional[str] = None def is_valid_update(self, value) -> WarningCollector: @@ -30,18 +28,6 @@ def is_valid_update(self, value) -> WarningCollector: warnings_obj = self.__class__(**new_obj_dict) return warnings_obj.warnings - def has_coupling_groups(self) -> bool: - """Check if this input has any coupling groups""" - return any( - isinstance(g, str) and g.startswith("external") - for g in (self.coupling_groups or []) - ) - - def get_coupling_groups(self) -> list[str]: - """Get the coupling groups for this input which must start with 'external'""" - groups = self.coupling_groups or [] - return [g for g in groups if isinstance(g, str) and g.startswith("external")] - @classmethod def from_json(cls, data: tuple[str, dict]) -> "Input": """ @@ -157,35 +143,8 @@ def check_min_max(self) -> FloatInput: ) -class CouplingState: - """Helper class to track coupling state""" - - def __init__(self): - self.active_groups: Set[str] = set() - self.inactive_groups: Set[str] = set() - - def activate_group(self, group: str): - """Activate a coupling group""" - self.active_groups.add(group) - self.inactive_groups.discard(group) - - def deactivate_group(self, group: str): - """Deactivate a coupling group""" - self.inactive_groups.add(group) - self.active_groups.discard(group) - - def is_active(self, group: str) -> bool: - """Check if a coupling group is active""" - return group in self.active_groups - - def is_inactive(self, group: str) -> bool: - """Check if a coupling group is inactive""" - return group in self.inactive_groups - - class Inputs(Base): inputs: list[Input] - _coupling_state: CouplingState = PrivateAttr(default_factory=CouplingState) def __init__(self, **data): super().__init__(**data) @@ -199,20 +158,6 @@ def __iter__(self): def keys(self): return [input.key for input in self.inputs] - def get_all_coupling_groups(self) -> Set[str]: - """Get all possible coupling groups from all inputs""" - all_groups = set() - for input_obj in self.inputs: - all_groups.update(input_obj.get_coupling_groups()) - return all_groups - - def get_coupling_groups_for_input(self, key: str) -> list[str]: - """Get coupling groups for a specific input key""" - input_obj = self.get_input_by_key(key) - if input_obj: - return input_obj.get_coupling_groups() - return [] - def get_input_by_key(self, key: str) -> Optional[Input]: """Get input by its key""" for input_obj in self.inputs: @@ -220,48 +165,6 @@ def get_input_by_key(self, key: str) -> Optional[Input]: return input_obj return None - def get_coupling_inputs(self) -> list[Input]: - """List all coupling inputs whose keys start with 'external_coupling'""" - return [ - inp - for inp in self.inputs - if isinstance(inp.key, str) and inp.key.startswith("external_coupling") - ] - - def activate_coupling_group(self, group: str): - """Activate a coupling group""" - if self._coupling_state: - self._coupling_state.activate_group(group) - - def deactivate_coupling_group(self, group: str): - """Deactivate a coupling group""" - if self._coupling_state: - self._coupling_state.deactivate_group(group) - - def get_active_coupling_groups(self) -> Set[str]: - """Get all active coupling groups""" - return self._coupling_state.active_groups if self._coupling_state else set() - - def get_inactive_coupling_groups(self) -> Set[str]: - """Get all inactive coupling groups""" - return self._coupling_state.inactive_groups if self._coupling_state else set() - - def activate_coupling_groups_for_updates(self, key_vals: dict): - """ - Activate coupling groups based on input updates. - """ - if not self._coupling_state: - return - - for key, value in key_vals.items(): - if isinstance(value, str) and value == "reset": - continue - - groups = self.get_coupling_groups_for_input(key) - for group in groups: - if not self._coupling_state.is_inactive(group): - self.activate_coupling_group(group) - def is_valid_update(self, key_vals: dict) -> dict[str, WarningCollector]: """ Returns a dict mapping input keys to their WarningCollectors when errors were found. @@ -283,20 +186,12 @@ def is_valid_update(self, key_vals: dict) -> dict[str, WarningCollector]: def update(self, key_vals: dict): """ - Update the values of certain inputs and activate coupling groups. + Update the values of certain inputs. """ - self.activate_coupling_groups_for_updates(key_vals) for input_obj in self.inputs: if input_obj.key in key_vals: input_obj.user = key_vals[input_obj.key] - def force_uncouple_all(self): - """Force uncouple all coupling groups""" - if self._coupling_state: - all_groups = self.get_all_coupling_groups() - for group in all_groups: - self.deactivate_coupling_group(group) - def _to_dataframe(self, columns="user", **kwargs) -> pd.DataFrame: """ Serialize the Inputs collection to DataFrame. diff --git a/src/pyetm/models/scenario.py b/src/pyetm/models/scenario.py index 8294752..e25c53e 100644 --- a/src/pyetm/models/scenario.py +++ b/src/pyetm/models/scenario.py @@ -1,11 +1,11 @@ from __future__ import annotations import pandas as pd from datetime import datetime -from pathlib import Path from typing import Any, Dict, List, Optional, Set, Union from urllib.parse import urlparse from pydantic import Field, PrivateAttr from os import PathLike +from pyetm.models.couplings import Couplings from pyetm.models.inputs import Inputs from pyetm.models.output_curves import OutputCurves from pyetm.clients import BaseClient @@ -27,6 +27,8 @@ from pyetm.services.scenario_runners.update_custom_curves import ( UpdateCustomCurvesRunner, ) +from pyetm.services.scenario_runners.fetch_couplings import FetchCouplingsRunner +from pyetm.services.scenario_runners.update_couplings import UpdateCouplingsRunner class ScenarioError(Exception): @@ -62,6 +64,7 @@ class Scenario(Base): _output_curves: Optional[OutputCurves] = PrivateAttr(default=None) _queries: Optional[Gqueries] = PrivateAttr(None) _export_config: Optional[ExportConfig] = PrivateAttr(default=None) + _couplings: Optional[Couplings] = PrivateAttr(default=None) @classmethod def new(cls, area_code: str, end_year: int, **kwargs) -> "Scenario": @@ -536,6 +539,7 @@ def show_all_warnings(self) -> None: ("Custom Curves", self._custom_curves), ("Output Curves", self._output_curves), ("Queries", self._queries), + ("Couplings", self._couplings), ] for name, submodel in submodels: @@ -558,3 +562,40 @@ def _handle_validity_errors( error_summary.append(f"{key}: {warnings_list}") raise ScenarioError(f"Could not update {context}: {error_summary}") + + @property + def couplings(self) -> Couplings: + """Get coupling groups for this scenario""" + if self._couplings is not None: + return self._couplings + + result = FetchCouplingsRunner.run(BaseClient(), self) + if not result.success: + raise ScenarioError(f"Could not retrieve couplings: {result.errors}") + + coll = Couplings.from_json(result.data) + for w in result.errors: + self.add_warning("couplings", w) + self._merge_submodel_warnings(coll) + + self._couplings = coll + return coll + + def update_couplings( + self, coupling_groups: List[str], action: str = "couple", force: bool = False + ) -> None: + + result = UpdateCouplingsRunner.run( + BaseClient(), self, coupling_groups, action, force + ) + + if not result.success: + raise ScenarioError(f"Could not update couplings: {result.errors}") + + # Update the cached couplings with the response data + if self._couplings is not None: + updated_couplings = Couplings.from_json(result.data) + self._couplings = updated_couplings + + for w in result.errors: + self.add_warning("couplings", w) diff --git a/src/pyetm/services/scenario_runners/fetch_couplings.py b/src/pyetm/services/scenario_runners/fetch_couplings.py new file mode 100644 index 0000000..1e100a2 --- /dev/null +++ b/src/pyetm/services/scenario_runners/fetch_couplings.py @@ -0,0 +1,45 @@ +from typing import Any, Dict + +from pyetm.services.scenario_runners.base_runner import BaseRunner +from ..service_result import ServiceResult +from pyetm.clients.base_client import BaseClient + + +class FetchCouplingsRunner(BaseRunner[Dict[str, Any]]): + """ + Runner for reading the coupling information of a scenario. + + GET /api/v3/scenarios/{scenario_id} + """ + + COUPLING_KEYS = [ + "active_couplings", + "inactive_couplings", + ] + + @staticmethod + def run( + client: BaseClient, + scenario: Any, + ) -> ServiceResult[Dict[str, Any]]: + result = FetchCouplingsRunner._make_request( + client=client, method="get", path=f"/scenarios/{scenario.id}" + ) + + if not result.success: + return result + + # Extract coupling-related data from response + body = result.data + coupling_data: Dict[str, Any] = {} + warnings: list[str] = [] + + for key in FetchCouplingsRunner.COUPLING_KEYS: + if key in body: + coupling_data[key] = body[key] + else: + # non-breaking: warning for missing coupling data + coupling_data[key] = None + warnings.append(f"Missing coupling field in response: {key!r}") + + return ServiceResult.ok(data=coupling_data, errors=warnings) diff --git a/src/pyetm/services/scenario_runners/update_couplings.py b/src/pyetm/services/scenario_runners/update_couplings.py new file mode 100644 index 0000000..4143129 --- /dev/null +++ b/src/pyetm/services/scenario_runners/update_couplings.py @@ -0,0 +1,73 @@ +from typing import Any, Dict, List, Union + +from pyetm.services.scenario_runners.base_runner import BaseRunner +from ..service_result import ServiceResult +from pyetm.clients.base_client import BaseClient + + +class UpdateCouplingsRunner(BaseRunner[Dict[str, Any]]): + """ + Runner for updating coupling groups in a scenario. + + POST /api/v3/scenarios/{scenario_id}/couple + POST /api/v3/scenarios/{scenario_id}/uncouple + """ + + @staticmethod + def run( + client: BaseClient, + scenario: Any, + coupling_groups: List[str], + action: str = "couple", + force: bool = False, + ) -> ServiceResult[Dict[str, Any]]: + """ + Update coupling groups for a scenario. + + Args: + client: The API client + scenario: The scenario object with an id attribute + coupling_groups: List of coupling group names to couple/uncouple + action: Either "couple" or "uncouple" + force: If True and action is "uncouple", force uncouple all groups + """ + if action not in ["couple", "uncouple"]: + return ServiceResult.error( + errors=[f"Invalid action: {action}. Must be 'couple' or 'uncouple'"] + ) + + # Prepare request data + data: Dict[str, Union[List[str], bool]] = {"groups": coupling_groups} + + if action == "uncouple" and force: + data["force"] = True + + result = UpdateCouplingsRunner._make_request( + client=client, + method="post", + path=f"/scenarios/{scenario.id}/{action}", + json=data, + ) + + if not result.success: + return result + + # The response should be the updated scenario data + body = result.data + coupling_data: Dict[str, Any] = {} + warnings: list[str] = [] + + # Extract relevant coupling information from the response + coupling_keys = [ + "active_couplings", + "inactive_couplings", + ] + + for key in coupling_keys: + if key in body: + coupling_data[key] = body[key] + else: + coupling_data[key] = None + warnings.append(f"Missing coupling field in response: {key!r}") + + return ServiceResult.ok(data=coupling_data, errors=warnings) diff --git a/tests/models/test_inputs.py b/tests/models/test_inputs.py index 2883e92..cae762c 100644 --- a/tests/models/test_inputs.py +++ b/tests/models/test_inputs.py @@ -320,8 +320,6 @@ def test_input_serializable_fields(): "default", "user", "disabled", - "coupling_disabled", - "coupling_groups", "disabled_by", ] for field in expected_base: From ddd4de1f47b81bff2fac0d78cc9d2244ac0ca673 Mon Sep 17 00:00:00 2001 From: louispt1 Date: Fri, 22 Aug 2025 10:30:10 +0200 Subject: [PATCH 19/19] Fixing gqueries to have the unit --- src/pyetm/models/gqueries.py | 18 ++++++++++++++++-- src/pyetm/models/scenario.py | 6 ++++-- 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/src/pyetm/models/gqueries.py b/src/pyetm/models/gqueries.py index 948dce6..3a3e7bc 100644 --- a/src/pyetm/models/gqueries.py +++ b/src/pyetm/models/gqueries.py @@ -54,9 +54,23 @@ def to_dataframe(self, columns="future"): if not self.is_ready(): return pd.DataFrame() - df = pd.DataFrame.from_dict(self.query_dict).reindex(["unit"] + [columns]).T + if isinstance(columns, str): + columns = [columns] + columns = ["unit"] + columns + + normalized = {} + for k, v in self.query_dict.items(): + if isinstance(v, dict): + normalized[k] = {col: v.get(col) for col in columns} + else: + normalized[k] = {"unit": None} + for col in columns: + if col != "unit": + normalized[k][col] = v + + df = pd.DataFrame.from_dict(normalized, orient="index") df.index.name = "gquery" - return df.set_index("unit", append=True) + return df def _to_dataframe(self, **kwargs) -> pd.DataFrame: """ diff --git a/src/pyetm/models/scenario.py b/src/pyetm/models/scenario.py index e25c53e..9c84c91 100644 --- a/src/pyetm/models/scenario.py +++ b/src/pyetm/models/scenario.py @@ -499,12 +499,14 @@ def execute_queries(self): self._queries.execute(BaseClient(), self) self._merge_submodel_warnings(self._queries) - def results(self, columns="future") -> pd.DataFrame: + def results(self, columns=None) -> pd.DataFrame: """ Returns the results of the requested queries in a dataframe """ + if columns is None: + columns = ["unit", "future"] + if not self.queries_requested(): - # TODO: Return something nicer, or more useful. return pd.DataFrame() if not self._queries.is_ready():