Stargazing Place Finder
English | 中文
项目简介
专为中国观星爱好者设计,基于光污染数据、地理信息、道路可达性和望远镜光学参数,智能推荐最适合观星的地点,并生成针对特定设备的深空天体拍摄计划。
功能特点
🌌 地点发现与分析
- 智能地点推荐: 基于 VIIRS 光污染数据 + PostGIS 高程 + OSM 路网,多维度综合评分
- 光污染分析: VIIRS DNB 辐射度 → 天光散射修正 → Bortle 等级 + SQM 值
- 道路连通性: PostGIS
planet_osm_line路网图 + OSMnx 回退,计算可达性评分 - 海拔筛选: 优先推荐高海拔、视野开阔的地点
- 避开网红点: 智能过滤热门景点,寻找安静观星场所(规划中)
光污染数据有效性:分析器遵守 GeoTIFF 的 NoData 和 GDAL 掩膜,NaN/无穷值也视为缺失。
缺失像元的单点查询返回 None,批量项返回 success=False,地图瓦片透明;未标缺失的有限零值仍有效。
天光模型仅对有效样本归一化,无有效支持时保持未知,不用邻近天光补造缺失的原始辐射度。
这不代表模型经过实地校准。旧 Web/网格接口的默认显示值仍需结合来源标记解读;
地点评分公式未变,未知光污染仍走既有的 18 分回退,不能将其理解为已验证的观测条件。
🔭 望远镜与拍摄规划
- 设备预设: 内置 Seestar S50、RedCat 51、Askar FRA300 等常见望远镜参数
- 目标匹配: 根据焦距/口径/传感器/滤镜,推荐最适合拍摄的 Messier/NGC 深空天体
- FOV 可视化: 天区覆盖图、目标在焦平面上的填充比例、FOV 旋转
- 拍摄计划: 单晚逐分钟观测序列,含中天翻转警告 + 月相分离 + 窄带推荐
- 马赛克拼接: 大目标多面板拼接规划,可调重叠率(5–40%),导出面板坐标
🌙 星图与日月信息
- 交互式天图: Aladin Lite 嵌入,实时显示目标 RA/Dec + FOV 框
- 高度曲线: 目标整夜高度变化 + 适合度评分曲线
- 月相叠加: 地图上实时显示日月位置,月相影响评估
- 地点 ↔ 目标联动: 地图点击地点自动跳转可见目标,目标列表跳转天图
🗺️ 地图与可视化
- 光污染瓦片: Leaflet 多层叠加(Bortle / SQM / 辐射度)
- 候选地点标记: 聚类展示 + 详情弹出窗
- 海拔热力图: 区域高程分布
- 面板联动: 搜索结果 ↔ 天图 ↔ 目标列表统一管理
显式重建后的瓦片缓存也区分有效性变化:有效零值与 NoData/掩膜/NaN 之间可双向更新, 旧 handle 的晚到 PNG 不会覆盖新 handle 的有效性。这不增加文件自动监听或客户端缓存清理。
快速开始
安装依赖
uv sync
启动 Web 服务
uv run uvicorn server.main:app --host 0.0.0.0 --port 5001 --reload
启动后访问:
| 地址 | 说明 |
|---|---|
http://localhost:5001/ |
Web UI(Leaflet SPA) |
http://localhost:5001/api/health |
健康检查 |
http://localhost:5001/docs |
Swagger API 文档 |
Docker 部署
配合 mcp-stargazing Docker 镜像使用,SPF Web 与 MCP Server 在同一容器中通过 supervisord 管理:
docker run -p 3001:3001 -p 5001:5001 mcp-stargazing
跨仓库 CI
SPF 的 PR 会自动用当前候选 wheel 运行 mcp-stargazing 测试,并与基线结果比较。
完整规则见
mcp-stargazing/docs/dependency-chain-ci.md。
API 端点
地点分析
| 端点 | 方法 | 说明 |
|---|---|---|
/api/health |
GET | 服务健康检查 |
/api/light_pollution |
GET | 视窗光污染数据(Bortle / SQM / 辐射度) |
/api/light_pollution/tiles/{z}/{x}/{y}.png |
GET | 光污染栅格瓦片 |
/api/coordinate_analysis |
GET | 单点坐标综合分析 |
/api/analyze_stargazing_area |
GET/POST | 区域观星地点搜索(分页 + 排序) |
望远镜
| 端点 | 方法 | 说明 |
|---|---|---|
/api/telescope/presets |
GET | 望远镜设备预设列表 |
/api/telescope/optics |
POST | 计算光学参数(FOV、放大倍率、极限星等) |
/api/telescope/targets |
POST | 匹配深空天体目标(排名 + FOV 适配 + 月相) |
/api/telescope/plan |
POST | 生成单晚拍摄计划(时间序列 + 中天翻转 + 窄带推荐) |
/api/telescope/mosaic |
POST | 马赛克拼接规划(多面板 + 可调重叠率) |
技术架构
架构总览
graph TB
classDef ui fill:#e1f5fe,stroke:#0288d1,stroke-width:2px
classDef orchestration fill:#fff3e0,stroke:#f57c00,stroke-width:2px
classDef analysis fill:#e8f5e9,stroke:#388e3c,stroke-width:2px
classDef infra fill:#f3e5f5,stroke:#7b1fa2,stroke-width:2px
classDef external fill:#fce4ec,stroke:#c62828,stroke-width:2px
classDef shared fill:#e0f2f1,stroke:#00695c,stroke-width:2px
subgraph UI["用户界面层"]
CLI["CLI<br/>stargazing-finder"]
Web["Web Dashboard<br/>Leaflet SPA"]
API["REST API<br/>FastAPI"]
end
subgraph ORCH["编排层"]
SA["stargazing_analyzer<br/>综合评分·排序·协调"]
end
subgraph MOD["分析模块"]
LP["light_pollution<br/>VIIRS→Bortle·天光散射"]
RC["road_connectivity<br/>路网分析·可达性"]
TS["server/routes/telescope<br/>目标匹配·拍摄计划·马赛克"]
end
subgraph SHARED["共享层 (PyPI)"]
CORE["stargazing-core<br/>光学·天体目录·拍摄引擎"]
end
subgraph INFRA["数据基础设施"]
Cache["cache<br/>磁盘+内存缓存"]
Models["models<br/>统一数据模型"]
Utils["utils<br/>KML·地图·地理计算"]
end
subgraph EXT["外部数据源"]
VIIRS["VIIRS DNB 2025<br/>GeoTIFF"]
OSM["OpenStreetMap<br/>Overpass API"]
PG[("PostGIS<br/>空间数据库")]
end
CLI --> SA
Web --> SA
API --> SA
SA --> LP
SA --> RC
TS --> CORE
LP --> VIIRS
RC --> OSM
LP --> Cache
RC --> Cache
SA -.-> Models
SA -.-> Utils
class CLI,Web,API ui
class SA orchestration
class LP,RC,TS analysis
class CORE shared
class Cache,Models,Utils infra
class VIIRS,OSM,PG external
数据流
sequenceDiagram
participant U as 用户
participant API as FastAPI
participant SA as stargazing_analyzer
participant LP as light_pollution
participant RC as road_connectivity
participant TS as telescope routes
participant CORE as stargazing-core
participant OSM as OpenStreetMap
participant VIIRS as VIIRS GeoTIFF
participant PG as PostGIS
U->>API: 输入边界框
API->>SA: 启动分析
par 并行分析
SA->>LP: 光污染分析
LP->>VIIRS: 读取辐射度
VIIRS-->>LP: 辐射度 + 天光修正
LP-->>SA: Bortle 等级 + SQM
end
SA->>RC: 道路可达性
RC->>OSM: 查询路网
OSM-->>RC: 路网数据
RC->>PG: 高程查询
PG-->>RC: 高程数据
RC-->>SA: 可达性评分
SA-->>API: 综合排序结果
API-->>U: 候选地点列表
opt 望远镜规划
U->>TS: 选择望远镜 + 地点
TS->>CORE: match_telescope_targets
CORE-->>TS: 排名目标列表
TS-->>U: 目标 + FOV + 拍摄计划
end
核心数据模型
统一 Location 模型
class Location(BaseModel):
name: str # 地点名称
lat: float # 纬度
lon: float # 经度
elevation_m: float | None # 海拔(米)
bortle_class: int | None # Bortle 等级(1–9)
road_distance_km: float | None # 道路距离
score: float | None # 综合评分(0–100)
location_type: str # 地点类型标签
望远镜模型(来自 stargazing-core)
class TelescopeConfig(BaseModel):
focal_length_mm: float
aperture_mm: float | None
sensor_width_mm: float | None
sensor_height_mm: float | None
sensor_pixel_size_um: float | None
central_obstruction_pct: float
reducer_factor: float
barlow_factor: float
mount_type: str # "equatorial" | "altaz"
filter_type: str | None # "Hα" | "OIII" | "SII" | None
class ShootingPlan(BaseModel):
slots: list[ShootingSlot] # 时间排序的拍摄时段
moon_warnings: list[str] # 月相影响警告
total_exposure_min: float # 总曝光时间
技术栈
| 层 | 技术 |
|---|---|
| Web 框架 | FastAPI + Uvicorn |
| 前端 | Leaflet.js + Aladin Lite + 原生 JS(3142 行 app.js) |
| 光污染 | rasterio 解析 VIIRS DNB GeoTIFF + 天光散射模型 |
| 路网 | OSMnx + NetworkX + PostGIS planet_osm_line |
| 数据库 | PostGIS(高程 + 空间查询) |
| 共享库 | stargazing-core ≥ 0.1.0(PyPI) |
| 包管理 | uv |
依赖关系
stargazing-place-finder
└── stargazing-core>=0.1.0 ← PyPI registry
├── TelescopeConfig, TelescopeOptics, TELESCOPE_PRESETS
├── match_telescope_targets, score_deep_sky_objects
├── generate_shooting_schedule, ShootingPlan
├── compute_mosaic_grid (MosaicGrid, MosaicPanel)
└── CelestialPosition, MoonInfo, RiseSet, GeoPoint, ...
本地开发时如需使用未发布的 core 版本:
# pyproject.toml(不要提交此配置)
[tool.uv.sources]
stargazing-core = { path = "../stargazing-core" }
评分算法
综合评分(0–100 分)由四个维度加权计算:
| 维度 | 权重 | 说明 |
|---|---|---|
| 光污染 | 0–35 | Bortle 等级越低分越高 |
| 城镇隔离 | 0–20 | 远离光污染源加分 |
| 道路可达 | 0–20 | 路网连通性 + 距离 |
| 海拔突出 | 0–15 | 相对周边高程差 |
| 地点类型 | 0–10 | 山峰 > 天文台 > 观景台 |
数据库配置
PostGIS 用于高程数据和空间查询,支持 JSON / TOML 两种配置格式。
export STARGAZING_DB_CONFIG="/path/to/config/db_config.json"
JSON 格式:
{
"host": "192.168.1.8",
"port": 5455,
"database": "osm_db",
"user": "postgres",
"password": "postgres123"
}
无 PostGIS 时,系统自动回退到 Overpass API + Open-Elevation API。
缓存架构
由 src/cache/ 统一管理,所有缓存存储在项目根目录 cache/ 下:
cache/
├── images/ # 地图图像缓存
├── road_networks/ # 道路网络数据
├── osmnx/ # OSMnx 地图缓存
├── light_pollution/ # 光污染数据缓存
└── temp/ # 临时文件
特点:MD5 缓存键、磁盘持久化、自动恢复、按类型清理。
地图 PNG 瓦片另有进程内缓存(默认 3600 秒、最多 500 条 LRU)。缓存按实际打开的
GeoTIFF 分析器代次与瓦片坐标隔离;公开 init_light_pollution_analyzer(...) 显式重建
文件句柄及 skyglow 模型后,服务端重新请求会使用新代次。旧请求晚完成不能覆盖新代次
的瓦片;未初始化、已关闭或身份未知的句柄不能复用之前来源的瓦片。
该代次不是数据集版本或资料年龄。只替换同路径文件不会自动重载,MCP 地点结果、
其他分析器及浏览器/CDN 缓存也不会随之主动失效;HTTP max-age=3600 保持原值,
客户端可能继续复用已有响应。并发关闭/读取的完整资源租约与来源更新时间规则仍待验证。
GIS 地点查询按后端区分缓存:PostGIS 结果只在当前 GisQueryService 实例内存中
复用(默认 24 小时,读取不续期),服务/连接配置重建后重新查询;不跨数据库、用户
或实例复用磁盘结果。Overpass 仍使用内存与磁盘缓存,带独立后端标识;旧的未标记
来源条目不再读取。数据库实例内清缓存不会删除共享磁盘缓存。
这会减少数据库服务重建后的缓存复用,尚未做部署性能对照。缓存寿命不是资料年龄; 本规则不监听数据库内容、配置文件或 GeoTIFF 更新,也不保证上层结果缓存主动失效。 配置/源版本变化仍需调用方重建实际服务和文件 handle,来源更新时间未知时保持未知。
项目状态
✅ 已完成的重大更新:
| 版本 | 内容 |
|---|---|
| 0.8.0 | stargazing-core 迁移至 PyPI;FastAPI 迁移完成 |
| Phase 4 | 拍摄计划 + 马赛克拼接 + 高度曲线优化 |
| Phase 3 | 地点↔目标联动 + 月相叠加 + 面板统一 |
| Phase 1 | 望远镜天图 + FOV 旋转 + 地图 UI 刷新 |
| 0.7.0 | FastAPI 迁移(Flask → FastAPI)、测试整合 |
🔄 计划中:
- 天气数据集成(实时预报 + 观测窗口评分)
- 科学评分系统(用户自定义权重)
- 国际暗夜保护区数据
- 移动端适配
贡献指南
欢迎参与贡献!请确保代码符合项目规范,提交前通过测试。
许可证
MIT License
让我们一起探索星空,寻找最美的观星地点! ✨
Metadata
Release files for stargazing-place-finder 0.9.3
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| stargazing_place_finder-0.9.3.tar.gz | 73.7 MB | With provenance | Details for stargazing_place_finder-0.9.3.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| stargazing_place_finder-0.9.3-py3-none-any.whl | Python 3 | none | any | Details for stargazing_place_finder-0.9.3-py3-none-any.whl |
Total release size: 147.4 MB
Release files / stargazing_place_finder-0.9.3.tar.gz
| Download URL | stargazing_place_finder-0.9.3.tar.gz |
|---|---|
| Size | 73.7 MB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
74b8f163b2a6248a972aa0eb5ca3ed9cc5930168e76bbb017a033244e0b24885
|
|
BLAKE2b-256 checksum How to use checksums |
661afc5e3a1736294a081e01c59e0c46a41b40628ba5d491cc557e63d3f8d3c8
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 5, 2026.
Transparency logRelease files / stargazing_place_finder-0.9.3-py3-none-any.whl
| Download URL | stargazing_place_finder-0.9.3-py3-none-any.whl |
|---|---|
| Size | 73.7 MB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
b11b73f682e210ff8c971fda8e675e93c0c5fcda89c60814e917728376b61fba
|
|
BLAKE2b-256 checksum How to use checksums |
c6550274990c2dbcfa68e80ae4347e64ace2cc6d8901c980a5ea7144abfafe22
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.16
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 5, 2026.
Transparency logSecurity for stargazing-place-finder 0.9.3
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
Full provenance
Both files in this release have been uploaded with provenance metadata.
Attestation for stargazing_place_finder-0.9.3.tar.gz
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Nov 5, 2026.
Transparency logA note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.