3 import basic_plot_functions
as bpf
4 import binning_utils
as bu
5 import predefined_configs
as pconf
6 from collections.abc
import Iterable
7 from collections
import defaultdict
8 from copy
import deepcopy
11 import diag_utils
as du
14 import multiprocessing
as mp
16 from pathlib
import Path
17 import plot_utils
as pu
20 import stat_utils
as su
21 import StatisticsDatabase
as sdb
22 import var_utils
as vu
25 for x
in su.sampleableAggStats:
26 if x !=
'Count': bootStrapStats.append(x)
29 figureFileType =
'pdf'
35 return DiagSpace+
'_analyses'
41 def __init__(self, db, analysisType, diagnosticGroupings = {}):
70 for (varName, varUnits)
in zip(self.
varNamesvarNames, self.
dbdb.varUnitss):
72 if varUnits != vu.miss_s:
73 label = label+
' ('+varUnits+
')'
74 varLabels.append(label)
106 wd = CWD.split(
'/')[-1]
112 self.
myFigPathmyFigPath.mkdir(parents=
True, exist_ok=
True)
116 Format the binMethod for file naming
121 binMethodFile =
'_'+binMethod
123 binMethodFile = binMethod+
'_'
129 Format the diagnosticGroup for forecast analysisType's
131 fcDiagName = diagnosticGroup
132 if self.
fcTDeltasfcTDeltas[-1] > dt.timedelta(0):
133 fcDiagName = fcDiagName.replace(
'omm',
'omf')
134 fcDiagName = fcDiagName.replace(
'omb',
'omf')
135 fcDiagName = fcDiagName.replace(
'bmo',
'fmo')
136 fcDiagName = fcDiagName.replace(
'mmo',
'fmo')
137 fcDiagName = fcDiagName.replace(
'hmo',
'fmo')
138 fcDiagName = fcDiagName.replace(
'bak',
'fc')
142 allDiagnosticNames = None):
144 Define plotting attributes for the combination of diagnosticGroup and statName
146 ommDiagnostics = [
'omb',
'oma',
'omm',
'omf']
147 mmoDiagnostics = [
'bmo',
'amo',
'mmo',
'fmo',
'mmgfsan']
148 truncateDiagnostics = ommDiagnostics+mmoDiagnostics
149 diagnosticGroup_ = diagnosticGroup
150 for diag
in truncateDiagnostics:
151 if diag
in diagnosticGroup_:
152 diagnosticGroup_ = diag
155 if statName
in [
'Count']+du.CRStatNames:
156 statDiagLabel = statName
157 fcstatDiagLabel = statName
159 statDiagLabel = statName+
'('+diagnosticGroup_+
')'
160 fcstatDiagLabel = statName+
'('+fcDiagName+
')'
164 allDiagnosticNames_ = deepcopy(allDiagnosticNames)
165 if allDiagnosticNames_
is None:
166 cntrlDiagnosticName = diagnosticGroup_
167 allDiagnosticNames_ = [diagnosticGroup_]
169 cntrlDiagnosticName = allDiagnosticNames_[0]
171 for diag
in truncateDiagnostics:
172 if diag
in cntrlDiagnosticName:
173 cntrlDiagnosticName = diag
174 for idiag, adiag
in enumerate(allDiagnosticNames_):
176 allDiagnosticNames_[idiag] = diag
179 fcstatDiagDiffLabel = statName+
'('+fcDiagName+
'): [EXP - '+cntrlExpDiagnosticLabel+
']'
180 if statName ==
'Mean':
181 if diagnosticGroup_
in ommDiagnostics:
183 fcstatDiagDiffLabel = statName+
': ['+cntrlExpDiagnosticLabel+
' - EXP]'
184 if diagnosticGroup_
in mmoDiagnostics:
186 fcstatDiagDiffLabel = statName+
': [EXP - '+cntrlExpDiagnosticLabel+
']'
188 sciTicks = (statName ==
'Count')
190 return statDiagLabel, fcstatDiagLabel, fcstatDiagDiffLabel, sciTicks, signDefinite
194 Determine the union of cyDTimes available between
195 the control and each other experiment at each fcTDelta
197 cntrlLoc = deepcopy(myLoc)
202 cntrlLoc[
'fcTDelta'] = fcTDelta
203 cntrlCYDTimes = set(dfw.levels(
'cyDTime', cntrlLoc))
205 expLoc = deepcopy(cntrlLoc)
206 for expName
in self.
expNamesexpNames:
207 expLoc[
'expName'] = expName
208 expCYDTimes = set(dfw.levels(
'cyDTime', expLoc))
209 expsCYDTimes[(expName, fcTDelta)] = list(cntrlCYDTimes & expCYDTimes)
210 if len(cntrlCYDTimes) != len(expCYDTimes):
211 self.
loggerlogger.warning(self.
cntrlExpNamecntrlExpName+
' and '+expName+
' have different number of CYDTimes at forecast length ', fcTDelta,
' Only using common CYDTimes for CI calculation.')
215 self.
loggerlogger.info(
'analyze()')
230 raise NotImplementedError()
234 if len(allDiagnosticNames) > 1:
235 return expName+
'-'+diagnosticName
242 Utility function for providing an ordered list of
243 pairs of binVals and associated labels for
244 category binMethods in the context of a DFWrapper
247 binVar = vu.varDictAll[fullBinVar][1]
249 dbSelect1DBinVals = dfw.levels(
'binVal')
250 binUnitss = dfw.uniquevals(
'binUnits')
253 assert (len(binUnitss) != 0
and len(dbSelect1DBinVals) > 0),
'ERROR: categoryBinValsAttributes received invalid binVar/binMethod'
255 binUnits = binUnitss[0]
259 tmp = deepcopy(pconf.binVarConfigs.get(
262 'values', dbSelect1DBinVals))
264 if (
not isinstance(tmp, Iterable)
or
265 isinstance(tmp, str)):
266 select1DBinVals += [tmp]
268 select1DBinVals += tmp
269 for Bin
in dbSelect1DBinVals:
270 if Bin
not in select1DBinVals:
271 select1DBinVals.append(Bin)
272 for Bin
in list(select1DBinVals):
273 if Bin
not in dbSelect1DBinVals:
274 select1DBinVals.remove(Bin)
277 for binVal
in select1DBinVals:
278 if pu.isfloat(binVal)
or pu.isint(binVal):
279 t =
' @ '+binVar+
'='+binVal
280 if binUnits != vu.miss_s:
286 binValsMap = list(zip(select1DBinVals, binTitles))
296 Base class used to analyze statistics across binMethods with zero-dimensioned or
297 category binValues, e.g., QC flag, named latitude band, cloudiness regime, surface type
299 def __init__(self, db, analysisType, diagnosticGroupings):
300 super().
__init__(db, analysisType, diagnosticGroupings)
306 (vu.obsVarQC, bu.goodQCMethod): {
'binVarTier': 1},
307 (vu.obsVarLat, bu.latbandsMethod): {
'binVarTier': 1},
308 (vu.obsVarCldFrac, bu.cloudbandsMethod): {
'binVarTier': 1},
310 (vu.noBinVar, bu.noBinMethod): {
'binVarTier': 1},
311 (vu.obsRegionBinVar, bu.geoirlatlonboxMethod): {
'binVarTier': 2},
312 (vu.modelRegionBinVar, bu.geoirlatlonboxMethod): {
'binVarTier': 2},
313 (vu.obsVarPrs, bu.PjetMethod): {
'binVarTier': 3},
314 (vu.obsVarAlt, bu.altjetMethod): {
'binVarTier': 3},
315 (vu.obsVarLandFrac, bu.surfbandsMethod): {
'binVarTier': 3},
321 if len(binValsMap) > 1:
322 nxplots = len(binValsMap)
323 nyplots = self.
nVarsnVars
324 nsubplots = nxplots * nyplots
326 nsubplots = self.
nVarsnVars
327 nxplots = np.int(np.ceil(np.sqrt(nsubplots)))
328 nyplots = np.int(np.ceil(np.true_divide(nsubplots, nxplots)))
330 return nxplots, nyplots, nsubplots
339 diagnosticGrouped = {}
341 diagnosticGrouped[diag] =
False
344 for group
in list(diagnosticGroupings.keys()):
345 diags = diagnosticGroupings[group]
348 del diagnosticGroupings[group]
350 for diag
in diags: diagnosticGrouped[diag] =
True
353 if not diagnosticGrouped[diag]:
354 diagnosticGroupings[diag] = [diag]
356 for diagnosticGroup, diagnosticNames
in diagnosticGroupings.items():
358 if len(set(diagnosticNames) & set(self.
availableDiagnosticsavailableDiagnostics)) == 0:
continue
359 diagnosticConfigs = {}
360 analysisStatistics = set([])
361 for diagnosticName
in diagnosticNames:
362 diagnosticConfigs[diagnosticName] = deepcopy(self.
diagnosticConfigsdiagnosticConfigs[diagnosticName])
363 analysisStatistics = set(list(analysisStatistics) +
364 diagnosticConfigs[diagnosticName][
'analysisStatistics'])
365 if not set(self.
requiredStatisticsrequiredStatistics).issubset(analysisStatistics):
continue
367 diagLoc = {
'diagName': diagnosticNames}
368 diagBinVars = self.
dbdb.dfw.levels(
'binVar', diagLoc)
369 diagBinMethods = self.
dbdb.dfw.levels(
'binMethod', diagLoc)
370 for (fullBinVar, binMethod), options
in self.
binVarDictbinVarDict.items():
371 if options.get(
'binVarTier', 10) > self.
maxBinVarTiermaxBinVarTier:
continue
372 binVar = vu.varDictAll[fullBinVar][1]
373 if (binVar
not in diagBinVars
or
374 binMethod
not in diagBinMethods):
continue
376 self.
loggerlogger.info(diagnosticGroup+
', '+binVar+
', '+binMethod)
380 args = (diagnosticGroup, diagnosticConfigs, fullBinVar, binMethod, analysisStatistics, options))
383 diagnosticGroup, diagnosticConfigs, fullBinVar, binMethod, analysisStatistics, options)
386 diagnosticGroup, diagnosticConfigs, fullBinVar, binMethod, analysisStatistics, options):
388 binVar = vu.varDictAll[fullBinVar][1]
392 myLoc[
'binVar'] = binVar
393 myLoc[
'binMethod'] = binMethod
395 mydfwDict = {
'dfw': self.
dbdb.loc(myLoc)}
399 mydfwDict[
'agg'] = sdb.DFWrapper.fromAggStats(mydfwDict[
'dfw'], [
'cyDTime'])
400 sdb.createORreplaceDerivedDiagnostics(mydfwDict[
'agg'], diagnosticConfigs)
405 myLoc[
'diagName'] = list(diagnosticConfigs.keys())
406 for key
in mydfwDict.keys():
407 mydfwDict[key] = sdb.DFWrapper.fromLoc(mydfwDict[key], myLoc)
410 mydfwDict[
'dfw'], fullBinVar, binMethod, options)
414 for statName
in analysisStatistics:
415 if statName
not in options.get(
'onlyStatNames', analysisStatistics):
continue
418 mydfwDict, diagnosticGroup, myLoc, statName, binValsMap, options,
419 nsubplots, nxplots, nyplots)
422 dfwDict, diagnosticGroup, myLoc, statName, binValsMap, options,
423 nsubplots, nxplots, nyplots):
427 raise NotImplementedError()
432 Creates a timeseries figure between firstCycleDTime and lastCycleDTime
433 for each forecast length between fcTDeltaFirst and fcTDeltaLast
434 - x-axis: cycle initial time
435 - line: per experiment
436 - subplot: combination of DiagSpace variable and binVal
437 - file: combination of binVar, statistic, and FC lead time (if applicable)
439 def __init__(self, db, analysisType, diagnosticGroupings):
440 super().
__init__(db, analysisType, diagnosticGroupings)
446 dfwDict, diagnosticGroup, myLoc, statName, binValsMap, options,
447 nsubplots, nxplots, nyplots):
449 if self.
nCYnCY < 2:
return
451 bgstatDiagLabel, fcstatDiagLabel, fcstatDiagDiffLabel, sciTicks, signDefinite = \
454 myPath = self.
myFigPathmyFigPath/diagnosticGroup
455 myPath.mkdir(parents=
True, exist_ok=
True)
461 for (fcTDelta, fcTDelta_totmin)
in self.
fcMapfcMap:
462 lineLoc[
'fcTDelta'] = fcTDelta
463 axisLimitsLoc[
'fcTDelta'] = fcTDelta
470 for (varName, varLabel)
in self.
varMapvarMap:
471 lineLoc[
'varName'] = varName
472 axisLimitsLoc[
'varName'] = varName
475 for binVal, binTitle
in binValsMap:
476 lineLoc[
'binVal'] = binVal
477 axisLimitsLoc[
'binVal'] = binVal
480 if statName ==
'Count':
483 dmin = dfwDict[
'dfw'].min(axisLimitsLoc, statName)
484 dmax = dfwDict[
'dfw'].max(axisLimitsLoc, statName)
490 for expName
in self.
expNamesexpNames:
491 lineLoc[
'expName'] = expName
492 for diagnosticName
in myLoc[
'diagName']:
493 linesGroup.append(expName)
495 expName, diagnosticName, myLoc[
'diagName']))
497 lineLoc[
'diagName'] = diagnosticName
499 lineCYDTimes = dfwDict[
'dfw'].levels(
'cyDTime', lineLoc)
501 lineVals = np.full(self.
nCYnCY, np.NaN)
502 cyLoc = deepcopy(lineLoc)
503 for cyDTime
in lineCYDTimes:
504 icy = self.
cyDTimescyDTimes.index(cyDTime)
505 cyLoc[
'cyDTime'] = cyDTime
506 lineVals[icy] = dfwDict[
'dfw'].loc(cyLoc, statName)
507 linesVals.append(lineVals)
510 title = varLabel+binTitle
515 self.
cyDTimescyDTimes, linesVals, linesLabel,
516 title, bgstatDiagLabel,
517 sciTicks,
False, signDefinite,
518 nyplots, nxplots, nsubplots, iplot,
519 dmin = dmin, dmax = dmax,
520 interiorLabels = interiorLabels)
529 filename = myPath/(
'%s%s_TSeries_%smin_%s_%s_%s'%(
533 pu.finalize_fig(fig, str(filename), figureFileType, interiorLabels)
540 Creates a timeseries figure between fcTDeltaFirst and fcTDeltaLast containing
541 aggregated statistics for the period between firstCycleDTime and lastCycleDTime
542 - x-axis: forecast duration
543 - line: per experiment
544 - subplot: combination of DiagSpace variable and binVal
545 - file: combination of binVar and statistic
547 def __init__(self, db, analysisType, diagnosticGroupings):
548 super().
__init__(db, analysisType, diagnosticGroupings)
556 dfwDict, diagnosticGroup, myLoc, statName, binValsMap, options,
557 nsubplots, nxplots, nyplots):
559 if self.
nFCnFC < 2:
return
561 bgstatDiagLabel, fcstatDiagLabel, fcstatDiagDiffLabel, sciTicks, signDefinite = \
565 myPath = self.
myFigPathmyFigPath/fcDiagName
566 myPath.mkdir(parents=
True, exist_ok=
True)
576 for (varName, varLabel)
in self.
varMapvarMap:
577 lineLoc[
'varName'] = varName
578 axisLimitsLoc[
'varName'] = varName
581 for binVal, binTitle
in binValsMap:
582 lineLoc[
'binVal'] = binVal
583 axisLimitsLoc[
'binVal'] = binVal
586 if statName ==
'Count':
589 dmin = dfwDict[
'agg'].min(axisLimitsLoc, statName)
590 dmax = dfwDict[
'agg'].max(axisLimitsLoc, statName)
596 for expName
in self.
expNamesexpNames:
597 lineLoc[
'expName'] = expName
598 for diagnosticName
in myLoc[
'diagName']:
599 linesGroup.append(expName)
601 expName, diagnosticName, myLoc[
'diagName']))
602 lineLoc[
'diagName'] = diagnosticName
604 lineFCTDeltas = dfwDict[
'agg'].levels(
'fcTDelta', lineLoc)
606 lineVals = np.full(self.
nFCnFC, np.NaN)
607 fcLoc = deepcopy(lineLoc)
608 for fcTDelta
in lineFCTDeltas:
609 ifc = self.
fcTDeltasfcTDeltas.index(fcTDelta)
610 fcLoc[
'fcTDelta'] = fcTDelta
611 lineVals[ifc] = dfwDict[
'agg'].loc(fcLoc, statName)
612 linesVals.append(lineVals)
615 title = varLabel+binTitle
620 self.
fcTDeltasfcTDeltas, linesVals, linesLabel,
621 title, fcstatDiagLabel,
622 sciTicks,
False, signDefinite,
623 nyplots, nxplots, nsubplots, iplot,
624 dmin = dmin, dmax = dmax,
625 interiorLabels = interiorLabels)
634 filename = myPath/(
'%s%s_TSeries_%s-%smin_%s_%s_%s'%(
639 pu.finalize_fig(fig, str(filename), figureFileType, interiorLabels)
644 Similar to FCAxisExpLines, except
645 - shows difference between experiment(s) and control
646 - control is selected using cntrlExpIndex
647 - statistics are narrowed down by bootStrapStats
648 - confidence intervals (CI) are shown at each lead time
649 - line+shaded region: per experiment
650 - subplot: combination of DiagSpace variable and binVal
651 - file: combination of binVar and statistic
653 def __init__(self, db, analysisType, diagnosticGroupings):
654 super().
__init__(db, analysisType, diagnosticGroupings)
663 if 'onlyStatNames' in self.
binVarDictbinVarDict[key]:
664 self.
binVarDictbinVarDict[key][
'onlyStatNames'] += bootStrapStats
666 self.
binVarDictbinVarDict[key][
'onlyStatNames'] = bootStrapStats
669 dfwDict, diagnosticGroup, myLoc, statName, binValsMap, options,
670 nsubplots, nxplots, nyplots):
672 if self.
nFCnFC < 2:
return
673 if self.
nExpnExp * len(myLoc[
'diagName']) < 2:
return
674 if self.
cntrlExpNamecntrlExpName
not in dfwDict[
'dfw'].levels(
'expName'):
return
676 bgstatDiagLabel, fcstatDiagLabel, fcstatDiagDiffLabel, sciTicks, signDefinite = \
680 myPath = self.
myFigPathmyFigPath/fcDiagName
681 myPath.mkdir(parents=
True, exist_ok=
True)
693 for (varName, varLabel)
in self.
varMapvarMap:
694 binValLoc[
'varName'] = varName
697 for binVal, binTitle
in binValsMap:
698 binValLoc[
'binVal'] = binVal
701 tempdfw = sdb.DFWrapper.fromLoc(dfwDict[
'dfw'], binValLoc)
703 cntrlLoc = deepcopy(binValLoc)
707 title = varLabel+binTitle
709 linesVals = defaultdict(list)
712 cntrlLoc[
'diagName'] = myLoc[
'diagName'][0]
713 for expName
in self.
expNamesexpNames:
714 for diagnosticName
in myLoc[
'diagName']:
715 if (expName == cntrlLoc[
'expName']
and
716 diagnosticName == cntrlLoc[
'diagName']):
continue
717 linesGroup.append(expName)
719 expName, diagnosticName, myLoc[
'diagName']))
721 lineVals = defaultdict(list)
723 cntrlLoc[
'cyDTime'] = myExpsCYDTimes[(expName, fcTDelta)]
724 cntrlLoc[
'fcTDelta'] = fcTDelta
726 expLoc = deepcopy(cntrlLoc)
727 expLoc[
'diagName'] = diagnosticName
728 expLoc[
'expName'] = expName
730 X = tempdfw.loc(expLoc)
731 Y = tempdfw.loc(cntrlLoc)
733 ciVals = su.bootStrapClusterFunc(
736 statNames = [statName])
738 for trait
in su.ciTraits:
739 lineVals[trait] += [ciVals[statName][trait][0]]
741 for trait
in su.ciTraits:
742 linesVals[trait].append(lineVals[trait])
745 dmin = np.nanmin(linesVals[su.cimin])
746 dmax = np.nanmax(linesVals[su.cimax])
751 self.
fcTDeltasfcTDeltas, linesVals[su.cimean],
756 nyplots, nxplots, nsubplots, iplot,
757 linesValsMinCI = linesVals[su.cimin],
758 linesValsMaxCI = linesVals[su.cimax],
759 dmin = dmin, dmax = dmax,
760 lineAttribOffset = 1,
761 interiorLabels = interiorLabels)
769 filename = myPath/(
'%s%s_TSeries_%s-%smin_%s_%s_%s'%(
774 pu.finalize_fig(fig, str(filename), figureFileType, interiorLabels)
779 Similar to CYAxisExpLines, except
780 each line is for a different forecast lead time and
781 each experiment is in a different file
782 - x-axis: valid time of forecast
783 - line: per FC lead time
784 - subplot: combination of DiagSpace variable and binVal
785 - file: combination of binVar, statistic, and experiment
786 - self.MAX_FC_LINES determines number of FC lead time lines to include
788 def __init__(self, db, analysisType, diagnosticGroupings):
789 super().
__init__(db, analysisType, diagnosticGroupings)
797 dfwDict, diagnosticGroup, myLoc, statName, binValsMap, options,
798 nsubplots, nxplots, nyplots):
800 if self.
nFCnFC < 2
or self.
nCYnCY < 2:
return
802 bgstatDiagLabel, fcstatDiagLabel, fcstatDiagDiffLabel, sciTicks, signDefinite = \
806 myPath = self.
myFigPathmyFigPath/fcDiagName
807 myPath.mkdir(parents=
True, exist_ok=
True)
813 for expName
in self.
expNamesexpNames:
814 lineLoc[
'expName'] = expName
821 for (varName, varLabel)
in self.
varMapvarMap:
822 lineLoc[
'varName'] = varName
823 axisLimitsLoc[
'varName'] = varName
826 for binVal, binTitle
in binValsMap:
827 lineLoc[
'binVal'] = binVal
828 axisLimitsLoc[
'binVal'] = binVal
831 if statName ==
'Count':
834 dmin = dfwDict[
'dfw'].min(axisLimitsLoc, statName)
835 dmax = dfwDict[
'dfw'].max(axisLimitsLoc, statName)
842 lineLoc[
'fcTDelta'] = fcTDelta
846 for cyDTime
in self.
cyDTimescyDTimes:
847 xVals.append(cyDTime+fcTDelta)
854 pu.timeDeltaTicks(fcTDelta.total_seconds(),0))
856 lineCYDTimes = dfwDict[
'dfw'].levels(
'cyDTime', lineLoc)
858 lineVals = np.full(self.
nCYnCY, np.NaN)
859 cyLoc = deepcopy(lineLoc)
860 for cyDTime
in lineCYDTimes:
861 icy = self.
cyDTimescyDTimes.index(cyDTime)
862 cyLoc[
'cyDTime'] = cyDTime
863 lineVals[icy] = dfwDict[
'dfw'].loc(cyLoc, statName)
865 linesVals.append(lineVals)
868 title = varLabel+binTitle
874 title, bgstatDiagLabel,
875 sciTicks,
False, signDefinite,
876 nyplots, nxplots, nsubplots, iplot,
877 dmin = dmin, dmax = dmax,
878 interiorLabels = interiorLabels)
885 expFileName = re.sub(
'\.',
'', re.sub(
'\s+',
'-', expName))
886 filename = myPath/(
'%s%s_TSeries_%s_%s_%s_%s'%(
890 pu.finalize_fig(fig, str(filename), figureFileType, interiorLabels)
900 def __init__(self, db, analysisType, diagnosticGroupings):
901 super().
__init__(db, analysisType, diagnosticGroupings)
912 (vu.obsVarQC, bu.badQCMethod): {
913 'onlyStatNames': [
'Count'],
916 (vu.obsVarQC, bu.allQCMethod): {
917 'onlyStatNames': [
'Count'],
920 (vu.obsVarLat, bu.latbandsMethod): {
'binVarTier': 1},
922 (vu.obsVarCldFrac, bu.cloudbandsMethod): {
'binVarTier': 1},
923 (vu.obsVarLandFrac, bu.surfbandsMethod): {
'binVarTier': 3},
933 Similar to CYAxisExpLines, except
934 each line is for a different binVal (e.g., latitude band, cloudiness, etc.)
935 - line: binVals for named bins (e.g., NXTro, Tro, SXTro for latitude)
936 - subplot: column by experiment, row by DiagSpace variable
937 - file: combination of statistic and forecast length
939 def __init__(self, db, analysisType, diagnosticGroupings):
940 super().
__init__(db, analysisType, diagnosticGroupings)
948 dfwDict, diagnosticGroup, myLoc, statName, binValsMap, options,
949 nsubplots, nxplots, nyplots):
951 if self.
nCYnCY < 2:
return
953 bgstatDiagLabel, fcstatDiagLabel, fcstatDiagDiffLabel, sciTicks, signDefinite = \
957 myPath = self.
myFigPathmyFigPath/diagnosticGroup
958 myPath.mkdir(parents=
True, exist_ok=
True)
962 for binVal, binTitle
in binValsMap: binVals.append(binVal)
963 lineLoc[
'binVal'] = binVals
965 axisLimitsLoc = deepcopy(lineLoc)
968 for (fcTDelta, fcTDelta_totmin)
in self.
fcMapfcMap:
969 lineLoc[
'fcTDelta'] = fcTDelta
970 axisLimitsLoc[
'fcTDelta'] = fcTDelta
978 for (varName, varLabel)
in self.
varMapvarMap:
979 lineLoc[
'varName'] = varName
980 axisLimitsLoc[
'varName'] = varName
983 if statName ==
'Count':
986 dmin = dfwDict[
'dfw'].min(axisLimitsLoc, statName)
987 dmax = dfwDict[
'dfw'].max(axisLimitsLoc, statName)
990 for expName
in self.
expNamesexpNames:
991 lineLoc[
'expName'] = expName
995 for binVal
in binVals:
996 lineLoc[
'binVal'] = binVal
997 lineCYDTimes = dfwDict[
'dfw'].levels(
'cyDTime', lineLoc)
999 lineVals = np.full(self.
nCYnCY, np.NaN)
1000 cyLoc = deepcopy(lineLoc)
1001 for cyDTime
in lineCYDTimes:
1002 icy = self.
cyDTimescyDTimes.index(cyDTime)
1003 cyLoc[
'cyDTime'] = cyDTime
1005 lineVals[icy] = dfwDict[
'dfw'].loc(cyLoc, statName)
1007 linesVals.append(lineVals)
1012 title = expName+
'\n'+varLabel
1017 self.
cyDTimescyDTimes, linesVals, binVals,
1018 title, bgstatDiagLabel,
1019 sciTicks,
False, signDefinite,
1020 nyplots, nxplots, nsubplots, iplot,
1021 dmin = dmin, dmax = dmax,
1022 interiorLabels = interiorLabels)
1030 filename = myPath/(
'%s%s_TSeries_%smin_%s_%s_%s'%(
1033 diagnosticGroup, statName))
1035 pu.finalize_fig(fig, str(filename), figureFileType, interiorLabels)
1048 Base class used to analyze statistics across binMethods with one-dimensional binValues
1049 that are assigned numerical values, e.g., altitude, pressure, latitude, cloud fraction
1051 def __init__(self, db, analysisType, diagnosticGroupings):
1052 super().
__init__(db, analysisType, diagnosticGroupings)
1058 vu.obsVarAlt: {
'profilefunc': bpf.plotProfile,
'binVarTier': 1},
1059 vu.obsVarACI: {
'profilefunc': bpf.plotSeries,
'binVarTier': 2},
1060 vu.obsVarCldFrac: {
'profilefunc': bpf.plotSeries,
'binVarTier': 1},
1061 vu.obsVarLat: {
'profilefunc': bpf.plotProfile,
'binVarTier': 1},
1062 vu.obsVarPrs: {
'profilefunc': bpf.plotProfile,
'binVarTier': 1},
1063 vu.obsVarSCI: {
'profilefunc': bpf.plotSeries,
'binVarTier': 2},
1065 vu.modVarLev: {
'profilefunc': bpf.plotProfile,
'binVarTier': 1},
1066 vu.obsVarGlint: {
'profilefunc': bpf.plotSeries,
'binVarTier': 3},
1067 vu.obsVarLandFrac: {
'profilefunc': bpf.plotSeries,
'binVarTier': 3},
1068 vu.obsVarLT: {
'profilefunc': bpf.plotSeries,
'binVarTier': 3},
1069 vu.obsVarSenZen: {
'profilefunc': bpf.plotSeries,
'binbinVarTier': 3},
1075 diagnosticGrouped = {}
1077 diagnosticGrouped[diag] =
False
1080 for group
in list(diagnosticGroupings.keys()):
1081 diags = diagnosticGroupings[group]
1084 del diagnosticGroupings[group]
1086 for diag
in diags: diagnosticGrouped[diag] =
True
1089 if not diagnosticGrouped[diag]:
1090 diagnosticGroupings[diag] = [diag]
1092 for diagnosticGroup, diagnosticNames
in diagnosticGroupings.items():
1094 if len(set(diagnosticNames) & set(self.
availableDiagnosticsavailableDiagnostics)) == 0:
continue
1095 diagnosticConfigs = {}
1096 analysisStatistics = set([])
1097 for diagnosticName
in diagnosticNames:
1098 diagnosticConfigs[diagnosticName] = deepcopy(self.
diagnosticConfigsdiagnosticConfigs[diagnosticName])
1099 analysisStatistics = set(list(analysisStatistics) +
1100 diagnosticConfigs[diagnosticName][
'analysisStatistics'])
1101 if not set(self.
requiredStatisticsrequiredStatistics).issubset(analysisStatistics):
continue
1103 diagBinVars = self.
dbdb.dfw.levels(
'binVar', {
'diagName': diagnosticNames})
1105 for fullBinVar, options
in self.
binVarDictbinVarDict.items():
1106 if options.get(
'binVarTier', 10) > self.
maxBinVarTiermaxBinVarTier:
continue
1107 binVar = vu.varDictAll[fullBinVar][1]
1108 if (binVar
not in diagBinVars):
continue
1111 binVarLoc[
'diagName'] = diagnosticNames
1112 binVarLoc[
'binVar'] = binVar
1116 binMethods = self.
dbdb.dfw.levels(
'binMethod', binVarLoc)
1117 for binMethod
in binMethods:
1119 self.
loggerlogger.info(diagnosticGroup+
', '+binVar+
', '+binMethod)
1123 args = (diagnosticGroup, diagnosticConfigs, binVar, binMethod, analysisStatistics, options))
1126 diagnosticGroup, diagnosticConfigs, binVar, binMethod, analysisStatistics, options)
1129 diagnosticGroup, diagnosticConfigs, binVar, binMethod, analysisStatistics, options):
1132 myLoc[
'binVar'] = binVar
1134 myLoc[
'binMethod'] = binMethod
1137 mydfwDict = {
'dfw': self.
dbdb.loc(myLoc)}
1141 mydfwDict[
'agg'] = sdb.DFWrapper.fromAggStats(mydfwDict[
'dfw'], [
'cyDTime'])
1142 sdb.createORreplaceDerivedDiagnostics(mydfwDict[
'agg'], diagnosticConfigs)
1147 myLoc[
'diagName'] = list(diagnosticConfigs.keys())
1148 for key
in mydfwDict.keys():
1149 mydfwDict[key] = sdb.DFWrapper.fromLoc(mydfwDict[key], myLoc)
1152 binVals = mydfwDict[
'dfw'].levels(
'binVal')
1153 binUnits = mydfwDict[
'dfw'].uniquevals(
'binUnits')[0]
1157 if binUnits != vu.miss_s:
1158 indepLabel = indepLabel+
' ('+binUnits+
')'
1162 for binVal
in binVals:
1163 ibin = self.
allBinValsallBinVals.index(binVal)
1164 binNumVals.append(self.
binNumValsbinNumVals[ibin])
1167 pressure_dict = vu.varDictAll.get(vu.obsVarPrs,[
'',
''])
1168 invert_ind_axis = (pressure_dict[1] == binVar)
1171 indices = list(range(len(binNumVals)))
1172 indices.sort(key=binNumVals.__getitem__)
1173 binNumVals = list(map(binNumVals.__getitem__, indices))
1174 binVals = list(map(binVals.__getitem__, indices))
1178 'values': binNumVals,
1179 'indepLabel': indepLabel,
1180 'invert_ind_axis': invert_ind_axis,
1182 if len(binVals) < 2:
return
1187 for (varName, varLabel)
in self.
varMapvarMap:
1188 countDF = mydfwDict[
'dfw'].loc({
'varName': varName},
'Count')
1189 if countDF.shape[0] > 0:
1190 counts = countDF.to_numpy()
1191 if np.nansum(counts) > 0:
1193 varMapLoc.append((varName, varLabel))
1195 for statName
in analysisStatistics:
1196 if statName
not in options.get(
'onlyStatNames', analysisStatistics):
continue
1199 mydfwDict, diagnosticGroup, myLoc, statName, nVarsLoc, varMapLoc, myBinConfigs, options)
1202 dfwDict, diagnosticGroup, myLoc, statName, nVarsLoc, varMapLoc, myBinConfigs, options):
1206 raise NotImplementedError()
1211 Creates raster maps with binVar binVals on y-axis
1212 - only applicable to binned diagnostics (e.g., vertical dimension, latitude, zenith angle)
1213 - subplot: column by experiment, row by DiagSpace variable
1214 - file: combination of binVar, binMethod, statistic, and FC lead time
1216 def __init__(self, db, analysisType, diagnosticGroupings):
1217 super().
__init__(db, analysisType, diagnosticGroupings)
1225 dfwDict, diagnosticGroup, myLoc, statName, nVarsLoc, varMapLoc, myBinConfigs, options):
1227 if self.
nCYnCY < 2:
return
1229 bgstatDiagLabel, fcstatDiagLabel, fcstatDiagDiffLabel, scilogScale, signDefinite = \
1232 myPath = self.
myFigPathmyFigPath/diagnosticGroup
1233 myPath.mkdir(parents=
True, exist_ok=
True)
1235 nxplots = self.
nExpnExp
1237 nsubplots = nxplots * nyplots
1243 for (fcTDelta, fcTDelta_totmin)
in self.
fcMapfcMap:
1244 planeLoc[
'fcTDelta'] = fcTDelta
1252 for (varName, varLabel)
in varMapLoc:
1253 planeLoc[
'varName'] = varName
1254 axisLimitsLoc[
'varName'] = varName
1257 if statName ==
'Count':
1260 dmin = dfwDict[
'dfw'].min(axisLimitsLoc, statName)
1261 dmax = dfwDict[
'dfw'].max(axisLimitsLoc, statName)
1265 for expName
in self.
expNamesexpNames:
1266 planeLoc[
'expName'] = expName
1267 planeCYDTimes = dfwDict[
'dfw'].levels(
'cyDTime', planeLoc)
1269 planeVals = np.full((len(myBinConfigs[
'str']), self.
nCYnCY), np.NaN)
1270 binLoc = deepcopy(planeLoc)
1271 for ibin, binVal
in enumerate(myBinConfigs[
'str']):
1272 binLoc[
'binVal'] = binVal
1273 tmp = dfwDict[
'dfw'].loc(binLoc, statName).to_numpy()
1274 for jcy, cyDTime
in enumerate(planeCYDTimes):
1275 if jcy > len(tmp)-1:
continue
1276 icy = self.
cyDTimescyDTimes.index(cyDTime)
1277 planeVals[ibin, icy] = tmp[jcy]
1280 title = expName+
'\n'+varLabel
1283 bpf.plotTimeSeries2D(
1285 self.
cyDTimescyDTimes, myBinConfigs[
'values'], planeVals,
1286 title, bgstatDiagLabel,
1287 scilogScale, scilogScale, signDefinite,
1288 myBinConfigs[
'indepLabel'], myBinConfigs[
'invert_ind_axis'],
1289 nyplots, nxplots, nsubplots, iplot,
1290 dmin = dmin, dmax = dmax,
1291 interiorLabels = interiorLabels)
1295 filename = myPath/(
'%s%s_BinValAxisTSeries_%smin_%s_%s_%s'%(
1298 diagnosticGroup, statName))
1300 pu.finalize_fig(fig, str(filename), figureFileType, interiorLabels)
1307 Creates raster maps with binVar binVals on y-axis
1308 - only applicable to binned diagnostics (e.g., vertical dimension, latitude, zenith angle)
1309 - subplot: column by experiment, row by DiagSpace variable
1310 - file: combination of binVar, binMethod, and statistic
1313 def __init__(self, db, analysisType, diagnosticGroupings):
1314 super().
__init__(db, analysisType, diagnosticGroupings)
1324 dfwDict, diagnosticGroup, myLoc, statName, nVarsLoc, varMapLoc, myBinConfigs, options):
1326 if self.
nFCnFC < 2:
return
1328 bgstatDiagLabel, fcstatDiagLabel, fcstatDiagDiffLabel, scilogScale, signDefinite = \
1332 myPath = self.
myFigPathmyFigPath/fcDiagName
1333 myPath.mkdir(parents=
True, exist_ok=
True)
1335 nxplots = self.
nExpnExp
1337 nsubplots = nxplots * nyplots
1347 for (varName, varLabel)
in varMapLoc:
1348 planeLoc[
'varName'] = varName
1349 axisLimitsLoc[
'varName'] = varName
1352 if statName ==
'Count':
1355 dmin = dfwDict[
'agg'].min(axisLimitsLoc, statName)
1356 dmax = dfwDict[
'agg'].max(axisLimitsLoc, statName)
1360 for expName
in self.
expNamesexpNames:
1361 planeLoc[
'expName'] = expName
1362 planeFCTDeltas = dfwDict[
'agg'].levels(
'fcTDelta', planeLoc)
1364 planeVals = np.full((len(myBinConfigs[
'str']), self.
nFCnFC), np.NaN)
1365 binLoc = deepcopy(planeLoc)
1366 for ibin, binVal
in enumerate(myBinConfigs[
'str']):
1367 binLoc[
'binVal'] = binVal
1368 tmp = dfwDict[
'agg'].loc(binLoc, statName).to_numpy()
1369 for jfc, fcTDelta
in enumerate(planeFCTDeltas):
1370 if jfc > len(tmp)-1:
continue
1371 ifc = self.
fcTDeltasfcTDeltas.index(fcTDelta)
1372 planeVals[ibin, ifc] = tmp[jfc]
1375 title = expName+
'\n'+varLabel
1378 bpf.plotTimeSeries2D(
1380 self.
fcTDeltasfcTDeltas, myBinConfigs[
'values'], planeVals,
1381 title, fcstatDiagLabel,
1382 scilogScale, scilogScale, signDefinite,
1383 myBinConfigs[
'indepLabel'], myBinConfigs[
'invert_ind_axis'],
1384 nyplots, nxplots, nsubplots, iplot,
1385 dmin = dmin, dmax = dmax,
1386 interiorLabels = interiorLabels)
1391 filename = myPath/(
'%s%s_BinValAxisTSeries_%s-%smin_%s_%s_%s'%(
1396 pu.finalize_fig(fig, str(filename), figureFileType, interiorLabels)
1401 Similar to FCandBinValAxes2D, except
1402 - each vertical column of raster points is plotted as a profile on
1403 a separate set of axes instead of in 2-D color
1404 - therefore this is a valid plot even for a single forecast length (omb)
1405 - line: per experiment
1406 - subplot: column by lead time, row by DiagSpace variable
1407 - file: combination of binVar, binMethod, and statistic
1408 - self.MAX_FC_SUBFIGS determines number of FC lead times to include
1410 def __init__(self, db, analysisType, diagnosticGroupings):
1411 super().
__init__(db, analysisType, diagnosticGroupings)
1419 dfwDict, diagnosticGroup, myLoc, statName, nVarsLoc, varMapLoc, myBinConfigs, options):
1421 bgstatDiagLabel, fcstatDiagLabel, fcstatDiagDiffLabel, scilogScale, signDefinite = \
1425 myPath = self.
myFigPathmyFigPath/fcDiagName
1426 myPath.mkdir(parents=
True, exist_ok=
True)
1431 nsubplots = nxplots * nyplots
1433 nsubplots = nVarsLoc
1434 nxplots = np.int(np.ceil(np.sqrt(nsubplots)))
1435 nyplots = np.int(np.ceil(np.true_divide(nsubplots, nxplots)))
1445 for (varName, varLabel)
in varMapLoc:
1446 ptLoc[
'varName'] = varName
1447 axisLimitsLoc[
'varName'] = varName
1450 for fcTDelta
in self.
fcTDeltasfcTDeltas:
1451 ptLoc[
'fcTDelta'] = fcTDelta
1452 axisLimitsLoc[
'fcTDelta'] = fcTDelta
1459 if statName ==
'Count':
1462 dmin = dfwDict[
'agg'].min(axisLimitsLoc, statName)
1463 dmax = dfwDict[
'agg'].max(axisLimitsLoc, statName)
1472 for expName
in self.
expNamesexpNames:
1473 ptLoc[
'expName'] = expName
1474 for diagnosticName
in myLoc[
'diagName']:
1475 linesGroup.append(expName)
1477 expName, diagnosticName, myLoc[
'diagName']))
1479 ptLoc[
'diagName'] = diagnosticName
1482 for binVal
in myBinConfigs[
'str']:
1483 ptLoc[
'binVal'] = binVal
1484 pt = dfwDict[
'agg'].loc(ptLoc, statName).to_numpy()
1486 lineVals.append(pt[0])
1488 lineVals.append(np.NaN)
1490 linesVals.append(lineVals)
1493 title = varLabel+
' @ '+str(float(fcTDelta.total_seconds()) / 3600.0 / 24.0)+
'days'
1496 options[
'profilefunc'](
1498 linesVals, myBinConfigs[
'values'],
1500 title, fcstatDiagLabel,
1501 scilogScale, scilogScale, signDefinite,
1502 myBinConfigs[
'indepLabel'], myBinConfigs[
'invert_ind_axis'],
1503 nyplots, nxplots, nsubplots, iplot,
1504 dmin = dmin, dmax = dmax,
1505 interiorLabels = interiorLabels)
1511 filename = myPath/(
'%s%s_BinValAxis_%s-%smin_%s_%s_%s'%(
1516 pu.finalize_fig(fig, str(filename), figureFileType, interiorLabels,
True)
1521 Similar to BinValAxisProfile, except
1522 shows difference between experiment(s) and control
1523 - control is selected using cntrlExpIndex
1524 - statistics are narrowed down by bootStrapStats
1525 - confidence intervals (CI) are shown at each lead time and binVal
1526 - line+shaded region: per experiment
1527 - subplot: column by lead time, row by DiagSpace variable
1528 - file: combination of binVar, binMethod, and statistic
1529 - self.MAX_FC_SUBFIGS determines number of FC lead times to include
1531 def __init__(self, db, analysisType, diagnosticGroupings):
1532 super().
__init__(db, analysisType, diagnosticGroupings)
1538 if 'onlyStatNames' in self.
binVarDictbinVarDict[key]:
1539 self.
binVarDictbinVarDict[key][
'onlyStatNames'] += bootStrapStats
1541 self.
binVarDictbinVarDict[key][
'onlyStatNames'] = bootStrapStats
1547 dfwDict, diagnosticGroup, myLoc, statName, nVarsLoc, varMapLoc, myBinConfigs, options):
1549 if self.
nExpnExp * len(myLoc[
'diagName']) < 2:
return
1550 if self.
cntrlExpNamecntrlExpName
not in dfwDict[
'dfw'].levels(
'expName'):
return
1552 bgstatDiagLabel, fcstatDiagLabel, fcstatDiagDiffLabel, scilogScale, signDefinite = \
1556 myPath = self.
myFigPathmyFigPath/fcDiagName
1557 myPath.mkdir(parents=
True, exist_ok=
True)
1562 nsubplots = nxplots * nyplots
1564 nsubplots = nVarsLoc
1565 nxplots = np.int(np.ceil(np.sqrt(nsubplots)))
1566 nyplots = np.int(np.ceil(np.true_divide(nsubplots, nxplots)))
1578 for (varName, varLabel)
in varMapLoc:
1579 fcLoc[
'varName'] = varName
1582 for fcTDelta
in self.
fcTDeltasfcTDeltas:
1583 fcLoc[
'fcTDelta'] = fcTDelta
1586 tempdfw = sdb.DFWrapper.fromLoc(dfwDict[
'dfw'], fcLoc)
1588 cntrlLoc = deepcopy(fcLoc)
1594 linesVals = defaultdict(list)
1597 cntrlLoc[
'diagName'] = myLoc[
'diagName'][0]
1598 for expName
in self.
expNamesexpNames:
1599 for diagnosticName
in myLoc[
'diagName']:
1600 if (expName == cntrlLoc[
'expName']
and
1601 diagnosticName == cntrlLoc[
'diagName']):
continue
1602 cntrlLoc[
'cyDTime'] = myExpsCYDTimes[(expName, fcTDelta)]
1603 linesGroup.append(expName)
1605 expName, diagnosticName, myLoc[
'diagName']))
1607 lineVals = defaultdict(list)
1609 for binVal
in myBinConfigs[
'str']:
1610 cntrlLoc[
'binVal'] = binVal
1611 expLoc = deepcopy(cntrlLoc)
1612 expLoc[
'diagName'] = diagnosticName
1613 expLoc[
'expName'] = expName
1615 X = tempdfw.loc(expLoc)
1616 Y = tempdfw.loc(cntrlLoc)
1618 ciVals = su.bootStrapClusterFunc(
1621 statNames = [statName])
1623 for trait
in su.ciTraits:
1624 lineVals[trait] += [ciVals[statName][trait][0]]
1626 for trait
in su.ciTraits:
1627 linesVals[trait].append(lineVals[trait])
1630 title = varLabel+
' @ '+str(float(fcTDelta.total_seconds()) / 3600.0 / 24.0)+
'days'
1633 dmin = np.nanmin(linesVals[su.cimin])
1634 dmax = np.nanmax(linesVals[su.cimax])
1637 options[
'profilefunc'](
1639 linesVals[su.cimean], myBinConfigs[
'values'],
1642 fcstatDiagDiffLabel,
1643 scilogScale, scilogScale,
False,
1644 myBinConfigs[
'indepLabel'], myBinConfigs[
'invert_ind_axis'],
1645 nyplots, nxplots, nsubplots, iplot,
1646 linesValsMinCI = linesVals[su.cimin],
1647 linesValsMaxCI = linesVals[su.cimax],
1648 dmin = dmin, dmax = dmax,
1649 lineAttribOffset = 1,
1650 interiorLabels = interiorLabels)
1655 filename = myPath/(
'%s%s_BinValAxis_%s-%smin_%s_%s_%s'%(
1660 pu.finalize_fig(fig, str(filename), figureFileType, interiorLabels,
True)
1665 Similar to BinValAxisProfile, except
1666 uses Count statistic to analyze a PDF across binVals
1668 - line: per binMethod
1669 - subplot: combination of FC lead time and DiagSpace variable
1670 - file: per experiment (if applicable)
1672 def __init__(self, db, analysisType, diagnosticGroupings):
1673 super().
__init__(db, analysisType, diagnosticGroupings)
1678 vu.obsVarNormErr: {
'pdffunc': bpf.plotPDF},
1689 for diagnosticName, diagnosticConfig
in self.
diagnosticConfigsdiagnosticConfigs.items():
1690 if diagnosticName
not in self.
dbdb.dfw.levels(
'diagName'):
continue
1691 analysisStatistics = diagnosticConfig[
'analysisStatistics']
1694 diagBinVars = self.
dbdb.dfw.levels(
'binVar', {
'diagName': diagnosticName})
1696 for fullBinVar, options
in self.
binVarDictbinVarDict:
1697 binVar = vu.varDictAll[fullBinVar][1]
1698 if binVar
not in diagBinVars:
continue
1701 myLoc[
'diagName'] = diagnosticName
1702 myLoc[
'binVar'] = binVar
1706 mydfwDict = {
'dfw': self.
dbdb.loc(myLoc)}
1710 mydfwDict[
'agg'] = sdb.DFWrapper.fromAggStats(mydfwDict[
'dfw'], [
'cyDTime'])
1713 binMethods = mydfwDict[
'dfw'].levels(
'binMethod')
1714 binVals = mydfwDict[
'dfw'].levels(
'binVal')
1715 binUnits = mydfwDict[
'dfw'].uniquevals(
'binUnits')[0]
1719 if binUnits != vu.miss_s:
1720 indepLabel = indepLabel+
' ('+binUnits+
')'
1724 for binVal
in binVals:
1725 ibin = self.
allBinValsallBinVals.index(binVal)
1726 binNumVals.append(self.
binNumValsbinNumVals[ibin])
1729 indices = list(range(len(binNumVals)))
1730 indices.sort(key=binNumVals.__getitem__)
1731 binNumVals = list(map(binNumVals.__getitem__, indices))
1732 binVals = list(map(binVals.__getitem__, indices))
1734 if len(binVals) < 2:
continue
1736 self.
loggerlogger.info(
'binVar=>'+binVar)
1739 myPath = self.
myFigPathmyFigPath/fcDiagName
1740 myPath.mkdir(parents=
True, exist_ok=
True)
1744 nyplots = self.
nVarsnVars
1745 nsubplots = nxplots * nyplots
1747 nsubplots = self.
nVarsnVars
1748 nxplots = np.int(np.ceil(np.sqrt(nsubplots)))
1749 nyplots = np.int(np.ceil(np.true_divide(nsubplots, nxplots)))
1751 ptLoc = deepcopy(myLoc)
1754 for expName
in self.
expNamesexpNames:
1755 ptLoc[
'expName'] = expName
1763 for (varName, varLabel)
in self.
varMapvarMap:
1764 ptLoc[
'varName'] = varName
1767 for fcTDelta
in self.
fcTDeltasfcTDeltas:
1768 ptLoc[
'fcTDelta'] = fcTDelta
1775 binMethodLabels = []
1776 for binMethod
in binMethods:
1777 ptLoc[
'binMethod'] = binMethod
1780 if binMethod == bu.identityBinMethod:
1781 binMethodLabels.append(
'ObsSpace')
1783 binMethodLabels.append(binMethod)
1786 for binVal
in binVals:
1787 ptLoc[
'binVal'] = binVal
1788 lineVals.append(dfwDict[
'agg'].loc(ptLoc,
'Count'))
1790 linesVals.append(lineVals)
1793 title = varLabel+
' @ '+str(float(fcTDelta.total_seconds()) / 3600.0 / 24.0)+
'days'
1798 linesVals, binNumVals,
1802 nyplots, nxplots, nsubplots, iplot,
1803 interiorLabels = interiorLabels)
1812 filename = myPath/(
'%s_BinValAxis_%s-%smin_%s_%s_%s'%(
1816 pu.finalize_fig(fig, str(filename), figureFileType, interiorLabels,
True)
1824 Similar to BinValAxisProfile, except
1825 all statistics (Count, Mean, RMS, STD) are placed on the same axis
1827 - line: per statistic
1828 - subplot: per DiagSpace variable
1829 - file: combination of FC lead time, experiment, and binMethod (if applicable)
1831 def __init__(self, db, analysisType, diagnosticGroupings):
1832 super().
__init__(db, analysisType, diagnosticGroupings)
1837 vu.obsVarSCI: {
'statsfunc': bpf.plotfitRampComposite},
1852 for diagnosticName, diagnosticConfig
in self.
diagnosticConfigsdiagnosticConfigs.items():
1853 if diagnosticName
not in self.
dbdb.dfw.levels(
'diagName'):
continue
1854 analysisStatistics = diagnosticConfig[
'analysisStatistics']
1857 diagBinVars = self.
dbdb.dfw.levels(
'binVar', {
'diagName': diagnosticName})
1859 for fullBinVar, options
in self.
binVarDictbinVarDict.items():
1860 binVar = vu.varDictAll[fullBinVar][1]
1861 if (binVar
not in diagBinVars):
continue
1864 myLoc[
'diagName'] = diagnosticName
1865 myLoc[
'binVar'] = binVar
1869 mydfwDict = {
'dfw': self.
dbdb.loc(myLoc)}
1873 mydfwDict[
'agg'] = sdb.DFWrapper.fromAggStats(mydfwDict[
'dfw'], [
'cyDTime'])
1876 binMethods = mydfwDict[
'dfw'].levels(
'binMethod')
1877 binVals = mydfwDict[
'dfw'].levels(
'binVal')
1878 binUnits = mydfwDict[
'dfw'].uniquevals(
'binUnits')[0]
1882 if binUnits != vu.miss_s:
1883 indepLabel = indepLabel+
' ('+binUnits+
')'
1887 for binVal
in binVals:
1888 ibin = self.
allBinValsallBinVals.index(binVal)
1889 binNumVals.append(self.
binNumValsbinNumVals[ibin])
1892 indices = list(range(len(binNumVals)))
1893 indices.sort(key=binNumVals.__getitem__)
1894 binNumVals = list(map(binNumVals.__getitem__, indices))
1895 binVals = list(map(binVals.__getitem__, indices))
1897 nBins = len(binVals)
1898 if nBins < 2:
continue
1901 myPath = self.
myFigPathmyFigPath/fcDiagName
1902 myPath.mkdir(parents=
True, exist_ok=
True)
1904 nsubplots = self.
nVarsnVars
1905 nxplots = np.int(np.ceil(np.sqrt(nsubplots)))
1906 nyplots = np.int(np.ceil(np.true_divide(nsubplots, nxplots)))
1911 for binMethod
in binMethods:
1912 ptLoc[
'binMethod'] = binMethod
1914 self.
loggerlogger.info(
'binVar=>'+binVar+
', binMethod=>'+binMethod)
1917 for expName
in self.
expNamesexpNames:
1918 ptLoc[
'expName'] = expName
1921 for (fcTDelta, fcTDelta_totmin)
in self.
fcMapfcMap:
1922 ptLoc[
'fcTDelta'] = fcTDelta
1932 for (varName, varLabel)
in self.
varMapvarMap:
1933 ptLoc[
'varName'] = varName
1936 countsVals = np.full(nBins,0)
1937 meansVals = np.full(nBins, np.NaN)
1938 rmssVals = np.full(nBins, np.NaN)
1939 stdsVals = np.full(nBins, np.NaN)
1941 for ibin, binVal
in enumerate(binVals):
1942 ptLoc[
'binVal'] = binVal
1943 countsVals[ibin] = mydfwDict[
'agg'].loc(ptLoc,
'Count').to_numpy()
1944 meansVals[ibin] = mydfwDict[
'agg'].loc(ptLoc,
'Mean').to_numpy()
1945 rmssVals[ibin] = mydfwDict[
'agg'].loc(ptLoc,
'RMS').to_numpy()
1946 stdsVals[ibin] = mydfwDict[
'agg'].loc(ptLoc,
'STD').to_numpy()
1952 FitParams = options[
'statsfunc'](
1960 'STATS('+fcDiagName+
')',
1962 nyplots, nxplots, nsubplots, iplot,
1963 interiorLabels = interiorLabels)
1965 paramKey = self.
chlistchlist[iplot]
1966 if paramKey ==
'': paramKey = varName
1967 ERRParams[self.
DiagSpaceNameDiagSpaceName][(paramKey, binMethod)] = FitParams
1972 print(
'\n#For binning_params:')
1973 for key
in sorted(ERRParams[self.
DiagSpaceNameDiagSpaceName]):
1974 print(binVar+
"ErrParams['"+self.
DiagSpaceNameDiagSpaceName+
"'][", key,
"] = ",
1976 for param, val
in ERRParams[self.
DiagSpaceNameDiagSpaceName][key][
'YAML'].items():
1977 if param
not in YAMLParams: YAMLParams[param] = []
1978 YAMLParams[param] += val
1979 print(
'\n#For UFO YAML config:')
1980 for param, val
in YAMLParams.items():
1981 print(
'# '+param+
':', val)
1984 filename = myPath/(
'%s%s_BinValAxis_%smin_%s_%s_%s'%(
1988 pu.finalize_fig(fig, str(filename), figureFileType, interiorLabels,
True)
2002 Calculate gross statistics for specified category binMethods at first forecast length
2003 NOTE: currently only calculates statistics at self.fcTDeltas[0]
2004 adjust minimum forecast length in order to calculate
2005 for non-zero forecast lengths, assuming those lengths
2008 def __init__(self, db, analysisType, diagnosticGroupings):
2009 super().
__init__(db, analysisType, diagnosticGroupings)
2018 (vu.obsVarQC, bu.goodQCMethod): {},
2019 (vu.obsVarCldFrac, bu.cloudbandsMethod): {},
2023 for diagnosticName, diagnosticConfig
in self.
diagnosticConfigsdiagnosticConfigs.items():
2024 if diagnosticName
not in self.
dbdb.dfw.levels(
'diagName'):
continue
2025 analysisStatistics = diagnosticConfig[
'analysisStatistics']
2026 if not set(self.
requiredStatisticsrequiredStatistics).issubset(set(analysisStatistics)):
continue
2028 diagLoc = {
'diagName': diagnosticName}
2029 diagBinVars = self.
dbdb.dfw.levels(
'binVar', diagLoc)
2030 diagBinMethods = self.
dbdb.dfw.levels(
'binMethod', diagLoc)
2032 for (fullBinVar, binMethod), options
in self.
binVarDictbinVarDict.items():
2033 binVar = vu.varDictAll[fullBinVar][1]
2034 if (binVar
not in diagBinVars
or
2035 binMethod
not in diagBinMethods):
continue
2039 myLoc[
'binVar'] = binVar
2040 myLoc[
'binMethod'] = binMethod
2043 mydfwDict = {
'dfw': self.
dbdb.loc(myLoc)}
2046 mydfwDict[
'agg'] = sdb.DFWrapper.fromAggStats(mydfwDict[
'dfw'], [
'cyDTime'])
2047 sdb.createORreplaceDerivedDiagnostics(mydfwDict[
'agg'], {diagnosticName: diagnosticConfig})
2052 myLoc[
'diagName'] = diagnosticName
2053 for key
in mydfwDict.keys():
2054 mydfwDict[key] = sdb.DFWrapper.fromLoc(mydfwDict[key], myLoc)
2056 print(
' Calculate gross statistics: binVar=>'+binVar+
', binMethod=>'+binMethod)
2059 mydfwDict[
'dfw'], fullBinVar, binMethod, options)
2061 print(
' at FC length ', self.
fcTDeltasfcTDeltas[0])
2064 statsLoc[
'fcTDelta'] = self.
fcTDeltasfcTDeltas[0]
2065 for binVal, binTitle
in binValsMap:
2066 statsLoc[
'binVal'] = binVal
2068 for varName
in self.
varNamesvarNames:
2069 statsLoc[
'varName'] = varName
2070 for expName
in self.
expNamesexpNames:
2071 statsLoc[
'expName'] = expName
2072 statsDFW = sdb.DFWrapper.fromLoc(mydfwDict[
'agg'], statsLoc)
2073 for statName
in analysisStatistics:
2074 GrossValues[(statName, expName, varName)] = statsDFW.var(statName).to_numpy()
2075 for expName
in self.
expNamesexpNames:
2076 print(
'Gross statistics for')
2077 print(
'experiment=>'+expName)
2078 if len(binValsMap) > 1:
2079 print(
'binVal=>'+binVal)
2080 print(
' variables: ', self.
varNamesvarNames)
2082 for statName
in analysisStatistics:
2084 tmp = np.asarray([])
2085 for varName
in self.
varNamesvarNames:
2086 tmp = np.append(tmp, GrossValues[(statName, expName, varName)])
2089 AnalysisTypeDict = {
2091 'CYAxisExpLines': CYAxisExpLines,
2092 'FCAxisExpLines': FCAxisExpLines,
2093 'FCAxisExpLinesDiffCI': FCAxisExpLinesDiffCI,
2094 'CYAxisFCLines': CYAxisFCLines,
2095 'CYAxisBinValLines': CYAxisBinValLines,
2097 'CYandBinValAxes2D': CYandBinValAxes2D,
2098 'FCandBinValAxes2D': FCandBinValAxes2D,
2099 'BinValAxisProfile': BinValAxisProfile,
2100 'BinValAxisProfileDiffCI': BinValAxisProfileDiffCI,
2104 'BinValAxisPDF': BinValAxisPDF,
2105 'BinValAxisStatsComposite': BinValAxisStatsComposite,
2106 'GrossValues': GrossValues,
2116 myClass = AnalysisTypeDict.get(analysisType,
None)
2117 assert (myClass
is not None and inspect.isclass(myClass)), \
2118 (
'\n\nERROR: AnalysisFactory cannot construct ', analysisType,
' without instructions in AnalysisTypeDict')
2119 return myClass(db, analysisType, diagnosticGroupings)
2123 def __init__(self, db, analysisTypes, diagnosticGroupings = {}, nproc = 1):
2126 for anType
in analysisTypes:
2128 self.
loggerlogger = logging.getLogger(__name__+
'.'+db.DiagSpaceName)
2129 self.
loggerlogger.info(
'Analyses Constructed')
2132 self.
loggerlogger.info(
"Entering Analyses.analyze()")
2134 if self.
nprocnproc > 1:
2135 workers = mp.Pool(self.
nprocnproc)
2142 if workers
is not None:
2146 self.
loggerlogger.info(
"Exiting Analyses.analyze()")
def __init__(self, db, analysisTypes, diagnosticGroupings={}, nproc=1)
Base class for all analysisTypes.
blocking
Establish default configuration.
DiagSpacePath
Setup paths.
def statPlotAttributes(self, diagnosticGroup, statName, allDiagnosticNames=None)
def __init__(self, db, analysisType, diagnosticGroupings={})
def binMethodFile(self, binMethod, before=True)
def fcName(self, diagnosticGroup)
def analyze_(self, workers=None)
def UNIONcntrlANDexpCYDTimes(self, dfw, myLoc={})
def analyze(self, workers=None)
db
Extract useful variables from the database.
def analyze_(self, workers=None)
def __init__(self, db, analysisType, diagnosticGroupings)
def __init__(self, db, analysisType, diagnosticGroupings)
def innerloops(self, dfwDict, diagnosticGroup, myLoc, statName, nVarsLoc, varMapLoc, myBinConfigs, options)
def innerloops(self, dfwDict, diagnosticGroup, myLoc, statName, nVarsLoc, varMapLoc, myBinConfigs, options)
def __init__(self, db, analysisType, diagnosticGroupings)
def analyze_(self, workers=None)
def __init__(self, db, analysisType, diagnosticGroupings)
Figures with individual lines per binVal.
def __init__(self, db, analysisType, diagnosticGroupings)
def subplotArrangement(self, dummy)
def innerloops(self, dfwDict, diagnosticGroup, myLoc, statName, binValsMap, options, nsubplots, nxplots, nyplots)
def __init__(self, db, analysisType, diagnosticGroupings)
maxDiagnosticsPerAnalysis
def __init__(self, db, analysisType, diagnosticGroupings)
def innerloops(self, dfwDict, diagnosticGroup, myLoc, statName, binValsMap, options, nsubplots, nxplots, nyplots)
maxDiagnosticsPerAnalysis
def __init__(self, db, analysisType, diagnosticGroupings)
def innerloops(self, dfwDict, diagnosticGroup, myLoc, statName, binValsMap, options, nsubplots, nxplots, nyplots)
maxDiagnosticsPerAnalysis
def __init__(self, db, analysisType, diagnosticGroupings)
def innerloops(self, dfwDict, diagnosticGroup, myLoc, statName, nVarsLoc, varMapLoc, myBinConfigs, options)
def innerloops(self, dfwDict, diagnosticGroup, myLoc, statName, binValsMap, options, nsubplots, nxplots, nyplots)
maxDiagnosticsPerAnalysis
def __init__(self, db, analysisType, diagnosticGroupings)
def analyze_(self, workers=None)
def subplotArrangement(self, binValsMap)
def innerloopsWrapper(self, diagnosticGroup, diagnosticConfigs, fullBinVar, binMethod, analysisStatistics, options)
def innerloops(self, dfwDict, diagnosticGroup, myLoc, statName, binValsMap, options, nsubplots, nxplots, nyplots)
def __init__(self, db, analysisType, diagnosticGroupings)
def __init__(self, db, analysisType, diagnosticGroupings)
def innerloops(self, dfwDict, diagnosticGroup, myLoc, statName, binValsMap, options, nsubplots, nxplots, nyplots)
def __init__(self, db, analysisType, diagnosticGroupings)
maxDiagnosticsPerAnalysis
def innerloops(self, dfwDict, diagnosticGroup, myLoc, statName, nVarsLoc, varMapLoc, myBinConfigs, options)
def analyze_(self, workers=None)
def __init__(self, db, analysisType, diagnosticGroupings)
Figures with binVal on one axis, i.e., 2D and profiles.
def analyze_(self, workers=None)
def __init__(self, db, analysisType, diagnosticGroupings)
maxDiagnosticsPerAnalysis
def innerloops(self, dfwDict, diagnosticGroup, myLoc, statName, nVarsLoc, varMapLoc, myBinConfigs, options)
def innerloopsWrapper(self, diagnosticGroup, diagnosticConfigs, binVar, binMethod, analysisStatistics, options)
def AnalysisFactory(db, analysisType, diagnosticGroupings)
def anWorkingDir(DiagSpace)
def categoryBinValsAttributes(dfw, fullBinVar, binMethod, options)
def expDiagnosticLabel(expName, diagnosticName, allDiagnosticNames)