rda-python-icoads 3.0.3__tar.gz → 3.0.4__tar.gz

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.
Files changed (38) hide show
  1. {rda_python_icoads-3.0.3/src/rda_python_icoads.egg-info → rda_python_icoads-3.0.4}/PKG-INFO +1 -1
  2. {rda_python_icoads-3.0.3 → rda_python_icoads-3.0.4}/pyproject.toml +1 -1
  3. {rda_python_icoads-3.0.3 → rda_python_icoads-3.0.4}/src/rda_python_icoads/fillicoads.py +14 -47
  4. {rda_python_icoads-3.0.3 → rda_python_icoads-3.0.4}/src/rda_python_icoads/fillmonth.py +55 -5
  5. {rda_python_icoads-3.0.3 → rda_python_icoads-3.0.4/src/rda_python_icoads.egg-info}/PKG-INFO +1 -1
  6. {rda_python_icoads-3.0.3 → rda_python_icoads-3.0.4}/LICENSE +0 -0
  7. {rda_python_icoads-3.0.3 → rda_python_icoads-3.0.4}/MANIFEST.in +0 -0
  8. {rda_python_icoads-3.0.3 → rda_python_icoads-3.0.4}/README.md +0 -0
  9. {rda_python_icoads-3.0.3 → rda_python_icoads-3.0.4}/setup.cfg +0 -0
  10. {rda_python_icoads-3.0.3 → rda_python_icoads-3.0.4}/src/rda_python_icoads/PgIMMA.py +0 -0
  11. {rda_python_icoads-3.0.3 → rda_python_icoads-3.0.4}/src/rda_python_icoads/R3.0-stat_doc.pdf +0 -0
  12. {rda_python_icoads-3.0.3 → rda_python_icoads-3.0.4}/src/rda_python_icoads/README_R3.0_Subset.html +0 -0
  13. {rda_python_icoads-3.0.3 → rda_python_icoads-3.0.4}/src/rda_python_icoads/__init__.py +0 -0
  14. {rda_python_icoads-3.0.3 → rda_python_icoads-3.0.4}/src/rda_python_icoads/checkicoads.py +0 -0
  15. {rda_python_icoads-3.0.3 → rda_python_icoads-3.0.4}/src/rda_python_icoads/cleanicoads.py +0 -0
  16. {rda_python_icoads-3.0.3 → rda_python_icoads-3.0.4}/src/rda_python_icoads/countattm.py +0 -0
  17. {rda_python_icoads-3.0.3 → rda_python_icoads-3.0.4}/src/rda_python_icoads/countattmvar.py +0 -0
  18. {rda_python_icoads-3.0.3 → rda_python_icoads-3.0.4}/src/rda_python_icoads/counticoads.py +0 -0
  19. {rda_python_icoads-3.0.3 → rda_python_icoads-3.0.4}/src/rda_python_icoads/countsst.py +0 -0
  20. {rda_python_icoads-3.0.3 → rda_python_icoads-3.0.4}/src/rda_python_icoads/fillinventory.py +0 -0
  21. {rda_python_icoads-3.0.3 → rda_python_icoads-3.0.4}/src/rda_python_icoads/fillitable.py +0 -0
  22. {rda_python_icoads-3.0.3 → rda_python_icoads-3.0.4}/src/rda_python_icoads/fixiidx.py +0 -0
  23. {rda_python_icoads-3.0.3 → rda_python_icoads-3.0.4}/src/rda_python_icoads/imma1_subset.py +0 -0
  24. {rda_python_icoads-3.0.3 → rda_python_icoads-3.0.4}/src/rda_python_icoads/maxsst.py +0 -0
  25. {rda_python_icoads-3.0.3 → rda_python_icoads-3.0.4}/src/rda_python_icoads/msg +0 -0
  26. {rda_python_icoads-3.0.3 → rda_python_icoads-3.0.4}/src/rda_python_icoads/msg3.0_subset_readme.txt +0 -0
  27. {rda_python_icoads-3.0.3 → rda_python_icoads-3.0.4}/src/rda_python_icoads/msg3_subset.py +0 -0
  28. {rda_python_icoads-3.0.3 → rda_python_icoads-3.0.4}/src/rda_python_icoads/msg_download.py +0 -0
  29. {rda_python_icoads-3.0.3 → rda_python_icoads-3.0.4}/src/rda_python_icoads/msgsubset.f +0 -0
  30. {rda_python_icoads-3.0.3 → rda_python_icoads-3.0.4}/src/rda_python_icoads/pg_imma.py +0 -0
  31. {rda_python_icoads-3.0.3 → rda_python_icoads-3.0.4}/src/rda_python_icoads/rdimma1_csv.f +0 -0
  32. {rda_python_icoads-3.0.3 → rda_python_icoads-3.0.4}/src/rda_python_icoads/writeicoads.py +0 -0
  33. {rda_python_icoads-3.0.3 → rda_python_icoads-3.0.4}/src/rda_python_icoads.egg-info/SOURCES.txt +0 -0
  34. {rda_python_icoads-3.0.3 → rda_python_icoads-3.0.4}/src/rda_python_icoads.egg-info/dependency_links.txt +0 -0
  35. {rda_python_icoads-3.0.3 → rda_python_icoads-3.0.4}/src/rda_python_icoads.egg-info/entry_points.txt +0 -0
  36. {rda_python_icoads-3.0.3 → rda_python_icoads-3.0.4}/src/rda_python_icoads.egg-info/requires.txt +0 -0
  37. {rda_python_icoads-3.0.3 → rda_python_icoads-3.0.4}/src/rda_python_icoads.egg-info/top_level.txt +0 -0
  38. {rda_python_icoads-3.0.3 → rda_python_icoads-3.0.4}/tests/test_icoads.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rda_python_icoads
