38 Commits

Author SHA1 Message Date
Nikhil Rao
0028c69c52 Merged in development (pull request #28)
Citation update

Approved-by: Michael Wiltberger
2025-12-12 16:40:35 +00:00
Nikhil Rao
c85793d3c2 Merged in citation (pull request #27)
Citation update

Approved-by: Michael Wiltberger
2025-12-12 16:39:19 +00:00
cookieenick
13a0ab933a Citation update 2025-12-12 09:36:13 -07:00
Nikhil Rao
01b89c8a4a Merged in development (pull request #26)
Development
2025-12-10 16:24:41 +00:00
Nikhil Rao
21c2150138 Merged in dev_test_update (pull request #25)
Updated test mix generator
2025-12-08 17:08:33 +00:00
cookieenick
d71bce3602 version update 2025-12-08 08:21:24 -07:00
cookieenick
7ab2cad938 Updated test mix generator 2025-12-08 08:17:29 -07:00
ksorathia
f208b7e1c6 Merged in magick (pull request #19)
Killing annoying image magick warning messages

Approved-by: Nikhil Rao
2025-12-08 14:30:17 +00:00
Anthony Sciola
c7f38ab652 Merged in slimH5Update (pull request #21)
Updating slimH5 to properly copy root groups that are not Step (e.g. raiju's Grid group)

Approved-by: Nikhil Rao
2025-12-08 14:30:02 +00:00
Anthony M. Sciola
606356cb04 Updating slimH5 to properly copy root groups that are not Step (e.g. raiju's Grid group) 2025-11-18 11:55:04 -06:00
Kevin Pham
d3bc19400a Merged in pyspedasFix (pull request #20)
Compatibility with both pyspedas 1.5 and 2.0

Approved-by: Michael Wiltberger
2025-11-10 23:02:37 +00:00
phamkh
c57cc7692c Compatibility with both pyspedas 1.5 and 2.0 2025-11-10 15:19:47 -07:00
Kareem Sorathia
3a87802bfc Killing annoying image magick warning messages 2025-10-16 12:37:47 -04:00
Jeff
a0b57be640 Merged in dashboard (pull request #16)
Dashboard

Approved-by: Nikhil Rao
2025-10-02 19:20:36 +00:00
Jeffrey Garretson
db8dd45b6f Adding dashboard requirements 2025-10-02 00:52:25 -06:00
Jeffrey Garretson
bceea9fbea Merge branch 'development' into dashboard 2025-09-30 11:56:22 -06:00
Nikhil Rao
4e98d39444 Merged in external_contrib (pull request #18)
External contrib

Approved-by: Michael Wiltberger
2025-09-30 15:35:22 +00:00
Nikhil Rao
d6384b9352 Merged in external_contrib (pull request #17)
External contrib

Approved-by: Michael Wiltberger
2025-09-30 15:34:41 +00:00
Nikhil Rao
ecd934f5ea Updated kaipy version 2025-09-30 11:28:24 -04:00
Nikhil Rao
85f6611bf9 Merge pull request #1 from darrendezeeuw/master
Enable rotation of the colorbar for GAMERA slice plots
2025-09-30 11:24:51 -04:00
Michael Wiltberger
a37cceb647 Merged in dev_citation (pull request #14)
Dev citation

Approved-by: Eric Winter
Approved-by: Nikhil Rao
2025-09-16 15:03:48 +00:00
Jeffrey Garretson
e785513fe5 Final tests and fixes 2025-09-16 00:55:28 -06:00
Jeffrey Garretson
81baf6ab0b Merge branch 'development' into dashboard 2025-09-11 15:28:19 -06:00
Jeffrey Garretson
8cad0634ef First usable version of magedash 2025-09-11 15:27:30 -06:00
Darren De Zeeuw
6ba3da3661 Enable rotation of the colorbar for GAMERA slice plots 2025-09-04 16:06:30 -04:00
Jeffrey Garretson
854548878b Fixes, and making browser optional for compatibility 2025-09-03 13:48:23 -07:00
Jeffrey Garretson
671e487f22 First version of dashboard, and updates to comparison plotting code 2025-09-02 13:17:25 -06:00
wiltbemj
6f06e90a44 Adds citation file to generate authors for Zenodo DOIs 2025-08-27 07:17:04 -06:00
wiltbemj
f9277f60eb Add citation file for author list on Zenodo 2025-08-20 12:40:31 -06:00
Dong Lin
7910fd31c3 Merged in mndf (pull request #12)
Mndf

Approved-by: Michael Wiltberger
2025-07-31 14:54:51 +00:00
Dong Lin
b05090ec2d Merged development into mndf 2025-07-31 14:28:57 +00:00
ksorathia
c74f7fdc28 Merged in somethingfishy (pull request #13)
Fixing fish progress bars

Approved-by: Jeff
2025-07-29 13:39:54 +00:00
Kareem Sorathia
3354d5b0f5 More fish ... 2025-07-28 21:49:25 -04:00
Kareem Sorathia
0372758129 Repairing broken fish progress bars. I don't know who is responsible and for their sake I hope I don't find out 2025-07-28 21:11:51 -04:00
Dong Lin
711770aa19 Update contour line options. 2025-07-23 21:28:35 -06:00
Dong Lin
8c3f0520d9 optimize eflux, nflux, and eavg limit in plotting. 2025-07-23 12:38:00 -06:00
Dong Lin
40748ba545 minor optimization for plotting. 2025-07-23 11:43:29 -06:00
Dong Lin
3c505d5f2e Adding options to plot mono/diffuse on a linear/log green/blue colormap. 2025-07-23 10:26:57 -06:00
18 changed files with 1428 additions and 102 deletions

64
CITATION.cff Normal file
View File

@@ -0,0 +1,64 @@
cff-version: 1.2.0
message: "If you use this software, please cite it using the metadata below."
title: "Kaipy: Python package for analysis and visualization of MAGE and space weather modeling data"
version: "1.1.4"
date-released: 2025-12-03
doi: 10.5281/zenodo.15801040
repository-code: "https://github.com/JHUAPL/kaipy"
license: "BSD-3-Clause"
authors:
- family-names: Wiltberger
given-names: Michael
orcid: https://orcid.org/0000-0002-4844-3148
affiliation: "NSF National Center for Atmospheric Research"
- family-names: Bao
given-names: Shanshan
orcid: https://orcid.org/0000-0002-5209-3988
affiliation: "Rice University"
- family-names: Garretson
given-names: Jeffery
orcid: https://orcid.org/0000-0003-3805-9860
affiliation: "Johns Hopkins University Applied Physics Laboratory"
- family-names: McCubbin
given-names: Andrew
orcid: https://orcid.org/0000-0002-6222-3627
affiliation: "Johns Hopkins University Applied Physics Laboratory"
- family-names: Merkin
given-names: Slava
orcid: https://orcid.org/0000-0003-4344-5424
affiliation: "Johns Hopkins University Applied Physics Laboratory"
- family-names: Michael
given-names: Adam
orcid: https://orcid.org/0000-0003-2227-1242
affiliation: "Johns Hopkins University Applied Physics Laboratory"
- family-names: Pham
given-names: Kevin
orcid: https://orcid.org/0000-0001-5031-5519
affiliation: "NSF National Center for Atmospheric Research"
- family-names: Provornikova
given-names: Elena
orcid: https://orcid.org/0000-0001-8875-7478
affiliation: "Johns Hopkins University Applied Physics Laboratory"
- family-names: Rao
given-names: Nikhil
affiliation: "NSF National Center for Atmospheric Research"
orcid: https://orcid.org/0000-0003-2639-9892
- family-names: Sciola
given-names: Anthony
orcid: https://orcid.org/0000-0002-9752-9618
affiliation: "Johns Hopkins University Applied Physics Laboratory"
- family-names: Sorathia
given-names: Kareem
orcid: https://orcid.org/0000-0002-6011-5470
affiliation: "Johns Hopkins University Applied Physics Laboratory"
- family-names: Winter
given-names: Eric
orcid: https://orcid.org/0000-0001-5226-2107
affiliation: "Johns Hopkins University Applied Physics Laboratory"
keywords:
- "space weather"
- "MAGE"
- "kaipy"
- "geospace modeling"

View File

@@ -275,7 +275,7 @@ class GameraPipe(object):
for data,vID in coords:
datasets = []
with alive_bar(NrX,title=f"{titStr}/{vID}".ljust(kdefs.barLab),length=kdefs.barLen,bar=kdefs.barDef) as bar, \
with alive_bar(NrX,title=f"{titStr}/{vID}".ljust(kdefs.barLab),length=kdefs.barLen,bar=kdefs.barDef2) as bar, \
ProcessPoolExecutor(max_workers=self.nWorkers) as executor:
futures = [executor.submit(kh5.PullVarLoc, fIn, vID, loc=loc) for fIn, loc in files]
for future in as_completed(futures):
@@ -328,7 +328,7 @@ class GameraPipe(object):
else:
titStr = None
NrX = max(self.Nr,1)
with alive_bar(NrX,title=titStr,length=kdefs.barLen) as bar:
with alive_bar(NrX,title=titStr,length=kdefs.barLen,bar=kdefs.barDef2) as bar:
for (i,j,k) in itertools.product(range(self.Ri),range(self.Rj),range(self.Rk)):
iS = i *self.dNi
jS = j *self.dNj
@@ -454,7 +454,7 @@ class GameraPipe(object):
else:
titStr = ''
NrX = max(self.Nr,1)
with alive_bar(NrX,title=titStr.ljust(kdefs.barLab),length=kdefs.barLen,disable=not doVerb) as bar:
with alive_bar(NrX,title=titStr.ljust(kdefs.barLab),length=kdefs.barLen,bar=kdefs.barDef,disable=not doVerb) as bar:
for (i,j,k) in itertools.product(range(self.Ri),range(self.Rj),range(self.Rk)):
iS = i*self.dNi

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
@@ -652,7 +660,7 @@ def AddIonBoxes(gs, ion):
ion.init_vars('SOUTH')
ax = ion.plot('current', gs=gsRM[-dY-wXY:-dY, dX:dX+wXY], doInset=True)
def plotPlane(gsph, data, xyBds, Ax, AxCB, var='D', vMin=None, vMax=None, doDeco=True, cmap='viridis', doLog=False, midp=None):
def plotPlane(gsph, data, xyBds, Ax, AxCB, var='D', vMin=None, vMax=None, doDeco=True, cmap='viridis', doLog=False, midp=None, doVert=False):
"""
Base plotting routine for gsph plane
@@ -669,6 +677,7 @@ def plotPlane(gsph, data, xyBds, Ax, AxCB, var='D', vMin=None, vMax=None, doDeco
cmap (str, optional): The colormap to be used (default is 'viridis').
doLog (bool, optional): Whether to use logarithmic scaling for the colorbar (default is False).
midp (float, optional): The midpoint value for the colorbar (default is None).
doVert (bool, optional): Whether to display the colorbar vertically (default is False).
Returns:
None
@@ -685,12 +694,12 @@ def plotPlane(gsph, data, xyBds, Ax, AxCB, var='D', vMin=None, vMax=None, doDeco
vMax = np.max(np.abs([np.min(data), np.max(data)]))
vMin = -1.0 * vMax
vNorm = kv.genNorm(vMin, vMax=vMax, doLog=doLog, midP=midp)
kv.genCB(AxCB, vNorm, cbT=var, cM=cmap, Ntk=7)
kv.genCB(AxCB, vNorm, cbT=var, cM=cmap, Ntk=7, doVert=doVert)
Ax.pcolormesh(gsph.xxi, gsph.yyi, data, cmap=cmap, norm=vNorm)
kv.SetAx(xyBds, Ax)
return
def plotXY(gsph, nStp, xyBds, Ax, AxCB, var='D', vMin=None, vMax=None, doDeco=True, cmap='viridis', doLog=False, midp=None):
def plotXY(gsph, nStp, xyBds, Ax, AxCB, var='D', vMin=None, vMax=None, doDeco=True, cmap='viridis', doLog=False, midp=None, doVert=False):
"""
Plot a 2D slice of data on the XY plane of the gsph object.
@@ -707,19 +716,20 @@ def plotXY(gsph, nStp, xyBds, Ax, AxCB, var='D', vMin=None, vMax=None, doDeco=Tr
cmap (str, optional): The colormap to use for the plot (default is 'viridis').
doLog (bool, optional): Whether to use a logarithmic scale for the colorbar (default is False).
midp (float, optional): The midpoint value for the colorbar (default is None).
doVert (bool, optional): Whether to display the colorbar vertically (default is False).
Returns:
data: The 2D slice of data.
"""
data = gsph.EggSlice(var, nStp, doEq=True)
plotPlane(gsph, data, xyBds, Ax, AxCB, var, vMin=vMin, vMax=vMax, doDeco=doDeco, cmap=cmap, doLog=doLog, midp=midp)
plotPlane(gsph, data, xyBds, Ax, AxCB, var, vMin=vMin, vMax=vMax, doDeco=doDeco, cmap=cmap, doLog=doLog, midp=midp, doVert=doVert)
if doDeco:
kv.addEarth2D(ax=Ax)
Ax.set_xlabel('SM_X [Re]')
Ax.set_ylabel('SM-Y [Re]')
return data
def plotXZ(gsph, nStp, xzBds, Ax, AxCB, var='D', vMin=None, vMax=None, doDeco=True, cmap='viridis', doLog=False, midp=None):
def plotXZ(gsph, nStp, xzBds, Ax, AxCB, var='D', vMin=None, vMax=None, doDeco=True, cmap='viridis', doLog=False, midp=None, doVert=False):
"""
Plot a 2D slice of data in the XZ plane.
@@ -736,12 +746,13 @@ def plotXZ(gsph, nStp, xzBds, Ax, AxCB, var='D', vMin=None, vMax=None, doDeco=Tr
cmap (str): The colormap to use. Default is 'viridis'.
doLog (bool): Whether to use a logarithmic scale for the colorbar. Default is False.
midp (float): The midpoint value for the colorbar. Default is None.
doVert (bool, optional): Whether to display the colorbar vertically (default is False).
Returns:
data (numpy.ndarray): The 2D slice of data.
"""
data = gsph.EggSlice(var,nStp,doEq=False)
plotPlane(gsph,data,xzBds,Ax,AxCB,var,vMin=vMin,vMax=vMax,doDeco=doDeco,cmap=cmap,doLog=doLog,midp=midp)
plotPlane(gsph,data,xzBds,Ax,AxCB,var,vMin=vMin,vMax=vMax,doDeco=doDeco,cmap=cmap,doLog=doLog,midp=midp,doVert=doVert)
if (doDeco):
kv.addEarth2D(ax=Ax)
Ax.set_xlabel('SM_X [Re]')

View File

@@ -15,6 +15,7 @@ from matplotlib.colors import Normalize
from matplotlib.colors import SymLogNorm
from matplotlib.patches import Wedge
from matplotlib import ticker
import shutil
# Kaipy modules
from kaipy.kdefs import *
@@ -288,6 +289,13 @@ def savePic(fOut, dpiQ=300, doTrim=True, bLenX=20, bLenY=None, doClose=False, do
else:
plt.close(saveFigure)
#Checks to see if image magick is in the current path
def isMagick():
path = shutil.which('magick')
if (path is None):
return False
else:
return True
#Use imagemagick to trim whitespace off figure
#doEven: Guarantee even number of pixels in X/Y
@@ -309,7 +317,9 @@ def trimFig(fName, bLenX=20, bLenY=None, doEven=True):
if bLenY is None:
bLenY = bLenX
ComS = 'convert -trim -border %dx%d -bordercolor "#FFFFFF" ' % (bLenX, bLenY) + fName + ' ' + fName
if (not isMagick()):
return
ComS = 'magick ' + fName + ' -trim -border %dx%d -bordercolor "#FFFFFF" '%(bLenX,bLenY) + ' ' + fName
os.system(ComS)
if doEven:
@@ -355,7 +365,8 @@ def ShaveX(fName):
Returns:
fName file is cropped by one pixel on the right side.
"""
ComS = 'convert -crop -1+0 +repage ' + fName + ' ' + fName
ComS = 'magick %s -crop -1+0 +repage %s'%(fName,fName)
os.system(ComS)
def ShaveY(fName):
@@ -368,7 +379,8 @@ def ShaveY(fName):
Returns:
fName file is cropped by one pixel on the top.
"""
ComS = 'convert -crop +0-1 +repage ' + fName + ' ' + fName
ComS = 'magick %s -crop +0-1 +repage %s'%(fName,fName)
os.system(ComS)
#---------------------------------

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

@@ -111,7 +111,8 @@ vc_cgs = 2.99792458e10 # [cm/s] speed of light
barLen = 30
barLab = 30
#barDef = 'fish'
barDef = alive_progress.animations.bars.bar_factory(tip="><('>", chars='',background='')
barDef = alive_progress.animations.bars.bar_factory(tip="><('>", chars="",background="")
barDef2 = alive_progress.animations.bars.bar_factory('∙○⦿●',tip=" ><>")
#------
# I/O

View File

@@ -7,6 +7,8 @@ import h5py
import matplotlib.pyplot as plt
import matplotlib.cm as cm
import numpy as np
import kaipy.kaiViz as kv
import cmasher as cmr
# Kaipy modules
from kaipy.kdefs import RionE, REarth
@@ -19,6 +21,7 @@ mu0o4pi = 1.e-7 # mu0=4pi*10^-7 => mu0/4pi=10^-7
facMax = 1.5
facCM = cm.RdBu_r
flxCM = cm.inferno
eflxCM = plt.get_cmap('cmr.seaweed')
class remix:
"""
@@ -51,7 +54,7 @@ class remix:
calcFaceAreas(self, x, y)
Calculates the area of each face in a quad mesh.
plot(self, varname, ncontours=16, addlabels={}, gs=None, doInset=False, doCB=True, doCBVert=True, doGTYPE=False, doPP=False)
plot(self, varname, ncontours=16, addlabels={}, gs=None, doInset=False, doCB=True, doCBVert=True, doGTYPE=False, nPP=0, doMNDF=False)
Plots the specified variable.
efield(self, returnDeltas=False, ri=Ri*1e3)
@@ -115,7 +118,10 @@ class remix:
'Deflux': {'min': 0, 'max': 10.},
'Penergy': {'min': 0, 'max': 240},
'Pflux': {'min': 0, 'max': 1.e7},
'Peflux': {'min': 0, 'max': 1.}
'Peflux': {'min': 0, 'max': 1.},
'beta': {'min':0.0, 'max':0.5},
'deltae': {'min':0, 'max':20},
'amtype': {'min':0, 'max':3}
}
def get_data(self, h5file, step):
@@ -171,6 +177,9 @@ class remix:
self.variables['sigmah']['data'] = self.ion['Hall conductance ' + h]
self.variables['energy']['data'] = self.ion['Average energy ' + h]
self.variables['flux']['data'] = self.ion['Number flux ' + h]
self.variables['beta']['data'] = self.ion['RCM beta '+h]
self.variables['deltae']['data'] = self.ion['Mono potential drop '+h]
self.variables['amtype']['data'] = self.ion['Auroral model type '+h]
if 'RCM grid type ' + h in self.ion.keys():
self.variables['gtype']['data'] = self.ion['RCM grid type ' + h]
if 'RCM plasmasphere density ' + h in self.ion.keys():
@@ -201,6 +210,9 @@ class remix:
self.variables['sigmah']['data'] = self.ion['Hall conductance ' + h][:, ::-1]
self.variables['energy']['data'] = self.ion['Average energy ' + h][:, ::-1]
self.variables['flux']['data'] = self.ion['Number flux ' + h][:, ::-1]
self.variables['beta']['data'] = self.ion['RCM beta '+h][:, ::-1]
self.variables['deltae']['data'] = self.ion['Mono potential drop '+h][:, ::-1]
self.variables['amtype']['data'] = self.ion['Auroral model type '+h][:, ::-1]
if 'RCM grid type ' + h in self.ion.keys():
self.variables['gtype']['data'] = self.ion['RCM grid type ' + h][:, ::-1]
if 'RCM plasmasphere density ' + h in self.ion.keys():
@@ -305,7 +317,7 @@ class remix:
# TODO: define and consolidate allowed variable names
def plot(self, varname, ncontours=16, addlabels={}, gs=None, doInset=False, doCB=True, doCBVert=True, doGTYPE=False, doPP=False):
def plot(self, varname, ncontours=16, addlabels={}, gs=None, doInset=False, doCB=True, doCBVert=True, doGTYPE=False, nPP=0, doMNDF=False):
"""
Plot the specified variable on a polar grid.
@@ -318,7 +330,8 @@ class remix:
doCB (bool): Whether to show the colorbar (default: True).
doCBVert (bool): Whether to show the colorbar vertically (default: True).
doGTYPE (bool): Whether to overplot grid type contours (default: False).
doPP (bool): Whether to overplot polar cap boundary contours (default: False).
nPP (real): plasmaspheric number density contour (default: 0 and not shown).
doMNDF (bool): Whether to plot mono/diffuse using gree/blue colorbar (default: False).
Returns:
ax (AxesSubplot): The AxesSubplot object containing the plot.
@@ -412,7 +425,13 @@ class remix:
LW = 0.75
alpha = 1
tOff = np.pi / 2.
ax.contour(tc + tOff, rc, tmp, levels=con_level, colors=con_color, linewidths=LW, alpha=alpha)
contour = ax.contour(tc + tOff, rc, tmp, levels=con_level, colors=con_color, linewidths=LW, alpha=alpha)
if con_name=='npsp':
cl_con = 'red'
ax.clabel(contour, inline=False, fontsize=8, fmt=lambda val: f"Npsph={val:.1f}", colors=cl_con, use_clabeltext=True)
if con_name=='gtype':
cl_con = 'purple'
ax.clabel(contour, inline=False, fontsize=8, fmt=lambda val: f"GIMAG={val:.2f}", colors=cl_con, use_clabeltext=True)
if not self.Initialized:
sys.exit("Variables should be initialized for the specific hemisphere (call init_var) prior to plotting.")
@@ -431,6 +450,10 @@ class remix:
'energy' : r'Energy [keV]',
'flux' : r'Flux [1/cm$^2$s]',
'eflux' : r'Energy flux [erg/cm$^2$s]',
'gtype' : r'IMAG grid type',
'beta' : r'$\beta$',
'deltae' : r'$\Delta$E [kV]',
'amtype' : r'Auroral model type',
'ephi' : r'$E_\phi$ [mV/m]',
'etheta' : r'$E_\theta$ [mV/m]',
'efield' : r'|E| [mV/m]',
@@ -461,7 +484,7 @@ class remix:
upper = self.variables[varname]['data'].max()
# define number format string for min/max labels
if varname !='flux' and varname !='Pflux':
if varname not in ['flux','Dflux','Mflux','Pflux']:
if varname == 'jped':
format_str = '%.2f'
else:
@@ -472,7 +495,10 @@ class remix:
if (varname == 'potential') or (varname == 'current'):
cmap=facCM
elif varname in ['flux','energy','eflux','joule','Mflux','Menergy','Meflux','Dflux','Denergy','Deflux','Pflux','Penergy','Peflux']:
cmap=flxCM
if not doMNDF:
cmap=flxCM
else:
cmap=eflxCM
latlblclr = 'white'
elif (varname == 'velocity'):
cmap=cm.YlOrRd
@@ -480,6 +506,12 @@ class remix:
cmap=None #cm.RdBu_r#None # cm.hsv
elif (varname == 'magpert'):
cmap = cm.YlOrRd
elif (varname == 'beta'):
cmap=cm.inferno
elif (varname == 'gtype'):
cmap=cm.magma_r
elif (varname == 'deltae'):
cmap=cm.viridis
else:
cmap=None # default is used
@@ -518,7 +550,7 @@ class remix:
if varname == 'joule':
self.variables[varname]['data'] = self.joule()*1.e3 # convert to mW/m^2
variable = self.variables[varname]['data']
# variable = self.variables[varname]['data']
fig = plt.gcf()
@@ -528,7 +560,39 @@ class remix:
else:
ax=fig.add_subplot(polar=True)
p=ax.pcolormesh(theta+tOff,r,variable,cmap=cmap,vmin=lower,vmax=upper)
# p=ax.pcolormesh(theta+tOff,r,variable,cmap=cmap,vmin=lower,vmax=upper)
if not doMNDF:
# traditional colorbar limits and maps
variable = self.variables[varname]['data']
p=ax.pcolormesh(theta+tOff,r,variable,cmap=cmap,vmin=lower,vmax=upper)
else:
# for mono/diffuse, use different colorbar limits and maps
efxAmax = 10 # limit in the Mono-diffuse asymmetric colorbar.
numAmax = 1e9
engAmax = 20
idiff = self.variables['amtype']['data']<=2
if varname in ['eflux','Meflux','Deflux','thmeflux']:
variable = self.variables[varname]['data']
variable[idiff] = -abs(variable[idiff])
# use linear scale if below 0.1 mW/m^2
# set color bar limit at efxAmax mW/m^2
vQ = kv.genNorm(efxAmax,doSymLog=False,linP=0.01*efxAmax)
p=ax.pcolormesh(theta+tOff,r,variable,cmap=cmap,norm=vQ)
elif varname in ['flux','Mflux','Dflux','thmflux']:
variable = self.variables[varname]['data']
variable[idiff] = -abs(variable[idiff])
# use linear scale if below 1e7 #/cm^2/s
# set color bar limit at numAmax #/cm^2/s
vQ = kv.genNorm(numAmax,doSymLog=False,linP=0.01*numAmax)
p=ax.pcolormesh(theta+tOff,r,variable,cmap=cmap,norm=vQ)
elif varname in ['energy','Menergy','Denergy']:
variable = self.variables[varname]['data']
variable[idiff] = -abs(variable[idiff])
# use linear scale if below 0.1 keV
# set color bar limit at engAmax keV
vQ = kv.genNorm(engAmax,doSymLog=False,linP=0.01*engAmax)
p=ax.pcolormesh(theta+tOff,r,variable,cmap=cmap,norm=vQ)
if (not doInset):
if (doCB):
@@ -538,8 +602,21 @@ class remix:
cb=plt.colorbar(p,ax=ax,pad=0.1,shrink=0.85,orientation="horizontal")
cb.set_label(cblabels[varname])
ax.text(-75.*np.pi/180.,1.2*r.max(),('min: '+format_str+'\nmax: ' +format_str) %
if not doMNDF:
ax.text(-75.*np.pi/180.,1.2*r.max(),('min: '+format_str+'\nmax: ' +format_str) %
(variable.min() ,variable.max()))
else:
if varname in ['flux','Mflux','Dflux']:
cticks = cb.get_ticks()
cticklab = [str('{:6.1e}'.format(abs(tick))) for tick in cticks]
cb.set_ticklabels(cticklab)
if varname in ['eflux','Meflux','Deflux','energy','Menergy','Denergy']:
cticks = cb.get_ticks()
cticklab = [str('{:.1f}'.format(abs(tick))) for tick in cticks]
cb.set_ticklabels(cticklab)
if varname in ['gtype']:
cb.set_ticks([0,1])
cb.set_ticklabels(['MHD','IMAG'])
lines, labels = plt.thetagrids((0.,90.,180.,270.),hour_labels)
lines, labels = plt.rgrids(circles,lbls,fontsize=8,color=latlblclr)
@@ -550,8 +627,18 @@ class remix:
# ax.axis([0,2*np.pi,0,r.max()],'tight')
ax.axis([0,2*np.pi,0,r.max()])
if (not doInset):
ax.text(-75.*np.pi/180.,1.2*r.max(),('min: '+format_str+'\nmax: ' +format_str) %
(variable.min() ,variable.max()))
if doMNDF and varname in ['eflux','Meflux','Deflux','flux','Mflux','Dflux','energy','Menergy','Denergy']:
mono=variable.copy()
diff=variable.copy()
mono[ idiff]=0.0
diff[~idiff]=0.0
# print('mono min/max:',mono.min(),mono.max())
# print('diff min/max:',diff.min(),diff.max())
ax.text(-77.*np.pi/180.,1.1*r.max(),('Diff max: '+format_str) % (-diff.min()))
ax.text( 75.*np.pi/180.,1.1*r.max(),('Mono max: '+format_str) % ( mono.max()))
else:
ax.text(-75.*np.pi/180.,1.2*r.max(),('min: '+format_str+'\nmax: ' +format_str) % (variable.min() ,variable.max()))
if varname in ['eflux','Meflux','Deflux','Peflux']:
ax.text(75.*np.pi/180.,1.3*r.max(),('GW: '+format_str) % power)
if (varname == 'current'):
@@ -561,9 +648,11 @@ class remix:
if varname=='current':
potential_overplot(doInset)
if doGTYPE and varname=='eflux':
boundary_overplot('gtype',[0.01,0.99],'green',doInset)
if doPP and varname=='eflux':
boundary_overplot('npsp',[10],'cyan',doInset)
cl_con = 'purple'
boundary_overplot('gtype',[0.5],cl_con,doInset)
if nPP>0.0 and varname=='eflux':
cl_con = 'red'
boundary_overplot('npsp',[nPP],cl_con,doInset)
return ax
# mpl.rcParams['contour.negative_linestyle'] = 'solid'

View File

@@ -56,9 +56,10 @@ def createfile(iH5,fOut):
sQ = str(Q)
#Don't include stuff that starts with "Step"
if "Step" not in sQ and cacheName not in sQ:
oH5.create_dataset(sQ,data=iH5[sQ])
if cacheName in sQ:
oH5.create_group(sQ)
if isinstance(iH5[sQ], h5py.Group):
oH5.copy(iH5[sQ], oH5)
else:
oH5.create_dataset(sQ,data=iH5[sQ])
return oH5
@@ -172,6 +173,7 @@ def main():
#Add the cache after steps, select the same steps for the cache that are contained in the
#Ns:Ne:Nsk start,end,stride
if cacheName in iH5.keys():
oH5.create_group(cacheName)
for Q in iH5[cacheName].keys():
sQ = str(Q)
@@ -201,4 +203,4 @@ def main():
oH5.close()
if __name__ == "__main__":
main()
main()

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 = []
@@ -284,7 +314,7 @@ def main():
#Loop over sub-range
titstr = "Comparing '%s' to '%s'"%(fdir1,fdir2)
with alive_bar(Nt,title=titstr.ljust(kdefs.barLab),length=kdefs.barLen,disable=doVerb) as bar:
with alive_bar(Nt,title=titstr.ljust(kdefs.barLab),length=kdefs.barLen,bar=kdefs.barDef,disable=doVerb) as bar:
#with concurrent.futures.ThreadPoolExecutor(max_workers=Nth) as executor:
with concurrent.futures.ProcessPoolExecutor(max_workers=Nth) as executor:
m = multiprocessing.Manager()
@@ -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

@@ -122,8 +122,12 @@ def create_command_line_parser():
help="Show RCM grid type in the eflx plot (default: %(default)s)"
)
parser.add_argument(
'-PP', action='store_true', default=False,
help="Show plasmapause (10/cc) in the eflx/nflx plot (default: %(default)s)"
'--nPP', type=float, metavar="nPP", default=0,
help="Plasmasphere density contour to show (default: %(default)/cc not shown)"
)
parser.add_argument(
'-MNDF', action='store_true', default=False,
help="Show mono-diffuse eflx/nflx in linear/log green/blue colormap (default: %(default)s)"
)
parser.add_argument(
'-vid', action='store_true', default=False,
@@ -156,7 +160,8 @@ def makePlot(i, remixFile, nStp, args, varDict):
spacecraft = args.spacecraft
verbose = args.verbose
do_GTYPE = args.GTYPE
do_PP = args.PP
nPP = args.nPP
do_MNDF = args.MNDF
do_vid = args.vid
do_overwrite = args.overwrite
do_hash = not args.nohash
@@ -233,12 +238,12 @@ def makePlot(i, remixFile, nStp, args, varDict):
axs[0] = ion.plot('current', gs=gs[0, 0])
axs[1] = ion.plot('sigmap', gs=gs[0, 1])
axs[2] = ion.plot('sigmah', gs=gs[0, 2])
axs[3] = ion.plot('joule', gs=gs[1, 0])
axs[4] = ion.plot('energy', gs=gs[1, 1])
if do_nflux:
axs[5] = ion.plot('flux', gs=gs[1, 2],doGTYPE=do_GTYPE,doPP=do_PP)
axs[3] = ion.plot('flux', gs=gs[1, 0],doGTYPE=do_GTYPE,nPP=nPP,doMNDF=do_MNDF)
else:
axs[5] = ion.plot('eflux', gs=gs[1, 2],doGTYPE=do_GTYPE,doPP=do_PP)
axs[3] = ion.plot('joule', gs=gs[1, 0])
axs[4] = ion.plot('energy', gs=gs[1, 1],doGTYPE=do_GTYPE,nPP=nPP,doMNDF=do_MNDF)
axs[5] = ion.plot('eflux', gs=gs[1, 2],doGTYPE=do_GTYPE,nPP=nPP,doMNDF=do_MNDF)
# If requested, plot the magnetic footprints for the specified
# spacecraft.
@@ -314,7 +319,8 @@ def main():
spacecraft = args.spacecraft
verbose = args.verbose
do_GTYPE = args.GTYPE
do_PP = args.PP
nPP = args.nPP
do_MNDF = args.MNDF
do_vid = args.vid
do_overwrite = args.overwrite
do_hash = not args.nohash

View File

@@ -5,8 +5,13 @@ import re
# Third-party modules
import numpy
from cdasws import CdasWs
from pyspedas import kyoto
from pytplot import get_data
try:
# Try the newer import path first (for recent pyspedas versions)
from pyspedas.projects import kyoto
except ImportError:
# Fall back to the older import path
from pyspedas import kyoto
# Kaipy modules
import kaipy.transform

View File

@@ -7,7 +7,7 @@ include-package-data = true
[project]
name = "kaipy"
version = "1.1.2"
version = "1.1.4"
authors = [
{name = "Eric Winter", email = "eric.winter@jhuapl.edu"},
]

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

@@ -2,7 +2,7 @@ from setuptools import setup, find_packages
setup(
name='kaipy',
version='1.1.2',
version='1.1.4',
description='Python software for CGS MAGE and other Kaiju models',
author='Kaiju team',
author_email='wiltbemj@ucar.edu',
@@ -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'
]
}
)

View File

@@ -47,6 +47,12 @@ def write_mix_h5(file_path,mjds=None):
grp.create_dataset("Average energy SOUTH", data=np.zeros((Nlat, Nlon)))
grp.create_dataset("Number flux NORTH", data=np.zeros((Nlat, Nlon)))
grp.create_dataset("Number flux SOUTH", data=np.zeros((Nlat, Nlon)))
grp.create_dataset("RCM beta NORTH", data=np.zeros((Nlat, Nlon)))
grp.create_dataset("RCM beta SOUTH", data=np.zeros((Nlat, Nlon)))
grp.create_dataset("Mono potential drop NORTH", data=np.zeros((Nlat, Nlon)))
grp.create_dataset("Mono potential drop SOUTH", data=np.zeros((Nlat, Nlon)))
grp.create_dataset("Auroral model type NORTH", data=np.zeros((Nlat, Nlon)))
grp.create_dataset("Auroral model type SOUTH", data=np.zeros((Nlat, Nlon)))
return file_path

View File

@@ -7,7 +7,7 @@ import argparse
from argparse import RawTextHelpFormatter
import kaipy.remix.remix as remix
from kaipy.gamera.msphViz import AddSizeArgs, GetSizeBds, PlotEqErrAbs, PlotEqErrRel, PlotLogicalErrAbs, PlotLogicalErrRel, CalcTotalErrAbs, CalcTotalErrRel, PlotEqB, PlotMerid, PlotJyXZ, PlotEqEphi, PlotMPI, AddIonBoxes, plotPlane, plotXY, plotXZ
from kaipy.gamera.msphViz import AddSizeArgs, GetSizeBds, PlotErrAbs, PlotErrRel, PlotLogicalErrAbs, PlotLogicalErrRel, CalcTotalErrAbs, CalcTotalErrRel, PlotEqB, PlotMerid, PlotJyXZ, PlotEqEphi, PlotMPI, AddIonBoxes, plotPlane, plotXY, plotXZ
@pytest.fixture
@@ -26,22 +26,22 @@ def test_GetSizeBds():
result = GetSizeBds(args)
assert result == [-100.0, 20.0, -60.0, 60.0]
def test_PlotEqErrAbs(gamera_pipe):
def test_PlotErrAbs(gamera_pipe):
fig, ax = plt.subplots()
gsphP = gamera_pipe
gsphO = gamera_pipe
fieldNames = ['Bz']
xyBds = [-100, 100, -100, 100]
result = PlotEqErrAbs(gsphP, gsphO, 0, xyBds, ax, fieldNames)
result = PlotErrAbs(gsphP, gsphO, 0, xyBds, ax, fieldNames)
assert isinstance(result, np.ndarray)
def test_PlotEqErrRel(gamera_pipe):
def test_PlotErrRel(gamera_pipe):
fig, ax = plt.subplots()
gsphP = gamera_pipe
gsphO = gamera_pipe
fieldNames = ['Bz']
xyBds = [-100, 100, -100, 100]
result = PlotEqErrRel(gsphP, gsphO, 0, xyBds, ax, fieldNames)
result = PlotErrRel(gsphP, gsphO, 0, xyBds, ax, fieldNames)
assert isinstance(result, np.ndarray)
def test_PlotLogicalErrAbs(gamera_pipe):