rc-qlc 0.3.24__cp310-cp310-win_amd64.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.
- qlc/__init__.py +8 -0
- qlc/cli/__init__.py +21 -0
- qlc/cli/installer.py +16 -0
- qlc/cli/qlc_main.py +185 -0
- qlc/cli/qlc_py_main.py +74 -0
- qlc/config/json/qlc_config.json +41 -0
- qlc/config/json/qlc_config_example_1a_all-obs.json +237 -0
- qlc/config/json/qlc_config_example_1b_all-mod.json +353 -0
- qlc/config/json/qlc_config_example_1c_all-coll.json +266 -0
- qlc/config/json/qlc_config_example_2a_all-obs.json +237 -0
- qlc/config/json/qlc_config_example_2b_all-mod.json +353 -0
- qlc/config/json/qlc_config_example_2c_all-coll.json +265 -0
- qlc/config/json/qlc_config_example_3a-us_obs.json +82 -0
- qlc/config/json/qlc_config_example_3b-us_mod.json +122 -0
- qlc/config/json/qlc_config_example_3c-us_coll.json +46 -0
- qlc/config/json/qlc_config_example_4a_eu-obs.json +41 -0
- qlc/config/json/qlc_config_example_4b_eu-mod.json +122 -0
- qlc/config/json/qlc_config_example_4c_eu-coll.json +45 -0
- qlc/config/nml/mars_A1_sfc.nml +19 -0
- qlc/config/nml/mars_A2_sfc.nml +19 -0
- qlc/config/nml/mars_A3_sfc.nml +19 -0
- qlc/config/nml/mars_B1_pl.nml +19 -0
- qlc/config/nml/mars_B2_pl.nml +19 -0
- qlc/config/nml/mars_C1_pl.nml +19 -0
- qlc/config/nml/mars_C2_pl.nml +19 -0
- qlc/config/nml/mars_C3_ml.nml +19 -0
- qlc/config/nml/mars_D.nml +19 -0
- qlc/config/nml/mars_E.nml +19 -0
- qlc/config/nml/mars_F.nml +19 -0
- qlc/config/nml/mars_G.nml +19 -0
- qlc/config/qlc_cams.conf +26 -0
- qlc/config/qlc_test.conf +26 -0
- qlc/config/qlc_tex.conf +107 -0
- qlc/doc/CONTRIBUTING.md +105 -0
- qlc/doc/README.md +116 -0
- qlc/doc/USAGE.md +58 -0
- qlc/examples/cams_case_1/config/json/qlc_config.json +41 -0
- qlc/examples/cams_case_1/config/nml/mars_A3_sfc.nml +19 -0
- qlc/examples/cams_case_1/config/nml/mars_B1_pl.nml +19 -0
- qlc/examples/cams_case_1/config/nml/mars_C1_pl.nml +19 -0
- qlc/examples/cams_case_1/config/qlc_cams.conf +122 -0
- qlc/examples/cams_case_1/mod/b2ro/2018/b2ro_20181215-20181231_A3_sfc.grb +0 -0
- qlc/examples/cams_case_1/mod/iqi9/2018/iqi9_20181215-20181231_A3_sfc.grb +0 -0
- qlc/examples/cams_case_1/obs/ebas_daily/v_20240216/201812/ebas_20181201.nc +0 -0
- qlc/examples/cams_case_1/obs/ebas_daily/v_20240216/201812/ebas_20181202.nc +0 -0
- qlc/examples/cams_case_1/obs/ebas_daily/v_20240216/201812/ebas_20181203.nc +0 -0
- qlc/examples/cams_case_1/obs/ebas_daily/v_20240216/201812/ebas_20181204.nc +0 -0
- qlc/examples/cams_case_1/obs/ebas_daily/v_20240216/201812/ebas_20181205.nc +0 -0
- qlc/examples/cams_case_1/obs/ebas_daily/v_20240216/201812/ebas_20181206.nc +0 -0
- qlc/examples/cams_case_1/obs/ebas_daily/v_20240216/201812/ebas_20181207.nc +0 -0
- qlc/examples/cams_case_1/obs/ebas_daily/v_20240216/201812/ebas_20181208.nc +0 -0
- qlc/examples/cams_case_1/obs/ebas_daily/v_20240216/201812/ebas_20181209.nc +0 -0
- qlc/examples/cams_case_1/obs/ebas_daily/v_20240216/201812/ebas_20181210.nc +0 -0
- qlc/examples/cams_case_1/obs/ebas_daily/v_20240216/201812/ebas_20181211.nc +0 -0
- qlc/examples/cams_case_1/obs/ebas_daily/v_20240216/201812/ebas_20181212.nc +0 -0
- qlc/examples/cams_case_1/obs/ebas_daily/v_20240216/201812/ebas_20181213.nc +0 -0
- qlc/examples/cams_case_1/obs/ebas_daily/v_20240216/201812/ebas_20181214.nc +0 -0
- qlc/examples/cams_case_1/obs/ebas_daily/v_20240216/201812/ebas_20181215.nc +0 -0
- qlc/examples/cams_case_1/obs/ebas_daily/v_20240216/201812/ebas_20181216.nc +0 -0
- qlc/examples/cams_case_1/obs/ebas_daily/v_20240216/201812/ebas_20181217.nc +0 -0
- qlc/examples/cams_case_1/obs/ebas_daily/v_20240216/201812/ebas_20181218.nc +0 -0
- qlc/examples/cams_case_1/obs/ebas_daily/v_20240216/201812/ebas_20181219.nc +0 -0
- qlc/examples/cams_case_1/obs/ebas_daily/v_20240216/201812/ebas_20181220.nc +0 -0
- qlc/examples/cams_case_1/obs/ebas_daily/v_20240216/201812/ebas_20181221.nc +0 -0
- qlc/examples/cams_case_1/obs/ebas_daily/v_20240216/201812/ebas_20181222.nc +0 -0
- qlc/examples/cams_case_1/obs/ebas_daily/v_20240216/201812/ebas_20181223.nc +0 -0
- qlc/examples/cams_case_1/obs/ebas_daily/v_20240216/201812/ebas_20181224.nc +0 -0
- qlc/examples/cams_case_1/obs/ebas_daily/v_20240216/201812/ebas_20181225.nc +0 -0
- qlc/examples/cams_case_1/obs/ebas_daily/v_20240216/201812/ebas_20181226.nc +0 -0
- qlc/examples/cams_case_1/obs/ebas_daily/v_20240216/201812/ebas_20181227.nc +0 -0
- qlc/examples/cams_case_1/obs/ebas_daily/v_20240216/201812/ebas_20181228.nc +0 -0
- qlc/examples/cams_case_1/obs/ebas_daily/v_20240216/201812/ebas_20181229.nc +0 -0
- qlc/examples/cams_case_1/obs/ebas_daily/v_20240216/201812/ebas_20181230.nc +0 -0
- qlc/examples/cams_case_1/obs/ebas_daily/v_20240216/201812/ebas_20181231.nc +0 -0
- qlc/examples/cams_case_1/obs/ebas_station-locations.csv +50 -0
- qlc/install.py +285 -0
- qlc/py/__main__.cp310-win_amd64.pyd +0 -0
- qlc/py/averaging.cp310-win_amd64.pyd +0 -0
- qlc/py/bias_plots.cp310-win_amd64.pyd +0 -0
- qlc/py/control.cp310-win_amd64.pyd +0 -0
- qlc/py/io.cp310-win_amd64.pyd +0 -0
- qlc/py/loadmod.cp310-win_amd64.pyd +0 -0
- qlc/py/loadobs.cp310-win_amd64.pyd +0 -0
- qlc/py/logging_utils.cp310-win_amd64.pyd +0 -0
- qlc/py/map_plots.cp310-win_amd64.pyd +0 -0
- qlc/py/matched.cp310-win_amd64.pyd +0 -0
- qlc/py/plot_config.cp310-win_amd64.pyd +0 -0
- qlc/py/plotting.cp310-win_amd64.pyd +0 -0
- qlc/py/plugin_loader.cp310-win_amd64.pyd +0 -0
- qlc/py/processing.cp310-win_amd64.pyd +0 -0
- qlc/py/scatter_plots.cp310-win_amd64.pyd +0 -0
- qlc/py/stations.cp310-win_amd64.pyd +0 -0
- qlc/py/statistics.cp310-win_amd64.pyd +0 -0
- qlc/py/style.cp310-win_amd64.pyd +0 -0
- qlc/py/timeseries_plots.cp310-win_amd64.pyd +0 -0
- qlc/py/utils.cp310-win_amd64.pyd +0 -0
- qlc/py/version.cp310-win_amd64.pyd +0 -0
- qlc/sh/qlc_A1.sh +127 -0
- qlc/sh/qlc_B1a.sh +123 -0
- qlc/sh/qlc_B2.sh +258 -0
- qlc/sh/qlc_C5.sh +825 -0
- qlc/sh/qlc_D1.sh +130 -0
- qlc/sh/qlc_Z1.sh +165 -0
- qlc/sh/qlc_common_functions.sh +157 -0
- qlc/sh/qlc_main.sh +127 -0
- qlc/sh/qlc_start.sh +23 -0
- qlc/sh/qlc_start_batch.sh +46 -0
- rc_qlc-0.3.24.dist-info/METADATA +142 -0
- rc_qlc-0.3.24.dist-info/RECORD +113 -0
- rc_qlc-0.3.24.dist-info/WHEEL +5 -0
- rc_qlc-0.3.24.dist-info/entry_points.txt +6 -0
- rc_qlc-0.3.24.dist-info/licenses/LICENSE +21 -0
- rc_qlc-0.3.24.dist-info/top_level.txt +1 -0
qlc/install.py
ADDED
@@ -0,0 +1,285 @@
|
|
1
|
+
import os
|
2
|
+
import sys
|
3
|
+
import shutil
|
4
|
+
import argparse
|
5
|
+
import json
|
6
|
+
from pathlib import Path
|
7
|
+
try:
|
8
|
+
import tomllib # Python 3.11+
|
9
|
+
except ModuleNotFoundError:
|
10
|
+
import tomli as tomllib # Python < 3.11
|
11
|
+
|
12
|
+
def get_version_from_pyproject(pyproject_path: Path) -> str:
|
13
|
+
with pyproject_path.open("rb") as f:
|
14
|
+
config = tomllib.load(f)
|
15
|
+
return config["project"]["version"]
|
16
|
+
|
17
|
+
def read_version_json(version_json_path: Path) -> dict:
|
18
|
+
if not version_json_path.exists():
|
19
|
+
raise FileNotFoundError(f"[ERROR] VERSION.json not found: {version_json_path}")
|
20
|
+
with version_json_path.open("r", encoding="utf-8") as f:
|
21
|
+
return json.load(f)
|
22
|
+
|
23
|
+
def get_bin_path():
|
24
|
+
return Path(sys.executable).resolve().parent
|
25
|
+
|
26
|
+
def copy_or_link(src, dst, symlink=False):
|
27
|
+
dst.parent.mkdir(parents=True, exist_ok=True)
|
28
|
+
if dst.exists() or dst.is_symlink():
|
29
|
+
dst.unlink()
|
30
|
+
if symlink:
|
31
|
+
dst.symlink_to(src.resolve())
|
32
|
+
else:
|
33
|
+
shutil.copy(src, dst)
|
34
|
+
|
35
|
+
def copytree_with_symlinks(src: Path, dst: Path):
|
36
|
+
if dst.exists():
|
37
|
+
shutil.rmtree(dst)
|
38
|
+
dst.mkdir(parents=True)
|
39
|
+
|
40
|
+
for item in src.iterdir():
|
41
|
+
s = src / item.name
|
42
|
+
d = dst / item.name
|
43
|
+
if s.is_symlink():
|
44
|
+
target = os.readlink(s)
|
45
|
+
print(f"[LINK] Preserving symlink {d} → {target}")
|
46
|
+
d.symlink_to(target)
|
47
|
+
elif s.is_dir():
|
48
|
+
copytree_with_symlinks(s, d)
|
49
|
+
else:
|
50
|
+
shutil.copy2(s, d)
|
51
|
+
|
52
|
+
def safe_move_and_link(source: Path, target: Path):
|
53
|
+
"""
|
54
|
+
Ensures `target` is a symlink to `source`.
|
55
|
+
If `target` exists but points elsewhere (or is a dir), it gets backed up first.
|
56
|
+
"""
|
57
|
+
if target.is_symlink():
|
58
|
+
current = target.resolve()
|
59
|
+
if current == source.resolve():
|
60
|
+
print(f"[SKIP] {target} already links to {source}")
|
61
|
+
return
|
62
|
+
else:
|
63
|
+
print(f"[BACKUP] {target} symlink points to {current}, backing up")
|
64
|
+
elif target.exists():
|
65
|
+
if target.is_dir():
|
66
|
+
# Only backup if it's not the install root (we don't want to mv source itself)
|
67
|
+
if target.resolve() != source.resolve():
|
68
|
+
backup = target.with_name(f"{target.name}_backup")
|
69
|
+
count = 1
|
70
|
+
while backup.exists():
|
71
|
+
backup = target.with_name(f"{target.name}_backup{count}")
|
72
|
+
count += 1
|
73
|
+
print(f"[BACKUP] Moving existing directory {target} → {backup}")
|
74
|
+
shutil.move(str(target), str(backup))
|
75
|
+
else:
|
76
|
+
# File or other type — always back up
|
77
|
+
backup = target.with_name(f"{target.name}_backup")
|
78
|
+
count = 1
|
79
|
+
while backup.exists():
|
80
|
+
backup = target.with_name(f"{target.name}_backup{count}")
|
81
|
+
count += 1
|
82
|
+
print(f"[BACKUP] Moving existing file {target} → {backup}")
|
83
|
+
shutil.move(str(target), str(backup))
|
84
|
+
|
85
|
+
print(f"[LINK] {target} → {source}")
|
86
|
+
target.symlink_to(source, target_is_directory=True)
|
87
|
+
|
88
|
+
def update_qlc_version(config_path: Path, version: str):
|
89
|
+
if not config_path.exists():
|
90
|
+
raise FileNotFoundError(f"[ERROR] Config file not found: {config_path}")
|
91
|
+
|
92
|
+
lines = config_path.read_text(encoding="utf-8").splitlines()
|
93
|
+
new_lines = []
|
94
|
+
updated = False
|
95
|
+
|
96
|
+
for line in lines:
|
97
|
+
if line.strip().startswith("QLC_VERSION="):
|
98
|
+
new_lines.append(f'QLC_VERSION="{version}"')
|
99
|
+
updated = True
|
100
|
+
else:
|
101
|
+
new_lines.append(line)
|
102
|
+
|
103
|
+
if not updated:
|
104
|
+
print(f"[WARN] QLC_VERSION=... not found in {config_path}")
|
105
|
+
else:
|
106
|
+
config_path.write_text("\n".join(new_lines) + "\n", encoding="utf-8")
|
107
|
+
print(f"[UPDATED] QLC_VERSION set to {version} in {config_path}")
|
108
|
+
|
109
|
+
def setup(mode, config_file=None, version="latest"):
|
110
|
+
|
111
|
+
# Define source root
|
112
|
+
qlc_root = Path(__file__).resolve().parent.parent
|
113
|
+
config_src = qlc_root / "qlc" / "config"
|
114
|
+
example_src = qlc_root / "qlc" / "examples"
|
115
|
+
sh_src = qlc_root / "qlc" / "sh"
|
116
|
+
doc_src = qlc_root / "qlc" / "doc"
|
117
|
+
|
118
|
+
from qlc.py.version import QLC_VERSION as version
|
119
|
+
|
120
|
+
# Select appropriate configuration file
|
121
|
+
if mode == "cams":
|
122
|
+
perm_path = Path(os.environ.get("PERM", "/perm")) / os.environ.get("USER", "user")
|
123
|
+
user_home = perm_path
|
124
|
+
selected_conf = config_src / "qlc_cams.conf"
|
125
|
+
elif mode == "test":
|
126
|
+
user_home = Path.home()
|
127
|
+
selected_conf = config_src / "qlc_test.conf"
|
128
|
+
elif mode == "interactive":
|
129
|
+
if not config_file:
|
130
|
+
raise ValueError("You must provide a config file via --interactive=<path>")
|
131
|
+
selected_conf = Path(config_file)
|
132
|
+
else:
|
133
|
+
raise ValueError(f"Unsupported mode: {mode}")
|
134
|
+
|
135
|
+
source = user_home / f"qlc_v{version}"
|
136
|
+
|
137
|
+
if source.exists() and not source.is_symlink():
|
138
|
+
backup = source.with_name(f"{source.name}_backup")
|
139
|
+
count = 1
|
140
|
+
while backup.exists():
|
141
|
+
backup = source.with_name(f"{source.name}_backup{count}")
|
142
|
+
count += 1
|
143
|
+
print(f"[BACKUP] Moving existing install root {source} → {backup}")
|
144
|
+
shutil.move(str(source), str(backup))
|
145
|
+
|
146
|
+
root = source / mode
|
147
|
+
# safe_move_and_link(source, Path.home() / f"qlc_v{version}")
|
148
|
+
|
149
|
+
print(f"[SETUP] Mode: {mode}, Version: {version}")
|
150
|
+
print(f"[PATHS] QLC Root: {root}")
|
151
|
+
|
152
|
+
# Prepare paths
|
153
|
+
config_dst = root / "config"
|
154
|
+
example_dst = root / "examples"
|
155
|
+
bin_dst = root / "bin"
|
156
|
+
log_dst = root / "log"
|
157
|
+
mod_dst = root / "mod"
|
158
|
+
obs_dst = root / "obs"
|
159
|
+
doc_dst = root / "doc"
|
160
|
+
run_dst = root / "run"
|
161
|
+
out_dst = root / "output"
|
162
|
+
plug_dst = root / "plugin"
|
163
|
+
|
164
|
+
# Create distribution directories
|
165
|
+
for path in [bin_dst, log_dst, mod_dst, obs_dst, doc_dst, run_dst, out_dst, plug_dst, example_dst, config_dst]:
|
166
|
+
path.mkdir(parents=True, exist_ok=True)
|
167
|
+
|
168
|
+
# Copy config files
|
169
|
+
if config_dst.exists():
|
170
|
+
copytree_with_symlinks(config_src, config_dst)
|
171
|
+
|
172
|
+
# Copy example files
|
173
|
+
if example_src.exists():
|
174
|
+
# shutil.copytree(example_src, example_dst, dirs_exist_ok=True, symlinks=True)
|
175
|
+
copytree_with_symlinks(example_src, example_dst)
|
176
|
+
|
177
|
+
# Link all documentation files
|
178
|
+
# shutil.copytree(doc_src, doc_dst, dirs_exist_ok=True)
|
179
|
+
for doc_file in doc_src.glob("*"):
|
180
|
+
dst = doc_dst / doc_file.name
|
181
|
+
copy_or_link(doc_file, dst, symlink=True)
|
182
|
+
|
183
|
+
# Link all *.sh files to bin_dst (helpers included)
|
184
|
+
for sh_file in sh_src.glob("*.sh"):
|
185
|
+
dst = bin_dst / sh_file.name
|
186
|
+
copy_or_link(sh_file, dst, symlink=True)
|
187
|
+
|
188
|
+
# Create shell tool links (now handled by entry_points in setup.py)
|
189
|
+
pass
|
190
|
+
|
191
|
+
# In test mode: link obs and mod to examples
|
192
|
+
if mode == "test":
|
193
|
+
# Link sample observation data as requested
|
194
|
+
# 1. $HOME/qlc/obs/data/ver0d/ebas_daily/v_20240216 -> $HOME/qlc/examples/cams_case_1/obs/ebas_daily/v_20240216
|
195
|
+
# 2. $HOME/qlc/obs/data/ver0d/ebas_daily/latest -> v_20240216 (relative)
|
196
|
+
|
197
|
+
obs_data_source = root / "examples/cams_case_1/obs/ebas_daily/v_20240216"
|
198
|
+
obs_data_dest_dir = root / "obs/data/ver0d/ebas_daily"
|
199
|
+
obs_data_dest_dir.mkdir(parents=True, exist_ok=True)
|
200
|
+
|
201
|
+
# Create the v_20240216 symlink
|
202
|
+
link1_target = obs_data_dest_dir / "v_20240216"
|
203
|
+
if link1_target.exists() or link1_target.is_symlink():
|
204
|
+
link1_target.unlink()
|
205
|
+
link1_target.symlink_to(obs_data_source.resolve(), target_is_directory=True)
|
206
|
+
print(f"[LINK] {link1_target} -> {obs_data_source}")
|
207
|
+
|
208
|
+
# Create the latest symlink, relative to its location
|
209
|
+
link2_target = obs_data_dest_dir / "latest"
|
210
|
+
if link2_target.exists() or link2_target.is_symlink():
|
211
|
+
link2_target.unlink()
|
212
|
+
link2_target.symlink_to("v_20240216", target_is_directory=True)
|
213
|
+
print(f"[LINK] {link2_target} -> v_20240216")
|
214
|
+
|
215
|
+
# Copy the station file for the test case
|
216
|
+
station_file_source = root / "examples/cams_case_1/obs/ebas_station-locations.csv"
|
217
|
+
station_file_dest = root / "obs/data/ebas_station-locations.csv"
|
218
|
+
if station_file_source.exists():
|
219
|
+
copy_or_link(station_file_source, station_file_dest, symlink=False)
|
220
|
+
print(f"[COPY] {station_file_dest}")
|
221
|
+
|
222
|
+
|
223
|
+
# Link sample model data (unchanged)
|
224
|
+
mod_data_src_root = root / "examples" / "cams_case_1" / "mod"
|
225
|
+
mod_data_dst_root = root / "mod"
|
226
|
+
if mod_data_src_root.is_dir():
|
227
|
+
for model_dir in mod_data_src_root.iterdir():
|
228
|
+
if model_dir.is_dir():
|
229
|
+
mod_data_dst = mod_data_dst_root / model_dir.name
|
230
|
+
if mod_data_dst.exists() or mod_data_dst.is_symlink():
|
231
|
+
mod_data_dst.unlink()
|
232
|
+
mod_data_dst.symlink_to(model_dir.resolve(), target_is_directory=True)
|
233
|
+
print(f"[LINK] {mod_data_dst} -> {model_dir}")
|
234
|
+
|
235
|
+
# Create a generic qlc.conf symlink
|
236
|
+
config_dir = root / "config"
|
237
|
+
generic_config_path = config_dir / "qlc.conf"
|
238
|
+
if generic_config_path.exists() or generic_config_path.is_symlink():
|
239
|
+
generic_config_path.unlink()
|
240
|
+
|
241
|
+
if selected_conf.exists():
|
242
|
+
generic_config_path.symlink_to(selected_conf.name)
|
243
|
+
print(f"[LINK] {generic_config_path} -> {selected_conf.name}")
|
244
|
+
|
245
|
+
# Write install info
|
246
|
+
info = {
|
247
|
+
"version": version,
|
248
|
+
"mode": mode,
|
249
|
+
"config": selected_conf.name
|
250
|
+
}
|
251
|
+
|
252
|
+
# Preemptively remove 'qlc_latest' symlink to ensure clean update, mimicking `ln -sf`.
|
253
|
+
qlc_latest_link = Path.home() / "qlc_latest"
|
254
|
+
if qlc_latest_link.is_symlink():
|
255
|
+
qlc_latest_link.unlink()
|
256
|
+
|
257
|
+
safe_move_and_link(root, qlc_latest_link)
|
258
|
+
safe_move_and_link(qlc_latest_link, Path.home() / "qlc")
|
259
|
+
|
260
|
+
(root / "VERSION.json").write_text(json.dumps(info, indent=2))
|
261
|
+
print(f"[WRITE] VERSION.json at {root}")
|
262
|
+
|
263
|
+
version_info = read_version_json(Path.home() / "qlc" / "VERSION.json")
|
264
|
+
update_qlc_version(generic_config_path, version_info["version"])
|
265
|
+
|
266
|
+
print("\n[INFO] QLC installation complete.")
|
267
|
+
print("[INFO] To get started, you may need to open a new terminal or run 'rehash'.")
|
268
|
+
print("[INFO] The following commands are now available: qlc, qlc-py, sqlc, qlc-install")
|
269
|
+
|
270
|
+
if __name__ == "__main__":
|
271
|
+
parser = argparse.ArgumentParser(description="Install QLC runtime structure")
|
272
|
+
parser.add_argument("--cams", action="store_true", help="Install in CAMS mode")
|
273
|
+
parser.add_argument("--test", action="store_true", help="Install in TEST mode")
|
274
|
+
parser.add_argument("--interactive", type=str, help="Install using custom config path")
|
275
|
+
parser.add_argument("--version", type=str, help="Override QLC version")
|
276
|
+
|
277
|
+
args = parser.parse_args()
|
278
|
+
if args.cams:
|
279
|
+
setup("cams", version=args.version)
|
280
|
+
elif args.test:
|
281
|
+
setup("test", version=args.version)
|
282
|
+
elif args.interactive:
|
283
|
+
setup("interactive", config_file=args.interactive, version=args.version)
|
284
|
+
else:
|
285
|
+
parser.print_help()
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
Binary file
|
qlc/sh/qlc_A1.sh
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
#!/bin/sh -e
|
2
|
+
|
3
|
+
# Source the configuration file to load the settings
|
4
|
+
. "$CONFIG_FILE"
|
5
|
+
# Include common functions
|
6
|
+
source $FUNCTIONS
|
7
|
+
|
8
|
+
SCRIPT="$0"
|
9
|
+
log "________________________________________________________________________________________"
|
10
|
+
log "Start ${SCRIPT} at `date`"
|
11
|
+
log "Retrieve grib data from MARS archive considering selected nml files (see $CONFIG_FILE) "
|
12
|
+
#log "----------------------------------------------------------------------------------------"
|
13
|
+
#log "Copyright (c) 2021-2025 ResearchConcepts io GmbH. All Rights Reserved. "
|
14
|
+
#log "Questions / comments to: Swen M. Metzger <sm@researchconcepts.io> "
|
15
|
+
log "----------------------------------------------------------------------------------------"
|
16
|
+
|
17
|
+
log "$0 MARS_RETRIEVALS = $CONFIG_DIR nml files: ${MARS_RETRIEVALS[*]}"
|
18
|
+
pwd -P
|
19
|
+
|
20
|
+
# Assign the command line input parameters to variables
|
21
|
+
exp1="$1"
|
22
|
+
exp2="$2"
|
23
|
+
sDat="$3"
|
24
|
+
eDat="$4"
|
25
|
+
|
26
|
+
myOS="`uname -s`"
|
27
|
+
|
28
|
+
exps="$exp1 $exp2"
|
29
|
+
for exp in $exps ; do
|
30
|
+
log "Processing experiment: $exp"
|
31
|
+
|
32
|
+
# Create experiment directory if not existent
|
33
|
+
if [ ! -d "$MARS_RETRIEVAL_DIRECTORY/$exp" ]; then
|
34
|
+
mkdir -p $MARS_RETRIEVAL_DIRECTORY/$exp
|
35
|
+
fi
|
36
|
+
|
37
|
+
EXPCLASS=`echo ${exp} | cut -c 1`
|
38
|
+
if [ "${EXPCLASS}" == "b" ]; then
|
39
|
+
XCLASS="nl"
|
40
|
+
elif [ "${EXPCLASS}" == "a" ]; then
|
41
|
+
XCLASS="be"
|
42
|
+
else
|
43
|
+
XCLASS="rd"
|
44
|
+
fi
|
45
|
+
log ${exp} ${XCLASS}
|
46
|
+
|
47
|
+
for name in "${MARS_RETRIEVALS[@]}"; do
|
48
|
+
nml_name="mars_${name}.nml"
|
49
|
+
log "Processing subscript: $nml_name"
|
50
|
+
|
51
|
+
if [ -f "$CONFIG_DIR/nml/$nml_name" ]; then
|
52
|
+
nml_template="$CONFIG_DIR/nml/$nml_name"
|
53
|
+
nml_file="$MARS_RETRIEVAL_DIRECTORY/$exp/$nml_name"
|
54
|
+
|
55
|
+
# Create a unique flag for this experiment and time period
|
56
|
+
data_retrieved_flag="$MARS_RETRIEVAL_DIRECTORY/$exp/data_retrieved_$sDat-$eDat.flag_${name}"
|
57
|
+
|
58
|
+
# Check for the control file in the mars retrieval directory
|
59
|
+
if [ -f "$data_retrieved_flag" ]; then
|
60
|
+
ls -lh "$data_retrieved_flag"
|
61
|
+
log "Data retrieval in progress or completed for experiment $exp and namelist case $name."
|
62
|
+
log "Proceeding without retrieval script qlc_${name}.sh for case $name"
|
63
|
+
else
|
64
|
+
log "Data has not been retrieved. Calling script:"
|
65
|
+
log "$0 for data retrieval for experiment $exp and namelist case $name"
|
66
|
+
# Replace placeholders in the namelist file
|
67
|
+
# EXP, SDATE, EDATE, MYPATH, MYFILE
|
68
|
+
sed -e "s/= EXP,/= $exp,/g" \
|
69
|
+
-e "s/= XCLASS/= $XCLASS/g" \
|
70
|
+
-e "s/= SDATE/= $sDat/g" \
|
71
|
+
-e "s|o/EDATE|o/$eDat|g" \
|
72
|
+
-e "s/MYFILE_/$exp\_${sDat//[-:]/}-${eDat//[-:]/}_/g" \
|
73
|
+
-e "s|MYPATH/|${MARS_RETRIEVAL_DIRECTORY}/$exp/|g" \
|
74
|
+
"$nml_template" > "$nml_file"
|
75
|
+
log "$nml_file"
|
76
|
+
cat "$nml_file" # Print the modified namelist
|
77
|
+
log MARS_RETRIEVAL_DIRECTORY $MARS_RETRIEVAL_DIRECTORY
|
78
|
+
|
79
|
+
# Extract the 'target' value and assign it to a variable
|
80
|
+
target=$(awk -F'=' '/target/ {gsub("\"", "", $2); print $2}' "$nml_file")
|
81
|
+
log "mars target file: $target"
|
82
|
+
|
83
|
+
# Create a batch job script
|
84
|
+
MARS_BATCH_SCRIPT="$MARS_RETRIEVAL_DIRECTORY/$exp/mars_$exp_$name.sh"
|
85
|
+
cat > "$MARS_BATCH_SCRIPT" <<EOF
|
86
|
+
#!/bin/ksh -e
|
87
|
+
#SBATCH --job-name=mars_$exp_$name.sh
|
88
|
+
#SBATCH --output=log-%J.out
|
89
|
+
#SBATCH --error=err-%J.out
|
90
|
+
mars < "$nml_file"
|
91
|
+
EOF
|
92
|
+
|
93
|
+
log "----------------------------------------------------------------------------------------"
|
94
|
+
cat "$MARS_BATCH_SCRIPT"
|
95
|
+
log "----------------------------------------------------------------------------------------"
|
96
|
+
log " $MARS_BATCH_SCRIPT"
|
97
|
+
|
98
|
+
# Check if pdflatex exists
|
99
|
+
if ! command_exists sbatch; then
|
100
|
+
log "Caution: sbatch command not found" >&2
|
101
|
+
log "Not submitting MARS request on $myOS ..."
|
102
|
+
# exit 1
|
103
|
+
else
|
104
|
+
log "Success: sbatch command found"
|
105
|
+
log "Submitting MARS request on $myOS:"
|
106
|
+
which sbatch mars squeue scancel
|
107
|
+
sbatch "$MARS_BATCH_SCRIPT"
|
108
|
+
squeue -u "$USER"
|
109
|
+
fi
|
110
|
+
|
111
|
+
# Create the control file in the retrieval directory
|
112
|
+
touch $data_retrieved_flag
|
113
|
+
log "----------------------------------------------------------------------------------------"
|
114
|
+
fi
|
115
|
+
else
|
116
|
+
log "Error: $nml_name not found in $CONFIG_DIR"
|
117
|
+
fi
|
118
|
+
done # name
|
119
|
+
log "$MARS_RETRIEVAL_DIRECTORY/$exp"
|
120
|
+
done # exps
|
121
|
+
|
122
|
+
log "----------------------------------------------------------------------------------------"
|
123
|
+
log "End ${SCRIPT} at `date`"
|
124
|
+
log "________________________________________________________________________________________"
|
125
|
+
|
126
|
+
exit 0
|
127
|
+
|
qlc/sh/qlc_B1a.sh
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
#!/bin/sh -e
|
2
|
+
|
3
|
+
# Source the configuration file to load the settings
|
4
|
+
. "$CONFIG_FILE"
|
5
|
+
# Include common functions
|
6
|
+
source $FUNCTIONS
|
7
|
+
|
8
|
+
SCRIPT="$0"
|
9
|
+
log "________________________________________________________________________________________"
|
10
|
+
log "Start ${SCRIPT} at `date`"
|
11
|
+
log "Process and convert retrieved grib data (MARS_RETRIEVALS as specified in $CONFIG_FILE) "
|
12
|
+
#log "----------------------------------------------------------------------------------------"
|
13
|
+
#log "Copyright (c) 2021-2025 ResearchConcepts io GmbH. All Rights Reserved. "
|
14
|
+
#log "Questions / comments to: Swen M. Metzger <sm@researchconcepts.io> "
|
15
|
+
log "----------------------------------------------------------------------------------------"
|
16
|
+
|
17
|
+
log "$0 MARS_RETRIEVAL_DIRECTORY = $MARS_RETRIEVAL_DIRECTORY"
|
18
|
+
pwd -P
|
19
|
+
|
20
|
+
# module load for ATOS
|
21
|
+
myOS="`uname -s`"
|
22
|
+
HOST=`hostname -s | awk '{printf $1}' | cut -c 1`
|
23
|
+
#log ${HOST} ${ARCH}
|
24
|
+
if [ "${HOST}" == "a" ] && [ "${myOS}" != "Darwin" ]; then
|
25
|
+
module load cdo
|
26
|
+
fi
|
27
|
+
|
28
|
+
# Check if cdo exists
|
29
|
+
if ! command_exists cdo; then
|
30
|
+
log "Error: cdo command not found" >&2
|
31
|
+
exit 1
|
32
|
+
else
|
33
|
+
log "Success: cdo command found"
|
34
|
+
which cdo
|
35
|
+
fi
|
36
|
+
|
37
|
+
# Check if ncdump exists
|
38
|
+
if ! command_exists ncdump; then
|
39
|
+
log "Error: ncdump command not found" >&2
|
40
|
+
exit 1
|
41
|
+
else
|
42
|
+
log "Success: ncdump command found"
|
43
|
+
which ncdump
|
44
|
+
fi
|
45
|
+
|
46
|
+
# Assign the command line input parameters to variables
|
47
|
+
exp1="$1"
|
48
|
+
exp2="$2"
|
49
|
+
sDat="$3"
|
50
|
+
eDat="$4"
|
51
|
+
sDate="${sDat//[-:]/}"
|
52
|
+
eDate="${eDat//[-:]/}"
|
53
|
+
mDate="$sDate-$eDate"
|
54
|
+
|
55
|
+
exps="$exp1 $exp2"
|
56
|
+
for exp in $exps ; do
|
57
|
+
log "Processing experiment: $exp"
|
58
|
+
|
59
|
+
# Create output directory if not existent
|
60
|
+
if [ ! -d "$ANALYSIS_DIRECTORY/$exp" ]; then
|
61
|
+
mkdir -p "$ANALYSIS_DIRECTORY/$exp"
|
62
|
+
fi
|
63
|
+
|
64
|
+
cd "$MARS_RETRIEVAL_DIRECTORY/$exp"
|
65
|
+
|
66
|
+
for name in "${MARS_RETRIEVALS[@]}"; do
|
67
|
+
|
68
|
+
set +e
|
69
|
+
# List available GRIB files for selected exp and time period
|
70
|
+
# grbfiles=($(ls *${mDate}*_${name}_*.grb))
|
71
|
+
grbfiles=($(ls *${mDate}*_${name}*.grb))
|
72
|
+
set -e
|
73
|
+
|
74
|
+
log "Processing grbfiles: $grbfiles"
|
75
|
+
|
76
|
+
if [ ${#grbfiles[@]} -eq 0 ]; then
|
77
|
+
log "No GRIB files found in $MARS_RETRIEVAL_DIRECTORY/$exp"
|
78
|
+
else
|
79
|
+
log "Files to convert: ${grbfiles[@]}"
|
80
|
+
log "----------------------------------------------------------------------------------------"
|
81
|
+
for file in "${grbfiles[@]}"; do
|
82
|
+
# convert grib files to netcdf
|
83
|
+
log "$file"
|
84
|
+
gribfile="$file"
|
85
|
+
ncfile="${gribfile%.grb}.nc"
|
86
|
+
if [ ! -f "$ncfile" ]; then
|
87
|
+
log "Converting $gribfile to $ncfile"
|
88
|
+
cdo -f nc copy "$gribfile" "$ncfile"
|
89
|
+
ls -lh "$ncfile"
|
90
|
+
ncdump -h "$ncfile"
|
91
|
+
else
|
92
|
+
log "Nothing to do! NC-file already exists: $ncfile"
|
93
|
+
ls -lh $ncfile
|
94
|
+
# ncdump -h $ncfile
|
95
|
+
fi
|
96
|
+
# conversion of tine averaged grib files to netcdf (seasmean)
|
97
|
+
ncfil2="${gribfile%.grb}_tavg.nc"
|
98
|
+
if [ ! -f "$ncfil2" ]; then
|
99
|
+
log "cdo timavg ${gribfile} ${gribfile%.grb}.grbtavg"
|
100
|
+
cdo timavg ${gribfile} ${gribfile%.grb}.grbtavg
|
101
|
+
log "cdo -f nc copy ${gribfile%.grb}.grbtavg $ncfil2"
|
102
|
+
cdo -f nc copy ${gribfile%.grb}.grbtavg $ncfil2
|
103
|
+
# rm -f "$gribfile" # Clean up GRIB file
|
104
|
+
ls -lh $ncfil2
|
105
|
+
ncdump -h $ncfil2
|
106
|
+
else
|
107
|
+
log "Nothing to do! NC-file already exists: $ncfil2"
|
108
|
+
ls -lh $ncfil2
|
109
|
+
# ncdump -h $ncfil2
|
110
|
+
fi
|
111
|
+
done # file
|
112
|
+
log "----------------------------------------------------------------------------------------"
|
113
|
+
fi
|
114
|
+
|
115
|
+
done # name
|
116
|
+
done # exps
|
117
|
+
|
118
|
+
log "----------------------------------------------------------------------------------------"
|
119
|
+
log "End ${SCRIPT} at `date`"
|
120
|
+
log "________________________________________________________________________________________"
|
121
|
+
|
122
|
+
exit 0
|
123
|
+
|