3 from collections
import defaultdict
4 from collections.abc
import Iterable
5 from copy
import deepcopy
10 import plot_utils
as pu
11 from binning_params
import allSCIErrParams, ABEIParams
12 import var_utils
as vu
14 _logger = logging.getLogger(__name__)
22 identityBinMethod =
'identity'
25 noBinMethod = identityBinMethod
35 P_jet_val =
'{:.0f}'.
format(0.5 * (P_jet_min + P_jet_max))
36 PjetMethod =
'P='+P_jet_val+
'hPa'
41 alt_jet_val =
'{:.0f}'.
format(0.5 * (alt_jet_min + alt_jet_max))
42 altjetMethod =
'alt='+alt_jet_val+
'm'
50 latbandsMethod =
'LatBands'
54 landsurfMethod =
'land'
55 mixsurfMethod =
'mixed-land-sea'
56 allsurfMethod =
'all-surface'
57 surfbandsMethod =
'surface-type'
60 clrskyMethod =
'clear'
61 cldskyMethod =
'cloudy'
62 mixskyMethod =
'mixed-clrcld'
63 allskyMethod =
'allsky'
64 cloudbandsMethod =
'cloudiness'
67 OkamotoMethod =
'Okamoto'
68 ScaleOkamotoMethod =
'ScaledOkamoto'
69 ModHarnischMethod =
'ModHarnisch'
70 ScaleModHarnischMethod =
'ScaledModHarnisch'
73 geoirlatlonboxMethod =
'geoirBox'
76 geoirlatlonBoxParams = defaultdict(list)
88 ahi_himawari8 =
'ahi_himawari8'
89 geoirlatlonBoxParams[
'values'] += [ahi_himawari8]
90 geoirlatlonBoxParams[
'centerLon'] += [140.7]
97 geoirlatlonBoxParams[
'values'] += [abi_g16]
98 geoirlatlonBoxParams[
'centerLon'] += [360. - 75.2]
110 mask = np.empty_like(x, bool)
111 if isinstance(bound, str):
112 mask = np.char.equal(x, bound)
114 finite = np.isfinite(x)
115 mask[finite] = np.equal(x[finite], bound)
116 mask[~finite] = missingValue
120 mask = np.empty_like(x, bool)
121 if isinstance(bound, str):
122 mask = np.char.not_equal(x, bound)
124 finite = np.isfinite(x)
125 mask[finite] = np.not_equal(x[finite], bound)
126 mask[~finite] = missingValue
130 assert isinstance(bounds, Iterable), \
131 (
'ERROR, bounds must be Iterable for notEqualAnyBound')
133 mask = np.full_like(x,
True, bool)
134 if isinstance(bounds[0], str):
136 mask = np.logical_and(mask,
137 np.char.not_equal(x, bound))
139 finite = np.isfinite(x)
141 mask[finite] = np.logical_and(mask[finite],
142 np.not_equal(x[finite], bound))
143 mask[~finite] = missingValue
147 finite = np.isfinite(x)
148 mask = np.empty_like(finite, bool)
149 mask[finite] = np.less_equal(x[finite], bound)
150 mask[~finite] = missingValue
153 def lessBound(x, bound, missingValue=True):
154 finite = np.isfinite(x)
155 mask = np.empty_like(finite, bool)
156 mask[finite] = np.less(x[finite], bound)
157 mask[~finite] = missingValue
161 finite = np.isfinite(x)
162 mask = np.empty_like(finite, bool)
163 mask[finite] = np.greater_equal(x[finite], bound)
164 mask[~finite] = missingValue
168 finite = np.isfinite(x)
169 mask = np.empty_like(finite, bool)
170 mask[finite] = np.greater(x[finite], bound)
171 mask[~finite] = missingValue
175 finite = np.isfinite(x)
178 mask = np.logical_not(np.logical_or(
179 belowbounds, abovebounds ))
180 mask[~finite] = missingValue
192 self.
baseVarsbaseVars.append(vu.senzenMeta)
193 self.
baseVarsbaseVars.append(vu.senaziMeta)
194 self.
baseVarsbaseVars.append(vu.solzenMeta)
195 self.
baseVarsbaseVars.append(vu.solaziMeta)
198 senazi = dbVals[insituParameters[vu.senaziMeta]]
199 solazi = dbVals[insituParameters[vu.solaziMeta]]
201 relazi = np.abs(np.subtract(solazi,senazi))
203 relazi[p] = np.subtract(360.0, relazi[p])
204 relazi = np.multiply(np.subtract(180.0, relazi), vu.deg2rad)
206 senzen = np.multiply(dbVals[insituParameters[vu.senzenMeta]], vu.deg2rad)
207 solzen = np.multiply(dbVals[insituParameters[vu.solzenMeta]], vu.deg2rad)
209 glint = np.add(np.multiply(np.cos(solzen), np.cos(senzen)),
210 np.multiply(np.sin(solzen),
211 np.multiply(np.sin(senzen), np.cos(relazi))))
216 glint = np.multiply(np.arccos(glint), vu.rad2deg)
217 glint[
greatBound(glint, maxGlint,
False)] = maxGlint
225 self.
baseVarsbaseVars.append(vu.datetimeMeta)
226 self.
baseVarsbaseVars.append(vu.lonMeta)
229 TimeStr = dbVals[insituParameters[vu.datetimeMeta]]
230 tzOffset = np.divide(dbVals[insituParameters[vu.lonMeta]], 15.0)
232 hh = np.empty_like(tzOffset, dtype=np.float32)
233 mmi = np.empty_like(tzOffset, dtype=np.float32)
234 ss = np.empty_like(tzOffset, dtype=np.float32)
239 for ii, Time
in enumerate(TimeStr):
244 hh[ii] = float(Time[11:13])
245 mmi[ii] = float(Time[14:16]) / 60.0
246 ss[ii] = float(Time[17:19]) / 3600.0
248 LH = hh + mmi + ss + tzOffset
250 yesterday = (LH < t0 - 0.5*dt)
251 LH[yesterday] = LH[yesterday] + 24.0
253 LH = np.mod(LH, 24.0)
255 tomorrow = (LH >= t1 + 0.5*dt)
256 LH[tomorrow] = LH[tomorrow] - 24.0
265 self.
baseVarsbaseVars.append(vu.selfObsValue)
267 self.
baseVarsbaseVars.append(vu.selfHofXValue)
268 self.
baseVarsbaseVars.append(vu.clrskyBTDiag)
272 BTobs = dbVals[insituParameters[vu.selfObsValue]]
275 BTbak = dbVals[insituParameters[vu.selfHofXValue]]
276 BTclr = deepcopy(dbVals[insituParameters[vu.clrskyBTDiag]])
280 ACI = np.subtract(np.abs(np.subtract(BTobs, BTclr)),
281 np.abs(np.subtract(BTbak, BTclr)))
300 osName = insituParameters[
'osName']
301 if osName
is None or osName
not in ABEIParams:
302 _logger.error(
'osName not available in ABEIParams => '+osName)
306 varName, ch = vu.splitIntSuffix(insituParameters[vu.selfHofXValue])
307 LambdaOverACI = ABEIParams[osName][(int(ch))][
'LambdaOverACI']
309 ACI = self.
ACIACI.
evaluate(dbVals, insituParameters)
310 lambdaOut = np.ones(ACI.shape)
312 lambdaOut[crit] = np.multiply(ACI[crit], LambdaOverACI) + self.
minLambdaminLambda
314 lambdaOut[crit] = self.
maxLambdamaxLambda
323 self.
baseVarsbaseVars.append(vu.selfObsValue)
325 self.
baseVarsbaseVars.append(vu.selfHofXValue)
326 self.
baseVarsbaseVars.append(vu.clrskyBTDiag)
333 BTobs = dbVals[insituParameters[vu.selfObsValue]]
336 BTbak = dbVals[insituParameters[vu.selfHofXValue]]
337 BTclr = deepcopy(dbVals[insituParameters[vu.clrskyBTDiag]])
338 BTclr[BTclr < 1.0] = BTbak[BTclr < 1.0]
339 SCI = np.multiply( 0.5,
340 np.add(np.abs(np.subtract(BTobs, BTclr)),
341 np.abs(np.subtract(BTbak, BTclr))) )
348 self.
baseVarsbaseVars.append(vu.selfObsValue)
350 self.
baseVarsbaseVars.append(vu.selfHofXValue)
351 self.
baseVarsbaseVars.append(vu.clrskyBTDiag)
352 self.
baseVarsbaseVars.append(vu.cldfracMeta)
355 BTobs = dbVals[insituParameters[vu.selfObsValue]]
358 BTbak = dbVals[insituParameters[vu.selfHofXValue]]
359 BTclr = deepcopy(dbVals[insituParameters[vu.clrskyBTDiag]])
360 BTclr[BTclr < 1.0] = BTbak[BTclr < 1.0]
361 CldFrac = dbVals[insituParameters[vu.cldfracMeta]]
370 SCI = np.multiply( 0.5,
373 np.abs(np.subtract(BTobs, BTclr))),
374 np.abs(np.subtract(BTbak, BTclr)) ) )
382 self.
baseVarsbaseVars.append(vu.selfObsValue)
384 self.
baseVarsbaseVars.append(vu.selfHofXValue)
385 self.
baseVarsbaseVars.append(vu.clrskyBTDiag)
389 BTobs = dbVals[insituParameters[vu.selfObsValue]]
392 BTbak = dbVals[insituParameters[vu.selfHofXValue]]
393 BTclr = deepcopy(dbVals[insituParameters[vu.clrskyBTDiag]])
394 BTclr[BTclr < 1.0] = BTbak[BTclr < 1.0]
395 zeros = np.full_like(BTbak,0.0)
396 SCI = np.multiply( 0.5,
397 np.add(np.maximum(zeros, np.subtract(BTclr, BTobs)),
398 np.maximum(zeros, np.subtract(BTclr, BTbak))) )
405 self.
baseVarsbaseVars.append(vu.selfObsValue)
407 self.
baseVarsbaseVars.append(vu.selfHofXValue)
408 self.
baseVarsbaseVars.append(vu.clrskyBTDiag)
409 self.
baseVarsbaseVars.append(vu.cldfracMeta)
413 BTobs = dbVals[insituParameters[vu.selfObsValue]]
416 BTbak = dbVals[insituParameters[vu.selfHofXValue]]
417 BTclr = deepcopy(dbVals[insituParameters[vu.clrskyBTDiag]])
418 BTclr[BTclr < 1.0] = BTbak[BTclr < 1.0]
419 CldFrac = dbVals[insituParameters[vu.cldfracMeta]]
421 zeros = np.full_like(BTbak,0.0)
422 SCI = np.multiply( 0.5,
424 np.add(np.maximum(zeros, np.subtract(BTclr, BTobs)),
425 np.maximum(zeros, np.subtract(BTclr, BTbak))) ) )
432 self.
baseVarsbaseVars.append(vu.selfObsValue)
434 self.
baseVarsbaseVars.append(vu.selfHofXValue)
435 self.
baseVarsbaseVars.append(vu.selfErrorValue)
438 BTerr = dbVals[insituParameters[vu.selfErrorValue]]
439 BTerr[BTerr==0.0] = np.NaN
441 BTobs = dbVals[insituParameters[vu.selfObsValue]]
442 BTbak = dbVals[insituParameters[vu.selfHofXValue]]
443 BTdep = np.subtract(BTbak, BTobs)
445 return np.divide(BTdep, BTerr)
450 biasCorrectType[
'abi_g16'] =
'constant'
451 biasCorrectType[
'ahi_himawari8'] =
None
457 self.
baseVarsbaseVars.append(vu.selfObsValue)
458 self.
baseVarsbaseVars.append(vu.selfHofXValue)
460 def evaluate(self, dbVals, insituParameters, SCISTDName, SCI):
473 osName = insituParameters[
'osName']
474 SCIErrParams = deepcopy(allSCIErrParams[(mpasFCRes,biasCorrectType.get(osName,
None))])
476 if osName
is None or osName
not in SCIErrParams:
477 _logger.error(
'osName not available in SCIErrParams => '+osName)
481 varName, ch = vu.splitIntSuffix(insituParameters[vu.selfHofXValue])
482 STD0 = SCIErrParams[osName][(int(ch), SCISTDName)][
'ERR'][0]
483 STD1 = SCIErrParams[osName][(int(ch), SCISTDName)][
'ERR'][1]
484 SCI0 = SCIErrParams[osName][(int(ch), SCISTDName)][
'X'][0]
485 SCI1 = SCIErrParams[osName][(int(ch), SCISTDName)][
'X'][1]
486 slope = (STD1 - STD0) / (SCI1 - SCI0)
492 BTerr = np.full_like(SCI, np.NaN)
493 BTerr[belowramp] = STD0
494 BTerr[onramp] = STD0 + slope * (SCI[onramp] - SCI0)
495 BTerr[aboveramp] = STD1
498 BTobs = dbVals[insituParameters[vu.selfObsValue]]
499 BTbak = dbVals[insituParameters[vu.selfHofXValue]]
500 BTdep = np.subtract(BTbak, BTobs)
502 return np.divide(BTdep, BTerr)
512 SCI = self.
SCISCI.
evaluate(dbVals, insituParameters)
513 return super().
evaluate(dbVals, insituParameters, OkamotoMethod, SCI)
523 SCI = self.
SCISCI.
evaluate(dbVals, insituParameters)
524 return super().
evaluate(dbVals, insituParameters, ScaleOkamotoMethod, SCI)
534 SCI = self.
SCISCI.
evaluate(dbVals, insituParameters)
535 return super().
evaluate(dbVals, insituParameters, ModHarnischMethod, SCI)
545 SCI = self.
SCISCI.
evaluate(dbVals, insituParameters)
546 return super().
evaluate(dbVals, insituParameters, ScaleModHarnischMethod, SCI)
565 self.
baseVarsbaseVars = deepcopy(baseVars)
568 def dbVars(self, varName, fileFormat, outerIters_):
571 if (
not isinstance(outerIters_, Iterable)
572 or isinstance(outerIters_,str)):
573 outerIters = [outerIters_]
575 outerIters = outerIters_
577 for baseVar
in self.
baseVarsbaseVars:
578 for outerIter
in outerIters:
579 dbVar = vu.base2dbVar(
580 baseVar, varName, fileFormat, outerIter)
582 return pu.uniqueMembers(dbVars)
590 return dbVals[insituParameters[self.
baseVarsbaseVars[0]]]
596 assert hasattr(self.
functionfunction,
'baseVars'), \
597 (
"ERROR, function class must have the baseVars attribute:", function)
606 self.
osNameosName = config[
'osName']
607 self.
fileFormatfileFormat = config[
'fileFormat']
609 variable = config[
'variable']
610 varIsString = isinstance(variable,str)
611 varIsClass = inspect.isclass(variable)
612 assert varIsString ^ varIsClass, \
613 (
"ERROR: 'variable' must either be a String or a Class", config)
626 insituParameters = {}
627 for baseVar
in self.
functionfunction.baseVars:
628 insituParameters[baseVar] = vu.base2dbVar(
629 baseVar, varName, self.
fileFormatfileFormat, outerIter)
630 insituParameters[
'osName'] = self.
osNameosName
642 self.
wherewhere = config[
'where']
643 tmp = config[
'bounds']
644 nBins = config[
'nBins']
653 ibins = list(range(nBins))
656 if (
not isinstance(tmp, Iterable)
or
657 isinstance(tmp, str)):
658 self.
boundsbounds = np.empty(nBins, dtype=type(tmp))
660 self.
boundsbounds[ii] = tmp
662 self.
boundsbounds = np.empty(nBins, dtype=type(tmp[0]))
667 self.
boundsbounds[ii] = tmp[0]
669 elif len(tmp) == nBins:
671 self.
boundsbounds[ii] = tmp[ii]
673 _logger.error(
"'bounds' must be a scalar, single-member Iterable, or an Iterable with the same length as 'values'!")
676 self.
except_diagsexcept_diags = config.get(
'except_diags', [])
677 self.
mask_valuemask_value = config.get(
'mask_value', np.NaN)
686 return pu.uniqueMembers(dbVars)
691 def apply(self, array, diagName, ibin):
692 newArray = deepcopy(array)
698 if len(mask) == len(newArray):
701 _logger.error(
'BinFilter mask is incorrectly defined!')
707 exclusiveDiags = [
'obs',
'bak',
'ana',
'SCI']
712 tmp = config[
'values']
714 if (
not isinstance(tmp, Iterable)
or
715 isinstance(tmp, str)):
716 self.
valuesvalues += [tmp]
720 self.
excludeDiagsexcludeDiags = deepcopy(exclusiveDiags)
721 override = config.get(
'override_exclusiveDiags',[])
722 for diag
in override:
727 fconf[
'osName'] = config[
'osName']
728 fconf[
'fileFormat'] = config[
'fileFormat']
729 fconf[
'nBins'] = len(self.
valuesvalues)
732 for filterConf
in config[
'filters']:
733 filterConf.update(fconf)
737 for Filter
in self.
filtersfilters:
738 if len(Filter.bounds) == len(self.
valuesvalues):
740 assert enoughBounds,
'\n\nERROR: BinMethod : at least one filter must have len(bounds) == len(values)!'
749 def dbVars(self, varName, outerIters=None):
751 for Filter
in self.
filtersfilters:
752 dbVars += Filter.dbVars(
754 return pu.uniqueMembers(dbVars)
757 for ii
in list(range(len(self.
filtersfilters))):
759 dbVals, varName, outerIter)
761 def apply(self, array, diagName, binVal):
762 ibin = self.
valuesvalues.index(binVal)
763 masked_array = deepcopy(array)
764 for Filter
in self.
filtersfilters:
765 masked_array = Filter.apply(
766 masked_array, diagName, ibin)
np.maximum(zeros, np.subtract(BTclr, BTbak)))
def evaluate(self, dbVals, insituParameters)
def evaluate(self, dbVals, insituParameters)
def dbVars(self, varName, fileFormat, outerIters_)
def __init__(self, baseVars)
def __init__(self, config)
def evaluate(self, dbVals, varName, outerIter)
def dbVars(self, varName, outerIters)
def apply(self, array, diagName, ibin)
def __init__(self, config)
def evaluate(self, dbVals, varName, outerIter)
def apply(self, array, diagName, binVal)
def dbVars(self, varName, outerIters=None)
def evaluate(self, dbVals, insituParameters)
def evaluate(self, dbVals, insituParameters)
def __init__(self, variable)
def evaluate(self, dbVals, insituParameters)
def evaluate(self, dbVals, insituParameters)
def evaluate(self, dbVals, insituParameters)
def evaluate(self, dbVals, insituParameters)
def __init__(self, function)
def dbVars(self, varName, outerIters)
def __init__(self, config)
def evaluate(self, dbVals, varName, outerIter)
def evaluate(self, dbVals, insituParameters)
def evaluate(self, dbVals, insituParameters)
def evaluate(self, dbVals, insituParameters, SCISTDName, SCI)
def evaluate(self, dbVals, insituParameters)
def evaluate(self, dbVals, insituParameters)
def evaluate(self, dbVals, insituParameters)
def evaluate(self, dbVals, insituParameters)
def evaluate(self, dbVals, insituParameters)
def notEqualAnyBound(x, bounds, missingValue=True)
def lessEqualBound(x, bound, missingValue=True)
def greatEqualBound(x, bound, missingValue=True)
def betweenBounds(x, bound1, bound2, missingValue=True)
def equalBound(x, bound, missingValue=True)
def greatBound(x, bound, missingValue=True)
def lessBound(x, bound, missingValue=True)
def notEqualBound(x, bound, missingValue=True)