Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

update DFA path runscript [ana5; runscripts] #1039

Open
wants to merge 8 commits into
base: master
Choose a base branch
from

Conversation

leon-wagner
Copy link
Contributor

@leon-wagner leon-wagner commented Oct 22, 2024

With the goal of addressing #848, as well as rework of the runScript

Summary of changes:

  • restructured runComputeDFAPath script to make it compatible with QGIS connector, moved script to /avaframe

  • the --runDFA flag can now be set to run com1 to generate results for path generation (this was previously handled by a True/False argument within the runScript). The avaFolder may now also be added to the run command.

  • settings that are used to override com1DFA run were moved to DFAPath cfg as overrides. changed some of the overrides, path is now essentially generated from a default null com1 run with standard friction and particle settings. path is now also generated from fields as default, instead of from particles.

  • if splitpoint is not found with the set angle (default 20 degrees), the splitpoint is now generated at the top of the path, instead of not creating one. changed plot output accordingly.

  • added missing discrete color levels for travel angle, so now colors in the path output plot are generated with the same levels.

  • color map for travel angles is now Crameri:nuuk (previously was undefined and a mix of Crameri:batlow and Crameri:lapaz)

  • fixes above remove 2 user warnings in DFAPath script log, one with legend, one with cmap

  • fix DFA path generation returns no coordinates for splitpoint #1038, here we should choose one of the commits to merge

To do:

  • update documentation with changes

@leon-wagner leon-wagner linked an issue Oct 22, 2024 that may be closed by this pull request
@pep8speaks
Copy link

pep8speaks commented Nov 11, 2024

Hello @leon-wagner! Thanks for updating this PR.

Line 624:121: E501 line too long (127 > 120 characters)

Line 420:52: E203 whitespace before ':'
Line 418:48: E203 whitespace before ':'
Line 417:48: E203 whitespace before ':'

Line 212:121: E501 line too long (121 > 120 characters)
Line 188:5: E265 block comment should start with '# '
Line 185:5: E265 block comment should start with '# '
Line 184:5: E265 block comment should start with '# '
Line 181:121: E501 line too long (139 > 120 characters)
Line 172:121: E501 line too long (122 > 120 characters)
Line 162:5: E303 too many blank lines (2)
Line 157:5: E265 block comment should start with '# '
Line 156:5: E265 block comment should start with '# '
Line 131:5: E303 too many blank lines (2)
Line 73:121: E501 line too long (131 > 120 characters)
Line 71:74: E251 unexpected spaces around keyword / parameter equals
Line 71:72: E251 unexpected spaces around keyword / parameter equals
Line 69:93: E251 unexpected spaces around keyword / parameter equals
Line 69:91: E251 unexpected spaces around keyword / parameter equals
Line 69:59: W605 invalid escape sequence '\m'
Line 30:121: E501 line too long (125 > 120 characters)

Line 979:121: E501 line too long (138 > 120 characters)
Line 977:19: E712 comparison to False should be 'if cond is False:' or 'if not cond:'
Line 948:21: E712 comparison to False should be 'if cond is False:' or 'if not cond:'
Line 805:121: E501 line too long (124 > 120 characters)
Line 689:37: E203 whitespace before ':'
Line 688:37: E203 whitespace before ':'
Line 537:15: E711 comparison to None should be 'if cond is not None:'
Line 501:71: E203 whitespace before ':'
Line 501:48: E203 whitespace before ':'
Line 495:71: E203 whitespace before ':'
Line 495:48: E203 whitespace before ':'
Line 482:121: E501 line too long (121 > 120 characters)

Line 130:20: E231 missing whitespace after ','
Line 114:121: E501 line too long (132 > 120 characters)
Line 105:5: E265 block comment should start with '# '
Line 85:70: E127 continuation line over-indented for visual indent

Comment last updated at 2024-11-28 10:33:20 UTC

@leon-wagner leon-wagner added the enhancement New feature or request label Nov 11, 2024
@leon-wagner leon-wagner linked an issue Nov 11, 2024 that may be closed by this pull request
@leon-wagner leon-wagner marked this pull request as ready for review November 11, 2024 12:28
@leon-wagner leon-wagner self-assigned this Nov 11, 2024
@fso42 fso42 self-requested a review November 19, 2024 14:34
@fso42 fso42 added this to the Version 1.10 milestone Nov 19, 2024
@leon-wagner leon-wagner force-pushed the dfaPathQGis branch 2 times, most recently from ea6318f to 83f2042 Compare November 21, 2024 11:58
…on.py

- com1 overrides moved from runScript to ini

- new --runDFA flag logic

- path is generated from fields by default (resType changed accordingly)

- moved runScript to main avaframe folder (for QGIS)

- clean DFAPath output folder in avadir before generating path (necessary for QGIS, so if script is run multiple times, paths that are previously generated are not returned to QGIS)
- removed coulomb friction and other com1 overrides, path is now generated from standard run

