Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 1 addition & 5 deletions .qlty/qlty.toml
Original file line number Diff line number Diff line change
Expand Up @@ -104,12 +104,8 @@ threshold = 10
enabled = true

[smells.function_complexity]
threshold = 10
enabled = true

[smells.duplication]
threshold = 15
enabled = true
threshold = 20

[[source]]
name = "default"
Expand Down
5 changes: 3 additions & 2 deletions avaframe/ana1Tests/rotationTest.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
# Local imports
# import config and init tools
from avaframe.in3Utils import fileHandlerUtils as fU
from avaframe.in3Utils import cfgUtils
from avaframe.log2Report import generateReport as gR
from avaframe.in3Utils import geoTrans as gT
import avaframe.in2Trans.rasterUtils as IOf
Expand Down Expand Up @@ -63,7 +64,7 @@ def mainRotationTest(avalancheDir, energyLineTestCfg, com1DFACfg, dem, simDF, re
fU.makeADir(outDir)
# get reference angle
simName = simDF.loc[refSimRowHash, 'simName']
relName = (simName.split('_'))[0]
relName = cfgUtils.parseSimName(simName)["releaseName"]
thetaRef = float(relName[3:])
for rowSimHash in simDF.index:
# rotate results to be able to proceed to the aimec analysis
Expand Down Expand Up @@ -119,7 +120,7 @@ def rotateDFAResults(avalancheDir, simDF, rowSimHash, resTypeList, thetaRef, com
"""
log.debug('Rotating simulation: %s' % rowSimHash)
simName = simDF.loc[rowSimHash, 'simName']
relName = (simName.split('_'))[0]
relName = cfgUtils.parseSimName(simName)["releaseName"]
theta = float(relName[3:])
simDF.loc[rowSimHash, 'relAngle'] = theta
thetaRot = theta - thetaRef
Expand Down
14 changes: 10 additions & 4 deletions avaframe/ana3AIMEC/dfa2Aimec.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

# local modules
from avaframe.in3Utils import fileHandlerUtils as fU
from avaframe.in3Utils import cfgUtils

# create local logger
# change log level in calling module to DEBUG to see log messages
Expand Down Expand Up @@ -52,12 +53,17 @@ def getMBInfo(avaDir, inputsDF, comMod, simName=''):
message = 'No mass log file found in directory %s' % (str(dir))
log.error(message)
raise FileNotFoundError(message)
mbNames = sorted(set(mbFiles), key=lambda s: (str(s).split("_")[1], str(s).split("_")[2], str(s).split("_")[4]))
# Sort mass balance files by simName components using parseSimName
mbNames = sorted(set(mbFiles), key=lambda f: (
# Extract simName by removing 'mass_' prefix (5 characters) and parse components
cfgUtils.parseSimName(f.stem[5:])["simHash"],
cfgUtils.parseSimName(f.stem[5:])["modName"],
cfgUtils.parseSimName(f.stem[5:])["simType"]
))

for mFile in mbNames:
name = mFile.stem
nameParts = name.split('_')
simName = ('_'.join(nameParts[1:]))
# Extract simName from filename (remove 'mass_' prefix)
simName = mFile.stem[5:]
simRowHash = inputsDF[inputsDF['simName'] == simName].index[0]
inputsDF.loc[simRowHash, 'massBal'] = mFile
log.debug('Added to inputsDF[massBal] %s' % (mFile))
Expand Down
12 changes: 9 additions & 3 deletions avaframe/ana4Stats/probAna.py
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ def probAnalysis(avaDir, cfg, modName, parametersDict="", inputDir="", probConf=
fU.makeADir(outDir)

# fetch all result files and filter simulations according to parametersDict
if modName.lower() == "com1dfa":
if modName.lower() in ["com1dfa", "com5snowslide", "com6rockavalanche", "com8motpsa", "com9motvoellmy"]:
simNameList = cfgHandling.filterSims(avaDir, parametersDict, specDir=inputDir, simDF=simDFActual)
filtering = True
else:
Expand Down Expand Up @@ -688,7 +688,13 @@ def createSampleFromConfig(avaDir, cfgProb, comMod):
_, thReadFromShp = checkParameterSettings(cfgStart, varParList)

modNameString = str(pathlib.Path(comMod.__file__).stem)
if modNameString.lower() in ["com1dfa", "com8motpsa"]:
if modNameString.lower() in [
"com1dfa",
"com5snowslide",
"com6rockavalanche",
"com8motpsa",
"com9motvoellmy",
]:
# check if thickness parameters are actually read from shp file
_, thReadFromShp = checkParameterSettings(cfgStart, varParList)
else:
Expand Down Expand Up @@ -1079,7 +1085,7 @@ def createCfgFiles(paramValuesDList, comMod, cfg, cfgPath=""):
cfgStart[section][par] = str(pVal[index])
else:
cfgStart["GENERAL"][par] = str(pVal[index])
if modName.lower() == "com1dfa":
if modName.lower() in ["com1dfa", "com5snowslide", "com6rockavalanche"]:
cfgStart["VISUALISATION"]["scenario"] = str(count1)
cfgStart["INPUT"]["thFromIni"] = paramValuesD["thFromIni"]
if "releaseScenario" in paramValuesD.keys():
Expand Down
2 changes: 1 addition & 1 deletion avaframe/ana5Utils/DFAPathGeneration.py
Original file line number Diff line number Diff line change
Expand Up @@ -690,7 +690,7 @@ def saveSplitAndPath(avalancheDir, simDFrow, splitPoint, avaProfileMass, dem):
avaProfileMass['y'] = avaProfileMass['y'] + dem['originalHeader']['yllcenter']
# get projection from release shp layer
simName = simDFrow['simName']
relName = simName.split('_')[0]
relName = cfgUtils.parseSimName(simName)["releaseName"]
inProjection = pathlib.Path(avalancheDir, 'Inputs', 'REL', relName + '.prj')
# save profile in Inputs
pathAB = pathlib.Path(avalancheDir, 'Outputs', 'ana5Utils', 'DFAPath', 'massAvgPath_%s_AB_aimec' % simName)
Expand Down
113 changes: 100 additions & 13 deletions avaframe/com1DFA/com1DFA.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,14 @@
"""

import copy
import inspect
import logging
import math
import os
import pathlib
import pickle
import platform
import re
import time
from datetime import datetime
from functools import partial
Expand Down Expand Up @@ -651,7 +653,9 @@ def prepareInputData(inputSimFiles, cfg):
)
else:
secRelRasterPath = pathlib.Path(
cfg["GENERAL"]["avalancheDir"], "Inputs", cfg["INPUT"]["secondaryRelThFile"]
cfg["GENERAL"]["avalancheDir"],
"Inputs",
cfg["INPUT"]["secondaryRelThFile"],
)
secrelRasterDict = IOf.readRaster(secRelRasterPath)
secondaryReleaseLine = {
Expand Down Expand Up @@ -1313,7 +1317,10 @@ def initializeSimulation(cfg, outDir, demOri, inputSimLines, logName):
)
log.info(
"Entrainment area raster derived from %s saved to %s"
% (inputSimLines["entResInfo"]["entThFileType"], str(outDir / "entrainmentRaster"))
% (
inputSimLines["entResInfo"]["entThFileType"],
str(outDir / "entrainmentRaster"),
)
)

# surfacic entrainment mass available (unit kg/m²)
Expand Down Expand Up @@ -2118,7 +2125,6 @@ def DFAIterate(cfg, particles, fields, dem, inputSimLines, outDir, cuSimName, si
# Update dtSave to remove the initial timestep we just saved
dtSave = updateSavingTimeStep(dtSaveOriginal, cfgGen, t)


# export particles properties for visulation
if cfg["VISUALISATION"].getboolean("writePartToCSV"):
particleTools.savePartToCsv(
Expand Down Expand Up @@ -2569,7 +2575,15 @@ def writeMBFile(infoDict, avaDir, logName):


def computeEulerTimeStep(
cfg, particles, fields, zPartArray0, dem, tCPU, frictType, resistanceType, reportAreaInfo
cfg,
particles,
fields,
zPartArray0,
dem,
tCPU,
frictType,
resistanceType,
reportAreaInfo,
):
"""compute next time step using an euler forward scheme

Expand Down Expand Up @@ -2735,7 +2749,11 @@ def releaseSecRelArea(cfg, particles, fields, dem, zPartArray0, reportAreaInfo):
else:
secondaryReleaseInfo["rasterData"] = secRelRaster
secRelParticles = initializeParticles(
cfg, secondaryReleaseInfo, dem, relThField=secRelRaster, thName="secondaryRel"
cfg,
secondaryReleaseInfo,
dem,
relThField=secRelRaster,
thName="secondaryRel",
)
# release secondary release area by just appending the particles
log.info(
Expand Down Expand Up @@ -3023,7 +3041,11 @@ def exportFields(
outFile = outDirPeak / dataName
useCompression = cfg["EXPORTS"].getboolean("useCompression")
IOf.writeResultToRaster(
dem["originalHeader"], resField, outFile, flip=True, useCompression=useCompression
dem["originalHeader"],
resField,
outFile,
flip=True,
useCompression=useCompression,
)
log.debug(
"Results parameter: %s has been exported to Outputs/peakFiles for time step: %.2f "
Expand All @@ -3042,10 +3064,74 @@ def exportFields(
outFile = outDirPeakAll / dataName
useCompression = cfg["EXPORTS"].getboolean("useCompression")
IOf.writeResultToRaster(
dem["originalHeader"], resField, outFile, flip=True, useCompression=useCompression
dem["originalHeader"],
resField,
outFile,
flip=True,
useCompression=useCompression,
)


def _findWrapperModuleInStack():
"""Find wrapper module name by inspecting the call stack.

Searches the call stack for wrapper modules (e.g., com5SnowSlide, com6RockAvalanche)
that are calling into com1DFA functions.

Returns
-------
str or None
Wrapper module name if found (e.g., "com6RockAvalanche"), None otherwise
"""
for frameInfo in inspect.stack():
frameModule = frameInfo.frame.f_globals.get("__name__", "")
# Look for modules matching comN{Name}.comN{Name} pattern
# but not com1DFA.com1DFA itself
if frameModule.startswith("avaframe.com"):
# Extract the last component (the actual module name)
moduleName = frameModule.split(".")[-1]
# Check if it matches the comN pattern (starts with "com" followed by a digit)
if re.match(r"^com\d+", moduleName) and not frameModule.endswith("com1DFA.com1DFA"):
return moduleName
return None


def getModuleNames(module):
"""Extract module name and short form by checking the call stack for wrapper modules.

This function checks if we're being called from a wrapper module (e.g., com5SnowSlide,
com6RockAvalanche) by inspecting the call stack. If found, it uses the wrapper's name.
Otherwise, it falls back to the passed module parameter.

Parameters
----------
module: module
The module object to extract names from (fallback if no wrapper is found)

Returns
-------
tuple
(modName, modNameShort) where modName is the full name (e.g., "com1DFA")
and modNameShort is the short form (e.g., "com1")
"""
# Check for wrapper module in call stack
modName = _findWrapperModuleInStack()

# Fall back to passed module if no wrapper found
if not modName:
modName = module.__name__.split(".")[-1]

# Special case: com7Regional should be treated as com1DFA
if modName == "com7Regional":
modName = "com1DFA"

# Extract short name (com1, com8, etc.)
shortModMatch = re.match(r"^(com\d+)", modName)
modNameShort = shortModMatch.group(1) if shortModMatch else modName

return modName, modNameShort


def prepareVarSimDict(standardCfg, inputSimFiles, variationDict, simNameExisting="", module=com1DFA):
"""Prepare a dictionary with simulations that shall be run with varying parameters following the variation dict

Expand All @@ -3070,8 +3156,8 @@ def prepareVarSimDict(standardCfg, inputSimFiles, variationDict, simNameExisting
simType and contains full configuration configparser object for simulation run
"""

# extract the name of the module
modName = module.__name__.split(".")[-1]
# extract the full module name and short form (e.g., "com1DFA" -> "com1")
modName, modNameShort = getModuleNames(module)

# get list of simulation types that are desired
if "simTypeList" in variationDict:
Expand Down Expand Up @@ -3176,7 +3262,7 @@ def prepareVarSimDict(standardCfg, inputSimFiles, variationDict, simNameExisting
cfgSim["INPUT"]["secondaryRelThFile"] = pathToSecRel
inputSimFiles["entResInfo"]["secondaryRelRemeshed"] = remeshedSecRel

if modName == "com1DFA":
if modName in ["com1DFA", "com5SnowSlide", "com6RockAvalanche"]:
# check if spatialVoellmy is chosen that friction fields have correct extent
if cfgSim["GENERAL"]["frictModel"].lower() == "spatialvoellmy":
dem = IOf.readRaster(pathlib.Path(cfgSim["GENERAL"]["avalancheDir"], "Inputs", pathToDem))
Expand Down Expand Up @@ -3271,7 +3357,7 @@ def prepareVarSimDict(standardCfg, inputSimFiles, variationDict, simNameExisting

pathToDemFull = pathlib.Path(cfgSim["GENERAL"]["avalancheDir"], "Inputs", pathToDem)

if modName == "com1DFA":
if modName in ["com1DFA", "com5SnowSlide", "com6RockAvalanche"]:
# if frictModel is samosATAuto compute release vol
if cfgSim["GENERAL"]["frictModel"].lower() == "samosatauto":
relVolume = fetchRelVolume(rel, cfgSim, pathToDemFull, inputSimFiles["secondaryRelFile"])
Expand All @@ -3287,7 +3373,7 @@ def prepareVarSimDict(standardCfg, inputSimFiles, variationDict, simNameExisting
# set frictModelIndicator, this needs to happen AFTER checkCfgFrictModel
frictIndi = com1DFATools.setFrictTypeIndicator(cfgSim)

elif modName == "com8MoTPSA":
elif modName in ["com8MoTPSA", "com9MoTVoellmy"]:
relVolume = fetchRelVolume(rel, cfgSim, pathToDemFull, inputSimFiles["secondaryRelFile"])

# set Volume class identificator
Expand All @@ -3304,6 +3390,7 @@ def prepareVarSimDict(standardCfg, inputSimFiles, variationDict, simNameExisting
[
relNameSim,
simHash,
modNameShort,
defID,
frictIndi or volIndi,
row._asdict()["simTypeList"],
Expand All @@ -3321,7 +3408,7 @@ def prepareVarSimDict(standardCfg, inputSimFiles, variationDict, simNameExisting
"relFile": rel,
"cfgSim": cfgSimObject,
}
if modName == "com1DFA":
if modName in ["com1DFA", "com5SnowSlide", "com6RockAvalanche"]:
# write configuration file, dont need to write cfg file for com8MoTPSA (does this later when creating rcf file)
cfgUtils.writeCfgFile(
cfgSimObject["GENERAL"]["avalancheDir"],
Expand Down
2 changes: 1 addition & 1 deletion avaframe/com1DFA/com1DFATools.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,7 @@ def compareSimCfgToDefaultCfgCom1DFA(simCfg, module=com1DFA):

# sphKernelSize is set during runtime, make sure it is not reported
# as changed if default is set to meshCellSize
if modName == "com1DFA":
if modName in ["com1DFA", "com5SnowSlide", "com6RockAvalanche"]:
if defCfg["GENERAL"]["sphKernelRadius"] == "meshCellSize":
if simCfg["GENERAL"]["sphKernelRadius"] == simCfg["GENERAL"]["meshCellSize"]:
excludeItems.append("root['GENERAL']['sphKernelRadius']")
Expand Down
Loading
Loading