3 import GenerateABEIFactorsArgs
5 from basic_plot_functions
import plotDistri
6 import binning_utils
as bu
7 import predefined_configs
as pconf
8 from collections
import defaultdict
9 from collections.abc
import Iterable
11 from copy
import deepcopy
12 import diag_utils
as du
15 from JediDB
import JediDB
16 from JediDBArgs
import obsFKey
20 import modelsp_utils
as modelUtils
21 import multiprocessing
as mp
22 from netCDF4
import Dataset
26 import stat_utils
as su
27 import var_utils
as vu
29 _logger = logging.getLogger(__name__)
33 Diagnose observation-space adaptive background error inflation
35 - static selections in conf
36 - command-line arguments in GenerateABEIFactorsArgs
40 self.
namename =
'GenerateABEIFactors'
41 self.
argsargs = GenerateABEIFactorsArgs.args
42 self.
loggerlogger = logging.getLogger(self.
namename)
50 self.
loggerlogger.info(
'database path: '+self.
argsargs.dbPath)
52 self.
osNamesosNames = self.
argsargs.IRInstruments.split(
',')
53 dbOSNames = list(self.
dbdb.ObsSpaceName.values())
55 for inst
in self.
osNamesosNames:
56 assert inst
in dbOSNames,
'GenerateABEIFactors::__init__ '+inst+
' not included in JediDB'
57 for osKey, osName
in self.
dbdb.ObsSpaceName.items():
59 self.
osKeysosKeys.append(osKey)
64 conducts diagnoseObsSpace across multiple ObsSpaces in parallel
67 for kk, osKey
in enumerate(self.
osKeysosKeys):
68 self.
loggerlogger.info(osKey)
85 'brightness_temperature_8',
86 'brightness_temperature_9',
87 'brightness_temperature_10',
91 binVarConfigs = defaultdict(list)
92 binVarConfigs[vu.obsVarQC] += [bu.goodQCMethod]
98 for binVarKey, binMethodKeys
in binVarConfigs.items():
99 binVarConfig = pconf.binVarConfigs.get(binVarKey,pconf.nullBinVarConfig)
100 for binMethodKey
in binMethodKeys:
101 config = binVarConfig.get(binMethodKey,pconf.nullBinMethod).copy()
103 if (len(config[
'values']) < 1
or
104 len(config[
'filters']) < 1):
continue
106 config[
'osName'] = ObsSpaceName
107 config[
'fileFormat'] = fileFormat
108 binMethods[(binVarKey,binMethodKey)] = bu.BinMethod(config)
114 return [
'ABEILambda']
119 for varName
in obsVars:
120 for diagName, diagnosticConfig
in diagnosticConfigs.items():
121 if 'ObsFunction' not in diagnosticConfig:
continue
124 for grpVar
in diagnosticConfig[
'ObsFunction'].dbVars(
125 varName, diagnosticConfig[
'outerIter']):
126 if diagnosticConfig[vu.mean]:
127 dbVars.append(grpVar)
130 for (binVarKey,binMethodKey), binMethod
in binMethods.items():
131 for grpVar
in binMethod.dbVars(
132 varName, diagnosticConfig[
'outerIter']):
133 dbVars.append(grpVar)
135 dbVars.append(vu.latMeta)
136 dbVars.append(vu.lonMeta)
143 logger = logging.getLogger(self.
namename+
'.diagnoseObsSpace('+osKey+
')')
147 db.initHandles(osKey)
153 ObsSpaceName = db.ObsSpaceName[osKey]
154 ObsSpaceInfo = conf.DiagSpaceConfig[ObsSpaceName]
155 ObsSpaceGrp = ObsSpaceInfo[
'DiagSpaceGrp']
170 diagnosticConfigs = du.diagnosticConfigs(
172 includeEnsembleDiagnostics =
False,
173 fileFormat = db.fileFormat(osKey, obsFKey))
190 dbVals = db.readVars(osKey, dbVars)
193 db.destroyHandles(osKey)
202 (modelLatsDeg, modelLonsDeg, EarthSphereR) = modelUtils.readGrid(gridFile=self.
argsargs.modelGridFile, returnR=
True)
203 modelLats = np.multiply(modelLatsDeg, np.pi / 180.0)
204 modelLons = np.multiply(modelLonsDeg, np.pi / 180.0)
206 modelTemplateVars = {}
207 for templateType, templateVar
in modelUtils.templateVariables.items():
208 modelTemplateVars[templateType] = {
209 'values': modelUtils.varRead(templateVar, self.
argsargs.modelGridFile),
210 'dims': modelUtils.varDims(templateVar, self.
argsargs.modelGridFile),
214 obsLatsDeg = dbVals[vu.latMeta]
215 obsLonsDeg = dbVals[vu.lonMeta]
216 obsLats = np.multiply(obsLatsDeg, np.pi / 180.0)
217 obsLons = np.multiply(obsLonsDeg, np.pi / 180.0)
218 obsnLocs = len(obsLons)
222 modelLons, modelLats,
223 weightMethod =
'barycentric',
224 Radius = EarthSphereR)
225 model2obs.initWeights(obsLons, obsLats)
230 diagColors[
'ABEILambda'] =
'BuPu'
231 minmaxValue[
'ABEILambda'] = [
232 bu.ABEILambda().minLambda,
233 bu.ABEILambda().maxLambda,
236 for diagName, diagnosticConfig
in diagnosticConfigs.items():
237 if 'ObsFunction' not in diagnosticConfig:
continue
239 logger.info(
'Calculating/writing diagnostic stats for:')
240 logger.info(
'Diagnostic => '+diagName)
241 Diagnostic = diagnosticConfig[
'ObsFunction']
242 outerIter = diagnosticConfig[
'outerIter']
244 for varName
in obsVars:
245 logger.info(
'Variable => '+varName)
247 varShort, varUnits = vu.varAttributes(varName)
249 Diagnostic.evaluate(dbVals, varName, outerIter)
250 diagValues = Diagnostic.result
251 nLocs = len(diagValues)-np.isnan(diagValues).sum()
254 logger.warning(
'All missing values for diagnostic: '+diagName)
256 for (binVarKey,binMethodKey), binMethod
in binMethods.items():
257 if diagName
in binMethod.excludeDiags:
continue
259 binVarName, binGrpName = vu.splitObsVarGrp(binVarKey)
260 binVarShort, binVarUnits = vu.varAttributes(binVarName)
265 binMethod.evaluate(dbVals, varName, outerIter)
267 for binVal
in binMethod.values:
269 binnedDiagnostic = binMethod.apply(diagValues,diagName,binVal)
272 if self.
argsargs.plotLambda:
273 logger.info(
'plotting obs-space diagnostic')
275 color = diagColors[diagName]
276 minmax = minmaxValue.get(diagName, [
None,
None])
277 nLocs = len(binnedDiagnostic)-np.isnan(binnedDiagnostic).sum()
279 obsLatsDeg, obsLonsDeg, binnedDiagnostic,
280 osName, varShort, varUnits, osName+
'_'+binVarName+
'='+binVal,
282 minmax[0], minmax[1], dotsize, color)
286 if diagName ==
'ABEILambda':
287 lambdaVarName =
'modelLambda_'+varShort
288 resetLambda = localConfig.get(
'resetLambda',
True)
289 inflationFile = varShort+
'_'+self.
argsargs.inflationFile
291 if not os.path.exists(inflationFile)
or resetLambda:
293 logger.info(
'creating fresh inflation file')
294 modelUtils.createHeaderOnlyFile(
295 self.
argsargs.modelGridFile,
297 date = self.
argsargs.datetime,
300 if modelUtils.hasVar(lambdaVarName, inflationFile):
302 modelLambda = modelUtils.varRead(lambdaVarName, inflationFile)
304 modelLambda = np.full_like(modelTemplateVars[
'1D-c'][
'values'],
305 bu.ABEILambda().minLambda)
311 logger.info(
'projecting inflation factors to model space')
312 for obsInd, (obsLambda, obsLat, obsLon)
in enumerate(list(zip(
313 binnedDiagnostic, obsLats, obsLons))):
314 if np.isfinite(obsLambda):
317 modelLons, modelLats,
320 rho = np.zeros(scales.shape)
329 rho[crit] = np.exp(- (scales[crit] ** 2) / 2.0)
330 crit = (np.abs(rho) > 0.0)
331 modelLocInds = np.arange(0, len(rho))[crit]
334 interpLambda = model2obs.applyAtIndex(modelLambda, obsInd)
337 modelLambda[modelLocInds] = modelLambda[modelLocInds] + \
338 rho[crit] * (obsLambda - interpLambda)
341 modelLambda[modelLambda < bu.ABEILambda().minLambda] = \
342 bu.ABEILambda().minLambda
344 if self.
argsargs.plotLambda:
346 logger.info(
'plotting model-space inflation factors')
348 color = diagColors[diagName]
349 minmax = minmaxValue.get(diagName, [
None,
None])
351 modelLatsDeg, modelLonsDeg, modelLambda,
352 'model-'+osName.upper()+
' '+diagName, varShort,
'',
353 'model-'+osName+
'_'+binVarName+
'='+binVal,
355 minmax[0], minmax[1], dotsize, color)
357 logger.info(
'writing inflation factors to NC file')
362 'long_name':
'Column-wise Inflation factor derived from '+varShort,
365 modelUtils.varWrite(lambdaVarName, modelLambda, inflationFile,
366 attrs, modelTemplateVars[
'1D-c'][
'dims'],
'double')
369 for modelInflateVarName
in modelUtils.inflationVariables:
370 templateInfo = modelUtils.variableTraits[modelInflateVarName]
371 if modelUtils.hasVar(modelInflateVarName, self.
argsargs.modelGridFile):
372 templateVarName = modelInflateVarName
374 'attrs': modelUtils.varAttrs(modelInflateVarName, self.
argsargs.modelGridFile),
377 templateVarName = modelUtils.templateVariables[templateInfo[
'templateVar']]
380 'units': templateInfo[
'units'],
381 'long_name': templateInfo[
'long_name'],
384 templateVar[
'values'] = modelUtils.varRead(templateVarName, self.
argsargs.modelGridFile)
385 templateVar[
'dims'] = modelUtils.varDims(templateVarName, self.
argsargs.modelGridFile)
386 templateVar[
'datatype'] = modelUtils.varDatatype(templateVarName, self.
argsargs.modelGridFile)
388 shape = templateVar[
'values'].shape
391 modelInflateVar = modelLambda
393 modelInflateVar = np.empty_like(templateVar[
'values'])
394 for level
in np.arange(0, shape[1]):
395 modelInflateVar[:,level] = modelLambda
397 modelUtils.varWrite(modelInflateVarName, modelInflateVar, inflationFile,
398 templateVar[
'attrs'], templateVar[
'dims'], templateVar[
'datatype'],
410 _logger.info(
'Starting '+__name__)
417 _logger.info(
'Finished '+__name__+
' successfully')
419 if __name__ ==
'__main__':
main()
def getBinMethods(binVarConfigs, ObsSpaceName, fileFormat)
def diagnoseObsSpace(self, db, osKey, localConfig)
def getObsVars(self, db, osKey)
def getDBVars(obsVars, binMethods, diagnosticConfigs)
def HaversineDistance(lon1, lat1, lon2, lat2, R=1.)
def plotDistri(lats, lons, values, ObsType, VarName, var_unit, out_name, nstation, levbin, dmin=None, dmax=None, dotsize=6, color="rainbow")