Merged in dashboard (pull request #16)

Dashboard

Approved-by: Nikhil Rao
This commit is contained in:
Jeff
2025-10-02 19:20:36 +00:00
7 changed files with 1191 additions and 53 deletions

View File

@@ -25,18 +25,18 @@ mpiCol = "deepskyblue"
jMax = 10.0 #Max current for contours
eMax = 5.0 #Max current for contours
eMax = 5.0 #Max current for contours
#Default pressure colorbar
vP = kv.genNorm(vMin=1.0e-2,vMax=10.0,doLog=True)
szStrs = ['small','std','big','bigger','fullD','dm']
szBds = {}
szBds["std"] = [-40.0 ,20.0,2.0]
szBds["big"] = [-100.0,20.0,2.0]
szBds["std"] = [-40.0 ,20.0,2.0]
szBds["big"] = [-100.0,20.0,2.0]
szBds["bigger"] = [-200.0,25.0,2.0]
szBds["fullD"] = [-300.0,30.0,3.0] # full domain for double res
szBds["small"] = [-10.0 , 5.0,2.0]
szBds["dm"] = [-30.0 ,10.0,40.0/15.0]
szBds["fullD"] = [-300.0,30.0,3.0] # full domain for double res
szBds["small"] = [-10.0 , 5.0,2.0]
szBds["dm"] = [-30.0 ,10.0,40.0/15.0]
#Add different size options to argument
def AddSizeArgs(parser):
@@ -74,10 +74,10 @@ def GetSizeBds(args):
return xyBds
#Plot absolute error in the requested, or given, equatorial field
def PlotEqErrAbs(gsphP, gsphO, nStp, xyBds, Ax, fieldNames, AxCB=None, doClear=True, doDeco=True, vMin=1e-9, vMax=1e-4, doLog=True, doVerb=True):
#Plot absolute error in the requested, or given, equatorial or meridional field
def PlotErrAbs(gsphP, gsphO, nStp, xyBds, Ax, fieldNames, AxCB=None, doClear=True, doDeco=True, vMin=1e-9, vMax=1e-4, doLog=True, doVerb=True, doEq=True):
"""
PlotEqErrAbs function plots the absolute error between two gsph objects.
PlotErrAbs function plots the absolute error between two gsph objects.
Args:
gsphP (gsph): The gsph object representing the predicted values.
@@ -93,6 +93,7 @@ def PlotEqErrAbs(gsphP, gsphO, nStp, xyBds, Ax, fieldNames, AxCB=None, doClear=T
vMax (float, optional): The maximum value for the colorbar. (default: 1e-4)
doLog (bool, optional): Whether to use logarithmic scale for the colorbar. (default: True)
doVerb (bool, optional): Whether to print verbose output. (default: True)
doEq (bool, optional): Whether to plot equatorial or meridional (default: True)
Returns:
dataAbs (ndarray): The absolute error data.
@@ -118,8 +119,8 @@ def PlotEqErrAbs(gsphP, gsphO, nStp, xyBds, Ax, fieldNames, AxCB=None, doClear=T
Ax.clear()
dataAbs = None
for fn in fieldNames:
dataP = gsphP.EggSlice(fn, nStp, doEq=True, doVerb=doVerb)
dataO = gsphO.EggSlice(fn, nStp, doEq=True, doVerb=doVerb)
dataP = gsphP.EggSlice(fn, nStp, doEq=doEq, doVerb=doVerb)
dataO = gsphO.EggSlice(fn, nStp, doEq=doEq, doVerb=doVerb)
if dataAbs is None:
dataAbs = np.square(dataO - dataP)
else:
@@ -132,13 +133,16 @@ def PlotEqErrAbs(gsphP, gsphO, nStp, xyBds, Ax, fieldNames, AxCB=None, doClear=T
if doDeco:
kv.addEarth2D(ax=Ax)
Ax.set_xlabel('SM-X [Re]')
Ax.set_ylabel('SM-Y [Re]')
if doEq:
Ax.set_ylabel('SM-Y [Re]')
else:
Ax.set_ylabel('SM-Z [Re]')
return dataAbs
#Plot relative error in the requested, or given, equatorial field
def PlotEqErrRel(gsphP, gsphO, nStp, xyBds, Ax, fieldNames, AxCB=None, doClear=True, doDeco=True, vMin=1e-16, vMax=1, doLog=True, doVerb=True):
#Plot relative error in the requested, or given, equatorial or meridional field
def PlotErrRel(gsphP, gsphO, nStp, xyBds, Ax, fieldNames, AxCB=None, doClear=True, doDeco=True, vMin=1e-16, vMax=1, doLog=True, doVerb=True, doEq=True):
"""
PlotEqErrRel function plots the relative error between two gsph objects.
PlotErrRel function plots the relative error between two gsph objects.
Args:
gsphP (gsph): The gsph object representing the predicted values.
@@ -154,6 +158,7 @@ def PlotEqErrRel(gsphP, gsphO, nStp, xyBds, Ax, fieldNames, AxCB=None, doClear=T
vMax (float, optional): The maximum value for the colorbar. (default: 1)
doLog (bool, optional): Whether to use logarithmic scale for the colorbar. (default: True)
doVerb (bool, optional): Whether to print verbose output. (default: True)
doEq (bool, optional): Whether to plot equatorial or meridional (default: True)
Returns:
dataRel (ndarray): The relative error data.
@@ -180,8 +185,8 @@ def PlotEqErrRel(gsphP, gsphO, nStp, xyBds, Ax, fieldNames, AxCB=None, doClear=T
dataAbs = None
dataBase = None
for fn in fieldNames:
dataP = gsphP.EggSlice(fn, nStp, doEq=True, doVerb=doVerb)
dataO = gsphO.EggSlice(fn, nStp, doEq=True, doVerb=doVerb)
dataP = gsphP.EggSlice(fn, nStp, doEq=doEq, doVerb=doVerb)
dataO = gsphO.EggSlice(fn, nStp, doEq=doEq, doVerb=doVerb)
if dataAbs is None:
dataBase = np.square(dataP)
dataAbs = np.square(dataO - dataP)
@@ -200,7 +205,10 @@ def PlotEqErrRel(gsphP, gsphO, nStp, xyBds, Ax, fieldNames, AxCB=None, doClear=T
if doDeco:
kv.addEarth2D(ax=Ax)
Ax.set_xlabel('SM-X [Re]')
Ax.set_ylabel('SM-Y [Re]')
if doEq:
Ax.set_ylabel('SM-Y [Re]')
else:
Ax.set_ylabel('SM-Z [Re]')
return dataRel
#Plot absolute error along the requested logical axis

31
kaipy/kaixml.py Normal file
View File

@@ -0,0 +1,31 @@
# Standard modules
import os
import json
import datetime
# Third-party modules
import xml.etree.ElementTree as ET
def getXmlElement(E, name, caseInsensitive=True):
if E is None:
return None
for element in E.iter():
if caseInsensitive:
if element.tag.casefold() == name.casefold():
return element
else:
if element.tag == name:
return element
return None
def getXmlAttribute(E, name, caseInsensitive=True):
if E is None:
return None
for attr_name,attr_value in E.attrib.items():
if caseInsensitive:
if attr_name.casefold() == name.casefold():
return attr_value
else:
if attr_name == name:
return attr_value
return None

View File

@@ -43,14 +43,14 @@ def makeMovie(frame_dir,movie_name):
return
cmd = [
ffmpegExe, "-nostdin", "-i", frame_pattern,
"-vcodec", "libx264", "-crf", "14", "-profile:v", "high", "-pix_fmt", "yuv420p",
movie_file,"-y"
ffmpegExe, "-nostdin", "-i", frame_pattern,
"-vcodec", "libx264", "-crf", "14", "-profile:v", "high", "-pix_fmt", "yuv420p",
movie_file,"-y"
]
subprocess.run(cmd, check=True)
# python allows changes by reference to the errTimes,errListRel, errListAbs lists
def makeImage(i,gsph1,gsph2,tOut,doVerb,xyBds,fnList,oDir,errTimes,errListRel,errListAbs,cv,dataCounter, vO, figSz, noMPI, noLog, fieldNames):
def makeImage(i,gsph1,gsph2,tOut,doVerb,doEq,logAx,xyBds,fnList,oDir,errTimes,errListRel,errListAbs,cv,dataCounter, vO, figSz, noMPI, noLog, fieldNames):
if doVerb:
print("Making image %d"%(i))
#Convert time (in seconds) to Step #
@@ -77,23 +77,45 @@ def makeImage(i,gsph1,gsph2,tOut,doVerb,xyBds,fnList,oDir,errTimes,errListRel,er
AxB2.clear()
#plot upper left msph error
mviz.PlotEqErrRel(gsph1,gsph2,nStp,xyBds,AxTL,fnList,AxCB=AxCT,doVerb=doVerb)
AxTL.set_title("Equatorial Slice of Relative Error")
mviz.PlotErrRel(gsph1,gsph2,nStp,xyBds,AxTL,fnList,AxCB=AxCT,doVerb=doVerb,doEq=doEq)
if doEq:
AxTL.set_title("Equatorial Slice of Relative Error")
else:
AxTL.set_title("Meridional Slice of Relative Error")
#plot upper right k-axis error
mviz.PlotLogicalErrRel(gsph1,gsph2,nStp,AxTR,fnList,2,doVerb=doVerb)
AxTR.set_title("Per-Cell Relative Error along K-Axis")
#plot upper right cumulative logical error
mviz.PlotLogicalErrRel(gsph1,gsph2,nStp,AxTR,fnList,logAx,doVerb=doVerb)
if logAx == 0:
AxTR.set_title("Per-Cell Relative Error along I-Axis")
elif logAx == 1:
AxTR.set_title("Per-Cell Relative Error along J-Axis")
else:
AxTR.set_title("Per-Cell Relative Error along K-Axis")
if (not noMPI):
#plot I-MPI decomp on logical plot
if(gsph2.Ri > 1):
if(gsph2.Ri > 1 and logAx != 0):
for im in range(gsph2.Ri):
i0 = im*gsph2.dNi
AxTR.plot([i0, i0],[0, gsph2.Nj],"deepskyblue",linewidth=0.25,alpha=0.5)
if logAx == 1:
AxTR.plot([i0, i0],[0, gsph2.Nk],"deepskyblue",linewidth=0.25,alpha=0.5)
else:
AxTR.plot([i0, i0],[0, gsph2.Nj],"deepskyblue",linewidth=0.25,alpha=0.5)
#plot J-MPI decomp on logical plot
if (gsph2.Rj>1):
if (gsph2.Rj>1 and logAx != 1):
for jm in range(1,gsph2.Rj):
j0 = jm*gsph2.dNj
AxTR.plot([0, gsph2.Ni],[j0, j0],"deepskyblue",linewidth=0.25,alpha=0.5)
if logAx == 0:
AxTR.plot([j0, j0],[0, gsph2.Nk],"deepskyblue",linewidth=0.25,alpha=0.5)
else:
AxTR.plot([0, gsph2.Ni],[j0, j0],"deepskyblue",linewidth=0.25,alpha=0.5)
#plot K-MPI decomp on logical plot
if (gsph2.Rk>1 and logAx != 2):
for km in range(1,gsph2.Rk):
k0 = km*gsph2.dNk
if logAx == 0:
AxTR.plot([0, gsph2.Nj],[k0, k0],"deepskyblue",linewidth=0.25,alpha=0.5)
else:
AxTR.plot([0, gsph2.Ni],[k0, k0],"deepskyblue",linewidth=0.25,alpha=0.5)
#plot bottom line plot
etval = tOut[i]/60.0
@@ -168,15 +190,17 @@ def create_command_line_parser():
fdir2 = os.getcwd()
ftag2 = "msphere"
oDir = "vid2D"
ts = 0 #[min]
te = 200 #[min]
ts = 0.0 #[min]
te = 200.0 #[min]
dt = 0.0 #[sec] 0 default means every timestep
logAx = 2 # axis to accumulate logical error along
Nth = 1 #Number of threads
noMPI = False # Don't add MPI tiling
noLog = False
fieldNames = "Bx, By, Bz"
doVerb = False
skipMovie = False
merid = False
MainS = """Creates simple multi-panel figure for Gamera magnetosphere run
Left Panel - Residual vertical magnetic field
@@ -189,14 +213,16 @@ def create_command_line_parser():
parser.add_argument('-d2',type=str,metavar="directory",default=fdir2,help="Directory to read second dataset from (default: %(default)s)")
parser.add_argument('-id2',type=str,metavar="runid",default=ftag2,help="RunID of second dataset (default: %(default)s)")
parser.add_argument('-o',type=str,metavar="directory",default=oDir,help="Subdirectory to write to (default: %(default)s)")
parser.add_argument('-ts' ,type=int,metavar="tStart",default=ts,help="Starting time [min] (default: %(default)s)")
parser.add_argument('-te' ,type=int,metavar="tEnd" ,default=te,help="Ending time [min] (default: %(default)s)")
parser.add_argument('-dt' ,type=int,metavar="dt" ,default=dt,help="Cadence [sec] (default: %(default)s)")
parser.add_argument('-ts' ,type=float,metavar="tStart",default=ts,help="Starting time [min] (default: %(default)s)")
parser.add_argument('-te' ,type=float,metavar="tEnd" ,default=te,help="Ending time [min] (default: %(default)s)")
parser.add_argument('-dt' ,type=float,metavar="dt" ,default=dt,help="Cadence [sec] (default: %(default)s)")
parser.add_argument('-logAx',type=int,metavar="logAx",default=logAx,help="Index of the axis to accumulate along in the upper-right plot (default: %(default)s)")
parser.add_argument('-Nth' ,type=int,metavar="Nth",default=Nth,help="Number of threads to use (default: %(default)s)")
parser.add_argument('-f',type=str,metavar="fieldnames",default=fieldNames,help="Comma-separated fields to plot (default: %(default)s)")
parser.add_argument('-linear',action='store_true', default=noLog,help="Plot linear line plot instead of logarithmic (default: %(default)s)")
parser.add_argument('-v',action='store_true', default=doVerb,help="Do verbose output (default: %(default)s)")
parser.add_argument('-skipMovie',action='store_true', default=skipMovie,help="Skip automatic movie generation afterwards (default: %(default)s)")
parser.add_argument('-merid',action='store_true', default=merid,help="Plot meridional instead of equatorial slice (default: %(default)s)")
#parser.add_argument('-nompi', action='store_true', default=noMPI,help="Don't show MPI boundaries (default: %(default)s)")
@@ -209,15 +235,17 @@ def main():
fdir2 = os.getcwd()
ftag2 = "msphere"
oDir = "vid2D"
ts = 0 #[min]
te = 200 #[min]
ts = 0.0 #[min]
te = 200.0 #[min]
dt = 0.0 #[sec] 0 default means every timestep
logAx = 2
Nth = 1 #Number of threads
noMPI = False # Don't add MPI tiling
noLog = False
fieldNames = "Bx, By, Bz"
doVerb = False
skipMovie = False
doEq = True
parser = create_command_line_parser()
mviz.AddSizeArgs(parser)
@@ -228,14 +256,16 @@ def main():
ftag1 = args.id1
fdir2 = args.d2
ftag2 = args.id2
ts = args.ts
te = args.te
dt = args.dt
ts = args.ts
te = args.te
dt = args.dt
logAx = args.logAx
oSub = args.o
Nth = args.Nth
fieldNames = args.f
noLog = args.linear
doVerb = args.v
doEq = not args.merid
#noMPI = args.noMPI
fnList = [item.strip() for item in fieldNames.split(',')]
@@ -275,8 +305,8 @@ def main():
Nt = len(tOut)
vO = np.arange(0,Nt)
print("Writing %d outputs between minutes %d and %d"%(Nt,ts,te))
print("Using %d threads"%(Nth))
print(f"Writing {Nt} outputs between minutes {ts} and {te}")
print(f"Using {Nth} threads")
errTimes = []
errListRel = []
@@ -293,8 +323,8 @@ def main():
met = m.list(errTimes)
melr = m.list(errListRel)
mela = m.list(errListAbs)
#imageFutures = {executor.submit(makeImage,i,gsph1,gsph2,tOut,doVerb,xyBds,fnList,oDir,errTimes,errListRel,errListAbs,cv): i for i in range(0,Nt)}
imageFutures = {executor.submit(makeImage,i,gsph1,gsph2,tOut,doVerb,xyBds,fnList,oDir,met,melr,mela,cv,dataCounter,vO,figSz,noMPI,noLog,fieldNames): i for i in range(0,Nt)}
#imageFutures = {executor.submit(makeImage,i,gsph1,gsph2,tOut,doVerb,doEq,logAx,xyBds,fnList,oDir,errTimes,errListRel,errListAbs,cv): i for i in range(0,Nt)}
imageFutures = {executor.submit(makeImage,i,gsph1,gsph2,tOut,doVerb,doEq,logAx,xyBds,fnList,oDir,met,melr,mela,cv,dataCounter,vO,figSz,noMPI,noLog,fieldNames): i for i in range(0,Nt)}
for future in concurrent.futures.as_completed(imageFutures):
try:
retVal = future.result()
@@ -304,9 +334,9 @@ def main():
traceback.print_exc()
exit()
bar()
makeMovie(oDir,oSub)
if __name__ == "__main__":
main()
main()

View File

@@ -102,8 +102,8 @@ def main():
AxL.clear()
AxR.clear()
mviz.PlotEqErrRel(gsph1,gsph2,nStp,xyBds,AxL,fnList,AxCB=AxCL)
mviz.PlotEqErrAbs(gsph1,gsph2,nStp,xyBds,AxR,fnList,AxCB=AxCR)
mviz.PlotErrRel(gsph1,gsph2,nStp,xyBds,AxL,fnList,AxCB=AxCL)
mviz.PlotErrAbs(gsph1,gsph2,nStp,xyBds,AxR,fnList,AxCB=AxCR)
gsph1.AddTime(nStp,AxL,xy=[0.025,0.89],fs="x-large")
@@ -116,4 +116,4 @@ def main():
if __name__ == "__main__":
main()
main()

File diff suppressed because it is too large Load Diff

View File

@@ -4,11 +4,16 @@ cartopy
cdasws
cmasher
configparser
dash
dash_bootstrap_components
flask_caching
h5py
jupyterlab
matplotlib
pandas
progressbar
pyqt5
pyqtwebengine
pyspedas
pytest
slack_sdk
@@ -17,4 +22,4 @@ sphinx-rtd-theme
sphinxcontrib-autoprogram
sunpy
gfz-api-client
supermag-api
supermag-api

View File

@@ -25,11 +25,16 @@ setup(
'cdasws',
'cmasher',
'configparser',
'dash',
'dash_bootstrap_components',
'flask_caching',
'h5py',
'jupyterlab',
'matplotlib',
'pandas',
'progressbar',
'pyqt5',
'pyqtwebengine',
'pyspedas',
'pytest',
'slack_sdk',
@@ -91,6 +96,7 @@ setup(
'gamsphVid=kaipy.scripts.quicklook.gamsphVid:main',
'heliomovie=kaipy.scripts.quicklook.heliomovie:main',
'heliopic=kaipy.scripts.quicklook.heliopic:main',
'mageDash=kaipy.scripts.quicklook.mageDash:main',
'mixpic=kaipy.scripts.quicklook.mixpic:main',
'msphpic=kaipy.scripts.quicklook.msphpic:main',
'raijupic=kaipy.scripts.quicklook.raijupic:main',
@@ -99,8 +105,8 @@ setup(
'remixTimeSeries=kaipy.scripts.quicklook.remixTimeSeries:main',
'swpic=kaipy.scripts.quicklook.swpic:main',
'vizTrj=kaipy.scripts.quicklook.vizTrj:main',
'raijudst=kaipy.raiju.dst:main',
'raijum2m=kaipy.raiju.m2m:main'
'raijudst=kaipy.raiju.dst:main',
'raijum2m=kaipy.raiju.m2m:main'
]
}
)