oafuncs 0.0.97.15__py3-none-any.whl → 0.0.97.17__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 +42 -20
- oafuncs/_script/netcdf_modify.py +10 -2
- oafuncs/oa_cmap.py +211 -95
- oafuncs/oa_data.py +157 -218
- oafuncs/oa_date.py +71 -37
- oafuncs/oa_down/hycom_3hourly.py +209 -320
- oafuncs/oa_down/hycom_3hourly_20250407.py +1295 -0
- oafuncs/oa_down/idm.py +4 -4
- oafuncs/oa_draw.py +224 -124
- oafuncs/oa_file.py +279 -333
- oafuncs/oa_help.py +10 -0
- oafuncs/oa_nc.py +197 -164
- oafuncs/oa_python.py +51 -25
- oafuncs/oa_tool.py +84 -48
- {oafuncs-0.0.97.15.dist-info → oafuncs-0.0.97.17.dist-info}/METADATA +1 -1
- {oafuncs-0.0.97.15.dist-info → oafuncs-0.0.97.17.dist-info}/RECORD +20 -19
- /oafuncs/_script/{replace_file_concent.py → replace_file_content.py} +0 -0
- {oafuncs-0.0.97.15.dist-info → oafuncs-0.0.97.17.dist-info}/WHEEL +0 -0
- {oafuncs-0.0.97.15.dist-info → oafuncs-0.0.97.17.dist-info}/licenses/LICENSE.txt +0 -0
- {oafuncs-0.0.97.15.dist-info → oafuncs-0.0.97.17.dist-info}/top_level.txt +0 -0
oafuncs/oa_down/idm.py
CHANGED
@@ -4,7 +4,7 @@
|
|
4
4
|
Author: Liu Kun && 16031215@qq.com
|
5
5
|
Date: 2025-03-27 16:51:26
|
6
6
|
LastEditors: Liu Kun && 16031215@qq.com
|
7
|
-
LastEditTime: 2025-04-
|
7
|
+
LastEditTime: 2025-04-07 13:38:27
|
8
8
|
FilePath: \\Python\\My_Funcs\\OAFuncs\\oafuncs\\oa_down\\idm.py
|
9
9
|
Description:
|
10
10
|
EditPlatform: vscode
|
@@ -14,6 +14,7 @@ Python Version: 3.12
|
|
14
14
|
"""
|
15
15
|
|
16
16
|
|
17
|
+
|
17
18
|
import datetime
|
18
19
|
import os
|
19
20
|
from subprocess import call
|
@@ -46,12 +47,11 @@ def downloader(task_url, folder_path, file_name, idm_engine=r"D:\Programs\Intern
|
|
46
47
|
call([idm_engine, "/d", task_url, "/p", folder_path, "/f", file_name, "/a"])
|
47
48
|
# 开始任务队列
|
48
49
|
call([idm_engine, "/s"])
|
49
|
-
# print(f"IDM下载器:{file_name}下载任务已添加至队列...")
|
50
50
|
# print("[purple]-" * 150 + f"\n{datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n" + "[purple]-" * 150)
|
51
51
|
print("[purple]*" * 100)
|
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
|
-
print(f"[green]IDM Downloader: {file_name}
|
55
|
+
print(f"[green]IDM Downloader: {file_name}[/green]".center(100, " "))
|
56
56
|
print("[purple]*" * 100)
|
57
|
-
print("\n")
|
57
|
+
# print("\n")
|
oafuncs/oa_draw.py
CHANGED
@@ -28,65 +28,75 @@ __all__ = ["fig_minus", "gif", "add_cartopy", "add_gridlines", "MidpointNormaliz
|
|
28
28
|
warnings.filterwarnings("ignore")
|
29
29
|
|
30
30
|
|
31
|
-
def fig_minus(
|
32
|
-
"""
|
33
|
-
|
31
|
+
def fig_minus(x_axis: plt.Axes = None, y_axis: plt.Axes = None, colorbar: mpl.colorbar.Colorbar = None, decimal_places: int = None, add_spacing: bool = False) -> plt.Axes | mpl.colorbar.Colorbar | None:
|
32
|
+
"""Replace negative signs with minus signs in axis tick labels.
|
33
|
+
|
34
|
+
Args:
|
35
|
+
x_axis (plt.Axes, optional): Matplotlib x-axis object to modify.
|
36
|
+
y_axis (plt.Axes, optional): Matplotlib y-axis object to modify.
|
37
|
+
colorbar (mpl.colorbar.Colorbar, optional): Matplotlib colorbar object to modify.
|
38
|
+
decimal_places (int, optional): Number of decimal places to display.
|
39
|
+
add_spacing (bool, optional): Whether to add spaces before non-negative numbers.
|
34
40
|
|
35
|
-
|
36
|
-
|
37
|
-
param {*} cbar : colorbar
|
38
|
-
param {*} decimal : 小数位数
|
39
|
-
param {*} add_space : 是否在非负数前面加空格
|
41
|
+
Returns:
|
42
|
+
plt.Axes | mpl.colorbar.Colorbar | None: The modified axis or colorbar object.
|
40
43
|
|
41
|
-
|
44
|
+
Example:
|
45
|
+
>>> fig_minus(x_axis=ax, y_axis=None, colorbar=colorbar, decimal_places=2, add_spacing=True)
|
42
46
|
"""
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
47
|
+
# Determine which object to use and get its ticks
|
48
|
+
if x_axis is not None:
|
49
|
+
current_ticks = x_axis.get_xticks()
|
50
|
+
if y_axis is not None:
|
51
|
+
current_ticks = y_axis.get_yticks()
|
52
|
+
if colorbar is not None:
|
53
|
+
current_ticks = colorbar.get_ticks()
|
54
|
+
|
55
|
+
# Find index for adding space to non-negative values if needed
|
56
|
+
if add_spacing:
|
51
57
|
index = 0
|
52
|
-
for
|
58
|
+
for i, tick in enumerate(current_ticks):
|
53
59
|
if tick >= 0:
|
54
|
-
index =
|
60
|
+
index = i
|
55
61
|
break
|
56
|
-
if decimal is not None:
|
57
|
-
# my_ticks = [(round(float(iii), decimal)) for iii in my_ticks]
|
58
|
-
current_ticks = [f"{val:.{decimal}f}" if val != 0 else "0" for val in current_ticks]
|
59
62
|
|
63
|
+
# Format according to decimal places if specified
|
64
|
+
if decimal_places is not None:
|
65
|
+
current_ticks = [f"{val:.{decimal_places}f}" if val != 0 else "0" for val in current_ticks]
|
66
|
+
|
67
|
+
# Replace negative signs with minus signs
|
60
68
|
out_ticks = [f"{val}".replace("-", "\u2212") for val in current_ticks]
|
61
|
-
|
62
|
-
|
69
|
+
|
70
|
+
# Add spaces before non-negative values if specified
|
71
|
+
if add_spacing:
|
63
72
|
out_ticks[index:] = [" " + m for m in out_ticks[index:]]
|
64
73
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
if
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
cbar.set_ticklabels(out_ticks)
|
73
|
-
return cbar
|
74
|
+
# Apply formatted ticks to the appropriate object
|
75
|
+
if x_axis is not None:
|
76
|
+
x_axis.set_xticklabels(out_ticks)
|
77
|
+
if y_axis is not None:
|
78
|
+
y_axis.set_yticklabels(out_ticks)
|
79
|
+
if colorbar is not None:
|
80
|
+
colorbar.set_ticklabels(out_ticks)
|
74
81
|
|
82
|
+
print("[green]Axis tick labels updated successfully.[/green]")
|
83
|
+
return x_axis or y_axis or colorbar
|
75
84
|
|
76
|
-
|
77
|
-
def gif(
|
78
|
-
"""
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
Returns
|
85
|
+
|
86
|
+
def gif(image_paths: list[str], output_gif_name: str, frame_duration: float = 200, resize_dimensions: tuple[int, int] = None) -> None:
|
87
|
+
"""Create a GIF from a list of images.
|
88
|
+
|
89
|
+
Args:
|
90
|
+
image_paths (list[str]): List of image file paths.
|
91
|
+
output_gif_name (str): Name of the output GIF file.
|
92
|
+
frame_duration (float): Duration of each frame in milliseconds.
|
93
|
+
resize_dimensions (tuple[int, int], optional): Resize dimensions (width, height). Defaults to None.
|
94
|
+
|
95
|
+
Returns:
|
87
96
|
None
|
88
|
-
|
89
|
-
|
97
|
+
|
98
|
+
Example:
|
99
|
+
>>> gif(['image1.png', 'image2.png'], 'output.gif', frame_duration=200, resize_dimensions=(800, 600))
|
90
100
|
"""
|
91
101
|
import imageio.v2 as imageio
|
92
102
|
import numpy as np
|
@@ -95,141 +105,231 @@ def gif(image_list: list[str], gif_name: str, duration: float = 200, resize: tup
|
|
95
105
|
frames = []
|
96
106
|
|
97
107
|
# 获取目标尺寸
|
98
|
-
if
|
108
|
+
if resize_dimensions is None and image_paths:
|
99
109
|
# 使用第一张图片的尺寸作为标准
|
100
|
-
with Image.open(
|
101
|
-
|
110
|
+
with Image.open(image_paths[0]) as img:
|
111
|
+
resize_dimensions = img.size
|
102
112
|
|
103
113
|
# 读取并调整所有图片的尺寸
|
104
|
-
for image_name in
|
114
|
+
for image_name in image_paths:
|
105
115
|
with Image.open(image_name) as img:
|
106
|
-
if
|
107
|
-
img = img.resize(
|
116
|
+
if resize_dimensions:
|
117
|
+
img = img.resize(resize_dimensions, Image.LANCZOS)
|
108
118
|
frames.append(np.array(img))
|
109
119
|
|
110
|
-
# 修改此处:明确使用
|
120
|
+
# 修改此处:明确使用 frame_duration 值,并将其作为每帧的持续时间(以秒为单位)
|
111
121
|
# 某些版本的 imageio 可能需要以毫秒为单位,或者使用 fps 参数
|
112
122
|
try:
|
113
|
-
# 先尝试直接使用
|
114
|
-
imageio.mimsave(
|
123
|
+
# 先尝试直接使用 frame_duration 参数(以秒为单位)
|
124
|
+
imageio.mimsave(output_gif_name, frames, format="GIF", duration=frame_duration)
|
115
125
|
except Exception as e:
|
116
|
-
print(f"
|
117
|
-
# 如果失败,尝试使用 fps 参数(fps = 1/
|
118
|
-
fps = 1.0 /
|
119
|
-
imageio.mimsave(
|
126
|
+
print(f"[yellow]Warning:[/yellow] Attempting to use fps parameter instead of duration: {e}")
|
127
|
+
# 如果失败,尝试使用 fps 参数(fps = 1/frame_duration)
|
128
|
+
fps = 1.0 / frame_duration if frame_duration > 0 else 5.0
|
129
|
+
imageio.mimsave(output_gif_name, frames, format="GIF", fps=fps)
|
120
130
|
|
121
|
-
print(f"
|
131
|
+
print(f"[green]GIF created successfully![/green] Size: {resize_dimensions}, Frame interval: {frame_duration} ms")
|
122
132
|
return
|
123
133
|
|
124
134
|
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
135
|
+
def add_lonlat_unit(longitudes: list[float] = None, latitudes: list[float] = None, decimal_places: int = 2) -> tuple[list[str], list[str]] | list[str]:
|
136
|
+
"""Convert longitude and latitude values to formatted string labels.
|
137
|
+
|
138
|
+
Args:
|
139
|
+
longitudes (list[float], optional): List of longitude values to format.
|
140
|
+
latitudes (list[float], optional): List of latitude values to format.
|
141
|
+
decimal_places (int, optional): Number of decimal places to display. Defaults to 2.
|
142
|
+
|
143
|
+
Returns:
|
144
|
+
tuple[list[str], list[str]] | list[str]: Formatted longitude and/or latitude labels.
|
145
|
+
Returns a tuple of two lists if both longitudes and latitudes are provided,
|
146
|
+
otherwise returns a single list of formatted values.
|
147
|
+
|
148
|
+
Examples:
|
149
|
+
>>> add_lonlat_unit(longitudes=[120, 180], latitudes=[30, 60], decimal_places=1)
|
150
|
+
(['120.0°E', '180.0°'], ['30.0°N', '60.0°N'])
|
151
|
+
>>> add_lonlat_unit(longitudes=[120, -60])
|
152
|
+
['120.00°E', '60.00°W']
|
133
153
|
"""
|
134
154
|
|
135
|
-
def _format_longitude(
|
155
|
+
def _format_longitude(longitude_values: list[float]) -> list[str] | str:
|
156
|
+
"""Format longitude values to string labels with directional indicators.
|
157
|
+
|
158
|
+
Converts numerical longitude values to formatted strings with degree symbols
|
159
|
+
and East/West indicators. Values outside the -180 to 180 range are normalized.
|
160
|
+
|
161
|
+
Args:
|
162
|
+
longitude_values: List of longitude values to format.
|
163
|
+
|
164
|
+
Returns:
|
165
|
+
List of formatted strings if input contains multiple values,
|
166
|
+
or a single string if input contains just one value.
|
167
|
+
"""
|
136
168
|
out_list = []
|
137
|
-
for x in
|
138
|
-
if x > 180:
|
139
|
-
x
|
140
|
-
|
141
|
-
|
169
|
+
for x in longitude_values:
|
170
|
+
if x > 180 or x < -180:
|
171
|
+
print(f"[yellow]Warning:[/yellow] Longitude value {x} outside normal range (-180 to 180)")
|
172
|
+
x = ((x + 180) % 360) - 180 # Normalize to -180 to 180 range
|
173
|
+
|
174
|
+
degrees = round(abs(x), decimal_places)
|
142
175
|
direction = "E" if x >= 0 else "W"
|
143
|
-
out_list.append(f"{degrees:.{
|
176
|
+
out_list.append(f"{degrees:.{decimal_places}f}°{direction}" if x != 0 and x != 180 else f"{degrees}°")
|
144
177
|
return out_list if len(out_list) > 1 else out_list[0]
|
145
178
|
|
146
|
-
def _format_latitude(
|
179
|
+
def _format_latitude(latitude_values: list[float]) -> list[str] | str:
|
180
|
+
"""Format latitude values to string labels with directional indicators.
|
181
|
+
|
182
|
+
Converts numerical latitude values to formatted strings with degree symbols
|
183
|
+
and North/South indicators. Values outside the -90 to 90 range are normalized.
|
184
|
+
|
185
|
+
Args:
|
186
|
+
latitude_values (list[float]): List of latitude values to format
|
187
|
+
|
188
|
+
Returns:
|
189
|
+
list[str] | str: List of formatted strings if input contains multiple values,
|
190
|
+
or a single string if input contains just one value
|
191
|
+
"""
|
147
192
|
out_list = []
|
148
|
-
for y in
|
149
|
-
if y > 90:
|
150
|
-
y
|
151
|
-
|
152
|
-
|
193
|
+
for y in latitude_values:
|
194
|
+
if y > 90 or y < -90:
|
195
|
+
print(f"[yellow]Warning:[/yellow] Latitude value {y} outside valid range (-90 to 90)")
|
196
|
+
y = min(max(y % 180 - 90, -90), 90) # Normalize to -90 to 90 range
|
197
|
+
|
198
|
+
degrees = round(abs(y), decimal_places)
|
153
199
|
direction = "N" if y >= 0 else "S"
|
154
|
-
out_list.append(f"{degrees:.{
|
200
|
+
out_list.append(f"{degrees:.{decimal_places}f}°{direction}" if y != 0 else f"{degrees}°")
|
155
201
|
return out_list if len(out_list) > 1 else out_list[0]
|
156
202
|
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
203
|
+
# Input validation
|
204
|
+
if longitudes is not None and not isinstance(longitudes, list):
|
205
|
+
longitudes = [longitudes] # Convert single value to list
|
206
|
+
if latitudes is not None and not isinstance(latitudes, list):
|
207
|
+
latitudes = [latitudes] # Convert single value to list
|
208
|
+
|
209
|
+
if longitudes and latitudes:
|
210
|
+
result = _format_longitude(longitudes), _format_latitude(latitudes)
|
211
|
+
elif longitudes:
|
212
|
+
result = _format_longitude(longitudes)
|
213
|
+
elif latitudes:
|
214
|
+
result = _format_latitude(latitudes)
|
215
|
+
else:
|
216
|
+
result = []
|
217
|
+
|
218
|
+
print("[green]Longitude and latitude values formatted successfully.[/green]")
|
219
|
+
return result
|
220
|
+
|
221
|
+
|
222
|
+
def add_gridlines(axes: plt.Axes, longitude_lines: list[float] = None, latitude_lines: list[float] = None, map_projection: ccrs.Projection = ccrs.PlateCarree(), line_color: str = "k", line_alpha: float = 0.5, line_style: str = "--", line_width: float = 0.5) -> tuple[plt.Axes, mpl.ticker.Locator]:
|
223
|
+
"""Add gridlines to a map.
|
224
|
+
|
225
|
+
Args:
|
226
|
+
axes (plt.Axes): The axes to add gridlines to.
|
227
|
+
longitude_lines (list[float], optional): List of longitude positions for gridlines.
|
228
|
+
latitude_lines (list[float], optional): List of latitude positions for gridlines.
|
229
|
+
map_projection (ccrs.Projection, optional): Coordinate reference system. Defaults to PlateCarree.
|
230
|
+
line_color (str, optional): Line color. Defaults to "k".
|
231
|
+
line_alpha (float, optional): Line transparency. Defaults to 0.5.
|
232
|
+
line_style (str, optional): Line style. Defaults to "--".
|
233
|
+
line_width (float, optional): Line width. Defaults to 0.5.
|
234
|
+
|
235
|
+
Returns:
|
236
|
+
tuple[plt.Axes, mpl.ticker.Locator]: The axes and gridlines objects.
|
163
237
|
|
164
|
-
|
165
|
-
|
166
|
-
|
238
|
+
Example:
|
239
|
+
>>> add_gridlines(axes, longitude_lines=[0, 30], latitude_lines=[-90, 90], map_projection=ccrs.PlateCarree())
|
240
|
+
>>> axes, gl = add_gridlines(axes, longitude_lines=[0, 30], latitude_lines=[-90, 90])
|
241
|
+
"""
|
167
242
|
from matplotlib import ticker as mticker
|
168
243
|
|
169
244
|
# add gridlines
|
170
|
-
gl =
|
245
|
+
gl = axes.gridlines(crs=map_projection, draw_labels=True, linewidth=line_width, color=line_color, alpha=line_alpha, linestyle=line_style)
|
171
246
|
gl.right_labels = False
|
172
247
|
gl.top_labels = False
|
173
248
|
gl.xformatter = LongitudeFormatter(zero_direction_label=False)
|
174
249
|
gl.yformatter = LatitudeFormatter()
|
175
250
|
|
176
|
-
if
|
177
|
-
gl.xlocator = mticker.FixedLocator(np.array(
|
178
|
-
if
|
179
|
-
gl.ylocator = mticker.FixedLocator(np.array(
|
251
|
+
if longitude_lines is not None:
|
252
|
+
gl.xlocator = mticker.FixedLocator(np.array(longitude_lines))
|
253
|
+
if latitude_lines is not None:
|
254
|
+
gl.ylocator = mticker.FixedLocator(np.array(latitude_lines))
|
255
|
+
|
256
|
+
print("[green]Gridlines added successfully.[/green]")
|
257
|
+
return axes, gl
|
180
258
|
|
181
|
-
return ax, gl
|
182
259
|
|
260
|
+
def add_cartopy(axes: plt.Axes, longitude_data: np.ndarray = None, latitude_data: np.ndarray = None, map_projection: ccrs.Projection = ccrs.PlateCarree(), show_gridlines: bool = True, land_color: str = "lightgrey", ocean_color: str = "lightblue", coastline_linewidth: float = 0.5) -> None:
|
261
|
+
"""Add cartopy features to a map.
|
183
262
|
|
184
|
-
|
185
|
-
|
263
|
+
Args:
|
264
|
+
axes (plt.Axes): The axes to add map features to.
|
265
|
+
longitude_data (np.ndarray, optional): Array of longitudes to set map extent.
|
266
|
+
latitude_data (np.ndarray, optional): Array of latitudes to set map extent.
|
267
|
+
map_projection (ccrs.Projection, optional): Coordinate reference system. Defaults to PlateCarree.
|
268
|
+
show_gridlines (bool, optional): Whether to add gridlines. Defaults to True.
|
269
|
+
land_color (str, optional): Color of land. Defaults to "lightgrey".
|
270
|
+
ocean_color (str, optional): Color of oceans. Defaults to "lightblue".
|
271
|
+
coastline_linewidth (float, optional): Line width for coastlines. Defaults to 0.5.
|
272
|
+
|
273
|
+
Returns:
|
274
|
+
None
|
275
|
+
|
276
|
+
Example:
|
277
|
+
>>> add_cartopy(axes, longitude_data=lon_data, latitude_data=lat_data, map_projection=ccrs.PlateCarree(), show_gridlines=True)
|
278
|
+
>>> axes = add_cartopy(axes, longitude_data=None, latitude_data=None, map_projection=ccrs.PlateCarree(), show_gridlines=False)
|
279
|
+
|
280
|
+
"""
|
186
281
|
# add coastlines
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
#
|
282
|
+
axes.add_feature(cfeature.LAND, facecolor=land_color)
|
283
|
+
axes.add_feature(cfeature.OCEAN, facecolor=ocean_color)
|
284
|
+
axes.add_feature(cfeature.COASTLINE, linewidth=coastline_linewidth)
|
285
|
+
# axes.add_feature(cfeature.BORDERS, linewidth=coastline_linewidth, linestyle=":")
|
191
286
|
|
192
287
|
# add gridlines
|
193
|
-
if
|
194
|
-
|
288
|
+
if show_gridlines:
|
289
|
+
axes, gl = add_gridlines(axes, map_projection=map_projection)
|
195
290
|
|
196
291
|
# set longitude and latitude format
|
197
292
|
lon_formatter = LongitudeFormatter(zero_direction_label=False)
|
198
293
|
lat_formatter = LatitudeFormatter()
|
199
|
-
|
200
|
-
|
294
|
+
axes.xaxis.set_major_formatter(lon_formatter)
|
295
|
+
axes.yaxis.set_major_formatter(lat_formatter)
|
201
296
|
|
202
297
|
# set extent
|
203
|
-
if
|
204
|
-
lon_min, lon_max = np.nanmin(
|
205
|
-
lat_min, lat_max = np.nanmin(
|
206
|
-
|
298
|
+
if longitude_data is not None and latitude_data is not None:
|
299
|
+
lon_min, lon_max = np.nanmin(longitude_data), np.nanmax(longitude_data)
|
300
|
+
lat_min, lat_max = np.nanmin(latitude_data), np.nanmax(latitude_data)
|
301
|
+
axes.set_extent([lon_min, lon_max, lat_min, lat_max], crs=map_projection)
|
302
|
+
|
303
|
+
print("[green]Cartopy features added successfully.[/green]")
|
304
|
+
return axes
|
207
305
|
|
208
306
|
|
209
|
-
# ** 自定义归一化类,使得0值处为中心点
|
210
307
|
class MidpointNormalize(mpl.colors.Normalize):
|
211
|
-
"""
|
212
|
-
Description: 自定义归一化类,使得0值处为中心点
|
308
|
+
"""Custom normalization class to center 0 value.
|
213
309
|
|
214
|
-
|
215
|
-
|
310
|
+
Args:
|
311
|
+
min_value (float, optional): Minimum data value. Defaults to None.
|
312
|
+
max_value (float, optional): Maximum data value. Defaults to None.
|
313
|
+
center_value (float, optional): Center value for normalization. Defaults to None.
|
314
|
+
clip_values (bool, optional): Whether to clip data outside the range. Defaults to False.
|
216
315
|
|
217
316
|
Example:
|
218
|
-
|
317
|
+
>>> norm = MidpointNormalize(min_value=-2, max_value=1, center_value=0)
|
219
318
|
"""
|
220
319
|
|
221
|
-
def __init__(self,
|
222
|
-
self.vcenter =
|
223
|
-
super().__init__(
|
320
|
+
def __init__(self, min_value: float = None, max_value: float = None, center_value: float = None, clip_values: bool = False) -> None:
|
321
|
+
self.vcenter = center_value
|
322
|
+
super().__init__(min_value, max_value, clip_values)
|
224
323
|
|
225
|
-
def __call__(self,
|
324
|
+
def __call__(self, input_values: np.ndarray, clip_values: bool = None) -> np.ma.MaskedArray:
|
226
325
|
x, y = [self.vmin, self.vcenter, self.vmax], [0, 0.5, 1.0]
|
227
|
-
return np.ma.masked_array(np.interp(
|
326
|
+
return np.ma.masked_array(np.interp(input_values, x, y, left=-np.inf, right=np.inf))
|
228
327
|
|
229
|
-
def inverse(self,
|
328
|
+
def inverse(self, normalized_values: np.ndarray) -> np.ndarray:
|
230
329
|
y, x = [self.vmin, self.vcenter, self.vmax], [0, 0.5, 1]
|
231
|
-
return np.interp(
|
330
|
+
return np.interp(normalized_values, x, y, left=-np.inf, right=np.inf)
|
232
331
|
|
332
|
+
# print("[green]Midpoint normalization applied successfully.[/green]")
|
233
333
|
|
234
334
|
|
235
335
|
if __name__ == "__main__":
|