oafuncs 0.0.97.2__tar.gz → 0.0.97.4__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. oafuncs-0.0.97.4/MANIFEST.in +5 -0
  2. {oafuncs-0.0.97.2/oafuncs.egg-info → oafuncs-0.0.97.4}/PKG-INFO +78 -7
  3. oafuncs-0.0.97.4/README.md +131 -0
  4. oafuncs-0.0.97.4/oafuncs/_script/plot_dataset.py +299 -0
  5. {oafuncs-0.0.97.2 → oafuncs-0.0.97.4/oafuncs.egg-info}/PKG-INFO +78 -7
  6. {oafuncs-0.0.97.2 → oafuncs-0.0.97.4}/oafuncs.egg-info/SOURCES.txt +3 -2
  7. {oafuncs-0.0.97.2 → oafuncs-0.0.97.4}/setup.py +9 -3
  8. oafuncs-0.0.97.2/MANIFEST.in +0 -4
  9. oafuncs-0.0.97.2/README.md +0 -60
  10. {oafuncs-0.0.97.2 → oafuncs-0.0.97.4}/LICENSE.txt +0 -0
  11. {oafuncs-0.0.97.2 → oafuncs-0.0.97.4}/oafuncs/__init__.py +0 -0
  12. {oafuncs-0.0.97.2/oafuncs/data_store → oafuncs-0.0.97.4/oafuncs/_data}/OAFuncs.png +0 -0
  13. {oafuncs-0.0.97.2/oafuncs/data_store → oafuncs-0.0.97.4/oafuncs/_data}/hycom_3hourly.png +0 -0
  14. {oafuncs-0.0.97.2 → oafuncs-0.0.97.4}/oafuncs/oa_cmap.py +0 -0
  15. {oafuncs-0.0.97.2 → oafuncs-0.0.97.4}/oafuncs/oa_data.py +0 -0
  16. {oafuncs-0.0.97.2 → oafuncs-0.0.97.4}/oafuncs/oa_down/User_Agent-list.txt +0 -0
  17. {oafuncs-0.0.97.2 → oafuncs-0.0.97.4}/oafuncs/oa_down/__init__.py +0 -0
  18. {oafuncs-0.0.97.2 → oafuncs-0.0.97.4}/oafuncs/oa_down/hycom_3hourly.py +0 -0
  19. {oafuncs-0.0.97.2 → oafuncs-0.0.97.4}/oafuncs/oa_down/hycom_3hourly_20250129.py +0 -0
  20. {oafuncs-0.0.97.2 → oafuncs-0.0.97.4}/oafuncs/oa_down/idm.py +0 -0
  21. {oafuncs-0.0.97.2 → oafuncs-0.0.97.4}/oafuncs/oa_down/literature.py +0 -0
  22. {oafuncs-0.0.97.2 → oafuncs-0.0.97.4}/oafuncs/oa_down/test_ua.py +0 -0
  23. {oafuncs-0.0.97.2 → oafuncs-0.0.97.4}/oafuncs/oa_down/user_agent.py +0 -0
  24. {oafuncs-0.0.97.2 → oafuncs-0.0.97.4}/oafuncs/oa_draw.py +0 -0
  25. {oafuncs-0.0.97.2 → oafuncs-0.0.97.4}/oafuncs/oa_file.py +0 -0
  26. {oafuncs-0.0.97.2 → oafuncs-0.0.97.4}/oafuncs/oa_help.py +0 -0
  27. {oafuncs-0.0.97.2 → oafuncs-0.0.97.4}/oafuncs/oa_model/__init__.py +0 -0
  28. {oafuncs-0.0.97.2 → oafuncs-0.0.97.4}/oafuncs/oa_model/roms/__init__.py +0 -0
  29. {oafuncs-0.0.97.2 → oafuncs-0.0.97.4}/oafuncs/oa_model/roms/test.py +0 -0
  30. {oafuncs-0.0.97.2 → oafuncs-0.0.97.4}/oafuncs/oa_model/wrf/__init__.py +0 -0
  31. {oafuncs-0.0.97.2 → oafuncs-0.0.97.4}/oafuncs/oa_model/wrf/little_r.py +0 -0
  32. {oafuncs-0.0.97.2 → oafuncs-0.0.97.4}/oafuncs/oa_nc.py +0 -0
  33. {oafuncs-0.0.97.2 → oafuncs-0.0.97.4}/oafuncs/oa_python.py +0 -0
  34. {oafuncs-0.0.97.2 → oafuncs-0.0.97.4}/oafuncs/oa_sign/__init__.py +0 -0
  35. {oafuncs-0.0.97.2 → oafuncs-0.0.97.4}/oafuncs/oa_sign/meteorological.py +0 -0
  36. {oafuncs-0.0.97.2 → oafuncs-0.0.97.4}/oafuncs/oa_sign/ocean.py +0 -0
  37. {oafuncs-0.0.97.2 → oafuncs-0.0.97.4}/oafuncs/oa_sign/scientific.py +0 -0
  38. {oafuncs-0.0.97.2 → oafuncs-0.0.97.4}/oafuncs/oa_tool/__init__.py +0 -0
  39. {oafuncs-0.0.97.2 → oafuncs-0.0.97.4}/oafuncs/oa_tool/email.py +0 -0
  40. {oafuncs-0.0.97.2 → oafuncs-0.0.97.4}/oafuncs/oa_tool/parallel.py +0 -0
  41. {oafuncs-0.0.97.2 → oafuncs-0.0.97.4}/oafuncs/oa_tool/time.py +0 -0
  42. {oafuncs-0.0.97.2 → oafuncs-0.0.97.4}/oafuncs.egg-info/dependency_links.txt +0 -0
  43. {oafuncs-0.0.97.2 → oafuncs-0.0.97.4}/oafuncs.egg-info/requires.txt +0 -0
  44. {oafuncs-0.0.97.2 → oafuncs-0.0.97.4}/oafuncs.egg-info/top_level.txt +0 -0
  45. {oafuncs-0.0.97.2 → oafuncs-0.0.97.4}/setup.cfg +0 -0
