Source code for oasislmf.pytools.converters.csvtobin.utils.vulnerability
importzlibimportnumbaasnbimportnumpyasnpfromoasislmf.pytools.common.dataimportresolve_filefromoasislmf.pytools.converters.csvtobin.utils.commonimportread_csv_as_ndarrayfromoasislmf.pytools.converters.dataimportTOOL_INFOfromoasislmf.pytools.getmodel.managerimportVulnerabilityIndex_dtype,VulnerabilityRow_dtypefromoasislmf.utils.exceptionsimportOasisException@nb.njit(cache=True,error_model="numpy")def_validate(data):ifdata.size==0:returnprev_vuln_id=data[0]["vulnerability_id"]prev_int_id=data[0]["intensity_bin_id"]prev_dmg_id=data[0]["damage_bin_id"]prob_sum=data[0]["probability"]# Check first damage_bin_id for each vuln_id/int_id starts at 1ifprev_dmg_id!=1:raiseOasisException(f"Error: First damage bin ID on line {0} is not 1 for vulnerability_id={prev_vuln_id}, intensity_bin_id={prev_int_id}.")next_expected_dmg_id=2# This is 2 as the first damage_bin_id must be 1foriinrange(1,len(data)):row=data[i]v_id=row["vulnerability_id"]int_id=row["intensity_bin_id"]dmg_id=row["damage_bin_id"]prob=row["probability"]# Check vulnerability_id is non-decreasingifv_id<prev_vuln_id:raiseOasisException(f"Error: Vulnerability IDs {prev_vuln_id} and {v_id} at line {i} are not in ascending order.")ifv_id==prev_vuln_idandint_id==prev_int_id:# Check damage_bin_id is contiguousifdmg_id!=next_expected_dmg_id:raiseOasisException(f"Error: Non-contiguous damage bin IDs got {dmg_id}, expected {next_expected_dmg_id} on line {i}.")prob_sum+=probnext_expected_dmg_id+=1else:# Check probabilities for each vuln_id/int_id group sum to 1ifnotnp.isclose(prob_sum,1,atol=1e-6):raiseOasisException(f"Error: Probabilities for vulnerability_id {prev_vuln_id} and intensity_bin_id {prev_int_id} do not sum to 1.""total probability = {prob_sum}.")ifv_id==prev_vuln_id:# Check intensity_bin_id is contiguousifint_id!=prev_int_id+1:raiseOasisException(f"Error: Non contiguous intensity bin IDs, got {int_id}, expected {prev_int_id+1} on line {i}.")# Check first damage_bin_id for each vuln_id/int_id starts at 1ifdmg_id!=1:raiseOasisException(f"Error: First damage bin ID on line {i} is not 1 for vulnerability_id={v_id}, intensity_bin_id={int_id}.")# Reset stateprob_sum=probnext_expected_dmg_id=2# Update prev idsprev_vuln_id=v_idprev_int_id=int_idprev_dmg_id=dmg_id# Check probabilities for each vuln_id/int_id group sum to 1ifnotnp.isclose(prob_sum,1,atol=1e-6):raiseOasisException(f"Error: Probabilities for vulnerability_id {prev_vuln_id} and intensity_bin_id {prev_int_id} do not sum to 1.""total probability = {prob_sum}.")def_validate_int_bins(data):fromoasislmf.pytools.converters.csvtobin.managerimportloggervuln_ids=np.unique(data['vulnerability_id'])int_ids_all=np.unique(data['intensity_bin_id'])missing_count=0forv_idinvuln_ids:mask=data["vulnerability_id"]==v_idvuln_bins=np.unique(data["intensity_bin_id"][mask])missing_bins=np.setdiff1d(int_ids_all,vuln_bins)ifmissing_bins.size>0:missing_count+=1logger.warning(f"WARNING: vulnerability_id {v_id} is missing intensity_bin_ids: {missing_bins.tolist()}")ifmissing_count>0:logger.warning("All intensity bins must be present for each vulnerability ID in single peril models.")
[docs]defvulnerability_tobin(stack,file_in,file_out,file_type,idx_file_out,max_damage_bin_idx,no_validation,suppress_int_bin_checks,zip_files):headers=TOOL_INFO[file_type]["headers"]dtype=TOOL_INFO[file_type]["dtype"]data=read_csv_as_ndarray(stack,file_in,headers,dtype)ifnotno_validation:_validate(data)ifnotsuppress_int_bin_checks:_validate_int_bins(data)# Write max_damage_bin to bin headernp.array([max_damage_bin_idx],dtype=np.int32).tofile(file_out)ifzip_filesandidx_file_outisNone:raiseOasisException(f"Error: Cannot write zip files without provided idx_file_out zip path, currently {idx_file_out}")# Write straight to bin file as no idx fileifidx_file_outisNone:data.tofile(file_out)returnidx_file_out=resolve_file(idx_file_out,"wb",stack)unique_vulns=np.unique(data["vulnerability_id"])offset=np.dtype(np.int32).itemsize# Header offsetforv_idinunique_vulns:vuln_mask=data["vulnerability_id"]==v_idvuln_data=data[vuln_mask]bin_data=np.empty(len(vuln_data),dtype=VulnerabilityRow_dtype)bin_data["intensity_bin_id"]=vuln_data["intensity_bin_id"]bin_data["damage_bin_id"]=vuln_data["damage_bin_id"]bin_data["probability"]=vuln_data["probability"]ifany(bin_data["damage_bin_id"]>max_damage_bin_idx):raiseOasisException(f"Error: Found damage_bin_id in data larger than max_damage_bin_idx: {max_damage_bin_idx}")bin_data=bin_data.tobytes()dsize=0ifzip_files:dsize=len(bin_data)bin_data=zlib.compress(bin_data)file_out.write(bin_data)size=len(bin_data)np.array([(v_id,offset,size,dsize)],dtype=VulnerabilityIndex_dtype).tofile(idx_file_out)offset+=size