3
- Version: 3.0.3
3
+ Version: 3.0.4
4
4
  Summary: RDA python package to manage RDA ICOADS datasets
5
5
  Author-email: Zaihua Ji <zji@ucar.edu>
6
6
  Project-URL: Homepage, https://github.com/NCAR/rda-python-icoads
@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
6
6
 
7
7
  [project]
8
8
  name = "rda_python_icoads"
9
- version = "3.0.3"
9
+ version = "3.0.4"
10
10
  authors = [
11
11
  { name="Zaihua Ji", email="zji@ucar.edu" },
12
12
  ]
@@ -29,8 +29,7 @@ class FillIcoads(PgIMMA):
29
29
  'names' : None,
30
30
  'files' : [],
31
31
  'dates' : [],
32
- 'dtlen' : 0,
33
- 'zipped' : 0
32
+ 'dtlen' : 0
34
33
  }
35
34
 
36
35
  #
@@ -112,12 +111,6 @@ class FillIcoads(PgIMMA):
112
111
  fcnt = 0
113
112
  tcounts = [0]*self.TABLECOUNT
114
113
  for file in self.PVALS['files']:
115
- pfile = self.get_partial_month_file(file) if addinventory else None
116
- if pfile:
117
- fcnt += 1
118
- acnts = self.process_imma_file(pfile, addinventory)
119
- for i in range(self.TABLECOUNT): tcounts[i] += acnts[i]
120
- if self.PVALS['zipped']: self.pgsystem("gzip " + pfile, self.LOGWRN, 5)
121
114
  fcnt += 1
122
115
  acnts = self.process_imma_file(file, addinventory)
123
116
  for i in range(self.TABLECOUNT): tcounts[i] += acnts[i]
@@ -152,49 +145,21 @@ class FillIcoads(PgIMMA):
152
145
  return self.format_date(pgrec['mdate']) if pgrec and pgrec['mdate'] else None
153
146
 
154
147
  #
155
- # locate a data file, gunzip it if only the gzipped one is on file
148
+ # the iidx values are allocated sequentially, so no date can be filled while an earlier one is
149
+ # still missing; a month must be filled up before the next month is filled, and a month cannot
150
+ # be skipped; months are sequenced by fillmonth, this only guards a direct call
156
151
  #
157
- def locate_imma_file(self, fname):
158
-
159
- self.PVALS['zipped'] = 0
160
- if op.isfile(fname): return fname
161
-
162
- zfile = fname + ".gz"
163
- if op.isfile(zfile):
164
- self.pgsystem("gunzip " + zfile, self.LOGWRN, 5)
165
- if op.isfile(fname):
166
- self.PVALS['zipped'] = 1
167
- return fname
168
-
169
- return None
170
-
171
- #
172
- # a month is filled up only if its last day is in the inventory; if an earlier month is
173
- # filled partially, return the name of its data file, to fill up the missing dates before
174
- # the given file is filled
175
- #
176
- def get_partial_month_file(self, fname):
152
+ def check_fill_order(self, fdate):
177
153
 
