Source code for ana4Stats.probAna

"""

This is a simple function for computing a probability map of all peak files of one parameter that
exceed a particular threshold

"""

import numpy as np
import logging
import pathlib
from scipy.stats import qmc

import avaframe.out3Plot.plotUtils as pU
from avaframe.in3Utils import cfgUtils
from avaframe.in3Utils import cfgHandling
from avaframe.in3Utils import fileHandlerUtils as fU
import avaframe.in2Trans.ascUtils as IOf
import avaframe.in1Data.computeFromDistribution as cP
import avaframe.com1DFA.deriveParameterSet as dP
from avaframe.in3Utils import geoTrans as gT
from avaframe.out3Plot import statsPlots as sP
from avaframe.in1Data import getInput as gI


# create local logger
# change log level in calling module to DEBUG to see log messages
log = logging.getLogger(__name__)


[docs]def createComModConfig(cfgProb, avaDir, modName): """ create configuration file for performing sims with modName com module Parameters ----------- cfgProb: configParser object configuration settings avaDir: pathlib path path to avalanche directory modName: module computational module Returns ------- cfgFiles: list list of paths to newly generated configuration files for com module inlcuding parameter variations """ # setup where configuration file is saved modNameString = str(pathlib.Path(modName.__file__).stem) outDir = avaDir / 'Work' / ('%sConfigFiles' % modNameString) fU.makeADir(outDir) # check variation settings variationsDict = makeDictFromVars(cfgProb['PROBRUN']) if cfgProb['PROBRUN'].getint('samplingStrategy') == 2: log.info('Probability run performed by varying one parameter at a time - local approach.') cfgFiles = cfgFilesLocalApproach(variationsDict, cfgProb, modName, outDir) else: log.info('Probability run perfromed drawing parameter set from full sample.') cfgFiles = cfgFilesGlobalApproach(avaDir, cfgProb, modName, outDir) return cfgFiles, outDir
[docs]def cfgFilesGlobalApproach(avaDir, cfgProb, modName, outDir): """ create configuration files with all parameter variations - drawn from full sample for performing sims with modName comModule Parameters ----------- cfgProb: configParser object configuration settings avaDir: pathlib path path to avalanche directory modName: module computational module Returns ------- cfgFiles: list list of paths to newly generated configuration files for com module inlcuding parameter variations """ # create sample of all parameter variations paramValuesDList = createSampleFromConfig(avaDir, cfgProb, modName) # create plot of parameter sample if variation of two parameters for paramValuesD in paramValuesDList: if 'releaseScenario' in paramValuesD.keys(): releaseScenario = paramValuesD['releaseScenario'] else: releaseScenario = '' plotDir = avaDir / 'Outputs' / 'ana4Stats' / 'plots' if len(paramValuesD['names']) == 2: sP.plotSample(paramValuesD, plotDir, releaseScenario=releaseScenario) elif len(paramValuesD['varParNamesInitial']) == 2: sP.plotThSampleFromVals(paramValuesD, plotDir) else: log.debug('More or less than two parameters have been varied - no plot of sample available') # write cfg files one for each parameter set drawn from full sample cfgFiles = createCfgFiles(paramValuesDList, modName, cfgProb, cfgPath=outDir) return cfgFiles
[docs]def cfgFilesLocalApproach(variationsDict, cfgProb, modName, outDir): """ create configuration file for performing sims with modName com module Parameters ----------- variationsDict: dict dictionary with for each varName, varVariation, varSteps, and type of variation cfgProb: configParser object configuration settings avaDir: pathlib path path to avalanche directory modName: module computational module Returns ------- cfgFiles: dict dictionary of paths to newly generated configuration files for com module for all parameters """ cfgFiles = [] for varName in variationsDict: # define configuration files # get filename of module modNameString = str(pathlib.Path(modName.__file__).stem) cfgFile = outDir / ('probRun%sCfg%s.ini' % (modNameString, varName)) # use cfgFile, local com module settings or default settings if local not available modCfg = fetchStartCfg(modName, cfgProb) modCfg = updateCfgRange(modCfg, cfgProb, varName, variationsDict[varName]) with open(cfgFile, 'w') as configfile: modCfg.write(configfile) # append cfgFiles to list cfgFiles.append(cfgFile) return cfgFiles
[docs]def updateCfgRange(cfg, cfgProb, varName, varDict): """ update cfg with a range for parameters in cfgProb Parameters ----------- cfg: configparser object configuration object to update cfgProb: configParser object configparser object with info on update varName: str name of parameter used for variation varDict: dict dictionary with variationValue and numberOfSteps for varName Returns -------- cfg: configParser updated configuration object """ # set reference values of parameters - override values in com module configurations varParList = cfgProb['PROBRUN']['varParList'].split('|') # also for the other parameters that are varied subsequently # first check if no parameter variation in provided for these parameters in the com module ini # if so - errror _, _ = checkParameterSettings(cfg, varParList) # this is now done for parameter VARNAME from inputs # get range, steps and reference value of parameter to perform variations valVariation = varDict['variationValue'] valSteps = varDict['numberOfSteps'] valVal = cfg['GENERAL'][varName] variationType = varDict['variationType'] if variationType.lower() == 'normaldistribution': # get computeFromDistribution configuration and apply override cfgDist = cfgUtils.getModuleConfig(cP, fileOverride='', modInfo=False, toPrint=False, onlyDefault=cfgProb['in1Data_computeFromDistribution_override'].getboolean('defaultConfig')) cfgDist, cfgProb = cfgHandling.applyCfgOverride(cfgDist, cfgProb, cP, addModValues=False) # set variation in configuration if varName in ['relTh', 'entTh', 'secondaryRelTh']: # if variation using normal distribution if variationType.lower() == 'normaldistribution': parName = varName + 'DistVariation' if valVariation == '': valVariation = '-' parValue = (variationType + '$' + valSteps + '$' + valVariation + '$' + cfgDist['GENERAL']['minMaxInterval'] + '$' + cfgDist['GENERAL']['buildType'] + '$' + cfgDist['GENERAL']['support']) # if variation using percent elif variationType.lower() == 'percent': parName = varName + 'PercentVariation' parValue = valVariation + '$' + valSteps # if variation using absolute range elif variationType.lower() == 'range': parName = varName + 'RangeVariation' parValue = valVariation + '$' + valSteps if 'ci' in valVariation: message = ('Variation Type: range - variationValue is %s not a valid option - only \ scalar value allowed or consider variationType rangefromci' % valVariation) log.error(message) raise AssertionError(message) elif variationType.lower() == 'rangefromci': parName = varName + 'RangeFromCiVariation' parValue = valVariation + '$' + valSteps else: message = ('Variation Type: %s - not a valid option, options are: percent, range, \ normaldistribution, rangefromci' % variationType) log.error(message) raise AssertionError(message) # write parameter variation for varName in config file cfg['GENERAL'][parName] = parValue else: # set variation if variationType.lower() == 'normaldistribution': cfgDist = {'sampleSize': valSteps, 'mean': valVal, 'buildType': cfgProb['in1Data_computeFromDistribution_override']['buildType'], 'buildValue': valVariation, 'minMaxInterval': cfgDist['GENERAL']['minMaxInterval'], 'support': cfgDist['GENERAL']['support']} _, valValues, _, _ = cP.extractNormalDist(cfgDist) cfg['GENERAL'][varName] = dP.writeToCfgLine(valValues) elif variationType.lower() == 'percent': cfg['GENERAL'][varName] = '%s$%s$%s' % (valVal, valVariation, valSteps) valValues = fU.splitIniValueToArraySteps(cfg['GENERAL'][varName]) elif variationType.lower() == 'range': if '-' in valVariation or '+' in valVariation: valStart = str(float(valVal) + float(valVariation)) valStop = float(valVal) else: valStart = str(float(valVal) - float(valVariation)) valStop = str(float(valVal) + float(valVariation)) cfg['GENERAL'][varName] = '%s:%s:%s' % (valStart, valStop, valSteps) valValues = np.linspace(float(valStart), float(valStop), int(valSteps)) else: message = ('Variation Type: %s - not a valid option, options are: percent, range, \ normaldistribution, rangefromci' % variationType) log.error(message) raise AssertionError(message) # add a scenario Name to VISUALISATION cfg['VISUALISATION']['scenario'] = varName return cfg
[docs]def checkParameterSettings(cfg, varParList): """ check if parameter settings in comMod configuration do not inlcude variation for parameters to be varied Parameters ----------- cfg: configparser object configuration settings varParList: list list of parameters (names) that shall be varied """ # set a list of all thickness parameters that are set to be read from shp file thReadFromShp = [] # loop over all parameters and check if no variation is set and if read from shp for varPar in varParList: if any(chars in cfg['GENERAL'][varPar] for chars in ['|', '$', ':']): message = ('Only one reference value is allowed for %s: but %s is given' % (varPar, cfg['GENERAL'][varPar])) log.error(message) raise AssertionError(message) elif varPar in ['entTh', 'relTh', 'secondaryRelTh']: thFromShp = varPar + 'FromShp' # check if reference settings have already variation of varPar _ = checkForNumberOfReferenceValues(cfg['GENERAL'], varPar) # check if th read from shp file if cfg['GENERAL'].getboolean(thFromShp): thReadFromShp.append(varPar) return True, thReadFromShp
[docs]def checkForNumberOfReferenceValues(cfgGen, varPar): """ check if in reference configuration no variation option of varPar is set if set - throw error Parameters ----------- cfgGen: configparser object reference configuration settings varPar: str name of parameter to be checked """ thPV = varPar + 'PercentVariation' thRV = varPar + 'RangeVariation' thDV = varPar + 'DistVariation' thRCiV = varPar + 'RangeFromCiVariation' # check if variation is set if cfgGen[thPV] != '' or cfgGen[thRV] != '' or cfgGen[thDV] != '' or cfgGen[thRCiV] != '': message = ('Only one reference value is allowed for %s: but %s %s, %s %s, %s %s, %s %s is given' % (varPar, thPV, cfgGen[thPV], thRV, cfgGen[thRV], thDV, cfgGen[thDV], thRCiV, cfgGen[thRCiV])) log.error(message) raise AssertionError(message) return True
[docs]def probAnalysis(avaDir, cfg, module, parametersDict='', inputDir='', probConf='', simDFActual=''): """ Compute probability map of a given set of simulation result exceeding a particular threshold and save to outDir Parameters ---------- avaDir: str path to avalanche directory cfg : dict configuration read from ini file of probAna function module computational module that was used to run the simulations parametersDict: dict dictionary with simulation parameters to filter simulations inputDir : str optional - path to directory where data that should be analysed can be found in a subfolder called peakFiles and configurationFiles, required if not in module results probConf : str name of probability configuration simDFActual: pandas dataFrame dataframe of simulation configurations that shall be used for prob analysis """ # get filename of module modName = pathlib.Path(module.__file__).stem avaDir = pathlib.Path(avaDir) # set output directory outDir = avaDir / 'Outputs' / 'ana4Stats' fU.makeADir(outDir) # fetch all result files and filter simulations according to parametersDict simNameList = cfgHandling.filterSims(avaDir, parametersDict, specDir=inputDir, simDF=simDFActual) # initialize flag if analysis has been performed or e.g. no matching files found analysisPerformed = False if simNameList == []: # no matching sims found for filtering criteria log.warning('No matching simulations found for filtering criteria') return analysisPerformed # if matching sims found - perform analysis if inputDir == '': inputDir = avaDir / 'Outputs' / modName / 'peakFiles' peakFilesDF = fU.makeSimDF(inputDir, avaDir=avaDir) else: inputDirPF = inputDir / 'peakFiles' peakFilesDF = fU.makeSimDF(inputDirPF, avaDir=avaDir) # get header info from peak files - this should be the same for all peakFiles header = IOf.readASCheader(peakFilesDF['files'][0]) refData = IOf.readRaster(peakFilesDF['files'][0]) nRows = header['nrows'] nCols = header['ncols'] # Initialise array for computations probSum = np.zeros((nRows, nCols)) count = 0 contourDict = {} # Loop through peakFiles and compute probability for m in range(len(peakFilesDF['names'])): # only take simulations that match filter criteria from parametersDict if peakFilesDF['simName'][m] in simNameList: # Load peak field for desired peak field parameter if peakFilesDF['resType'][m] == cfg['GENERAL']['peakVar']: # Load data fileName = peakFilesDF['files'][m] dataLim = np.zeros((nRows, nCols)) fileData = IOf.readRaster(fileName) # check if extent is the same as first loaded dataset # if not - remesh and print warning if fileData['header']['nrows'] != nRows or fileData['header']['ncols'] != nCols: log.warning('datasets used to create probMap do not match in extent - remeshing: %s to cellSize %s' % (fileName, header['cellsize'])) data, _ = gT.resizeData(fileData, refData) data = np.flipud(fileData['rasterData']) # fetch contourline info xGrid, yGrid, _, _ = gT.makeCoordGridFromHeader(refData['header']) contourDictXY = pU.fetchContourCoords(xGrid, yGrid, data, float(cfg['GENERAL']['peakLim'])) contourDict[fileName.stem] = contourDictXY log.info('File Name: %s , simulation parameter %s ' % (fileName, cfg['GENERAL']['peakVar'])) # Check if peak values exceed desired threshold dataLim[data > float(cfg['GENERAL']['peakLim'])] = 1.0 probSum = probSum + dataLim count = count + 1 # Create probability map ranging from 0-1 probMap = probSum / count unit = pU.cfgPlotUtils['unit%s' % cfg['GENERAL']['peakVar']] log.info('probability analysis performed for peak parameter: %s and a peak value ' 'threshold of: %s %s' % (cfg['GENERAL']['peakVar'], cfg['GENERAL']['peakLim'], unit)) log.info('%s peak fields added to analysis' % count) # # Save to .asc file avaName = avaDir.name outFileName = '%s_prob_%s_%s_lim%s.asc' % (avaName, probConf, cfg['GENERAL']['peakVar'], cfg['GENERAL']['peakLim']) outFile = outDir / outFileName IOf.writeResultToAsc(header, probMap, outFile) log.info('Prob result written to %s' % outFile) analysisPerformed = True return analysisPerformed, contourDict
[docs]def makeDictFromVars(cfg): """ create a dictionary with info on parameter variation for all parameter in varParList Parameters ----------- cfg: configparser object configuration settings, here varParList, variationValue, numberOfSteps Returns -------- variationsDict: dict dictionary with for each varName, varVariation, varSteps, and type of variation """ varParList = cfg['varParList'].split('|') varParTypes = cfg['varParType'].split('|') varValues = cfg['variationValue'].split('|') varSteps = cfg['numberOfSteps'].split('|') varTypes = cfg['variationType'].split('|') # check if value is provided for each parameter if cfg.getint('samplingStrategy') == 1: lengthsPar = 'varParType' elif cfg.getint('samplingStrategy') == 2: lengthsPar = 'numberOfSteps' else: message = 'Chosen sampling strategy not valid: options are 1 or 2' log.error(message) raise AssertionError(message) if (len(varParList) == len(varValues) == len(cfg[lengthsPar].split('|')) == len(varTypes)) is False: message = ('For every parameter in varParList a variationValue, %s and variationType needs to be provided' % lengthsPar) log.error(message) raise AssertionError(message) # check if correct values provided for rangefromci rangeFromCi = [idx for idx, v in enumerate(varTypes) if v.lower() == 'rangefromci'] varValuesRCi = np.asarray(varValues)[rangeFromCi] ciCheck = [False for ci in varValuesRCi if ci != 'ci95'] if len(ciCheck) > 0: message = 'If rangefromci is chosen as variation type, ci95 is required as variationValue' log.error(message) raise AssertionError(message) variationsDict = {} if cfg.getint('samplingStrategy') == 2: for idx, val in enumerate(varParList): variationsDict[val] = {'variationValue': varValues[idx], 'numberOfSteps': varSteps[idx], 'variationType': varTypes[idx]} return variationsDict
[docs]def fetchThicknessInfo(avaDir): """ Fetch input data for avaDir and thickness info Parameters ------------ cfg: configparser object configuration settings avaDir: pathlib path or str path to avalanche directory Returns ----------- inputSimFilesAll: dict dictionary with info on available input data (release areas, entrainment, and thickness info) """ # fetch input data - dem, release-, entrainment- and resistance areas (and secondary release areas) inputSimFilesAll = gI.getInputDataCom1DFA(avaDir) # get thickness of release and entrainment areas (and secondary release areas) -if thFromShp = True inputSimFilesAll = gI.getThicknessInputSimFiles(inputSimFilesAll) return inputSimFilesAll
[docs]def createSampleFromConfig(avaDir, cfgProb, comMod): """ Create a sample of parameters for a desired parameter variation, and draw nSample sets of parameter values if thickness values read from shp for comMod, convert sample values for these Parameters ------------ avaDir: pathlib path path to avalanche directory cfgProb: configparser object configuration settings for parameter variation comMod: computational module module to perform then sims for parameter variation Returns -------- paramValuesDList: list list of paramValuesD (multiple if multiple release area scenarios) - names: list, list of parameter names (that are varied) - values: numpy nd array, as many rows as sets of parameter values and as many rows as parameters - typeList: list, list of types of parameters (float, ...) - thFromIni: str, str of parameter names where the base value is read from shape """ # read initial configuration cfgStart = fetchStartCfg(comMod, cfgProb) # fetch parameter names for parameter variation and variation value and variation type varParList = cfgProb['PROBRUN']['varParList'].split('|') valVariationValue = cfgProb['PROBRUN']['variationValue'].split('|') varType = cfgProb['PROBRUN']['variationType'].split('|') # check if thickness parameters are actually read from shp file _, thReadFromShp = checkParameterSettings(cfgStart, varParList) # create sets of parameters values for parameter variation if len(thReadFromShp) > 0: paramValuesDList = createSampleWithVariationForThParameters(avaDir, cfgProb, cfgStart, varParList, valVariationValue, varType, thReadFromShp) else: paramValuesD = createSampleWithVariationStandardParameters(cfgProb, cfgStart, varParList, valVariationValue, varType) paramValuesDList = [paramValuesD] return paramValuesDList
[docs]def createSampleWithVariationStandardParameters(cfgProb, cfgStart, varParList, valVariationValue, varType): """ create a sample for a parameter variation using latin hypercube sampling Parameters ------------ cfgProb: configparser object configuration settings for parameter variation cfgStart: configparser object configuration settings for comMod without variation values varParList: list list of parameters that shall be varied valVariationValue: list list if value used for variation varType: list list of type of variation for each parameter (percent, range, rangefromci) Returns -------- paramValuesD: dict dictionary used to pass parameter variation values - names: list, list of parameter names (that are varied) - values: numpy nd array, as many rows as sets of parameter values and as many rows as parameters - typeList: list, list of types of parameters (float, ...) - thFromIni: str, str of parameter names where the base value is read from shape """ # initialze lower and upper bounds required to get a sample for the parameter values lowerBounds = [] upperBounds = [] for idx, varPar in enumerate(varParList): # if parameter value directly set in configuration modify the value directly varVal = cfgStart['GENERAL'].getfloat(varPar) if varType[idx].lower() == 'percent': lB = varVal - varVal * (float(valVariationValue[idx]) / 100.) uB = varVal + varVal * (float(valVariationValue[idx]) / 100.) elif varType[idx].lower() == 'range': lB = varVal - float(valVariationValue[idx]) uB = varVal + float(valVariationValue[idx]) else: message = ('Variation method: %s not a valid option' % varType[idx]) log.error(message) raise AssertionError(message) # update bounds lowerBounds.append(lB) upperBounds.append(uB) # create a sample of parameter values using scipy latin hypercube sampling sample = createSample(cfgProb, varParList) sampleWBounds = qmc.scale(sample, lowerBounds, upperBounds) # create dictionary with all the info paramValuesD = {'names': varParList, 'values': sampleWBounds, 'typeList': cfgProb['PROBRUN']['varParType'].split('|'), 'thFromIni': ''} return paramValuesD
[docs]def createSampleWithVariationForThParameters(avaDir, cfgProb, cfgStart, varParList, valVariationValue, varType, thReadFromShp): """ Create a sample of parameters for a desired parameter variation, and fetch thickness values from shp file and perform variation for each feature within shapefile but treating the features of one shapefile as not-independent paramsValuesD dict in output list contains Parameters ------------ cfgProb: configparser object configuration settings for parameter variation cfgStart: configparser object configuration settings for comMod without variation values varParList: list list of parameters that shall be varied valVariationValue: list list if value used for variation varType: list list of type of variation for each parameter (percent, range, rangefromci) Returns -------- paramValuesDList: list list of paramValuesD (multiple if multiple release area scenarios) - names: list, list of parameter names (that are varied) - values: numpy nd array, as many rows as sets of parameter values and as many rows as parameters - typeList: list, list of types of parameters (float, ...) - thFromIni: str, str of parameter names where the base value is read from shape """ # fetch input files and corresponding thickness info inputSimFiles = fetchThicknessInfo(avaDir) paramValuesDList = [] for iRel, relF in enumerate(inputSimFiles['relFiles']): paramValuesD = {} # create lower and upper bounds for all thickness parameters - taking into account all features fullListOfParameters = [] parentParameterId = [] staParameter = [] thValues = np.asarray([]) ciValues = np.asarray([]) for idx1, varPar in enumerate(varParList): if varPar in thReadFromShp: ciRequired = varType[idx1].lower() == 'rangefromci' thV, ciV, thFeatureNames = fetchThThicknessLists(varPar, inputSimFiles, relF, ciRequired=ciRequired) # add to list all the parameter names fullListOfParameters = fullListOfParameters + thFeatureNames parentParameterId = parentParameterId + [varParList.index(varPar)]*len(thFeatureNames) thValues = np.append(thValues, thV) ciValues = np.append(ciValues, ciV) else: parentParameterId.append(varParList.index(varPar)) fullListOfParameters.append(varPar) staParameter.append(varPar) thValues = np.append(thValues, np.asarray([None])) ciValues = np.append(ciValues, np.asarray([None])) # initialize lower and upper bounds required to get a sample for the parameter values # numpy arrays required to do masking as lists don't work for a list indices varValList = np.asarray([cfgStart['GENERAL'].getfloat(varPar) if varPar in staParameter else thValues[idx] for idx, varPar in enumerate(fullListOfParameters)]) fullValVar = np.asarray([float(valVariationValue[i]) if valVariationValue[i] != 'ci95' else np.nan for i in parentParameterId]) fullVarType = np.asarray([varType[i].lower() for i in parentParameterId]) lowerBounds = np.asarray([None]*len(fullListOfParameters)) upperBounds = np.asarray([None]*len(fullListOfParameters)) # set lower and upper bounds depending on varType (percent, range, rangefromci) lowerBounds[fullVarType == 'percent'] = (varValList[fullVarType == 'percent'] - varValList[fullVarType == 'percent'] * (fullValVar[fullVarType == 'percent'] / 100.)) upperBounds[fullVarType == 'percent'] = (varValList[fullVarType == 'percent'] + varValList[fullVarType == 'percent'] * (fullValVar[fullVarType == 'percent'] / 100.)) lowerBounds[fullVarType == 'range'] = (varValList[fullVarType == 'range'] - fullValVar[fullVarType == 'range']) upperBounds[fullVarType == 'range'] = (varValList[fullVarType == 'range'] + fullValVar[fullVarType == 'range']) lowerBounds[fullVarType == 'rangefromci'] = (varValList[fullVarType == 'rangefromci'] - ciValues[fullVarType == 'rangefromci']) upperBounds[fullVarType == 'rangefromci'] = (varValList[fullVarType == 'rangefromci'] + ciValues[fullVarType == 'rangefromci']) # create a sample of parameter values using scipy latin hypercube sampling sample = createSample(cfgProb, varParList) # create a full sample including those thickness values for the potentially multiple features # however, the thickness values for one parameter (relTh or entTh or secondaryRelTh) should not # be independent for the different features within one parameter fullSample = np.zeros((int(cfgProb['PROBRUN']['nSample']), len(fullListOfParameters))) for idx, varPar in enumerate(fullListOfParameters): lB = [0]*len(varParList) uB = [1]*len(varParList) lB[parentParameterId[idx]] = lowerBounds[idx] uB[parentParameterId[idx]] = upperBounds[idx] parSample = qmc.scale(sample, lB, uB) fullSample[:, idx] = parSample[:, parentParameterId[idx]] # create dictionary with all the info thFromIni = cfgUtils.convertToCfgList(list(set(varParList).symmetric_difference(set(staParameter)))) paramValuesD = {'names': fullListOfParameters, 'values': fullSample, 'typeList': cfgProb['PROBRUN']['varParType'].split('|'), 'thFromIni': thFromIni, 'thVariationBasedOnFromShp': thReadFromShp, 'varParNamesInitial': varParList, 'releaseScenario': relF.stem} paramValuesDList.append(paramValuesD) return paramValuesDList
[docs]def createSample(cfgProb, varParList): """ create a sample of parameters Parameters ----------- cfgProb: configparser object configuration settings varParList: list list of parameters used for creating a sample Returns -------- sample: scipy object sample object of given dimension that can be adjusted to desired bounds """ # random generator initialized with seed randomGen = np.random.default_rng(cfgProb['PROBRUN'].getint('sampleSeed')) # create a sample of parameter values using scipy latin hypercube sampling if cfgProb['PROBRUN']['sampleMethod'].lower() == 'latin': sampler = qmc.LatinHypercube(d=len(varParList), seed=randomGen) sample = sampler.random(n=int(cfgProb['PROBRUN']['nSample'])) log.info('Parameter sample created using latin hypercube sampling') else: message = ('Sampling method: %s not a valid option' % cfgProb['PROBRUN']['sampleMethod']) log.error(message) raise AssertionError(message) return sample
[docs]def fetchThThicknessLists(varPar, inputSimFiles, releaseFile, ciRequired=False): """ fetch the desired thickness shp file info on thickness, id and ci values of all available features in shp file Parameters ----------- varPar: str name of thickness parameter inputSimFiles: dict dictionary with info in input data ciRequired: bool if True throw error if ci Values not provided Returns -------- thicknessFeatureNames: list list of names of thickness features thValues: list list of thickness values for all features ciValues: list list of ci values for all feature """ if varPar == 'relTh': thFile = [inputSimFiles['relFiles'][idx] for idx, relF in enumerate(inputSimFiles['relFiles']) if relF == releaseFile][0] elif varPar == 'entTh': thFile = inputSimFiles['entFile'] elif varPar == 'secondaryRelTh': thFile = inputSimFiles['secondaryReleaseFile'] infoDict = inputSimFiles[thFile.stem] thicknessFeatureNames = [varPar+str(id) for id in infoDict['id']] thValues = [float(th) for th in infoDict['thickness']] ciValues = [float(ci) if ci != 'None' else np.nan for ci in infoDict['ci95']] if np.nan in ciValues and ciRequired: msg = ('ci95 values required in shape file but not provided for %s' % varPar) log.error(msg) raise AssertionError(msg) return thValues, ciValues, thicknessFeatureNames
[docs]def createCfgFiles(paramValuesDList, comMod, cfg, cfgPath=''): """ create all config files required to run com Module from parameter variations using paramValues Parameters ----------- paramValuesDList: list list of dictionaries with parameter names and values (array of all sets of parameter values, one row per value set) multiple dictionaries if multiple release area scenarios and thFromShp comMod: com module computational module cfg: configparser object configuration settings cfgPath: str path where cfg files should be saved to Returns -------- cfgFiles: list list of cfg file paths for comMod including the updated values of the parameters to vary """ # get filename of module modName = str(pathlib.Path(comMod.__file__).stem) # create one cfgFile with one line of the parameter values from the full parameter variation cfgFiles = [] countS = 0 for paramValuesD in paramValuesDList: # read initial configuration cfgStart = fetchStartCfg(comMod, cfg) for count1, pVal in enumerate(paramValuesD['values']): for index, par in enumerate(paramValuesD['names']): cfgStart['GENERAL'][par] = str(pVal[index]) cfgStart['VISUALISATION']['scenario'] = str(count1) cfgStart['INPUT']['thFromIni'] = paramValuesD['thFromIni'] if 'releaseScenario' in paramValuesD.keys(): cfgStart['INPUT']['releaseScenario'] = paramValuesD['releaseScenario'] cfgF = pathlib.Path(cfgPath, ('%d_%sCfg.ini' % (countS, modName))) with open(cfgF, 'w') as configfile: cfgStart.write(configfile) # append file path to list of cfg files cfgFiles.append(cfgF) countS = countS + 1 return cfgFiles
[docs]def fetchStartCfg(comMod, cfgProb): """ fetch start configuration of comMod if onlyDefault use default comModCfg.ini and if false check if there is a local_comModCfg.ini Parameters ----------- comMod: computational module module where configuration is read from cfgProb: configparser object configuration settings of probAna with collection_comMod_override section Returns -------- cfgStart: configparser object configuration object of comMod """ # get filename of module modName = str(pathlib.Path(comMod.__file__).stem) modP = (pathlib.Path(comMod.__file__).resolve().parent).stem # fetch comMod config cfgStart = cfgUtils.getModuleConfig(comMod, fileOverride='', toPrint=False, onlyDefault=cfgProb['%s_%s_override' % (modP, modName)].getboolean('defaultConfig')) # override with parameters set in in the cfgProb comMod_override section cfgStart, cfgProb = cfgHandling.applyCfgOverride(cfgStart, cfgProb, comMod, addModValues=False) return cfgStart
[docs]def fetchProbConfigs(cfg): """ fetch configurations of prob run in order to filter simulations e.g. to create probability maps for different scenarios Parameters ----------- cfg: configparser object configuration setting, here used: samplingStrategy, varParList Returns -------- probConfigs: dict dictionary with one key per config and a dict per key with parameter and value """ probConfigs = {'includeAll': {}} if cfg.getint('samplingStrategy') == 2: for par in cfg['varParList'].split('|'): probConfigs['include' + par] = {'scenario': par} log.info('Probability maps are created for full parameter variation and for %s separately' % cfg['varParList']) else: log.info('Probability map is created for full parameter variation') return probConfigs