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)