- added option to add velocity info when FV is saved
… instead of not at all (avoids issues with QGIS)

- adjusted corresponding error message

- accordingly adjusted plot generation to exclude splitPoints set at the top
- add missing discrete color levels for Travel Angle and changed it from a mix of lapaz and batlow to nuuk color map
- grey out faulty legend plotting line thereby removing user warning: “no artists found with label”… in log and removes empty legend in top right corner of birds eye view panel
- more descriptive runDFA flag comment in runScript
- set dt to 1
…t or other)

- adjustment to writePoint2SHPfile to account for pytest. tested and it still fixes the addressed problem.
Copy link

codeclimate bot commented Nov 28, 2024

Code Climate has analyzed commit fdf3c6b and detected 1 issue on this pull request.

Here's the issue category breakdown:

Category Count
Complexity 1

The test coverage on the diff in this pull request is 45.8% (50% is the threshold).

This pull request will bring the total coverage in the repository to 69.6% (0.0% change).

View more on Code Climate.

@@ -623,6 +627,7 @@ def saveSplitAndPath(avalancheDir, simDFrow, splitPoint, avaProfileMass, dem):
if inProjection.is_file():
shutil.copy(inProjection, splitAB.with_suffix('.prj'))
log.info('Saved split point to: %s', splitAB)
return str(pathAB), str(splitAB)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please keep the return as a pathlib object

Comment on lines 45 to 60
pathFromPart = False

# If path from fields, True to add velocity info (needs FV saved)
addVelocityInfo = False

[com1DFA_com1DFA_override]
# use default com1DFA config as base configuration (True)
# if False and local is available use local
defaultConfig = True
# and override following parameters
# Especially one needs to save multiple intermediate time steps in order to
# compute the path. One also needs to save pta, and the correct particle or fields variables.
tSteps = 0:5
resType = pta|FT|FM
#resType = pta|particles
simTypeList = null
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please see my PM about testing this. Then lets decide which one to take based on the results

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-> new one

# compute the path. One also needs to save pta, and the correct particle or fields variables.
tSteps = 0:5
resType = pta|FT|FM
#resType = pta|particles
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If you want to keep this as the alternative option, then please make a comment above the parameter and describe the options

@@ -146,15 +146,15 @@ def generateCom1DFAPathPlot(avalancheDir, cfgPath, avaProfileMass, dem, paraboli
label='_bottom extension', lw=2, path_effects=[pe.Stroke(linewidth=3, foreground='g'), pe.Normal()])
ax1.plot(avaProfileMass['x'][indStart:indEnd+1], avaProfileMass['y'][indStart:indEnd+1], '-y.', zorder=20,
label='_Center of mass path', lw=2, path_effects=[pe.Stroke(linewidth=3, foreground='k'), pe.Normal()])
if splitPoint != '':
if not splitPoint.get('isTopSplitPoint', False):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is really hard to read, since you are negative testing for a negative. Please change to is... True

ax1.plot(splitPoint['x'], splitPoint['y'], 'P', color='r', label='_Split point', zorder=20)
ax1.set_xlabel('x [m]')
ax1.set_ylabel('y [m]')
ax1.axis('equal')
ax1.set_ylim([rowsMin, rowsMax])
ax1.set_xlim([colsMin, colsMax])
l1 = ax1.legend()
l1.set_zorder(40)
#ax1.legend()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove if not needed

@@ -172,7 +172,7 @@ def generateCom1DFAPathPlot(avalancheDir, cfgPath, avaProfileMass, dem, paraboli
label='_Center of mass path slope', lw=2, path_effects=[pe.Stroke(linewidth=3, foreground='k'), pe.Normal()])
minY, _ = ax3.get_ylim()
minX, _ = ax3.get_xlim()
if splitPoint != '':
if not splitPoint.get('isTopSplitPoint', False):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same here with the double negative

