Release notes v3.6#

This release features several major new features (including completely revised disaggregation, automatic optimization of duplicated sources, fast exposure importer and taxonomy mapping) and lots of improvements, new checks and bug fixes. Nearly 200 pull requests were merged. For the complete list of changes, see the changelog:


The most relevant development on the hazard side was the work on the disaggregation calculator. We changed substantially the business logic. While in previous versions of the engine we were disaggregating for all possible realizations in order to compute disaggregation statistics, in this version we gave up on statistics. Instead, we disaggregate only for a specific realization. The realization can be specified by the user with the rlz_index parameter in the job.ini file, or it can be determined automatically by the engine as the realization closest to the mean curve for the given disaggregation site.

Moreover, now the disaggregation calculation works like a post-calculator (i.e. with the --hc option) and it is able to reuse information computed in its parent calculation: the net effect is that it is always faster than the corresponding classical calculation while in the past it was several times slower. We also fixed a couple of performance bugs: there was a slow operation truncnorm.cdf in an inner loop and ruptures outside the integration distance were not discarded. Finally, we changed the file names of the disaggregation outputs.

For models with thousands of realizations, the disaggregation can easily be thousands of times faster than before.

Classical PSHA calculator#

The engine is now smart enough to recognize duplicated sources appearing in different branches of the composite source model and to avoid redundant computations. Because this optimization is always on, the flag optimize_same_id_sources has been removed, as it has now been rendered useless. There are several models in the hazard mosaic with duplicates sources and the new optimization has a significant impact on those. Moreover the demo LogicTreeCase2ClassicalPSHA has become an order of magnitude faster than before thanks to the reduction of the duplicated sources.

There was a big improvement in the computation of the statistical hazard curves which now is not only faster, but uses a lot less memory than before. The trick was to consider one site at the time, instead of a block of sites. As a consequence it is now possible to consider tens of thousands of realizations for hundreds of thousands of sites without requiring terabytes of RAM. Moreover the data transfer has been reduced by storing some auxiliary information in the datastore and reading it from the workers instead of transferring it via celery/rabbitmq.

There was a substantial change in the way the tasks are distributed for a classical calculation. The engine has acquired the ability to estimate the runtime of each task and if the estimated time exceeds a task_duration parameter, the engine is able to split the task in subtasks that run in less than task_duration seconds. The user can set the task_duration manually in the job.ini, or she can leave it empty; in that case the engine will figure out a reasonable value for it.

The approach is not perfect since there are non-splittable sources, so there is a minimum size for a given subtask and sometimes subtasks taking much longer that the task_duration parameter may still appear: however, the new approach is a drastic improvement and the situation was never better than it is now.

We added a check on sources with a suspiciously large spatial extent (more than 5,000 km) so that a warning is printed. Usually this means that there was a bug in the generation of the source model.

We added a check on sources with suspicious hypo-depths and nodal plane distributions (i.e. distributions with duplicated values) since they make the calculation slower.

In extra-large models saving some debugging information (eg. the number of sites affected by each source) was exceedingly slow, so now the information is stored only if there are fewer than 100,000 relevant sources.

Logic trees#

There was a tricky bug with the minimum_distance feature in presence of multiple GSIMs in a logic tree branchset. Now each GSIMs keeps its own minimum distance; before they were all getting the same minimum distance, causing wrong results to be computed. Fortunaly the minimum_distance feature is rarely used (and only for internal purposes) so the bug is minor. The feature is documented here:

We implemented zero weights for intensity measure types that should be discarded in the GSIM logic tree. You can see the relevant documentation here:

We implemented risk logic trees, a.k.a. the taxonomy mapping feature. The idea is that users can map the taxonomy strings in their exposure to one or more vulnerability/fragility functions, with corresponding weights for each function assignment, to take into account the epistemic uncertainty in the exposure ⟷ vulnerability domain. The feature is documented here:

A big conceptual change (but with no impact on the user) was the simplification of the source model logic tree XML file. Before it was necessary to specify a logicTreeBranchingLevel node that was not used internally, now that node is optional. Old files will keep working, as long as the logicTreeBranchingLevel contains only a single subnode. The case of multiple subnodes is now correctly flagged as an error. Thanks to the change, source model logic trees, gsim logic tree, and risk logic trees are now stored in the same way internally.

Lastly, we fixed a bug in source model logic trees with the options applyToSources and applyToBranches on; in some times a fake error about the source not being in the source model - even if it actually was - was raised.

Event based hazard#

We introduced a parameter max_sites_per_gmf in the job.ini (only for event_based calculations that are trying to store ground motion fields), with a default of 65,536 sites. A user trying to run an event_based calculation that has ground_motion_fields = true, with more than the number of sites permitted by max_sites_per_gmf will now get an early validation error instead of running out of memory after several hours of calculations. The max_sites_per_gmf limit can be raised beyond the default of 65,536 sites, at the user’s own responsibility.

