oafuncs 0.0.98.9__py3-none-any.whl → 0.0.98.11__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.
- oafuncs/_script/cprogressbar.py +1 -1
- oafuncs/_script/parallel.py +26 -13
- oafuncs/oa_data.py +26 -5
- oafuncs/oa_down/hycom_3hourly.py +10 -10
- oafuncs/oa_file.py +5 -1
- oafuncs/oa_nc.py +43 -1
- oafuncs/oa_tool.py +17 -2
- {oafuncs-0.0.98.9.dist-info → oafuncs-0.0.98.11.dist-info}/METADATA +1 -1
- {oafuncs-0.0.98.9.dist-info → oafuncs-0.0.98.11.dist-info}/RECORD +12 -12
- {oafuncs-0.0.98.9.dist-info → oafuncs-0.0.98.11.dist-info}/WHEEL +1 -1
- {oafuncs-0.0.98.9.dist-info → oafuncs-0.0.98.11.dist-info}/licenses/LICENSE.txt +0 -0
- {oafuncs-0.0.98.9.dist-info → oafuncs-0.0.98.11.dist-info}/top_level.txt +0 -0
oafuncs/_script/cprogressbar.py
CHANGED
@@ -148,7 +148,7 @@ class ColorProgressBar:
|
|
148
148
|
description: str = "Working ...",
|
149
149
|
total: Optional[float] = None,
|
150
150
|
completed: float = 0,
|
151
|
-
color: Any = "
|
151
|
+
color: Any = "green",
|
152
152
|
cmap: Union[str, List[str]] = None,
|
153
153
|
update_interval: float = 0.1,
|
154
154
|
bar_length: int = None,
|
oafuncs/_script/parallel.py
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
import atexit
|
2
1
|
import logging
|
3
2
|
import multiprocessing as mp
|
4
3
|
import platform
|
@@ -30,6 +29,7 @@ class ParallelExecutor:
|
|
30
29
|
self.running = True
|
31
30
|
self.task_history = []
|
32
31
|
self._executor = None
|
32
|
+
self._shutdown_called = False
|
33
33
|
|
34
34
|
self.mode, default_workers = self._determine_optimal_settings()
|
35
35
|
self.max_workers = max_workers or default_workers
|
@@ -37,7 +37,6 @@ class ParallelExecutor:
|
|
37
37
|
|
38
38
|
self._init_platform_settings()
|
39
39
|
self._start_resource_monitor()
|
40
|
-
atexit.register(self.shutdown)
|
41
40
|
|
42
41
|
logging.info(f"Initialized {self.__class__.__name__} on {self.platform} (mode={self.mode}, workers={self.max_workers})")
|
43
42
|
|
@@ -99,16 +98,26 @@ class ParallelExecutor:
|
|
99
98
|
|
100
99
|
def run(self, func: Callable, params: List[Tuple], chunk_size: Optional[int] = None) -> List[Any]:
|
101
100
|
chunk_size = chunk_size or self.chunk_size
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
101
|
+
try:
|
102
|
+
for retry in range(self.max_retries + 1):
|
103
|
+
try:
|
104
|
+
start_time = time.monotonic()
|
105
|
+
results = self._execute_batch(func, params, chunk_size)
|
106
|
+
self._update_settings(time.monotonic() - start_time, len(params))
|
107
|
+
return results
|
108
|
+
except Exception as e:
|
109
|
+
logging.error(f"Attempt {retry + 1} failed: {e}")
|
110
|
+
self._handle_failure()
|
111
|
+
raise RuntimeError(f"Failed after {self.max_retries} retries")
|
112
|
+
finally:
|
113
|
+
# 仅关闭当前 executor,保留资源监控等运行状态
|
114
|
+
if self._executor:
|
115
|
+
try:
|
116
|
+
self._executor.shutdown(wait=True)
|
117
|
+
except Exception as e:
|
118
|
+
logging.error(f"Executor shutdown error: {e}")
|
119
|
+
finally:
|
120
|
+
self._executor = None
|
112
121
|
|
113
122
|
def _execute_batch(self, func: Callable, params: List[Tuple], chunk_size: int) -> List[Any]:
|
114
123
|
if not params:
|
@@ -168,10 +177,14 @@ class ParallelExecutor:
|
|
168
177
|
self._restart_executor()
|
169
178
|
|
170
179
|
def shutdown(self):
|
180
|
+
if self._shutdown_called:
|
181
|
+
return
|
182
|
+
self._shutdown_called = True
|
171
183
|
self.running = False
|
184
|
+
# 基类不再打印日志,由子类统一处理
|
172
185
|
if self._executor:
|
173
186
|
try:
|
174
|
-
self._executor.shutdown(wait=
|
187
|
+
self._executor.shutdown(wait=True)
|
175
188
|
except Exception as e:
|
176
189
|
logging.error(f"Shutdown error: {e}")
|
177
190
|
finally:
|
oafuncs/oa_data.py
CHANGED
@@ -121,7 +121,26 @@ def _interp_single_worker(*args):
|
|
121
121
|
"""
|
122
122
|
data_slice, origin_points, target_points, interpolation_method, target_shape = args
|
123
123
|
|
124
|
-
|
124
|
+
# 过滤掉包含 NaN 的点
|
125
|
+
valid_mask = ~np.isnan(data_slice.ravel())
|
126
|
+
valid_data = data_slice.ravel()[valid_mask]
|
127
|
+
valid_points = origin_points[valid_mask]
|
128
|
+
|
129
|
+
if len(valid_data) < 10: # 如果有效数据太少,用均值填充
|
130
|
+
return np.full(target_shape, np.nanmean(data_slice))
|
131
|
+
|
132
|
+
# 使用有效数据进行插值
|
133
|
+
result = griddata(valid_points, valid_data, target_points, method=interpolation_method)
|
134
|
+
result = result.reshape(target_shape)
|
135
|
+
|
136
|
+
# 检查插值结果中是否仍有 NaN,如果有,用最近邻插值填充
|
137
|
+
if np.any(np.isnan(result)):
|
138
|
+
# 使用最近邻方法填充剩余的 NaN 值
|
139
|
+
nan_mask = np.isnan(result)
|
140
|
+
result_nn = griddata(valid_points, valid_data, target_points[nan_mask.ravel()], method="nearest")
|
141
|
+
result.ravel()[nan_mask.ravel()] = result_nn
|
142
|
+
|
143
|
+
return result
|
125
144
|
|
126
145
|
|
127
146
|
def interp_2d(
|
@@ -130,7 +149,7 @@ def interp_2d(
|
|
130
149
|
source_x_coordinates: Union[np.ndarray, List[float]],
|
131
150
|
source_y_coordinates: Union[np.ndarray, List[float]],
|
132
151
|
source_data: np.ndarray,
|
133
|
-
interpolation_method: str = "
|
152
|
+
interpolation_method: str = "cubic",
|
134
153
|
) -> np.ndarray:
|
135
154
|
"""
|
136
155
|
Perform 2D interpolation on the last two dimensions of a multi-dimensional array.
|
@@ -141,7 +160,8 @@ def interp_2d(
|
|
141
160
|
source_x_coordinates (Union[np.ndarray, List[float]]): Original grid's x-coordinates.
|
142
161
|
source_y_coordinates (Union[np.ndarray, List[float]]): Original grid's y-coordinates.
|
143
162
|
source_data (np.ndarray): Multi-dimensional array with the last two dimensions as spatial.
|
144
|
-
interpolation_method (str, optional): Interpolation method. Defaults to "
|
163
|
+
interpolation_method (str, optional): Interpolation method. Defaults to "cubic".
|
164
|
+
>>> optional: 'linear', 'nearest', 'cubic', 'quintic', etc.
|
145
165
|
use_parallel (bool, optional): Enable parallel processing. Defaults to True.
|
146
166
|
|
147
167
|
Returns:
|
@@ -190,11 +210,12 @@ def interp_2d(
|
|
190
210
|
for t_index in range(t):
|
191
211
|
for z_index in range(z):
|
192
212
|
paras.append((new_src_data[t_index, z_index], origin_points, target_points, interpolation_method, target_shape))
|
193
|
-
|
213
|
+
|
194
214
|
with PEx() as excutor:
|
195
215
|
result = excutor.run(_interp_single_worker, paras)
|
196
216
|
|
197
|
-
return np.squeeze(np.array(result))
|
217
|
+
return np.squeeze(np.array(result).reshape(t, z, *target_shape))
|
218
|
+
|
198
219
|
|
199
220
|
|
200
221
|
def mask_shapefile(
|
oafuncs/oa_down/hycom_3hourly.py
CHANGED
@@ -584,7 +584,7 @@ def _clear_existing_file(file_full_path):
|
|
584
584
|
|
585
585
|
def _check_existing_file(file_full_path, avg_size):
|
586
586
|
if os.path.exists(file_full_path):
|
587
|
-
print(f"[bold #FFA54F]{file_full_path} exists")
|
587
|
+
print(f"[bold #FFA54F]{file_full_path} exists ...")
|
588
588
|
fsize = file_size(file_full_path)
|
589
589
|
delta_size_ratio = (fsize - avg_size) / avg_size
|
590
590
|
if abs(delta_size_ratio) > 0.025:
|
@@ -796,7 +796,7 @@ def _download_file(target_url, store_path, file_name, cover=False):
|
|
796
796
|
get_mean_size = _get_mean_size_move(same_file, save_path)
|
797
797
|
|
798
798
|
if _check_existing_file(save_path, get_mean_size):
|
799
|
-
print(f"[bold #FFA54F]{save_path} exists, skipping ...")
|
799
|
+
# print(f"[bold #FFA54F]{save_path} exists, skipping ...")
|
800
800
|
count_dict["skip"] += 1
|
801
801
|
return
|
802
802
|
|
@@ -901,7 +901,7 @@ def _prepare_url_to_download(var, lon_min=0, lon_max=359.92, lat_min=-80, lat_ma
|
|
901
901
|
else:
|
902
902
|
if download_time < "2024081012":
|
903
903
|
varlist = [_ for _ in var]
|
904
|
-
for key, value in pbar(var_group.items(), description=f"Var Group {download_time}
|
904
|
+
for key, value in pbar(var_group.items(), description=f"Var Group {download_time}", total=len(var_group), next_line=True):
|
905
905
|
current_group = []
|
906
906
|
for v in varlist:
|
907
907
|
if v in value:
|
@@ -923,7 +923,7 @@ def _prepare_url_to_download(var, lon_min=0, lon_max=359.92, lat_min=-80, lat_ma
|
|
923
923
|
file_name = f"HYCOM_{key}_{download_time}-{download_time_end}.nc"
|
924
924
|
_download_file(submit_url, store_path, file_name, cover)
|
925
925
|
else:
|
926
|
-
for v in pbar(var, description=f"Var {download_time}
|
926
|
+
for v in pbar(var, description=f"Var {download_time}", total=len(var), next_line=True):
|
927
927
|
submit_url = _get_submit_url_var(v, depth, level_num, lon_min, lon_max, lat_min, lat_max, dataset_name, version_name, download_time, download_time_end)
|
928
928
|
file_name = f"HYCOM_{variable_info[v]['var_name']}_{download_time}.nc"
|
929
929
|
if download_time_end is not None:
|
@@ -968,7 +968,7 @@ def _download_hourly_func(var, time_s, time_e, lon_min=0, lon_max=359.92, lat_mi
|
|
968
968
|
# with Progress() as progress:
|
969
969
|
# task = progress.add_task(f"[cyan]{bar_desc}", total=len(time_list))
|
970
970
|
if num_workers is None or num_workers <= 1:
|
971
|
-
for i, time_str in pbar(enumerate(time_list), description=f"{bar_desc}", total=len(time_list),
|
971
|
+
for i, time_str in pbar(enumerate(time_list), description=f"{bar_desc}", total=len(time_list), next_line=True):
|
972
972
|
_prepare_url_to_download(var, lon_min, lon_max, lat_min, lat_max, time_str, None, depth, level, store_path, dataset_name, version_name, cover)
|
973
973
|
# progress.update(task, advance=1, description=f"[cyan]{bar_desc} {i + 1}/{len(time_list)}")
|
974
974
|
else:
|
@@ -976,7 +976,7 @@ def _download_hourly_func(var, time_s, time_e, lon_min=0, lon_max=359.92, lat_mi
|
|
976
976
|
futures = [executor.submit(_download_task, var, time_str, None, lon_min, lon_max, lat_min, lat_max, depth, level, store_path, dataset_name, version_name, cover) for time_str in time_list]
|
977
977
|
""" for feature in as_completed(futures):
|
978
978
|
_done_callback(feature, progress, task, len(time_list), counter_lock) """
|
979
|
-
for _ in pbar(as_completed(futures),description=f"{bar_desc}", total=len(futures),
|
979
|
+
for _ in pbar(as_completed(futures),description=f"{bar_desc}", total=len(futures),next_line=True):
|
980
980
|
pass
|
981
981
|
else:
|
982
982
|
print("[bold red]Please ensure the time_s is no more than time_e")
|
@@ -1121,10 +1121,10 @@ def download(
|
|
1121
1121
|
workers = 1
|
1122
1122
|
given_idm_engine = idm_path
|
1123
1123
|
idm_download_list = []
|
1124
|
-
bar_desc = "Submitting to IDM
|
1124
|
+
bar_desc = "Submitting to IDM"
|
1125
1125
|
else:
|
1126
1126
|
use_idm = False
|
1127
|
-
bar_desc = "Downloading
|
1127
|
+
bar_desc = "Downloading"
|
1128
1128
|
|
1129
1129
|
global match_time
|
1130
1130
|
match_time = validate_time
|
@@ -1136,7 +1136,7 @@ def download(
|
|
1136
1136
|
workers = 1
|
1137
1137
|
print("*" * mark_len)
|
1138
1138
|
print("[bold red]Only checking the time of existing files.")
|
1139
|
-
bar_desc = "Checking time
|
1139
|
+
bar_desc = "Checking time"
|
1140
1140
|
|
1141
1141
|
_download_hourly_func(
|
1142
1142
|
variables,
|
@@ -1162,7 +1162,7 @@ def download(
|
|
1162
1162
|
print("[bold #ecdbfe]*" * mark_len)
|
1163
1163
|
if idm_download_list:
|
1164
1164
|
remain_list = idm_download_list.copy()
|
1165
|
-
for _ in pbar(range(len(idm_download_list)),
|
1165
|
+
for _ in pbar(range(len(idm_download_list)), description="Downloading"):
|
1166
1166
|
success = False
|
1167
1167
|
while not success:
|
1168
1168
|
for f in remain_list:
|
oafuncs/oa_file.py
CHANGED
@@ -287,7 +287,11 @@ def remove(target_pattern: str) -> None:
|
|
287
287
|
(shutil.rmtree if os.path.isdir(file_path) else os.remove)(file_path)
|
288
288
|
print(f"[green]Successfully deleted:[/green] [bold]{file_path}[/bold]")
|
289
289
|
else:
|
290
|
-
|
290
|
+
if not os.path.exists(file_path):
|
291
|
+
# print(f"[yellow]File not found:[/yellow] [bold]{file_path}[/bold]")
|
292
|
+
pass
|
293
|
+
else:
|
294
|
+
print(f"[yellow]Skipping unknown file type:[/yellow] [bold]{file_path}[/bold]")
|
291
295
|
except Exception as e:
|
292
296
|
print(f"[red]Failed to delete:[/red] [bold]{file_path}[/bold]. Error: {e}")
|
293
297
|
|
oafuncs/oa_nc.py
CHANGED
@@ -6,7 +6,7 @@ import numpy as np
|
|
6
6
|
import xarray as xr
|
7
7
|
from rich import print
|
8
8
|
|
9
|
-
__all__ = ["save", "merge", "modify", "rename", "check", "convert_longitude", "isel", "draw"]
|
9
|
+
__all__ = ["save", "merge", "modify", "rename", "check", "convert_longitude", "isel", "draw", "compress_netcdf", "unpack_netcdf"]
|
10
10
|
|
11
11
|
|
12
12
|
def save(
|
@@ -278,6 +278,48 @@ def draw(
|
|
278
278
|
print("[red]No dataset or file provided.[/red]")
|
279
279
|
|
280
280
|
|
281
|
+
def compress_netcdf(src_path, dst_path=None):
|
282
|
+
"""
|
283
|
+
压缩 NetCDF 文件,使用 scale_factor/add_offset 压缩数据。
|
284
|
+
若 dst_path 省略,则自动生成新文件名,写出后删除原文件并将新文件改回原名。
|
285
|
+
"""
|
286
|
+
# 判断是否要替换原文件
|
287
|
+
delete_orig = dst_path is None
|
288
|
+
if delete_orig:
|
289
|
+
dst_path = src_path.replace(".nc", "_compress.nc")
|
290
|
+
|
291
|
+
ds = xr.open_dataset(src_path)
|
292
|
+
save(dst_path, ds)
|
293
|
+
ds.close()
|
294
|
+
|
295
|
+
if delete_orig:
|
296
|
+
os.remove(src_path)
|
297
|
+
os.rename(dst_path, src_path)
|
298
|
+
pass
|
299
|
+
|
300
|
+
|
301
|
+
def unpack_netcdf(src_path, dst_path=None):
|
302
|
+
"""解码 NetCDF 并移除 scale_factor/add_offset,写出真实值。
|
303
|
+
若 dst_path 省略,则自动生成新文件名,写出后删除原文件并将新文件改回原名。
|
304
|
+
"""
|
305
|
+
# 判断是否要替换原文件
|
306
|
+
delete_orig = dst_path is None
|
307
|
+
if delete_orig:
|
308
|
+
dst_path = src_path.replace(".nc", "_unpacked.nc")
|
309
|
+
|
310
|
+
ds = xr.open_dataset(src_path, decode_cf=True)
|
311
|
+
for var in ds.data_vars:
|
312
|
+
ds[var].attrs.pop("scale_factor", None)
|
313
|
+
ds[var].attrs.pop("add_offset", None)
|
314
|
+
ds[var].encoding.clear()
|
315
|
+
ds.to_netcdf(dst_path, mode="w", format="NETCDF4", engine="netcdf4")
|
316
|
+
ds.close()
|
317
|
+
|
318
|
+
if delete_orig:
|
319
|
+
os.remove(src_path)
|
320
|
+
os.rename(dst_path, src_path)
|
321
|
+
|
322
|
+
|
281
323
|
if __name__ == "__main__":
|
282
324
|
data = np.random.rand(100, 50)
|
283
325
|
save(r"test.nc", data, "data", {"time": np.linspace(0, 120, 100), "lev": np.linspace(0, 120, 50)}, "a")
|
oafuncs/oa_tool.py
CHANGED
@@ -137,7 +137,7 @@ def pbar(
|
|
137
137
|
description: str = "Working...",
|
138
138
|
total: Optional[float] = None,
|
139
139
|
completed: float = 0,
|
140
|
-
color: Any = "
|
140
|
+
color: Any = "None",
|
141
141
|
cmap: Union[str, List[str], None] = None,
|
142
142
|
update_interval: float = 0.1,
|
143
143
|
bar_length: Optional[int] = None,
|
@@ -173,8 +173,23 @@ def pbar(
|
|
173
173
|
... time.sleep(0.1)
|
174
174
|
"""
|
175
175
|
from ._script.cprogressbar import ColorProgressBar
|
176
|
+
import random
|
176
177
|
|
177
|
-
|
178
|
+
def _generate_random_color_hex():
|
179
|
+
"""Generate a random color in hexadecimal format."""
|
180
|
+
r = random.randint(0, 255)
|
181
|
+
g = random.randint(0, 255)
|
182
|
+
b = random.randint(0, 255)
|
183
|
+
return '#{r:02x}{g:02x}{b:02x}'.format(r=r, g=g, b=b)
|
184
|
+
|
185
|
+
if color == 'None' and cmap is None:
|
186
|
+
color = _generate_random_color_hex()
|
187
|
+
|
188
|
+
style = f"bold {color if color != 'None' else 'green'}"
|
189
|
+
print(f"[{style}]~*^* {description} *^*~[/{style}]")
|
190
|
+
|
191
|
+
description=''
|
192
|
+
|
178
193
|
return ColorProgressBar(
|
179
194
|
iterable=iterable,
|
180
195
|
description=description,
|
@@ -1,27 +1,27 @@
|
|
1
1
|
oafuncs/__init__.py,sha256=T_-VtnWWllV3Q91twT5Yt2sUapeA051QbPNnBxmg9nw,1456
|
2
2
|
oafuncs/oa_cmap.py,sha256=DimWT4Bg7uE5Lx8hSw1REp7whpsR2pFRStAwk1cowEM,11494
|
3
|
-
oafuncs/oa_data.py,sha256=
|
3
|
+
oafuncs/oa_data.py,sha256=PXn4EpSbLPHhYmNJXEStd8vIMwInl3a9O9sW2c9z-g0,11152
|
4
4
|
oafuncs/oa_date.py,sha256=WhM6cyD4G3IeghjLTHhAMtlvJbA7kwQG2sHnxdTgyso,6303
|
5
5
|
oafuncs/oa_draw.py,sha256=Wj2QBgyIPpV_dxaDrH10jqj_puK9ZM9rd-si-3VrsrE,17631
|
6
|
-
oafuncs/oa_file.py,sha256=
|
6
|
+
oafuncs/oa_file.py,sha256=j9gXJgPOJsliu4IOUc4bc-luW4yBvQyNCEmMyDVjUwQ,16404
|
7
7
|
oafuncs/oa_help.py,sha256=_4AZgRDq5Or0vauNvq5IDDHIBoBfdOQtzak-mG1wwAw,4537
|
8
|
-
oafuncs/oa_nc.py,sha256=
|
8
|
+
oafuncs/oa_nc.py,sha256=lLEPjj4qgdEw1al0r1nKGZUnMP_ejT8A2NKD4lrs2kc,11936
|
9
9
|
oafuncs/oa_python.py,sha256=NkopwkYFGSEuVljnTBvXCl6o2CeyRNBqRXSsUl3euEE,5192
|
10
|
-
oafuncs/oa_tool.py,sha256=
|
10
|
+
oafuncs/oa_tool.py,sha256=EqOlGPq3Rx2ohqVnGuCZhMvr2o9_XgglrETMbAdEifM,8471
|
11
11
|
oafuncs/_data/hycom.png,sha256=MadKs6Gyj5n9-TOu7L4atQfTXtF9dvN9w-tdU9IfygI,10945710
|
12
12
|
oafuncs/_data/oafuncs.png,sha256=o3VD7wm-kwDea5E98JqxXl04_78cBX7VcdUt7uQXGiU,3679898
|
13
|
-
oafuncs/_script/cprogressbar.py,sha256=
|
13
|
+
oafuncs/_script/cprogressbar.py,sha256=UIgGcLFs-6IgWlITuBLaQqrpt4OAK3Mst5RlCiNfZdQ,15772
|
14
14
|
oafuncs/_script/email.py,sha256=lL4HGKrr524-g0xLlgs-4u7x4-u7DtgNoD9AL8XJKj4,3058
|
15
15
|
oafuncs/_script/netcdf_merge.py,sha256=ktmTOgGfLHBNdS4HBc6xFDfO8B7E4DT7d1e6Dtare9Y,5596
|
16
16
|
oafuncs/_script/netcdf_modify.py,sha256=sGRUYNhfGgf9JV70rnBzw3bzuTRSXzBTL_RMDnDPeLQ,4552
|
17
17
|
oafuncs/_script/netcdf_write.py,sha256=iO1Qv9bp6RLiw1D8Nrv7tX_8X-diUZaX3Nxhk6pJ5Nw,8556
|
18
|
-
oafuncs/_script/parallel.py,sha256=
|
18
|
+
oafuncs/_script/parallel.py,sha256=T9Aie-e4LcbKlFTLZ0l4lhEN3SBVa84jRcrAsIm8s0I,8767
|
19
19
|
oafuncs/_script/parallel_test.py,sha256=0GBqZOX7IaCOKF2t1y8N8YYu53GJ33OkfsWgpvZNqM4,372
|
20
20
|
oafuncs/_script/plot_dataset.py,sha256=zkSEnO_-biyagorwWXPoihts_cwuvripzEt-l9bHJ2E,13989
|
21
21
|
oafuncs/_script/replace_file_content.py,sha256=eCFZjnZcwyRvy6b4mmIfBna-kylSZTyJRfgXd6DdCjk,5982
|
22
22
|
oafuncs/oa_down/User_Agent-list.txt,sha256=pHaMlElMvZ8TG4vf4BqkZYKqe0JIGkr4kCN0lM1Y9FQ,514295
|
23
23
|
oafuncs/oa_down/__init__.py,sha256=kRX5eTUCbAiz3zTaQM1501paOYS_3fizDN4Pa0mtNUA,585
|
24
|
-
oafuncs/oa_down/hycom_3hourly.py,sha256=
|
24
|
+
oafuncs/oa_down/hycom_3hourly.py,sha256=VYxG9DPAnS1wk8gEXyqSIww4IvNRWOYGC4D6PTh5t3A,55450
|
25
25
|
oafuncs/oa_down/hycom_3hourly_proxy.py,sha256=1eaoJGI_m-7w4ZZ3n7NGxkZaeFdsm0d3U-hyw8RFNbc,54563
|
26
26
|
oafuncs/oa_down/idm.py,sha256=4z5IvgfTyIKEI1kOtqXZwN7Jnfjwp6qDBOIoVyOLp0I,1823
|
27
27
|
oafuncs/oa_down/literature.py,sha256=2bF9gSKQbzcci9LcKE81j8JEjIJwON7jbwQB3gDDA3E,11331
|
@@ -37,8 +37,8 @@ oafuncs/oa_sign/__init__.py,sha256=QKqTFrJDFK40C5uvk48GlRRbGFzO40rgkYwu6dYxatM,5
|
|
37
37
|
oafuncs/oa_sign/meteorological.py,sha256=8091SHo2L8kl4dCFmmSH5NGVHDku5i5lSiLEG5DLnOQ,6489
|
38
38
|
oafuncs/oa_sign/ocean.py,sha256=xrW-rWD7xBWsB5PuCyEwQ1Q_RDKq2KCLz-LOONHgldU,5932
|
39
39
|
oafuncs/oa_sign/scientific.py,sha256=a4JxOBgm9vzNZKpJ_GQIQf7cokkraV5nh23HGbmTYKw,5064
|
40
|
-
oafuncs-0.0.98.
|
41
|
-
oafuncs-0.0.98.
|
42
|
-
oafuncs-0.0.98.
|
43
|
-
oafuncs-0.0.98.
|
44
|
-
oafuncs-0.0.98.
|
40
|
+
oafuncs-0.0.98.11.dist-info/licenses/LICENSE.txt,sha256=rMtLpVg8sKiSlwClfR9w_Dd_5WubTQgoOzE2PDFxzs4,1074
|
41
|
+
oafuncs-0.0.98.11.dist-info/METADATA,sha256=vbHI4zd7XEcXnbCI7VuGmyDEcnfv5hsVjR8XczfObTU,4273
|
42
|
+
oafuncs-0.0.98.11.dist-info/WHEEL,sha256=SmOxYU7pzNKBqASvQJ7DjX3XGUF92lrGhMb3R6_iiqI,91
|
43
|
+
oafuncs-0.0.98.11.dist-info/top_level.txt,sha256=bgC35QkXbN4EmPHEveg_xGIZ5i9NNPYWqtJqaKqTPsQ,8
|
44
|
+
oafuncs-0.0.98.11.dist-info/RECORD,,
|
File without changes
|
File without changes
|