oasislmf.pytools.gulmc.structure

Pre-compute and persist gulmc read-only data structures.

Follows the same pattern as oasislmf.pytools.fm.financial_structure:
  • create_gulmc_structure builds all read-only numpy arrays once and saves them as .npy files.

  • load_gulmc_structure memory-maps them via np.load(mmap_mode='r'), allowing multiple gulmc processes to share physical memory pages through the OS page cache.

Attributes

Functions

build_coverage_dependency_forest(items, n_coverages)

Build the coverage dependency forest from the per-item source_item_id links.

get_conditional_vulns(storage, damage_bins[, ...])

Load the conditional (dependent) vulnerability transition matrices.

align_conditional_damage_axis(conditional_vuln_array, ...)

Align a conditional vulnerability matrix's dependent-damage axis to the vuln array's.

build_vuln_idx_to_cond_idx(items, cond_vuln_ids, n_vulns)

Map each vulnerability's dense index to its conditional (damage-transition) matrix row.

gulmc_structure_exists(run_dir)

Check whether pre-computed gulmc structures exist.

build_structures(run_dir, ignore_file_type, ...)

Build all read-only gulmc data structures from input files.

create_gulmc_structure(run_dir, ignore_file_type, ...)

Build and save all read-only gulmc data structures as .npy files.

load_gulmc_structure(run_dir)

Load pre-computed gulmc structures via memory-mapped numpy files.

Module Contents