178
154
  mdate = self.get_max_filled_date()
179
- if not mdate: return None # nothing filled yet
180
-
181
- edate = self.enddate(mdate, 0, 'M')
182
- if mdate == edate: return None # the latest filled month is filled up
183
-
184
- fdate = self.get_imma_file_date(fname)
185
- if not fdate or self.diffdate(fdate, edate) <= 0: return None # the given file holds the partial month
186
-
187
- pgrec = self.pgget(f"{self.CNTLSC}.inventory", "fname", "date = '{}'".format(mdate), self.LGEREX)
188
- pfile = self.locate_imma_file(pgrec['fname']) if pgrec and pgrec['fname'] else None
189
- if not pfile:
190
- self.pglog("{}: month is filled through {} only, and its data file is not found in {} to "
191
- "fill it up before filling {}".format(mdate[0:7], mdate, op.abspath('.'), fdate[0:7]), self.LGEREX)
155
+ if not mdate: return # nothing filled yet
156
+ if self.diffdate(mdate, fdate) >= 0: return # the file holds filled dates already
192
157
 
193
- # the leading '>' propagates the note up through the calling processes, into the email report
194
- self.pglog("> {}: filled through {} only, fill it up from {} before filling {}".format(
195
- mdate[0:7], mdate, pfile, fdate[0:7]), self.LOGWRN)
158
+ rdate = self.adddate(mdate, 0, 0, 1) # the first missing date
159
+ if self.diffdate(fdate[0:7] + "-01", rdate) <= 0: return # the file covers it
196
160
 
197
- return pfile
161
+ self.pglog("{}: filled through {} only, fill from {} before filling {}".format(
162
+ mdate[0:7], mdate, rdate, fdate[0:7]), self.LGEREX)
198
163
 
199
164
  #
200
165
  # skip the dates that are filled already if the month of the given file is resumed
@@ -245,7 +210,9 @@ class FillIcoads(PgIMMA):
245
210
  edate = self.PVALS['dates'][1] if self.PVALS['dtlen'] > 1 else None
246
211
 
247
212
  fdate = self.get_imma_file_date(fname) if iname else None
248
- if fdate: bdate = self.get_resume_date(fname, fdate, bdate)
213
+ if fdate:
214
+ if self.PVALS['dtlen'] == 0: self.check_fill_order(fdate)
215
+ bdate = self.get_resume_date(fname, fdate, bdate)
249
216
 
250
217
  IMMA = open(fname, 'r', encoding = 'latin_1')
251
218
 
@@ -8,6 +8,7 @@
8
8
  # 2025-03-03 transferred to package rda_python_icoads from
9
9
  # https://github.com/NCAR/rda-icoads.git
10
10
  # 2026-09-04 convert to class FillMonth
11
+ # 2026-09-09 fill each missing month, in order, up to the given month
11
12
  # Purpose : process ICOADS monthly data file in IMMA1 format and fill into IVADDB
12
13
  #
13
14
  # Github : https://github.com/NCAR/rda-python-icoads.git
@@ -18,8 +19,9 @@ import sys
18
19
  import re
19
20
  from os import path as op
20
21
  from rda_python_common.pg_util import PgUtil
22
+ from rda_python_common.pg_dbi import PgDBI
21
23
 
22
- class FillMonth(PgUtil):
24
+ class FillMonth(PgUtil, PgDBI):
23
25
 
24
26
  def __init__(self):
25
27
  super().__init__()
@@ -27,7 +29,8 @@ class FillMonth(PgUtil):
27
29
  'filenames' : ["IMMA1_R3.0.2_", "IMMA1_R3.0.3_"], # IMMA1_R3.0.3_ since 2025-08
28
30
  'fillicoads' : "fillicoads -i ",
29
31
  'fillitable' : "fillitable -t -v dck pt sid -r ",
30
- 'cdmsmonth' : "cdmsmonth "
32
+ 'cdmsmonth' : "cdmsmonth ",
33
+ 'inventory' : "cntldb.inventory"
31
34
  }
32
35
 
33
36
  #
@@ -36,7 +39,7 @@ class FillMonth(PgUtil):
36
39
  def main(self):
37
40
 
38
41
  argv = sys.argv[1:]
39
- smonth = srange = None
42
+ smonth = None
40
43
 
