def assoc_assets_sites(self, sitecol): """ :param sitecol: a sequence of sites :returns: a pair (filtered sites, asset collection) The new site collection is different from the original one if some assets were discarded or if there were missing assets for some sites. """ asset_hazard_distance = self.oqparam.asset_hazard_distance siteobjects = geo.utils.GeographicObjects( Site(sid, lon, lat) for sid, lon, lat in zip(sitecol.sids, sitecol.lons, sitecol.lats)) assets_by_sid = general.AccumDict() for assets in self.assetcol.assets_by_site(): if len(assets): lon, lat = assets[0].location site, distance = siteobjects.get_closest(lon, lat) if distance <= asset_hazard_distance: # keep the assets, otherwise discard them assets_by_sid += {site.sid: list(assets)} if not assets_by_sid: raise AssetSiteAssociationError( 'Could not associate any site to any assets within the ' 'asset_hazard_distance of %s km' % asset_hazard_distance) mask = numpy.array([sid in assets_by_sid for sid in sitecol.sids]) assets_by_site = [assets_by_sid.get(sid, []) for sid in sitecol.sids] return sitecol.filter(mask), asset.AssetCollection( assets_by_site, self.exposure.tagnames, self.exposure.cost_calculator, self.oqparam.time_event, occupancy_periods=hdf5.array_of_vstr( sorted(self.exposure.occupancy_periods)))
def get_sitecol_assetcol(oqparam, haz_sitecol=None, cost_types=()): """ :param oqparam: calculation parameters :param haz_sitecol: the hazard site collection :param cost_types: the expected cost types :returns: (site collection, asset collection, discarded) """ global exposure asset_hazard_distance = oqparam.asset_hazard_distance['default'] if exposure is None: # haz_sitecol not extracted from the exposure exposure = get_exposure(oqparam) if haz_sitecol is None: haz_sitecol = get_site_collection(oqparam) if oqparam.region_grid_spacing: haz_distance = oqparam.region_grid_spacing * 1.414 if haz_distance != asset_hazard_distance: logging.info('Using asset_hazard_distance=%d km instead of %d km', haz_distance, asset_hazard_distance) else: haz_distance = asset_hazard_distance if haz_sitecol.mesh != exposure.mesh: # associate the assets to the hazard sites sitecol, assets_by, discarded = geo.utils.assoc( exposure.assets_by_site, haz_sitecol, haz_distance, 'filter', exposure.asset_refs) assets_by_site = [[] for _ in sitecol.complete.sids] num_assets = 0 for sid, assets in zip(sitecol.sids, assets_by): assets_by_site[sid] = assets num_assets += len(assets) logging.info('Associated %d assets to %d sites', num_assets, len(sitecol)) else: # asset sites and hazard sites are the same sitecol = haz_sitecol assets_by_site = exposure.assets_by_site discarded = [] logging.info('Read %d sites and %d assets from the exposure', len(sitecol), sum(len(a) for a in assets_by_site)) assetcol = asset.AssetCollection(exposure, assets_by_site, oqparam.time_event) if assetcol.occupancy_periods: missing = set(cost_types) - set(exposure.cost_types['name']) - set( ['occupants']) else: missing = set(cost_types) - set(exposure.cost_types['name']) if missing and not oqparam.calculation_mode.endswith('damage'): raise InvalidFile('The exposure %s is missing %s' % (oqparam.inputs['exposure'], missing)) if (not oqparam.hazard_calculation_id and 'gmfs' not in oqparam.inputs and 'hazard_curves' not in oqparam.inputs and sitecol is not sitecol.complete): # for predefined hazard you cannot reduce the site collection; instead # you can in other cases, typically with a grid which is mostly empty # (i.e. there are many hazard sites with no assets) assetcol.reduce_also(sitecol) return sitecol, assetcol, discarded
def get_sitecol_assetcol(oqparam, haz_sitecol): """ :param oqparam: calculation parameters :param haz_sitecol: the hazard site collection :returns: (site collection, asset collection) instances """ global exposure if exposure is None: # haz_sitecol not extracted from the exposure exposure = get_exposure(oqparam) if oqparam.region_grid_spacing and not oqparam.region: # extract the hazard grid from the exposure exposure.mesh = exposure.mesh.get_convex_hull().dilate( oqparam.region_grid_spacing).discretize( oqparam.region_grid_spacing) haz_sitecol = get_site_collection(oqparam) haz_distance = oqparam.region_grid_spacing if haz_distance != oqparam.asset_hazard_distance: logging.info('Using asset_hazard_distance=%d km instead of %d km', haz_distance, oqparam.asset_hazard_distance) else: haz_distance = oqparam.asset_hazard_distance if haz_sitecol.mesh != exposure.mesh: # associate the assets to the hazard sites tot_assets = sum(len(assets) for assets in exposure.assets_by_site) mode = 'strict' if oqparam.region_grid_spacing else 'filter' sitecol, assets_by = geo.utils.assoc(exposure.assets_by_site, haz_sitecol, haz_distance, mode) assets_by_site = [[] for _ in sitecol.complete.sids] num_assets = 0 for sid, assets in zip(sitecol.sids, assets_by): assets_by_site[sid] = assets num_assets += len(assets) logging.info('Associated %d assets to %d sites', num_assets, len(sitecol)) if num_assets < tot_assets: logging.warn( 'Discarded %d assets outside the ' 'asset_hazard_distance of %d km', tot_assets - num_assets, haz_distance) else: # asset sites and hazard sites are the same sitecol = haz_sitecol assets_by_site = exposure.assets_by_site asset_refs = [ exposure.asset_refs[asset.ordinal] for assets in assets_by_site for asset in assets ] assetcol = asset.AssetCollection(asset_refs, assets_by_site, exposure.tagcol, exposure.cost_calculator, oqparam.time_event, exposure.occupancy_periods) return sitecol, assetcol
def read_exposure(self, haz_sitecol=None): """ Read the exposure, the riskmodel and update the attributes .exposure, .sitecol, .assetcol """ logging.info('Reading the exposure') with self.monitor('reading exposure', autoflush=True): self.exposure = readinput.get_exposure(self.oqparam) mesh, assets_by_site = (readinput.get_mesh_assets_by_site( self.oqparam, self.exposure)) if haz_sitecol: tot_assets = sum(len(assets) for assets in assets_by_site) all_sids = haz_sitecol.complete.sids sids = set(haz_sitecol.sids) # associate the assets to the hazard sites asset_hazard_distance = self.oqparam.asset_hazard_distance siteobjects = geo.utils.GeographicObjects( Site(sid, lon, lat) for sid, lon, lat in zip( haz_sitecol.sids, haz_sitecol.lons, haz_sitecol.lats)) assets_by_sid = general.AccumDict(accum=[]) for assets in assets_by_site: if len(assets): lon, lat = assets[0].location site, distance = siteobjects.get_closest(lon, lat) if site.sid in sids and distance <= asset_hazard_distance: # keep the assets, otherwise discard them assets_by_sid += {site.sid: list(assets)} if not assets_by_sid: raise AssetSiteAssociationError( 'Could not associate any site to any assets within the ' 'asset_hazard_distance of %s km' % asset_hazard_distance) mask = numpy.array([sid in assets_by_sid for sid in all_sids]) assets_by_site = [assets_by_sid[sid] for sid in all_sids] num_assets = sum(len(assets) for assets in assets_by_site) logging.info('Associated %d/%d assets to the hazard sites', num_assets, tot_assets) self.sitecol = haz_sitecol.complete.filter(mask) else: # use the exposure sites as hazard sites self.sitecol = readinput.get_site_collection(self.oqparam, mesh) self.assetcol = asset.AssetCollection( self.exposure.asset_refs, assets_by_site, self.exposure.tagcol, self.exposure.cost_calculator, self.oqparam.time_event, occupancy_periods=hdf5.array_of_vstr( sorted(self.exposure.occupancy_periods))) logging.info('Considering %d assets on %d sites', len(self.assetcol), len(self.sitecol))
def get_sitecol_assetcol(oqparam, exposure): """ :param oqparam: an :class:`openquake.commonlib.oqvalidation.OqParam` instance :returns: the site collection and the asset collection """ assets_by_loc = groupby(exposure.assets, key=lambda a: a.location) lons, lats = zip(*sorted(assets_by_loc)) mesh = geo.Mesh(numpy.array(lons), numpy.array(lats)) sitecol = get_site_collection(oqparam, mesh) assets_by_site = [] for lonlat in zip(sitecol.lons, sitecol.lats): assets = assets_by_loc[lonlat] assets_by_site.append(sorted(assets, key=operator.attrgetter('idx'))) assetcol = asset.AssetCollection( assets_by_site, exposure.assets_by_tag, exposure.cost_calculator, oqparam.time_event, time_events=hdf5.array_of_vstr( sorted(exposure.time_events))) return sitecol, assetcol
def get_sitecol_assetcol(oqparam, haz_sitecol=None, cost_types=()): """ :param oqparam: calculation parameters :param haz_sitecol: the hazard site collection :param cost_types: the expected cost types :returns: (site collection, asset collection) instances """ global exposure if exposure is None: # haz_sitecol not extracted from the exposure exposure = get_exposure(oqparam) if haz_sitecol is None: haz_sitecol = get_site_collection(oqparam) missing = set(cost_types) - set(exposure.cost_types['name']) - set( ['occupants']) # TODO: remove occupants and fragility special cases if missing and not oqparam.calculation_mode.endswith('damage'): expo = oqparam.inputs.get('exposure', '') raise InvalidFile( 'Expected cost types %s but the exposure %r contains %s' % (cost_types, expo, exposure.cost_types['name'])) if oqparam.region_grid_spacing and not oqparam.region: # extract the hazard grid from the exposure poly = exposure.mesh.get_convex_hull() mesh = poly.dilate(oqparam.region_grid_spacing).discretize( oqparam.region_grid_spacing) if len(mesh) > len(haz_sitecol): raise LargeExposureGrid(mesh, haz_sitecol.mesh, oqparam.region_grid_spacing) haz_sitecol = get_site_collection(oqparam, mesh) # redefine haz_distance = oqparam.region_grid_spacing if haz_distance != oqparam.asset_hazard_distance: logging.info('Using asset_hazard_distance=%d km instead of %d km', haz_distance, oqparam.asset_hazard_distance) else: haz_distance = oqparam.asset_hazard_distance if haz_sitecol.mesh != exposure.mesh: # associate the assets to the hazard sites tot_assets = sum(len(assets) for assets in exposure.assets_by_site) mode = 'strict' if oqparam.region_grid_spacing else 'filter' sitecol, assets_by = geo.utils.assoc(exposure.assets_by_site, haz_sitecol, haz_distance, mode) assets_by_site = [[] for _ in sitecol.complete.sids] num_assets = 0 for sid, assets in zip(sitecol.sids, assets_by): assets_by_site[sid] = assets num_assets += len(assets) logging.info('Associated %d assets to %d sites', num_assets, len(sitecol)) if num_assets < tot_assets: logging.warn( 'Discarded %d assets outside the ' 'asset_hazard_distance of %d km', tot_assets - num_assets, haz_distance) else: # asset sites and hazard sites are the same sitecol = haz_sitecol assets_by_site = exposure.assets_by_site asset_refs = numpy.array([ exposure.asset_refs[asset.ordinal] for assets in assets_by_site for asset in assets ]) assetcol = asset.AssetCollection(asset_refs, assets_by_site, exposure.tagcol, exposure.cost_calculator, oqparam.time_event, exposure.occupancy_periods) return sitecol, assetcol
def get_sitecol_assetcol(oqparam, haz_sitecol=None, cost_types=()): """ :param oqparam: calculation parameters :param haz_sitecol: the hazard site collection :param cost_types: the expected cost types :returns: (site collection, asset collection) instances """ global exposure if exposure is None: # haz_sitecol not extracted from the exposure exposure = get_exposure(oqparam) if haz_sitecol is None: haz_sitecol = get_site_collection(oqparam) missing = set(cost_types) - set(exposure.cost_types['name']) - set( ['occupants']) # TODO: remove occupants and fragility special cases if missing and not oqparam.calculation_mode.endswith('damage'): expo = oqparam.inputs.get('exposure', '') raise InvalidFile( 'Expected cost types %s but the exposure %r contains %s' % (cost_types, expo, exposure.cost_types['name'])) if oqparam.region_grid_spacing: haz_distance = oqparam.region_grid_spacing if haz_distance != oqparam.asset_hazard_distance: logging.info('Using asset_hazard_distance=%d km instead of %d km', haz_distance, oqparam.asset_hazard_distance) else: haz_distance = oqparam.asset_hazard_distance if haz_sitecol.mesh != exposure.mesh: # associate the assets to the hazard sites tot_assets = sum(len(assets) for assets in exposure.assets_by_site) mode = 'filter' if oqparam.region_grid_spacing else 'warn' sitecol, assets_by, discarded = geo.utils.assoc( exposure.assets_by_site, haz_sitecol, haz_distance, mode) if oqparam.region_grid_spacing: # it is normal to discard sites discarded = [] assets_by_site = [[] for _ in sitecol.complete.sids] num_assets = 0 for sid, assets in zip(sitecol.sids, assets_by): assets_by_site[sid] = assets num_assets += len(assets) logging.info('Associated %d assets to %d sites', num_assets, len(sitecol)) if num_assets < tot_assets: logging.warn( 'Discarded %d assets outside the ' 'asset_hazard_distance of %d km', tot_assets - num_assets, haz_distance) else: # asset sites and hazard sites are the same sitecol = haz_sitecol assets_by_site = exposure.assets_by_site discarded = [] asset_refs = numpy.array([ exposure.asset_refs[asset.ordinal] for assets in assets_by_site for asset in assets ]) assetcol = asset.AssetCollection(asset_refs, assets_by_site, exposure.tagcol, exposure.cost_calculator, oqparam.time_event, exposure.occupancy_periods) if (not oqparam.hazard_calculation_id and 'gmfs' not in oqparam.inputs and 'hazard_curves' not in oqparam.inputs): # TODO: think if we should remove this in presence of GMF-correlation assetcol = assetcol.reduce_also(sitecol) return sitecol, assetcol, discarded