We also added a limit of 2**32 events in event based calculations: this is a hard limit that cannot be raised. If your calculation produces more than 4 billion events, it will need to be be split into smaller calculations. Such calculations involving billions of ruptures would likely never work anyway, because it would eventually run out of memory.

We added a check for missing intensity_measure_types: this avoids cryptic errors in the middle of the computation of the ground motion fields.

We optimized the rupture sampling procedure for point sources (which includes multi point sources and area sources). The improvement can be quite significant, for instance the generation of ruptures for a large multipoint source for Colombia became 30x faster using 12x less memory.

We changed the way ruptures are stored internally: the code field in the ruptures dataset is now a unique checksum depending on the kind of rupture. Before it was an incremental number depending on the order of the Python module imports which was making debugging difficult.

The rupture CSV exporter has been enhanced, and now it exports the rupture surface boundaries as 3D multipolygons instead of 2D multipolygons.

We fixed a small bug in the rupture XML exporter, which was failing if the user did not specify the hazard sites.

We added the ability to generate hazard curves without storing the GMFs, simply by setting the flags

  hazard_curves_from_gmfs = true
  ground_motion_fields = false

This is useful when one is interested in the hazard curves generated by an event_based calculation but not in the ground motion fields themselves. Not storing the GMFs reduces the data transfer and the memory occupation.

In engine 3.5 we changed the gmf_data CSV exporter to export a file sitemodel.csv instead of the file sitemesh.csv. That change has been reverted because it was generating confusion. The right way to to export the site model information for the most recently completed calculation - which works for all calculators, not only for event based - is to use the command oq show sitecol > sitecol.csv

Importing GMFs from CSV has been enhanced and now it does not require anymore the field rlzi: previously, this was a required field, but it was assumed to contain always the value 0. On the other hand, now the GMF exporter to CSV does not export the field rlzi, because it is redundant: the association between events and realizations can be found in the events table and it is exported in the file sigma_epsilon.csv.

In the sigma_epsilon.csv file, we renamed the field eid to event_id in order to avoid confusion with the naming used in the gmf_data.csv file (event_id is the 64 bit event ID in the events table in the datastore, eid is the 32 bit index to the event ID record).

Event based risk#

There was a huge refactoring of all risk calculators. As a consequence the event_based_risk calculator has become simpler and faster than before (twice as fast in some cases).

In the ebrisk calculator it is now possible to aggregate by asset_id and therefore to produce individual loss curves and maps for each asset. Needless to mention, this is only viable for exposures of manageable size.

There was some work to make the losses_by_event exporter for the ebrisk calculator more similar to the ones for event_based_risk and for scenario_risk.

We fixed a bug in the agg_curves-rlzs and agg_curves-stats outputs in ebrisk: they were missing the units compared to the same outputs coming from the event_based_risk calculator. This was breaking the QGIS plugin.

We changed the agglosses exporter in scenario_risk calculations, by adding a column with the realization index.

The agg_curves exporter for event based risk was broken if the exposure was imported in the parent calculation and not in the child calculation.

We fixed a bug in the exporter of the aggregate loss curves coming from an ebrisk calculation: now the loss ratios are computed correctly even in presence of occupants. Before the exporter was writing incorrect loss ratios to the output file.


Graeme Weatherill (@g-weatherill) contributed a finite rupture option to the Germany-adjusted Cauzzi and Derras GMPEs. Moreover, he contributed the Tromans et al. (2019) adjustable GMPE, used for a nuclear power plant in the UK.

Chris van Houtte (@cvanhoutte) contributed the Van Houtte et al. (2018) Significant duration model for New Zealand.

Robin Gee (@rcgee) fixed a bug in the GMPE Sharma (2009): there was a key error if the intensity measure level specified in the job.ini included periods that required interpolation.

Marco Pagani (@mmpagani) discovered a bug in calc_hazard_curves which was failing with a cryptic AttributeError: 'NoneType' object has no attribute 'within_bbox' when used in parallel mode. It has been fixed.


The CSV importer for the exposure has been optimized. Before, for legacy reasons, the importer was converting the CSV records into node objects similar to the ones coming from the XML importer and then it was reusing the XML logic. Now we are doing the opposite: the XML importer is producing records and reusing the logic of the CSV importer. Thanks to this change for large CSV exposure the new importer is 4-5 times faster and uses over 10 times less memory than before.

Since a long time ago the engine has the ability to reduce the hazard site collection (which can be large, think of a fine grid) only to the locations where there are assets. Such feature has been optimized in this release, up to a spectacular extent in some cases: we measured a speedup from 2h to 0.1s for Canada.

We changed how zipped exposures are managed by the engine. In version 3.5 a zipped exposure was expected to contain an XML file with the same name of the archive, apart from the extension. Because of that the job.ini file had to contain a line exposure_file = <exposure_path>.xml while now it requires a line exposure_file = <exposure_path>.zip, which is clearer. The change was requested by the risk team in the context of the CRAVE project because it simplifies the unzipping of the exposure. Unzipping will overwrite files of the same name already present, but a warning will be printed and the original files will be not lost, but renamed with a .bak extension.