41
44
  for arg in argv:
42
45
  if arg == "-b":
@@ -47,7 +50,6 @@ class FillMonth(PgUtil):
47
50
  ms = re.match(r'^(\d+)-(\d+)', arg)
48
51
  if ms:
49
52
  smonth = "{:04}-{:02}".format(int(ms.group(1)), int(ms.group(2)))
50
- srange = "{}-01 {}".format(smonth, self.enddate(smonth, 0, 'M'))
51
53
  else:
52
54
  self.pglog(arg +": Invalid month format", self.LGWNEX)
53
55
  else:
@@ -56,14 +58,62 @@ class FillMonth(PgUtil):
56
58
  if not smonth:
57
59
  print("Usage: fillmonth ProcessMonth")
58
60
  print(" Provide a month (YYYY-MM), to fill monthly IMMA1 into IVADDB")
61
+ print(" Any earlier month not filled up yet is filled first, in order")
59
62
  sys.exit(0)
60
63
 
61
64
  self.PGLOG['LOGFILE'] = "icoads.log"
65
+ self.ivaddb_dbname()
62
66
  self.cmdlog("fillmonth {}".format(' '.join(argv)))
63
- self.fill_monthly_data(smonth, srange)
67
+ months = self.get_fill_months(smonth)
68
+ if len(months) > 1:
69
+ self.pglog("> {}: fill {} months, {} through {}, in order".format(
70
+ smonth, len(months), months[0][0], months[-1][0]), self.LOGWRN)
71
+ mcnt = len(months)
72
+ for i in range(mcnt):
73
+ (cmonth, bdate, edate) = months[i]
74
+ self.fill_monthly_data(cmonth, "{} {}".format(bdate, edate))
75
+ if self.month_filled(cmonth, edate) or (i + 1) == mcnt: continue
76
+ # a later month cannot be filled while this one is short of dates
77
+ self.pglog("> {}: filled partially, stop before {}".format(cmonth, months[i+1][0]), self.LOGWRN)
78
+ break
64
79
  self.cmdlog()
65
80
  sys.exit(0)
66
81
 
82
+ #
83
+ # the iidx values are allocated sequentially, so every month between the last filled date
84
+ # and the given month must be filled, in order; return a [month, bdate, edate] per month,
85
+ # with bdate on the first month set to resume a partially filled month
86
+ #
87
+ def get_fill_months(self, smonth):
88
+
89
+ edate = self.enddate(smonth, 0, 'M')
90
+ pgrec = self.pgget(self.CMDS['inventory'], "max(date) mdate", "", self.LGEREX)
91
+ mdate = self.format_date(pgrec['mdate']) if pgrec and pgrec['mdate'] else None
92
+ if not mdate: return [[smonth, smonth + "-01", edate]] # nothing filled yet
93
+
94
+ bdate = self.adddate(mdate, 0, 0, 1) # resume the partial month, or start the next one
95
+ if self.diffdate(bdate, edate) > 0: return [[smonth, smonth + "-01", edate]] # refill an earlier month
96
+
97
+ months = []
98
+ while self.diffdate(bdate, edate) <= 0:
99
+ cmonth = bdate[0:7]
100
+ cedate = self.enddate(cmonth, 0, 'M')
101
+ if self.diffdate(cedate, edate) > 0: cedate = edate
102
+ months.append([cmonth, bdate, cedate])
103
+ bdate = self.adddate(cedate, 0, 0, 1)
104
+
105
+ return months
106
+
107
+ #
108
+ # check if the given month is filled through its last date
109
+ #
110
+ def month_filled(self, cmonth, edate):
111
+
112
+ pgrec = self.pgget(self.CMDS['inventory'], "max(date) mdate",
113
+ "date BETWEEN '{}-01' AND '{}'".format(cmonth, edate), self.LGEREX)
114
+
115
+ return (pgrec and pgrec['mdate'] and self.format_date(pgrec['mdate']) == edate)
116
+
67
117
  #
68
118
  # locate the monthly IMMA1 file, gunzip it if only the gzipped one is on file
69
119
  #
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rda_python_icoads
3
- Version: 3.0.3
3
+ Version: 3.0.4
4
4
  Summary: RDA python package to manage RDA ICOADS datasets
5
5
  Author-email: Zaihua Ji <zji@ucar.edu>
6
6
  Project-URL: Homepage, https://github.com/NCAR/rda-python-icoads