oasislmf.pytools.gulmc.structure.logger[source]
oasislmf.pytools.gulmc.structure.STRUCTURE_DIR = 'gulmc_structure'[source]
oasislmf.pytools.gulmc.structure.ARRAY_FILES = ['items', 'coverages', 'item_map_ja_areaperil_ids', 'item_map_ja_offsets',...[source]
oasislmf.pytools.gulmc.structure.build_coverage_dependency_forest(items, n_coverages)[source]

Build the coverage dependency forest from the per-item source_item_id links.

Produces coverage_source_id (indexed by coverage_id, 0 = independent/root) and the parent -> dependents jagged array (coverage_dependents_ja_offsets / coverage_dependents_ja_data) used by the gulmc DFS push, plus source_item_idx: the index into items of each item’s source item, or -1 when it has none. The input preparation guarantees every item of a dependent coverage links to an item of the same source coverage, so the coverage-level forest is a scatter of the resolved coverages.

Parameters:
  • items (np.ndarray) – items table containing ‘coverage_id’ and ‘source_coverage_id’.

  • n_coverages (int) – number of coverage slots (coverages.shape[0] == max coverage_id + 1).

Returns:

coverage_source_id (len n_coverages), coverage_dependents_ja_offsets (len n_coverages + 1), coverage_dependents_ja_data (len = number of dependent coverages), source_item_idx (len items, -1 where the item has no source).

Return type:

tuple(np.ndarray, np.ndarray, np.ndarray, np.ndarray)

Raises:

OasisException – if a source_item_id does not exist, or resolves to a coverage that is out of range, self-referencing or cyclic. These are raised rather than asserted so the checks survive python -O, where a bad id would otherwise reach the njit compute_max_dependency_depth and index out of bounds with no boundscheck.

oasislmf.pytools.gulmc.structure.get_conditional_vulns(storage, damage_bins, ignore_file_type=set())[source]

Load the conditional (dependent) vulnerability transition matrices.

A conditional vulnerability is a damage-transition matrix P(dependent damage bin | source damage bin): it drives a dependent coverage from its source coverage’s sampled damage bin instead of from the footprint hazard. It is a distinct model input from vulnerability and is correctly sized num_damage_bins x num_damage_bins (independent of the footprint’s intensity resolution). Its columns are vulnerability_id, source_damage_bin, damage_bin, probability, and its binary layout is interchangeable with a flat vulnerability file (a 4-byte int32 header, then one record per row), so the csvtobin / bintocsv tools handle it as the conditionalvulnerability file type. The file is optional; when absent, no coverage may be a (conditional) dependent.

Completeness is not required: a source damage bin the source can never reach may be left with no rows. Such a column is filled here with a point mass on the first damage bin — the damage_bin_dict’s no-damage bin — so it samples as “this source damage => no dependent damage”. That requires the first damage bin to be a zero-damage point bin, which is checked; leaving it as an all-zero column instead would make the sampled loss undefined (an all-zero column collapses to a single-element, zero-height cdf, and interpolating within a bin of zero probability height divides by zero).

Parameters:
  • storage (BaseStorage) – storage connector for the model static data.

  • damage_bins (np.ndarray) – the damage_bin_dict (bin_from / bin_to / interpolation).

  • ignore_file_type (set[str]) – file extensions to ignore.

Returns:

conditional_vuln_array of shape (n_cond, num_damage_bins, num_damage_bins) indexed [cond_idx, dependent_damage_bin - 1, source_damage_bin - 1], and cond_vuln_ids (the vulnerability ids, ascending, aligned with cond_idx). Both empty when no file exists.

Return type:

tuple(np.ndarray, np.ndarray)

Raises:

OasisException – if a bin id is out of range (1..num_damage_bins), or if a source damage bin is left undefined while the first damage bin is not a zero-damage point bin.

oasislmf.pytools.gulmc.structure.align_conditional_damage_axis(conditional_vuln_array, Ndamage_bins_max)[source]

Align a conditional vulnerability matrix’s dependent-damage axis to the vuln array’s.

get_conditional_vulns sizes both axes from the damage_bin_dict, but the kernel copies a conditional column straight into a vuln_pdf row (resolve_item_cdfs), whose width is Ndamage_bins_max == vuln_array.shape[1]. That comes from the vulnerability file (parquet metadata, the vulnerability.bin header, or max(damage_bin_id) for csv) and is not guaranteed to equal the damage_bin_dict size — a vulnerability file whose top damage bin is unused makes it smaller. Drop the unreachable tail of the dependent-damage axis so the copy is always a matching-shape assignment, and refuse the run outright in the opposite case, where a source’s sampled damage bin could fall outside the conditional matrix’s source axis.

Parameters:
  • conditional_vuln_array (np.ndarray) – shape (n_cond, num_damage_bins, num_source_bins) as returned by get_conditional_vulns.

  • Ndamage_bins_max (int) – the vulnerability array’s damage bin count (vuln_array.shape[1]).

Returns:

shape (n_cond, Ndamage_bins_max, num_source_bins).

Return type:

np.ndarray

Raises:

OasisException – if a dependent damage bin beyond Ndamage_bins_max carries probability (the conditional file reaches a damage bin the vulnerability array cannot represent), or if Ndamage_bins_max exceeds the damage_bin_dict size.

oasislmf.pytools.gulmc.structure.build_vuln_idx_to_cond_idx(items, cond_vuln_ids, n_vulns)[source]

Map each vulnerability’s dense index to its conditional (damage-transition) matrix row.

conditional_vuln_array is compact (one row per conditional vulnerability), while the kernel reaches it through an item’s vulnerability_idx — the dense index assigned by generate_item_map. This inverts the two: dense vuln index -> conditional row, or -1 for a normal hazard-indexed vulnerability.

Only non-aggregate items carry a vulnerability_idx (generate_item_map assigns it in the non-aggregate branch only, and sets areaperil_agg_vuln_idx instead for aggregates), so aggregate items are excluded: an aggregate vulnerability id that happens to collide with a conditional one must not scatter through an index that was never assigned. A dependent coverage may not use an aggregate vulnerability anyway — validate_coverage_dependency rejects that.

Parameters:
  • items (np.ndarray) – items table with ‘vulnerability_id’, ‘vulnerability_idx’ and ‘areaperil_agg_vuln_idx’.

  • cond_vuln_ids (np.ndarray) – conditional vulnerability ids, ascending (from np.unique).

  • n_vulns (int) – number of dense vulnerability indices (vuln_array.shape[0]).

Returns:

length n_vulns, conditional row per dense vuln index, else -1. The

signed dtype keeps the -1 sentinel usable under an unsigned oasis_int override.

Return type:

np.ndarray[int64]

oasislmf.pytools.gulmc.structure.gulmc_structure_exists(run_dir)[source]

Check whether pre-computed gulmc structures exist.

oasislmf.pytools.gulmc.structure.build_structures(run_dir, ignore_file_type, peril_filter, dynamic_footprint, model_df_engine)[source]

Build all read-only gulmc data structures from input files.

This extracts the preparation logic from manager.run() into a standalone callable so that it can be invoked once (by create_gulmc_structure) rather than repeated in every parallel gulmc process.

Parameters:
  • run_dir (str) – path to the run directory.

  • ignore_file_type (set[str]) – file extensions to ignore when loading.

  • peril_filter (list) – list of perils to include (empty = all).

  • dynamic_footprint (bool) – whether to apply dynamic footprint logic.

  • model_df_engine (str) – engine for loading model dataframes.

Returns:

mapping variable names to numpy arrays / scalars.

Return type:

dict

oasislmf.pytools.gulmc.structure.create_gulmc_structure(run_dir, ignore_file_type, peril_filter, dynamic_footprint, model_df_engine)[source]

Build and save all read-only gulmc data structures as .npy files.

Parameters:
  • run_dir (str) – path to the run directory.

  • ignore_file_type (set[str]) – file extensions to ignore when loading.

  • peril_filter (list) – list of perils to include (empty = all).

  • dynamic_footprint (bool) – whether to apply dynamic footprint logic.

  • model_df_engine (str) – engine for loading model dataframes.

oasislmf.pytools.gulmc.structure.load_gulmc_structure(run_dir)[source]

Load pre-computed gulmc structures via memory-mapped numpy files.

Each array is loaded with mmap_mode='r' so that multiple gulmc processes share physical memory pages through the OS page cache.

Parameters:

run_dir (str) – path to the run directory.

Returns:

mapping variable names to numpy arrays / scalars.

Return type:

dict