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,149 @@
1
+ #!/usr/bin/env python3
2
+ #
3
+ ##################################################################################
4
+ #
5
+ # Title : fillinventory
6
+ # Author : Zaihua Ji, zji@ucar.edu
7
+ # Date : 12/31/2020
8
+ # 2025-03-03 transferred to package rda_python_icoads from
9
+ # https://github.com/NCAR/rda-icoads.git
10
+ # Purpose : process ICOADS data files in IMMA format and fill inventory
11
+ # information into IVADDB
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 rda_python_common import PgUtil
24
+ from . import PgIMMA
25
+
26
+ PVALS = {
27
+ 'files' : [],
28
+ 'oflag' : 0
29
+ }
30
+
31
+ #
32
+ # main function to run dsarch
33
+ #
34
+ def main():
35
+
36
+ argv = sys.argv[1:]
37
+
38
+ for arg in argv:
39
+ if arg == "-b":
40
+ PgLOG.PGLOG['BCKGRND'] = 1
41
+ elif arg == "-s":
42
+ PVALS['oflag'] |= 2
43
+ elif arg == "-o":
44
+ PVALS['oflag'] |= 1
45
+ elif re.match(r'^-', arg):
46
+ PgLOG.pglog(arg + ": Invalid Option", PgLOG.LGWNEX)
47
+ else:
48
+ PVALS['files'].append(arg)
49
+
50
+ if PVALS['oflag'] == 3: PgLOG.pglog("Use option -o or -s, but not both", PgLOG.LGEREX)
51
+
52
+ if not (PVALS['files'] or PVALS['oflag'] == 2):
53
+ print("Usage: fillinventory [-(o|s)] FileNameList")
54
+ print(" Option -o: Count daily records only if present")
55
+ print(" Option -s: set daily counted records with table indices if present")
56
+ print(" At least one file name needs to be present to fill inventory data")
57
+ sys.exit(0)
58
+
59
+ PgLOG.PGLOG['LOGFILE'] = "icoads.log"
60
+ PgDBI.ivaddb_dbname()
61
+ PgLOG.cmdlog("fillinventory {}".format(' '.join(argv)))
62
+
63
+ if PVALS['oflag'] == 2:
64
+ refill_imma_inventory();
65
+ else:
66
+ fill_imma_inventory()
67
+
68
+ PgLOG.cmdlog()
69
+ sys.exit(0)
70
+
71
+ #
72
+ # fill imma inventory tables
73
+ #
74
+ def fill_imma_inventory():
75
+
76
+ fcnt = len(PVALS['files'])
77
+ inventory = PgIMMA.get_inventory_record(0, PVALS['oflag'])
78
+
79
+ fidx = 0
80
+ for file in PVALS['files']:
81
+ inventory = process_imma_file(file, inventory)
82
+
83
+ PgLOG.pglog("inventory records recorded for {} files".format(fcnt), PgLOG.LOGWRN)
84
+
85
+ #
86
+ # refill imma inventory tablers
87
+ #
88
+ def refill_imma_inventory():
89
+
90
+ dcnt = 0
91
+ inventory = PgIMMA.get_inventory_record(0, PVALS['oflag'])
92
+
93
+ cdate = get_inventory_next_date(inventory['date'])
94
+ while cdate:
95
+ inventory = PgIMMA.add_inventory_record('', cdate, 0, inventory, PVALS['oflag'])
96
+ dcnt += 1
97
+ cdate = get_inventory_next_date(inventory['date'])
98
+
99
+ PgLOG.pglog("inventory records refilled up for {} days".format(dcnt), PgLOG.LOGWRN)
100
+
101
+ #
102
+ # get inventory next date for given date
103
+ #
104
+ def get_inventory_next_date(cdate):
105
+
106
+ pgrec = PgDBI.pgget("cntldb.inventory", "min(date) mdate", ("date > '{}'".format(cdate) if cdate else ''), PgLOG.LGEREX)
107
+
108
+ return (pgrec['mdate'] if pgrec else None)
109
+
110
+ #
111
+ # read icoads record from given file name and save them into IVADDB
112
+ #
113
+ def process_imma_file(fname, inventory):
114
+
115
+ PgLOG.pglog("Record IMMA Inventory for File '{}' into IVADDB".format(fname), PgLOG.WARNLG)
116
+
117
+ IMMA = open(fname, 'r')
118
+ line = IMMA.readline()
119
+ cdate = PgIMMA.get_imma_date(line)
120
+ if PVALS['oflag'] == 0 and cdate <= inventory['date']:
121
+ PgLOG.pglog("{}({}): Must be later than saved {}".format(cdate, fname, inventory['date']), PgLOG.LGEREX)
122
+
123
+ mcnt = icnt = 0
124
+ count = 1
125
+ while line:
126
+ idate = PgIMMA.get_imma_date(line)
127
+ if idate != cdate:
128
+ inventory = PgIMMA.add_inventory_record(fname, cdate, count, inventory, PVALS['oflag'])
129
+ mcnt += count
130
+ count = 0
131
+ cdate = idate
132
+ icnt += 1
133
+
134
+ count += 1
135
+ line = IMMA.readline()
136
+
137
+ IMMA.close()
138
+
139
+ inventory = PgIMMA.add_inventory_record(fname, cdate, count, inventory, PVALS['oflag'])
140
+ mcnt += count
141
+ icnt += 1
142
+ PgLOG.pglog("{}: {} records recorded into {} inventory records".format(fname, mcnt, icnt), PgLOG.LOGWRN)
143
+
144
+ return inventory
145
+
146
+ #
147
+ # call main() to start program
148
+ #
149
+ if __name__ == "__main__": main()
@@ -0,0 +1,289 @@
1
+ #!/usr/bin/env python3
2
+ #
3
+ ##################################################################################
4
+ #
5
+ # Title : fillitable
6
+ # Author : Zaihua Ji, zji@ucar.edu
7
+ # Date : 12/31/2020
8
+ # 2025-03-03 transferred to package rda_python_icoads from
9
+ # https://github.com/NCAR/rda-icoads.git
10
+ # Purpose : fill ICOADS tables for specified fields, such as PT, DCK, SID, and etc.
11
+ #
12
+ # Github : https://github.com/NCAR/rda-python-icoads.git
13
+ #
14
+ ##################################################################################
15
+
16
+ import sys
17
+ import os
18
+ import re
19
+ from os import path as op
20
+ from rda_python_common import PgLOG
21
+ from rda_python_common import PgDBI
22
+ from rda_python_common import PgUtil
23
+ from . import PgIMMA
24
+
25
+ PVALS = {
26
+ 'vars' : [],
27
+ 'tinfo' : None,
28
+ 'tcnt' : 0,
29
+ 'tidx' : [],
30
+ 'bdate' : None,
31
+ 'edate' : None,
32
+ }
33
+
34
+ #
35
+ # main function to run dsarch
36
+ #
37
+ def main():
38
+
39
+ option = ''
40
+ addvar = fillit = 0
41
+ argv = sys.argv[1:]
42
+
43
+ for arg in argv:
44
+ if arg == "-b":
45
+ PgLOG.PGLOG['BCKGRND'] = 1
46
+ option = ''
47
+ elif arg == "-a":
48
+ addvar = 1
49
+ option = ''
50
+ elif arg == "-t":
51
+ fillit = 1
52
+ option = ''
53
+ elif arg == "-i":
54
+ option = 'i'
55
+ elif arg == "-r":
56
+ option = 'r'
57
+ elif arg == "-v":
58
+ option = 'v'
59
+ elif re.match(r'^-', arg):
60
+ PgLOG.pglog(arg + ": Invalid Option", PgLOG.LGWNEX)
61
+ else:
62
+ if option == 'v':
63
+ PVALS['vars'].append(arg)
64
+ elif option == 'i':
65
+ if len(PVALS['tidx']) == 2:
66
+ PgLOG.pglog(arg + ": More than 2 table indices provided for index range", PgLOG.LGEREX)
67
+ PVALS['tidx'].append(arg)
68
+ elif option == 'r':
69
+ if not PVALS['bdate']:
70
+ PVALS['bdate'] = arg
71
+ elif not PVALS['edate']:
72
+ PVALS['edate'] = arg
73
+ else:
74
+ PgLOG.pglog("{}: More than 2 dates passed in for -{}".foramt(arg, option), PgLOG.LGWNEX)
75
+ else:
76
+ PgLOG.pglog(arg + ": Value passed in without leading Option", PgLOG.LGWNEX)
77
+
78
+ if not (PVALS['vars'] or fillit):
79
+ print("Usage: fillitable [-i TableIndex1 [TableIndex2]] [-r BeginDate [EndDate]] [-a] [-t] [-v VariableNameList]")
80
+ print(" Option -i: specify table index range to fill variable tables, use one table index if TableIndex2 is missed")
81
+ print(" Option -r: provide date range to fill variable tables")
82
+ print(" Option -a: read key and descrition pairs from file i(pt|dck|sid).txt to add/update variable tables ipt/idck/isid")
83
+ print(" Option -v: specify variable names (pt dck sid) to fill variable tables")
84
+ print(" Option -t: fill dssdb.itable if present")
85
+ PgLOG.pgexit()
86
+
87
+ PgLOG.PGLOG['LOGFILE'] = "icoads.log"
88
+ PgDBI.ivaddb_dbname()
89
+ PgLOG.cmdlog("fillitable {}".format(' '.join(argv)))
90
+ get_table_info(fillit)
91
+
92
+ if PVALS['vars']:
93
+ if addvar: add_field_records()
94
+ fill_field_records()
95
+
96
+ if fillit: fill_itable_records()
97
+
98
+ PgLOG.cmdlog()
99
+ PgLOG.pgexit()
100
+
101
+ #
102
+ # get the table info array
103
+ #
104
+ def get_table_info(fillit):
105
+
106
+ if len(PVALS['tidx']) == 2:
107
+ cnd = "tidx BETWEEN {} AND {}".format(PVALS['tidx'][0], PVALS['tidx'][1])
108
+ elif len(PVALS['tidx']) == 1:
109
+ cnd = "tidx = {}".format(PVALS['tidx'][0])
110
+ elif PVALS['edate']:
111
+ cnd = "date BETWEEN '{}' AND '{}'".format(PVALS['bdate'], PVALS['edate'])
112
+ elif PVALS['edate']:
113
+ cnd = "date >= '{}'".format(PVALS['bdate'])
114
+ else:
115
+ cnd = ''
116
+
117
+ flds = "tidx, min(miniidx) miniidx, max(maxiidx) maxiidx"
118
+ if fillit: flds += ", min(date) bdate, max(date) edate"
119
+ PVALS['tinfo'] = PgDBI.pgmget('cntldb.inventory', flds, cnd + " GROUP BY tidx", PgLOG.LGEREX);
120
+ PVALS['tcnt'] = len(PVALS['tinfo']['tidx']) if PVALS['tinfo'] else 0
121
+
122
+ if not PVALS['tcnt']: PgLOG.pglog("No table index found in IVADDB for " + cnd, PgLOG.LGEREX)
123
+
124
+ #
125
+ # add fiels records into IVADDB
126
+ #
127
+ def add_field_records():
128
+
129
+ # add field record if not exists yet
130
+ for var in PVALS['vars']:
131
+ vtable = "i" + var
132
+ file = vtable + ".txt"
133
+ vcnt = acnt = ucnt = 0
134
+ IVAR = open(file, 'r')
135
+ line = IVAR.readline()
136
+ while line:
137
+ line = PgLOG.pgtrim(line)
138
+ ms = re.match(r'^(\d+)\t(\w.*)$', line)
139
+ if ms:
140
+ stat = add_field_value(var, vtable, ms.group(1), ms.group(2))
141
+ vcnt += 1
142
+ if stat == 1:
143
+ acnt += 1
144
+ elif stat == 2:
145
+ ucnt += 1
146
+
147
+ IVAR.close()
148
+ PgLOG.pglog("{}/{} of {} values added/updated into table {}".format(acnt, ucnt, vcnt, vtable), PgLOG.LOGWRN)
149
+
150
+ #
151
+ # add a single field value
152
+ #
153
+ def add_field_value(var, vtable, key, desc):
154
+
155
+ cnd = "{} = {}".foramt(var, key)
156
+
157
+ pgrec = PgDBI.pgget(vtable, "*", cnd)
158
+
159
+ if pgrec:
160
+ if desc != pgrec['note']:
161
+ record = {'note' : desc}
162
+ if PgDBI.pgupdt(vtable, record, cnd, PgLOG.LGEREX): return 2
163
+ else:
164
+ record = {var: key, 'note' : desc}
165
+ if PgDBI.pgadd(vtable, record, PgLOG.LGEREX): return 1
166
+
167
+ return 0
168
+
169
+ #
170
+ # file field records in to IVADDB
171
+ #
172
+ def fill_field_records():
173
+
174
+ # count records and set max/min dates for given variable values
175
+ for var in PVALS['vars']:
176
+ vtable = "i" + var
177
+ vinfo = PgIMMA.name2number(var)
178
+ aname = vinfo[2]
179
+ fill_field_value(var, vtable, aname)
180
+
181
+ #
182
+ # fill a signle field value
183
+ #
184
+ def fill_field_value(var, vtable, aname):
185
+
186
+ flds = var +", min(iidx) imin, max(iidx) imax, count(iidx) icnt"
187
+ cnd = "GROUP BY " + var
188
+
189
+ # find min tidx/date
190
+ records = {}
191
+ pgvars = {}
192
+ pgrecs = PgDBI.pgmget(vtable, "*", "", PgLOG.LGEREX)
193
+ vcnt = len(pgrecs[var]) if pgrecs else 0
194
+ for i in range(vcnt):
195
+ pgrec = PgUtil.onerecord(pgrecs, i)
196
+ pgvars[pgrec[var]] = pgrec
197
+
198
+ for i in range(PVALS['tcnt']):
199
+ tidx = PVALS['tinfo']['tidx'][i]
200
+ miniidx = PVALS['tinfo']['miniidx'][i]
201
+ maxiidx = PVALS['tinfo']['maxiidx'][i]
202
+ atable = "{}_{}".format(aname, tidx)
203
+ pgrecs = PgDBI.pgmget(atable, flds, "iidx BETWEEN {} AND {} AND {} IS NOT NULL GROUP BY {}".format(miniidx, maxiidx, var, var), PgLOG.LGEREX)
204
+ cnt = len(pgrecs[var]) if pgrecs else 0
205
+ if not cnt: continue
206
+
207
+ PgLOG.pglog("TIDX{}: count indices for variable {}".format(tidx, var), PgLOG.LOGWRN)
208
+ for j in range(cnt):
209
+ pgrec = PgUtil.onerecord(pgrecs, j)
210
+ val = pgrec[var]
211
+ pgvar = pgvars[val] if val in pgvars else None
212
+ if not pgvar: PgLOG.pglog("{}: Missing value of {} in {}".format(var, val, vtable), PgLOG.LGEREX)
213
+ if val not in records: records[val] = {}
214
+ if not pgvar['count']:
215
+ records[val]['count'] = pgvar['count'] = pgrec['icnt']
216
+ records[val]['miniidx'] = pgvar['miniidx'] = pgrec['imin']
217
+ records[val]['start_date'] = pgvar['start_date'] = PgIMMA.iidx2date(pgrec['imin'])
218
+ records[val]['maxiidx'] = pgvar['maxiidx'] = pgrec['imax']
219
+ records[val]['end_date'] = pgvar['end_date'] = PgIMMA.iidx2date(pgrec['imax'])
220
+ elif pgrec['imin'] > pgvar['maxiidx']:
221
+ pgvar['count'] += pgrec['icnt']
222
+ records[val]['count'] = pgvar['count']
223
+ records[val]['maxiidx'] = pgvar['maxiidx'] = pgrec['imax']
224
+ records[val]['end_date'] = pgvar['end_date'] = PgIMMA.iidx2date(pgrec['imax'])
225
+ elif pgrec['imax'] < pgvar['miniidx']:
226
+ pgvar['count'] += pgrec['icnt']
227
+ records[val]['count'] = pgvar['count']
228
+ records[val]['miniidx'] = pgvar['miniidx'] = pgrec['imin']
229
+ records[val]['start_date'] = pgvar['start_date'] = PgIMMA.iidx2date(pgrec['imin'])
230
+ else:
231
+ PgLOG.pglog("{}({}): index counted already between {} and {}".format(var, val, pgrec['imin'], pgrec['imax']), PgLOG.LOGWRN)
232
+
233
+ cnt = 0
234
+ for val in records:
235
+ pgrec = records[val]
236
+ cnt += PgDBI.pgupdt(vtable, pgrec, "{} = {}".format(var, val), PgLOG.LGEREX)
237
+
238
+ PgLOG.pglog("{} of {} values recounted in table '{}'".format(cnt, vcnt, vtable), PgLOG.LOGWRN)
239
+
240
+ #
241
+ # fill in the itable records in dabase dssdb
242
+ #
243
+ def fill_itable_records():
244
+
245
+ PgDBI.dssdb_dbname()
246
+
247
+ acnt = ucnt = 0
248
+ for i in range(PVALS['tcnt']):
249
+ tidx = PVALS['tinfo']['tidx'][i]
250
+ miniidx = PVALS['tinfo']['miniidx'][i]
251
+ maxiidx = PVALS['tinfo']['maxiidx'][i]
252
+ bdate = PVALS['tinfo']['bdate'][i]
253
+ edate = PVALS['tinfo']['edate'][i]
254
+ pgrec = PgDBI.pgget('itable', "*", "tidx = {}".format(tidx), PgLOG.LGEREX)
255
+ record = {}
256
+ msg = "{}: ".format(tidx)
257
+ if pgrec:
258
+ sep = ''
259
+ msg += "Change "
260
+ if miniidx < pgrec['miniidx']:
261
+ record['miniidx'] = miniidx
262
+ record['bdate'] = bdate
263
+ sep = ', '
264
+ msg += "Miniidx from {} to {} & Bdate from {} to {}".format(pgrec['miniidx'], miniidx, pgrec['bdate'], bdate)
265
+ if maxiidx > pgrec['maxiidx']:
266
+ record['maxiidx'] = maxiidx
267
+ record['edate'] = edate
268
+ msg += "{}Maxiidx from {} to {} & Edate from {} to {}".format(sep, pgrec['maxiidx'], maxiidx, pgrec['edate'], edate)
269
+ if record and PgDBI.pgupdt('itable', record, "tidx = {}".format(tidx), PgLOG.LGEREX):
270
+ ucnt += 1
271
+ PgLOG.pglog(msg, PgLOG.LOGWRN)
272
+ else:
273
+ record['tidx'] = tidx
274
+ record['miniidx'] = miniidx
275
+ record['bdate'] = bdate
276
+ record['maxiidx'] = maxiidx
277
+ record['edate'] = edate
278
+ msg += "Add Miniidx={} & Bdate={}, Maxiidx={} & Edate={}".format(miniidx, bdate, maxiidx, edate)
279
+ if PgDBI.pgadd('itable', record, PgLOG.LGEREX):
280
+ acnt += 1
281
+ PgLOG.pglog(msg, PgLOG.LOGWRN)
282
+
283
+ s = 's' if PVALS['tcnt'] > 1 else ''
284
+ PgLOG.pglog("{}/{} of {} dssdb.itable records Added/Updated".format(acnt, ucnt, PVALS['tcnt']), PgLOG.LOGWRN)
285
+
286
+ #
287
+ # call main() to start program
288
+ #
289
+ if __name__ == "__main__": main()
@@ -0,0 +1,94 @@
1
+ #!/usr/bin/env python3
2
+ #
3
+ ##################################################################################
4
+ #
5
+ # Title : fillmonth
6
+ # Author : Zaihua Ji, zji@ucar.edu
7
+ # Date : 01/03/2021
8
+ # 2025-03-03 transferred to package rda_python_icoads from
9
+ # https://github.com/NCAR/rda-icoads.git
10
+ # Purpose : process ICOADS monthly data file in IMMA1 format and fill into IVADDB
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
+
22
+ CMDS = {
23
+ 'filename' : "IMMA1_R3.0.2_",
24
+ 'fillicoads' : "fillicoads -i ",
25
+ 'fillitable' : "fillitable -t -v dck pt sid -r ",
26
+ 'cdmsmonth' : "cdmsmonth "
27
+ }
28
+
29
+ #
30
+ # main function to run dsarch
31
+ #
32
+ def main():
33
+
34
+ argv = sys.argv[1:]
35
+ smonth = srange = None
36
+
37
+ for arg in argv:
38
+ if arg == "-b":
39
+ PgLOG.PGLOG['BCKGRND'] = 1
40
+ elif re.match(r'^-', arg):
41
+ PgLOG.pglog(arg + ": Invalid Option", PgLOG.LGWNEX)
42
+ elif not smonth:
43
+ ms = re.match(r'^(\d+)-(\d+)', arg)
44
+ if ms:
45
+ smonth = "{:04}-{:02}".format(int(ms.group(1)), int(ms.group(2)))
46
+ srange = "{}-01 {}".format(smonth, PgUtil.enddate(smonth, 0, 'M'))
47
+ else:
48
+ PgLOG.pglog(arg +": Invalid month format", PgLOG.LGWNEX)
49
+ else:
50
+ PgLOG.pglog("{}: Month is given alreay as '{}'".format(arg, smonth), PgLOG.LGWNEX)
51
+
52
+ if not smonth:
53
+ print("Usage: fillmonth ProcessMonth")
54
+ print(" Provide a month (YYYY-MM), to fill monthly IMMA1 into IVADDB")
55
+ sys.exit(0)
56
+
57
+ PgLOG.PGLOG['LOGFILE'] = "icoads.log"
58
+ PgLOG.cmdlog("fillmonth {}".format(' '.join(argv)))
59
+ fill_monthly_data(smonth, srange)
60
+ PgLOG.cmdlog()
61
+ sys.exit(0)
62
+
63
+ #
64
+ # fill monthly IMMA1 data to IVADDB
65
+ #
66
+ def fill_monthly_data(smonth, srange):
67
+
68
+ file = CMDS['filename'] + smonth
69
+
70
+ if not op.isfile(file):
71
+ # unzip file
72
+ cmd = "gunzip {}.gz".format(file)
73
+ PgLOG.pgsystem(cmd, PgLOG.LGWNEX, 5)
74
+
75
+ # fillicoads
76
+ cmd = CMDS['fillicoads'] + file
77
+ PgLOG.pgsystem(cmd, PgLOG.LGWNEX, 5)
78
+
79
+ # zip file
80
+ cmd = "gzip " + file
81
+ PgLOG.pgsystem(cmd, PgLOG.LGWNEX, 5)
82
+
83
+ # fillitable
84
+ cmd = CMDS['fillitable'] + srange
85
+ PgLOG.pgsystem(cmd, PgLOG.LOGWRN, 5)
86
+
87
+ # cdmsmonth
88
+ # cmd = CMDS['cdmsmonth'] + smonth
89
+ # PgLOG.pgsystem(cmd, PgLOG.LOGWRN, 5)
90
+
91
+ #
92
+ # call main() to start program
93
+ #
94
+ if __name__ == "__main__": main()