Beispiel #1
0
def save_gmf(gmfcoll_id, gmf_dict, sites):
    """
    Helper method to save computed GMF data to the database.

    :param int gmfcoll_id:
        the id of a :class:`openquake.engine.db.models.Gmf` record
    :param dict gmf_dict:
        The GMF results during the calculation
    :param sites:
        An :class:`openquake.engine.models.SiteCollection`
        object
    """
    inserter = writer.CacheInserter(models.GmfData, 100)
    # NB: GmfData may contain large arrays and the cache may become large

    for imt, gmfs_ in gmf_dict.iteritems():
        # ``gmfs`` comes in as a numpy.matrix
        # we want it is an array; it handles subscripting
        # in the way that we want
        gmfarray = numpy.array(gmfs_)

        sa_period = None
        sa_damping = None
        if isinstance(imt, openquake.hazardlib.imt.SA):
            sa_period = imt.period
            sa_damping = imt.damping
        imt_name = imt.__class__.__name__

        for i, site in enumerate(sites):
            inserter.add(models.GmfData(
                gmf_id=gmfcoll_id,
                ses_id=None,
                imt=imt_name,
                sa_period=sa_period,
                sa_damping=sa_damping,
                site_id=site.id,
                rupture_ids=None,
                gmvs=gmfarray[i].tolist()))

    inserter.flush()
Beispiel #2
0
 def post_execute(self, result=None):
     """
     Saving the GMFs in the database
     """
     gmf_id = self.gmf.id
     inserter = writer.CacheInserter(models.GmfData, max_cache_size=1000)
     gsim = self.oqparam.gsim
     for imt in self.imts:
         gmfs = numpy.array([
             self.acc[tag][gsim][str(imt)] for tag in self.tags
         ]).transpose()
         for site_id, gmvs in zip(self.sites.sids, gmfs):
             inserter.add(
                 models.GmfData(gmf_id=gmf_id,
                                task_no=0,
                                imt=imt[0],
                                sa_period=imt[1],
                                sa_damping=imt[2],
                                site_id=site_id,
                                rupture_ids=self.rupids,
                                gmvs=list(gmvs)))
     inserter.flush()
Beispiel #3
0
def create_db_ruptures(rupture, ses_coll, tags, seed):
    """
    Insert the SESRuptures associated to the given rupture and
    SESCollection.

    :param rupture: hazardlib rupture
    :param ses_coll: SESCollection instance
    :param tags: tags of the ruptures to insert
    :seed: a random seed
    :returns: the IDs of the inserted ProbabilisticRupture and SESRuptures
    """
    prob_rup = models.ProbabilisticRupture.create(rupture, ses_coll)
    inserter = writer.CacheInserter(models.SESRupture, max_cache_size=100000)
    rnd = random.Random()
    rnd.seed(seed)
    seeds = []
    sesrupts = []
    for tag in tags:
        s = rnd.randint(0, models.MAX_SINT_32)
        seeds.append(s)
        sesrupts.append(
            models.SESRupture(ses_id=1, rupture=prob_rup, tag=tag, seed=s))
    return prob_rup.id, inserter.saveall(sesrupts), seeds
