Release notes v3.12#

The 3.12 release is the result of 6 months of work involving around 550 pull requests and touching all aspects of the engine.

Most of the work went into the optimization/enhancement of the risk calculators - notably the event based risk and damage calculators - and into a full rewrite of the GMPE library, described in this post:

The complete list of changes is listed in the changelog:

New risk features#

Flexible field names in exposure csv files#

Before engine 3.11 the header names of the columns in a CSV exposure was hard-coded and therefore one had to manually rename columns to strictly match the names required by the engine from any pre-existing exposure files. That often meant maintaning two exposure formats and required the exposure files for the engine to be regenerated after any changes in the original one. Now a user can simply specify a mapping of the custom column names in their exposure files to the names required by the engine, in the exposure.xml metadata file.

An example is given here:

ShakeMaps enhancements#

There was a nontrivial amount of work on the ShakeMaps module, mostly contributed by Nicolas Schmid of ETH Zurich. Now it is possible to read a ShakeMap from a custom URL (or local file) and not only from the USGS site. It is also possible to read ShakeMaps in ShapeFile format, as well as many other formats (.xml, .zip, .npy). Moreover we now support the MMI intensity measure type if spatial and cross correlation are disabled. The advanced manual has been updated with the new features, see

Risk calculations starting from GMFs in HDF5#

It is now possible to run risk calculations starting from GMFs in HDF5 format by setting the option

gmfs_file = gmf-data.hdf5

but that involves some limitations. The HDF5 format of the GMFs is meant to be stable across engine versions. However, the details of the logic- tree implementation change in every release. Therefore, the approach can only work if risk calculations starting from GMFs in HDF5 format are restricted to see a single realization, obtained by collecting together all realizations. This is equivalent to using the new option


Notice that the results will be meaningful and corresponding to mean results only if originally all the realizations have the same weight, which is the case if the original hazard calculation was using sampling of the logic tree.

Event based risk calculators#

  • The work on unifying the scenario_risk, event_based_risk and ebrisk calculators - started in engine 3.11 - has been finally completed. Thanks to this work the ebrisk calculator is now deprecated. You should use the event_based_risk calculator instead, since it is more efficient than ebrisk ever was. The trick was to change event_based_risk to use the same distribution mechanism as ebrisk (i.e. distribution by ruptures, not by site).

  • The management of random numbers in risk calculations has been changed. In particular, previously, it was impossible to run even medium-sized event based risk calculations if the vulnerability functions had non-zero coefficients of variation, because all the time was spent reading a huge matrix of epsilons which could be hundreds of GB in size.

Now the epsilons matrix has disappeared since the corresponding random numbers (governed by the master_seed parameter) are generated dynamically by using modern numpy features (i.e. the numpy.random.Philox random number generator).

However, running extra-large event based risk calculations may still impossible unless you set ignore_master_seed = true, which effectively turns off the generation of the epsilons.

  • The work on the risk random numbers allowed us to fix some long standing bugs in calculations with vulnerability functions using the Beta distribution (dist=”BT”). In particular, the results are now independent from the number of spawned tasks, and are the same both for ebrisk and event_based_risk. Before engine 3.12 we were not able to ensure 100% replicability of results from risk calculations using the beta distribution in the vulnerability functions.

  • A lot of work went into estimating and saving the variance of the losses due to the coefficients of variation, therefore, it is possible to set ignore_master_seed = true for performance reasons but still have an indication of the uncertainty. Such information is only available by reading the event loss table with pandas and is not exposed as a CSV file, due to the sheer amount of data involved.

  • Aggregation by tag has been optimized - their calculation now utilizes all available cores and a lot less memory - and is documented in the advanced manual, see the section

  • Moreover, it is now possible to set the parameter

    collect_rlzs = true

    in the job.ini file. That makes the risk part of an event based risk calculation even faster and more memory efficient than before, at the price of losing information about the specific realizations.

    For continental scale calculations setting collect_rlzs = true can make the difference between being able to run a calculation and being unable to do so due to memory constraint or computational constraints.

  • Finally the scenario from CSV ruptures calculators have been extended to work with multiple TRTs.

Event based damage calculator#

We introduced an experimental event_based_damage calculator in the engine in v3.8. Now it has been rewritten, optimized, and extended, so that it is possible to use it for very large calculations and to compute generic consequences based on the damage tables, not only for economic losses.

In order to be efficient, some features had to be sacrified, and in particular it is not possible to compute consequences for each individual realization: we can can only compute means. This is equivalent to using collect_rlzs = true in event_based_risk. To be completely correct, it is actually possible to compute the consequences for a specific realization, but it is inconvenient since you have to manually change the logic tree until there is only the desired realization.

