Skip to content

Commit 7e30183

Browse files
committed
Merge remote-tracking branch 'origin/develop' into feature/option-appraisal-costincome
2 parents dd9c738 + a99b10b commit 7e30183

3 files changed

Lines changed: 98 additions & 26 deletions

File tree

climada/entity/measures/measure_config.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -382,9 +382,10 @@ class CostIncomeConfig(ModifierConfig):
382382
income_yearly_growth_rate : float, optional
383383
Annual growth rate applied to periodic income. Default is ``0.0``.
384384
freq : str, optional
385-
Pandas period alias defining the period length (e.g. ``"Y"`` for
386-
yearly, ``"M"`` for monthly). Default is ``"Y"``.
385+
Pandas period alias defining the periodicity of the costs and incomes
386+
(e.g. ``"Y"`` for yearly, ``"M"`` for monthly). Default is ``"Y"``.
387387
See [pandas documentation](https://pandas.pydata.org/pandas-docs/stable/user_guide/timeseries.html#period-aliases).
388+
Note that growth rates remain yearly, independently from the freq.
388389
custom_cash_flows : list of dict, optional
389390
Explicit cash flow schedule as a list of records with at minimum
390391
a ``"date"`` key (ISO 8601 string) and a value key. If provided,

doc/getting-started/install.rst

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,54 @@ These instructions will install the most recent stable version of CLIMADA withou
139139
140140
mamba install -n climada_env -c conda-forge climada-petals
141141
142+
.. attention::
143+
144+
On Windows, installing ``climada-petals`` with Conda/Mamba may be prohibited as it takes forever to resolve the dependency tree.
145+
In these cases, `Pixi`_ is often the only reliable fallback (s.b.).
146+
147+
.. _install-pixi:
148+
149+
-------------------
150+
Simple Instructions with Pixi (Alternative)
151+
-------------------
152+
153+
As an alternative to mamba `Pixi`_ can be used to install climada from conda-forge.
154+
Pixi is a modern package manager, based on Conda, that offers much faster dependency resolution.
155+
156+
#. Open the command line and create a new folder for your Pixi project:
157+
158+
.. code-block:: shell
159+
160+
pixi init climada_pixi
161+
162+
.. _install-simple:
163+
164+
#. Add CLIMADA from ``conda-forge``:
165+
166+
.. code-block:: shell
167+
168+
pixi add --manifest-path climada_pixi/pixi.toml climada
169+
170+
#. Verify that everything is installed correctly by executing a single test:
171+
172+
.. code-block:: shell
173+
174+
# the pixi way to activate an environment
175+
pixi shell --manifest-path climada_pixi/pixi.toml
176+
# execute the test
177+
python -m unittest climada.engine.test.test_impact
178+
# the pixi way to deactivate an environment
179+
exit
180+
181+
Executing CLIMADA for the first time in a pixi environment will take quite some time because it will generate
182+
a directory tree in your home/user directory. If this test passes, great! You are good to go.
183+
184+
#. *Optional:* Install CLIMADA Petals into the same Pixi environment:
185+
186+
.. code-block:: shell
187+
188+
pixi add --manifest-path climada_pixi/pixi.toml climada-petals
189+
142190
.. _install-advanced:
143191

144192
---------------------------------------------
@@ -710,6 +758,9 @@ Terminal, Command Line
710758
`Mamba`_
711759
The faster reimplementation of the ``conda`` package manager.
712760

761+
`Pixi`_
762+
The much faster modern package manager based on ``conda``.
763+
713764
Environment (Programming)
714765
A setup where only a specific set of modules and programs can interact.
715766
This is especially useful if you want to install programs with mutually incompatible requirements.
@@ -737,4 +788,5 @@ IDE
737788
.. _Conda: https://docs.conda.io/en/latest/
738789
.. _Mamba: https://mamba.readthedocs.io/en/latest/installation/mamba-installation.html
739790
.. _Miniforge: https://github.com/conda-forge/miniforge
791+
.. _Pixi: https://pixi.sh/
740792
.. _CLIMADA Petals: https://climada-petals.readthedocs.io/en/latest/

doc/user-guide/climada_measure_config.ipynb

Lines changed: 43 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121
"\n",
2222
"The caveat of defining measure effects as python functions is that it cannot be serialized (written to a file), and also makes reading from a file a challenge.\n",
2323
"\n",
24-
"In order to retain close that gap, the `measure` module now ships `MeasureConfig` objects, which handle the reading, writing and \"declarative\" defining of `Measure` objects.\n",
24+
"In order to close that gap, the `measure` module now ships `MeasureConfig` objects which can be read from and written to files, and which enable \"declarative\" defining of `Measure` objects.\n",
25+
"As such `MeasureConfig` objects re-implement and improve the workflow from the old `Measure` objects and handle the translation to the new `Measure` objects:\n",
2526
"\n",
2627
"`Measure` objects can be instantiated from `MeasureConfig` objects using `Measure.from_config(<MeasureConfig object>)`.\n",
2728
"\n",
@@ -30,7 +31,7 @@
3031
"| `Measure` | `MeasureConfig` |\n",
3132
"|-----------|--------------------|\n",
3233
"| Is used for the actual computation | Is transformed into a `Measure` for actual computation |\n",
33-
"| Uses python function to define what change to apply to the `Exposures`, `ImpactFuncSet`, `Hazard` objects | Define the changes (functions) to apply via the former way (scaling/shifting effect, alternate file loading, etc.) |\n",
34+
"| Uses python functions to define what change to apply to the `Exposures`, `ImpactFuncSet`, `Hazard` objects | Defines the changes to apply using the (former) declarative way (scaling/shifting effect, alternate file loading, etc.) |\n",
3435
"| Accepts any possible effect as long as it can be defined as a python function | Is restricted to a set of defined effects |\n",
3536
"| Cannot be written to a file (unless it was created by a `MeasureConfig`) | Can easily be read from/written to a file (`.xlsx` or `.yaml`) |"
3637
]
@@ -50,7 +51,7 @@
5051
"- `ExposuresModifierConfig`: Modifies exposure data (e.g., reassigning IDs or zeroing regions).\n",
5152
"- `CostIncomeConfig`: Handles the financial aspects, including initial costs and recurring income.\n",
5253
"\n",
53-
"Note that everything can be defined and accessed directly from the `MeasureConfig` container, the underlying ones are there to keep things organized.\n",
54+
"Note that all effects of a `MeasureConfig` can be directly defined from the `MeasureConfig` container (with `from_dict()`, the underlying ones are there to keep things organized.\n",
5455
"\n",
5556
"In the following we present each of these subclasses and the possibilities they offer."
5657
]
@@ -81,14 +82,14 @@
8182
"| **Hazard** | `haz_int_mult` | `float` | Multiplier for hazard intensity (default: 1.0). |\n",
8283
"| | `haz_int_add` | `float` | Additive offset for hazard intensity (default: 0.0). |\n",
8384
"| | `new_hazard_path` | | Path to an HDF5 file to replace the current hazard. |\n",
84-
"| | `impact_rp_cutoff` | `float` | Return period (years) threshold; events below this are ignored. |\n",
85+
"| | `impact_rp_cutoff` | `float` | Return period (years) threshold; events with impacts below this threshold are ignored. |\n",
8586
"| **Impact Function**| `impf_ids` | `list` | Specific impact function IDs to modify (None = all). |\n",
8687
"| | `impf_mdd_mult` / `_add` | `float` | Scale or shift the Mean Damage Degree curve. |\n",
8788
"| | `impf_paa_mult` / `_add` | `float` | Scale or shift the Percentage of Assets Affected curve. |\n",
8889
"| | `impf_int_mult` / `_add` | `float` | Scale or shift the intensity axis of the function. |\n",
8990
"| | `new_impfset_path` | | Path to an Excel file to replace the impact function set. |\n",
9091
"| **Exposures** | `reassign_impf_id` | `dict` | Mapping `{haz_type: {old_id: new_id}}` for reclassification. |\n",
91-
"| | `set_to_zero` | `list` | List of Region IDs where exposure value is set to 0. |\n",
92+
"| | `set_to_zero` | `list` | List of exposures IDs where exposure value is set to 0. |\n",
9293
"| | `new_exposures_path` | | Path to an HDF5 file to replace the current exposures. |\n",
9394
"| **Cost & Income** | `init_cost` | `float` | One-time investment cost (absolute value). |\n",
9495
"| | `periodic_cost` | `float` | Recurring maintenance/operational costs. |\n",
@@ -154,6 +155,18 @@
154155
"print(meas_config)"
155156
]
156157
},
158+
{
159+
"cell_type": "markdown",
160+
"id": "37a913e2-6517-45ee-b011-58de8d740d77",
161+
"metadata": {},
162+
"source": [
163+
"```{note}\n",
164+
"The string representation of a `MeasureConfig` object filters out the default values to avoid clutter.\n",
165+
"\n",
166+
"You can see all fields using `MeasureConfig.to_dict(omit_default=False)`\n",
167+
"```"
168+
]
169+
},
157170
{
158171
"cell_type": "markdown",
159172
"id": "ac98393f-575f-4580-ac4a-dae578638916",
@@ -163,7 +176,7 @@
163176
"\n",
164177
"The `ImpfsetModifierConfig` is used to define how an adaptation measure changes the vulnerability (refer to the [impact functions tutorial](impact-functions-tutorial)).\n",
165178
"\n",
166-
"When \"translated\" to a `Measure` object the `ImpfsetModifierConfig` populates the `impfset_change` attribute with a function that takes an `ImpactFuncSet` and returns a modified one, according to the specifications.\n",
179+
"When \"translated\" to a `Measure` object, the `ImpfsetModifierConfig` populates the `impfset_change` attribute with a function that takes an `ImpactFuncSet` and returns a modified one, according to the specifications.\n",
167180
"\n",
168181
"```{note}\n",
169182
"Modifications are always applied to a specific hazard type (`haz_type` parameter).\n",
@@ -218,12 +231,12 @@
218231
"\n",
219232
"# 1. Scaling existing Impact Functions\n",
220233
"# Let's say we want to simulate a 20% reduction in MDD\n",
221-
"# and a slight shift in the intensity threshold for Hazard 'TC'.\n",
234+
"# and a horziontal translation of the impact function for Hazard 'TC'.\n",
222235
"impf_mod_scaling = ImpfsetModifierConfig(\n",
223236
" haz_type=\"TC\",\n",
224237
" impf_ids=[1, 2], # Apply only to specific function IDs\n",
225238
" impf_mdd_mult=0.8, # Reduce Mean Damage Degree by 20%\n",
226-
" impf_int_add=5.0, # Shift intensity axis by 5 units (e.g., higher resistance)\n",
239+
" impf_int_add=5.0, # Shift intensity array by 5 units, i.e. move impact function by 5 units to the right (e.g., higher resistance)\n",
227240
")\n",
228241
"\n",
229242
"print(\"--- Scaling Config ---\")\n",
@@ -248,7 +261,7 @@
248261
"\n",
249262
"The `HazardModifierConfig` is used to define how an adaptation measure changes the hazard (refer to the [hazard tutorial](hazard-tutorial)).\n",
250263
"\n",
251-
"When \"translated\" to a `Measure` object the `HazardModifierConfig` populates the `hazard_change` attribute with a function that takes a `Hazard` (possibly additional arguments, see below) and returns a modified one, according to the specifications.\n",
264+
"When \"translated\" to a `Measure` object, the `HazardModifierConfig` populates the `hazard_change` attribute with a function that takes a `Hazard` (possibly additional arguments, see below) and returns a modified one, according to the specifications.\n",
252265
"\n",
253266
"```{note}\n",
254267
"Modifications are always applied to a specific hazard type (`haz_type` parameter).\n",
@@ -268,12 +281,15 @@
268281
"\n",
269282
"In that case the function changing the hazard (`Measure.hazard_change`) will be a function with the following signature:\n",
270283
"\n",
271-
" f(hazard: Hazard, # The hazard to apply on\n",
272-
" exposures: Exposures, # The exposure for the impact computation\n",
273-
" impfset: ImpactFuncSet, # The impfset for the impact computation\n",
274-
" base_hazard: Hazard, # The hazard for the impact computation\n",
275-
" exposures_region_id: Optional[list[int]] = None, # Region id to filter to\n",
276-
" ) -> Hazard\n",
284+
" def hazard_change(\n",
285+
" hazard: Hazard, # Hazard to apply change to\n",
286+
" base_exposures: Exposures, # Exposure to use for impact computation\n",
287+
" base_impfset: ImpactFuncSet, # Impfset to use for impact computation\n",
288+
" base_hazard: Hazard, # Hazard to use for impact computation\n",
289+
" exposures_region_id: Optional[list[int]] = None, # Exposures id to restrict the effect to\n",
290+
" ) -> Hazard\n",
291+
"\n",
292+
"The base_<> triplet is provided by default when the measure is applied so you are not required to supply them if they should indeed be the base triplet before the measure is applied.\n",
277293
"```\n",
278294
"\n",
279295
"```{warning}\n",
@@ -359,7 +375,7 @@
359375
"\n",
360376
"The `ExposuresModifierConfig` is used to define how an adaptation measure changes the exposure (refer to the [exposure tutorial](exposure-tutorial)).\n",
361377
"\n",
362-
"When \"translated\" to a `Measure` object the `ExposuresModifierConfig` populates the `exposures_change` attribute with a function that takes an `Exposures` and returns a modified one, according to the specifications.\n",
378+
"When \"translated\" to a `Measure` object, the `ExposuresModifierConfig` populates the `exposures_change` attribute with a function that takes an `Exposures` and returns a modified one, according to the specifications.\n",
363379
"\n",
364380
"`ExposuresModifierConfig` allows you to modify the impact function assigned to different hazard, to set a list of points to 0 value, or to load a different Exposures:\n",
365381
"\n",
@@ -402,7 +418,9 @@
402418
"\n",
403419
"# 1. Changing existing Exposures\n",
404420
"exp_mod = ExposuresModifierConfig(\n",
405-
" reassign_impf_id={\"TC\": {1: 2}}, # Remaps exposures points with impf_TC == 1 to 2.\n",
421+
" reassign_impf_id={\n",
422+
" \"TC\": {1: 2}\n",
423+
" }, # Reassigns exposures points with impact function id impf_TC == 1 to 2.\n",
406424
" set_to_zero=[\n",
407425
" 0,\n",
408426
" 25,\n",
@@ -427,7 +445,7 @@
427445
"source": [
428446
"## Defining the financial aspects of the measure\n",
429447
"\n",
430-
"For in depth description of CostIncome objects, refer to the [related tutorial](cost-income-tutorial).\n",
448+
"For in depth description of `CostIncome` objects, refer to the [related tutorial](cost-income-tutorial).\n",
431449
"\n",
432450
"```{note}\n",
433451
"The default for mkt_price_year if not provided is the current year.\n",
@@ -460,7 +478,7 @@
460478
"--- Custom Schedule Config ---\n",
461479
"CostIncomeConfig(\n",
462480
"\t\tNon default fields:\n",
463-
"\t\t\tcustom_cash_flows=[{'date': '2024-01-01', 'value': -1000000}, {'date': '2029-01-01', 'value': -200000}, {'date': '2034-01-01', 'value': 500000}]\n",
481+
"\t\t\tcustom_cash_flows=[{'date': '2024-01-01', 'cost': 1000000.0, 'income': 0.0}, {'date': '2029-01-01', 'cost': 200000.0, 'income': 0.0}, {'date': '2034-01-01', 'cost': 10000.0, 'income': 500000}]\n",
464482
")\n"
465483
]
466484
}
@@ -470,13 +488,13 @@
470488
"\n",
471489
"# This models a measure where costs increase by 2% annually,\n",
472490
"# but it generates 100k in yearly income which grows by 3%.\n",
491+
"# By default, the periodicity of costs and income is yearly.\n",
473492
"growth_finance = CostIncomeConfig(\n",
474493
" init_cost=500_000.0,\n",
475494
" periodic_cost=20_000.0,\n",
476495
" cost_yearly_growth_rate=0.02,\n",
477496
" periodic_income=100_000.0,\n",
478497
" income_yearly_growth_rate=0.03,\n",
479-
" freq=\"Y\",\n",
480498
")\n",
481499
"\n",
482500
"print(\"\\n--- Growth & Income Config ---\")\n",
@@ -485,11 +503,12 @@
485503
"\n",
486504
"# Custom Cash Flow\n",
487505
"# If the investment isn't linear (e.g., a major retrofit in year 5),\n",
488-
"# you can define a list of specific events.\n",
506+
"# you can define a custom cash flow, with negative values representing\n",
507+
"# net costs and positive ones net benefits.\n",
489508
"custom_schedule = [\n",
490-
" {\"date\": \"2024-01-01\", \"value\": -1000000}, # Initial cost\n",
491-
" {\"date\": \"2029-01-01\", \"value\": -200000}, # Mid-term overhaul\n",
492-
" {\"date\": \"2034-01-01\", \"value\": 500000}, # Terminal value\n",
509+
" {\"date\": \"2024-01-01\", \"cost\": 1000000.0, \"income\": 0.0},\n",
510+
" {\"date\": \"2029-01-01\", \"cost\": 200000.0, \"income\": 0.0},\n",
511+
" {\"date\": \"2034-01-01\", \"cost\": 10000.0, \"income\": 500000},\n",
493512
"]\n",
494513
"\n",
495514
"custom_finance = CostIncomeConfig(custom_cash_flows=custom_schedule)\n",

0 commit comments

Comments
 (0)