def test_discrete(self): hazard_imls = [0.05, 0.2, 0.4, 0.6, 0.8, 1, 1.2, 1.4] fragility_functions = scientific.FragilityFunctionList( [], imls=hazard_imls, format='discrete') fragility_functions.extend([ scientific.FragilityFunctionDiscrete( 'slight', hazard_imls, [0.0, 0.771, 0.95, 0.989, 0.997, 0.999, 1., 1.]), scientific.FragilityFunctionDiscrete( 'moderate', hazard_imls, [0, 0.5, 0.861, 0.957, 0.985, 0.994, 0.997, 0.999]), scientific.FragilityFunctionDiscrete( 'extreme', hazard_imls, [0.0, 0.231, 0.636, 0.837, 0.924, 0.962, .981, .989]), scientific.FragilityFunctionDiscrete( 'complete', hazard_imls, [0, 0.097, 0.414, 0.661, 0.806, 0.887, 0.933, 0.959]), ]) hazard_poes = numpy.array([ 0.999999999997518, 0.077404949, 0.015530587, 0.004201327, 0.001284191, 0.000389925, 0.000127992, 0.000030350, ]) investigation_time = 50. risk_investigation_time = 100. poos = scientific.classical_damage( fragility_functions, hazard_imls, hazard_poes, investigation_time, risk_investigation_time) aaae(poos, [1.0415184E-09, 1.4577245E-06, 1.9585762E-03, 6.9677521E-02, 9.2836244E-01])
def _parse_fragility(content): """ Parse the fragility XML file and return fragility_model, fragility_functions, and damage_states for usage in get_risk_models. """ iterparse = iter(parsers.FragilityModelParser(content)) fmt, limit_states = iterparse.next() damage_states = ['no_damage'] + limit_states fragility_functions = collections.defaultdict(dict) tax_imt = dict() for taxonomy, iml, params, no_damage_limit in iterparse: tax_imt[taxonomy] = iml['IMT'] if fmt == "discrete": if no_damage_limit is None: fragility_functions[taxonomy] = [ scientific.FragilityFunctionDiscrete( iml['imls'], poes, iml['imls'][0]) for poes in params ] else: fragility_functions[taxonomy] = [ scientific.FragilityFunctionDiscrete( [no_damage_limit] + iml['imls'], [0.0] + poes, no_damage_limit) for poes in params ] else: fragility_functions[taxonomy] = [ scientific.FragilityFunctionContinuous(*mean_stddev) for mean_stddev in params ] risk_models = dict((tax, dict(damage=RiskModel(tax_imt[tax], None, ffs))) for tax, ffs in fragility_functions.items()) return damage_states, risk_models
def to_node(self): """ Build a full discrete fragility node from CSV """ tset = self.tableset frag = tset.tableFragilityDiscrete[0].to_node() ffs_node = record.nodedict(tset.tableFFSetDiscrete) nodamage = float(ffs_node['noDamageLimit']) \ if 'noDamageLimit' in ffs_node else None frag.nodes.extend(ffs_node.values()) for (ls, ordinal), data in groupby(tset.tableFFDataDiscrete, ['limitState', 'ffs_ordinal']): data = list(data) # check that we can instantiate a FragilityFunction in risklib if nodamage: scientific.FragilityFunctionDiscrete( [nodamage] + [rec.iml for rec in data], [0.0] + [rec.poe for rec in data], nodamage) else: scientific.FragilityFunctionDiscrete([rec.iml for rec in data], [rec.poe for rec in data], nodamage) imls = ' '.join(rec['iml'] for rec in data) ffs_node[(ordinal, )].IML.text = imls poes = ' '.join(rec['poe'] for rec in data) n = Node('ffd', dict(ls=ls)) n.append(Node('poEs', text=poes)) ffs_node[(ordinal, )].append(n) return frag
def test_discrete_ff(self): fragility_model = { 'RC': [ scientific.FragilityFunctionDiscrete( 'LS1', [0.1, 0.2, 0.3, 0.5], [0.0073, 0.35, 0.74, 0.99]), scientific.FragilityFunctionDiscrete( 'LS2', [0.1, 0.2, 0.3, 0.5], [0.001, 0.02, 0.25, 0.72])], 'RM': [ scientific.FragilityFunctionDiscrete( 'LS1', [0.1, 0.2, 0.3, 0.5], [0.01, 0.64, 0.95, 1.0]), scientific.FragilityFunctionDiscrete( 'LS2', [0.1, 0.2, 0.3, 0.5], [0.0003, 0.05, 0.40, 0.86])]} calculator_rm = workflows.Damage( 'PGA', 'RM', dict(damage=fragility_model['RM'])) [asset_output_a1] = calculator_rm( 'damage', ['a1'], [self.hazard['a1']]).damages expected_means = [875.81078203, 1448.29628694, 675.89293103] expected_stdevs = [757.54019289, 256.15319254, 556.76593931] self.assert_ok(asset_output_a1 * 3000, expected_means, expected_stdevs) [asset_output_a3] = calculator_rm( 'damage', ['a3'], [self.hazard['a3']]).damages expected_means = [224.4178072, 465.64396155, 309.93823125] expected_stdevs = [220.65161409, 136.92817619, 246.84424913] self.assert_ok(asset_output_a3 * 1000, expected_means, expected_stdevs) rm = asset_output_a1 * 3000 + asset_output_a3 * 1000 calculator_rc = workflows.Damage( 'PGA', 'RC', dict(damage=fragility_model['RC'])) [asset_output_a2] = calculator_rc( 'damage', ['a2'], [self.hazard['a2']]).damages expected_means = [344.90849228, 747.62412976, 907.46737796] expected_stdevs = [300.61123079, 144.64852962, 417.30737837] self.assert_ok(asset_output_a2 * 2000, expected_means, expected_stdevs) rc = asset_output_a2 * 2000 assert_close( rm.mean(0), [1100.2285892246, 1913.9402484967, 985.8311622787]) assert_close( rm.std(0, ddof=1), [880.2774984768, 296.2197411105, 616.5632580754]) assert_close( rc.mean(0), [344.9084922789, 747.6241297573, 907.4673779638]) assert_close( rc.std(0, ddof=1), [300.6112307894, 144.6485296163, 417.307378365])
def test_dda_iml_above_range(self): # corner case where we have a ground motion value # (that corresponds to the intensity measure level in the # fragility function) that is higher than the highest # intensity measure level defined in the model (in this # particular case 0.7). Given this condition, to compute # the fractions of buildings we use the highest intensity # measure level defined in the model (0.7 in this case) ffns = [ scientific.FragilityFunctionDiscrete( 'LS1', [0.1, 0.1, 0.3, 0.5, 0.7], [0, 0.05, 0.20, 0.50, 1.00]), scientific.FragilityFunctionDiscrete( 'LS2', [0.1, 0.1, 0.3, 0.5, 0.7], [0, 0.05, 0.20, 0.50, 1.00]) ] self._close_to(scientific.scenario_damage(ffns, [0.7]), scientific.scenario_damage(ffns, [0.8]))
def test_gmv_between_no_damage_limit_and_first_iml(self): # corner case where we have a ground motion value # (that corresponds to the intensity measure level in the # fragility function) that is lower than the lowest # intensity measure level defined in the model (in this # particular case 0.1) but bigger than the no_damage_limit # attribute defined in the model. Given this condition, the # fractions of buildings is 97.5% no_damage and 2.5% for the # remaining limit states defined in the model. ffs = [ scientific.FragilityFunctionDiscrete( 'LS1', [0.05, 0.1, 0.3, 0.5, 0.7], [0, 0.05, 0.20, 0.50, 1.00], 0.05), scientific.FragilityFunctionDiscrete( 'LS2', [0.05, 0.1, 0.3, 0.5, 0.7], [0, 0.00, 0.05, 0.20, 0.50], 0.05)] self._close_to([0.975, 0.025, 0], scientific.scenario_damage(ffs, 0.075))
def test_dda_iml_below_range_damage_limit_defined(self): # corner case where we have a ground motion value # (that corresponds to the intensity measure level in the # fragility function) that is lower than the lowest # intensity measure level defined in the model (in this # particular case 0.1) and lower than the no_damage_limit # attribute defined in the model. Given this condition, the # fractions of buildings is 100% no_damage and 0% for the # remaining limit states defined in the model. ffns = [ scientific.FragilityFunctionDiscrete( 'LS1', [0.05, 0.1, 0.3, 0.5, 0.7], [0, 0.05, 0.20, 0.50, 1.00], 0.5), scientific.FragilityFunctionDiscrete( 'LS2', [0.05, 0.1, 0.3, 0.5, 0.7], [0, 0.05, 0.20, 0.50, 1.00], 0.5), ] self._close_to([[1.0], [0.0], [0.0]], scientific.scenario_damage(ffns, [0.02]))
def get_damage_states_and_risk_models(content): """ Parse the fragility XML file and return a list of damage_states and a dictionary {taxonomy: risk model} """ iterparse = iter(parsers.FragilityModelParser(content)) fmt, limit_states = iterparse.next() damage_states = ['no_damage'] + limit_states fragility_functions = collections.defaultdict(dict) tax_imt = dict() for taxonomy, iml, params, no_damage_limit in iterparse: tax_imt[taxonomy] = iml['IMT'] if fmt == "discrete": if no_damage_limit is None: fragility_functions[taxonomy] = [ scientific.FragilityFunctionDiscrete( iml['imls'], poes, iml['imls'][0]) for poes in params ] else: fragility_functions[taxonomy] = [ scientific.FragilityFunctionDiscrete( [no_damage_limit] + iml['imls'], [0.0] + poes, no_damage_limit) for poes in params ] else: fragility_functions[taxonomy] = [ scientific.FragilityFunctionContinuous(*mean_stddev) for mean_stddev in params ] risk_models = {} for taxonomy, ffs in fragility_functions.items(): dic = dict(damage=List(ffs, imt=tax_imt[taxonomy])) risk_models[taxonomy] = workflows.RiskModel(taxonomy, workflows.Damage(dic)) return damage_states, risk_models
def test_discrete_ne(self): ffd1 = scientific.FragilityFunctionDiscrete('LS1', [], []) ffd2 = scientific.FragilityFunctionDiscrete('LS1', [0.1], [0.1]) self.assertTrue(ffd1 != ffd2)
def test_can_pickle(self): ffd = scientific.FragilityFunctionDiscrete('LS1', [0, .1, .2, .3], [0.05, 0.20, 0.50, 1.00]) self.assertEqual(pickle.loads(pickle.dumps(ffd)), ffd)
def get_fragility_functions(fname, continuous_fragility_discretization, steps_per_interval=None): """ :param fname: path of the fragility file :param continuous_fragility_discretization: continuous_fragility_discretization parameter :param steps_per_interval: steps_per_interval parameter :returns: damage_states list and dictionary taxonomy -> functions """ [fmodel] = read_nodes(fname, lambda el: el.tag.endswith('fragilityModel'), nodefactory['fragilityModel']) # ~fmodel.description is ignored limit_states = ~fmodel.limitStates tag = 'ffc' if fmodel['format'] == 'continuous' else 'ffd' fragility_functions = AccumDict() # taxonomy -> functions for ffs in fmodel.getnodes('ffs'): add_zero_value = False # NB: the noDamageLimit is only defined for discrete fragility # functions. It is a way to set the starting point of the functions: # if noDamageLimit is at the left of each IMLs, it means that the # function starts at zero at the given point, so we need to add # noDamageLimit to the list of IMLs and zero to the list of poes nodamage = ffs.attrib.get('noDamageLimit') taxonomy = ~ffs.taxonomy imt_str, imls, min_iml, max_iml, imlUnit = ~ffs.IML if fmodel['format'] == 'discrete': if nodamage is not None and nodamage < imls[0]: # discrete fragility imls = [nodamage] + imls add_zero_value = True if steps_per_interval: gen_imls = scientific.fine_graining(imls, steps_per_interval) else: gen_imls = imls else: # continuous: if min_iml is None: raise InvalidFile('Missing attribute minIML, line %d' % ffs.IML.lineno) elif max_iml is None: raise InvalidFile('Missing attribute maxIML, line %d' % ffs.IML.lineno) gen_imls = numpy.linspace(min_iml, max_iml, continuous_fragility_discretization) fragility_functions[taxonomy] = scientific.FragilityFunctionList( [], imt=imt_str, imls=list(gen_imls), no_damage_limit=nodamage, continuous_fragility_discretization= continuous_fragility_discretization, steps_per_interval=steps_per_interval) lstates = [] for ff in ffs.getnodes(tag): ls = ff['ls'] # limit state lstates.append(ls) if tag == 'ffc': with context(fname, ff): mean_stddev = ~ff.params fragility_functions[taxonomy].append( scientific.FragilityFunctionContinuous(ls, *mean_stddev)) else: # discrete with context(fname, ff): poes = ~ff.poEs if add_zero_value: poes = [0.] + poes fragility_functions[taxonomy].append( scientific.FragilityFunctionDiscrete( ls, imls, poes, nodamage)) if lstates != limit_states: raise InvalidFile("Expected limit states %s, got %s in %s" % (limit_states, lstates, fname)) fragility_functions.damage_states = ['no_damage'] + limit_states return fragility_functions