We added a consistency check between statistics for calculations leveraging the --hc option, because some users were making mistakes like trying to compute means in the child calculation without having them in the parent calculation. Now one gets a clear error message.

We fixed a bug in classical_damage from CSV with discrete fragility functions: for hazard intensity measure levels different from the fragility levels, the engine was giving incorrect results.

Vulnerability functions with the beta distribution must satisfy some consistency requirements if the coefficients of variation are nonzero. Unfortunately the consistency check were missing and it was possible to accept invalid functions raising and error in the middle of the computation. Now the error will be raised much early, at the time of the instantiating the vulnerability functions. See #4841 for more details.

Hyeuk Ryu (@dynaryu) discovered a bug in the agg_loss-curves outputs for the event_based_risk calculators, which has been fixed.

Finally there were some improvements to the multi_risk calculator in the context of the CRAVE project. In particular now the engine is able to manage the geometries of volcanic perils like lava, lahar and pyroclastic flow and it is also able to manage other binary perils without requiring the introduction of new intensity measure types.

General changes#

The CSV exporters have been enhanced: now there is an additional line before the header, starting with a # character, containing some metadata, like the date when the file the generated, the version of the engine that generated it, and some relevant parameters, like the investigation time in the case of the hazard outputs. In the future we may add even more metadata and extend the approach to other outputs.

Before release 3.3, the engine had the ability to associate site model parameters to hazard sites on a grid. This feature was sometimes buggy and removed, by recommending to the users the command oq prepare_site_model instead. oq prepare_site_model is able to produce a site_model.csv file with sites on the grid and it performs the associations explicitly, once and for all.

In this release, we restored the ability to perform the association directly in the engine. This is less efficient than using oq prepare_site_model, since the same associations will be recomputed during each run. It is still useful for people wanting to experiment with the grid spacing: they can run several calculations and when they are happy with the grid spacing, run oq prepare_site_model and fix the site model once and for all with the preferred grid spacing.

We fixed a performance regression in the ucerf_classical calculator, due to a change of logic in engine 3.5, which was trying to filter thousands of sources in the controller node instead than in the workers, thus becoming extra-slow.

We decided to change the realizations.csv output for scenario calculations, by replacing the branch_path field with the GSIM representation. This is more informative for the users and more convenient for the QGIS plugin too.


The job queue first introduced in engine-3.5 is now enabled by default. This means than only on job can run at a given time for a given engine instance.

The progress report has been improved: before in large classical calculations the progress started to be printed too late, even days after the start of the calculation.

We improved the oq abort command to remove submitted jobs too.

Deleting a calculation in the engine has always been tricky in the case of multiple users. In this release we fixed several issues and now an user can delete all of her calculations with the command oq reset. The engine will look inside the database and correctly remove the calculations of the user, including all the relevant .hdf5 files.

We improved the oq plot command by adding several new kinds of plot. They are still for internal use only (i.e. introspection and debugging).

We extended the command oq db to run generic queries for the openquake user. Other users can only run SELECT queries.

There was a bug in oq webui start not supplying the --noreload argument that has been fixed (the reload functionality of the Django development server interferes with SIGCHLD and causes zombies).

We fixed another bug with the --hc functionality in a multi-user situation, due to the fact that the engine was searching the the datastore of the parent calculation in the wrong directory.

There is now a better error message if the shared directory is not mounted.

Source models can now be serialized in TOML format, which is useful for debugging purposes.

Libraries and Python 3.7#

In this releases we updated some of our libraries (numpy from version 1.14 to 1.16 and scipy from version 1.0.1 to 1.3.0) to make it possible to use the engine with Python 3.7. We actually have a cluster using Python 3.7 in production.

In the future we may distribute installers for Windows and macOS based on Python 3.7, but for the moment Python 3.6 is still the only officially supported version and we not plan to abandon Python 3.6 any time soon.

We raised the minimum version for h5py from 2.8.0 to 2.9.0, fixed some compatibility issue with Django 2.1 and 2.2 and fixed several Python 3.7 deprecation warnings. Finally we removed the external dependency from the mock module since it is included in the standard library since Python 3.3.


For years the engine has been able to import ground motion fields and hazard curves in CSV format and NRML format, with the NRML format deprecated. Now finally the NRML importers have been removed.

There was an old deprecated GMF exporter in NRML format for scenario calculations. It has been finally deprecated. You should use the CSV exporter thas has been available for years instead.

We deprecated the XML disaggregation exporters in favor of the CSV exporters.

We removed the long time deprecated agg_loss_table exporter since now all the needed information is in the losses_by_event exporter.

We switched officially the testing framework from nosetests to pytest.