Beispiel #4
0
    def post_process(self):
        """
          Compute aggregate loss curves and event loss tables
        """
        with EnginePerformanceMonitor('post processing', self.job.id):

            time_span, tses = self.hazard_times()
            for loss_type, event_loss_table in self.event_loss_tables.items():
                for hazard_output in self.rc.hazard_outputs():

                    event_loss = models.EventLoss.objects.create(
                        output=models.Output.objects.create_output(
                            self.job, "Event Loss Table. type=%s, hazard=%s" %
                            (loss_type, hazard_output.id), "event_loss"),
                        loss_type=loss_type,
                        hazard_output=hazard_output)
                    inserter = writer.CacheInserter(models.EventLossData, 9999)

                    rupture_ids = models.SESRupture.objects.filter(
                        ses__ses_collection__lt_realization=hazard_output.
                        output_container.lt_realization).values_list('id',
                                                                     flat=True)

                    for rupture_id in rupture_ids:
                        if rupture_id in event_loss_table:
                            inserter.add(
                                models.EventLossData(
                                    event_loss_id=event_loss.id,
                                    rupture_id=rupture_id,
                                    aggregate_loss=event_loss_table[rupture_id]
                                ))
                    inserter.flush()

                    aggregate_losses = [
                        event_loss_table[rupture_id]
                        for rupture_id in rupture_ids
                        if rupture_id in event_loss_table
                    ]

                    if aggregate_losses:
                        aggregate_loss_losses, aggregate_loss_poes = (
                            scientific.event_based(
                                aggregate_losses,
                                tses=tses,
                                time_span=time_span,
                                curve_resolution=self.rc.loss_curve_resolution)
                        )

                        models.AggregateLossCurveData.objects.create(
                            loss_curve=models.LossCurve.objects.create(
                                aggregate=True,
                                insured=False,
                                hazard_output=hazard_output,
                                loss_type=loss_type,
                                output=models.Output.objects.create_output(
                                    self.job, "aggregate loss curves. "
                                    "loss_type=%s hazard=%s" %
                                    (loss_type, hazard_output),
                                    "agg_loss_curve")),
                            losses=aggregate_loss_losses,
                            poes=aggregate_loss_poes,
                            average_loss=scientific.average_loss(
                                aggregate_loss_losses, aggregate_loss_poes),
                            stddev_loss=numpy.std(aggregate_losses))
