rda-python-icoads 1.0.7__py3-none-any.whl → 1.0.9__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.

@@ -0,0 +1,345 @@
1
+ #!/usr/bin/env python3
2
+ #
3
+ ##################################################################################
4
+ #
5
+ # Title : msg3_subset
6
+ # Author : Zaihua Ji, zji@ucar.edu
7
+ # Date : 01/07/2020
8
+ # 2025-02-28 transferred to package rda_python_icoads from
9
+ # https://github.com/NCAR/rda-icoads.git
10
+ # Purpose : process ICOADS 3.0 MSG subset requests under control of dsrqst
11
+ # for mouthly summary data files
12
+ #
13
+ # Github : https://github.com/NCAR/rda-python-icoads.git
14
+ #
15
+ ##################################################################################
16
+
17
+ import sys
18
+ import os
19
+ import re
20
+ from os import path as op
21
+ from rda_python_common import PgLOG
22
+ from rda_python_common import PgDBI
23
+ from . import PgIMMA
24
+ from rda_python_common import PgUtil
25
+ from rda_python_common import PgFile
26
+ from rda_python_dsrqst import PgSubset
27
+
28
+
29
+ MISSIDX = [22, 23, 24, 25]
30
+ STATNUM = ['10 14 18 22 26 30 34 38 42 46 ', '11 15 19 23 27 31 35 39 43 47 ',
31
+ '12 16 20 24 28 32 36 40 44 48 ', '13 17 21 25 29 33 37 41 45 49']
32
+ VARARRAY = {
33
+ # VAR : GRP IDX DESCRIPTION
34
+ 'S' : [3, 0, 'sea surface temperature 0.01 @C'],
35
+ 'A' : [3, 1, 'air temperature 0.01 @C'],
36
+ 'Q' : [3, 2, 'specific humidity 0.01 g/kg'],
37
+ 'R' : [3, 3, 'relative humidity 0.1 %'],
38
+ 'W' : [4, 0, 'scalar wind 0.01 m/s'],
39
+ 'U' : [4, 1, 'vector wind eastward component 0.01 m/s'],
40
+ 'V' : [4, 2, 'vector wind northward component 0.01 m/s'],
41
+ 'P' : [4, 3, 'sea level pressure 0.01 hPa'],
42
+ 'C' : [5, 0, 'total cloudiness 0.1 okta'],
43
+ 'X' : [5, 2, 'WU (wind stress 0.1 m**2/s**2'],
44
+ 'Y' : [5, 3, 'WV parameters) 0.1 m**2/s**2'],
45
+ 'D' : [6, 0, 'S - A = sea-air temp. diff. 0.01 @C'],
46
+ 'E' : [6, 1, '(S - A)W 0.1 @C m/s'],
47
+ 'F' : [6, 2, 'QS - Q = (sat. Q at S) - Q 0.01 g/kg'],
48
+ 'G' : [6, 3, 'FW = (QS - Q)W = (evap. param.) 0.1 g/kg m/s'],
49
+ 'I' : [7, 0, 'UA (sensible-heat--transport 0.1 @C m/s'],
50
+ 'J' : [7, 1, 'VA parameters) 0.1 @C m/s'],
51
+ 'K' : [7, 2, 'UQ (latent-heat--transport 0.1 g/kg m/s'],
52
+ 'L' : [7, 3, 'VQ parameters) 0.1 g/kg m/s'],
53
+ 'M' : [9, 0, 'FU 0.1 g/kg m/s'],
54
+ 'N' : [9, 1, 'FV 0.1 g/kg m/s'],
55
+ 'B1' : [8, 2, 'B = W**3 (high-resolution) 0.5 m**3/s**3'],
56
+ 'B2' : [9, 3, 'B = W**3 (low-resolution) 5 m**3/s**3']
57
+ }
58
+
59
+ IDSID = 'd548001'
60
+ PVALS = {
61
+ 'datadir' : PgLOG.PGLOG['DSDHOME'] + "/icoads/MSG3.0",
62
+ 'docdir' : op.dirname(op.abspath(__file__)) + '/',
63
+ 'readtxt' : "msg3.0_subset_readme.txt",
64
+ 'readme' : "readme_msg3.0.",
65
+ 'msgfile' : 'msg',
66
+ 'statdoc' : 'R3.0-stat_doc.pdf',
67
+ 'subset' : 'msgsubset',
68
+ 'numstat' : 10,
69
+ 'format' : "(i5,2i4,2f7.1,i5,10f8.2)",
70
+ 'title' : " YEAR MON BSZ BLO BLA PID2 S1 S3 S5 M N S D HT X Y",
71
+ 'varlist' : "",
72
+ 'ptype' : "enh",
73
+ 'resol' : 2,
74
+ 'keys' : [],
75
+ 'lats' : [],
76
+ 'lons' : [],
77
+ 'limits' : [],
78
+ 'insize' : 0,
79
+ 'outsize' : 0,
80
+ 'ridx' : 0,
81
+ 'rdir' : None
82
+ }
83
+
84
+ PGRQST = {}
85
+ INRECS = {}
86
+ OUTRECS = {}
87
+
88
+ #
89
+ # main function to run dsarch
90
+ #
91
+ def main():
92
+
93
+ global PGRQST
94
+ argv = sys.argv[1:]
95
+ PgLOG.PGLOG['LOGFILE'] = "icoads.log"
96
+
97
+ for arg in argv:
98
+ if arg == "-b":
99
+ PgLOG.PGLOG['BCKGRND'] = 1
100
+ elif arg == "-d":
101
+ PgLOG.PGLOG['DBGLEVEL'] = 1000
102
+ elif re.match(r'^-', arg):
103
+ PgLOG.pglog(arg + ": Unknown Option", PgLOG.LGEREX)
104
+ elif re.match(r'^(\d+)$', arg):
105
+ if PVALS['ridx']: PgLOG.pglog("{}: Request Index ({}) given already".format(arg, PVALS['ridx']), PgLOG.LGEREX)
106
+ PVALS['ridx'] = int(arg)
107
+ else:
108
+ if PVALS['rdir']: PgLOG.pglog("{}: Request Directory ({}) given already".format(arg, PVALS['rdir']), PgLOG.LGEREX)
109
+ PVALS['rdir'] = arg
110
+
111
+ PgLOG.cmdlog("msg3.0_subset {}".format(' '.join(argv)))
112
+ PGRQST = PgSubset.valid_subset_request(PVALS['ridx'], PVALS['rdir'], IDSID, PgLOG.LGWNEX)
113
+ if not PVALS['rdir']: PVALS['rdir'] = PgLOG.join_paths(PgLOG.PGLOG['RQSTHOME'], PGRQST['rqstid'])
114
+ process_subset_request()
115
+ PgLOG.cmdlog()
116
+ sys.exit(0)
117
+
118
+ #
119
+ # process a validated subset request
120
+ #
121
+ def process_subset_request():
122
+
123
+ if not op.isdir(PVALS['rdir']):
124
+ PgFile.make_local_directory(PVALS['rdir'], PgLOG.LGWNEX)
125
+ else:
126
+ if PgSubset.request_built(PVALS['ridx'], PVALS['rdir'], PVALS['msgfile'], PGRQST['fcount'], PgLOG.LGWNEX):
127
+ return PgLOG.pglog("MSG Subset Request built already for Index {}".format(PVALS['ridx']), PgLOG.LOGWRN)
128
+ PgSubset.clean_subset_request(PVALS['ridx'], PVALS['rdir'], None, PgLOG.LGWNEX)
129
+
130
+ cmdfiles = create_cmd_file()
131
+ process_data(cmdfiles)
132
+
133
+ PgFile.change_local_directory(PVALS['rdir'], PgLOG.LGWNEX)
134
+ offset = cnt = PVALS['outsize'] = 0
135
+ files = PgFile.local_glob("*{}*".format(PVALS['limits']))
136
+ for wfile in files:
137
+ PVALS['outsize'] += files[wfile]['data_size']
138
+ ms = re.search(r'(\d+)$', wfile)
139
+ if ms:
140
+ n = int(ms.group(1))
141
+ if n == 1: offset = cnt
142
+ order = offset + n
143
+ else:
144
+ order = cnt + 1
145
+
146
+ if PGRQST['file_format']: (wfile, fmt) = PgFile.compress_local_file(wfile, PGRQST['file_format'], 1)
147
+ PgSubset.add_subset_file(PVALS['ridx'], wfile, None, "D", "ASCII", order, None, PgLOG.LGWNEX)
148
+ cnt += 1
149
+
150
+ if cnt > 0:
151
+ wfile = write_readme()
152
+ cnt += 1
153
+ PgSubset.add_subset_file(PVALS['ridx'], wfile, None, "O", "TEXT", cnt, None, PgLOG.LGWNEX)
154
+ wfile = PVALS['statdoc']
155
+ cnt += 1
156
+ PgSubset.add_subset_file(PVALS['ridx'], wfile, PVALS['docdir'] + wfile, "O", "PDF", cnt, None, PgLOG.LGWNEX)
157
+ wfile = PVALS['msgfile']
158
+ cnt += 1
159
+ PgSubset.add_subset_file(PVALS['ridx'], wfile, PVALS['docdir'] + wfile, "O", "TEXT", cnt, None, PgLOG.LGWNEX)
160
+ if PVALS['insize'] > 0 and PVALS['insize'] != PGRQST['size_input']:
161
+ PgDBI.pgexec("UPDATE dsrqst SET size_input = {} WHERE rindex = {}".format(PVALS['insize'], PVALS['ridx']))
162
+ PgSubset.set_dsrqst_fcount(PVALS['ridx'], cnt, PVALS['insize'], PVALS['outsize'])
163
+ PgLOG.pglog("{} MSG subset files added to Request Index {}".format(cnt, PVALS['ridx']), PgLOG.LOGWRN)
164
+ else:
165
+ PgSubset.set_dsrqst_fcount(PVALS['ridx'], 0, PVALS['insize'], 0)
166
+
167
+ #
168
+ # process reqest and create the command file for data processing
169
+ #
170
+ def create_cmd_file():
171
+
172
+ datafiles = []
173
+ variables = []
174
+ cmdfiles = {}
175
+ ystr = yend = None
176
+ rinfo = PGRQST['rinfo'] if PGRQST['rinfo'] else PGRQST['note']
177
+
178
+ for line in rinfo.split("&"):
179
+ ms = re.search(r'(\w+)=(.+)', line)
180
+ if not ms: continue
181
+ token = ms.group(1)
182
+ pstring = ms.group(2)
183
+ if token == "dates": # Date Limits
184
+ dates = pstring
185
+ PVALS['limits'] = dates.replace(' ', '.')
186
+ ms = re.search(r'(\d\d\d\d)\d\d\s(\d\d\d\d)\d\d', dates)
187
+ if ms:
188
+ ystr = int(ms.group(1))
189
+ yend = int(ms.group(2))
190
+ elif token == 'lats':
191
+ PVALS['lats'] = pstring
192
+ elif token == 'lons':
193
+ PVALS['lons'] = pstring
194
+ elif token == 'resol':
195
+ ms = re.match(r'^(\d)DEG', pstring)
196
+ if ms: PVALS['resol'] = int(ms.group(1))
197
+ elif token == 'ptype':
198
+ PVALS['ptype'] = pstring.lower()
199
+ elif token == 'vars': # Variable Names
200
+ variables = pstring.split(', ')
201
+
202
+ if not variables: PgLOG.pglog("{}: No variable specified for subset Request".format(PVALS['ridx']), PgLOG.LGEREX)
203
+ if not ystr: PgLOG.pglog("{}: No Time limits specified for subset Request".format(PVALS['ridx']), PgLOG.LGEREX)
204
+ if PVALS['resol'] == 1 and ystr < 1960: PVALS['resol'] = 2
205
+ pos = PgSubset.get_latitudes(PVALS['lats'], PVALS['resol'])
206
+ PVALS['lats'] = "{:7.2f} {:7.2f}".format(pos[0], pos[1])
207
+ pos = PgSubset.get_longitudes(PVALS['lons'], PVALS['resol'])
208
+ PVALS['lons'] = "{:7.2f} {:7.2f}".format(pos[0], pos[1])
209
+ datadir = "{}/{}deg".format(PVALS['datadir'], PVALS['resol'])
210
+
211
+ # write out command file for input of Fortran code 'subset'
212
+ PVALS['insize'] = 0
213
+ for token in variables:
214
+ group = VARARRAY[token][0]
215
+ datafiles = get_data_files(group, PVALS['ptype'], ystr, yend, datadir)
216
+ if not datafiles: continue
217
+ cmdfile = "{}.MSG.{}".format(PGRQST['rqstid'], token)
218
+ OUT = open(cmdfile, 'w')
219
+ pstring = "Variable name : {} , description : {}, format{}\n".format(token, VARARRAY[token][2], PVALS['format'])
220
+ PVALS['varlist'] += pstring
221
+ OUT.write(pstring)
222
+ OUT.write(PVALS['title'] + "\n")
223
+ OUT.write("{} :Group number\n".format(group))
224
+ OUT.write("{} :nstat\n".format(PVALS['numstat']))
225
+ OUT.write("{} :stat index num.\n".format(STATNUM[VARARRAY[token][1]]))
226
+ OUT.write("{} :missing data index check\n".format(MISSIDX[VARARRAY[token][1]]))
227
+ OUT.write(PVALS['format'] + "\n")
228
+ OUT.write("{} {} {} :lat-lon SW corn. and time limits\n".format(PVALS['lats'], PVALS['lons'], dates))
229
+ OUT.write("{} :data resolution (1 or 2)\n".format(PVALS['resol']))
230
+ OUT.write("{} :data type (std or enh)\n".format(PVALS['ptype']))
231
+ OUT.write(token + " :variable name\n")
232
+ OUT.write(datadir + "/\n") # MSG data path
233
+ OUT.write(PVALS['rdir'] + "/\n") # output data path
234
+ OUT.write("{}\n".format(len(datafiles))) # number of MSG data files
235
+ for datafile in datafiles:
236
+ info = PgFile.check_local_file("{}/{}".format(datadir, datafile))
237
+ if info: PVALS['insize'] += info['data_size']
238
+ OUT.write(datafile + "\n")
239
+
240
+ OUT.close()
241
+ cmdfiles[token] = cmdfile
242
+
243
+ return cmdfiles
244
+
245
+ #
246
+ # gather data files
247
+ #
248
+ def get_data_files(group, ptype, ystr, yend, datadir):
249
+
250
+ datafiles = []
251
+
252
+ prefix = "{}g{}".format(ptype, group)
253
+ for yr in range(ystr, yend+1):
254
+ datafile = prefix + ".{}".format(yr)
255
+ if op.isfile("{}/{}".format(datadir, datafile)):
256
+ datafiles.append(datafile) # include existing files only
257
+
258
+ return datafiles
259
+
260
+ #
261
+ # process data and create the sub-dataset
262
+ #
263
+ def process_data(cmdfiles):
264
+
265
+ for var in cmdfiles:
266
+ infile = cmdfiles[var]
267
+ INRECS[var] = OUTRECS[var] = 0
268
+ if not op.isfile(infile): continue # no input file, skip it
269
+ retmsg = PgLOG.pgsystem("{} < {}".format(PVALS['subset'], infile), PgLOG.LGWNEX, 23)
270
+ if retmsg:
271
+ for line in retmsg.split("\n"):
272
+ ms = re.match(r'^\s*(IN|OUT)RECS:\s+(\d+)', line)
273
+ if ms:
274
+ if ms.group(1) == 'IN':
275
+ INRECS[var] = int(ms.group(2))
276
+ else:
277
+ OUTRECS[var] = int(ms.group(2))
278
+ if PgLOG.PGLOG['DBGLEVEL']: PgLOG.pgdbg(1000, line)
279
+
280
+ PgLOG.pgsystem("rm -f " + infile)
281
+
282
+ #
283
+ # create a readme file specified to the request
284
+ #
285
+ def write_readme():
286
+
287
+ user = PgDBI.get_ruser_names(PGRQST['email'])
288
+ readme = PVALS['readme'] + PGRQST['rqstid'].lower()
289
+ PgLOG.pglog("Create Readme file " + readme, PgLOG.LOGWRN)
290
+ URM = open(readme, 'w')
291
+ RTXT = open(PVALS['docdir'] + PVALS['readtxt'], 'r')
292
+ line = RTXT.readline()
293
+ while line:
294
+ if re.match(r'^#', line): # skip comment line
295
+ line = RTXT.readline()
296
+ continue
297
+ if re.search(r'__VARLIST__', line): # print user-selected variable list
298
+ URM.write(PVALS['varlist'])
299
+ line = RTXT.readline()
300
+ continue
301
+
302
+ if re.search(r'__USER__', line):
303
+ line = line.replace('__USER__', "{}<{}>".format(user['name'], PGRQST['email']))
304
+ elif re.search(r'__LATS__', line):
305
+ line = line.replace('__LATS__', PVALS['lats'])
306
+ elif re.search(r'__LONS__', line):
307
+ line = line.replace('__LONS__', PVALS['lons'])
308
+ elif re.search(r'__DATES__', line):
309
+ line = line.replace('__DATES__', PVALS['limits'])
310
+ elif re.search(r'__RESOL__', line):
311
+ line = line.replace('__RESOL__', str(PVALS['resol']))
312
+ elif re.search(r'__PTYPE__', line):
313
+ line = line.replace('__PTYPE__', PVALS['ptype'])
314
+ elif re.search(r'__INRECS__', line):
315
+ line = line.replace('__INRECS__', get_recs_string(INRECS))
316
+ elif re.search(r'__OUTRECS__', line):
317
+ line = line.replace('__OUTRECS__', get_recs_string(OUTRECS))
318
+ elif re.search(r'__INSIZES__', line):
319
+ line = line.replace('__INSIZES__', "{:.3f} MB".format(PVALS['insize']/1000000.))
320
+ elif re.search(r'__OUTSIZES__', line):
321
+ line = line.replace('__OUTSIZES__', "{:.3f} MB".format(PVALS['outsize']/1000000.))
322
+ URM.write(line)
323
+ line = RTXT.readline()
324
+
325
+ RTXT.close()
326
+ URM.close()
327
+
328
+ return readme
329
+
330
+ #
331
+ # get string buffer of in/out record counts
332
+ #
333
+ def get_recs_string(recs):
334
+
335
+ str = ''
336
+ for var in recs:
337
+ if str: str += ", "
338
+ str += "{}({})".format(recs[var], var)
339
+
340
+ return str
341
+
342
+ #
343
+ # call main() to start program
344
+ #
345
+ if __name__ == "__main__": main()
@@ -0,0 +1,211 @@
1
+ #!/usr/bin/env python3
2
+ #
3
+ ##################################################################################
4
+ #
5
+ # Title : msg_download
6
+ # Author : Zaihua Ji, zji@ucar.edu
7
+ # Date : 03/02/2021
8
+ # 2025-03-03 transferred to package rda_python_icoads from
9
+ # https://github.com/NCAR/rda-icoads.git
10
+ # Purpose : download MSG monthly update tar file and untar it for dsupdt
11
+ #
12
+ # Github : https://github.com/NCAR/rda-python-icoads.git
13
+ #
14
+ ##################################################################################
15
+
16
+ import sys
17
+ import re
18
+ from os import path as op
19
+ from rda_python_common import PgLOG
20
+ from rda_python_common import PgUtil
21
+ from rda_python_common import PgFile
22
+
23
+ LFILES = [
24
+ "MSG1_R3.0.2_ENH_",
25
+ "MSG1_R3.0.2_STD_",
26
+ "MSG1_R3.0.2_ENH_EQ_",
27
+ "MSG1_R3.0.2_STD_EQ_",
28
+ "MSG2_R3.0.2_ENH_",
29
+ "MSG2_R3.0.2_STD_",
30
+ ]
31
+ MFILES = [
32
+ ["MSG1_", ".?.ENH.gz"],
33
+ ["MSG1_", ".?.STD.gz"],
34
+ ["MSG1_", ".?.ENH.S.gz"],
35
+ ["MSG1_", ".?.STD.S.gz"],
36
+ ["MSG2_", ".?.ENH.gz"],
37
+ ["MSG2_", ".?.STD.gz"],
38
+ ]
39
+ LCNT = 6
40
+
41
+ OPTIONS = {
42
+ 'CD' : None,
43
+ 'ED' : None,
44
+ 'NL' : 0,
45
+ 'NS' : 0,
46
+ 'MU' : 0
47
+ }
48
+
49
+ WEBURL = "https://www.ncei.noaa.gov/data/international-comprehensive-ocean-atmosphere/v3/archive/msg/"
50
+ SUBDIR = PgLOG.PGLOG['DSDHOME'] + "/icoads/MSG3.0"
51
+ #WPATH = "data/msg3.0.0"
52
+ #WPATH = "data/netcdf3.0.2"
53
+ WPATH = "data/netcdf3.0.2new"
54
+ PPATH = "../.."
55
+ WORKDIR = PgLOG.get_environment("ICOADSDIR", PgLOG.PGLOG['UPDTWKP'] + "/zji/icoads") + "/icoads_rt"
56
+ #SFMT = "ICOADS_v3.0.0_MSG-binary_d{}{}_c"
57
+ SFMT = "icoads-nrt_r3.0.2_msg-binary_d{}{}_c"
58
+
59
+ #
60
+ # main function to excecute this script
61
+ #
62
+ def main():
63
+
64
+ PgLOG.PGLOG['LOGFILE'] = "icoads.log"
65
+ argv = sys.argv[1:]
66
+ options = '|'.join(OPTIONS)
67
+ option = None
68
+
69
+ for arg in argv:
70
+ if arg == "-b":
71
+ PgLOG.PGLOG['BCKGRND'] = 1
72
+ option = None
73
+ continue
74
+ ms = re.match(r'^-({})$'.format(options), arg, re.I)
75
+ if ms:
76
+ option = ms.group(1).upper()
77
+ if re.match(r'^(NS|NL|MU)$', option):
78
+ OPTIONS[option] = 1
79
+ option = None
80
+ continue
81
+ elif re.match(r'^-.*', arg):
82
+ PgLOG.pglog(arg + ": Unknown Option", PgLOG.LGEREX)
83
+ elif option:
84
+ OPTIONS[option] = arg
85
+ option = None
86
+ elif not OPTIONS['ED']:
87
+ OPTIONS['ED'] = arg
88
+ else:
89
+ PgLOG.pglog(arg + ": Value passed in without leading option", PgLOG.LGEREX)
90
+
91
+ if not OPTIONS['ED']:
92
+ print("Usage: msg_download [-MU] [-NL] [-NS] [-CD CurrentDate] [-ED] EndDate")
93
+ print(" Provide end date for monthly MSG data to download it from $WEBURL")
94
+ print(" Option -MU - download/build files for multiple month")
95
+ print(" Option -NL - do not build local files")
96
+ print(" Option -NS - do not save subset files")
97
+ print(" Option -CD - optional current date, default to today")
98
+ print(" Option -ED - mandatory for the end data date")
99
+ sys.exit(0)
100
+
101
+ PgLOG.cmdlog("msg_download {}".format(' '.join(argv)))
102
+ PgFile.change_local_directory(WORKDIR)
103
+
104
+ if not OPTIONS['CD']: OPTIONS['CD'] = PgUtil.curdate()
105
+
106
+ diff = PgUtil.diffdate(OPTIONS['ED'], OPTIONS['CD'])
107
+ if diff > 0: PgLOG.pglog("{}: data date is later than current date {}".format(OPTIONS['ED'], OPTIONS['CD']), PgLOG.LGEREX)
108
+
109
+ while diff < 0:
110
+ process_msg_files()
111
+ if not OPTIONS['MU']: break
112
+ OPTIONS['ED'] = PgUtil.adddate(OPTIONS['ED'], 0, 1, 0)
113
+ diff = PgUtil.diffdate(OPTIONS['ED'], OPTIONS['CD'])
114
+
115
+ PgLOG.cmdlog()
116
+ sys.exit(0)
117
+
118
+ #
119
+ # process download and build MSG files for a month
120
+ #
121
+ def process_msg_files():
122
+
123
+ ms = re.match(r'^(\d+)-(\d+)', OPTIONS['ED'])
124
+ if ms:
125
+ yr = ms.group(1)
126
+ mn = ms.group(2)
127
+ if len(mn) == 1: mn = '{:02}'.format(int(mn))
128
+ else:
129
+ PgLOG.pglog(OPTIONS['ED'] + ": invalid date format", PgLOG.LGEREX)
130
+
131
+ sfile = SFMT.format(yr, mn)
132
+ cnt = 0
133
+ lfiles = [None]*LCNT
134
+ lexists = [0]*LCNT
135
+ for i in range(LCNT):
136
+ lfiles[i] = "{}{}-{}.tar".format(LFILES[i], yr, mn)
137
+ if PgFile.local_file_size(lfiles[i], 3) > 0:
138
+ lexists[i] = 1
139
+ cnt += 1
140
+
141
+ if cnt == LCNT:
142
+ PgLOG.pglog("{}-{}:: all {} local files created already for the month".format(yr, mn, cnt), PgLOG.LOGWRN)
143
+ return cnt
144
+
145
+ rfile = download_msg_file(sfile)
146
+ if not rfile: return PgLOG.pglog(sfile + ": remote file NOT exists", PgLOG.LOGWRN)
147
+
148
+ # untar downloaded remote file
149
+ # PgLOG.pgsystem("tar -xvf {} -C {}".format(rfile, WPATH), PgLOG.LOGWRN, 5)
150
+ PgLOG.pgsystem("tar -xvf " + rfile, PgLOG.LOGWRN, 5)
151
+
152
+ PgFile.change_local_directory(WPATH)
153
+ if not OPTIONS['NL']: build_msg_files(yr, mn, lfiles, lexists)
154
+ if not OPTIONS['NS']: build_subset_files(yr, mn)
155
+ PgLOG.pgsystem("rm -f MSG?_{}.{}*".format(yr, mn), PgLOG.LOGWRN, 1029)
156
+ PgFile.change_local_directory(PPATH)
157
+
158
+ #
159
+ # download a MSG tar file from remote web server
160
+ #
161
+ def download_msg_file(sfile):
162
+
163
+ rfile = sfile + ".tar"
164
+ cmd = "pgwget -ul {} -rn {} -ex tar -fn {} -cr".format(WEBURL, sfile, rfile)
165
+ PgLOG.pgsystem(cmd, PgLOG.LOGWRN, 5)
166
+ if PgFile.check_local_file(rfile): return rfile
167
+
168
+ return None
169
+
170
+ #
171
+ # build up the local MSG files for archive
172
+ #
173
+ def build_msg_files(yr, mn, lfiles, lexists):
174
+
175
+ for i in range(LCNT):
176
+ if lexists[i]: continue
177
+ lfile = "{}/{}".format(PPATH, lfiles[i])
178
+ mfiles = "{}{}.{}{}".format(MFILES[i][0], yr, mn, MFILES[i][1])
179
+ PgLOG.pgsystem("tar -cvf {} {}".format(lfile, mfiles), PgLOG.LOGWRN, 1029)
180
+
181
+ #
182
+ # build up the subset MSG files
183
+ #
184
+ def build_subset_files(yr, mn):
185
+
186
+ grps = [3,4,5,6,7,9]
187
+ omonth = False if mn == '01' else True
188
+ for grp in grps:
189
+ PgLOG.pgsystem("gunzip MSG?_{}.{}.{}.???.gz".format(yr, mn, grp), PgLOG.LOGWRN, 1029)
190
+ build_one_subset_file("MSG1_{}.{}.{}.ENH".format(yr, mn, grp), 'enh', grp, 1, yr, omonth)
191
+ build_one_subset_file("MSG1_{}.{}.{}.STD".format(yr, mn, grp), 'std', grp, 1, yr, omonth)
192
+ build_one_subset_file("MSG2_{}.{}.{}.ENH".format(yr, mn, grp), 'enh', grp, 2, yr, omonth)
193
+ build_one_subset_file("MSG2_{}.{}.{}.STD".format(yr, mn, grp), 'std', grp, 2, yr, omonth)
194
+
195
+ #
196
+ # build one subset MSG file
197
+ #
198
+ def build_one_subset_file(nfile, type, grp, deg, yr, omonth):
199
+
200
+ # check and get the existing tar file
201
+ lfile = "{}g{}.{}".format(type, grp, yr)
202
+ tfile = "{}/{}deg/{}".format(SUBDIR, deg, lfile)
203
+
204
+ if omonth and not op.isfile(lfile) and op.isfile(tfile): PgLOG.pgsystem("cp -f {} {}".format(tfile, lfile), PgLOG.LGWNEX)
205
+ PgLOG.pgsystem("cat {} >> {}".format(nfile, lfile), PgLOG.LGWNEX)
206
+ PgLOG.pgsystem("cp -f {} {}".format(lfile, tfile), PgLOG.LGWNEX)
207
+
208
+ #
209
+ # call main() to start program
210
+ #
211
+ if __name__ == "__main__": main()