diff --git a/.github/workflows/test-install.yml b/.github/workflows/test-install.yml new file mode 100644 index 0000000000..65994b79b7 --- /dev/null +++ b/.github/workflows/test-install.yml @@ -0,0 +1,49 @@ +# Check if installation with conda/mamba works + +name: Install Test + +on: + schedule: + - cron: "0 6 * * *" + workflow_dispatch: + +jobs: + install-conda: + name: Install from Conda + timeout-minutes: 10 + + strategy: + fail-fast: false + matrix: + python-version: ["3.10", "3.11", "3.12"] + os: [ubuntu-latest, windows-latest, macos-latest] + + runs-on: ${{ matrix.os }} + + steps: + - + name: Install with Mamba + uses: mamba-org/setup-micromamba@v2 + with: + environment-name: climada_env_${{ matrix.python-version }} + create-args: >- + python=${{ matrix.python-version }} + climada + init-shell: bash powershell + # Recompute environment for each run, but possibly use cached downloads + cache-environment: false + cache-downloads: true + cache-downloads-key: downloads-${{ matrix.os }}-py${{ matrix.python-version }} + - + name: Test CLIMADA (bash) + shell: bash -el {0} + run: | + python -c "import climada" + python -m unittest climada.engine.test.test_impact + - + name: Test CLIMADA (powershell) + shell: pwsh + if: ${{ matrix.os == 'windows-latest' }} + run: | + python -c "import climada" + python -m unittest climada.engine.test.test_impact diff --git a/CHANGELOG.md b/CHANGELOG.md index ae9b568374..b618408e94 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,12 +1,8 @@ # Changelog -## Unreleased - -Release date: YYYY-MM-DD - -Code freeze date: YYYY-MM-DD +## 6.1.0 -### Description +Release date: 2025-09-30 ### Dependency Changes diff --git a/climada/hazard/io.py b/climada/hazard/io.py index 6f8bd01b09..679fd6722c 100644 --- a/climada/hazard/io.py +++ b/climada/hazard/io.py @@ -44,6 +44,18 @@ LOGGER = logging.getLogger(__name__) +ATTRS_TO_CHECK = { + "event_name": (list, (str, np.str_)), # int for backward compatibility + "event_id": (np.ndarray, None), + "frequency": (np.ndarray, float), + "frequency_unit": (str, None), + "date": (np.ndarray, (int, np.int64)), + "orig": (np.ndarray, (bool, np.bool_)), + "unit": (str, None), # For backward compatibility. Replaced by units. + "units": (str, None), +} +"""Additional attributes that can be specified when reading a raster file""" + DEF_VAR_EXCEL = { "sheet_name": {"inten": "hazard_intensity", "freq": "hazard_frequency"}, "col_name": { @@ -135,7 +147,8 @@ def from_raster( files_fraction : list(str) file names containing fraction attrs : dict, optional - name of Hazard attributes and their values + name of Hazard attributes and their values. See the ATTRS_TO_CHECK constant for supported attributes. + Missing attributes will be filled with sensible defaults. band : list(int), optional bands to read (starting at 1), default [1] haz_type : str, optional @@ -693,11 +706,13 @@ def _check_and_cast_elements( # Perform type checking and casting of elements if isinstance(attr_value, (list, np.ndarray)): if not all(isinstance(val, expected_dtype) for val in attr_value): + provided_types = set(type(val) for val in attr_value) warnings.warn( - f"Not all values are of type {expected_dtype}. Casting values.", + f"Not all values are type {expected_dtype}. Provided type(s): {provided_types}. Casting values.", UserWarning, ) - casted_values = [expected_dtype(val) for val in attr_value] + cast_dtype = expected_dtype if not isinstance(expected_dtype, tuple) else expected_dtype[0] + casted_values = [cast_dtype(val) for val in attr_value] # Return the casted values in the same container type if container_type is list: return casted_values @@ -712,10 +727,7 @@ def _check_and_cast_elements( return attr_value - ## This should probably be defined as a CONSTANT? - attrs_to_check = {"event_name": (list, str), "event_id": (np.ndarray, None)} - - for attr_name, (expected_container, expected_dtype) in attrs_to_check.items(): + for attr_name, (expected_container, expected_dtype) in ATTRS_TO_CHECK.items(): attr_value = attrs.get(attr_name) if attr_value is not None: @@ -777,6 +789,8 @@ def _attrs_to_kwargs(attrs: Dict[str, Any], num_events: int) -> Dict[str, Any]: kwargs["orig"] = np.ones(kwargs["event_id"].size, bool) if "unit" in attrs: kwargs["units"] = attrs["unit"] + if "units" in attrs: + kwargs["units"] = attrs["units"] return kwargs