From 2c67939663dd877aeefcb3ba3d80bcaf2f257964 Mon Sep 17 00:00:00 2001 From: Michele Simionato Date: Wed, 30 Aug 2023 06:51:18 +0200 Subject: [PATCH 1/4] Fixed two export bugs in absence of ruptures --- debian/changelog | 2 ++ openquake/calculators/base.py | 4 +++- openquake/calculators/export/risk.py | 14 ++++++++------ openquake/calculators/tests/classical_test.py | 6 +++--- openquake/engine/engine.py | 2 +- 5 files changed, 17 insertions(+), 11 deletions(-) diff --git a/debian/changelog b/debian/changelog index ed588ce2ed35..759dc82dcb28 100644 --- a/debian/changelog +++ b/debian/changelog @@ -1,4 +1,6 @@ [Michele Simionato] + * Fixed a bug when exporting `risk_by_event` in absence of ruptures + * Fixed a bug by not exporting `event_based_mfd` in absence of ruptures * Implemented Risk Targeted Disaggregations for the AELO project * Enabled the pointsource_distance approximation by default at 100 km * Fixed an error with sources below the minimum_magnitude diff --git a/openquake/calculators/base.py b/openquake/calculators/base.py index d137b4ccb79e..09c830900090 100644 --- a/openquake/calculators/base.py +++ b/openquake/calculators/base.py @@ -321,8 +321,10 @@ def export(self, exports=None): 'hcurves-rlzs' in self.datastore) if has_hcurves: keys.add('hcurves') - if 'ruptures' in self.datastore: + if 'ruptures' in self.datastore and len(self.datastore['ruptures']): keys.add('event_based_mfd') + elif 'ruptures' in keys: + keys.remove('ruptures') for fmt in fmts: if not fmt: continue diff --git a/openquake/calculators/export/risk.py b/openquake/calculators/export/risk.py index 38293f46874d..6f9ee17f9bbc 100644 --- a/openquake/calculators/export/risk.py +++ b/openquake/calculators/export/risk.py @@ -256,7 +256,7 @@ def export_event_loss_table(ekey, dstore): md.update(dict(investigation_time=oq.investigation_time, risk_investigation_time=oq.risk_investigation_time or oq.investigation_time)) - events = dstore['events'][()] + events = dstore.read_df('events', 'id') K = dstore.get_attr('risk_by_event', 'K', 0) try: lstates = dstore.get_attr('risk_by_event', 'limit_states').split() @@ -269,11 +269,13 @@ def export_event_loss_table(ekey, dstore): del df['variance'] ren = {'dmg_%d' % i: lstate for i, lstate in enumerate(lstates, 1)} df.rename(columns=ren, inplace=True) - evs = events[df.event_id.to_numpy()] - if 'scenario' not in oq.calculation_mode: - df['rup_id'] = evs['rup_id'] - if 'scenario' not in oq.calculation_mode and 'year' in evs.dtype.names: - df['year'] = evs['year'] + df = df.join(events, on='event_id') + if 'ses_id' in df.columns: + del df['ses_id'] + del df['rlz_id'] + if 'scenario' in oq.calculation_mode: + del df['rup_id'] + del df['year'] df.sort_values(['event_id', 'loss_type'], inplace=True) writer.save(df, dest, comment=md) return writer.getsaved() diff --git a/openquake/calculators/tests/classical_test.py b/openquake/calculators/tests/classical_test.py index d2e4dc7efd95..03a1b816c883 100644 --- a/openquake/calculators/tests/classical_test.py +++ b/openquake/calculators/tests/classical_test.py @@ -658,9 +658,9 @@ def test_case_78(self): hazard_calculation_id=hc_str) # skipped because broken on CI due to a mysterious extra space - # dbm = view('disagg:Dist', self.calc.datastore) - # fname = general.gettemp(text_table(dbm, ext='org')) - # self.assertEqualFiles('expected/disagg_by_dist.org', fname) + dbm = view('disagg:Dist', self.calc.datastore) + fname = general.gettemp(text_table(dbm, ext='org')) + self.assertEqualFiles('expected/disagg_by_dist.org', fname) def test_case_80(self): # New Madrid cluster with rup_mutex diff --git a/openquake/engine/engine.py b/openquake/engine/engine.py index 151797119b2c..860eaadbe484 100644 --- a/openquake/engine/engine.py +++ b/openquake/engine/engine.py @@ -136,7 +136,7 @@ def expose_outputs(dstore, owner=USER, status='complete'): if 'loss_curves-stats' in dstore: dskeys.add('loss_maps-stats') if 'ruptures' in dskeys: - if 'scenario' in calcmode: + if 'scenario' in calcmode or len(dstore['ruptures']) == 0: # do not export, as requested by Vitor exportable.remove('ruptures') else: From cef92a8a331bc8e86e28475ef631b054f82dab46 Mon Sep 17 00:00:00 2001 From: Michele Simionato Date: Wed, 30 Aug 2023 07:15:30 +0200 Subject: [PATCH 2/4] Fixed comments [ci skip] --- openquake/calculators/tests/classical_test.py | 1 - openquake/hazardlib/calc/mean_rates.py | 1 + 2 files changed, 1 insertion(+), 1 deletion(-) diff --git a/openquake/calculators/tests/classical_test.py b/openquake/calculators/tests/classical_test.py index 03a1b816c883..df2c4f165351 100644 --- a/openquake/calculators/tests/classical_test.py +++ b/openquake/calculators/tests/classical_test.py @@ -657,7 +657,6 @@ def test_case_78(self): disagg_bin_edges='{"dist": [0, 15, 30]}', hazard_calculation_id=hc_str) - # skipped because broken on CI due to a mysterious extra space dbm = view('disagg:Dist', self.calc.datastore) fname = general.gettemp(text_table(dbm, ext='org')) self.assertEqualFiles('expected/disagg_by_dist.org', fname) diff --git a/openquake/hazardlib/calc/mean_rates.py b/openquake/hazardlib/calc/mean_rates.py index dc180a59e3bb..09b0be907be0 100644 --- a/openquake/hazardlib/calc/mean_rates.py +++ b/openquake/hazardlib/calc/mean_rates.py @@ -33,6 +33,7 @@ def to_rates(probs, itime=1): """ pnes = 1. - probs pnes[pnes == 0] = 1E-45 # mininum 32 bit float + # NB: the test most sensitivie to 1E-45 and 1E-12 is case_78 return numpy.clip(- numpy.log(pnes) / itime, 1E-12, 100) From c435853888493b52827887df4f0bf0b6bed6da4d Mon Sep 17 00:00:00 2001 From: Michele Simionato Date: Wed, 30 Aug 2023 07:25:54 +0200 Subject: [PATCH 3/4] Fixed test --- openquake/calculators/export/risk.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openquake/calculators/export/risk.py b/openquake/calculators/export/risk.py index 6f9ee17f9bbc..fb4d138b6bea 100644 --- a/openquake/calculators/export/risk.py +++ b/openquake/calculators/export/risk.py @@ -275,7 +275,8 @@ def export_event_loss_table(ekey, dstore): del df['rlz_id'] if 'scenario' in oq.calculation_mode: del df['rup_id'] - del df['year'] + if 'year' in df.columns: + del df['year'] df.sort_values(['event_id', 'loss_type'], inplace=True) writer.save(df, dest, comment=md) return writer.getsaved() From 98a51e23809f6515c7b3ad7f86bf956cd8cebab9 Mon Sep 17 00:00:00 2001 From: Michele Simionato Date: Wed, 30 Aug 2023 07:28:11 +0200 Subject: [PATCH 4/4] Fixed comment [ci skip] --- openquake/hazardlib/calc/mean_rates.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openquake/hazardlib/calc/mean_rates.py b/openquake/hazardlib/calc/mean_rates.py index 09b0be907be0..322f28fea4df 100644 --- a/openquake/hazardlib/calc/mean_rates.py +++ b/openquake/hazardlib/calc/mean_rates.py @@ -33,7 +33,7 @@ def to_rates(probs, itime=1): """ pnes = 1. - probs pnes[pnes == 0] = 1E-45 # mininum 32 bit float - # NB: the test most sensitivie to 1E-45 and 1E-12 is case_78 + # NB: the test most sensitive to 1E-45 and 1E-12 is case_78 return numpy.clip(- numpy.log(pnes) / itime, 1E-12, 100)