rda-python-icoads 1.0.19__tar.gz → 3.0.1__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.
- rda_python_icoads-3.0.1/PKG-INFO +99 -0
- rda_python_icoads-3.0.1/README.md +81 -0
- {rda_python_icoads-1.0.19 → rda_python_icoads-3.0.1}/pyproject.toml +5 -3
- rda_python_icoads-3.0.1/src/rda_python_icoads/checkicoads.py +224 -0
- rda_python_icoads-3.0.1/src/rda_python_icoads/cleanicoads.py +180 -0
- rda_python_icoads-3.0.1/src/rda_python_icoads/countattm.py +129 -0
- rda_python_icoads-3.0.1/src/rda_python_icoads/countattmvar.py +241 -0
- rda_python_icoads-3.0.1/src/rda_python_icoads/counticoads.py +155 -0
- rda_python_icoads-3.0.1/src/rda_python_icoads/countsst.py +225 -0
- rda_python_icoads-3.0.1/src/rda_python_icoads/fillicoads.py +175 -0
- rda_python_icoads-3.0.1/src/rda_python_icoads/fillinventory.py +153 -0
- rda_python_icoads-3.0.1/src/rda_python_icoads/fillitable.py +294 -0
- rda_python_icoads-3.0.1/src/rda_python_icoads/fillmonth.py +100 -0
- rda_python_icoads-3.0.1/src/rda_python_icoads/fixiidx.py +73 -0
- rda_python_icoads-3.0.1/src/rda_python_icoads/imma1_subset.py +773 -0
- rda_python_icoads-3.0.1/src/rda_python_icoads/maxsst.py +264 -0
- rda_python_icoads-3.0.1/src/rda_python_icoads/msg3_subset.py +344 -0
- rda_python_icoads-3.0.1/src/rda_python_icoads/msg_download.py +214 -0
- rda_python_icoads-3.0.1/src/rda_python_icoads/pg_imma.py +1793 -0
- rda_python_icoads-3.0.1/src/rda_python_icoads/writeicoads.py +171 -0
- rda_python_icoads-3.0.1/src/rda_python_icoads.egg-info/PKG-INFO +99 -0
- {rda_python_icoads-1.0.19 → rda_python_icoads-3.0.1}/src/rda_python_icoads.egg-info/SOURCES.txt +1 -0
- {rda_python_icoads-1.0.19 → rda_python_icoads-3.0.1}/src/rda_python_icoads.egg-info/entry_points.txt +1 -1
- rda_python_icoads-3.0.1/src/rda_python_icoads.egg-info/requires.txt +3 -0
- rda_python_icoads-1.0.19/PKG-INFO +0 -21
- rda_python_icoads-1.0.19/README.md +0 -5
- rda_python_icoads-1.0.19/src/rda_python_icoads/checkicoads.py +0 -222
- rda_python_icoads-1.0.19/src/rda_python_icoads/cleanicoads.py +0 -176
- rda_python_icoads-1.0.19/src/rda_python_icoads/countattm.py +0 -125
- rda_python_icoads-1.0.19/src/rda_python_icoads/countattmvar.py +0 -237
- rda_python_icoads-1.0.19/src/rda_python_icoads/counticoads.py +0 -153
- rda_python_icoads-1.0.19/src/rda_python_icoads/countsst.py +0 -221
- rda_python_icoads-1.0.19/src/rda_python_icoads/fillicoads.py +0 -171
- rda_python_icoads-1.0.19/src/rda_python_icoads/fillinventory.py +0 -149
- rda_python_icoads-1.0.19/src/rda_python_icoads/fillitable.py +0 -290
- rda_python_icoads-1.0.19/src/rda_python_icoads/fillmonth.py +0 -94
- rda_python_icoads-1.0.19/src/rda_python_icoads/fixiidx.py +0 -70
- rda_python_icoads-1.0.19/src/rda_python_icoads/imma1_subset.py +0 -778
- rda_python_icoads-1.0.19/src/rda_python_icoads/maxsst.py +0 -262
- rda_python_icoads-1.0.19/src/rda_python_icoads/msg3_subset.py +0 -345
- rda_python_icoads-1.0.19/src/rda_python_icoads/msg_download.py +0 -211
- rda_python_icoads-1.0.19/src/rda_python_icoads/writeicoads.py +0 -169
- rda_python_icoads-1.0.19/src/rda_python_icoads.egg-info/PKG-INFO +0 -21
- rda_python_icoads-1.0.19/src/rda_python_icoads.egg-info/requires.txt +0 -1
- {rda_python_icoads-1.0.19 → rda_python_icoads-3.0.1}/LICENSE +0 -0
- {rda_python_icoads-1.0.19 → rda_python_icoads-3.0.1}/MANIFEST.in +0 -0
- {rda_python_icoads-1.0.19 → rda_python_icoads-3.0.1}/setup.cfg +0 -0
- {rda_python_icoads-1.0.19 → rda_python_icoads-3.0.1}/src/rda_python_icoads/PgIMMA.py +0 -0
- {rda_python_icoads-1.0.19 → rda_python_icoads-3.0.1}/src/rda_python_icoads/R3.0-stat_doc.pdf +0 -0
- {rda_python_icoads-1.0.19 → rda_python_icoads-3.0.1}/src/rda_python_icoads/README_R3.0_Subset.html +0 -0
- {rda_python_icoads-1.0.19 → rda_python_icoads-3.0.1}/src/rda_python_icoads/__init__.py +0 -0
- {rda_python_icoads-1.0.19 → rda_python_icoads-3.0.1}/src/rda_python_icoads/msg +0 -0
- {rda_python_icoads-1.0.19 → rda_python_icoads-3.0.1}/src/rda_python_icoads/msg3.0_subset_readme.txt +0 -0
- {rda_python_icoads-1.0.19 → rda_python_icoads-3.0.1}/src/rda_python_icoads/msgsubset.f +0 -0
- {rda_python_icoads-1.0.19 → rda_python_icoads-3.0.1}/src/rda_python_icoads/rdimma1_csv.f +0 -0
- {rda_python_icoads-1.0.19 → rda_python_icoads-3.0.1}/src/rda_python_icoads.egg-info/dependency_links.txt +0 -0
- {rda_python_icoads-1.0.19 → rda_python_icoads-3.0.1}/src/rda_python_icoads.egg-info/top_level.txt +0 -0
- {rda_python_icoads-1.0.19 → rda_python_icoads-3.0.1}/tests/test_icoads.py +0 -0
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: rda_python_icoads
|
|
3
|
+
Version: 3.0.1
|
|
4
|
+
Summary: RDA python package to manage RDA ICOADS datasets
|
|
5
|
+
Author-email: Zaihua Ji <zji@ucar.edu>
|
|
6
|
+
Project-URL: Homepage, https://github.com/NCAR/rda-python-icoads
|
|
7
|
+
Classifier: Programming Language :: Python :: 3
|
|
8
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
9
|
+
Classifier: Operating System :: OS Independent
|
|
10
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
11
|
+
Requires-Python: >=3.7
|
|
12
|
+
Description-Content-Type: text/markdown
|
|
13
|
+
License-File: LICENSE
|
|
14
|
+
Requires-Dist: numpy
|
|
15
|
+
Requires-Dist: rda_python_common>=3.0.14
|
|
16
|
+
Requires-Dist: rda_python_dsrqst>=2.0.4
|
|
17
|
+
Dynamic: license-file
|
|
18
|
+
|
|
19
|
+
# rda_python_icoads
|
|
20
|
+
|
|
21
|
+
RDA Python package to manage RDA ICOADS datasets.
|
|
22
|
+
|
|
23
|
+
## Prerequisite
|
|
24
|
+
|
|
25
|
+
To dynamically generate a PDF readme fitting for each data subset, the Linux
|
|
26
|
+
commandline utility `wkhtmltopdf` must be installed. See
|
|
27
|
+
<https://wkhtmltopdf.org/index.html> for download and install instructions.
|
|
28
|
+
|
|
29
|
+
## Programs
|
|
30
|
+
|
|
31
|
+
The package installs the following command-line utilities, all running as the
|
|
32
|
+
current user:
|
|
33
|
+
|
|
34
|
+
- `imma1_subset` — generate IMMA1-format ICOADS subset deliveries
|
|
35
|
+
- `msg3_subset` — generate MSG-format ICOADS R3 subsets
|
|
36
|
+
- `msg_download` — download MSG ICOADS source files
|
|
37
|
+
- `checkicoads` — check ICOADS archive integrity
|
|
38
|
+
- `cleanicoads` — clean up stale ICOADS files
|
|
39
|
+
- `counticoads`, `countattm`, `countattmvar`, `countsst` — record/attribute counters
|
|
40
|
+
- `fillicoads`, `fillinventory`, `fillitable`, `fillmonth` — populate ICOADS DB tables
|
|
41
|
+
- `fixiidx` — fix ICOADS indices
|
|
42
|
+
- `maxsst` — compute maximum SST values
|
|
43
|
+
- `writeicoads` — write ICOADS records
|
|
44
|
+
|
|
45
|
+
Run any program with no arguments to print its usage details.
|
|
46
|
+
|
|
47
|
+
## Environment setup
|
|
48
|
+
|
|
49
|
+
Create a Python environment first; package installs in the next section run
|
|
50
|
+
inside whichever environment you activate here.
|
|
51
|
+
|
|
52
|
+
### Option A — Python venv (DECS machines)
|
|
53
|
+
|
|
54
|
+
```bash
|
|
55
|
+
python3 -m venv $ENVHOME # e.g. /glade/u/home/gdexdata/gdexmsenv
|
|
56
|
+
source $ENVHOME/bin/activate
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Option B — Conda (DAV/Casper)
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
conda create --prefix $ENVHOME python=3.12 # e.g. /glade/work/gdexdata/conda-envs/pg-gdex
|
|
63
|
+
conda activate $ENVHOME
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Installing rda-python-icoads
|
|
67
|
+
|
|
68
|
+
Pick whichever install mode fits your workflow. All variants pull in the
|
|
69
|
+
transitive dependency (`rda_python_common`) automatically.
|
|
70
|
+
|
|
71
|
+
For local development, clone this repo alongside your project and install it
|
|
72
|
+
in editable mode so that changes are picked up without re-installing:
|
|
73
|
+
|
|
74
|
+
```bash
|
|
75
|
+
git clone https://github.com/NCAR/rda-python-icoads.git
|
|
76
|
+
cd rda-python-icoads
|
|
77
|
+
pip install -e .
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
To test a specific branch (e.g. an in-progress feature or fix branch), pass
|
|
81
|
+
`-b/--branch` to `git clone`:
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
git clone -b <branch-name> https://github.com/NCAR/rda-python-icoads.git
|
|
85
|
+
cd rda-python-icoads
|
|
86
|
+
pip install -e .
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
For a regular (non-editable) install from a checkout:
|
|
90
|
+
|
|
91
|
+
```bash
|
|
92
|
+
pip install /path/to/rda-python-icoads
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
For a production install on a system that uses the published distribution:
|
|
96
|
+
|
|
97
|
+
```bash
|
|
98
|
+
pip install rda_python_icoads
|
|
99
|
+
```
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
# rda_python_icoads
|
|
2
|
+
|
|
3
|
+
RDA Python package to manage RDA ICOADS datasets.
|
|
4
|
+
|
|
5
|
+
## Prerequisite
|
|
6
|
+
|
|
7
|
+
To dynamically generate a PDF readme fitting for each data subset, the Linux
|
|
8
|
+
commandline utility `wkhtmltopdf` must be installed. See
|
|
9
|
+
<https://wkhtmltopdf.org/index.html> for download and install instructions.
|
|
10
|
+
|
|
11
|
+
## Programs
|
|
12
|
+
|
|
13
|
+
The package installs the following command-line utilities, all running as the
|
|
14
|
+
current user:
|
|
15
|
+
|
|
16
|
+
- `imma1_subset` — generate IMMA1-format ICOADS subset deliveries
|
|
17
|
+
- `msg3_subset` — generate MSG-format ICOADS R3 subsets
|
|
18
|
+
- `msg_download` — download MSG ICOADS source files
|
|
19
|
+
- `checkicoads` — check ICOADS archive integrity
|
|
20
|
+
- `cleanicoads` — clean up stale ICOADS files
|
|
21
|
+
- `counticoads`, `countattm`, `countattmvar`, `countsst` — record/attribute counters
|
|
22
|
+
- `fillicoads`, `fillinventory`, `fillitable`, `fillmonth` — populate ICOADS DB tables
|
|
23
|
+
- `fixiidx` — fix ICOADS indices
|
|
24
|
+
- `maxsst` — compute maximum SST values
|
|
25
|
+
- `writeicoads` — write ICOADS records
|
|
26
|
+
|
|
27
|
+
Run any program with no arguments to print its usage details.
|
|
28
|
+
|
|
29
|
+
## Environment setup
|
|
30
|
+
|
|
31
|
+
Create a Python environment first; package installs in the next section run
|
|
32
|
+
inside whichever environment you activate here.
|
|
33
|
+
|
|
34
|
+
### Option A — Python venv (DECS machines)
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
python3 -m venv $ENVHOME # e.g. /glade/u/home/gdexdata/gdexmsenv
|
|
38
|
+
source $ENVHOME/bin/activate
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Option B — Conda (DAV/Casper)
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
conda create --prefix $ENVHOME python=3.12 # e.g. /glade/work/gdexdata/conda-envs/pg-gdex
|
|
45
|
+
conda activate $ENVHOME
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
## Installing rda-python-icoads
|
|
49
|
+
|
|
50
|
+
Pick whichever install mode fits your workflow. All variants pull in the
|
|
51
|
+
transitive dependency (`rda_python_common`) automatically.
|
|
52
|
+
|
|
53
|
+
For local development, clone this repo alongside your project and install it
|
|
54
|
+
in editable mode so that changes are picked up without re-installing:
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
git clone https://github.com/NCAR/rda-python-icoads.git
|
|
58
|
+
cd rda-python-icoads
|
|
59
|
+
pip install -e .
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
To test a specific branch (e.g. an in-progress feature or fix branch), pass
|
|
63
|
+
`-b/--branch` to `git clone`:
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
git clone -b <branch-name> https://github.com/NCAR/rda-python-icoads.git
|
|
67
|
+
cd rda-python-icoads
|
|
68
|
+
pip install -e .
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
For a regular (non-editable) install from a checkout:
|
|
72
|
+
|
|
73
|
+
```bash
|
|
74
|
+
pip install /path/to/rda-python-icoads
|
|
75
|
+
```
|
|
76
|
+
|
|
77
|
+
For a production install on a system that uses the published distribution:
|
|
78
|
+
|
|
79
|
+
```bash
|
|
80
|
+
pip install rda_python_icoads
|
|
81
|
+
```
|
|
@@ -6,7 +6,7 @@ build-backend = "setuptools.build_meta"
|
|
|
6
6
|
|
|
7
7
|
[project]
|
|
8
8
|
name = "rda_python_icoads"
|
|
9
|
-
version = "
|
|
9
|
+
version = "3.0.1"
|
|
10
10
|
authors = [
|
|
11
11
|
{ name="Zaihua Ji", email="zji@ucar.edu" },
|
|
12
12
|
]
|
|
@@ -20,7 +20,9 @@ classifiers = [
|
|
|
20
20
|
"Development Status :: 5 - Production/Stable",
|
|
21
21
|
]
|
|
22
22
|
dependencies = [
|
|
23
|
-
"
|
|
23
|
+
"numpy",
|
|
24
|
+
"rda_python_common>=3.0.14",
|
|
25
|
+
"rda_python_dsrqst>=2.0.4",
|
|
24
26
|
]
|
|
25
27
|
|
|
26
28
|
[tool.setuptools]
|
|
@@ -55,7 +57,7 @@ where = ["src"]
|
|
|
55
57
|
"fillinventory" = "rda_python_icoads.fillinventory:main"
|
|
56
58
|
"fillitable" = "rda_python_icoads.fillitable:main"
|
|
57
59
|
"fillmonth" = "rda_python_icoads.fillmonth:main"
|
|
58
|
-
"
|
|
60
|
+
"fixiidx" = "rda_python_icoads.fixiidx:main"
|
|
59
61
|
"msg_download" = "rda_python_icoads.msg_download:main"
|
|
60
62
|
"maxsst" = "rda_python_icoads.maxsst:main"
|
|
61
63
|
"writeicoads" = "rda_python_icoads.writeicoads:main"
|
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
#
|
|
3
|
+
##################################################################################
|
|
4
|
+
#
|
|
5
|
+
# Title : checkicoads
|
|
6
|
+
# Author : Zaihua Ji, zji@ucar.edu
|
|
7
|
+
# Date : 12/30/2020
|
|
8
|
+
# 2025-03-03 transferred to package rda_python_icoads from
|
|
9
|
+
# https://github.com/NCAR/rda-icoads.git
|
|
10
|
+
# 2026-09-04 convert to class CheckIcoads
|
|
11
|
+
# Purpose : check and compare ICOADS data files and IVADDB records
|
|
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 .pg_imma import PgIMMA
|
|
22
|
+
|
|
23
|
+
class CheckIcoads(PgIMMA):
|
|
24
|
+
|
|
25
|
+
def __init__(self):
|
|
26
|
+
super().__init__()
|
|
27
|
+
self.PVALS = {
|
|
28
|
+
'bdate' : None,
|
|
29
|
+
'edate' : None,
|
|
30
|
+
'bmdate' : [],
|
|
31
|
+
'emdate' : [],
|
|
32
|
+
'fname' : [],
|
|
33
|
+
'flag' : [], # 1 - file exists, 2 - db records exist, 3 - both
|
|
34
|
+
'mproc' : 10,
|
|
35
|
+
'fpattern' : "IMMA1_R3.0.0_<YYYY-MM>",
|
|
36
|
+
'readall' : 0
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
#
|
|
40
|
+
# main function to run dsarch
|
|
41
|
+
#
|
|
42
|
+
def main(self):
|
|
43
|
+
|
|
44
|
+
option = ''
|
|
45
|
+
argv = sys.argv[1:]
|
|
46
|
+
|
|
47
|
+
for arg in argv:
|
|
48
|
+
if arg == "-b":
|
|
49
|
+
self.PGLOG['BCKGRND'] = 1
|
|
50
|
+
elif arg == "-a":
|
|
51
|
+
self.PVALS['readall'] = 1
|
|
52
|
+
elif arg == "-f":
|
|
53
|
+
option = 'f'
|
|
54
|
+
elif arg == "-m":
|
|
55
|
+
option = 'm'
|
|
56
|
+
elif re.match(r'^-', arg):
|
|
57
|
+
self.pglog(arg + ": Invalid Option", self.LGWNEX)
|
|
58
|
+
elif option:
|
|
59
|
+
if option == 'f':
|
|
60
|
+
self.PVALS['fpattern'] = arg
|
|
61
|
+
elif option == 'm':
|
|
62
|
+
self.PVALS['mproc'] = arg
|
|
63
|
+
option = ''
|
|
64
|
+
elif not self.PVALS['bdate']:
|
|
65
|
+
self.PVALS['bdate'] = arg
|
|
66
|
+
elif not self.PVALS['edate']:
|
|
67
|
+
self.PVALS['edate'] = arg
|
|
68
|
+
else:
|
|
69
|
+
self.pglog(arg + ": Invalid parameter", self.LGWNEX)
|
|
70
|
+
|
|
71
|
+
self.PGLOG['LOGFILE'] = "icoads.log"
|
|
72
|
+
self.ivaddb_dbname()
|
|
73
|
+
|
|
74
|
+
if not (self.PVALS['bdate'] and self.PVALS['edate']):
|
|
75
|
+
pgrec = self.pgget("cntldb.inventory", "min(date) bdate, max(date) edate", '', self.LGEREX)
|
|
76
|
+
print("Usage: checkicoads [-a] [-m mproc] [-f FilePattern] BeginDate EndDate")
|
|
77
|
+
print(" Default FilePattern is " + self.PVALS['fpattern'])
|
|
78
|
+
print(" Option -a - read all attms, including multi-line ones, such as IVAD and REANQC")
|
|
79
|
+
print(" Option -m - start up to given number of processes, one for each month (Default to 10)")
|
|
80
|
+
print(" Set BeginDate and EndDate between '{}' and '{}'".format(pgrec['bdate'], pgrec['edate']))
|
|
81
|
+
sys.exit(0)
|
|
82
|
+
|
|
83
|
+
if self.diffdate(self.PVALS['bdate'], self.PVALS['edate']) > 0:
|
|
84
|
+
tmpdate = self.PVALS['bdate']
|
|
85
|
+
self.PVALS['bdate'] = self.PVALS['edate']
|
|
86
|
+
self.PVALS['edate'] = tmpdate
|
|
87
|
+
|
|
88
|
+
self.cmdlog("checkicoads {}".format(' '.join(argv)))
|
|
89
|
+
self.check_imma_data()
|
|
90
|
+
self.cmdlog()
|
|
91
|
+
sys.exit(0)
|
|
92
|
+
|
|
93
|
+
#
|
|
94
|
+
# check imma data
|
|
95
|
+
#
|
|
96
|
+
def check_imma_data(self):
|
|
97
|
+
|
|
98
|
+
mcnt = self.init_months()
|
|
99
|
+
if mcnt == 1: self.PVALS['mproc'] = 1
|
|
100
|
+
if self.PVALS['mproc'] > 1:
|
|
101
|
+
self.start_none_daemon('writeicoads', '', self.PGLOG['CURUID'], self.PVALS['mproc'], 300, 1)
|
|
102
|
+
|
|
103
|
+
for midx in range(mcnt):
|
|
104
|
+
fname = self.PVALS['fname'][midx]
|
|
105
|
+
if op.isfile(fname +".cnt"): continue # monthly file counted already
|
|
106
|
+
if self.PVALS['mproc'] > 1:
|
|
107
|
+
stat = self.start_child("checkicoads_{}".format(midx), self.LOGWRN, 1) # try to start a child process
|
|
108
|
+
if stat <= 0:
|
|
109
|
+
sys.exit(1) # something wrong
|
|
110
|
+
elif self.PGSIG['PPID'] > 1:
|
|
111
|
+
self.check_imma_file(fname, midx)
|
|
112
|
+
sys.exit(0) # stop child process
|
|
113
|
+
else:
|
|
114
|
+
self.pgdisconnect(0) # disconnect database for reconnection
|
|
115
|
+
continue # continue for next midx
|
|
116
|
+
else:
|
|
117
|
+
self.check_imma_file(fname, midx)
|
|
118
|
+
|
|
119
|
+
if self.PVALS['mproc'] > 1: self.check_child(None, 0, self.LOGWRN, 1)
|
|
120
|
+
|
|
121
|
+
self.dump_final_counts()
|
|
122
|
+
|
|
123
|
+
#
|
|
124
|
+
# compare icoads records from given file name and IVADDB
|
|
125
|
+
#
|
|
126
|
+
def check_imma_file(self, fname, midx):
|
|
127
|
+
|
|
128
|
+
self.pglog("Count IMMA records in File '{}'".format(fname), self.WARNLG)
|
|
129
|
+
flag = self.PVALS['flag'][midx]
|
|
130
|
+
|
|
131
|
+
acnts = [0]*self.TABLECOUNT
|
|
132
|
+
acounts = [0]*self.TABLECOUNT
|
|
133
|
+
|
|
134
|
+
if flag&1:
|
|
135
|
+
IMMA = open(fname, 'r')
|
|
136
|
+
line = IMMA.readline()
|
|
137
|
+
while line:
|
|
138
|
+
if self.PVALS['readall'] and re.match(r'^98', line):
|
|
139
|
+
self.get_imma_multiple_counts(line, acnts)
|
|
140
|
+
else:
|
|
141
|
+
self.get_imma_counts(line, acnts)
|
|
142
|
+
line.IMMA.readline()
|
|
143
|
+
IMMA.close()
|
|
144
|
+
for i in range(self.TABLECOUNT): acounts[i] = acnts[i]
|
|
145
|
+
|
|
146
|
+
if flag&2:
|
|
147
|
+
self.pglog("Count IMMA records in in IVADDB", self.WARNLG)
|
|
148
|
+
cdate = bdate = self.PVALS['bmdate'][midx]
|
|
149
|
+
edate = self.PVALS['emdate'][midx]
|
|
150
|
+
while cdate <= edate:
|
|
151
|
+
acnts = self.count_imma_records(cdate, 0, self.PVALS['readall'])
|
|
152
|
+
cdate = self.adddate(cdate, 0, 0, 1)
|
|
153
|
+
if acnts:
|
|
154
|
+
for i in range(self.TABLECOUNT): acounts[i] -= acnts[i]
|
|
155
|
+
|
|
156
|
+
self.dump_monthly_counts(fname, acounts)
|
|
157
|
+
|
|
158
|
+
#
|
|
159
|
+
# dump monthly counts
|
|
160
|
+
#
|
|
161
|
+
def dump_monthly_counts(self, fname, acounts):
|
|
162
|
+
|
|
163
|
+
oname = fname + ".cnt"
|
|
164
|
+
IMMA = open(oname, 'w')
|
|
165
|
+
IMMA.write("{}, {}\n".format(fname, ', '.join(acounts)))
|
|
166
|
+
IMMA.close()
|
|
167
|
+
|
|
168
|
+
#
|
|
169
|
+
# concat all monthly counts into one
|
|
170
|
+
#
|
|
171
|
+
def dump_final_counts(self):
|
|
172
|
+
|
|
173
|
+
fname = "ICOADS_DIFF_COUNTS.csv"
|
|
174
|
+
|
|
175
|
+
IMMA = open(fname, 'w')
|
|
176
|
+
IMMA.write("FileName, {}\n".format(', '.join(self.IMMA_NAMES)))
|
|
177
|
+
IMMA.close()
|
|
178
|
+
self.pgsystem("cat *.cnt >> " + fname)
|
|
179
|
+
|
|
180
|
+
#
|
|
181
|
+
# initialize the month list
|
|
182
|
+
#
|
|
183
|
+
def init_months(self):
|
|
184
|
+
|
|
185
|
+
seps = ["<" , ">"]; # temporal pattern delimiters
|
|
186
|
+
match = "[^" + seps[1] + "]+"
|
|
187
|
+
|
|
188
|
+
ms = re.search(r'{}({}){}'.format(seps[0], match, seps[1]), self.PVALS['fpattern'])
|
|
189
|
+
if ms:
|
|
190
|
+
tpattern = ms.group(1)
|
|
191
|
+
treplace = "{}{}{}".format(seps[0], tpattern, seps[1])
|
|
192
|
+
else:
|
|
193
|
+
self.pglog(self.PVALS['fpattern'] + ": Not temporal pattern found to get month list", self.LGEREX)
|
|
194
|
+
|
|
195
|
+
bdate = self.PVALS['bdate']
|
|
196
|
+
done = midx = 0
|
|
197
|
+
while True:
|
|
198
|
+
edate = self.enddate(bdate, 0, 'M')
|
|
199
|
+
if self.diffdate(self.PVALS['edate'], edate) <= 0:
|
|
200
|
+
edate = self.PVALS['edate']
|
|
201
|
+
done = 1
|
|
202
|
+
mdate = self.format_date(bdate, tpattern)
|
|
203
|
+
fname = self.PVALS['fpattern'].replace(treplace, mdate)
|
|
204
|
+
flag = 0
|
|
205
|
+
if op.isfile(fname): flag += 1
|
|
206
|
+
if self.pgget("cntldb.inventory", "", "date BETWEEN '{}' AND '{}'".format(bdate, edate), self.LGEREX):
|
|
207
|
+
flag += 2
|
|
208
|
+
if flag:
|
|
209
|
+
self.PVALS['bmdate'].append(bdate)
|
|
210
|
+
self.PVALS['emdate'].append(edate)
|
|
211
|
+
self.PVALS['fname'].append(fname)
|
|
212
|
+
self.PVALS['flag'].append(flag)
|
|
213
|
+
midx += 1
|
|
214
|
+
if done: break
|
|
215
|
+
bdate = self.adddate(edate, 0, 0, 1)
|
|
216
|
+
|
|
217
|
+
return midx
|
|
218
|
+
|
|
219
|
+
# main function to execute this script
|
|
220
|
+
def main():
|
|
221
|
+
CheckIcoads().main()
|
|
222
|
+
|
|
223
|
+
# call main() to start program
|
|
224
|
+
if __name__ == "__main__": main()
|
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
#
|
|
3
|
+
##################################################################################
|
|
4
|
+
#
|
|
5
|
+
# Title : cleanicoads
|
|
6
|
+
# Author : Zaihua Ji, zji@ucar.edu
|
|
7
|
+
# Date : 12/30/2020
|
|
8
|
+
# 2025-03-03 transferred to package rda_python_icoads from
|
|
9
|
+
# https://github.com/NCAR/rda-icoads.git
|
|
10
|
+
# 2026-09-04 convert to class CleanIcoads
|
|
11
|
+
# Purpose : clean up one or all IMMA1 attms in IVADDB for given period
|
|
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 .pg_imma import PgIMMA
|
|
22
|
+
|
|
23
|
+
class CleanIcoads(PgIMMA):
|
|
24
|
+
|
|
25
|
+
def __init__(self):
|
|
26
|
+
super().__init__()
|
|
27
|
+
self.PVALS = {
|
|
28
|
+
'bdate' : None,
|
|
29
|
+
'edate' : None,
|
|
30
|
+
'aname' : None,
|
|
31
|
+
'tinfo' : {},
|
|
32
|
+
'tcnt' : 0,
|
|
33
|
+
'dcnd' : None,
|
|
34
|
+
'uatti' : '',
|
|
35
|
+
'names' : None
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
#
|
|
39
|
+
# main function to run dsarch
|
|
40
|
+
#
|
|
41
|
+
def main(self):
|
|
42
|
+
|
|
43
|
+
option = ''
|
|
44
|
+
files = []
|
|
45
|
+
leaduid = 0
|
|
46
|
+
chkexist = 0
|
|
47
|
+
readall = 0
|
|
48
|
+
argv = sys.argv[1:]
|
|
49
|
+
|
|
50
|
+
for arg in argv:
|
|
51
|
+
if arg == "-b":
|
|
52
|
+
self.PGLOG['BCKGRND'] = 1
|
|
53
|
+
elif arg == "-a":
|
|
54
|
+
option = 'a'
|
|
55
|
+
elif re.match(r'^-', arg):
|
|
56
|
+
self.pglog(arg + ": Invalid Option", self.LGWNEX)
|
|
57
|
+
elif option:
|
|
58
|
+
self.PVALS['aname'] = arg
|
|
59
|
+
option = ''
|
|
60
|
+
elif not self.PVALS['bdate']:
|
|
61
|
+
self.PVALS['bdate'] = arg
|
|
62
|
+
elif not self.PVALS['edate']:
|
|
63
|
+
self.PVALS['edate'] = arg
|
|
64
|
+
else:
|
|
65
|
+
self.pglog(arg + ": Invalid parameter", self.LGWNEX)
|
|
66
|
+
|
|
67
|
+
if not self.PVALS['bdate']:
|
|
68
|
+
print("Usage: cleanicoads [-a ATTNAME] BDATE EDATE")
|
|
69
|
+
print(" Option -a - clean a single attm for given attm name")
|
|
70
|
+
self.pgexit()
|
|
71
|
+
|
|
72
|
+
self.PGLOG['LOGFILE'] = "icoads.log"
|
|
73
|
+
self.set_scname(dbname = 'ivaddb', scname = self.IVADSC, lnname = 'ivaddb', dbhost = self.PGLOG['PMISCHOST'])
|
|
74
|
+
self.cmdlog("cleanicoads {}".format(' '.join(argv)))
|
|
75
|
+
self.set_table_info()
|
|
76
|
+
self.clean_imma_data()
|
|
77
|
+
self.cmdlog()
|
|
78
|
+
self.pgexit()
|
|
79
|
+
|
|
80
|
+
#
|
|
81
|
+
# set the table index list
|
|
82
|
+
#
|
|
83
|
+
def set_table_info(self):
|
|
84
|
+
|
|
85
|
+
table = f"{self.CNTLSC}.inventory"
|
|
86
|
+
if self.PVALS['edate']:
|
|
87
|
+
self.PVALS['dcnd'] = "date BETWEEN '{}' AND '{}'".format(self.PVALS['bdate'], self.PVALS['edate'])
|
|
88
|
+
else:
|
|
89
|
+
self.PVALS['dcnd'] = "date >= '{}'".format(self.PVALS['bdate'])
|
|
90
|
+
|
|
91
|
+
self.PVALS['tinfo'] = self.pgmget(table, "tidx, min(miniidx) bidx, max(maxiidx) eidx", self.PVALS['dcnd'] + " GROUP BY tidx", self.LGEREX)
|
|
92
|
+
self.PVALS['tcnt'] = len(self.PVALS['tinfo']['tidx']) if self.PVALS['tinfo'] else 0
|
|
93
|
+
|
|
94
|
+
if not self.PVALS['tcnt']:
|
|
95
|
+
self.pglog("{}: No data found in IVADDB for {}".format(table, self.PVALS['dcnd']), self.LGEREX)
|
|
96
|
+
|
|
97
|
+
#
|
|
98
|
+
# clean up imma data
|
|
99
|
+
#
|
|
100
|
+
def clean_imma_data(self):
|
|
101
|
+
|
|
102
|
+
table = f"{self.CNTLSC}.inventory"
|
|
103
|
+
|
|
104
|
+
for i in range(self.PVALS['tcnt']):
|
|
105
|
+
tidx = self.PVALS['tinfo']['tidx'][i]
|
|
106
|
+
cnd = "iidx BETWEEN {} AND {}".format(self.PVALS['tinfo']['bidx'][i], self.PVALS['tinfo']['eidx'][i])
|
|
107
|
+
if self.PVALS['aname']:
|
|
108
|
+
self.clean_one_attm_for_tidx(self.PVALS['aname'], tidx, cnd)
|
|
109
|
+
else:
|
|
110
|
+
self.clean_imma_data_for_tidx(tidx, cnd)
|
|
111
|
+
|
|
112
|
+
if not self.PVALS['aname']:
|
|
113
|
+
cnt = self.pgdel(table, self.PVALS['dcnd'], self.LGEREX)
|
|
114
|
+
s = 's' if cnt > 1 else ''
|
|
115
|
+
self.pglog("{}: {} record{} deleted for {}".format(table, cnt, s, self.PVALS['dcnd']), self.LOGWRN)
|
|
116
|
+
|
|
117
|
+
#
|
|
118
|
+
# clean up imma data for table index
|
|
119
|
+
#
|
|
120
|
+
def clean_imma_data_for_tidx(self, tidx, cnd):
|
|
121
|
+
|
|
122
|
+
self.pglog("Clean IMMA data for table index {}...".format(tidx), self.LOGWRN)
|
|
123
|
+
|
|
124
|
+
for i in range(self.TABLECOUNT):
|
|
125
|
+
aname = self.IMMA_NAMES[i]
|
|
126
|
+
self.clean_one_attm_for_tidx(aname, tidx, cnd)
|
|
127
|
+
|
|
128
|
+
#
|
|
129
|
+
# clean up one attm data for table index
|
|
130
|
+
#
|
|
131
|
+
def clean_one_attm_for_tidx(self, aname, tidx, cnd):
|
|
132
|
+
|
|
133
|
+
table = f"{self.IVADSC}.{aname}_{tidx}"
|
|
134
|
+
if not self.pgcheck(table): return 0 # not record to delete
|
|
135
|
+
|
|
136
|
+
if aname == 'iuida': self.clean_itidx_for_tidx(table, cnd)
|
|
137
|
+
|
|
138
|
+
cnt = self.pgdel(table, cnd, self.LGEREX)
|
|
139
|
+
s = 's' if cnt > 1 else ''
|
|
140
|
+
self.pglog("{}: {} record{} deleted for {}".format(table, cnt, s, cnd), self.LOGWRN)
|
|
141
|
+
|
|
142
|
+
cnt = self.pgget(table, "", "", self.LGEREX)
|
|
143
|
+
self.clean_iattm_for_tidx(aname, tidx, cnt)
|
|
144
|
+
|
|
145
|
+
#
|
|
146
|
+
# clean up table itidx for table index
|
|
147
|
+
#
|
|
148
|
+
def clean_itidx_for_tidx(self, table, cnd):
|
|
149
|
+
|
|
150
|
+
tname = f"{self.CNTLSC}.itidx"
|
|
151
|
+
uids = self.pgmget(table, "distinct (substring(uid, 1, 2)) uida", cnd, self.LGEREX)
|
|
152
|
+
ucnt = len(uids['uida']) if uids else 0
|
|
153
|
+
for i in range(ucnt):
|
|
154
|
+
table = "{}_{}".format(tname, uids['uida'][i].lower())
|
|
155
|
+
if not self.pgcheck(table): continue
|
|
156
|
+
cnt = self.pgdel(table, cnd, self.LOGWRN)
|
|
157
|
+
s = 's' if cnt > 1 else ''
|
|
158
|
+
self.pglog("{}: {} record{} deleted".format(table, cnt, s), self.LOGWRN)
|
|
159
|
+
|
|
160
|
+
#
|
|
161
|
+
# clean up table iattm for table index
|
|
162
|
+
#
|
|
163
|
+
def clean_iattm_for_tidx(self, aname, tidx, cnt):
|
|
164
|
+
|
|
165
|
+
table = f"{self.CNTLSC}.iattm"
|
|
166
|
+
cnd = "attm = '{}' AND tidx = {}".format(aname, tidx)
|
|
167
|
+
pgrec = {'count' : cnt}
|
|
168
|
+
self.pgupdt(table, pgrec, cnd, self.LGWNEX)
|
|
169
|
+
self.pglog("{}: Set count to {} for {}".format(table, cnt, cnd), self.LOGWRN)
|
|
170
|
+
|
|
171
|
+
table += "_daily"
|
|
172
|
+
cnd += " AND " + self.PVALS['dcnd']
|
|
173
|
+
self.pgdel(table, self.PVALS['dcnd'], self.LGWNEX)
|
|
174
|
+
|
|
175
|
+
# main function to execute this script
|
|
176
|
+
def main():
|
|
177
|
+
CleanIcoads().main()
|
|
178
|
+
|
|
179
|
+
# call main() to start program
|
|
180
|
+
if __name__ == "__main__": main()
|