@@ -0,0 +1,5 @@
1
+ include LICENSE.txt
2
+ include README.md
3
+ recursive-include oafuncs/_data *
4
+ recursive-include oafuncs/oa_down *.txt
5
+ recursive-include oafuncs/_script *.py
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: oafuncs
3
- Version: 0.0.97.2
3
+ Version: 0.0.97.4
4
4
  Summary: Oceanic and Atmospheric Functions
5
5
  Home-page: https://github.com/Industry-Pays/OAFuncs
6
6
  Author: Kun Liu
@@ -86,17 +86,88 @@ oafuncs.oa_help.use('query')
86
86
  ```
87
87
 
88
88
  ```shell
89
- # 此小板块于2024/12/26更新,仅为示例,不代表最新情况
89
+ # 此小板块于2025/03/16更新,仅为示例,不代表最新情况
90
90
  函数数量:
91
- 49
91
+ 62
92
92
  函数列表:
93
- ['MidpointNormalize', 'add_cartopy', 'add_gridlines', 'add_lonlat_unit', 'check_ncfile', 'choose_cmap', 'clear_folder', 'cmap2colors', 'convert_longitude', 'copy_file', 'create_cmap', 'create_cmap_rgbtxt', 'create_gif', 'download', 'download5doi', 'draw_time_range', 'extract5nc', 'fig_minus', 'file_size', 'find_file', 'get_time_list', 'get_ua', 'get_var', 'how_to_use', 'install_lib', 'interp_2d', 'link_file', 'make_folder', 'merge5nc', 'modify_var_attr', 'modify_var_value', 'nc_isel', 'plot_contourf', 'plot_contourf_cartopy', 'plot_contourf_lonlat', 'plot_quiver', 'query', 'remove', 'remove_empty_folder', 'rename_file', 'rename_var_or_dim', 'send', 'show', 'sign_in_love_ocean', 'sign_in_meteorological_home', 'sign_in_scientific_research', 'upgrade_lib', 'use', 'write2nc']
93
+ [
94
+ 'MidpointNormalize',
95
+ 'ParallelExecutor',
96
+ 'add_cartopy',
97
+ 'add_gridlines',
98
+ 'add_lonlat_unit',
99
+ 'check',
100
+ 'clear_folder',
101
+ 'contour',
102
+ 'contourf',
103
+ 'convert_longitude',
104
+ 'copy_file',
105
+ 'create',
106
+ 'create_rgbtxt',
107
+ 'data_record',
108
+ 'download',
109
+ 'download5doi',
110
+ 'downloader',
111
+ 'draw',
112
+ 'draw_time_range',
113
+ 'ending_record',
114
+ 'ensure_list',
115
+ 'extract',
116
+ 'fig_minus',
117
+ 'file_size',
118
+ 'find_file',
119
+ 'get',
120
+ 'get_days',
121
+ 'get_time_list',
122
+ 'get_ua',
123
+ 'get_var',
124
+ 'gif',
125
+ 'header_record',
126
+ 'how_to_use',
127
+ 'install_lib',
128
+ 'interp_2d',
129
+ 'interp_along_dim',
130
+ 'isel',
131
+ 'link_file',
132
+ 'log',
133
+ 'make_dir',
134
+ 'make_folder',
135
+ 'mask_shapefile',
136
+ 'mean_size',
137
+ 'merge',
138
+ 'modify',
139
+ 'query',
140
+ 'quiver',
141
+ 'remove',
142
+ 'remove_empty_folder',
143
+ 'rename',
144
+ 'rename_file',
145
+ 'save',
146
+ 'send',
147
+ 'show',
148
+ 'sign_in_love_ocean',
149
+ 'sign_in_meteorological_home',
150
+ 'sign_in_scientific_research',
151
+ 'tail_record',
152
+ 'test',
153
+ 'to_color',
154
+ 'upgrade_lib',
155
+ 'use'
156
+ ]
157
+ 同名函数:
158
+ ----------------------------------------
94
159
  模块全路径:
95
160
  oafuncs.oa_help.query
96
- 函数提示:
97
161
 
98
- description: 查看oafuncs模块的函数列表
99
- example: query()
162
+ Help on function query in module oafuncs.oa_help:
163
+
164
+ query()
165
+ Description:
166
+ Show the number of functions and the list of functions in the module.
167
+ Example:
168
+ query()
169
+
170
+ ----------------------------------------
100
171
  ```
101
172
 
102
173
  ## Structure
@@ -0,0 +1,131 @@
1
+ # oafuncs
2
+
3
+ ## Description
4
+
5
+ **Python Function**
6
+
7
+ ```text
8
+ In the field of geoscience, some commonly used and universal operations!
9
+
10
+ Just for the convenience of daily use, some complex operations are integrated into general functions.
11
+
12
+ The code will be optimized and updated from time to time, with additions, deletions, or modifications…
13
+
14
+ Existing functions will not be completely removed, they might just have a different function name, or the parameter passing might have been optimized…
15
+
16
+ Note: If there are any requirements, you can email to liukun0312@stu.ouc.edu.cn. Within my capabilities, I can consider implementing them.
17
+ ```
18
+
19
+ ## PyPI
20
+
21
+ ```html
22
+ https://pypi.org/project/oafuncs
23
+ ```
24
+
25
+ ## Github
26
+
27
+ ```html
28
+ https://github.com/Industry-Pays/OAFuncs
29
+ ```
30
+
31
+ ## Example
32
+
33
+ ```python
34
+ import oafuncs
35
+
36
+ # 查询当前所有可用函数
37
+ oafuncs.oa_help.query()
38
+ # 根据函数名获取使用方法
39
+ oafuncs.oa_help.use('query')
40
+ ```
41
+
42
+ ```shell
43
+ # 此小板块于2025/03/16更新,仅为示例,不代表最新情况
44
+ 函数数量:
45
+ 62
46
+ 函数列表:
47
+ [
48
+ 'MidpointNormalize',
49
+ 'ParallelExecutor',
50
+ 'add_cartopy',
51
+ 'add_gridlines',
52
+ 'add_lonlat_unit',
53
+ 'check',
54
+ 'clear_folder',
55
+ 'contour',
56
+ 'contourf',
57
+ 'convert_longitude',
58
+ 'copy_file',
59
+ 'create',
60
+ 'create_rgbtxt',
61
+ 'data_record',
62
+ 'download',
63
+ 'download5doi',
64
+ 'downloader',
65
+ 'draw',
66
+ 'draw_time_range',
67
+ 'ending_record',
68
+ 'ensure_list',
69
+ 'extract',
70
+ 'fig_minus',
71
+ 'file_size',
72
+ 'find_file',
73
+ 'get',
74
+ 'get_days',
75
+ 'get_time_list',
76
+ 'get_ua',
77
+ 'get_var',
78
+ 'gif',
79
+ 'header_record',
80
+ 'how_to_use',
81
+ 'install_lib',
82
+ 'interp_2d',
83
+ 'interp_along_dim',
84
+ 'isel',
85
+ 'link_file',
86
+ 'log',
87
+ 'make_dir',
88
+ 'make_folder',
89
+ 'mask_shapefile',
90
+ 'mean_size',
91
+ 'merge',
92
+ 'modify',
93
+ 'query',
94
+ 'quiver',
95
+ 'remove',
96
+ 'remove_empty_folder',
97
+ 'rename',
98
+ 'rename_file',
99
+ 'save',
100
+ 'send',
101
+ 'show',
102
+ 'sign_in_love_ocean',
103
+ 'sign_in_meteorological_home',
104
+ 'sign_in_scientific_research',
105
+ 'tail_record',
106
+ 'test',
107
+ 'to_color',
108
+ 'upgrade_lib',
109
+ 'use'
110
+ ]
111
+ 同名函数:
112
+ ----------------------------------------
113
+ 模块全路径:
114
+ oafuncs.oa_help.query
115
+
116
+ Help on function query in module oafuncs.oa_help:
117
+
118
+ query()
119
+ Description:
120
+ Show the number of functions and the list of functions in the module.
121
+ Example:
122
+ query()
123
+
124
+ ----------------------------------------
125
+ ```
126
+
127
+ ## Structure
128
+
129
+ <img title="" src="./oafuncs/data_store/OAFuncs.png" alt="">
130
+
131
+ <img title="OAFuncs" src="https://raw.githubusercontent.com/Industry-Pays/OAFuncs/main/oafuncs/data_store/OAFuncs.png" alt="OAFuncs">
@@ -0,0 +1,299 @@
1
+ import os
2
+ from typing import Optional, Tuple
3
+
4
+ import matplotlib as mpl
5
+
6
+ mpl.use("Agg") # Use non-interactive backend
7
+
8
+ import cftime
9
+ import matplotlib.pyplot as plt
10
+ import numpy as np
11
+ from rich import print
12
+ import cartopy.crs as ccrs
13
+ import xarray as xr
14
+
15
+ import oafuncs
16
+
17
+
18
+ def plot_1d(data: xr.DataArray, output_path: str, x_dim: str, y_dim: str, z_dim: str, t_dim: str) -> None:
19
+ """Plot 1D data."""
20
+ plt.figure(figsize=(10, 6))
21
+
22
+ # Handle time dimension
23
+ if t_dim in data.dims and isinstance(data[t_dim].values[0], cftime.datetime):
24
+ try:
25
+ data[t_dim] = data.indexes[t_dim].to_datetimeindex()
26
+ except (AttributeError, ValueError, TypeError) as e:
27
+ print(f"Warning: Could not convert {t_dim} to datetime index: {e}")
28
+
29
+ # Determine X axis data
30
+ x, x_label = determine_x_axis(data, x_dim, y_dim, z_dim, t_dim)
31
+
32
+ y = data.values
33
+ plt.plot(x, y, linewidth=2)
34
+
35
+ # Add chart info
36
+ long_name = getattr(data, "long_name", "No long_name")
37
+ units = getattr(data, "units", "")
38
+ plt.title(f"{data.name} | {long_name}", fontsize=12)
39
+ plt.xlabel(x_label)
40
+ plt.ylabel(f"{data.name} ({units})" if units else data.name)
41
+
42
+ plt.grid(True, linestyle="--", alpha=0.7)
43
+ plt.tight_layout()
44
+
45
+ # Save image
46
+ os.makedirs(os.path.dirname(output_path), exist_ok=True)
47
+ plt.savefig(output_path, bbox_inches="tight", dpi=600)
48
+ plt.clf()
49
+ plt.close()
50
+
51
+
52
+ def determine_x_axis(data: xr.DataArray, x_dim: str, y_dim: str, z_dim: str, t_dim: str) -> Tuple[np.ndarray, str]:
53
+ """Determine the X axis data and label."""
54
+ if x_dim in data.dims:
55
+ return data[x_dim].values, x_dim
56
+ elif y_dim in data.dims:
57
+ return data[y_dim].values, y_dim
58
+ elif z_dim in data.dims:
59
+ return data[z_dim].values, z_dim
60
+ elif t_dim in data.dims:
61
+ return data[t_dim].values, t_dim
62
+ else:
63
+ return np.arange(len(data)), "Index"
64
+
65
+
66
+ def plot_2d(data: xr.DataArray, output_path: str, data_range: Optional[Tuple[float, float]], x_dim: str, y_dim: str, t_dim: str, plot_type: str) -> bool:
67
+ """Plot 2D data."""
68
+ if x_dim in data.dims and y_dim in data.dims and x_dim.lower() in ["lon", "longitude"] and y_dim.lower() in ["lat", "latitude"]:
69
+ lon_range = data[x_dim].values
70
+ lat_range = data[y_dim].values
71
+ lon_lat_ratio = np.abs(np.max(lon_range) - np.min(lon_range)) / (np.max(lat_range) - np.min(lat_range))
72
+ figsize = (10, 10 / lon_lat_ratio)
73
+ fig, ax = plt.subplots(figsize=figsize, subplot_kw={"projection": ccrs.PlateCarree()})
74
+ oafuncs.oa_draw.add_cartopy(ax, lon_range, lat_range)
75
+ else:
76
+ fig, ax = plt.subplots(figsize=(10, 8))
77
+
78
+ # Handle time dimension
79
+ if t_dim in data.dims and isinstance(data[t_dim].values[0], cftime.datetime):
80
+ try:
81
+ data[t_dim] = data.indexes[t_dim].to_datetimeindex()
82
+ except (AttributeError, ValueError, TypeError) as e:
83
+ print(f"Warning: Could not convert {t_dim} to datetime index: {e}")
84
+
85
+ # Check for valid data
86
+ if np.all(np.isnan(data.values)) or data.size == 0:
87
+ print(f"Skipping {data.name}: All values are NaN or empty")
88
+ plt.close()
89
+ return False
90
+
91
+ data_range = calculate_data_range(data, data_range)
92
+
93
+ if data_range is None:
94
+ print(f"Skipping {data.name} due to all NaN values")
95
+ plt.close()
96
+ return False
97
+
98
+ # Select appropriate colormap and levels
99
+ cmap, norm, levels = select_colormap_and_levels(data_range, plot_type)
100
+
101
+ mappable = None
102
+ try:
103
+ if plot_type == "contourf":
104
+ if np.ptp(data.values) < 1e-10 and not np.all(np.isnan(data.values)):
105
+ print(f"Warning: {data.name} has very little variation. Using imshow instead.")
106
+ mappable = ax.imshow(data.values, cmap=cmap, aspect="auto", interpolation="none")
107
+ colorbar = plt.colorbar(mappable, ax=ax)
108
+ else:
109
+ mappable = ax.contourf(data[x_dim], data[y_dim], data.values, levels=levels, cmap=cmap, norm=norm)
110
+ colorbar = plt.colorbar(mappable, ax=ax)
111
+ elif plot_type == "contour":
112
+ if np.ptp(data.values) < 1e-10 and not np.all(np.isnan(data.values)):
113
+ print(f"Warning: {data.name} has very little variation. Using imshow instead.")
114
+ mappable = ax.imshow(data.values, cmap=cmap, aspect="auto", interpolation="none")
115
+ colorbar = plt.colorbar(mappable, ax=ax)
116
+ else:
117
+ mappable = ax.contour(data[x_dim], data[y_dim], data.values, levels=levels, cmap=cmap, norm=norm)
118
+ ax.clabel(mappable, inline=True, fontsize=8, fmt="%1.1f")
119
+ colorbar = plt.colorbar(mappable, ax=ax)
120
+ except (ValueError, TypeError) as e:
121
+ print(f"Warning: Could not plot with specified parameters: {e}. Trying simplified parameters.")
122
+ try:
123
+ mappable = data.plot(ax=ax, cmap=cmap, add_colorbar=False)
124
+ colorbar = plt.colorbar(mappable, ax=ax)
125
+ except Exception as e2:
126
+ print(f"Error plotting {data.name}: {e2}")
127
+ plt.figure(figsize=(10, 8))
128
+ mappable = ax.imshow(data.values, cmap="viridis", aspect="auto")
129
+ colorbar = plt.colorbar(mappable, ax=ax, label=getattr(data, "units", ""))
130
+ plt.title(f"{data.name} | {getattr(data, 'long_name', 'No long_name')} (basic plot)", fontsize=12)
131
+ plt.tight_layout()
132
+ os.makedirs(os.path.dirname(output_path), exist_ok=True)
133
+ plt.savefig(output_path, bbox_inches="tight", dpi=600)
134
+ plt.close()
135
+ return True
136
+
137
+ plt.title(f"{data.name} | {getattr(data, 'long_name', 'No long_name')}", fontsize=12)
138
+ units = getattr(data, "units", "")
139
+ if units and colorbar:
140
+ colorbar.set_label(units)
141
+
142
+ plt.tight_layout()
143
+ os.makedirs(os.path.dirname(output_path), exist_ok=True)
144
+ plt.savefig(output_path, bbox_inches="tight", dpi=600)
145
+ plt.close()
146
+ return True
147
+
148
+
149
+ def calculate_data_range(data: xr.DataArray, data_range: Optional[Tuple[float, float]]) -> Optional[Tuple[float, float]]:
150
+ """Calculate the data range, ignoring extreme outliers."""
151
+ if data_range is None:
152
+ flat_data = data.values.flatten()
153
+ if flat_data.size == 0:
154
+ return None
155
+ valid_data = flat_data[~np.isnan(flat_data)]
156
+ if len(valid_data) == 0:
157
+ return None
158
+ low, high = np.percentile(valid_data, [0.5, 99.5])
159
+ filtered_data = valid_data[(valid_data >= low) & (valid_data <= high)]
160
+ if len(filtered_data) > 0:
161
+ data_range = (np.min(filtered_data), np.max(filtered_data))
162
+ else:
163
+ data_range = (np.nanmin(valid_data), np.nanmax(valid_data))
164
+ if abs(data_range[1] - data_range[0]) < 1e-10:
165
+ mean = (data_range[0] + data_range[1]) / 2
166
+ data_range = (mean - 1e-10 if mean != 0 else -1e-10, mean + 1e-10 if mean != 0 else 1e-10)
167
+ return data_range
168
+
169
+
170
+ def select_colormap_and_levels(data_range: Tuple[float, float], plot_type: str) -> Tuple[mpl.colors.Colormap, mpl.colors.Normalize, np.ndarray]:
171
+ """Select colormap and levels based on data range."""
172
+ if plot_type == "contour":
173
+ # For contour plots, use fewer levels
174
+ num_levels = 10
175
+ else:
176
+ # For filled contour plots, use more levels
177
+ num_levels = 128
178
+
179
+ if data_range[0] * data_range[1] < 0:
180
+ cmap = oafuncs.oa_cmap.get("diverging_1")
181
+ bdy = max(abs(data_range[0]), abs(data_range[1]))
182
+ norm = mpl.colors.TwoSlopeNorm(vmin=-bdy, vcenter=0, vmax=bdy)
183
+ levels = np.linspace(-bdy, bdy, num_levels)
184
+ else:
185
+ cmap = oafuncs.oa_cmap.get("cool_1") if data_range[0] < 0 else oafuncs.oa_cmap.get("warm_1")
186
+ norm = mpl.colors.Normalize(vmin=data_range[0], vmax=data_range[1])
187
+ levels = np.linspace(data_range[0], data_range[1], num_levels)
188
+
189
+ if np.any(np.diff(levels) <= 0):
190
+ levels = np.linspace(data_range[0], data_range[1], 10)
191
+ return cmap, norm, levels
192
+
193
+
194
+ def process_variable(var: str, data: xr.DataArray, dims: int, dims_name: Tuple[str, ...], output_dir: str, x_dim: str, y_dim: str, z_dim: str, t_dim: str, fixed_colorscale: bool, plot_type: str) -> None:
195
+ """Process a single variable."""
196
+ valid_dims = {x_dim, y_dim, z_dim, t_dim}
197
+ if not set(dims_name).issubset(valid_dims):
198
+ print(f"Skipping {var} due to unsupported dimensions: {dims_name}")
199
+ return
200
+
201
+ # Process 1D data
202
+ if dims == 1:
203
+ if np.issubdtype(data.dtype, np.character):
204
+ print(f"Skipping {var} due to character data type")
205
+ return
206
+ plot_1d(data, os.path.join(output_dir, f"{var}.png"), x_dim, y_dim, z_dim, t_dim)
207
+ print(f"{var}.png")
208
+ return
209
+
210
+ # Compute global data range for fixed colorscale
211
+ global_data_range = None
212
+ if dims >= 2 and fixed_colorscale:
213
+ global_data_range = calculate_data_range(data, None)
214
+ if global_data_range is None:
215
+ print(f"Skipping {var} due to no valid data")
216
+ return
217
+ print(f"Fixed colorscale range: {global_data_range}")
218
+
219
+ # Process 2D data
220
+ if dims == 2:
221
+ success = plot_2d(data, os.path.join(output_dir, f"{var}.png"), global_data_range, x_dim, y_dim, t_dim, plot_type)
222
+ if success:
223
+ print(f"{var}.png")
224
+
225
+ # Process 3D data
226
+ if dims == 3:
227
+ for i in range(data.shape[0]):
228
+ for attempt in range(10):
229
+ try:
230
+ if data[i].values.size == 0:
231
+ print(f"Skipped {var}_{dims_name[0]}-{i} (empty data)")
232
+ break
233
+ success = plot_2d(data[i], os.path.join(output_dir, f"{var}_{dims_name[0]}-{i}.png"), global_data_range, x_dim, y_dim, t_dim, plot_type)
234
+ if success:
235
+ print(f"{var}_{dims_name[0]}-{i}.png")
236
+ else:
237
+ print(f"Skipped {var}_{dims_name[0]}-{i} (invalid data)")
238
+ break
239
+ except Exception as e:
240
+ if attempt < 9:
241
+ print(f"Retrying {var}_{dims_name[0]}-{i} (attempt {attempt + 1})")
242
+ else:
243
+ print(f"Error processing {var}_{dims_name[0]}-{i}: {e}")
244
+
245
+ # Process 4D data
246
+ if dims == 4:
247
+ for i in range(data.shape[0]):
248
+ for j in range(data.shape[1]):
249
+ for attempt in range(3):
250
+ try:
251
+ if data[i, j].values.size == 0:
252
+ print(f"Skipped {var}_{dims_name[0]}-{i}_{dims_name[1]}-{j} (empty data)")
253
+ break
254
+ success = plot_2d(data[i, j], os.path.join(output_dir, f"{var}_{dims_name[0]}-{i}_{dims_name[1]}-{j}.png"), global_data_range, x_dim, y_dim, t_dim, plot_type)
255
+ if success:
256
+ print(f"{var}_{dims_name[0]}-{i}_{dims_name[1]}-{j}.png")
257
+ else:
258
+ print(f"Skipped {var}_{dims_name[0]}-{i}_{dims_name[1]}-{j} (invalid data)")
259
+ break
260
+ except Exception as e:
261
+ if attempt < 2:
262
+ print(f"Retrying {var}_{dims_name[0]}-{i}_{dims_name[1]}-{j} (attempt {attempt + 1})")
263
+ else:
264
+ print(f"Error processing {var}_{dims_name[0]}-{i}_{dims_name[1]}-{j}: {e}")
265
+
266
+
267
+ def func_plot_dataset(ds_in: xr.Dataset, output_dir: str, xyzt_dims: Tuple[str, str, str, str] = ("longitude", "latitude", "level", "time"), plot_type: str = "contourf", fixed_colorscale: bool = False) -> None:
268
+ """Plot variables from a NetCDF file and save the plots to the specified directory."""
269
+ os.makedirs(output_dir, exist_ok=True)
270
+ x_dim, y_dim, z_dim, t_dim = xyzt_dims
271
+
272
+ # Main processing function
273
+ try:
274
+ ds = ds_in
275
+ varlist = list(ds.data_vars)
276
+ print(f"Found {len(varlist)} variables in dataset")
277
+
278
+ for var in varlist:
279
+ print("=" * 120)
280
+ print(f"Processing: {var}")
281
+ data = ds[var]
282
+ dims = len(data.shape)
283
+ dims_name = data.dims
284
+ try:
285
+ process_variable(var, data, dims, dims_name, output_dir, x_dim, y_dim, z_dim, t_dim, fixed_colorscale, plot_type)
286
+ except Exception as e:
287
+ print(f"Error processing variable {var}: {e}")
288
+
289
+ except Exception as e:
290
+ print(f"Error processing dataset: {e}")
291
+ finally:
292
+ if "ds" in locals():
293
+ ds.close()
294
+ print("Dataset closed")
295
+
296
+
297
+ if __name__ == "__main__":
298
+ pass
299
+ # func_plot_dataset(ds, output_dir, xyzt_dims=("longitude", "latitude", "level", "time"), plot_type="contourf", fixed_colorscale=False)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: oafuncs
3
- Version: 0.0.97.2
3
+ Version: 0.0.97.4
4
4
  Summary: Oceanic and Atmospheric Functions
5
5
  Home-page: https://github.com/Industry-Pays/OAFuncs
6
6
  Author: Kun Liu
@@ -86,17 +86,88 @@ oafuncs.oa_help.use('query')
86
86
  ```
