oafuncs 0.0.98.0__tar.gz → 0.0.98.2__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.
- {oafuncs-0.0.98.0/oafuncs.egg-info → oafuncs-0.0.98.2}/PKG-INFO +1 -1
- oafuncs-0.0.98.2/oafuncs/_script/netcdf_write.py +116 -0
- {oafuncs-0.0.98.0 → oafuncs-0.0.98.2}/oafuncs/oa_down/idm.py +2 -1
- {oafuncs-0.0.98.0 → oafuncs-0.0.98.2}/oafuncs/oa_nc.py +2 -2
- {oafuncs-0.0.98.0 → oafuncs-0.0.98.2/oafuncs.egg-info}/PKG-INFO +1 -1
- {oafuncs-0.0.98.0 → oafuncs-0.0.98.2}/setup.py +1 -1
- oafuncs-0.0.98.0/oafuncs/_script/netcdf_write.py +0 -125
- {oafuncs-0.0.98.0 → oafuncs-0.0.98.2}/LICENSE.txt +0 -0
- {oafuncs-0.0.98.0 → oafuncs-0.0.98.2}/MANIFEST.in +0 -0
- {oafuncs-0.0.98.0 → oafuncs-0.0.98.2}/README.md +0 -0
- {oafuncs-0.0.98.0 → oafuncs-0.0.98.2}/oafuncs/__init__.py +0 -0
- {oafuncs-0.0.98.0 → oafuncs-0.0.98.2}/oafuncs/_data/hycom.png +0 -0
- {oafuncs-0.0.98.0 → oafuncs-0.0.98.2}/oafuncs/_data/oafuncs.png +0 -0
- {oafuncs-0.0.98.0 → oafuncs-0.0.98.2}/oafuncs/_script/cprogressbar.py +0 -0
- {oafuncs-0.0.98.0 → oafuncs-0.0.98.2}/oafuncs/_script/email.py +0 -0
- {oafuncs-0.0.98.0 → oafuncs-0.0.98.2}/oafuncs/_script/netcdf_merge.py +0 -0
- {oafuncs-0.0.98.0 → oafuncs-0.0.98.2}/oafuncs/_script/netcdf_modify.py +0 -0
- {oafuncs-0.0.98.0 → oafuncs-0.0.98.2}/oafuncs/_script/parallel.py +0 -0
- {oafuncs-0.0.98.0 → oafuncs-0.0.98.2}/oafuncs/_script/parallel_example_usage.py +0 -0
- {oafuncs-0.0.98.0 → oafuncs-0.0.98.2}/oafuncs/_script/plot_dataset.py +0 -0
- {oafuncs-0.0.98.0 → oafuncs-0.0.98.2}/oafuncs/_script/replace_file_content.py +0 -0
- {oafuncs-0.0.98.0 → oafuncs-0.0.98.2}/oafuncs/oa_cmap.py +0 -0
- {oafuncs-0.0.98.0 → oafuncs-0.0.98.2}/oafuncs/oa_data.py +0 -0
- {oafuncs-0.0.98.0 → oafuncs-0.0.98.2}/oafuncs/oa_date.py +0 -0
- {oafuncs-0.0.98.0 → oafuncs-0.0.98.2}/oafuncs/oa_down/User_Agent-list.txt +0 -0
- {oafuncs-0.0.98.0 → oafuncs-0.0.98.2}/oafuncs/oa_down/__init__.py +0 -0
- {oafuncs-0.0.98.0 → oafuncs-0.0.98.2}/oafuncs/oa_down/hycom_3hourly.py +0 -0
- {oafuncs-0.0.98.0 → oafuncs-0.0.98.2}/oafuncs/oa_down/hycom_3hourly_20250407.py +0 -0
- {oafuncs-0.0.98.0 → oafuncs-0.0.98.2}/oafuncs/oa_down/literature.py +0 -0
- {oafuncs-0.0.98.0 → oafuncs-0.0.98.2}/oafuncs/oa_down/test_ua.py +0 -0
- {oafuncs-0.0.98.0 → oafuncs-0.0.98.2}/oafuncs/oa_down/user_agent.py +0 -0
- {oafuncs-0.0.98.0 → oafuncs-0.0.98.2}/oafuncs/oa_draw.py +0 -0
- {oafuncs-0.0.98.0 → oafuncs-0.0.98.2}/oafuncs/oa_file.py +0 -0
- {oafuncs-0.0.98.0 → oafuncs-0.0.98.2}/oafuncs/oa_help.py +0 -0
- {oafuncs-0.0.98.0 → oafuncs-0.0.98.2}/oafuncs/oa_model/__init__.py +0 -0
- {oafuncs-0.0.98.0 → oafuncs-0.0.98.2}/oafuncs/oa_model/roms/__init__.py +0 -0
- {oafuncs-0.0.98.0 → oafuncs-0.0.98.2}/oafuncs/oa_model/roms/test.py +0 -0
- {oafuncs-0.0.98.0 → oafuncs-0.0.98.2}/oafuncs/oa_model/wrf/__init__.py +0 -0
- {oafuncs-0.0.98.0 → oafuncs-0.0.98.2}/oafuncs/oa_model/wrf/little_r.py +0 -0
- {oafuncs-0.0.98.0 → oafuncs-0.0.98.2}/oafuncs/oa_python.py +0 -0
- {oafuncs-0.0.98.0 → oafuncs-0.0.98.2}/oafuncs/oa_sign/__init__.py +0 -0
- {oafuncs-0.0.98.0 → oafuncs-0.0.98.2}/oafuncs/oa_sign/meteorological.py +0 -0
- {oafuncs-0.0.98.0 → oafuncs-0.0.98.2}/oafuncs/oa_sign/ocean.py +0 -0
- {oafuncs-0.0.98.0 → oafuncs-0.0.98.2}/oafuncs/oa_sign/scientific.py +0 -0
- {oafuncs-0.0.98.0 → oafuncs-0.0.98.2}/oafuncs/oa_tool.py +0 -0
- {oafuncs-0.0.98.0 → oafuncs-0.0.98.2}/oafuncs.egg-info/SOURCES.txt +0 -0
- {oafuncs-0.0.98.0 → oafuncs-0.0.98.2}/oafuncs.egg-info/dependency_links.txt +0 -0
- {oafuncs-0.0.98.0 → oafuncs-0.0.98.2}/oafuncs.egg-info/requires.txt +0 -0
- {oafuncs-0.0.98.0 → oafuncs-0.0.98.2}/oafuncs.egg-info/top_level.txt +0 -0
- {oafuncs-0.0.98.0 → oafuncs-0.0.98.2}/setup.cfg +0 -0
@@ -0,0 +1,116 @@
|
|
1
|
+
import os
|
2
|
+
import netCDF4 as nc
|
3
|
+
import numpy as np
|
4
|
+
import xarray as xr
|
5
|
+
|
6
|
+
|
7
|
+
def _numpy_to_nc_type(numpy_type):
|
8
|
+
"""将NumPy数据类型映射到NetCDF数据类型"""
|
9
|
+
numpy_to_nc = {
|
10
|
+
"float32": "f4",
|
11
|
+
"float64": "f8",
|
12
|
+
"int8": "i1",
|
13
|
+
"int16": "i2",
|
14
|
+
"int32": "i4",
|
15
|
+
"int64": "i8",
|
16
|
+
"uint8": "u1",
|
17
|
+
"uint16": "u2",
|
18
|
+
"uint32": "u4",
|
19
|
+
"uint64": "u8",
|
20
|
+
}
|
21
|
+
numpy_type_str = str(numpy_type) if not isinstance(numpy_type, str) else numpy_type
|
22
|
+
return numpy_to_nc.get(numpy_type_str, "f4")
|
23
|
+
|
24
|
+
|
25
|
+
def _calculate_scale_and_offset(data, n=16):
|
26
|
+
if not isinstance(data, np.ndarray):
|
27
|
+
raise ValueError("Input data must be a NumPy array.")
|
28
|
+
|
29
|
+
data_min = np.nanmin(data)
|
30
|
+
data_max = np.nanmax(data)
|
31
|
+
|
32
|
+
if np.isnan(data_min) or np.isnan(data_max):
|
33
|
+
raise ValueError("Input data contains NaN values.")
|
34
|
+
|
35
|
+
scale_factor = (data_max - data_min) / (2**n - 1)
|
36
|
+
add_offset = data_min + 2 ** (n - 1) * scale_factor
|
37
|
+
return scale_factor, add_offset
|
38
|
+
|
39
|
+
|
40
|
+
def save_to_nc(file, data, varname=None, coords=None, mode="w", scale_offset_switch=True, compile_switch=True):
|
41
|
+
# 处理xarray对象的情况(当varname和coords都为None时)
|
42
|
+
if varname is None and coords is None:
|
43
|
+
if not isinstance(data, (xr.DataArray, xr.Dataset)):
|
44
|
+
raise ValueError("When varname and coords are not provided, data must be an xarray object")
|
45
|
+
|
46
|
+
encoding = {}
|
47
|
+
if isinstance(data, xr.DataArray):
|
48
|
+
if data.name is None:
|
49
|
+
data = data.rename("data")
|
50
|
+
varname = data.name
|
51
|
+
encoding[varname] = {"zlib": compile_switch, "complevel": 4}
|
52
|
+
if scale_offset_switch:
|
53
|
+
scale, offset = _calculate_scale_and_offset(data.values)
|
54
|
+
encoding[varname].update({"dtype": "int16", "scale_factor": scale, "add_offset": offset, "_FillValue": -32767})
|
55
|
+
else:
|
56
|
+
encoding[varname].update({"dtype": "float32", "_FillValue": np.nan})
|
57
|
+
else: # Dataset情况
|
58
|
+
for var in data.data_vars:
|
59
|
+
encoding[var] = {"zlib": compile_switch, "complevel": 4}
|
60
|
+
if scale_offset_switch:
|
61
|
+
scale, offset = _calculate_scale_and_offset(data[var].values)
|
62
|
+
encoding[var].update({"dtype": "int16", "scale_factor": scale, "add_offset": offset, "_FillValue": -32767})
|
63
|
+
else:
|
64
|
+
encoding[var].update({"dtype": "float32", "_FillValue": np.nan})
|
65
|
+
|
66
|
+
try:
|
67
|
+
data.to_netcdf(file, mode=mode, encoding=encoding)
|
68
|
+
return
|
69
|
+
except Exception as e:
|
70
|
+
raise RuntimeError(f"Failed to save xarray object: {str(e)}") from e
|
71
|
+
|
72
|
+
# 处理普通numpy数组的情况
|
73
|
+
if mode == "w" and os.path.exists(file):
|
74
|
+
os.remove(file)
|
75
|
+
elif mode == "a" and not os.path.exists(file):
|
76
|
+
mode = "w"
|
77
|
+
|
78
|
+
try:
|
79
|
+
with nc.Dataset(file, mode, format="NETCDF4") as ncfile:
|
80
|
+
# 创建维度并写入坐标
|
81
|
+
if coords is not None:
|
82
|
+
for dim, values in coords.items():
|
83
|
+
if dim not in ncfile.dimensions:
|
84
|
+
ncfile.createDimension(dim, len(values))
|
85
|
+
var = ncfile.createVariable(dim, _numpy_to_nc_type(values.dtype), (dim,))
|
86
|
+
var[:] = values
|
87
|
+
|
88
|
+
# 创建变量
|
89
|
+
dims = list(coords.keys()) if coords else []
|
90
|
+
if scale_offset_switch:
|
91
|
+
scale, offset = _calculate_scale_and_offset(data)
|
92
|
+
var = ncfile.createVariable(varname, "i2", dims, fill_value=-32767, zlib=compile_switch)
|
93
|
+
var.scale_factor = scale
|
94
|
+
var.add_offset = offset
|
95
|
+
else:
|
96
|
+
dtype = _numpy_to_nc_type(data.dtype)
|
97
|
+
var = ncfile.createVariable(varname, dtype, dims, zlib=compile_switch)
|
98
|
+
|
99
|
+
var[:] = data
|
100
|
+
except Exception as e:
|
101
|
+
raise RuntimeError(f"Failed to save netCDF4 file: {str(e)}") from e
|
102
|
+
|
103
|
+
|
104
|
+
if __name__ == "__main__":
|
105
|
+
# Example usage
|
106
|
+
data = xr.open_dataset(r"F:\roms_rst.nc")["u"]
|
107
|
+
save_to_nc(r"F:\test.nc", data)
|
108
|
+
|
109
|
+
# xarray测试
|
110
|
+
data = xr.DataArray(np.random.rand(10, 20), dims=("x", "y"), name="temperature")
|
111
|
+
save_to_nc(r"F:\test_xarray.nc", data)
|
112
|
+
|
113
|
+
# numpy测试
|
114
|
+
arr = np.random.rand(5, 3)
|
115
|
+
coords = {"x": np.arange(5), "y": np.arange(3)}
|
116
|
+
save_to_nc(r"F:\test_numpy.nc", arr, varname="data", coords=coords)
|
@@ -52,6 +52,7 @@ def downloader(task_url, folder_path, file_name, idm_engine=r"D:\Programs\Intern
|
|
52
52
|
time_str = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
|
53
53
|
time_str = time_str.center(100, " ")
|
54
54
|
print(f"[bold purple]{time_str}")
|
55
|
-
|
55
|
+
info = f'IDM Downloader: {file_name}'.center(100, " ")
|
56
|
+
print(f"[green]{info}[/green]")
|
56
57
|
print("[purple]*" * 100)
|
57
58
|
# print("\n")
|
@@ -11,7 +11,7 @@ __all__ = ["save", "merge", "modify", "rename", "check", "convert_longitude", "i
|
|
11
11
|
|
12
12
|
def save(
|
13
13
|
file_path: str,
|
14
|
-
data: Union[np.ndarray, xr.DataArray],
|
14
|
+
data: Union[np.ndarray, xr.DataArray, xr.Dataset],
|
15
15
|
variable_name: Optional[str] = None,
|
16
16
|
coordinates: Optional[dict] = None,
|
17
17
|
write_mode: str = "w",
|
@@ -23,7 +23,7 @@ def save(
|
|
23
23
|
|
24
24
|
Args:
|
25
25
|
file_path (str): File path to save the NetCDF file.
|
26
|
-
data (Union[np.ndarray, xr.DataArray]): Data to be written.
|
26
|
+
data (Union[np.ndarray, xr.DataArray, xr.Dataset]): Data to be written.
|
27
27
|
variable_name (Optional[str]): Variable name for the data.
|
28
28
|
coordinates (Optional[dict]): Coordinates, where keys are dimension names and values are coordinate data.
|
29
29
|
write_mode (str): Write mode, 'w' for write, 'a' for append. Default is 'w'.
|
@@ -18,7 +18,7 @@ URL = "https://github.com/Industry-Pays/OAFuncs"
|
|
18
18
|
EMAIL = "liukun0312@stu.ouc.edu.cn"
|
19
19
|
AUTHOR = "Kun Liu"
|
20
20
|
REQUIRES_PYTHON = ">=3.9.0" # 2025/03/13
|
21
|
-
VERSION = "0.0.98.
|
21
|
+
VERSION = "0.0.98.2"
|
22
22
|
|
23
23
|
# What packages are required for this module to be executed?
|
24
24
|
REQUIRED = [
|
@@ -1,125 +0,0 @@
|
|
1
|
-
import numpy as np
|
2
|
-
import os
|
3
|
-
import netCDF4 as nc
|
4
|
-
import xarray as xr
|
5
|
-
|
6
|
-
|
7
|
-
def _numpy_to_nc_type(numpy_type):
|
8
|
-
"""将NumPy数据类型映射到NetCDF数据类型"""
|
9
|
-
numpy_to_nc = {
|
10
|
-
"float32": "f4",
|
11
|
-
"float64": "f8",
|
12
|
-
"int8": "i1",
|
13
|
-
"int16": "i2",
|
14
|
-
"int32": "i4",
|
15
|
-
"int64": "i8",
|
16
|
-
"uint8": "u1",
|
17
|
-
"uint16": "u2",
|
18
|
-
"uint32": "u4",
|
19
|
-
"uint64": "u8",
|
20
|
-
}
|
21
|
-
# 确保传入的是字符串类型,如果不是,则转换为字符串
|
22
|
-
numpy_type_str = str(numpy_type) if not isinstance(numpy_type, str) else numpy_type
|
23
|
-
return numpy_to_nc.get(numpy_type_str, "f4") # 默认使用 'float32'
|
24
|
-
|
25
|
-
|
26
|
-
def _calculate_scale_and_offset(data, n=16):
|
27
|
-
if not isinstance(data, np.ndarray):
|
28
|
-
raise ValueError("Input data must be a NumPy array.")
|
29
|
-
|
30
|
-
# 使用 nan_to_num 来避免 NaN 值对 min 和 max 的影响
|
31
|
-
data_min = np.nanmin(data)
|
32
|
-
data_max = np.nanmax(data)
|
33
|
-
|
34
|
-
if np.isnan(data_min) or np.isnan(data_max):
|
35
|
-
raise ValueError("Input data contains NaN values, which are not allowed.")
|
36
|
-
|
37
|
-
scale_factor = (data_max - data_min) / (2**n - 1)
|
38
|
-
add_offset = data_min + 2 ** (n - 1) * scale_factor
|
39
|
-
|
40
|
-
return scale_factor, add_offset
|
41
|
-
|
42
|
-
|
43
|
-
def save_to_nc(file, data, varname=None, coords=None, mode="w", scale_offset_switch=True, compile_switch=True):
|
44
|
-
"""
|
45
|
-
Description:
|
46
|
-
Write data to NetCDF file
|
47
|
-
Parameters:
|
48
|
-
file: str, file path
|
49
|
-
data: data
|
50
|
-
varname: str, variable name
|
51
|
-
coords: dict, coordinates, key is the dimension name, value is the coordinate data
|
52
|
-
mode: str, write mode, 'w' for write, 'a' for append
|
53
|
-
scale_offset_switch: bool, whether to use scale_factor and add_offset, default is True
|
54
|
-
compile_switch: bool, whether to use compression parameters, default is True
|
55
|
-
Example:
|
56
|
-
save(r'test.nc', data, 'u', {'time': np.linspace(0, 120, 100), 'lev': np.linspace(0, 120, 50)}, 'a')
|
57
|
-
"""
|
58
|
-
# 设置压缩参数
|
59
|
-
kwargs = {"zlib": True, "complevel": 4} if compile_switch else {}
|
60
|
-
|
61
|
-
# 检查文件存在性并根据模式决定操作
|
62
|
-
if mode == "w" and os.path.exists(file):
|
63
|
-
os.remove(file)
|
64
|
-
elif mode == "a" and not os.path.exists(file):
|
65
|
-
mode = "w"
|
66
|
-
|
67
|
-
# 打开 NetCDF 文件
|
68
|
-
with nc.Dataset(file, mode, format="NETCDF4") as ncfile:
|
69
|
-
# 如果 data 是 DataArray 并且没有提供 varname 和 coords
|
70
|
-
if varname is None and coords is None and isinstance(data, xr.DataArray):
|
71
|
-
encoding = {}
|
72
|
-
for var in data.data_vars:
|
73
|
-
scale_factor, add_offset = _calculate_scale_and_offset(data[var].values)
|
74
|
-
encoding[var] = {
|
75
|
-
"zlib": True,
|
76
|
-
"complevel": 4,
|
77
|
-
"dtype": "int16",
|
78
|
-
"scale_factor": scale_factor,
|
79
|
-
"add_offset": add_offset,
|
80
|
-
"_FillValue": -32767,
|
81
|
-
}
|
82
|
-
data.to_netcdf(file, mode=mode, encoding=encoding)
|
83
|
-
return
|
84
|
-
|
85
|
-
# 添加坐标
|
86
|
-
for dim, coord_data in coords.items():
|
87
|
-
if dim in ncfile.dimensions:
|
88
|
-
if len(coord_data) != len(ncfile.dimensions[dim]):
|
89
|
-
raise ValueError(f"Length of coordinate '{dim}' does not match the dimension length.")
|
90
|
-
else:
|
91
|
-
ncfile.variables[dim][:] = np.array(coord_data)
|
92
|
-
else:
|
93
|
-
ncfile.createDimension(dim, len(coord_data))
|
94
|
-
var = ncfile.createVariable(dim, _numpy_to_nc_type(coord_data.dtype), (dim,), **kwargs)
|
95
|
-
var[:] = np.array(coord_data)
|
96
|
-
|
97
|
-
# 如果坐标数据有属性,则添加到 NetCDF 变量
|
98
|
-
if isinstance(coord_data, xr.DataArray) and coord_data.attrs:
|
99
|
-
for attr_name, attr_value in coord_data.attrs.items():
|
100
|
-
var.setncattr(attr_name, attr_value)
|
101
|
-
|
102
|
-
# 添加或更新变量
|
103
|
-
if varname in ncfile.variables:
|
104
|
-
if data.shape != ncfile.variables[varname].shape:
|
105
|
-
raise ValueError(f"Shape of data does not match the variable shape for '{varname}'.")
|
106
|
-
ncfile.variables[varname][:] = np.array(data)
|
107
|
-
else:
|
108
|
-
# 创建变量
|
109
|
-
dim_names = tuple(coords.keys())
|
110
|
-
if scale_offset_switch:
|
111
|
-
scale_factor, add_offset = _calculate_scale_and_offset(np.array(data))
|
112
|
-
dtype = "i2"
|
113
|
-
var = ncfile.createVariable(varname, dtype, dim_names, fill_value=-32767, **kwargs)
|
114
|
-
var.setncattr("scale_factor", scale_factor)
|
115
|
-
var.setncattr("add_offset", add_offset)
|
116
|
-
else:
|
117
|
-
dtype = _numpy_to_nc_type(data.dtype)
|
118
|
-
var = ncfile.createVariable(varname, dtype, dim_names, **kwargs)
|
119
|
-
var[:] = np.array(data)
|
120
|
-
|
121
|
-
# 添加属性
|
122
|
-
if isinstance(data, xr.DataArray) and data.attrs:
|
123
|
-
for key, value in data.attrs.items():
|
124
|
-
if key not in ["scale_factor", "add_offset", "_FillValue", "missing_value"] or not scale_offset_switch:
|
125
|
-
var.setncattr(key, value)
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|