Beispiel #5
0
    def do_aggregate_post_proc(self):
        """
        Grab hazard data for all realizations and sites from the database and
        compute mean and/or quantile aggregates (depending on which options are
        enabled in the calculation).

        Post-processing results will be stored directly into the database.
        """
        num_rlzs = models.LtRealization.objects.filter(
            hazard_calculation=self.hc).count()

        num_site_blocks_per_incr = int(CURVE_CACHE_SIZE) / int(num_rlzs)
        if num_site_blocks_per_incr == 0:
            # This means we have `num_rlzs` >= `CURVE_CACHE_SIZE`.
            # The minimum number of sites should be 1.
            num_site_blocks_per_incr = 1
        slice_incr = num_site_blocks_per_incr * num_rlzs  # unit: num records

        if self.hc.mean_hazard_curves:
            # create a new `HazardCurve` 'container' record for mean
            # curves (virtual container for multiple imts)
            models.HazardCurve.objects.create(
                output=models.Output.objects.create_output(
                    self.job, "mean-curves-multi-imt", "hazard_curve_multi"),
                statistics="mean",
                imt=None,
                investigation_time=self.hc.investigation_time)

        if self.hc.quantile_hazard_curves:
            for quantile in self.hc.quantile_hazard_curves:
                # create a new `HazardCurve` 'container' record for quantile
                # curves (virtual container for multiple imts)
                models.HazardCurve.objects.create(
                    output=models.Output.objects.create_output(
                        self.job, 'quantile(%s)-curves' % quantile,
                        "hazard_curve_multi"),
                    statistics="quantile",
                    imt=None,
                    quantile=quantile,
                    investigation_time=self.hc.investigation_time)

        for imt, imls in self.hc.intensity_measure_types_and_levels.items():
            im_type, sa_period, sa_damping = models.parse_imt(imt)

            # prepare `output` and `hazard_curve` containers in the DB:
            container_ids = dict()
            if self.hc.mean_hazard_curves:
                mean_output = models.Output.objects.create_output(
                    job=self.job,
                    display_name='mean-curves-%s' % imt,
                    output_type='hazard_curve')
                mean_hc = models.HazardCurve.objects.create(
                    output=mean_output,
                    investigation_time=self.hc.investigation_time,
                    imt=im_type,
                    imls=imls,
                    sa_period=sa_period,
                    sa_damping=sa_damping,
                    statistics='mean')
                container_ids['mean'] = mean_hc.id

            if self.hc.quantile_hazard_curves:
                for quantile in self.hc.quantile_hazard_curves:
                    q_output = models.Output.objects.create_output(
                        job=self.job,
                        display_name=('quantile(%s)-curves-%s' %
                                      (quantile, imt)),
                        output_type='hazard_curve')
                    q_hc = models.HazardCurve.objects.create(
                        output=q_output,
                        investigation_time=self.hc.investigation_time,
                        imt=im_type,
                        imls=imls,
                        sa_period=sa_period,
                        sa_damping=sa_damping,
                        statistics='quantile',
                        quantile=quantile)
                    container_ids['q%s' % quantile] = q_hc.id

            all_curves_for_imt = models.order_by_location(
                models.HazardCurveData.objects.all_curves_for_imt(
                    self.job.id, im_type, sa_period, sa_damping))

            with transaction.commit_on_success(using='reslt_writer'):
                inserter = writer.CacheInserter(models.HazardCurveData,
                                                CURVE_CACHE_SIZE)

                for chunk in models.queryset_iter(all_curves_for_imt,
                                                  slice_incr):
                    # slice each chunk by `num_rlzs` into `site_chunk`
                    # and compute the aggregate
                    for site_chunk in block_splitter(chunk, num_rlzs):
                        site = site_chunk[0].location
                        curves_poes = [x.poes for x in site_chunk]
                        curves_weights = [x.weight for x in site_chunk]

                        # do means and quantiles
                        # quantiles first:
                        if self.hc.quantile_hazard_curves:
                            for quantile in self.hc.quantile_hazard_curves:
                                if self.hc.number_of_logic_tree_samples == 0:
                                    # explicitly weighted quantiles
                                    q_curve = weighted_quantile_curve(
                                        curves_poes, curves_weights, quantile)
                                else:
                                    # implicitly weighted quantiles
                                    q_curve = quantile_curve(
                                        curves_poes, quantile)
                                inserter.add(
                                    models.HazardCurveData(
                                        hazard_curve_id=(
                                            container_ids['q%s' % quantile]),
                                        poes=q_curve.tolist(),
                                        location=site.wkt))

                        # then means
                        if self.hc.mean_hazard_curves:
                            m_curve = mean_curve(curves_poes,
                                                 weights=curves_weights)
                            inserter.add(
                                models.HazardCurveData(
                                    hazard_curve_id=container_ids['mean'],
                                    poes=m_curve.tolist(),
                                    location=site.wkt))
                inserter.flush()
Beispiel #6
0
    post_processing as cls_post_proc)
from openquake.engine.calculators.hazard.event_based import post_processing
from openquake.engine.db import models
from openquake.engine.input import logictree
from openquake.engine.utils import tasks
from openquake.engine.performance import EnginePerformanceMonitor


#: Always 1 for the computation of ground motion fields in the event-based
#: hazard calculator.
DEFAULT_GMF_REALIZATIONS = 1

BLOCK_SIZE = 5000  # TODO: put this in openquake.cfg

# NB: beware of large caches
inserter = writer.CacheInserter(models.GmfData, 1000)