87
87
 
88
88
  ```shell
89
- # 此小板块于2024/12/26更新,仅为示例,不代表最新情况
89
+ # 此小板块于2025/03/16更新,仅为示例,不代表最新情况
90
90
  函数数量:
91
- 49
91
+ 62
92
92
  函数列表:
93
- ['MidpointNormalize', 'add_cartopy', 'add_gridlines', 'add_lonlat_unit', 'check_ncfile', 'choose_cmap', 'clear_folder', 'cmap2colors', 'convert_longitude', 'copy_file', 'create_cmap', 'create_cmap_rgbtxt', 'create_gif', 'download', 'download5doi', 'draw_time_range', 'extract5nc', 'fig_minus', 'file_size', 'find_file', 'get_time_list', 'get_ua', 'get_var', 'how_to_use', 'install_lib', 'interp_2d', 'link_file', 'make_folder', 'merge5nc', 'modify_var_attr', 'modify_var_value', 'nc_isel', 'plot_contourf', 'plot_contourf_cartopy', 'plot_contourf_lonlat', 'plot_quiver', 'query', 'remove', 'remove_empty_folder', 'rename_file', 'rename_var_or_dim', 'send', 'show', 'sign_in_love_ocean', 'sign_in_meteorological_home', 'sign_in_scientific_research', 'upgrade_lib', 'use', 'write2nc']
93
+ [
94
+ 'MidpointNormalize',
95
+ 'ParallelExecutor',
96
+ 'add_cartopy',
97
+ 'add_gridlines',
98
+ 'add_lonlat_unit',
99
+ 'check',
100
+ 'clear_folder',
101
+ 'contour',
102
+ 'contourf',
103
+ 'convert_longitude',
104
+ 'copy_file',
105
+ 'create',
106
+ 'create_rgbtxt',
107
+ 'data_record',
108
+ 'download',
109
+ 'download5doi',
110
+ 'downloader',
111
+ 'draw',
112
+ 'draw_time_range',
113
+ 'ending_record',
114
+ 'ensure_list',
115
+ 'extract',
116
+ 'fig_minus',
117
+ 'file_size',
118
+ 'find_file',
119
+ 'get',
120
+ 'get_days',
121
+ 'get_time_list',
122
+ 'get_ua',
123
+ 'get_var',
124
+ 'gif',
125
+ 'header_record',
126
+ 'how_to_use',
127
+ 'install_lib',
128
+ 'interp_2d',
129
+ 'interp_along_dim',
130
+ 'isel',
131
+ 'link_file',
132
+ 'log',
133
+ 'make_dir',
134
+ 'make_folder',
135
+ 'mask_shapefile',
136
+ 'mean_size',
137
+ 'merge',
138
+ 'modify',
139
+ 'query',
140
+ 'quiver',
141
+ 'remove',
142
+ 'remove_empty_folder',
143
+ 'rename',
144
+ 'rename_file',
145
+ 'save',
146
+ 'send',
147
+ 'show',
148
+ 'sign_in_love_ocean',
149
+ 'sign_in_meteorological_home',
150
+ 'sign_in_scientific_research',
151
+ 'tail_record',
152
+ 'test',
153
+ 'to_color',
154
+ 'upgrade_lib',
155
+ 'use'
156
+ ]
157
+ 同名函数:
158
+ ----------------------------------------
94
159
  模块全路径:
95
160
  oafuncs.oa_help.query
96
- 函数提示:
97
161
 
98
- description: 查看oafuncs模块的函数列表
99
- example: query()
162
+ Help on function query in module oafuncs.oa_help:
163
+
164
+ query()
165
+ Description:
166
+ Show the number of functions and the list of functions in the module.
167
+ Example:
168
+ query()
169
+
170
+ ----------------------------------------
100
171
  ```
