# frykit
一个配合 Matplotlib 和 Cartopy 使用的地图工具箱,主要由 `shp` 和 `plot` 模块组成。
`shp` 模块的功能是:
- 读取中国行政区划数据
- 创建多边形掩膜(mask)
- 对几何对象做投影变换
`plot` 模块的功能包括:
- 绘制中国行政区划数据。
- 利用行政区划做裁剪(clip)
- 快速设置地图范围和刻度
- 添加南海小图
- 添加风矢量图的图例
- 添加指北针
- 添加比例尺
特色是:
- 自带高德地图行政区划数据
- 可同时用于 `Axes` 或 `GeoAxes`
- 对画图速度有优化
- 对裁剪出界问题有优化
暂无文档,但是每个函数都有详细的 docstring,可以在 Python 命令行中通过 `help` 函数查看,或者在 IDE 中查看。
这个包只是作者自用的小工具集,函数编写粗糙,可能存在不少 bug,还请多多交流指正。类似的更完备的包还请移步 [cnmaps](https://github.com/cnmetlab/cnmaps)、[gma](https://gma.luosgeo.com/) 或 [EOmaps](https://github.com/raphaelquast/EOmaps)。
## 安装
```
pip install frykit # 安装
pip install -U frykit # 更新
```
依赖为:
```
python>=3.9.0
numpy>=1.20.0
cartopy>=0.20.0
pandas>=1.2.0
```
Python 版本不满足要求时可能装上 `frykit==0.2.5`,不建议使用。
## 更新记录
[CHANGELOG.md](CHANGELOG.md)
## 使用指南
### 读取中国行政区划
`get_cn_xxx` 系列函数能读取中国行政区划,返回 [Shapely](https://shapely.readthedocs.io/en/stable/manual.html) 多边形对象。具体来说:
- `get_cn_border`:读取国界。
- `get_nine_line`:读取九段线。
- `get_cn_province`:读取省界。默认返回所有省,也可以通过省名指定单个省或多个省。
- `get_cn_city`:读取市界。默认返回所有市。
- 通过市名指定单个市或多个市。
- 通过省名指定单个省或多个省包含的所有市。
- `get_cn_district`:读取县界。默认返回所有县。
- 通过县名指定单个县或多个县。
- 通过市名指定单个市或多个市包含的所有县。
- 通过省名指定单个省或多个省包含的所有县。
```Python
import frykit.shp as fshp
国界 = fshp.get_cn_border()
九段线 = fshp.get_nine_line()
所有省 = fshp.get_cn_province()
安徽省 = fshp.get_cn_province('安徽省')
安徽省, 江苏省 = fshp.get_cn_province(['安徽省', '江苏省'])
所有市 = fshp.get_cn_city()
合肥市 = fshp.get_cn_city('合肥市')
合肥市, 六安市 = fshp.get_cn_city(['合肥市', '六安市'])
安徽省的所有市 = fshp.get_cn_city(province='安徽省')
安徽省和江苏省的所有市 = fshp.get_cn_city(province=['安徽省', '江苏省'])
所有区县 = fshp.get_cn_district()
蜀山区 = fshp.get_cn_district('蜀山区')
蜀山区, 包河区 = fshp.get_cn_district(['蜀山区', '包河区'])
合肥市的所有区县 = fshp.get_cn_district(city='合肥市')
安徽省的所有区县 = fshp.get_cn_district(province='安徽省')
```
除了用字符串名称,也可以用行政区划代码(adcode)查询。不确定名称时可以用以下函数
- `get_cn_province_names`
- `get_cn_city_names`
- `get_cn_district_names`
查询各级行政区划的名称。
行政区划数据来自 [高德地图行政区域查询接口](https://lbs.amap.com/api/webservice/guide/api/district),已从 GCJ-02 坐标系处理到了 WGS84 坐标系上。文件都在 `frykit.DATA_DIRPATH` 指向的目录里。制作方法见 [amap-shp](https://github.com/ZhaJiMan/amap-shp)。
### 绘制中国行政区划
- `add_cn_border`:绘制国界。
- `add_nine_line`:绘制九段线。
- `add_cn_province`:绘制省界。
- `add_cn_city`:绘制市界。
- `add_cn_district`:绘制县界。
另外还提供标注名字的函数:
- `label_cn_province`:标注省名。
- `label_cn_city`:标注市名。
- `label_cn_district`:标注县名。
画出所有省份,同时用颜色区分京津冀地区:
```Python
import matplotlib.pyplot as plt
import frykit.plot as fplt
plt.figure(figsize=(8, 8))
ax = plt.axes(projection=fplt.PLATE_CARREE)
fplt.add_cn_province(ax)
fplt.add_cn_province(ax, ['北京市', '天津市', '河北省'], fc='dodgerblue')
fplt.add_nine_line(ax)
fplt.label_cn_province(ax)
plt.show()
```
![add_cn_province](image/add_cn_province.png)
画出北京所有区:
```Python
import matplotlib.pyplot as plt
import frykit.plot as fplt
ax = plt.axes(projection=fplt.PLATE_CARREE)
fplt.add_cn_district(ax, province='北京市', fc=plt.cm.Pastel1.colors)
fplt.label_cn_district(ax, province='北京市')
plt.show()
```
![add_cn_province](image/beijing.png)
### 绘制任意多边形
`add_cn_border` 函数相当于
```Python
add_geoms(ax, get_cn_border())
```
底层的 `add_geoms` 类似 `GeoAxes.add_geometries`,可以绘制除 `Point` 外的任意 Shapely 几何对象。
画一个半径为 10 的圆:
```Python
import shapely.geometry as sgeom
circle = sgeom.Point(0, 0).buffer(10)
fplt.add_geoms(ax, circle)
```
画自己的 shapefile,用 Cartopy 的 `Reader`、PyShp 或 Fiona 读取:
```Python
from cartopy.io.shapereader import Reader
reader = Reader('2023年_CTAmap_1.12版/2023年县级/2023年县级.shp')
fplt.add_geoms(ax, reader.geometries(), fc='none', ec='k', lw=0.25)
```
画自己的 GeoJSON,用 Shapley 做转换:
```Python
import json
import shapely.geometry as sgeom
with open('天地图_行政区划可视化/中国_省.geojson') as f:
geoj = json.load(f)
geoms = [sgeom.shape(feature['geometry']) for feature in geoj['features']]
fplt.add_geoms(ax, geoms, fc='none', ec='k', lw=0.25)
```
通过 `array`、 `cmap` 和 `norm` 参数还能实现类似分省填色的效果(详见 [fill.py](example/fill.py))。
`add_geoms` 默认直接用 pyproj 做地图投影变换,速度更快但也更容易出现错误的效果。可以指定参数 `fast_transform=False`,切换成更正确但速度更慢的模式。或者直接换用 `GeoAxes.add_geometries`。
### 裁剪 Artist
这里 Artist 泛指 Matplotlib 里 `contourf`、 `pcolormesh`、 `imshow`、 `quiver`、 `scatter` 等方法返回的对象。
- `clip_by_cn_border`:用国界裁剪。
- `clip_by_cn_province`:用省界裁剪。
- `clip_by_cn_city`:用市界裁剪。
- `clip_by_cn_district`:用县界裁剪。
- `clip_by_polygon`:用任意多边形裁剪。
用国界裁剪 `contourf` 的例子:
```Python
import matplotlib.pyplot as plt
import frykit.plot as fplt
crs = fplt.PLATE_CARREE
ax = plt.axes(projection=crs)
fplt.add_cn_province(ax)
fplt.add_nine_line(ax)
data = fplt.load_test_data()
cf = ax.contourf(
data['longitude'],
data['latitude'],
data['t2m'],
levels=20,
cmap='rainbow',
transform=crs
)
fplt.clip_by_cn_border(cf)
plt.show()
```
![clip_by_cn_border](image/clip_by_cn_border.png)
多省裁剪直接传入列表即可:
```Python
jingjinji = ['北京市', '天津市', '河北省']
fplt.clip_by_polygon(cf, jingjinji)
```
### 制作掩膜
裁剪是在画图阶段从视觉效果上屏蔽多边形外的数据,而掩膜则是在数据处理阶段对多边形外的数据进行处理,例如设为缺测。
```Python
border = fshp.get_cn_border()
mask = fshp.polygon_to_mask(border, lon, lat)
data[~mask] = np.nan
ax.contourf(lon, lat, data)
```
### 设置地图范围和刻度
`GeoAxes` 设置地图范围和刻度需要以下步骤:
```Python
import numpy as np
from cartopy.mpl.ticker import LongitudeFormatter, LatitudeFormatter
crs = fplt.PLATE_CARREE
ax.set_extent((70, 140, 0, 60), crs=crs)
ax.set_xticks(np.arange(70, 141, 10), crs=crs)
ax.set_yticks(np.arange(0, 61, 10), crs=crs)
ax.xaxis.set_major_formatter(LongitudeFormatter())
ax.yaxis.set_major_formatter(LatitudeFormatter())
```
`set_map_ticks` 函数可以将这段简化成一行:
```Python
fplt.set_map_ticks(ax, (70, 140, 0, 60), dx=10, dy=10)
```
会自动根据经度间隔和纬度间隔生成刻度,并加上度数和东南西北的符号。另外还可以:
* 用 `xticks` 和 `yticks` 显式指定刻度。
* 用 `mx` 和 `my` 参数指定次刻度的数量。
* 适用于非等经纬度投影。
> 对于非等经纬度投影的 `GeoAxes`,如果显示范围不是矩形,或者范围跨越了 180 度经线,该函数可能产生错误的效果。
### 添加风矢量图例
在右下角添加一个白色矩形背景的风矢量图例:
```Python
Q = ax.quiver(x, y, u, v, transform=crs)
fplt.add_quiver_legend(Q, U=10, width=0.15, height=0.12)
```
### 添加指北针
```Python
fplt.add_compass(ax, 0.95, 0.8, size=15)
```
指北针的位置基于 `Axes` 坐标系。 `ax` 是 `GeoAxes` 时指北针会自动指向所在位置处的北向,也可以通过 `angle` 参数手动指定角度。
### 添加比例尺
```Python
scale_bar = fplt.add_scale_bar(ax1, 0.36, 0.8, length=1000)
scale_bar.set_xticks([0, 500, 1000])
```
比例尺的长度通过采样 `GeoAxes` 中心处单位长度对应的地理距离得出。比例尺对象类似 `Axes`,可以用 `set_xticks` 等方法进一步修改样式。
### 添加小地图
```Python
mini_ax = fplt.add_mini_axes(ax)
mini_ax.set_extent((105, 120, 2, 25), crs=crs)
fplt.add_cn_province(mini_ax)
fplt.add_nine_line(mini_ax)
```
小地图默认使用大地图的投影,会自动定位到大地图的角落,无需像 `add_axes` 那样需要反复调整位置。
### GMT 风格边框
```Python
fplt.add_frame(ax)
```
添加类似 [GMT](https://www.generic-mapping-tools.org/) 风格的黑白相间格子的边框。目前仅支持等经纬度或墨卡托投影的 `GeoAxes`。
### 特殊 colorbar
构造一个颜色对应一个刻度的 colorbar:
```Python
colors = [
'orangered',
'orange',
'yellow',
'limegreen',
'royalblue',
'darkviolet'
]
cmap, norm, ticks = fplt.get_qualitative_palette(colors)
cbar = fplt.plot_colormap(cmap, norm)
cbar.set_ticks(ticks)
cbar.set_ticklabels(colors)
```
构造零值所在区间对应白色的 colorbar:
```Python
import cmaps
boundaries = [-10, -5, -2, -1, 1, 2, 5, 10, 20, 50, 100]
norm = fplt.CenteredBoundaryNorm(boundaries)
cbar = fplt.plot_colormap(cmaps.BlueWhiteOrangeRed, norm)
cbar.set_ticks(boundaries)
```
![colorbar](image/colorbar.png)
## 模块结构
![structure](image/structure.jpg)
## 性能测试
![perf](image/perf.png)
测试内容:在等距方位投影的 `GeoAxes` 上绘制 frykit 自带的行政区划数据,分国、省、市、县四种,同时按 `GeoAxes` 的范围分全国和东南小区域两种。绘制四次运行的耗时,结果如上图所示。
- frykit 模仿 Cartopy 实现了缓存机制,所以都是第一次画图耗时最长,后续三次会快很多。
- Cartopy 首次画省图要 10 秒,市图要 40 秒,县图要 70 秒;而 frykit 都在 3 秒以内。
- Cartopy 0.23 在小区域画图时仍然会画出区域外的所有内容,所以耗时相比 0.22 反而大幅倒退。frykit 对此也有优化。
顺带一提 frykit 的 `add_texts` 也有优化,比用循环调用 `ax.text` 更快。
## 详细介绍
工具箱的原理和使用场景可见下面几篇博文:
- [Cartopy 系列:画中国地图的工具箱 frykit](https://zhajiman.github.io/post/frykit/)
- [Cartopy 系列:探索 shapefile](https://zhajiman.github.io/post/cartopy_shapefile/)
- [Cartopy 系列:裁剪填色图出界问题](https://zhajiman.github.io/post/cartopy_clip_outside/)
- [Cartopy 添加南海小地图的三种方法](https://mp.weixin.qq.com/s/-QMVN6MS-UuQ9lQjz9vqBQ)
- [Matplotlib 系列:colormap 的设置](https://zhajiman.github.io/post/matplotlib_colormap/)
- [CALIPSO L2 VFM 产品的读取和绘制(with Python)](https://zhajiman.github.io/post/calipso_vfm/)
## 示例效果
包的 `example` 目录里有更复杂的示例脚本:
- [在普通 `Axes` 上画地图](example/axes.py)
![axes](image/axes.png)
- [重庆区县](example/chongqing.py)
![chongqing](image/chongqing.png)
- [分省填色](example/fill.py)
![fill](image/fill.png)
- [裁剪 `contourf` 和 `quiver`](example/quiver.py)
![quiver](image/quiver.png)
- [裁剪出界处理](example/strict_clip.py)
![strict_clip](image/strict_clip.png)
- [裁剪主图和南海小图的 `contourf`](example/contourf.py)
![contourf](image/contourf.png)
- [模仿 NERV 风格的地图](example/nerv_style.py)
![nerv_style](image/nerv_style.png)
Raw data
{
"_id": null,
"home_page": "https://github.com/ZhaJiMan/frykit",
"name": "frykit",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.9",
"maintainer_email": null,
"keywords": null,
"author": "ZhaJiMan",
"author_email": "915023793@qq.com",
"download_url": "https://files.pythonhosted.org/packages/1b/22/a068320c50e321e058aefd76a2d2f56e4f980c709dc4f92d7b3c1b7502dd/frykit-0.6.7.tar.gz",
"platform": null,
"description": "# frykit\r\n\r\n\u4e00\u4e2a\u914d\u5408 Matplotlib \u548c Cartopy \u4f7f\u7528\u7684\u5730\u56fe\u5de5\u5177\u7bb1\uff0c\u4e3b\u8981\u7531 `shp` \u548c `plot` \u6a21\u5757\u7ec4\u6210\u3002\r\n\r\n`shp` \u6a21\u5757\u7684\u529f\u80fd\u662f\uff1a\r\n\r\n- \u8bfb\u53d6\u4e2d\u56fd\u884c\u653f\u533a\u5212\u6570\u636e\r\n- \u521b\u5efa\u591a\u8fb9\u5f62\u63a9\u819c\uff08mask\uff09\r\n- \u5bf9\u51e0\u4f55\u5bf9\u8c61\u505a\u6295\u5f71\u53d8\u6362\r\n\r\n`plot` \u6a21\u5757\u7684\u529f\u80fd\u5305\u62ec\uff1a\r\n\r\n- \u7ed8\u5236\u4e2d\u56fd\u884c\u653f\u533a\u5212\u6570\u636e\u3002\r\n- \u5229\u7528\u884c\u653f\u533a\u5212\u505a\u88c1\u526a\uff08clip\uff09\r\n- \u5feb\u901f\u8bbe\u7f6e\u5730\u56fe\u8303\u56f4\u548c\u523b\u5ea6\r\n- \u6dfb\u52a0\u5357\u6d77\u5c0f\u56fe\r\n- \u6dfb\u52a0\u98ce\u77e2\u91cf\u56fe\u7684\u56fe\u4f8b\r\n- \u6dfb\u52a0\u6307\u5317\u9488\r\n- \u6dfb\u52a0\u6bd4\u4f8b\u5c3a\r\n\r\n\u7279\u8272\u662f\uff1a\r\n\r\n- \u81ea\u5e26\u9ad8\u5fb7\u5730\u56fe\u884c\u653f\u533a\u5212\u6570\u636e\r\n- \u53ef\u540c\u65f6\u7528\u4e8e `Axes` \u6216 `GeoAxes`\r\n- \u5bf9\u753b\u56fe\u901f\u5ea6\u6709\u4f18\u5316\r\n- \u5bf9\u88c1\u526a\u51fa\u754c\u95ee\u9898\u6709\u4f18\u5316\r\n\r\n\u6682\u65e0\u6587\u6863\uff0c\u4f46\u662f\u6bcf\u4e2a\u51fd\u6570\u90fd\u6709\u8be6\u7ec6\u7684 docstring\uff0c\u53ef\u4ee5\u5728 Python \u547d\u4ee4\u884c\u4e2d\u901a\u8fc7 `help` \u51fd\u6570\u67e5\u770b\uff0c\u6216\u8005\u5728 IDE \u4e2d\u67e5\u770b\u3002\r\n\r\n\u8fd9\u4e2a\u5305\u53ea\u662f\u4f5c\u8005\u81ea\u7528\u7684\u5c0f\u5de5\u5177\u96c6\uff0c\u51fd\u6570\u7f16\u5199\u7c97\u7cd9\uff0c\u53ef\u80fd\u5b58\u5728\u4e0d\u5c11 bug\uff0c\u8fd8\u8bf7\u591a\u591a\u4ea4\u6d41\u6307\u6b63\u3002\u7c7b\u4f3c\u7684\u66f4\u5b8c\u5907\u7684\u5305\u8fd8\u8bf7\u79fb\u6b65 [cnmaps](https://github.com/cnmetlab/cnmaps)\u3001[gma](https://gma.luosgeo.com/) \u6216 [EOmaps](https://github.com/raphaelquast/EOmaps)\u3002\r\n\r\n## \u5b89\u88c5\r\n\r\n```\r\npip install frykit # \u5b89\u88c5\r\npip install -U frykit # \u66f4\u65b0\r\n```\r\n\r\n\u4f9d\u8d56\u4e3a\uff1a\r\n\r\n```\r\npython>=3.9.0\r\nnumpy>=1.20.0\r\ncartopy>=0.20.0\r\npandas>=1.2.0\r\n```\r\n\r\nPython \u7248\u672c\u4e0d\u6ee1\u8db3\u8981\u6c42\u65f6\u53ef\u80fd\u88c5\u4e0a `frykit==0.2.5`\uff0c\u4e0d\u5efa\u8bae\u4f7f\u7528\u3002\r\n\r\n## \u66f4\u65b0\u8bb0\u5f55\r\n\r\n[CHANGELOG.md](CHANGELOG.md)\r\n\r\n## \u4f7f\u7528\u6307\u5357\r\n\r\n### \u8bfb\u53d6\u4e2d\u56fd\u884c\u653f\u533a\u5212\r\n\r\n`get_cn_xxx` \u7cfb\u5217\u51fd\u6570\u80fd\u8bfb\u53d6\u4e2d\u56fd\u884c\u653f\u533a\u5212\uff0c\u8fd4\u56de [Shapely](https://shapely.readthedocs.io/en/stable/manual.html) \u591a\u8fb9\u5f62\u5bf9\u8c61\u3002\u5177\u4f53\u6765\u8bf4\uff1a\r\n\r\n- `get_cn_border`\uff1a\u8bfb\u53d6\u56fd\u754c\u3002\r\n- `get_nine_line`\uff1a\u8bfb\u53d6\u4e5d\u6bb5\u7ebf\u3002\r\n- `get_cn_province`\uff1a\u8bfb\u53d6\u7701\u754c\u3002\u9ed8\u8ba4\u8fd4\u56de\u6240\u6709\u7701\uff0c\u4e5f\u53ef\u4ee5\u901a\u8fc7\u7701\u540d\u6307\u5b9a\u5355\u4e2a\u7701\u6216\u591a\u4e2a\u7701\u3002\r\n- `get_cn_city`\uff1a\u8bfb\u53d6\u5e02\u754c\u3002\u9ed8\u8ba4\u8fd4\u56de\u6240\u6709\u5e02\u3002\r\n - \u901a\u8fc7\u5e02\u540d\u6307\u5b9a\u5355\u4e2a\u5e02\u6216\u591a\u4e2a\u5e02\u3002\r\n - \u901a\u8fc7\u7701\u540d\u6307\u5b9a\u5355\u4e2a\u7701\u6216\u591a\u4e2a\u7701\u5305\u542b\u7684\u6240\u6709\u5e02\u3002\r\n- `get_cn_district`\uff1a\u8bfb\u53d6\u53bf\u754c\u3002\u9ed8\u8ba4\u8fd4\u56de\u6240\u6709\u53bf\u3002\r\n - \u901a\u8fc7\u53bf\u540d\u6307\u5b9a\u5355\u4e2a\u53bf\u6216\u591a\u4e2a\u53bf\u3002\r\n - \u901a\u8fc7\u5e02\u540d\u6307\u5b9a\u5355\u4e2a\u5e02\u6216\u591a\u4e2a\u5e02\u5305\u542b\u7684\u6240\u6709\u53bf\u3002\r\n - \u901a\u8fc7\u7701\u540d\u6307\u5b9a\u5355\u4e2a\u7701\u6216\u591a\u4e2a\u7701\u5305\u542b\u7684\u6240\u6709\u53bf\u3002\r\n\r\n```Python\r\nimport frykit.shp as fshp\r\n\r\n\u56fd\u754c = fshp.get_cn_border()\r\n\u4e5d\u6bb5\u7ebf = fshp.get_nine_line()\r\n\r\n\u6240\u6709\u7701 = fshp.get_cn_province()\r\n\u5b89\u5fbd\u7701 = fshp.get_cn_province('\u5b89\u5fbd\u7701')\r\n\u5b89\u5fbd\u7701, \u6c5f\u82cf\u7701 = fshp.get_cn_province(['\u5b89\u5fbd\u7701', '\u6c5f\u82cf\u7701'])\r\n\r\n\u6240\u6709\u5e02 = fshp.get_cn_city()\r\n\u5408\u80a5\u5e02 = fshp.get_cn_city('\u5408\u80a5\u5e02')\r\n\u5408\u80a5\u5e02, \u516d\u5b89\u5e02 = fshp.get_cn_city(['\u5408\u80a5\u5e02', '\u516d\u5b89\u5e02'])\r\n\r\n\u5b89\u5fbd\u7701\u7684\u6240\u6709\u5e02 = fshp.get_cn_city(province='\u5b89\u5fbd\u7701')\r\n\u5b89\u5fbd\u7701\u548c\u6c5f\u82cf\u7701\u7684\u6240\u6709\u5e02 = fshp.get_cn_city(province=['\u5b89\u5fbd\u7701', '\u6c5f\u82cf\u7701'])\r\n\r\n\u6240\u6709\u533a\u53bf = fshp.get_cn_district()\r\n\u8700\u5c71\u533a = fshp.get_cn_district('\u8700\u5c71\u533a')\r\n\u8700\u5c71\u533a, \u5305\u6cb3\u533a = fshp.get_cn_district(['\u8700\u5c71\u533a', '\u5305\u6cb3\u533a'])\r\n\r\n\u5408\u80a5\u5e02\u7684\u6240\u6709\u533a\u53bf = fshp.get_cn_district(city='\u5408\u80a5\u5e02')\r\n\u5b89\u5fbd\u7701\u7684\u6240\u6709\u533a\u53bf = fshp.get_cn_district(province='\u5b89\u5fbd\u7701')\r\n```\r\n\r\n\u9664\u4e86\u7528\u5b57\u7b26\u4e32\u540d\u79f0\uff0c\u4e5f\u53ef\u4ee5\u7528\u884c\u653f\u533a\u5212\u4ee3\u7801\uff08adcode\uff09\u67e5\u8be2\u3002\u4e0d\u786e\u5b9a\u540d\u79f0\u65f6\u53ef\u4ee5\u7528\u4ee5\u4e0b\u51fd\u6570\r\n\r\n- `get_cn_province_names`\r\n- `get_cn_city_names`\r\n- `get_cn_district_names`\r\n\r\n\u67e5\u8be2\u5404\u7ea7\u884c\u653f\u533a\u5212\u7684\u540d\u79f0\u3002\r\n\r\n\u884c\u653f\u533a\u5212\u6570\u636e\u6765\u81ea [\u9ad8\u5fb7\u5730\u56fe\u884c\u653f\u533a\u57df\u67e5\u8be2\u63a5\u53e3](https://lbs.amap.com/api/webservice/guide/api/district)\uff0c\u5df2\u4ece GCJ-02 \u5750\u6807\u7cfb\u5904\u7406\u5230\u4e86 WGS84 \u5750\u6807\u7cfb\u4e0a\u3002\u6587\u4ef6\u90fd\u5728 `frykit.DATA_DIRPATH` \u6307\u5411\u7684\u76ee\u5f55\u91cc\u3002\u5236\u4f5c\u65b9\u6cd5\u89c1 [amap-shp](https://github.com/ZhaJiMan/amap-shp)\u3002\r\n\r\n### \u7ed8\u5236\u4e2d\u56fd\u884c\u653f\u533a\u5212\r\n\r\n- `add_cn_border`\uff1a\u7ed8\u5236\u56fd\u754c\u3002\r\n- `add_nine_line`\uff1a\u7ed8\u5236\u4e5d\u6bb5\u7ebf\u3002\r\n- `add_cn_province`\uff1a\u7ed8\u5236\u7701\u754c\u3002\r\n- `add_cn_city`\uff1a\u7ed8\u5236\u5e02\u754c\u3002\r\n- `add_cn_district`\uff1a\u7ed8\u5236\u53bf\u754c\u3002\r\n\r\n\u53e6\u5916\u8fd8\u63d0\u4f9b\u6807\u6ce8\u540d\u5b57\u7684\u51fd\u6570\uff1a\r\n\r\n- `label_cn_province`\uff1a\u6807\u6ce8\u7701\u540d\u3002\r\n- `label_cn_city`\uff1a\u6807\u6ce8\u5e02\u540d\u3002\r\n- `label_cn_district`\uff1a\u6807\u6ce8\u53bf\u540d\u3002\r\n\r\n\u753b\u51fa\u6240\u6709\u7701\u4efd\uff0c\u540c\u65f6\u7528\u989c\u8272\u533a\u5206\u4eac\u6d25\u5180\u5730\u533a\uff1a\r\n\r\n```Python\r\nimport matplotlib.pyplot as plt\r\nimport frykit.plot as fplt\r\n\r\nplt.figure(figsize=(8, 8))\r\nax = plt.axes(projection=fplt.PLATE_CARREE)\r\nfplt.add_cn_province(ax)\r\nfplt.add_cn_province(ax, ['\u5317\u4eac\u5e02', '\u5929\u6d25\u5e02', '\u6cb3\u5317\u7701'], fc='dodgerblue')\r\nfplt.add_nine_line(ax)\r\nfplt.label_cn_province(ax)\r\n\r\nplt.show()\r\n```\r\n\r\n![add_cn_province](image/add_cn_province.png)\r\n\r\n\u753b\u51fa\u5317\u4eac\u6240\u6709\u533a\uff1a\r\n\r\n```Python\r\nimport matplotlib.pyplot as plt\r\nimport frykit.plot as fplt\r\n\r\nax = plt.axes(projection=fplt.PLATE_CARREE)\r\nfplt.add_cn_district(ax, province='\u5317\u4eac\u5e02', fc=plt.cm.Pastel1.colors)\r\nfplt.label_cn_district(ax, province='\u5317\u4eac\u5e02')\r\n\r\nplt.show()\r\n```\r\n\r\n![add_cn_province](image/beijing.png)\r\n\r\n### \u7ed8\u5236\u4efb\u610f\u591a\u8fb9\u5f62\r\n\r\n`add_cn_border` \u51fd\u6570\u76f8\u5f53\u4e8e\r\n\r\n```Python\r\nadd_geoms(ax, get_cn_border())\r\n```\r\n\r\n\u5e95\u5c42\u7684 `add_geoms` \u7c7b\u4f3c `GeoAxes.add_geometries`\uff0c\u53ef\u4ee5\u7ed8\u5236\u9664 `Point` \u5916\u7684\u4efb\u610f Shapely \u51e0\u4f55\u5bf9\u8c61\u3002\r\n\r\n\u753b\u4e00\u4e2a\u534a\u5f84\u4e3a 10 \u7684\u5706\uff1a\r\n\r\n```Python\r\nimport shapely.geometry as sgeom\r\n\r\ncircle = sgeom.Point(0, 0).buffer(10)\r\nfplt.add_geoms(ax, circle)\r\n```\r\n\r\n\u753b\u81ea\u5df1\u7684 shapefile\uff0c\u7528 Cartopy \u7684 `Reader`\u3001PyShp \u6216 Fiona \u8bfb\u53d6\uff1a\r\n\r\n```Python\r\nfrom cartopy.io.shapereader import Reader\r\n\r\nreader = Reader('2023\u5e74_CTAmap_1.12\u7248/2023\u5e74\u53bf\u7ea7/2023\u5e74\u53bf\u7ea7.shp')\r\nfplt.add_geoms(ax, reader.geometries(), fc='none', ec='k', lw=0.25)\r\n```\r\n\r\n\u753b\u81ea\u5df1\u7684 GeoJSON\uff0c\u7528 Shapley \u505a\u8f6c\u6362\uff1a\r\n\r\n```Python\r\nimport json\r\nimport shapely.geometry as sgeom\r\n\r\nwith open('\u5929\u5730\u56fe_\u884c\u653f\u533a\u5212\u53ef\u89c6\u5316/\u4e2d\u56fd_\u7701.geojson') as f:\r\n geoj = json.load(f)\r\ngeoms = [sgeom.shape(feature['geometry']) for feature in geoj['features']]\r\nfplt.add_geoms(ax, geoms, fc='none', ec='k', lw=0.25)\r\n```\r\n\r\n\u901a\u8fc7 `array`\u3001 `cmap` \u548c `norm` \u53c2\u6570\u8fd8\u80fd\u5b9e\u73b0\u7c7b\u4f3c\u5206\u7701\u586b\u8272\u7684\u6548\u679c\uff08\u8be6\u89c1 [fill.py](example/fill.py)\uff09\u3002\r\n\r\n`add_geoms` \u9ed8\u8ba4\u76f4\u63a5\u7528 pyproj \u505a\u5730\u56fe\u6295\u5f71\u53d8\u6362\uff0c\u901f\u5ea6\u66f4\u5feb\u4f46\u4e5f\u66f4\u5bb9\u6613\u51fa\u73b0\u9519\u8bef\u7684\u6548\u679c\u3002\u53ef\u4ee5\u6307\u5b9a\u53c2\u6570 `fast_transform=False`\uff0c\u5207\u6362\u6210\u66f4\u6b63\u786e\u4f46\u901f\u5ea6\u66f4\u6162\u7684\u6a21\u5f0f\u3002\u6216\u8005\u76f4\u63a5\u6362\u7528 `GeoAxes.add_geometries`\u3002\r\n\r\n### \u88c1\u526a Artist\r\n\r\n\u8fd9\u91cc Artist \u6cdb\u6307 Matplotlib \u91cc `contourf`\u3001 `pcolormesh`\u3001 `imshow`\u3001 `quiver`\u3001 `scatter` \u7b49\u65b9\u6cd5\u8fd4\u56de\u7684\u5bf9\u8c61\u3002\r\n\r\n- `clip_by_cn_border`\uff1a\u7528\u56fd\u754c\u88c1\u526a\u3002\r\n- `clip_by_cn_province`\uff1a\u7528\u7701\u754c\u88c1\u526a\u3002\r\n- `clip_by_cn_city`\uff1a\u7528\u5e02\u754c\u88c1\u526a\u3002\r\n- `clip_by_cn_district`\uff1a\u7528\u53bf\u754c\u88c1\u526a\u3002\r\n- `clip_by_polygon`\uff1a\u7528\u4efb\u610f\u591a\u8fb9\u5f62\u88c1\u526a\u3002\r\n\r\n\u7528\u56fd\u754c\u88c1\u526a `contourf` \u7684\u4f8b\u5b50\uff1a\r\n\r\n```Python\r\nimport matplotlib.pyplot as plt\r\nimport frykit.plot as fplt\r\n\r\ncrs = fplt.PLATE_CARREE\r\nax = plt.axes(projection=crs)\r\nfplt.add_cn_province(ax)\r\nfplt.add_nine_line(ax)\r\n\r\ndata = fplt.load_test_data()\r\ncf = ax.contourf(\r\n data['longitude'],\r\n data['latitude'],\r\n data['t2m'],\r\n levels=20,\r\n cmap='rainbow',\r\n transform=crs\r\n)\r\nfplt.clip_by_cn_border(cf)\r\n\r\nplt.show()\r\n```\r\n\r\n![clip_by_cn_border](image/clip_by_cn_border.png)\r\n\r\n\u591a\u7701\u88c1\u526a\u76f4\u63a5\u4f20\u5165\u5217\u8868\u5373\u53ef\uff1a\r\n\r\n```Python\r\njingjinji = ['\u5317\u4eac\u5e02', '\u5929\u6d25\u5e02', '\u6cb3\u5317\u7701']\r\nfplt.clip_by_polygon(cf, jingjinji)\r\n```\r\n\r\n### \u5236\u4f5c\u63a9\u819c\r\n\r\n\u88c1\u526a\u662f\u5728\u753b\u56fe\u9636\u6bb5\u4ece\u89c6\u89c9\u6548\u679c\u4e0a\u5c4f\u853d\u591a\u8fb9\u5f62\u5916\u7684\u6570\u636e\uff0c\u800c\u63a9\u819c\u5219\u662f\u5728\u6570\u636e\u5904\u7406\u9636\u6bb5\u5bf9\u591a\u8fb9\u5f62\u5916\u7684\u6570\u636e\u8fdb\u884c\u5904\u7406\uff0c\u4f8b\u5982\u8bbe\u4e3a\u7f3a\u6d4b\u3002\r\n\r\n```Python\r\nborder = fshp.get_cn_border()\r\nmask = fshp.polygon_to_mask(border, lon, lat)\r\ndata[~mask] = np.nan\r\nax.contourf(lon, lat, data)\r\n```\r\n\r\n### \u8bbe\u7f6e\u5730\u56fe\u8303\u56f4\u548c\u523b\u5ea6\r\n\r\n\r\n`GeoAxes` \u8bbe\u7f6e\u5730\u56fe\u8303\u56f4\u548c\u523b\u5ea6\u9700\u8981\u4ee5\u4e0b\u6b65\u9aa4\uff1a\r\n\r\n```Python\r\nimport numpy as np\r\nfrom cartopy.mpl.ticker import LongitudeFormatter, LatitudeFormatter\r\n\r\ncrs = fplt.PLATE_CARREE\r\nax.set_extent((70, 140, 0, 60), crs=crs)\r\nax.set_xticks(np.arange(70, 141, 10), crs=crs)\r\nax.set_yticks(np.arange(0, 61, 10), crs=crs)\r\nax.xaxis.set_major_formatter(LongitudeFormatter())\r\nax.yaxis.set_major_formatter(LatitudeFormatter())\r\n```\r\n\r\n`set_map_ticks` \u51fd\u6570\u53ef\u4ee5\u5c06\u8fd9\u6bb5\u7b80\u5316\u6210\u4e00\u884c\uff1a\r\n\r\n```Python\r\nfplt.set_map_ticks(ax, (70, 140, 0, 60), dx=10, dy=10)\r\n```\r\n\r\n\u4f1a\u81ea\u52a8\u6839\u636e\u7ecf\u5ea6\u95f4\u9694\u548c\u7eac\u5ea6\u95f4\u9694\u751f\u6210\u523b\u5ea6\uff0c\u5e76\u52a0\u4e0a\u5ea6\u6570\u548c\u4e1c\u5357\u897f\u5317\u7684\u7b26\u53f7\u3002\u53e6\u5916\u8fd8\u53ef\u4ee5\uff1a\r\n\r\n* \u7528 `xticks` \u548c `yticks` \u663e\u5f0f\u6307\u5b9a\u523b\u5ea6\u3002\r\n* \u7528 `mx` \u548c `my` \u53c2\u6570\u6307\u5b9a\u6b21\u523b\u5ea6\u7684\u6570\u91cf\u3002\r\n* \u9002\u7528\u4e8e\u975e\u7b49\u7ecf\u7eac\u5ea6\u6295\u5f71\u3002\r\n\r\n> \u5bf9\u4e8e\u975e\u7b49\u7ecf\u7eac\u5ea6\u6295\u5f71\u7684 `GeoAxes`\uff0c\u5982\u679c\u663e\u793a\u8303\u56f4\u4e0d\u662f\u77e9\u5f62\uff0c\u6216\u8005\u8303\u56f4\u8de8\u8d8a\u4e86 180 \u5ea6\u7ecf\u7ebf\uff0c\u8be5\u51fd\u6570\u53ef\u80fd\u4ea7\u751f\u9519\u8bef\u7684\u6548\u679c\u3002\r\n\r\n### \u6dfb\u52a0\u98ce\u77e2\u91cf\u56fe\u4f8b\r\n\r\n\u5728\u53f3\u4e0b\u89d2\u6dfb\u52a0\u4e00\u4e2a\u767d\u8272\u77e9\u5f62\u80cc\u666f\u7684\u98ce\u77e2\u91cf\u56fe\u4f8b\uff1a\r\n\r\n```Python\r\nQ = ax.quiver(x, y, u, v, transform=crs)\r\nfplt.add_quiver_legend(Q, U=10, width=0.15, height=0.12)\r\n```\r\n\r\n### \u6dfb\u52a0\u6307\u5317\u9488\r\n\r\n```Python\r\nfplt.add_compass(ax, 0.95, 0.8, size=15)\r\n```\r\n\r\n\u6307\u5317\u9488\u7684\u4f4d\u7f6e\u57fa\u4e8e `Axes` \u5750\u6807\u7cfb\u3002 `ax` \u662f `GeoAxes` \u65f6\u6307\u5317\u9488\u4f1a\u81ea\u52a8\u6307\u5411\u6240\u5728\u4f4d\u7f6e\u5904\u7684\u5317\u5411\uff0c\u4e5f\u53ef\u4ee5\u901a\u8fc7 `angle` \u53c2\u6570\u624b\u52a8\u6307\u5b9a\u89d2\u5ea6\u3002\r\n\r\n### \u6dfb\u52a0\u6bd4\u4f8b\u5c3a\r\n\r\n```Python\r\nscale_bar = fplt.add_scale_bar(ax1, 0.36, 0.8, length=1000)\r\nscale_bar.set_xticks([0, 500, 1000])\r\n```\r\n\r\n\u6bd4\u4f8b\u5c3a\u7684\u957f\u5ea6\u901a\u8fc7\u91c7\u6837 `GeoAxes` \u4e2d\u5fc3\u5904\u5355\u4f4d\u957f\u5ea6\u5bf9\u5e94\u7684\u5730\u7406\u8ddd\u79bb\u5f97\u51fa\u3002\u6bd4\u4f8b\u5c3a\u5bf9\u8c61\u7c7b\u4f3c `Axes`\uff0c\u53ef\u4ee5\u7528 `set_xticks` \u7b49\u65b9\u6cd5\u8fdb\u4e00\u6b65\u4fee\u6539\u6837\u5f0f\u3002\r\n\r\n### \u6dfb\u52a0\u5c0f\u5730\u56fe\r\n\r\n```Python\r\nmini_ax = fplt.add_mini_axes(ax)\r\nmini_ax.set_extent((105, 120, 2, 25), crs=crs)\r\nfplt.add_cn_province(mini_ax)\r\nfplt.add_nine_line(mini_ax)\r\n```\r\n\r\n\u5c0f\u5730\u56fe\u9ed8\u8ba4\u4f7f\u7528\u5927\u5730\u56fe\u7684\u6295\u5f71\uff0c\u4f1a\u81ea\u52a8\u5b9a\u4f4d\u5230\u5927\u5730\u56fe\u7684\u89d2\u843d\uff0c\u65e0\u9700\u50cf `add_axes` \u90a3\u6837\u9700\u8981\u53cd\u590d\u8c03\u6574\u4f4d\u7f6e\u3002\r\n\r\n### GMT \u98ce\u683c\u8fb9\u6846\r\n\r\n```Python\r\nfplt.add_frame(ax)\r\n```\r\n\r\n\u6dfb\u52a0\u7c7b\u4f3c [GMT](https://www.generic-mapping-tools.org/) \u98ce\u683c\u7684\u9ed1\u767d\u76f8\u95f4\u683c\u5b50\u7684\u8fb9\u6846\u3002\u76ee\u524d\u4ec5\u652f\u6301\u7b49\u7ecf\u7eac\u5ea6\u6216\u58a8\u5361\u6258\u6295\u5f71\u7684 `GeoAxes`\u3002\r\n\r\n### \u7279\u6b8a colorbar\r\n\r\n\u6784\u9020\u4e00\u4e2a\u989c\u8272\u5bf9\u5e94\u4e00\u4e2a\u523b\u5ea6\u7684 colorbar\uff1a\r\n\r\n```Python\r\ncolors = [\r\n 'orangered',\r\n 'orange',\r\n 'yellow',\r\n 'limegreen',\r\n 'royalblue',\r\n 'darkviolet'\r\n]\r\ncmap, norm, ticks = fplt.get_qualitative_palette(colors)\r\ncbar = fplt.plot_colormap(cmap, norm)\r\ncbar.set_ticks(ticks)\r\ncbar.set_ticklabels(colors)\r\n```\r\n\r\n\u6784\u9020\u96f6\u503c\u6240\u5728\u533a\u95f4\u5bf9\u5e94\u767d\u8272\u7684 colorbar\uff1a\r\n\r\n```Python\r\nimport cmaps\r\n\r\nboundaries = [-10, -5, -2, -1, 1, 2, 5, 10, 20, 50, 100]\r\nnorm = fplt.CenteredBoundaryNorm(boundaries)\r\ncbar = fplt.plot_colormap(cmaps.BlueWhiteOrangeRed, norm)\r\ncbar.set_ticks(boundaries)\r\n```\r\n\r\n![colorbar](image/colorbar.png)\r\n\r\n## \u6a21\u5757\u7ed3\u6784\r\n\r\n![structure](image/structure.jpg)\r\n\r\n## \u6027\u80fd\u6d4b\u8bd5\r\n\r\n![perf](image/perf.png)\r\n\r\n\u6d4b\u8bd5\u5185\u5bb9\uff1a\u5728\u7b49\u8ddd\u65b9\u4f4d\u6295\u5f71\u7684 `GeoAxes` \u4e0a\u7ed8\u5236 frykit \u81ea\u5e26\u7684\u884c\u653f\u533a\u5212\u6570\u636e\uff0c\u5206\u56fd\u3001\u7701\u3001\u5e02\u3001\u53bf\u56db\u79cd\uff0c\u540c\u65f6\u6309 `GeoAxes` \u7684\u8303\u56f4\u5206\u5168\u56fd\u548c\u4e1c\u5357\u5c0f\u533a\u57df\u4e24\u79cd\u3002\u7ed8\u5236\u56db\u6b21\u8fd0\u884c\u7684\u8017\u65f6\uff0c\u7ed3\u679c\u5982\u4e0a\u56fe\u6240\u793a\u3002\r\n\r\n- frykit \u6a21\u4eff Cartopy \u5b9e\u73b0\u4e86\u7f13\u5b58\u673a\u5236\uff0c\u6240\u4ee5\u90fd\u662f\u7b2c\u4e00\u6b21\u753b\u56fe\u8017\u65f6\u6700\u957f\uff0c\u540e\u7eed\u4e09\u6b21\u4f1a\u5feb\u5f88\u591a\u3002\r\n- Cartopy \u9996\u6b21\u753b\u7701\u56fe\u8981 10 \u79d2\uff0c\u5e02\u56fe\u8981 40 \u79d2\uff0c\u53bf\u56fe\u8981 70 \u79d2\uff1b\u800c frykit \u90fd\u5728 3 \u79d2\u4ee5\u5185\u3002\r\n- Cartopy 0.23 \u5728\u5c0f\u533a\u57df\u753b\u56fe\u65f6\u4ecd\u7136\u4f1a\u753b\u51fa\u533a\u57df\u5916\u7684\u6240\u6709\u5185\u5bb9\uff0c\u6240\u4ee5\u8017\u65f6\u76f8\u6bd4 0.22 \u53cd\u800c\u5927\u5e45\u5012\u9000\u3002frykit \u5bf9\u6b64\u4e5f\u6709\u4f18\u5316\u3002\r\n\r\n\u987a\u5e26\u4e00\u63d0 frykit \u7684 `add_texts` \u4e5f\u6709\u4f18\u5316\uff0c\u6bd4\u7528\u5faa\u73af\u8c03\u7528 `ax.text` \u66f4\u5feb\u3002\r\n\r\n## \u8be6\u7ec6\u4ecb\u7ecd\r\n\r\n\u5de5\u5177\u7bb1\u7684\u539f\u7406\u548c\u4f7f\u7528\u573a\u666f\u53ef\u89c1\u4e0b\u9762\u51e0\u7bc7\u535a\u6587\uff1a\r\n\r\n- [Cartopy \u7cfb\u5217\uff1a\u753b\u4e2d\u56fd\u5730\u56fe\u7684\u5de5\u5177\u7bb1 frykit](https://zhajiman.github.io/post/frykit/)\r\n- [Cartopy \u7cfb\u5217\uff1a\u63a2\u7d22 shapefile](https://zhajiman.github.io/post/cartopy_shapefile/)\r\n- [Cartopy \u7cfb\u5217\uff1a\u88c1\u526a\u586b\u8272\u56fe\u51fa\u754c\u95ee\u9898](https://zhajiman.github.io/post/cartopy_clip_outside/)\r\n- [Cartopy \u6dfb\u52a0\u5357\u6d77\u5c0f\u5730\u56fe\u7684\u4e09\u79cd\u65b9\u6cd5](https://mp.weixin.qq.com/s/-QMVN6MS-UuQ9lQjz9vqBQ)\r\n- [Matplotlib \u7cfb\u5217\uff1acolormap \u7684\u8bbe\u7f6e](https://zhajiman.github.io/post/matplotlib_colormap/)\r\n- [CALIPSO L2 VFM \u4ea7\u54c1\u7684\u8bfb\u53d6\u548c\u7ed8\u5236\uff08with Python\uff09](https://zhajiman.github.io/post/calipso_vfm/)\r\n\r\n## \u793a\u4f8b\u6548\u679c\r\n\r\n\u5305\u7684 `example` \u76ee\u5f55\u91cc\u6709\u66f4\u590d\u6742\u7684\u793a\u4f8b\u811a\u672c\uff1a\r\n\r\n- [\u5728\u666e\u901a `Axes` \u4e0a\u753b\u5730\u56fe](example/axes.py)\r\n\r\n![axes](image/axes.png)\r\n\r\n- [\u91cd\u5e86\u533a\u53bf](example/chongqing.py)\r\n\r\n![chongqing](image/chongqing.png)\r\n\r\n- [\u5206\u7701\u586b\u8272](example/fill.py)\r\n\r\n![fill](image/fill.png)\r\n\r\n- [\u88c1\u526a `contourf` \u548c `quiver`](example/quiver.py)\r\n\r\n![quiver](image/quiver.png)\r\n\r\n- [\u88c1\u526a\u51fa\u754c\u5904\u7406](example/strict_clip.py)\r\n\r\n![strict_clip](image/strict_clip.png)\r\n\r\n- [\u88c1\u526a\u4e3b\u56fe\u548c\u5357\u6d77\u5c0f\u56fe\u7684 `contourf`](example/contourf.py)\r\n\r\n![contourf](image/contourf.png)\r\n\r\n- [\u6a21\u4eff NERV \u98ce\u683c\u7684\u5730\u56fe](example/nerv_style.py)\r\n\r\n![nerv_style](image/nerv_style.png)\r\n",
"bugtrack_url": null,
"license": null,
"summary": "A simple toolbox for Matplotib and Cartopy",
"version": "0.6.7",
"project_urls": {
"Homepage": "https://github.com/ZhaJiMan/frykit"
},
"split_keywords": [],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "1b22a068320c50e321e058aefd76a2d2f56e4f980c709dc4f92d7b3c1b7502dd",
"md5": "c9cbdf174177919a4714fa0e5931ab49",
"sha256": "220fa9887a5a403992d07c1cad4ee1bf81e9660345a320c8be63ccf642540b4b"
},
"downloads": -1,
"filename": "frykit-0.6.7.tar.gz",
"has_sig": false,
"md5_digest": "c9cbdf174177919a4714fa0e5931ab49",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.9",
"size": 29326483,
"upload_time": "2024-08-27T14:32:57",
"upload_time_iso_8601": "2024-08-27T14:32:57.840649Z",
"url": "https://files.pythonhosted.org/packages/1b/22/a068320c50e321e058aefd76a2d2f56e4f980c709dc4f92d7b3c1b7502dd/frykit-0.6.7.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-08-27 14:32:57",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "ZhaJiMan",
"github_project": "frykit",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"requirements": [
{
"name": "numpy",
"specs": [
[
">=",
"1.20.0"
]
]
},
{
"name": "pandas",
"specs": [
[
">=",
"1.2.0"
]
]
},
{
"name": "cartopy",
"specs": [
[
">=",
"0.20.0"
]
]
}
],
"lcname": "frykit"
}