Geospatial risk modeling including catastrophe models, exposure analysis, and underwriting. Use when assessing spatial risk, building catastrophe models, analyzing exposure/hazard/vulnerability, or computing portfolio risk metrics.
Resources
9Install
npx skillscat add activeinferenceinstitute/geo-infer/geo-infer-risk Install via the SkillsCat registry.
This skill provides geospatial risk modeling through catastrophe modeling, exposure analysis, and hazard assessment. It enables the calculation of portfolio risk metrics and loss exceedance using Monte Carlo simulations and spatial correlation. Use this tool when assessing spatial risk, quantifying vulnerability uncertainty, or performing underwriting tasks involving multi-source exposure data.
GEO-INFER-RISK
Instructions
Core Capabilities
- Catastrophe models: Spatial correlation and directed multi-hazard interactions
- Risk engine: Moran's I, Geary C, Monte Carlo loss calculation
- Exposure modeling: Multi-source data loading (DB, file, stream, API)
- Hazard modeling: Spatial hazard assessment and mapping
- Vulnerability: Bayesian uncertainty quantification
- Underwriting: Rule-based fraud detection, env var API keys
Key Imports
from geo_infer_risk.core.risk_engine import EnhancedRiskEngine
from geo_infer_risk.core.catastrophe_models import (
EnhancedCatastropheModel,
MultiHazardInteractionMatrix,
)
from geo_infer_risk.core.exposure_model import EnhancedExposureModel
from geo_infer_risk.core.hazard_model import EnhancedHazardModelExamples
Every snippet below runs against the current API.
Reproducible catastrophe simulation. The seed lives on the config, and all
draws come from the model's own generator, so a run replays exactly and never
disturbs the caller's numpy.random stream:
from geo_infer_risk.core.catastrophe_models import (
CatastropheConfig,
EnhancedEarthquakeModel,
)
config = CatastropheConfig(
simulation_years=50, spatial_correlation=False, random_seed=7
)
model = EnhancedEarthquakeModel(config=config)
model.model_parameters = {"mean_depth": 15.0}
events = model.simulate_events(200)Estimate compound annual exceedance along a directed hazard chain. Zero
off-diagonal interaction recovers independent joint exceedance; positive
interaction raises the downstream conditional probability:
from geo_infer_risk.core import MultiHazardInteractionMatrix
interactions = MultiHazardInteractionMatrix(
["earthquake", "fire_following", "flood"],
[[1.0, 0.5, 0.0], [0.0, 1.0, 0.4], [0.0, 0.0, 1.0]],
)
compound_probability = interactions.compound_exceedance_probability(
{"earthquake": 0.1, "fire_following": 0.2, "flood": 0.3}
)Risk metrics from an event loss table. exposure_years is how many years the
table spans; omit it and every per-year figure is inflated (a warning says so):
import pandas as pd
from geo_infer_risk.utils.risk_metrics import (
calculate_aal,
calculate_pml,
calculate_annual_aggregate_exceedance_probability,
)
losses = pd.DataFrame(
{
"event_id": [event["event_id"] for event in events],
"hazard_type": ["earthquake"] * len(events),
"loss": modelled_losses, # one loss per event
}
)
aal = calculate_aal(losses, exposure_years=50.0)["total"]
pml_25 = calculate_pml(losses, return_period=25, exposure_years=50.0)
aep = calculate_annual_aggregate_exceedance_probability(
losses, threshold=5e6, num_years=20_000, random_seed=7, exposure_years=50.0
)calculate_pml warns when the requested return period is longer than the
record can resolve; the value is then clamped to the largest observed loss and
understates the tail.
Reproducibility
Every stochastic entry point in this module takes a random_seed and routes it
through geo_infer_risk.utils.rng.resolve_rng, which accepts None, an int,
a SeedSequence, a BitGenerator, a numpy.random.Generator, or a legacyRandomState, and always returns a Generator. Consequences worth knowing:
- Passing an
intmakes a run replayable;0is a valid seed. - Passing a
Generatorthreads one stream through a whole pipeline. Nonemeans OS entropy, so results are not replayable. Callingnp.random.seed(...)does not make them so: this module never reads the
process-wide singleton, and never advances it either.- For independent parallel streams use
geo_infer_risk.utils.rng.spawn_rng(seed, n)rather thanseed,seed + 1,
... which carries no independence guarantee. - At boundaries that accept only an
intseed, such as scikit-learn'srandom_state, usegeo_infer_risk.utils.rng.derive_int_seed.
Guidelines
- Production paths require configured data sources and do not fabricate risk inputs.
- Spatial correlation uses Cholesky decomposition
- Directed interaction entries are bounded to
[-1, 1]; ordered compound
exceedance uses the configured source-to-target chain - Risk aggregation uses real Moran's I and Monte Carlo
- Exceedance-probability curves use the Weibull plotting position and
interpolate loss as a function of exceedance probability; return periods
beyond the record are clamped, not extrapolated - Pass
exposure_yearsto any per-year metric (AAL, OEP, AEP, and the
annualized EP curve); the fallback treats the table as spanning one year - Test:
uv run python -m pytest GEO-INFER-RISK/tests/ -v
Integrations
- BAYES → Bayesian uncertainty quantification
- ECON → Economic loss and insurance modeling
- CLIMATE → Climate-driven hazard projections
- SPACE → Spatial correlation of hazards
- AG → Crop loss risk assessment