101
172
 
102
173
  ## Structure
@@ -15,8 +15,9 @@ oafuncs.egg-info/SOURCES.txt
15
15
  oafuncs.egg-info/dependency_links.txt
16
16
  oafuncs.egg-info/requires.txt
17
17
  oafuncs.egg-info/top_level.txt
18
- oafuncs/data_store/OAFuncs.png
19
- oafuncs/data_store/hycom_3hourly.png
18
+ oafuncs/_data/OAFuncs.png
19
+ oafuncs/_data/hycom_3hourly.png
20
+ oafuncs/_script/plot_dataset.py
20
21
  oafuncs/oa_down/User_Agent-list.txt
21
22
  oafuncs/oa_down/__init__.py
22
23
  oafuncs/oa_down/hycom_3hourly.py
@@ -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.97.2" # 下次用98.0,98.1已经被用过了
21
+ VERSION = "0.0.97.4" # 下次用98.0,98.1已经被用过了
22
22
 
23
23
  # What packages are required for this module to be executed?
24
24
  REQUIRED = [
@@ -117,8 +117,14 @@ class UploadCommand(Command):
117
117
  # 确保包含所有包
118
118
  packages = find_packages(exclude=["tests", "*.tests", "*.tests.*", "tests.*"])
119
119
  # 显式添加 data_store 目录
120
- if "oafuncs.data_store" not in packages:
121
- packages.append("oafuncs.data_store")
120
+ # 若添加,还是会被显示为包,但其函数不会被直接显示(应该也可调用)
121
+ # 要完全隐藏,但同时包含其py脚本和函数,试试在MANIFEST.in中添加
122
+ # 同一级不写__init__.py,但是在MANIFEST.in中写入,就不会显示函数
123
+ # if "oafuncs.data_store" not in packages:
124
+ # packages.append("oafuncs.data_store")
125
+
126
+ # if "oafuncs._nc_script" not in packages:
127
+ # packages.append("oafuncs._nc_script")
122
128
 
123
129
  # Where the magic happens:
124
130
  setup(
@@ -1,4 +0,0 @@
1
- include LICENSE.txt
2
- include README.md
3
- recursive-include oafuncs/data_store *
4
- recursive-include oafuncs/oa_down *.txt
@@ -1,60 +0,0 @@
1
- # oafuncs
2
-
3
- ## Description
4
-
5
- **Python Function**
6
-
7
- ```text
8
- In the field of geoscience, some commonly used and universal operations!
9
-
10
- Just for the convenience of daily use, some complex operations are integrated into general functions.
11
-
12
- The code will be optimized and updated from time to time, with additions, deletions, or modifications…
13
-
14
- Existing functions will not be completely removed, they might just have a different function name, or the parameter passing might have been optimized…
15
-
16
- Note: If there are any requirements, you can email to liukun0312@stu.ouc.edu.cn. Within my capabilities, I can consider implementing them.
17
- ```
18
-
19
- ## PyPI
20
-
21
- ```html
22
- https://pypi.org/project/oafuncs
23
- ```
24
-
25
- ## Github
26
-
27
- ```html
28
- https://github.com/Industry-Pays/OAFuncs
29
- ```
30
-
31
- ## Example
32
-
33
- ```python
34
- import oafuncs
35
-
36
- # 查询当前所有可用函数
37
- oafuncs.oa_help.query()
38
- # 根据函数名获取使用方法
39
- oafuncs.oa_help.use('query')
40
- ```
41
-
42
- ```shell
43
- # 此小板块于2024/12/26更新,仅为示例,不代表最新情况
44
- 函数数量:
45
- 49
46
- 函数列表:
47
- ['MidpointNormalize', 'add_cartopy', 'add_gridlines', 'add_lonlat_unit', 'check_ncfile', 'choose_cmap', 'clear_folder', 'cmap2colors', 'convert_longitude', 'copy_file', 'create_cmap', 'create_cmap_rgbtxt', 'create_gif', 'download', 'download5doi', 'draw_time_range', 'extract5nc', 'fig_minus', 'file_size', 'find_file', 'get_time_list', 'get_ua', 'get_var', 'how_to_use', 'install_lib', 'interp_2d', 'link_file', 'make_folder', 'merge5nc', 'modify_var_attr', 'modify_var_value', 'nc_isel', 'plot_contourf', 'plot_contourf_cartopy', 'plot_contourf_lonlat', 'plot_quiver', 'query', 'remove', 'remove_empty_folder', 'rename_file', 'rename_var_or_dim', 'send', 'show', 'sign_in_love_ocean', 'sign_in_meteorological_home', 'sign_in_scientific_research', 'upgrade_lib', 'use', 'write2nc']
48
- 模块全路径:
49
- oafuncs.oa_help.query
50
- 函数提示:
51
-
52
- description: 查看oafuncs模块的函数列表
53
- example: query()
54
- ```
55
-
56
- ## Structure
57
-
58
- <img title="" src="./oafuncs/data_store/OAFuncs.png" alt="">
59
-
60
- <img title="OAFuncs" src="https://raw.githubusercontent.com/Industry-Pays/OAFuncs/main/oafuncs/data_store/OAFuncs.png" alt="OAFuncs">
File without changes
File without changes
File without changes