If you want to see an example of usage of the calculator, you should look at the EventBasedDamage demo:

The new EventBasedDamage also works in presence of a taxonomy mapping file, a feature that was missing in the past. Currently the following generic consequences are supported: “losses”, “collapsed”, “injured”, “fatalities”, “homeless”. Since the mechanism to add a new consequence is now quite simple, more are expected to be supported in the future. You can print the updated list of available consequences with the command

$ oq info consequences

New optimizations in the hazard calculators#

  • We improved the rupture weighting algorithm, thus removing some dramatic slow tasks in event based calculations.

  • We also saved some preprocessing time by weighting the heavy sources in parallel in event based calculations.

  • We saved memory when generating PoEs in classical calculations and we mitigated the slow task issue when using the point source gridding approximation.

  • We also did some experiments with the optimizing compiler numba and we were able to speedup significantly some parts of the engine - we measured a 54x speedup when computing the mean hazard curves - but sadly not the real bottlenecks. numba is not a dependency of the engine and everything works without it. The plan is to keep it that way.

Refactoring of the GMPE library#

The GMPE library has been completely rewritten and the API for implementing new GMPEs has changed significantly. That means that if you have written a GMPE with the old API it will not work anymore once you upgrade to engine 3.12: you will have to rewrite it. This is quite simple is the GMPE is simple, but it can be quite difficult if the GMPE depends from other GMPEs in complex ways. Should you encounter any compatibility issue, please contact us.

On the bright side, if you are just using library GMPEs by calling the method .get_mean_and_stddevs, your application should work exactly as before. We tried very hard to keep backward compatibility as much as possible.

As part of the refactoring, 15 GMPEs of the SHARE model have been vectorized and are now a lot faster than before (up to 200x in single site situations). The rest of the GMPEs have not been vectorized, so they are slow as before. The good news is that with the new API it easy to vectorize a GMPE and more are expected to be vectorized in the future.

Due to the refactoring work, many things have changed internally, and are listed here for completeness sake:

  • hazardlib.const.TRT is now an Enum class

  • hazardlib.imt.PGA, SA and all other constructors are now factory functions and not classes

  • there is a limit of 12 characters to IMT names

  • multiple inheritance in GMPE hierarchies has been forbidden

  • defining methods different from __init__ and compile in GMPE classes is now an error

  • a name convention on GMPE classes has been enforced: attributes starting with COEFF must be instances of the the CoeffsTable class, which has been refactored too

Other updates to hazardlib#

There was also a lot of activity not related to the refactoring:

  • we fixed a bug in the Abrahamson et al. (2014) GMPE and updated the verification tables

  • we added a hazardlib.cross_correlation module to compute the correlation between different intensity measure types

  • we implemented MultiFaultSources, a new typology of sources to be used in UCERF-like models

  • we improved the precision of site amplification with the convolution method

  • we added more epistemic uncertainties to the logic tree module

  • we fixed a few bugs in KiteSurfaces (having to do with NaN values)

  • we added a classmethod PlanarSurface.from_hypocenter

  • we updated the parameter DEFINED_FOR_REFERENCE_VELOCITY in a few GMPEs -we optimized the SiteCollection class and now unneeded parameters are not stored anymore; an example could be the parameter reference_depth_to_2pt5km_per_sec in a calculations with GMPEs that do not require it; same for the reference_siteclass and reference_backarc parameters

  • we changed how the SiteCollection is stored so that it can be read with pandas

  • we changed the signature of the functions calc.hazard_curve.classical and calc.stochastic.sample_ruptures

New GMPEs#