# Disabling pylint for 'Too many local variables'
# pylint: disable=R0914
@tasks.oqtask
def compute_ses(job_id, src_ids, ses, src_seeds, ltp):
    """
    Celery task for the stochastic event set calculator.

    Samples logic trees and calls the stochastic event set calculator.

    Once stochastic event sets are calculated, results will be saved to the
    database. See :class:`openquake.engine.db.models.SESCollection`.

    Optionally (specified in the job configuration using the
Beispiel #7
0
def event_based(workflow, getter, outputdict, params, monitor):
    """
    Celery task for the event based risk calculator.

    :param job_id: the id of the current
        :class:`openquake.engine.db.models.OqJob`
    :param workflow:
      A :class:`openquake.risklib.workflows.Workflow` instance
    :param getter:
      A :class:`HazardGetter` instance
    :param outputdict:
      An instance of :class:`..writers.OutputDict` containing
      output container instances (e.g. a LossCurve)
    :param params:
      An instance of :class:`..base.CalcParams` used to compute
      derived outputs
    :param monitor:
      A monitor instance
    :returns:
      A dictionary {loss_type: event_loss_table}
    """
    # NB: event_loss_table is a dictionary (loss_type, out_id) -> loss,
    # out_id can be None, and it that case it stores the statistics
    event_loss_table = {}

    # num_loss is a dictionary asset_ref -> array([not_zeros, total])
    num_losses = collections.defaultdict(lambda: numpy.zeros(2, dtype=int))

    specific_assets = set(params.specific_assets)
    statistics = params.statistics  # enabled by default
    # keep in memory the loss_matrix only when specific_assets are set
    workflow.return_loss_matrix = bool(specific_assets)

    # the insert here will work only if specific_assets is set
    inserter = writer.CacheInserter(
        models.EventLossAsset, max_cache_size=10000)
    for loss_type in workflow.loss_types:
        with monitor('computing individual risk', autoflush=True):
            outputs = workflow.compute_all_outputs(getter, loss_type)
            if statistics:
                outputs = list(outputs)  # expand the generator
                # this is needed, otherwise the call to workflow.statistics
                # below will find an empty iterable; notice that by disabling
                # the statistics we can save memory by keeping only one
                # hazard realization at the time
        for out in outputs:
            event_loss_table[loss_type, out.hid] = out.event_loss_table
            disagg_outputs = None  # changed if params.sites_disagg is set
            if specific_assets:
                loss_matrix, assets = _filter_loss_matrix_assets(
                    out.loss_matrix, out.assets, specific_assets)
                if len(assets):
                    # compute the loss per rupture per asset
                    event_loss = models.EventLoss.objects.get(
                        output__oq_job=monitor.job_id,
                        output__output_type='event_loss_asset',
                        loss_type=loss_type, hazard_output=out.hid)
                    # losses is E x n matrix, where E is the number of ruptures
                    # and n the number of assets in the specific_assets set
                    losses = (loss_matrix.transpose() *
                              numpy_map(lambda a: a.value(loss_type), assets))
                    # save an EventLossAsset record for each specific asset
                    for rup_id, losses_per_rup in zip(
                            getter.rupture_ids, losses):
                        for asset, loss_per_rup in zip(assets, losses_per_rup):
                            if loss_per_rup:  # save only non-zero losses
                                ela = models.EventLossAsset(
                                    event_loss=event_loss, rupture_id=rup_id,
                                    asset=asset, loss=loss_per_rup)
                                inserter.add(ela)
                            # update the counters: not_zeros is incremented
                            # only if loss_per_rup is nonzero, total always
                            num_losses[asset.asset_ref] += numpy.array(
                                [bool(loss_per_rup), 1])
                    if params.sites_disagg:
                        with monitor('disaggregating results', autoflush=True):
                            ruptures = [models.SESRupture.objects.get(pk=rid)
                                        for rid in getter.rupture_ids]
                            disagg_outputs = disaggregate(
                                out, [r.rupture for r in ruptures], params)

            with monitor('saving individual risk', autoflush=True):
                save_individual_outputs(
                    outputdict.with_args(hazard_output_id=out.hid,
                                         loss_type=loss_type),
                    out, disagg_outputs, params)

        if statistics and len(outputs) > 1:
            stats = workflow.statistics(
                outputs, params.quantile_loss_curves)

            with monitor('saving risk statistics', autoflush=True):
                save_statistical_output(
                    outputdict.with_args(
                        hazard_output_id=None, loss_type=loss_type),
                    stats, params)
            event_loss_table[loss_type, None] = stats.event_loss_table

    inserter.flush()

    # log info about the rows entered in the event_loss_asset table
    for asset_ref in sorted(num_losses):
        not_zeros, total = num_losses[asset_ref]
        logs.LOG.info('Saved %d/%d losses for asset %s',
                      not_zeros, total, asset_ref)
    return event_loss_table
Beispiel #8
0
    def post_process(self):
        """
          Compute aggregate loss curves and event loss tables
        """
        oq = self.oqparam
        tses = oq.investigation_time * oq.ses_per_logic_tree_path
        with self.monitor('post processing', autoflush=True):
            inserter = writer.CacheInserter(models.EventLossData,
                                            max_cache_size=10000)
            for (loss_type, out_id), event_loss_table in self.acc.items():
                if out_id:  # values for individual realizations
                    hazard_output = models.Output.objects.get(pk=out_id)
                    event_loss = models.EventLoss.objects.get(
                        output__oq_job=self.job,
                        output__output_type='event_loss',
                        loss_type=loss_type, hazard_output=hazard_output)
                    if isinstance(hazard_output.output_container,
                                  models.SESCollection):
                        ses_coll = hazard_output.output_container
                        rupture_ids = ses_coll.get_ruptures().values_list(
                            'id', flat=True)
                    else:  # extract the SES collection from the Gmf
                        rupture_ids = models.SESRupture.objects.filter(
                            rupture__ses_collection__trt_model__lt_model=
                            hazard_output.output_container.
                            lt_realization.lt_model).values_list(
                            'id', flat=True)
                    for rupture_id in rupture_ids:
                        if rupture_id in event_loss_table:
                            inserter.add(
                                models.EventLossData(
                                    event_loss_id=event_loss.id,
                                    rupture_id=rupture_id,
                                    aggregate_loss=event_loss_table[
                                        rupture_id]))
                    inserter.flush()

                    aggregate_losses = [
                        event_loss_table[rupture_id]
                        for rupture_id in rupture_ids
                        if rupture_id in event_loss_table]

                    if aggregate_losses:
                        aggregate_loss = scientific.event_based(
                            aggregate_losses, tses=tses,
                            time_span=oq.investigation_time,
                            curve_resolution=oq.loss_curve_resolution)

                        models.AggregateLossCurveData.objects.create(
                            loss_curve=models.LossCurve.objects.create(
                                aggregate=True, insured=False,
                                hazard_output=hazard_output,
                                loss_type=loss_type,
                                output=models.Output.objects.create_output(
                                    self.job,
                                    "aggregate loss curves. "
                                    "loss_type=%s hazard=%s" % (
                                        loss_type, hazard_output),
                                    "agg_loss_curve")),
                            losses=aggregate_loss[0],
                            poes=aggregate_loss[1],
                            average_loss=scientific.average_loss(
                                aggregate_loss),
                            stddev_loss=numpy.std(aggregate_losses))
Beispiel #9
0
    def do_aggregate_post_proc(self):
        """
        Grab hazard data for all realizations and sites from the database and
        compute mean and/or quantile aggregates (depending on which options are
        enabled in the calculation).

        Post-processing results will be stored directly into the database.
        """
        num_rlzs = len(self._realizations)
        if not num_rlzs:
            logs.LOG.warn('No realizations for hazard_calculation_id=%d',
                          self.job.id)
            return
        elif num_rlzs == 1 and self.quantile_hazard_curves:
            logs.LOG.warn(
                'There is only one realization, the configuration parameter '
                'quantile_hazard_curves should not be set')
            return

        weights = (None if self.oqparam.number_of_logic_tree_samples else
                   [rlz.weight for rlz in self._realizations])

        if self.oqparam.mean_hazard_curves:
            # create a new `HazardCurve` 'container' record for mean
            # curves (virtual container for multiple imts)
            models.HazardCurve.objects.create(
                output=models.Output.objects.create_output(
                    self.job, "mean-curves-multi-imt", "hazard_curve_multi"),
                statistics="mean",
                imt=None,
                investigation_time=self.oqparam.investigation_time)

        for quantile in self.quantile_hazard_curves:
            # create a new `HazardCurve` 'container' record for quantile
            # curves (virtual container for multiple imts)
            models.HazardCurve.objects.create(
                output=models.Output.objects.create_output(
                    self.job, 'quantile(%s)-curves' % quantile,
                    "hazard_curve_multi"),
                statistics="quantile",
                imt=None,
                quantile=quantile,
                investigation_time=self.oqparam.investigation_time)

        for imt, imls in self.oqparam.imtls.items():
            im_type, sa_period, sa_damping = from_string(imt)

            # prepare `output` and `hazard_curve` containers in the DB:
            container_ids = dict()
            if self.oqparam.mean_hazard_curves:
                mean_output = self.job.get_or_create_output(
                    display_name='Mean Hazard Curves %s' % imt,
                    output_type='hazard_curve')
                mean_hc = models.HazardCurve.objects.create(
                    output=mean_output,
                    investigation_time=self.oqparam.investigation_time,
                    imt=im_type,
                    imls=imls,
                    sa_period=sa_period,
                    sa_damping=sa_damping,
                    statistics='mean')
                self._hazard_curves.append(mean_hc)
                container_ids['mean'] = mean_hc.id

            for quantile in self.quantile_hazard_curves:
                q_output = self.job.get_or_create_output(
                    display_name=('%s quantile Hazard Curves %s' %
                                  (quantile, imt)),
                    output_type='hazard_curve')
                q_hc = models.HazardCurve.objects.create(
                    output=q_output,
                    investigation_time=self.oqparam.investigation_time,
                    imt=im_type,
                    imls=imls,
                    sa_period=sa_period,
                    sa_damping=sa_damping,
                    statistics='quantile',
                    quantile=quantile)
                self._hazard_curves.append(q_hc)
                container_ids['q%s' % quantile] = q_hc.id

            # num_rlzs * num_sites * num_levels
            # NB: different IMTs can have different num_levels
            all_curves_for_imt = numpy.array(self.curves_by_imt[imt])
            del self.curves_by_imt[imt]  # save memory

            inserter = writer.CacheInserter(models.HazardCurveData,
                                            max_cache_size=10000)

            # curve_poes below is an array num_rlzs * num_levels
            for i, site in enumerate(self.site_collection):
                wkt = site.location.wkt2d
                curve_poes = numpy.array(
                    [c_by_rlz[i] for c_by_rlz in all_curves_for_imt])

                # calc quantiles first
                for quantile in self.quantile_hazard_curves:
                    q_curve = scientific.quantile_curve(
                        curve_poes, quantile, weights)
                    inserter.add(
                        models.HazardCurveData(
                            hazard_curve_id=(container_ids['q%s' % quantile]),
                            poes=q_curve.tolist(),
                            location=wkt))

                # then means
                if self.mean_hazard_curves:
                    m_curve = scientific.mean_curve(curve_poes, weights)
                    inserter.add(
                        models.HazardCurveData(
                            hazard_curve_id=container_ids['mean'],
                            poes=m_curve.tolist(),
                            location=wkt))
            inserter.flush()
Beispiel #10
0
import numpy

from openquake.hazardlib.imt import from_string
from openquake.hazardlib.geo.utils import get_spherical_bounding_box
from openquake.hazardlib.geo.utils import get_longitudinal_extent
from openquake.hazardlib.geo.geodetic import npoints_between

from openquake.commonlib.calculators.calc import gen_ruptures

from openquake.engine import writer
from openquake.engine.calculators import calculators
from openquake.engine.calculators.hazard import general
from openquake.engine.db import models
from openquake.engine.utils import tasks

inserter = writer.CacheInserter(models.SourceInfo, 100)


class BoundingBox(object):
    """
    A class to store the bounding box in distances, longitudes and magnitudes,
    given a source model and a site. This is used for disaggregation
    calculations. The goal is to determine the minimum and maximum
    distances of the ruptures generated from the model from the site;
    moreover the maximum and minimum longitudes and magnitudes are stored, by
    taking in account the international date line.
    """
    def __init__(self, lt_model_id, site_id):
        self.lt_model_id = lt_model_id
        self.site_id = site_id
        self.min_dist = self.max_dist = None