diff --git a/openquake/hazardlib/valid.py b/openquake/hazardlib/valid.py index 26213da1a91d..a70dd945b47d 100644 --- a/openquake/hazardlib/valid.py +++ b/openquake/hazardlib/valid.py @@ -1209,9 +1209,6 @@ def host_port(value=None): # used for the exposure validation -cost_type = Choice('structural', 'nonstructural', 'contents', - 'business_interruption') - cost_type_type = Choice('aggregated', 'per_area', 'per_asset') diff --git a/openquake/qa_tests_data/scenario/case_16/Example_Exposure.xml b/openquake/qa_tests_data/scenario/case_16/Example_Exposure.xml index 64ba9a291d99..a75976ec26e3 100644 --- a/openquake/qa_tests_data/scenario/case_16/Example_Exposure.xml +++ b/openquake/qa_tests_data/scenario/case_16/Example_Exposure.xml @@ -6,8 +6,8 @@ A flexible exposure model - + diff --git a/openquake/risklib/asset.py b/openquake/risklib/asset.py index 8bf51c87befb..cf036ee51327 100644 --- a/openquake/risklib/asset.py +++ b/openquake/risklib/asset.py @@ -103,16 +103,10 @@ class CostCalculator(object): The same "formula" applies to retrofitting cost. """ - def __init__(self, cost_types, area_types, units, tagi={'taxonomy': 0}): - if set(cost_types) != set(area_types): - raise ValueError('cost_types has keys %s, area_types has keys %s' - % (sorted(cost_types), sorted(area_types))) + def __init__(self, cost_types, units, tagi={'taxonomy': 0}): for ct in cost_types.values(): assert ct in ('aggregated', 'per_asset', 'per_area'), ct - for at in area_types.values(): - assert at in ('aggregated', 'per_asset'), at self.cost_types = cost_types - self.area_types = area_types self.units = units self.tagi = tagi @@ -142,7 +136,7 @@ def __call__(self, loss_type, assetcol): if cost_type == "per_asset": return cost * number if cost_type == "per_area": - area_type = self.area_types[loss_type] + area_type = self.cost_types['area'] if area_type == "aggregated": return cost * area elif area_type == "per_asset": @@ -587,14 +581,7 @@ def get_other_fields(fields): def _get_exposure(fname, stop=None): - """ - :param fname: - path of the XML file containing the exposure - :param stop: - node at which to stop parsing (or None) - :returns: - a pair (Exposure instance, list of asset nodes) - """ + # returns (Exposure instance, asset nodes) [xml] = nrml.read(fname, stop=stop) if not xml.tag.endswith('exposureModel'): raise InvalidFile('%s: expected exposureModel, got %s' % @@ -617,14 +604,6 @@ def _get_exposure(fname, stop=None): pairs.append((node['input'], noq)) except AttributeError: pass # no fieldmap - try: - area = conversions.area - except AttributeError: - # NB: the area type cannot be an empty string because when sending - # around the CostCalculator object we would run into this numpy bug - # about pickling dictionaries with empty strings: - # https://github.com/numpy/numpy/pull/5475 - area = Node('area', dict(type='?')) try: occupancy_periods = xml.occupancyPeriods.text.split() except AttributeError: @@ -666,14 +645,12 @@ def _get_exposure(fname, stop=None): cost_types.sort(key=operator.itemgetter(0)) cost_types = numpy.array(cost_types, cost_type_dt) cc = CostCalculator( - {}, {}, {}, {name: i for i, name in enumerate(tagnames)}) + {}, {}, {name: i for i, name in enumerate(tagnames)}) for ct in cost_types: name = ct['name'] # structural, nonstructural, ... cc.cost_types[name] = ct['type'] # aggregated, per_asset, per_area - cc.area_types[name] = area['type'] cc.units[name] = ct['unit'] - exp = Exposure(occupancy_periods, area.attrib, [], cc, - TagCollection(tagnames), pairs) + exp = Exposure(occupancy_periods, [], cc, TagCollection(tagnames), pairs) assets_text = xml.assets.text.strip() if assets_text: # the tag contains a list of file names @@ -887,18 +864,15 @@ class Exposure(object): """ A class to read the exposure from XML/CSV files """ - fields = ['occupancy_periods', 'area', 'assets', + fields = ['occupancy_periods', 'assets', 'cost_calculator', 'tagcol', 'pairs'] def __toh5__(self): cc = self.cost_calculator loss_types = sorted(cc.cost_types) - dt = numpy.dtype([('cost_type', hdf5.vstr), - ('area_type', hdf5.vstr), - ('unit', hdf5.vstr)]) + dt = numpy.dtype([('cost_type', hdf5.vstr), ('unit', hdf5.vstr)]) array = numpy.zeros(len(loss_types), dt) array['cost_type'] = [cc.cost_types[lt] for lt in loss_types] - array['area_type'] = [cc.area_types[lt] for lt in loss_types] array['unit'] = [cc.units[lt] for lt in loss_types] attrs = dict( loss_types=hdf5.array_of_vstr(loss_types), @@ -910,7 +884,6 @@ def __fromh5__(self, array, attrs): vars(self).update(attrs) cc = self.cost_calculator = object.__new__(CostCalculator) cc.cost_types = dict(zip(self.loss_types, decode(array['cost_type']))) - cc.area_types = dict(zip(self.loss_types, decode(array['area_type']))) cc.units = dict(zip(self.loss_types, decode(array['unit']))) @staticmethod diff --git a/openquake/risklib/read_nrml.py b/openquake/risklib/read_nrml.py index 73218a4e9615..e6c3eff04861 100644 --- a/openquake/risklib/read_nrml.py +++ b/openquake/risklib/read_nrml.py @@ -352,8 +352,8 @@ def get_fragility_model_04(fmodel, fname): # ######################## validators ######################## # -valid_loss_types = valid.Choice('structural', 'nonstructural', 'contents', - 'business_interruption', 'occupants') +valid_loss_type = valid.Choice(*[lt for lt in scientific.LOSSTYPE + if '+' not in lt and '_ins' not in lt]) def asset_mean_stddev(value, assetRef, mean, stdDev): @@ -386,9 +386,9 @@ def update_validators(): 'vulnerabilityFunction.id': valid.risk_id, # taxonomy 'consequenceFunction.id': valid.risk_id, # taxonomy 'asset.id': valid.asset_id, - 'costType.name': valid.cost_type, + 'costType.name': valid_loss_type, 'costType.type': valid.cost_type_type, - 'cost.type': valid.cost_type, + 'cost.type': valid_loss_type, 'area.type': valid.name, 'isAbsolute': valid.boolean, 'insuranceLimit': valid.positivefloat, @@ -416,14 +416,14 @@ def update_validators(): 'maxIML': valid.positivefloat, 'limitStates': valid.namelist, 'noDamageLimit': valid.NoneOr(valid.positivefloat), - 'loss_type': valid_loss_types, + 'loss_type': valid_loss_type, 'losses': valid.positivefloats, 'averageLoss': valid.positivefloat, 'stdDevLoss': valid.positivefloat, 'ffs.type': valid.ChoiceCI('lognormal'), 'assetLifeExpectancy': valid.positivefloat, 'interestRate': valid.positivefloat, - 'lossType': valid_loss_types, + 'lossType': valid_loss_type, 'aalOrig': valid.positivefloat, 'aalRetr': valid.positivefloat, 'ratio': valid.positivefloat,