skyborn 0.1.0__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.
- skyborn-0.1.0/PKG-INFO +28 -0
- skyborn-0.1.0/README.md +11 -0
- skyborn-0.1.0/setup.cfg +4 -0
- skyborn-0.1.0/setup.py +30 -0
- skyborn-0.1.0/src/skyborn/__init__.py +21 -0
- skyborn-0.1.0/src/skyborn/calculations.py +54 -0
- skyborn-0.1.0/src/skyborn/gradients.py +189 -0
- skyborn-0.1.0/src/skyborn/io.py +25 -0
- skyborn-0.1.0/src/skyborn/plotting.py +67 -0
- skyborn-0.1.0/src/skyborn.egg-info/PKG-INFO +28 -0
- skyborn-0.1.0/src/skyborn.egg-info/SOURCES.txt +12 -0
- skyborn-0.1.0/src/skyborn.egg-info/dependency_links.txt +1 -0
- skyborn-0.1.0/src/skyborn.egg-info/requires.txt +9 -0
- skyborn-0.1.0/src/skyborn.egg-info/top_level.txt +1 -0
skyborn-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
|
+
Name: skyborn
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Atmospheric science research utilities
|
|
5
|
+
Author: Qianye Su
|
|
6
|
+
Author-email: suqianye2000@gmail.com
|
|
7
|
+
License: MIT
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Requires-Dist: numpy>=1.20.0
|
|
12
|
+
Requires-Dist: xarray>=0.19.0
|
|
13
|
+
Requires-Dist: matplotlib>=3.4.0
|
|
14
|
+
Requires-Dist: cartopy>=0.20.0
|
|
15
|
+
Requires-Dist: netCDF4>=1.5.7
|
|
16
|
+
Requires-Dist: metpy>=1.1.0
|
|
17
|
+
Requires-Dist: cfgrib>=0.9.9
|
|
18
|
+
Requires-Dist: eccodes>=1.4.0
|
|
19
|
+
Requires-Dist: scikit-learn>=1.0.0
|
|
20
|
+
Dynamic: author
|
|
21
|
+
Dynamic: author-email
|
|
22
|
+
Dynamic: classifier
|
|
23
|
+
Dynamic: description
|
|
24
|
+
Dynamic: license
|
|
25
|
+
Dynamic: requires-dist
|
|
26
|
+
Dynamic: summary
|
|
27
|
+
|
|
28
|
+
Skyborn is a tool for easy plotting ERA5 weather data.
|
skyborn-0.1.0/README.md
ADDED
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Skyborn: A Collection of Tools for My Research
|
|
2
|
+
|
|
3
|
+
Skyborn is a collection of functions I use in my general research, primarily for personal use.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
To install the Skyborn package, you can use pip:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
pip install skyborn
|
|
11
|
+
```
|
skyborn-0.1.0/setup.cfg
ADDED
skyborn-0.1.0/setup.py
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import setuptools
|
|
2
|
+
|
|
3
|
+
setuptools.setup(
|
|
4
|
+
name="skyborn",
|
|
5
|
+
version="0.1.0", # 与pyproject.toml保持一致
|
|
6
|
+
author="Qianye Su",
|
|
7
|
+
author_email="suqianye2000@gmail.com",
|
|
8
|
+
description="Atmospheric science research utilities",
|
|
9
|
+
long_description="Skyborn is a tool for easy plotting ERA5 weather data.",
|
|
10
|
+
license="MIT",
|
|
11
|
+
packages=setuptools.find_packages(where="src"),
|
|
12
|
+
package_dir={"": "src"},
|
|
13
|
+
classifiers=[
|
|
14
|
+
"Programming Language :: Python :: 3",
|
|
15
|
+
"License :: OSI Approved :: MIT License",
|
|
16
|
+
"Operating System :: OS Independent",
|
|
17
|
+
],
|
|
18
|
+
license_files=("LICENSE.txt"),
|
|
19
|
+
install_requires=[
|
|
20
|
+
"numpy>=1.20.0",
|
|
21
|
+
"xarray>=0.19.0",
|
|
22
|
+
"matplotlib>=3.4.0",
|
|
23
|
+
"cartopy>=0.20.0",
|
|
24
|
+
"netCDF4>=1.5.7",
|
|
25
|
+
"metpy>=1.1.0",
|
|
26
|
+
"cfgrib>=0.9.9",
|
|
27
|
+
"eccodes>=1.4.0",
|
|
28
|
+
"scikit-learn>=1.0.0"
|
|
29
|
+
]
|
|
30
|
+
)
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Skyborn 大气科学研究工具库
|
|
3
|
+
|
|
4
|
+
提供大气科学常用数据处理、分析和可视化功能模块
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from .io import read_netcdf, read_grib
|
|
8
|
+
from .calculations import (
|
|
9
|
+
convert_longitude_range,
|
|
10
|
+
linearRegression
|
|
11
|
+
)
|
|
12
|
+
from .plotting import add_equal_axes, createFigure
|
|
13
|
+
from .gradients import (
|
|
14
|
+
calculate_gradient,
|
|
15
|
+
calculate_meridional_gradient,
|
|
16
|
+
calculate_zonal_gradient,
|
|
17
|
+
calculate_vertical_gradient
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
__version__ = "0.1.0"
|
|
21
|
+
__all__ = ['io', 'calculations', 'gradients', 'plotting']
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
import xarray as xr
|
|
3
|
+
import metpy.calc as mpcalc
|
|
4
|
+
from metpy.units import units
|
|
5
|
+
from typing import Tuple, Union
|
|
6
|
+
from sklearn.feature_selection import f_regression
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def linearRegression(mat, sequence):
|
|
10
|
+
'''
|
|
11
|
+
回归函数 第一个是需要回归的变量,第二个为一个数组
|
|
12
|
+
'''
|
|
13
|
+
if len(mat) != len(sequence):
|
|
14
|
+
raise ValueError('Data, array must be must be equal!!!!!!!'
|
|
15
|
+
' %s and %s' % (mat.shape[0], len(sequence)))
|
|
16
|
+
A = np.column_stack((sequence, np.ones(sequence.shape[0])))
|
|
17
|
+
(a, b, c) = mat.shape
|
|
18
|
+
mat_rshp = mat.reshape((a, b*c))
|
|
19
|
+
mat_rshp_reg = np.linalg.lstsq(A, mat_rshp, rcond=None)[0][0]
|
|
20
|
+
mat_reg = mat_rshp_reg.reshape((b, c))
|
|
21
|
+
pvalue = f_regression(mat_rshp, sequence)[1].reshape(b, c)
|
|
22
|
+
return mat_reg, pvalue
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def convert_longitude_range(data: Union[xr.DataArray, xr.Dataset],
|
|
26
|
+
lon: str = 'lon',
|
|
27
|
+
center_on_180: bool = True
|
|
28
|
+
) -> Union[xr.DataArray, xr.Dataset]:
|
|
29
|
+
'''
|
|
30
|
+
Wrap longitude coordinates of DataArray or Dataset to either -180..179 or 0..359.
|
|
31
|
+
|
|
32
|
+
Parameters
|
|
33
|
+
----------
|
|
34
|
+
data : xr.DataArray or xr.Dataset
|
|
35
|
+
An xarray DataArray or Dataset object containing longitude coordinates.
|
|
36
|
+
lon : str, optional
|
|
37
|
+
The name of the longitude coordinate, default is 'lon'.
|
|
38
|
+
center_on_180 : bool, optional
|
|
39
|
+
If True, wrap longitude from 0..359 to -180..179;
|
|
40
|
+
If False, wrap longitude from -180..179 to 0..359.
|
|
41
|
+
|
|
42
|
+
Returns
|
|
43
|
+
-------
|
|
44
|
+
xr.DataArray or xr.Dataset
|
|
45
|
+
The DataArray or Dataset with wrapped longitude coordinates.
|
|
46
|
+
'''
|
|
47
|
+
# Wrap -180..179 to 0..359
|
|
48
|
+
if center_on_180:
|
|
49
|
+
data = data.assign_coords(**{lon: (lambda x: (x[lon] % 360))})
|
|
50
|
+
# Wrap 0..359 to -180..179
|
|
51
|
+
else:
|
|
52
|
+
data = data.assign_coords(
|
|
53
|
+
**{lon: (lambda x: ((x[lon] + 180) % 360) - 180)})
|
|
54
|
+
return data.sortby(lon, ascending=True)
|
|
@@ -0,0 +1,189 @@
|
|
|
1
|
+
import numpy as np
|
|
2
|
+
from typing import Union, Optional
|
|
3
|
+
|
|
4
|
+
EARTH_RADIUS = 6371e3 # 地球平均半径 (m)
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
def calculate_gradient(field: np.ndarray, coordinates: np.ndarray,
|
|
8
|
+
axis: int = -1, radius: float = 6371000.0) -> np.ndarray:
|
|
9
|
+
"""计算任意维度数组沿指定坐标的梯度
|
|
10
|
+
|
|
11
|
+
Args:
|
|
12
|
+
field: 待计算梯度的数据场,可以是任意维度的数组,如(time, level, lat, lon)
|
|
13
|
+
coordinates: 沿着计算梯度的坐标数组,如纬度或经度值
|
|
14
|
+
axis: 指定计算梯度的维度轴,默认为最后一个维度(-1)
|
|
15
|
+
radius: 地球半径,默认为6371000.0米,用于纬度梯度计算
|
|
16
|
+
|
|
17
|
+
Returns:
|
|
18
|
+
与输入场相同形状的梯度场
|
|
19
|
+
"""
|
|
20
|
+
# 检查输入数据维度是否匹配
|
|
21
|
+
if coordinates.size != field.shape[axis]:
|
|
22
|
+
raise ValueError(
|
|
23
|
+
f"坐标数组大小({coordinates.size})与场数据在指定轴上的大小({field.shape[axis]})不匹配")
|
|
24
|
+
|
|
25
|
+
# 确定是经度还是纬度坐标
|
|
26
|
+
is_latitude = False
|
|
27
|
+
if np.min(coordinates) >= -90 and np.max(coordinates) <= 90:
|
|
28
|
+
is_latitude = True
|
|
29
|
+
# 对于纬度,计算实际距离(单位:米)
|
|
30
|
+
if is_latitude:
|
|
31
|
+
# 将纬度转换为实际距离
|
|
32
|
+
distances = coordinates * np.pi / 180.0 * radius
|
|
33
|
+
else:
|
|
34
|
+
# 对于经度,我们需要考虑纬度的影响,但这需要额外的纬度信息
|
|
35
|
+
# 这里简单处理为直接使用经度差
|
|
36
|
+
distances = coordinates
|
|
37
|
+
|
|
38
|
+
# 创建与输入相同形状的输出数组
|
|
39
|
+
gradient = np.zeros_like(field, dtype=float)
|
|
40
|
+
|
|
41
|
+
# 为了使用numpy的高级索引,我们需要创建索引数组
|
|
42
|
+
ndim = field.ndim
|
|
43
|
+
idx_ranges = [slice(None)] * ndim
|
|
44
|
+
|
|
45
|
+
# 对内部点使用中心差分
|
|
46
|
+
inner_range = slice(1, field.shape[axis]-1)
|
|
47
|
+
idx_forward = idx_ranges.copy()
|
|
48
|
+
idx_forward[axis] = slice(2, field.shape[axis])
|
|
49
|
+
|
|
50
|
+
idx_center = idx_ranges.copy()
|
|
51
|
+
idx_center[axis] = inner_range
|
|
52
|
+
|
|
53
|
+
idx_backward = idx_ranges.copy()
|
|
54
|
+
idx_backward[axis] = slice(0, field.shape[axis]-2)
|
|
55
|
+
|
|
56
|
+
# 使用矢量化操作计算内部点的梯度
|
|
57
|
+
forward_dists = np.diff(distances[1:])
|
|
58
|
+
backward_dists = np.diff(distances[:-1])
|
|
59
|
+
total_dists = distances[2:] - distances[:-2]
|
|
60
|
+
|
|
61
|
+
# 创建系数数组,形状适合广播
|
|
62
|
+
shape = [1] * ndim
|
|
63
|
+
shape[axis] = len(forward_dists)
|
|
64
|
+
|
|
65
|
+
a0 = forward_dists.reshape(shape)
|
|
66
|
+
b0 = backward_dists.reshape(shape)
|
|
67
|
+
c0 = total_dists.reshape(shape)
|
|
68
|
+
|
|
69
|
+
# 使用加权差分公式计算梯度
|
|
70
|
+
gradient[tuple(idx_center)] = (
|
|
71
|
+
b0 / a0 / c0 * field[tuple(idx_forward)] -
|
|
72
|
+
a0 / b0 / c0 * field[tuple(idx_backward)] +
|
|
73
|
+
(a0 - b0) / a0 / b0 * field[tuple(idx_center)]
|
|
74
|
+
)
|
|
75
|
+
|
|
76
|
+
# 处理边界点(前向和后向差分)
|
|
77
|
+
# 左边界
|
|
78
|
+
left_idx = idx_ranges.copy()
|
|
79
|
+
left_idx[axis] = 0
|
|
80
|
+
left_idx_plus = idx_ranges.copy()
|
|
81
|
+
left_idx_plus[axis] = 1
|
|
82
|
+
gradient[tuple(left_idx)] = (field[tuple(left_idx_plus)] -
|
|
83
|
+
field[tuple(left_idx)]) / (distances[1] - distances[0])
|
|
84
|
+
|
|
85
|
+
# 右边界
|
|
86
|
+
right_idx = idx_ranges.copy()
|
|
87
|
+
right_idx[axis] = -1
|
|
88
|
+
right_idx_minus = idx_ranges.copy()
|
|
89
|
+
right_idx_minus[axis] = -2
|
|
90
|
+
gradient[tuple(right_idx)] = (field[tuple(right_idx)] -
|
|
91
|
+
field[tuple(right_idx_minus)]) / (distances[-1] - distances[-2])
|
|
92
|
+
|
|
93
|
+
return gradient
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
def calculate_meridional_gradient(field: np.ndarray, latitudes: np.ndarray,
|
|
97
|
+
lat_axis: int = -1, radius: float = 6371000.0) -> np.ndarray:
|
|
98
|
+
"""计算经向梯度(沿纬度方向的梯度)
|
|
99
|
+
|
|
100
|
+
Args:
|
|
101
|
+
field: 待计算梯度的数据场,可以是任意维度的数组
|
|
102
|
+
latitudes: 纬度数组(度)
|
|
103
|
+
lat_axis: 指定纬度所在的轴,默认为最后一个维度(-1)
|
|
104
|
+
radius: 地球半径,默认为6371000.0米
|
|
105
|
+
|
|
106
|
+
Returns:
|
|
107
|
+
经向梯度场
|
|
108
|
+
"""
|
|
109
|
+
return calculate_gradient(field, latitudes, axis=lat_axis, radius=radius)
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def calculate_vertical_gradient(field: np.ndarray,
|
|
113
|
+
pressure: np.ndarray,
|
|
114
|
+
pressure_axis: int = -3) -> np.ndarray:
|
|
115
|
+
"""计算垂直梯度(沿气压方向的梯度)
|
|
116
|
+
|
|
117
|
+
Args:
|
|
118
|
+
field: 待计算梯度的数据场
|
|
119
|
+
pressure: 气压数组(Pa),必须为单调递减
|
|
120
|
+
pressure_axis: 指定气压所在的轴,默认为倒数第三个维度(-3)
|
|
121
|
+
|
|
122
|
+
Returns:
|
|
123
|
+
垂直梯度场
|
|
124
|
+
"""
|
|
125
|
+
return calculate_gradient(field, pressure, axis=pressure_axis, radius=None)
|
|
126
|
+
|
|
127
|
+
|
|
128
|
+
def calculate_zonal_gradient(field: np.ndarray, longitudes: np.ndarray, latitudes: np.ndarray,
|
|
129
|
+
lon_axis: int = -1, lat_axis: int = -2, radius: float = 6371000.0) -> np.ndarray:
|
|
130
|
+
"""计算纬向梯度(沿经度方向的梯度)
|
|
131
|
+
|
|
132
|
+
Args:
|
|
133
|
+
field: 待计算梯度的数据场,可以是任意维度的数组
|
|
134
|
+
longitudes: 经度数组(度)
|
|
135
|
+
latitudes: 纬度数组(度),用于计算不同纬度下经度的实际距离
|
|
136
|
+
lon_axis: 指定经度所在的轴,默认为最后一个维度(-1)
|
|
137
|
+
lat_axis: 指定纬度所在的轴,默认为倒数第二个维度(-2)
|
|
138
|
+
radius: 地球半径,默认为6371000.0米
|
|
139
|
+
|
|
140
|
+
Returns:
|
|
141
|
+
纬向梯度场
|
|
142
|
+
"""
|
|
143
|
+
# 获取纬度因子,用于调整不同纬度下经度间的实际距离
|
|
144
|
+
cos_lat = np.cos(np.radians(latitudes))
|
|
145
|
+
|
|
146
|
+
# 如果场是4D (time, level, lat, lon)
|
|
147
|
+
if field.ndim == 4 and lon_axis == -1 and lat_axis == -2:
|
|
148
|
+
# 创建一个广播形状的纬度因子数组
|
|
149
|
+
cos_lat_expanded = cos_lat.reshape(1, 1, -1, 1)
|
|
150
|
+
|
|
151
|
+
# 将经度转换为考虑纬度的实际距离
|
|
152
|
+
effective_distances = np.radians(
|
|
153
|
+
longitudes) * radius * cos_lat_expanded
|
|
154
|
+
|
|
155
|
+
# 现在计算梯度
|
|
156
|
+
return calculate_gradient(field, effective_distances, axis=lon_axis, radius=1.0)
|
|
157
|
+
|
|
158
|
+
# 如果场是3D (time, lat, lon)
|
|
159
|
+
elif field.ndim == 3 and lon_axis == -1 and lat_axis == -2:
|
|
160
|
+
cos_lat_expanded = cos_lat.reshape(1, -1, 1)
|
|
161
|
+
effective_distances = np.radians(
|
|
162
|
+
longitudes) * radius * cos_lat_expanded
|
|
163
|
+
return calculate_gradient(field, effective_distances, axis=lon_axis, radius=1.0)
|
|
164
|
+
|
|
165
|
+
else:
|
|
166
|
+
# 对于其他维度组合,需要创建适当的广播形状
|
|
167
|
+
broadcast_shape = [1] * field.ndim
|
|
168
|
+
broadcast_shape[lat_axis] = len(latitudes)
|
|
169
|
+
cos_lat_expanded = cos_lat.reshape(broadcast_shape)
|
|
170
|
+
|
|
171
|
+
# 创建有效距离数组
|
|
172
|
+
effective_longitudes = np.radians(longitudes) * radius
|
|
173
|
+
|
|
174
|
+
# 对于每个纬度,计算梯度
|
|
175
|
+
result = np.zeros_like(field)
|
|
176
|
+
|
|
177
|
+
# 循环处理每个纬度(这部分实现取决于具体数据结构,可能需要调整)
|
|
178
|
+
for i in range(len(latitudes)):
|
|
179
|
+
idx = [slice(None)] * field.ndim
|
|
180
|
+
idx[lat_axis] = i
|
|
181
|
+
|
|
182
|
+
# 调整当前纬度的经度距离
|
|
183
|
+
current_effective_dist = effective_longitudes * cos_lat[i]
|
|
184
|
+
|
|
185
|
+
# 计算当前纬度的梯度
|
|
186
|
+
result[tuple(idx)] = calculate_gradient(
|
|
187
|
+
field[tuple(idx)], current_effective_dist, axis=lon_axis, radius=1.0)
|
|
188
|
+
|
|
189
|
+
return result
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import xarray as xr
|
|
2
|
+
import cfgrib
|
|
3
|
+
|
|
4
|
+
def read_netcdf(file_path: str) -> xr.Dataset:
|
|
5
|
+
"""读取NetCDF格式气象数据
|
|
6
|
+
|
|
7
|
+
Args:
|
|
8
|
+
file_path: 文件路径
|
|
9
|
+
|
|
10
|
+
Returns:
|
|
11
|
+
xarray Dataset对象
|
|
12
|
+
"""
|
|
13
|
+
return xr.open_dataset(file_path)
|
|
14
|
+
|
|
15
|
+
def read_grib(file_path: str, **kwargs) -> xr.Dataset:
|
|
16
|
+
"""读取GRIB格式气象数据
|
|
17
|
+
|
|
18
|
+
Args:
|
|
19
|
+
file_path: 文件路径
|
|
20
|
+
kwargs: 传递给cfgrib.open_dataset的额外参数
|
|
21
|
+
|
|
22
|
+
Returns:
|
|
23
|
+
xarray Dataset对象
|
|
24
|
+
"""
|
|
25
|
+
return cfgrib.open_dataset(file_path, **kwargs)
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import matplotlib.pyplot as plt
|
|
2
|
+
import matplotlib.transforms as mtransforms
|
|
3
|
+
import numpy as np
|
|
4
|
+
|
|
5
|
+
def add_equal_axes(ax, loc, pad, width):
|
|
6
|
+
'''
|
|
7
|
+
在原有的Axes旁新添一个等高或等宽的Axes并返回该对象.
|
|
8
|
+
|
|
9
|
+
Parameters
|
|
10
|
+
----------
|
|
11
|
+
ax : Axes or array_like of Axes
|
|
12
|
+
原有的Axes,也可以为一组Axes构成的数组.
|
|
13
|
+
|
|
14
|
+
loc : {'left', 'right', 'bottom', 'top'}
|
|
15
|
+
新Axes相对于旧Axes的位置.
|
|
16
|
+
|
|
17
|
+
pad : float
|
|
18
|
+
新Axes与旧Axes的间距.
|
|
19
|
+
|
|
20
|
+
width: float
|
|
21
|
+
当loc='left'或'right'时,width表示新Axes的宽度.
|
|
22
|
+
当loc='bottom'或'top'时,width表示新Axes的高度.
|
|
23
|
+
|
|
24
|
+
Returns
|
|
25
|
+
-------
|
|
26
|
+
ax_new : Axes
|
|
27
|
+
新Axes对象.
|
|
28
|
+
'''
|
|
29
|
+
# 无论ax是单个还是一组Axes,获取ax的大小位置.
|
|
30
|
+
axes = np.atleast_1d(ax).ravel()
|
|
31
|
+
bbox = mtransforms.Bbox.union([ax.get_position() for ax in axes])
|
|
32
|
+
|
|
33
|
+
# 决定新Axes的大小位置.
|
|
34
|
+
if loc == 'left':
|
|
35
|
+
x0_new = bbox.x0 - pad - width
|
|
36
|
+
x1_new = x0_new + width
|
|
37
|
+
y0_new = bbox.y0
|
|
38
|
+
y1_new = bbox.y1
|
|
39
|
+
elif loc == 'right':
|
|
40
|
+
x0_new = bbox.x1 + pad
|
|
41
|
+
x1_new = x0_new + width
|
|
42
|
+
y0_new = bbox.y0
|
|
43
|
+
y1_new = bbox.y1
|
|
44
|
+
elif loc == 'bottom':
|
|
45
|
+
x0_new = bbox.x0
|
|
46
|
+
x1_new = bbox.x1
|
|
47
|
+
y0_new = bbox.y0 - pad - width
|
|
48
|
+
y1_new = y0_new + width
|
|
49
|
+
elif loc == 'top':
|
|
50
|
+
x0_new = bbox.x0
|
|
51
|
+
x1_new = bbox.x1
|
|
52
|
+
y0_new = bbox.y1 + pad
|
|
53
|
+
y1_new = y0_new + width
|
|
54
|
+
|
|
55
|
+
# 创建新Axes.
|
|
56
|
+
fig = axes[0].get_figure()
|
|
57
|
+
bbox_new = mtransforms.Bbox.from_extents(x0_new, y0_new, x1_new, y1_new)
|
|
58
|
+
ax_new = fig.add_axes(bbox_new)
|
|
59
|
+
|
|
60
|
+
return ax_new
|
|
61
|
+
|
|
62
|
+
def createFigure(figsize=(12, 8), dpi=300, subplotAdj=None, **kwargs):
|
|
63
|
+
figsize = figsize
|
|
64
|
+
figure = plt.figure(figsize=figsize, dpi=dpi, **kwargs)
|
|
65
|
+
if subplotAdj is not None:
|
|
66
|
+
plt.subplots_adjust(**subplotAdj)
|
|
67
|
+
return figure
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
|
+
Name: skyborn
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Atmospheric science research utilities
|
|
5
|
+
Author: Qianye Su
|
|
6
|
+
Author-email: suqianye2000@gmail.com
|
|
7
|
+
License: MIT
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
10
|
+
Classifier: Operating System :: OS Independent
|
|
11
|
+
Requires-Dist: numpy>=1.20.0
|
|
12
|
+
Requires-Dist: xarray>=0.19.0
|
|
13
|
+
Requires-Dist: matplotlib>=3.4.0
|
|
14
|
+
Requires-Dist: cartopy>=0.20.0
|
|
15
|
+
Requires-Dist: netCDF4>=1.5.7
|
|
16
|
+
Requires-Dist: metpy>=1.1.0
|
|
17
|
+
Requires-Dist: cfgrib>=0.9.9
|
|
18
|
+
Requires-Dist: eccodes>=1.4.0
|
|
19
|
+
Requires-Dist: scikit-learn>=1.0.0
|
|
20
|
+
Dynamic: author
|
|
21
|
+
Dynamic: author-email
|
|
22
|
+
Dynamic: classifier
|
|
23
|
+
Dynamic: description
|
|
24
|
+
Dynamic: license
|
|
25
|
+
Dynamic: requires-dist
|
|
26
|
+
Dynamic: summary
|
|
27
|
+
|
|
28
|
+
Skyborn is a tool for easy plotting ERA5 weather data.
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
setup.py
|
|
3
|
+
src/skyborn/__init__.py
|
|
4
|
+
src/skyborn/calculations.py
|
|
5
|
+
src/skyborn/gradients.py
|
|
6
|
+
src/skyborn/io.py
|
|
7
|
+
src/skyborn/plotting.py
|
|
8
|
+
src/skyborn.egg-info/PKG-INFO
|
|
9
|
+
src/skyborn.egg-info/SOURCES.txt
|
|
10
|
+
src/skyborn.egg-info/dependency_links.txt
|
|
11
|
+
src/skyborn.egg-info/requires.txt
|
|
12
|
+
src/skyborn.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
skyborn
|