Finally, many new GMPEs have been contributed.

  • Graeme Weatherill has contributed the Abrahamson & Gulerce (2020) NGA Subduction Model as well as the Ameri (2014) Rjb GMPE. Moreover, he has updated the Atkinson (2015) GMPE in accordance with the indications of the original author. He also updated the KothaEtAl2020ESHMSlopeGeology GMPE, following changes to the underlying geology dataset.

  • Nico Kuehn and Graeme Weatherill have contributed the NGA Subduction ground motion model of Si, Midorikawa and Kishida (2020) as well as the Kuehn et al. (2020) NGA Subduction Model.

  • Stanley Sayson contributed the Gulerce and Abrahamson (2011) GMPE for the vertical-to-horizontal (V/H) ratio model derived using ground motions from the PEER NGA-West1 Project. Moreover he contributed the SBSA15b GMPE by Stewart et al. (2016) vertical-to-horizontal ratio (V/H) for ground motions from the PEER NGA-West2 Project, as well as the GMPE by Bozorgnia & Campbell (2016) for vertical-to-horizontal (V/H) ratio. Finally he fixed a few bugs in the Campbell and Bozorgnia (2014) GMPE.

  • Chung-Han Chan and Jia-Cian Gao have contributed a couple of GMPEs for the Taiwan 2020 hazard model (TEM): Lin2011foot and Lin2011hanging.

  • Pablo Heresi has contributed the Idini (2017) GMPE.

  • Cladia Mascandola has contributed the Lanzano et al (2020) GMPE and the Sgobba et al. (2020) GMPE.

  • Laurentiu Danciu has contributed the Boore (2020) GMPE.


  • We fixed a few bugs in the CSV exporters. First, the encoding was not specified, thus causing issues when exporting exposure data on systems with a non-UTF8 locale (affecting a Chinese user). Second, the CSV exporters on Windows were not producing the right line ending. Finally, we fixed some CSV exporters that were not generating the usual pre-header line with the metadata of the calculation, such as the date and the engine version.

  • There was a bug in scenario damage calculations, happening (rarely) in situations with very few events and causing an IndexError in the middle of the calculation. This is fixed now.

  • We fixed a subtle bug in risk calculations with a nontrivial taxonomy mapping: loss curves could be not computed due to spurious duplicated event IDs in the event loss table.

  • We fixed a bug in the serialization of the gsim logic tree in the datastore, preventing a correct deserialization due to missing branchset attributes.

  • We fixed a bug in the logic tree processing: the option applyToSources did not work with multipoint sources, by not modifying the parameters and by producing the same contribution for each branch.

  • We fixed the function baselib.hdf5.dumps that was generating invalid JSON for Windows pathnames, thus breaking the QGIS plugin on Windows.

  • We fixed a bug in the management of GMPE aliases; now the dictionary returned by get_available_gsims() contains also the aliases. That means that now the Input Preparation Toolkit (IPT) also work with GMPE aliases.

New checks and warnings#

  • Years ago we restricted the asset_correlation parameter to be 0 or 1. Setting an unsupported value now raises a clear error early in the calculation an not in the middle of it, also for scenario risk calculations.

  • We added a check to forbid -Inf in the sources. This happened to people generating the source model automatically, where the XML file contained things like

<truncGutenbergRichterMFD aValue="-Inf" bValue="0.90" maxMag="6.5" minMag="4.5"/>
  • We added an early check to discover situations in which the user mistakenly uses fragility functions in place of vulnerability functions or viceversa.

  • We added a warning if extreme ground motion values (larger than 10g) are generated by the engine. This may happen for sites extremely close to a fault.

  • The warning about discardable tectonic region types now appears in all calculations, not only in classical calculations.

  • A warning is now printed if the loss curves appear to be numerically instable.

  • Setting a too large area_source_discretization parameter was breaking the engine with an ugly error; now you get a clear error message.

oq commands#

  • The command oq checksum source_model_logic_tree.xml was broken, raising a TypeError. It is fixed now.

  • The command oq workers kill (to be used on a linux cluster) now calls killall and kills all processes of the user openquake, including possible zombies left by an out-of-memory crash, so it is much better than before.

  • We added a new kind of plot (oq plot uhs_cluster) displaying similar uniform hazard spectra from different realizations clustered together.

  • We added a new command oq export disagg_traditional to export the disaggregation outputs in traditional format (i.e. Bazzurro and Cornell 1999), where the probabilities sum up to 1.

  • The command oq --version now gives the git hash if the engine was installed with the universal installer using the --version=master option.

Other changes#

  • As often is the case with every new release, the inner format of the datastore has changed in several places, and in particular, the event loss table has been renamed from losses_by_event to risk_by_event, since this table can now also be populated by the event-based damage calculator, with consequences other than economic losses.

  • The XML exporter for the ruptures, deprecated years ago, has been finally removed. You should use the CSV exporter instead.

  • The experimental feature “pointsource_distance=?” has been removed. It was complicating the engine without giving a significant benefit.

  • The special feature minimum_distance ( now works with a single parameter in the job.ini which is used for all GMPEs. This is simpler and more consistent than the previous approach that required changing the gsim logic tree XML file by adding an attribute to each GMPE.

  • For single-site classical calculations now the engine automatically stores individual hazard curves for each realization.

  • The hazard curve and UHS exporters now export the custom_site_id parameter if defined.

  • We improved the universal installer, especially on Windows.

  • We upgraded Django to release 3.2.6.

  • We updated the documentation (including the API docs) and the demos.