@@ -181,11 +181,11 @@ def generateCom1DFAPathPlot(avalancheDir, cfgPath, avaProfileMass, dem, paraboli
ax3.text(minX, cfgPath.getfloat('slopeSplitPoint'), "%.0f°" % (cfgPath.getfloat('slopeSplitPoint')), color='r', ha="left", va="bottom")
ax3.axhline(y=10, color='0.8', linewidth=1, linestyle='-.', label='_Beta angle (10°)')
ax3.text(minX, 10, "%.0f°" % (10), color='0.8', ha="left", va="bottom")
# ax3.axvline(x=avaProfileMass['s'][indStart], color='b', linewidth=1, linestyle='-.', label='Start of profile')
# ax3.axvline(x=avaProfileMass['s'][indEnd], color='g', linewidth=1, linestyle='-.', label='End of profile')
#ax3.axvline(x=avaProfileMass['s'][indStart], color='b', linewidth=1, linestyle='-.', label='Start of profile')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

also remove these comments if they are not needed

ax3.set_xlabel('$s_{xy}$ [m]')
ax3.set_ylabel('slope angle [°]')
ax3.legend()
#ax3.legend()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

same here

@@ -199,7 +199,7 @@ def generateCom1DFAPathPlot(avalancheDir, cfgPath, avaProfileMass, dem, paraboli
label='Center of mass path / profile / angle',
lw=1, path_effects=[pe.Stroke(linewidth=3, foreground='k'), pe.Normal()])
ax2.plot(sPara, zPara, '-k', label='Parabolic fit')
if splitPoint != '':
if not splitPoint.get('isTopSplitPoint', False):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

negative negative again

Comment on lines +76 to +130
if runDFAModule:
# Clean input directory of old work and output files from module
initProj.cleanModuleFiles(avalancheDir, com1DFA, deleteOutput=True)
# create and read the default com1DFA config (no local is read)
com1DFACfg = cfgUtils.getModuleConfig(com1DFA, fileOverride='', modInfo=False, toPrint=False,
onlyDefault=cfgDFAPath['com1DFA_com1DFA_override'].getboolean(
'defaultConfig'))
# and override with settings from DFAPath config
com1DFACfg, cfgDFAPath = cfgHandling.applyCfgOverride(com1DFACfg, cfgDFAPath, com1DFA,
addModValues=False)
outDir = pathlib.Path(avalancheDir, 'Outputs', 'ana5Utils', 'DFAPath')
fU.makeADir(outDir)
# write configuration to file
com1DFACfgFile = outDir / 'com1DFAPathGenerationCfg.ini'
with open(com1DFACfgFile, 'w') as configfile:
com1DFACfg.write(configfile)
# call com1DFA and perform simulations
dem, plotDict, reportDictList, simDF = com1DFA.com1DFAMain(cfgMain, cfgInfo=com1DFACfgFile)
else:
# read simulation dem
demOri = gI.readDEM(avalancheDir)
dem = com1DFA.setDEMoriginToZero(demOri)
dem['originalHeader'] = demOri['header'].copy()
# load DFA results (use runCom1DFA to generate these results for example)
# here is an example with com1DFA but another DFA computational module can be used
# as long as it produces some particles or FV, FT and FM results
# create dataFrame of results (read DFA data)
simDF, _ = cfgUtils.readAllConfigurationInfo(avalancheDir)

#Clean DFAPath output in avalanche directory
initProj.cleanModuleFiles(avalancheDir, DFAPath, deleteOutput=True)

for simName, simDFrow in simDF.iterrows():
log.info('Computing avalanche path from simulation: %s', simName)
pathFromPart = cfgDFAPath['PATH'].getboolean('pathFromPart')
resampleDistance = cfgDFAPath['PATH'].getfloat('nCellsResample') * dem['header']['cellsize']
# get the mass average path
avaProfileMass, particlesIni = DFAPath.generateAveragePath(avalancheDir, pathFromPart, simName, dem,
addVelocityInfo=cfgDFAPath['PATH'].getboolean('addVelocityInfo'))
avaProfileMass, _ = gT.prepareLine(dem, avaProfileMass, distance=resampleDistance, Point=None)
avaProfileMass['indStartMassAverage'] = 1
avaProfileMass['indEndMassAverage'] = np.size(avaProfileMass['x'])
# make the parabolic fit
parabolicFit = DFAPath.getParabolicFit(cfgDFAPath['PATH'], avaProfileMass, dem)
# here the avaProfileMass given in input is overwritten and returns only an x, y, z extended profile
avaProfileMass = DFAPath.extendDFAPath(cfgDFAPath['PATH'], avaProfileMass, dem, particlesIni)
# resample path and keep track of start and end of mass averaged part
avaProfileMass = DFAPath.resamplePath(cfgDFAPath['PATH'], dem, avaProfileMass)
# get split point
splitPoint = DFAPath.getSplitPoint(cfgDFAPath['PATH'], avaProfileMass, parabolicFit)
# make analysis and generate plots
_ = outCom3Plots.generateCom1DFAPathPlot(avalancheDir, cfgDFAPath['PATH'], avaProfileMass, dem,
parabolicFit, splitPoint, simName)
# now save the path and split point as shapefiles
massAvgPath,splitPoint = DFAPath.saveSplitAndPath(avalancheDir, simDFrow, splitPoint, avaProfileMass, dem)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now we are moving this file away from an example runscript, I think we should move this part as a function to the ana5 DFAPathGeneration.py file (similar to com1DFAMain).
-> keep the runscript smaller
-> have a function to be called directly

@fso42 fso42 changed the title update DFA path runscript (ana5Utils) update DFA path runscript [ana5U; runscripts] Nov 29, 2024
@fso42 fso42 changed the title update DFA path runscript [ana5U; runscripts] update DFA path runscript [ana5; runscripts] Nov 29, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

Successfully merging this pull request may close these issues.

DFA path generation returns no coordinates for splitpoint Add automatic path to connector as extra
3 participants