tilekit 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.
@@ -0,0 +1,8 @@
1
+ # 默认忽略的文件
2
+ /shelf/
3
+ /workspace.xml
4
+ # 基于编辑器的 HTTP 客户端请求
5
+ /httpRequests/
6
+ # Datasource local storage ignored files
7
+ /dataSources/
8
+ /dataSources.local.xml
@@ -0,0 +1,6 @@
1
+ <component name="InspectionProjectProfileManager">
2
+ <settings>
3
+ <option name="USE_PROJECT_PROFILE" value="false" />
4
+ <version value="1.0" />
5
+ </settings>
6
+ </component>
@@ -0,0 +1,7 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="Black">
4
+ <option name="sdkName" value="uv (tilekit)" />
5
+ </component>
6
+ <component name="ProjectRootManager" version="2" project-jdk-name="py13" project-jdk-type="Python SDK" />
7
+ </project>
@@ -0,0 +1,8 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="ProjectModuleManager">
4
+ <modules>
5
+ <module fileurl="file://$PROJECT_DIR$/.idea/tilekit.iml" filepath="$PROJECT_DIR$/.idea/tilekit.iml" />
6
+ </modules>
7
+ </component>
8
+ </project>
@@ -0,0 +1,11 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <module type="PYTHON_MODULE" version="4">
3
+ <component name="NewModuleRootManager">
4
+ <content url="file://$MODULE_DIR$">
5
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
6
+ <excludeFolder url="file://$MODULE_DIR$/.venv" />
7
+ </content>
8
+ <orderEntry type="jdk" jdkName="uv (tilekit)" jdkType="Python SDK" />
9
+ <orderEntry type="sourceFolder" forTests="false" />
10
+ </component>
11
+ </module>
@@ -0,0 +1,6 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="VcsDirectoryMappings">
4
+ <mapping directory="$PROJECT_DIR$" vcs="Git" />
5
+ </component>
6
+ </project>
@@ -0,0 +1,94 @@
1
+ <?xml version="1.0" encoding="UTF-8"?>
2
+ <project version="4">
3
+ <component name="AutoImportSettings">
4
+ <option name="autoReloadType" value="SELECTIVE" />
5
+ </component>
6
+ <component name="ChangeListManager">
7
+ <list default="true" id="7ecbaad1-0830-4879-b1c9-a862886743c8" name="更改" comment="">
8
+ <change afterPath="$PROJECT_DIR$/.idea/.gitignore" afterDir="false" />
9
+ <change afterPath="$PROJECT_DIR$/.idea/inspectionProfiles/profiles_settings.xml" afterDir="false" />
10
+ <change afterPath="$PROJECT_DIR$/.idea/misc.xml" afterDir="false" />
11
+ <change afterPath="$PROJECT_DIR$/.idea/modules.xml" afterDir="false" />
12
+ <change afterPath="$PROJECT_DIR$/.idea/tilekit.iml" afterDir="false" />
13
+ <change afterPath="$PROJECT_DIR$/.idea/vcs.xml" afterDir="false" />
14
+ <change afterPath="$PROJECT_DIR$/pyproject.toml" afterDir="false" />
15
+ </list>
16
+ <option name="SHOW_DIALOG" value="false" />
17
+ <option name="HIGHLIGHT_CONFLICTS" value="true" />
18
+ <option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
19
+ <option name="LAST_RESOLUTION" value="IGNORE" />
20
+ </component>
21
+ <component name="FileTemplateManagerImpl">
22
+ <option name="RECENT_TEMPLATES">
23
+ <list>
24
+ <option value="Python Script" />
25
+ </list>
26
+ </option>
27
+ </component>
28
+ <component name="Git.Settings">
29
+ <option name="RECENT_GIT_ROOT_PATH" value="$PROJECT_DIR$" />
30
+ </component>
31
+ <component name="ProjectColorInfo">{
32
+ &quot;associatedIndex&quot;: 8
33
+ }</component>
34
+ <component name="ProjectId" id="368YvrMt0ewdwPXScps4FAd05Jq" />
35
+ <component name="ProjectLevelVcsManager">
36
+ <ConfirmationsSetting value="1" id="Add" />
37
+ </component>
38
+ <component name="ProjectViewState">
39
+ <option name="hideEmptyMiddlePackages" value="true" />
40
+ <option name="showLibraryContents" value="true" />
41
+ </component>
42
+ <component name="PropertiesComponent">{
43
+ &quot;keyToString&quot;: {
44
+ &quot;ModuleVcsDetector.initialDetectionPerformed&quot;: &quot;true&quot;,
45
+ &quot;RunOnceActivity.ShowReadmeOnStart&quot;: &quot;true&quot;,
46
+ &quot;RunOnceActivity.TerminalTabsStorage.copyFrom.TerminalArrangementManager&quot;: &quot;true&quot;,
47
+ &quot;RunOnceActivity.git.unshallow&quot;: &quot;true&quot;,
48
+ &quot;git-widget-placeholder&quot;: &quot;main&quot;,
49
+ &quot;last_opened_file_path&quot;: &quot;F:/zpz/Projects3/tilekit/src/tilekit&quot;,
50
+ &quot;node.js.detected.package.eslint&quot;: &quot;true&quot;,
51
+ &quot;node.js.detected.package.tslint&quot;: &quot;true&quot;,
52
+ &quot;node.js.selected.package.eslint&quot;: &quot;(autodetect)&quot;,
53
+ &quot;node.js.selected.package.tslint&quot;: &quot;(autodetect)&quot;,
54
+ &quot;nodejs_package_manager_path&quot;: &quot;npm&quot;,
55
+ &quot;settings.editor.selected.configurable&quot;: &quot;com.jetbrains.python.configuration.PyActiveSdkModuleConfigurable&quot;,
56
+ &quot;vue.rearranger.settings.migration&quot;: &quot;true&quot;
57
+ }
58
+ }</component>
59
+ <component name="RecentsManager">
60
+ <key name="CopyFile.RECENT_KEYS">
61
+ <recent name="F:\zpz\Projects3\tilekit\src\tilekit" />
62
+ <recent name="F:\zpz\Projects3\tilekit\tilekit" />
63
+ </key>
64
+ <key name="MoveFile.RECENT_KEYS">
65
+ <recent name="F:\zpz\Projects3\tilekit\test" />
66
+ </key>
67
+ </component>
68
+ <component name="SharedIndexes">
69
+ <attachedChunks>
70
+ <set>
71
+ <option value="bundled-js-predefined-d6986cc7102b-b26f3e71634d-JavaScript-PY-251.26094.141" />
72
+ <option value="bundled-python-sdk-9f8e2b94138c-36ea0e71a18c-com.jetbrains.pycharm.pro.sharedIndexes.bundled-PY-251.26094.141" />
73
+ </set>
74
+ </attachedChunks>
75
+ </component>
76
+ <component name="TaskManager">
77
+ <task active="true" id="Default" summary="默认任务">
78
+ <changelist id="7ecbaad1-0830-4879-b1c9-a862886743c8" name="更改" comment="" />
79
+ <created>1764389899006</created>
80
+ <option name="number" value="Default" />
81
+ <option name="presentableId" value="Default" />
82
+ <updated>1764389899006</updated>
83
+ <workItem from="1764389900136" duration="637000" />
84
+ <workItem from="1764390545007" duration="171000" />
85
+ <workItem from="1764390726886" duration="1651000" />
86
+ <workItem from="1764392460821" duration="643000" />
87
+ <workItem from="1764393268748" duration="2106000" />
88
+ </task>
89
+ <servers />
90
+ </component>
91
+ <component name="TypeScriptGeneratedFilesManager">
92
+ <option name="version" value="3" />
93
+ </component>
94
+ </project>
tilekit-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,212 @@
1
+ Metadata-Version: 2.4
2
+ Name: tilekit
3
+ Version: 0.1.0
4
+ Summary: tilekit
5
+ Author: ZPZ
6
+ License: Apache-2.0
7
+ Requires-Python: >=3.11
8
+ Requires-Dist: mercantile>=1.2.1
9
+ Requires-Dist: numpy>=2.3.5
10
+ Requires-Dist: pillow>=12.0.0
11
+ Requires-Dist: rasterio>=1.4.3
12
+ Requires-Dist: requests>=2.32.5
13
+ Requires-Dist: tqdm>=4.67.1
14
+ Description-Content-Type: text/markdown
15
+
16
+ # tilekit
17
+
18
+ A lightweight toolkit for downloading **JL1 (Jilin-1)** XYZ/TMS tiles and saving them as **georeferenced GeoTIFFs**.
19
+
20
+ `tilekit` wraps the low-level HTTP requests, TMS/XYZ conversion, logging, and raster writing into a simple, high-level API based on `mercantile`, `rasterio`, and `Pillow`.
21
+
22
+ ---
23
+
24
+ ## Features
25
+
26
+ - 🗺 **Bounding box download**
27
+ Construct tile lists from a lon/lat bounding box and zoom level.
28
+
29
+ - 📐 **Shapefile-based download**
30
+ Use a polygon boundary (shapefile, EPSG:4326) to determine the tile coverage.
31
+
32
+ - 🔁 **XYZ → TMS conversion**
33
+ Handles the JL1 API’s TMS-style Y coordinate internally, while filenames remain in standard XYZ.
34
+
35
+ - ⏸ **Resume support / precheck**
36
+ Skips tiles that already exist on disk (`z/x/y.tif`) to avoid duplicate downloads.
37
+
38
+ - 🧍 **Human-like throttling**
39
+ Randomized delays between requests to mimic human behavior and reduce the risk of rate limiting.
40
+
41
+ - 🧾 **Structured logging**
42
+ Logs progress and errors both to console and to `download.log` in the output folder.
43
+
44
+ ---
45
+
46
+ ## Installation
47
+
48
+ Once published on PyPI:
49
+
50
+ ```bash
51
+ pip install tilekit
52
+ ```
53
+
54
+
55
+
56
+ ## Getting Started
57
+
58
+ ### 1. Download tiles by lon/lat bounding box
59
+
60
+ ```
61
+ from tilekit.downloader import TileDownloader
62
+
63
+ min_lon = 114.98
64
+ max_lon = 117.20
65
+ min_lat = 38.69
66
+ max_lat = 41.18
67
+ zoom = 18
68
+
69
+ # JL1 API keys (replace with your own)
70
+ mk = "your_mk_token_here"
71
+ tk = "your_tk_token_here"
72
+
73
+ downloader = TileDownloader.from_lon_lat(
74
+ min_lat=min_lat,
75
+ max_lat=max_lat,
76
+ min_lon=min_lon,
77
+ max_lon=max_lon,
78
+ zoom=zoom,
79
+ mk=mk,
80
+ tk=tk,
81
+ )
82
+
83
+ print("Total tiles to download:", len(downloader.tile_list))
84
+
85
+ downloader.download_tiles(
86
+ output_folder=r"F:\xxx\JL1Tiles",
87
+ verbose_debug=False,
88
+ )
89
+ ```
90
+
91
+ This will:
92
+
93
+ - Compute all tiles covering the bounding box at zoom level 18
94
+ - Convert XYZ Y to JL1’s TMS convention internally
95
+ - Download each tile and save it as `z/x/y.tif` with proper georeferencing
96
+
97
+ ------
98
+
99
+ ### 2. Download tiles based on a shapefile boundary
100
+
101
+ ```
102
+ from tilekit.downloader import TileDownloader
103
+
104
+ zoom = 18
105
+ mk = "your_mk_token_here"
106
+ tk = "your_tk_token_here"
107
+
108
+ # Shapefile should be in EPSG:4326 (lon/lat)
109
+ shp_path = r"beijing.shp"
110
+
111
+ downloader = TileDownloader.from_shp(
112
+ shp_path=shp_path,
113
+ zoom=zoom,
114
+ mk=mk,
115
+ tk=tk,
116
+ )
117
+
118
+ print("Total tiles to download:", len(downloader.tile_list))
119
+
120
+ downloader.download_tiles(
121
+ output_folder=r"F:\xxx\JL1Tiles",
122
+ verbose_debug=False,
123
+ )
124
+ ```
125
+
126
+ `from_shp` will:
127
+
128
+ - Read the shapefile using `geopandas`
129
+ - Reproject to EPSG:4326 if necessary
130
+ - Use the overall bounding box (`total_bounds`) to determine the tile range
131
+
132
+ > Note: `geopandas` is only required if you use `from_shp`.
133
+ > You can install it via `pip install geopandas`.
134
+
135
+ ------
136
+
137
+ ## API Overview
138
+
139
+ ### `TileDownloader`
140
+
141
+ ```
142
+ @dataclass
143
+ class TileDownloader:
144
+ tile_list: Sequence[mercantile.Tile]
145
+ mk: str = "..."
146
+ tk: str = "..."
147
+ zoom: Optional[int] = None
148
+
149
+ def download_tiles(
150
+ self,
151
+ output_folder: Union[str, Path],
152
+ tile_list: Optional[Sequence[Tile]] = None,
153
+ verbose_debug: bool = False,
154
+ ) -> None:
155
+ ...
156
+ ```
157
+
158
+ **Key methods:**
159
+
160
+ - `TileDownloader.from_lon_lat(min_lat, max_lat, min_lon, max_lon, zoom, mk, tk)`
161
+ Build a downloader from a bounding box.
162
+ - `TileDownloader.from_shp(shp_path, zoom, mk, tk)`
163
+ Build a downloader from a shapefile boundary.
164
+ - `TileDownloader.from_XYZs(tiles, mk, tk)`
165
+ Build a downloader from an existing list of `mercantile.Tile` objects (all at the same zoom level).
166
+ - `TileDownloader.download_tiles(output_folder, tile_list=None, verbose_debug=False)`
167
+ Download all tiles and save as GeoTIFF files (`z/x/y.tif`), skipping files that already exist.
168
+
169
+ ------
170
+
171
+ ## Output Format
172
+
173
+ Each downloaded tile is saved as a **multi-band GeoTIFF**:
174
+
175
+ - Filename: `output_folder/z/x/y.tif`
176
+ - Coordinate reference system: `EPSG:4326`
177
+ - Transform: computed from the tile’s geographic bounds via `rasterio.transform.from_bounds`
178
+ - Compression: LZW (`Compression.lzw`)
179
+ - Bands: derived from the source image (e.g., RGB → 3 bands)
180
+
181
+ ------
182
+
183
+ ## Requirements
184
+
185
+ Core dependencies (installed automatically when you install `tilekit`):
186
+
187
+ - `mercantile`
188
+ - `rasterio`
189
+ - `numpy`
190
+ - `requests`
191
+ - `Pillow`
192
+ - `tqdm`
193
+
194
+ Optional (for shapefile-based workflows):
195
+
196
+ - `geopandas`
197
+
198
+ ------
199
+
200
+ ## Notes
201
+
202
+ - You must provide valid **JL1 API keys** (`mk`, `tk`) to access the tile service.
203
+ The examples in this README use placeholder values; please replace them with your own.
204
+ - The downloader includes:
205
+ - A precheck step that skips already downloaded tiles
206
+ - Randomized delays between requests via `human_delay` to reduce the risk of being rate-limited
207
+
208
+ ------
209
+
210
+ ## License
211
+
212
+ `tilekit` is released under the **Apache 2.0** License.
@@ -0,0 +1,197 @@
1
+ # tilekit
2
+
3
+ A lightweight toolkit for downloading **JL1 (Jilin-1)** XYZ/TMS tiles and saving them as **georeferenced GeoTIFFs**.
4
+
5
+ `tilekit` wraps the low-level HTTP requests, TMS/XYZ conversion, logging, and raster writing into a simple, high-level API based on `mercantile`, `rasterio`, and `Pillow`.
6
+
7
+ ---
8
+
9
+ ## Features
10
+
11
+ - 🗺 **Bounding box download**
12
+ Construct tile lists from a lon/lat bounding box and zoom level.
13
+
14
+ - 📐 **Shapefile-based download**
15
+ Use a polygon boundary (shapefile, EPSG:4326) to determine the tile coverage.
16
+
17
+ - 🔁 **XYZ → TMS conversion**
18
+ Handles the JL1 API’s TMS-style Y coordinate internally, while filenames remain in standard XYZ.
19
+
20
+ - ⏸ **Resume support / precheck**
21
+ Skips tiles that already exist on disk (`z/x/y.tif`) to avoid duplicate downloads.
22
+
23
+ - 🧍 **Human-like throttling**
24
+ Randomized delays between requests to mimic human behavior and reduce the risk of rate limiting.
25
+
26
+ - 🧾 **Structured logging**
27
+ Logs progress and errors both to console and to `download.log` in the output folder.
28
+
29
+ ---
30
+
31
+ ## Installation
32
+
33
+ Once published on PyPI:
34
+
35
+ ```bash
36
+ pip install tilekit
37
+ ```
38
+
39
+
40
+
41
+ ## Getting Started
42
+
43
+ ### 1. Download tiles by lon/lat bounding box
44
+
45
+ ```
46
+ from tilekit.downloader import TileDownloader
47
+
48
+ min_lon = 114.98
49
+ max_lon = 117.20
50
+ min_lat = 38.69
51
+ max_lat = 41.18
52
+ zoom = 18
53
+
54
+ # JL1 API keys (replace with your own)
55
+ mk = "your_mk_token_here"
56
+ tk = "your_tk_token_here"
57
+
58
+ downloader = TileDownloader.from_lon_lat(
59
+ min_lat=min_lat,
60
+ max_lat=max_lat,
61
+ min_lon=min_lon,
62
+ max_lon=max_lon,
63
+ zoom=zoom,
64
+ mk=mk,
65
+ tk=tk,
66
+ )
67
+
68
+ print("Total tiles to download:", len(downloader.tile_list))
69
+
70
+ downloader.download_tiles(
71
+ output_folder=r"F:\xxx\JL1Tiles",
72
+ verbose_debug=False,
73
+ )
74
+ ```
75
+
76
+ This will:
77
+
78
+ - Compute all tiles covering the bounding box at zoom level 18
79
+ - Convert XYZ Y to JL1’s TMS convention internally
80
+ - Download each tile and save it as `z/x/y.tif` with proper georeferencing
81
+
82
+ ------
83
+
84
+ ### 2. Download tiles based on a shapefile boundary
85
+
86
+ ```
87
+ from tilekit.downloader import TileDownloader
88
+
89
+ zoom = 18
90
+ mk = "your_mk_token_here"
91
+ tk = "your_tk_token_here"
92
+
93
+ # Shapefile should be in EPSG:4326 (lon/lat)
94
+ shp_path = r"beijing.shp"
95
+
96
+ downloader = TileDownloader.from_shp(
97
+ shp_path=shp_path,
98
+ zoom=zoom,
99
+ mk=mk,
100
+ tk=tk,
101
+ )
102
+
103
+ print("Total tiles to download:", len(downloader.tile_list))
104
+
105
+ downloader.download_tiles(
106
+ output_folder=r"F:\xxx\JL1Tiles",
107
+ verbose_debug=False,
108
+ )
109
+ ```
110
+
111
+ `from_shp` will:
112
+
113
+ - Read the shapefile using `geopandas`
114
+ - Reproject to EPSG:4326 if necessary
115
+ - Use the overall bounding box (`total_bounds`) to determine the tile range
116
+
117
+ > Note: `geopandas` is only required if you use `from_shp`.
118
+ > You can install it via `pip install geopandas`.
119
+
120
+ ------
121
+
122
+ ## API Overview
123
+
124
+ ### `TileDownloader`
125
+
126
+ ```
127
+ @dataclass
128
+ class TileDownloader:
129
+ tile_list: Sequence[mercantile.Tile]
130
+ mk: str = "..."
131
+ tk: str = "..."
132
+ zoom: Optional[int] = None
133
+
134
+ def download_tiles(
135
+ self,
136
+ output_folder: Union[str, Path],
137
+ tile_list: Optional[Sequence[Tile]] = None,
138
+ verbose_debug: bool = False,
139
+ ) -> None:
140
+ ...
141
+ ```
142
+
143
+ **Key methods:**
144
+
145
+ - `TileDownloader.from_lon_lat(min_lat, max_lat, min_lon, max_lon, zoom, mk, tk)`
146
+ Build a downloader from a bounding box.
147
+ - `TileDownloader.from_shp(shp_path, zoom, mk, tk)`
148
+ Build a downloader from a shapefile boundary.
149
+ - `TileDownloader.from_XYZs(tiles, mk, tk)`
150
+ Build a downloader from an existing list of `mercantile.Tile` objects (all at the same zoom level).
151
+ - `TileDownloader.download_tiles(output_folder, tile_list=None, verbose_debug=False)`
152
+ Download all tiles and save as GeoTIFF files (`z/x/y.tif`), skipping files that already exist.
153
+
154
+ ------
155
+
156
+ ## Output Format
157
+
158
+ Each downloaded tile is saved as a **multi-band GeoTIFF**:
159
+
160
+ - Filename: `output_folder/z/x/y.tif`
161
+ - Coordinate reference system: `EPSG:4326`
162
+ - Transform: computed from the tile’s geographic bounds via `rasterio.transform.from_bounds`
163
+ - Compression: LZW (`Compression.lzw`)
164
+ - Bands: derived from the source image (e.g., RGB → 3 bands)
165
+
166
+ ------
167
+
168
+ ## Requirements
169
+
170
+ Core dependencies (installed automatically when you install `tilekit`):
171
+
172
+ - `mercantile`
173
+ - `rasterio`
174
+ - `numpy`
175
+ - `requests`
176
+ - `Pillow`
177
+ - `tqdm`
178
+
179
+ Optional (for shapefile-based workflows):
180
+
181
+ - `geopandas`
182
+
183
+ ------
184
+
185
+ ## Notes
186
+
187
+ - You must provide valid **JL1 API keys** (`mk`, `tk`) to access the tile service.
188
+ The examples in this README use placeholder values; please replace them with your own.
189
+ - The downloader includes:
190
+ - A precheck step that skips already downloaded tiles
191
+ - Randomized delays between requests via `human_delay` to reduce the risk of being rate-limited
192
+
193
+ ------
194
+
195
+ ## License
196
+
197
+ `tilekit` is released under the **Apache 2.0** License.
@@ -0,0 +1,28 @@
1
+ [project]
2
+ name = "tilekit"
3
+ version = "0.1.0"
4
+ description = "tilekit"
5
+ license = { text = "Apache-2.0" }
6
+ readme = { file = "README.md", content-type = "text/markdown" }
7
+ requires-python = ">=3.11"
8
+ authors = [
9
+ { name = "ZPZ" }
10
+ ]
11
+ dependencies = [
12
+ "mercantile>=1.2.1",
13
+ "numpy>=2.3.5",
14
+ "pillow>=12.0.0",
15
+ "rasterio>=1.4.3",
16
+ "requests>=2.32.5",
17
+ "tqdm>=4.67.1",
18
+ ]
19
+
20
+ [build-system]
21
+ requires = ["hatchling"]
22
+ build-backend = "hatchling.build"
23
+
24
+ # [tool.uv]
25
+ # package-dir = "src"
26
+
27
+ # [tool.hatch.build.targets.wheel]
28
+ # packages = ["src/foo"]
@@ -0,0 +1 @@
1
+ from .downloader import TileDownloader