rda-python-icoads 1.0.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of rda-python-icoads might be problematic. Click here for more details.
- rda_python_icoads/PgIMMA.py +1785 -0
- rda_python_icoads/README_R3.0_Subset.html +154 -0
- rda_python_icoads/__init__.py +1 -0
- rda_python_icoads/imma1_subset.py +764 -0
- rda_python_icoads/rdimma1_csv.f +443 -0
- rda_python_icoads-1.0.1.dist-info/LICENSE +21 -0
- rda_python_icoads-1.0.1.dist-info/METADATA +20 -0
- rda_python_icoads-1.0.1.dist-info/RECORD +11 -0
- rda_python_icoads-1.0.1.dist-info/WHEEL +5 -0
- rda_python_icoads-1.0.1.dist-info/entry_points.txt +2 -0
- rda_python_icoads-1.0.1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,764 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
#
|
|
3
|
+
##################################################################################
|
|
4
|
+
#
|
|
5
|
+
# Title : imma1_subset
|
|
6
|
+
# Author : Zaihua Ji, zji@ucar.edu
|
|
7
|
+
# Date : 01/04/2021
|
|
8
|
+
# 2025-02-18 transferred to package rda_python_icoads from
|
|
9
|
+
# https://github.com/NCAR/rda-icoads.git
|
|
10
|
+
# Purpose : process ICOADS requests under control of dsrqst
|
|
11
|
+
# for data in PostgreSQL IVADDB in IMMA1 format
|
|
12
|
+
#
|
|
13
|
+
# Github: https://github.com/NCAR/rda-python-icoads.git
|
|
14
|
+
#
|
|
15
|
+
##################################################################################
|
|
16
|
+
|
|
17
|
+
import sys
|
|
18
|
+
import os
|
|
19
|
+
import re
|
|
20
|
+
import glob
|
|
21
|
+
from os import path as op
|
|
22
|
+
from rda_python_common import PgLOG
|
|
23
|
+
from rda_python_common import PgDBI
|
|
24
|
+
from rda_python_common import PgSIG
|
|
25
|
+
from rda_python_common import PgUtil
|
|
26
|
+
from rda_python_common import PgFile
|
|
27
|
+
from rda_python_common import PgOPT
|
|
28
|
+
from rda_python_dsrqst import PgSubset
|
|
29
|
+
from . import PgIMMA
|
|
30
|
+
|
|
31
|
+
IDSID = 'd548000'
|
|
32
|
+
VAR2DB = {'IS' : "ics"}
|
|
33
|
+
PVALS = {
|
|
34
|
+
'codedir' : op.dirname(op.abspath(__file__)) + '/',
|
|
35
|
+
'rdimma1' : "rdimma1_csv.f",
|
|
36
|
+
'readhtml' : "README_R3.0_Subset.html",
|
|
37
|
+
'readme' : "readme_imma1.",
|
|
38
|
+
'html2pdf' : "wkhtmltopdf",
|
|
39
|
+
'resol' : 0.02,
|
|
40
|
+
'trmcnt' : 0, # count of trim variables selected
|
|
41
|
+
'dates' : [], # [bdate, edate]
|
|
42
|
+
'lats' : [], # [slat, nlat]
|
|
43
|
+
'lons' : [], # [wlon, elon]
|
|
44
|
+
'flts' : [],
|
|
45
|
+
'vars' : [],
|
|
46
|
+
'fmts' : {},
|
|
47
|
+
'rinfo' : {},
|
|
48
|
+
'vinfo' : {},
|
|
49
|
+
'tidx' : [],
|
|
50
|
+
'facnt' : 0, # full attm count, for Reanqc and Ivad attms
|
|
51
|
+
'bdate' : [],
|
|
52
|
+
'edate' : [],
|
|
53
|
+
'fachar' : 97, # chr(97) = 'a'
|
|
54
|
+
# hash array if specified
|
|
55
|
+
'pts' : [],
|
|
56
|
+
'dcks' : [],
|
|
57
|
+
'sids' : [],
|
|
58
|
+
'iopts' : 0,
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
FAVARS = {} # hash of ireanqc and iivad, values are selected source name-var
|
|
62
|
+
FSFLDS = {} # hash of selected data variables in FACNDS
|
|
63
|
+
FSSRCS = {} # hash of ireanqc and iivad, values are array of selected source names
|
|
64
|
+
FSCNDS = {} # hash of ireanqc and iivad, values are array of conditions for variables in FSFLDS
|
|
65
|
+
FACNDS = {
|
|
66
|
+
'ERA-20C' : 'dprp = 1',
|
|
67
|
+
'CERA-20C' : 'dprp = 2',
|
|
68
|
+
'FS01' : "arci = 'FS01'",
|
|
69
|
+
'BKT' : "arci = ' BKT'"
|
|
70
|
+
} # additional condition for full attm
|
|
71
|
+
FAFLDS = {'d' : [0, 18], 'w' : [0, 20], 'slp' : [0, 25], 'at' : [0, 29]}
|
|
72
|
+
FASRCS = {
|
|
73
|
+
'ERA-20C' : ['d', 'w', 'slp', 'at'],
|
|
74
|
+
'CERA-20C' : ['d', 'w', 'slp', 'at'],
|
|
75
|
+
'FS01' : ['w'],
|
|
76
|
+
'BKT' : ['at']
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
TRIMS = {'sst' : 0, 'at' : 0, 'd' : 0, 'w' : 0, 'slp' : 0, 'wbt' : 0, 'dpt' : 0, 'rh' : 0}
|
|
80
|
+
|
|
81
|
+
# Optional attms for subset. Append var-list to Replace <OPTATTMS> in the README template file
|
|
82
|
+
OPTATTMS = {
|
|
83
|
+
'headline' : "<h2>Details for optional selections</h2>\n<ul>\n",
|
|
84
|
+
'iimmt5' : "<li>P/V <i>Immt</i>, <a href=\"http://rda.ucar.edu/datasets/" + IDSID + "/docs/R3.0-imma1.pdf#page=37\">Table C5, page 37</a>\n<ul><li><i>\n",
|
|
85
|
+
'imodqc' : "<li>P/V <i>Mod-qc</i>, <a href=\"http://rda.ucar.edu/datasets/" + IDSID + "/docs/R3.0-imma1.pdf#page=38\">Table C6, page 38</a>\n<ul><li><i>\n",
|
|
86
|
+
'imetavos' : "<li>P/V <i>Meta-vos</i>, <a href=\"http://rda.ucar.edu/datasets/" + IDSID + "/docs/R3.0-imma1.pdf#page=39\">Table C7, page 39</a><ul><li><i>\n",
|
|
87
|
+
'inocn' : "<li>P/V <i>Nocn</i>, <a href=\"http://rda.ucar.edu/datasets/" + IDSID + "/docs/R3.0-imma1.pdf#page=40\">Table C8, page 40</a><ul><li><i>\n",
|
|
88
|
+
'iecr' : "<li>P/V <i>Ecr</i>, <a href=\"http://rda.ucar.edu/datasets/" + IDSID + "/docs/R3.0-imma1.pdf#page=41\">Table C9, page 41</a><ul><li><i>\n",
|
|
89
|
+
'ireanqc' : "<li>P/V <i>Rean-qc</i>, <a href=\"http://rda.ucar.edu/datasets/" + IDSID + "/docs/R3.0-imma1.pdf#page=42\">Table C95, page 42</a><ul>\n",
|
|
90
|
+
'iivad' : "<li>P/V <i>Ivad</i>, <a href=\"http://rda.ucar.edu/datasets/" + IDSID + "/docs/R3.0-imma1.pdf#page=43\">Table C96, page 43</a><ul>\n"
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
PGRQST = PGFILE = None
|
|
94
|
+
pgcmd = 'imma1_subset'
|
|
95
|
+
PSTEP = 32
|
|
96
|
+
|
|
97
|
+
#
|
|
98
|
+
# main function to run dsarch
|
|
99
|
+
#
|
|
100
|
+
def main():
|
|
101
|
+
|
|
102
|
+
global PGRQST, PGFILE
|
|
103
|
+
|
|
104
|
+
PgLOG.PGLOG['LOGFILE'] = "icoads.log"
|
|
105
|
+
argv = sys.argv[1:]
|
|
106
|
+
option = rdir = None
|
|
107
|
+
fidx = ridx = 0
|
|
108
|
+
|
|
109
|
+
for arg in argv:
|
|
110
|
+
if arg == "-b":
|
|
111
|
+
PgLOG.PGLOG['BCKGRND'] = 1
|
|
112
|
+
elif arg == "-d":
|
|
113
|
+
PgLOG.PGLOG['DBGLEVEL'] = 1000
|
|
114
|
+
elif arg == "-f":
|
|
115
|
+
option = 'f'
|
|
116
|
+
elif re.match(r'^-', arg):
|
|
117
|
+
PgLOG.pglog(arg + ": Unknown Option", PgLOG.LGEREX)
|
|
118
|
+
elif option and option == 'f':
|
|
119
|
+
fidx = int(arg)
|
|
120
|
+
option = None
|
|
121
|
+
elif re.match(r'^(\d+)$', arg):
|
|
122
|
+
if ridx == 0:
|
|
123
|
+
ridx = int(arg)
|
|
124
|
+
else:
|
|
125
|
+
PgLOG.pglog("{}: Request Index ({}) given already".format(arg, ridx), PgLOG.LGEREX)
|
|
126
|
+
else:
|
|
127
|
+
if rdir: PgLOG.pglog("{}: Request Directory ({}) given already".format(arg, rdir), PgLOG.LGEREX)
|
|
128
|
+
rdir = arg
|
|
129
|
+
|
|
130
|
+
PgLOG.cmdlog("{} {}".format(pgcmd, ' '.join(argv)))
|
|
131
|
+
PgDBI.dssdb_scname()
|
|
132
|
+
if fidx:
|
|
133
|
+
PGFILE = PgDBI.pgget('wfrqst', '*', "findex = {}".format(fidx), PgLOG.LGEREX)
|
|
134
|
+
if ridx == 0: ridx = PGFILE['rindex']
|
|
135
|
+
PGRQST = PgSubset.valid_subset_request(ridx, rdir, IDSID, PgLOG.LGWNEX)
|
|
136
|
+
if not rdir: rdir = PgLOG.join_paths(PgLOG.PGLOG['RQSTHOME'], PGRQST['rqstid'])
|
|
137
|
+
rstr = "{}-Rqst{}".format(PGRQST['dsid'], ridx)
|
|
138
|
+
if fidx > 0: rstr += "-" + PGFILE['wfile']
|
|
139
|
+
|
|
140
|
+
if fidx:
|
|
141
|
+
process_subset_file(ridx, fidx, rdir, rstr)
|
|
142
|
+
else:
|
|
143
|
+
process_subset_request(ridx, rdir, rstr)
|
|
144
|
+
|
|
145
|
+
PgLOG.cmdlog()
|
|
146
|
+
sys.exit(0)
|
|
147
|
+
|
|
148
|
+
#
|
|
149
|
+
# set the table info array
|
|
150
|
+
#
|
|
151
|
+
def get_table_info(dates):
|
|
152
|
+
|
|
153
|
+
bdate = PgUtil.validate_date(dates[0])
|
|
154
|
+
edate = PgUtil.validate_date(dates[1])
|
|
155
|
+
cnd = "bdate <= '{}' AND edate >= '{}'".format(edate, bdate)
|
|
156
|
+
pgrecs = PgDBI.pgmget('itable', "tidx, bdate, edate", cnd + " ORDER BY tidx", PgLOG.LGEREX)
|
|
157
|
+
tcnt = len(pgrecs['tidx']) if pgrecs else 0
|
|
158
|
+
if not tcnt: PgLOG.pglog("No table index found in dssdb.itable for " + cnd, PgLOG.LGEREX)
|
|
159
|
+
PVALS['tidx'] = pgrecs['tidx']
|
|
160
|
+
PVALS['bdate'] = [bdate]
|
|
161
|
+
PVALS['bdate'].extend([str(d) for d in pgrecs['bdate'][1:]])
|
|
162
|
+
PVALS['edate'] = [str(d) for d in pgrecs['edate'][:-1]]
|
|
163
|
+
PVALS['edate'].append(edate)
|
|
164
|
+
|
|
165
|
+
return tcnt
|
|
166
|
+
|
|
167
|
+
#
|
|
168
|
+
# get the float format string
|
|
169
|
+
#
|
|
170
|
+
def get_float_format(resl):
|
|
171
|
+
|
|
172
|
+
prec = 0
|
|
173
|
+
while resl < 1:
|
|
174
|
+
prec += 1
|
|
175
|
+
resl *=10
|
|
176
|
+
|
|
177
|
+
return r'{:.%df}' % prec if prec else ''
|
|
178
|
+
|
|
179
|
+
#
|
|
180
|
+
# set variable information
|
|
181
|
+
#
|
|
182
|
+
def set_var_info():
|
|
183
|
+
|
|
184
|
+
vars = PVALS['vars']
|
|
185
|
+
flts = PVALS['flts']
|
|
186
|
+
anames = []
|
|
187
|
+
tcodes = []
|
|
188
|
+
avars = {}
|
|
189
|
+
ovars = {}
|
|
190
|
+
uvars = {}
|
|
191
|
+
dvars = {}
|
|
192
|
+
alens = {}
|
|
193
|
+
aprecs = {}
|
|
194
|
+
fmts = {}
|
|
195
|
+
maxs = {}
|
|
196
|
+
fscnts = {}
|
|
197
|
+
|
|
198
|
+
vcnt = len(vars)
|
|
199
|
+
pname = ''
|
|
200
|
+
for i in range(vcnt):
|
|
201
|
+
uvar = ovar = vars[i].upper()
|
|
202
|
+
if ovar in VAR2DB:
|
|
203
|
+
var = VAR2DB[ovar]
|
|
204
|
+
else:
|
|
205
|
+
var = ovar.lower()
|
|
206
|
+
|
|
207
|
+
if var in TRIMS:
|
|
208
|
+
TRIMS[var] = 1
|
|
209
|
+
PVALS['trmcnt'] +=1
|
|
210
|
+
|
|
211
|
+
vinfo = PVALS['vinfo'][var] = PgIMMA.name2number(var)
|
|
212
|
+
aname = vinfo[2]
|
|
213
|
+
if aname != pname:
|
|
214
|
+
anames.append(aname)
|
|
215
|
+
avars[aname] = []
|
|
216
|
+
ovars[aname] = []
|
|
217
|
+
uvars[aname] = []
|
|
218
|
+
dvars[aname] = []
|
|
219
|
+
aprecs[aname] = []
|
|
220
|
+
imma = PgIMMA.IMMAS[aname]
|
|
221
|
+
attm = imma[3]
|
|
222
|
+
tcodes.append("C{}".format(vinfo[0]))
|
|
223
|
+
pname = aname
|
|
224
|
+
|
|
225
|
+
avars[aname].append(var)
|
|
226
|
+
ovars[aname].append(ovar)
|
|
227
|
+
prec = attm[var][2]
|
|
228
|
+
aprecs[aname].append(prec)
|
|
229
|
+
vfld = attm[var]
|
|
230
|
+
vlen = len(vfld)
|
|
231
|
+
if prec > 0 and prec < 1:
|
|
232
|
+
fmts[var] = get_float_format(prec)
|
|
233
|
+
if vlen > 5:
|
|
234
|
+
unit = vfld[5]
|
|
235
|
+
if unit.find('deg') > -1: unit.replace('deg', '°')
|
|
236
|
+
uvar += "({})".format(unit)
|
|
237
|
+
if vlen > 6: maxs[var] = vfld[6]
|
|
238
|
+
uvars[aname].append(uvar)
|
|
239
|
+
if vlen > 4 and vfld[4] == 0:
|
|
240
|
+
dvars[aname].append(var)
|
|
241
|
+
if var in FAFLDS: FSFLDS[var] = FAFLDS[var]
|
|
242
|
+
|
|
243
|
+
set_full_attm_info("iuida", anames, tcodes, avars, aprecs)
|
|
244
|
+
|
|
245
|
+
aname = "ireanqc"
|
|
246
|
+
fscnts[aname] = set_full_attm_count(aname, "fnr")
|
|
247
|
+
if fscnts[aname]:
|
|
248
|
+
set_full_attm_info(aname, anames, tcodes, avars, aprecs)
|
|
249
|
+
PVALS['facnt'] += 1
|
|
250
|
+
|
|
251
|
+
aname = "iivad"
|
|
252
|
+
fscnts[aname] = set_full_attm_count(aname, "fni")
|
|
253
|
+
if fscnts[aname]:
|
|
254
|
+
set_full_attm_info(aname, anames, tcodes, avars, aprecs)
|
|
255
|
+
PVALS['facnt'] += 1
|
|
256
|
+
|
|
257
|
+
# create headline and optional document
|
|
258
|
+
vhead = vcore = optattms = ''
|
|
259
|
+
facnt = len(anames)
|
|
260
|
+
acnt = facnt - PVALS['facnt'] - 1
|
|
261
|
+
for i in range(acnt):
|
|
262
|
+
aname = anames[i]
|
|
263
|
+
vinfo = ','.join(ovars[aname])
|
|
264
|
+
if vhead: vhead += ","
|
|
265
|
+
vhead += vinfo
|
|
266
|
+
uinfo = ','.join(uvars[aname])
|
|
267
|
+
if aname in OPTATTMS:
|
|
268
|
+
optattms += OPTATTMS[aname] + PgLOG.break_long_string(uinfo, 60, "<br>", 20, ",") + "</i></li></ul></li>\n"
|
|
269
|
+
elif aname == 'icoreloc':
|
|
270
|
+
vcore = uinfo
|
|
271
|
+
if 'icorereg' not in ovars:
|
|
272
|
+
PVALS['rinfo']['C0LIST'] = PgLOG.break_long_string(vcore, 60, "<br>", 20, ",")
|
|
273
|
+
elif aname == 'icorereg':
|
|
274
|
+
vcore += ',' + uinfo
|
|
275
|
+
PVALS['rinfo']['C0LIST'] = PgLOG.break_long_string(vcore, 60, "<br>", 20, ",")
|
|
276
|
+
else:
|
|
277
|
+
lkey = tcodes[i] + "LIST"
|
|
278
|
+
PVALS['rinfo'][lkey] = PgLOG.break_long_string(uinfo, 60, "<br>", 20, ",")
|
|
279
|
+
|
|
280
|
+
# add attm Uida variables to
|
|
281
|
+
vinfo = ','.join(avars['iuida'])
|
|
282
|
+
vhead += "," + vinfo.upper()
|
|
283
|
+
acnt += 1
|
|
284
|
+
|
|
285
|
+
for i in range(acnt, facnt):
|
|
286
|
+
aname = anames[i]
|
|
287
|
+
optattms += OPTATTMS[aname]
|
|
288
|
+
if fscnts[aname] > 1:
|
|
289
|
+
j = PVALS['fachar']
|
|
290
|
+
for favar in FAVARS[aname]:
|
|
291
|
+
fachar = chr(j)
|
|
292
|
+
j += 1
|
|
293
|
+
vinfo = ''
|
|
294
|
+
for var in avars[aname]:
|
|
295
|
+
if vinfo: vinfo += ","
|
|
296
|
+
vinfo += "{}-{}".format(fachar, var.upper())
|
|
297
|
+
vhead += "," + vinfo
|
|
298
|
+
optattms += "<li><i>" + PgLOG.break_long_string("{} => {}: {}".format(favar, fachar, vinfo), 60, "<br>", 20, ",") + "</i></li>\n"
|
|
299
|
+
else:
|
|
300
|
+
favar = FAVARS[aname][0]
|
|
301
|
+
vinfo = ''
|
|
302
|
+
for var in avars[aname]:
|
|
303
|
+
if vinfo: vinfo += ","
|
|
304
|
+
vinfo += var.upper()
|
|
305
|
+
vhead += "," + vinfo
|
|
306
|
+
optattms += "<li><i>" + PgLOG.break_long_string("{}: {}".format(favar, vinfo), 60, "<br>", 20, ",") + "</i></li>\n"
|
|
307
|
+
optattms += "</ul></li>\n"
|
|
308
|
+
|
|
309
|
+
PVALS['vhead'] = vhead
|
|
310
|
+
if optattms: PVALS['rinfo']['OPTATTMS'] = "{}{}</ul>".format(OPTATTMS['headline'], optattms)
|
|
311
|
+
PVALS['anames'] = anames
|
|
312
|
+
PVALS['avars'] = avars
|
|
313
|
+
PVALS['aprecs'] = aprecs
|
|
314
|
+
PVALS['dvars'] = dvars
|
|
315
|
+
PVALS['fmts'] = fmts
|
|
316
|
+
PVALS['maxs'] = maxs
|
|
317
|
+
|
|
318
|
+
wlon = int(100*PVALS['lons'][0])
|
|
319
|
+
elon = int(100*PVALS['lons'][1])
|
|
320
|
+
slat = int(100*PVALS['lats'][0])
|
|
321
|
+
nlat = int(100*PVALS['lats'][1])
|
|
322
|
+
if wlon == 0 and elon == 36000:
|
|
323
|
+
loncnd = ''
|
|
324
|
+
elif wlon == elon:
|
|
325
|
+
loncnd = "lon = {}".format(elon)
|
|
326
|
+
elif wlon > elon:
|
|
327
|
+
loncnd = "(lon >= {} OR lon <= {})".format(wlon, elon)
|
|
328
|
+
elif wlon > 0 and elon < 36000:
|
|
329
|
+
loncnd = " lon between {} AND {}".format(wlon, elon)
|
|
330
|
+
elif elon < 36000:
|
|
331
|
+
loncnd = "lon <= {}".format(elon)
|
|
332
|
+
elif wlon > 0:
|
|
333
|
+
loncnd = "lon >= {}".format(wlon)
|
|
334
|
+
else:
|
|
335
|
+
loncnd = ''
|
|
336
|
+
|
|
337
|
+
if slat == -9000 and nlat == 9000:
|
|
338
|
+
latcnd = ''
|
|
339
|
+
elif slat == nlat:
|
|
340
|
+
latcnd = "lat = {}".format(slat)
|
|
341
|
+
elif slat > -9000 and nlat < 9000:
|
|
342
|
+
latcnd = " lat between {} AND {}".format(slat, nlat)
|
|
343
|
+
elif nlat < 9000:
|
|
344
|
+
latcnd = "lat <= {}".format(nlat)
|
|
345
|
+
else:
|
|
346
|
+
latcnd = "lat >= {}".format(slat)
|
|
347
|
+
|
|
348
|
+
if latcnd and loncnd:
|
|
349
|
+
PVALS['spcnd'] = "{} AND {}".format(latcnd, loncnd)
|
|
350
|
+
elif latcnd:
|
|
351
|
+
PVALS['spcnd'] = latcnd
|
|
352
|
+
elif loncnd:
|
|
353
|
+
PVALS['spcnd'] = loncnd
|
|
354
|
+
else:
|
|
355
|
+
PVALS['spcnd'] = ''
|
|
356
|
+
|
|
357
|
+
PVALS['fopts'] = {'OPDN' : flts[0], 'OPPT' : flts[1], 'OPSE' : flts[2],
|
|
358
|
+
'OPCQ' : flts[3], 'OPTF' : flts[4], 'OP11' : flts[5]}
|
|
359
|
+
|
|
360
|
+
#
|
|
361
|
+
# set counts for the included full attms
|
|
362
|
+
#
|
|
363
|
+
def set_full_attm_count(aname, cname):
|
|
364
|
+
|
|
365
|
+
if aname not in FSSRCS: return 0
|
|
366
|
+
|
|
367
|
+
vcnt = 0
|
|
368
|
+
for sname in FSSRCS[aname]:
|
|
369
|
+
fv = []
|
|
370
|
+
fn = []
|
|
371
|
+
for var in FASRCS[sname]:
|
|
372
|
+
if var in FSFLDS and FSFLDS[var]:
|
|
373
|
+
fv.append("{}-{}".format(sname, var.upper()))
|
|
374
|
+
fn.append(" AND {} AND {} = {}".format(FACNDS[sname], cname, FSFLDS[var][1]))
|
|
375
|
+
vcnt += 1
|
|
376
|
+
if fv: FAVARS[aname] = fv
|
|
377
|
+
if fn: FSCNDS[aname] = fn
|
|
378
|
+
|
|
379
|
+
return vcnt
|
|
380
|
+
|
|
381
|
+
#
|
|
382
|
+
# set information for the included full attms
|
|
383
|
+
#
|
|
384
|
+
def set_full_attm_info(aname, anames, tcodes, avars, aprecs):
|
|
385
|
+
|
|
386
|
+
anames.append(aname)
|
|
387
|
+
imma = PgIMMA.IMMAS[aname]
|
|
388
|
+
attm = imma[3]
|
|
389
|
+
avars[aname] = PgIMMA.order_attm_variables(attm)
|
|
390
|
+
if aname not in aprecs: aprecs[aname] = []
|
|
391
|
+
tcodes.append("C" + imma[1])
|
|
392
|
+
for var in avars[aname]:
|
|
393
|
+
aprecs[aname].append(attm[var][2])
|
|
394
|
+
|
|
395
|
+
#
|
|
396
|
+
# process a validated subset request
|
|
397
|
+
#
|
|
398
|
+
def process_subset_request(ridx, rdir, rstr):
|
|
399
|
+
|
|
400
|
+
ptcnt = PGRQST['ptcount']
|
|
401
|
+
if ptcnt > 0 and check_request_built(ridx, ptcnt, rstr) != 1: return
|
|
402
|
+
|
|
403
|
+
get_subset_info(rstr)
|
|
404
|
+
|
|
405
|
+
if ptcnt > 0:
|
|
406
|
+
PgFile.change_local_directory(rdir, PgLOG.LOGWRN)
|
|
407
|
+
build_final_files(ridx, rstr)
|
|
408
|
+
else:
|
|
409
|
+
tcnt = get_table_info(PVALS['dates'])
|
|
410
|
+
for i in range(tcnt):
|
|
411
|
+
bdate = PVALS['edate'][i]
|
|
412
|
+
edate = PVALS['edate'][i]
|
|
413
|
+
tidx = PVALS['tidx'][i]
|
|
414
|
+
pgrec = {}
|
|
415
|
+
pgrec['data_format'] = 'ASCII'
|
|
416
|
+
pgrec['disp_order'] = i+1
|
|
417
|
+
pgrec['command'] = PVALS['pgcmd'] + " -f -FI"
|
|
418
|
+
pgrec['cmd_detail'] = "dates={} {}&tidx={}".format(bdate, edate, tidx)
|
|
419
|
+
fname = "ICOADS_R3.0_Rqst{}_{}-{}.csv".format(ridx, bdate, edate)
|
|
420
|
+
PgSubset.add_request_file(ridx, fname, pgrec, PgLOG.LGEREX)
|
|
421
|
+
|
|
422
|
+
#
|
|
423
|
+
# process a validated subset request file
|
|
424
|
+
#
|
|
425
|
+
def process_subset_file(ridx, fidx, rdir, rstr):
|
|
426
|
+
|
|
427
|
+
if PGFILE['status'] == 'O':
|
|
428
|
+
PgLOG.pglog(rstr + ': Request File is built already', PgLOG.LOGWRN)
|
|
429
|
+
return
|
|
430
|
+
|
|
431
|
+
PgFile.change_local_directory(rdir, PgLOG.LOGWRN)
|
|
432
|
+
get_subset_info(rstr)
|
|
433
|
+
set_var_info()
|
|
434
|
+
cinfo = PGFILE['cmd_detail']
|
|
435
|
+
tidx = 0
|
|
436
|
+
dates = []
|
|
437
|
+
for line in cinfo.split("&"):
|
|
438
|
+
ms = re.search(r'([-\w]+)=(.+)', line)
|
|
439
|
+
if not ms: continue
|
|
440
|
+
token = ms.group(1)
|
|
441
|
+
pstring = ms.group(2)
|
|
442
|
+
if token == "dates": # Date Limits
|
|
443
|
+
dates = pstring.split(' ')
|
|
444
|
+
elif token == 'tidx':
|
|
445
|
+
tidx = int(pstring)
|
|
446
|
+
|
|
447
|
+
if not (tidx and dates):
|
|
448
|
+
PgLOG.pglog(rstr + ': Miss tidx or date range to build request', PgLOG.LOGWRN)
|
|
449
|
+
|
|
450
|
+
subset_table_index(PGFILE['wfile'], tidx, dates[0], dates[1])
|
|
451
|
+
|
|
452
|
+
#
|
|
453
|
+
# build range dates for subsetting
|
|
454
|
+
#
|
|
455
|
+
def build_table_file(fd, tidx, bdate, edate, atables):
|
|
456
|
+
|
|
457
|
+
anames = PVALS['anames']
|
|
458
|
+
facnt = len(anames)
|
|
459
|
+
acnt = facnt - PVALS['facnt'] - 1
|
|
460
|
+
|
|
461
|
+
# query on the icoreloc
|
|
462
|
+
aname = anames[0]
|
|
463
|
+
qcnd = "date BETWEEN '{}' AND '{}'".format(bdate, edate)
|
|
464
|
+
if PVALS['spcnd']: qcnd += " AND " + PVALS['spcnd']
|
|
465
|
+
tname = "{}_{}".format(aname, tidx)
|
|
466
|
+
pgrecs = PgDBI.pgmget(tname, "*", qcnd, PgLOG.LGEREX)
|
|
467
|
+
rcnt = len(pgrecs['iidx']) if pgrecs else 0
|
|
468
|
+
for r in range(rcnt):
|
|
469
|
+
pgrec = {'icoreloc' : PgUtil.onerecord(pgrecs, r)}
|
|
470
|
+
# quey for all attms
|
|
471
|
+
qcnd = "iidx = {}".format(pgrec['icoreloc']['iidx'])
|
|
472
|
+
for a in range(1, acnt):
|
|
473
|
+
aname = anames[a]
|
|
474
|
+
if atables[aname]:
|
|
475
|
+
tname = "{}_{}".format(aname, tidx)
|
|
476
|
+
pgrec[aname] = PgDBI.pgget(tname, "*", qcnd, PgLOG.LGEREX)
|
|
477
|
+
else:
|
|
478
|
+
pgrec[aname] = None
|
|
479
|
+
|
|
480
|
+
# process trimming
|
|
481
|
+
if 'icorereg' not in pgrec:
|
|
482
|
+
aname = "icorereg"
|
|
483
|
+
tname = "icorereg_{}".format(tidx)
|
|
484
|
+
pgrec[aname] = PgDBI.pgget(tname, "*", qcnd, PgLOG.LGEREX)
|
|
485
|
+
|
|
486
|
+
if 'iicoads' not in pgrec:
|
|
487
|
+
aname = "iicoads"
|
|
488
|
+
tname = "iicoads_{}".format(tidx)
|
|
489
|
+
pgrec[aname] = PgDBI.pgget(tname, "*", qcnd, PgLOG.LGEREX)
|
|
490
|
+
elif PVALS['iopts']:
|
|
491
|
+
if not_match_iopts(pgrec['iicoads']): continue
|
|
492
|
+
|
|
493
|
+
values = PgIMMA.TRIMQC2(pgrec, PVALS['fopts'])
|
|
494
|
+
if not values: continue
|
|
495
|
+
|
|
496
|
+
if PVALS['trmcnt'] > 0:
|
|
497
|
+
for var in values:
|
|
498
|
+
if not TRIMS[var] or values[var]: continue
|
|
499
|
+
if var == 'rh':
|
|
500
|
+
if pgrec['iimmt5'] and var in pgrec['iimmt5']:
|
|
501
|
+
pgrec['iimmt5'][var] = None
|
|
502
|
+
elif pgrec['icorereg'] and var in pgrec['icorereg']:
|
|
503
|
+
pgrec['icorereg'][var] = None
|
|
504
|
+
|
|
505
|
+
#skip empty record
|
|
506
|
+
valid = 0
|
|
507
|
+
for a in range(acnt):
|
|
508
|
+
aname = anames[a]
|
|
509
|
+
record = pgrec[aname]
|
|
510
|
+
dvars = PVALS['dvars'][aname]
|
|
511
|
+
if not (dvars and record): continue
|
|
512
|
+
for var in dvars:
|
|
513
|
+
if var in record and record[var] != None:
|
|
514
|
+
if isinstance(record[var], int) or len(record[var]) > 0:
|
|
515
|
+
valid = 1
|
|
516
|
+
break
|
|
517
|
+
if valid: break
|
|
518
|
+
|
|
519
|
+
if not valid: continue
|
|
520
|
+
|
|
521
|
+
buf = ''
|
|
522
|
+
# save each attm values
|
|
523
|
+
for a in range(acnt):
|
|
524
|
+
aname = anames[a]
|
|
525
|
+
buf += join_attm_fields(aname, pgrec[aname]) + ","
|
|
526
|
+
|
|
527
|
+
# get and save Uida attm values
|
|
528
|
+
aname = "iuida"
|
|
529
|
+
tname = "iuida_{}".format(tidx)
|
|
530
|
+
record = PgDBI.pgget(tname, "*", qcnd, PgLOG.LGEREX)
|
|
531
|
+
buf += join_attm_fields(aname, record)
|
|
532
|
+
|
|
533
|
+
# get and save full attm values
|
|
534
|
+
for a in range(acnt+1, facnt):
|
|
535
|
+
aname = anames[a]
|
|
536
|
+
tname = "{}_{}".format(aname, tidx)
|
|
537
|
+
for cnd in FSCNDS[aname]:
|
|
538
|
+
if atables[aname]:
|
|
539
|
+
record = PgDBI.pgget(tname, "*", qcnd + cnd, PgLOG.LGEREX)
|
|
540
|
+
else:
|
|
541
|
+
record = None
|
|
542
|
+
|
|
543
|
+
buf += ',' + join_attm_fields(aname, record)
|
|
544
|
+
|
|
545
|
+
buf += "\n"
|
|
546
|
+
fd.write(buf)
|
|
547
|
+
|
|
548
|
+
#
|
|
549
|
+
# check if not matching options
|
|
550
|
+
#
|
|
551
|
+
def not_match_iopts(pgrec):
|
|
552
|
+
|
|
553
|
+
if PVALS['pts'] and not (pgrec['pt'] and pgrec['pt'] in PVALS['pts']): return 1
|
|
554
|
+
if PVALS['dcks'] and not (pgrec['dck'] and pgrec['dck'] in PVALS['dcks']): return 1
|
|
555
|
+
if PVALS['sids'] and not (pgrec['sid'] and pgrec['sid'] in PVALS['sids']): return 1
|
|
556
|
+
|
|
557
|
+
return 0 # matched
|
|
558
|
+
|
|
559
|
+
#
|
|
560
|
+
# join the attm fields to generate a string
|
|
561
|
+
#
|
|
562
|
+
def join_attm_fields(aname, record):
|
|
563
|
+
|
|
564
|
+
fmts = PVALS['fmts']
|
|
565
|
+
maxs = PVALS['maxs']
|
|
566
|
+
vars = PVALS['avars'][aname]
|
|
567
|
+
precs = PVALS['aprecs'][aname]
|
|
568
|
+
vcnt = len(vars)
|
|
569
|
+
if not record: return ','.join(['']*vcnt)
|
|
570
|
+
|
|
571
|
+
sret = ''
|
|
572
|
+
for v in range(vcnt):
|
|
573
|
+
if v: sret += ','
|
|
574
|
+
var = vars[v]
|
|
575
|
+
val = record[var]
|
|
576
|
+
if val is None: continue
|
|
577
|
+
fmt = '{}'
|
|
578
|
+
if precs[v] == 0:
|
|
579
|
+
if var == 'id' and val.find(',') > -1: fmt = '"{}"'
|
|
580
|
+
elif precs[v] != 1:
|
|
581
|
+
if var not in maxs or val < maxs[var]:
|
|
582
|
+
val *= precs[v]
|
|
583
|
+
if var in fmts: fmt = fmts[var]
|
|
584
|
+
sret += fmt.format(val)
|
|
585
|
+
|
|
586
|
+
return sret
|
|
587
|
+
|
|
588
|
+
#
|
|
589
|
+
# check if all table files are built
|
|
590
|
+
#
|
|
591
|
+
def check_table_filename(ridx, tidx, edate):
|
|
592
|
+
|
|
593
|
+
fname = "Rqst{}-t{:03}.*-{}".format(ridx, tidx, edate.replace('-', ''))
|
|
594
|
+
return True if glob.glob(fname) else False
|
|
595
|
+
|
|
596
|
+
#
|
|
597
|
+
# check if all request data files are built
|
|
598
|
+
# return 0 - not yet;
|
|
599
|
+
# 1 - all data files are built;
|
|
600
|
+
# 2 - all files done including help files
|
|
601
|
+
#
|
|
602
|
+
def check_request_built(ridx, ptcnt, rstr):
|
|
603
|
+
|
|
604
|
+
cnd = "rindex = {} AND status = 'O'".format(ridx)
|
|
605
|
+
if ptcnt > 1:
|
|
606
|
+
pcnt = PgDBI.pgget('ptrqst', '', cnd)
|
|
607
|
+
if pcnt < ptcnt:
|
|
608
|
+
PgLOG.pglog('{}: {}/{} Request Partitions not finished yet'.format(rstr, (ptcnt-pcnt), ptcnt), PgLOG.LOGWRN)
|
|
609
|
+
return 0
|
|
610
|
+
wfcnt = PGRQST['fcount']
|
|
611
|
+
fcnt = PgDBI.pgget('wfrqst', '', cnd)
|
|
612
|
+
if fcnt < wfcnt:
|
|
613
|
+
PgLOG.pglog('{}: {}/{} Request Files not finished yet'.format(rstr, (wfcnt-fcnt), wfcnt), PgLOG.LOGWRN)
|
|
614
|
+
return 0
|
|
615
|
+
fname = PVALS['rdimma1']
|
|
616
|
+
cnd += " AND wfile = '{}'".format(fname)
|
|
617
|
+
if op.isfile(fname) and PgDBI.pgget("wfrqst", "", cnd):
|
|
618
|
+
PgLOG.pglog('{}: Request built already'.format(rstr), PgLOG.LOGWRN)
|
|
619
|
+
return 2
|
|
620
|
+
return 1
|
|
621
|
+
|
|
622
|
+
#
|
|
623
|
+
# subset data and save in fname
|
|
624
|
+
#
|
|
625
|
+
def subset_table_index(fname, tidx, bdate, edate):
|
|
626
|
+
|
|
627
|
+
atables = {}
|
|
628
|
+
PgDBI.ivaddb_scname()
|
|
629
|
+
|
|
630
|
+
for aname in PVALS['anames']:
|
|
631
|
+
atables[aname] = PgDBI.pgget('cntldb.iattm', "", "tidx = {} AND attm = '{}'".format(tidx, aname), PgLOG.LGEREX)
|
|
632
|
+
|
|
633
|
+
dstep = int(PgUtil.diffdate(edate, bdate)/PSTEP)
|
|
634
|
+
if dstep == 0: dstep = 1
|
|
635
|
+
PgLOG.pgsystem("echo '{}' > {}".format(PVALS['vhead'], fname), PgLOG.LGWNEX, 1029)
|
|
636
|
+
fd = open(fname, 'a')
|
|
637
|
+
while bdate <= edate:
|
|
638
|
+
pdate = PgUtil.adddate(bdate, 0, 0, dstep)
|
|
639
|
+
if pdate > edate: pdate = edate
|
|
640
|
+
build_table_file(fd, tidx, bdate, pdate, atables)
|
|
641
|
+
bdate = PgUtil.adddate(pdate, 0, 0, 1)
|
|
642
|
+
|
|
643
|
+
fd.close()
|
|
644
|
+
|
|
645
|
+
#
|
|
646
|
+
# build the final subset files
|
|
647
|
+
#
|
|
648
|
+
def build_final_files(ridx, rstr):
|
|
649
|
+
|
|
650
|
+
PgDBI.dssdb_scname()
|
|
651
|
+
|
|
652
|
+
fcnt = PgDBI.pghet('wfrqst', '', "rindex = {} AND type = 'D'".format(ridx))
|
|
653
|
+
fname = write_readme()
|
|
654
|
+
pgrec = {'status' : 'O', 'type' : 'O', 'data_format' : 'PDF'}
|
|
655
|
+
fcnt += 1
|
|
656
|
+
pgrec['disp_order'] = fcnt
|
|
657
|
+
PgSubset.add_request_file(ridx, fname, pgrec, PgLOG.LGEREX)
|
|
658
|
+
|
|
659
|
+
fname = PVALS['rdimma1']
|
|
660
|
+
pgrec = {'status' : 'O', 'type' : 'S', 'data_format' : 'FORTRAN'}
|
|
661
|
+
fcnt += 1
|
|
662
|
+
pgrec['disp_order'] = fcnt
|
|
663
|
+
PgFile.local_copy_local(fname, PVALS['codedir'] + fname, PgLOG.LGEREX)
|
|
664
|
+
PgSubset.add_request_file(ridx, fname, pgrec, PgLOG.LGEREX)
|
|
665
|
+
|
|
666
|
+
#
|
|
667
|
+
# process reqest info, create command file and the input file list
|
|
668
|
+
#
|
|
669
|
+
def get_subset_info(rstr):
|
|
670
|
+
|
|
671
|
+
rinfo = PGRQST['rinfo'] if PGRQST['rinfo'] else PGRQST['note']
|
|
672
|
+
cnt = 0
|
|
673
|
+
for line in rinfo.split("&"):
|
|
674
|
+
ms = re.search(r'([-\w]+)=(.+)', line)
|
|
675
|
+
if not ms: continue
|
|
676
|
+
token = ms.group(1)
|
|
677
|
+
pstring = ms.group(2)
|
|
678
|
+
if token == "dates": # Date Limits
|
|
679
|
+
PVALS['rinfo']['DATES'] = pstring
|
|
680
|
+
PVALS['dates'] = pstring.split(' ')
|
|
681
|
+
if len(PVALS['dates']) == 2: cnt += 1
|
|
682
|
+
elif token == 'lats':
|
|
683
|
+
PVALS['lats'] = PgSubset.get_latitudes(pstring, PVALS['resol'])
|
|
684
|
+
PVALS['rinfo']['LATS'] = "{}, {}".format(PVALS['lats'][0], PVALS['lats'][1])
|
|
685
|
+
cnt += 1
|
|
686
|
+
elif token == 'lons':
|
|
687
|
+
PVALS['lons'] = PgSubset.get_longitudes(pstring, PVALS['resol'])
|
|
688
|
+
PVALS['rinfo']['LONS'] = "{}, {}".format(PVALS['lons'][0], PVALS['lons'][1])
|
|
689
|
+
cnt += 1
|
|
690
|
+
elif token == 'flts': # Filter Options
|
|
691
|
+
sflts = pstring.split(' ')
|
|
692
|
+
PVALS['flts'] = [int(sflt) for sflt in sflts]
|
|
693
|
+
PVALS['rinfo']['FLTLIST'] = "</td><td>".join(sflts)
|
|
694
|
+
cnt += 1
|
|
695
|
+
elif token == 'vars': # Variable Names
|
|
696
|
+
PVALS['vars'] = pstring.split(', ')
|
|
697
|
+
cnt += 1
|
|
698
|
+
elif token == 'pts': # platform ids
|
|
699
|
+
PVALS['iopts'] += 1
|
|
700
|
+
PVALS['pts'] = list(map(int, pstring.split(', ')))
|
|
701
|
+
cnt += 1
|
|
702
|
+
elif token == 'dcks': # Deck ids
|
|
703
|
+
PVALS['iopts'] += 1
|
|
704
|
+
PVALS['dcks'] = list(map(int, pstring.split(', ')))
|
|
705
|
+
cnt += 1
|
|
706
|
+
elif token == 'sids': # source ids
|
|
707
|
+
PVALS['iopts'] += 1
|
|
708
|
+
PVALS['sids'] = list(map(int, pstring.split(', ')))
|
|
709
|
+
cnt += 1
|
|
710
|
+
elif token == 'Rean-qc':
|
|
711
|
+
FSSRCS['ireanqc'] = pstring.split(', ')
|
|
712
|
+
elif token == 'Ivad':
|
|
713
|
+
FSSRCS['iivad'] = pstring.split(', ')
|
|
714
|
+
|
|
715
|
+
if cnt < 5: PgLOG.pglog(rstr + ": Incomplete request control information", PgLOG.LGEREX)
|
|
716
|
+
|
|
717
|
+
#
|
|
718
|
+
# write a HTML readme file, and convert it to PDF format
|
|
719
|
+
#
|
|
720
|
+
def write_readme():
|
|
721
|
+
|
|
722
|
+
user = PgDBI.get_ruser_names(PGRQST['email'])
|
|
723
|
+
readme = PVALS['readme'] + PGRQST['rqstid'].lower()
|
|
724
|
+
rinfo = PVALS['rinfo']
|
|
725
|
+
readtmp = PVALS['codedir'] + PVALS['readhtml']
|
|
726
|
+
|
|
727
|
+
PgLOG.pglog("Create Readme file " + readme, PgLOG.LOGWRN)
|
|
728
|
+
readhtml = readme + ".html"
|
|
729
|
+
URM = open(readhtml, 'w')
|
|
730
|
+
RHTML = open(readtmp, 'r')
|
|
731
|
+
rinfo['CURDATE'] = PgUtil.curdate("D Month YYYY")
|
|
732
|
+
rinfo['ACCDATE'] = PgUtil.curdate()
|
|
733
|
+
rinfo['USER'] = "{} [{}]".format(user['name'], PGRQST['email'])
|
|
734
|
+
|
|
735
|
+
line = RHTML.readline()
|
|
736
|
+
while line:
|
|
737
|
+
if re.match(r'^#', line): continue # skip comment line
|
|
738
|
+
ms = re.search(r'__(\w+)__', line)
|
|
739
|
+
if ms:
|
|
740
|
+
key = ms.group(1)
|
|
741
|
+
rep = "__{}__".format(key)
|
|
742
|
+
if key in rinfo:
|
|
743
|
+
line = line.replace(rep, rinfo[key])
|
|
744
|
+
else:
|
|
745
|
+
line = line.replace(rep, '')
|
|
746
|
+
URM.write(line)
|
|
747
|
+
line = RHTML.readline()
|
|
748
|
+
|
|
749
|
+
RHTML.close()
|
|
750
|
+
URM.close()
|
|
751
|
+
|
|
752
|
+
readpdf = readme + ".pdf"
|
|
753
|
+
PgLOG.pgsystem("{} {} {}".format(PVALS['html2pdf'], readhtml, readpdf), PgLOG.LOGWRN, 35)
|
|
754
|
+
if not PgFile.check_local_file(readpdf):
|
|
755
|
+
PgLOG.pglog("{}: Error convert {} to {}".format(PVALS['html2pdf'], readhtml, readpdf), PgLOG.LOGWRN)
|
|
756
|
+
|
|
757
|
+
PgFile.delete_local_file(readhtml, PgLOG.LGWNEX)
|
|
758
|
+
|
|
759
|
+
return readpdf
|
|
760
|
+
|
|
761
|
+
#
|
|
762
|
+
# call main() to start program
|
|
763
|
+
#
|
|
764
|
+
if __name__ == "__main__": main()
|