mcpField
G
geomaster

geomaster

github.com/kalarislabsその他7340 回インストール3 日前に更新
リポジトリ

geomaster について

GeoMasterは、GIS、リモートセンシング、空間解析、地球観測の機械学習を扱う地理空間科学向けスキルです。幅広いトピックのコード例に加え、結果を検証するエージェントの手順を備えています。

主な機能

  1. 01GISと座標系のガイダンス
  2. 02リモートセンシングとスペクトル指数
  3. 03ベクター・ラスタの空間解析
  4. 04地形・ネットワーク解析
  5. 05地球観測の機械学習
  6. 068言語にわたるコード例

活用シーン

  1. 01Sentinel-2の植生指数の計算
  2. 02GeoPandasによる空間データの結合
  3. 03標高モデルを使った地形解析
  4. 04再現可能な地理空間ワークフローの策定

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/kalarislabs/research-agent-skills --skill geomaster

インストール後、Claude Code で/geomasterを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

README.md
references/
advanced-gis.md
big-data.md
code-examples.md
coordinate-systems.md
core-libraries.md
data-sources.md
gis-software.md
industry-applications.md
machine-learning.md
programming-languages.md
remote-sensing.md
scientific-domains.md
specialized-topics.md
troubleshooting.md

詳細

GeoMaster

GIS、リモートセンシング、空間解析、地球観測のための機械学習を網羅する包括的な地理空間科学スキルです。70以上のトピックを扱い、8つのプログラミング言語による500以上のコード例を掲載しています。

インストール

# Core Python stack (conda recommended)
conda install -c conda-forge gdal rasterio fiona shapely pyproj geopandas

# Remote sensing & ML (rsgislib is conda-forge only, not on PyPI)
conda install -c conda-forge rsgislib
uv pip install torchgeo earthengine-api
uv pip install scikit-learn xgboost torch-geometric

# Network & visualization
uv pip install osmnx networkx folium keplergl
uv pip install cartopy contextily mapclassify

# Big data & cloud
uv pip install xarray rioxarray dask-geopandas
uv pip install pystac-client planetary-computer

# Point clouds
uv pip install laspy pylas open3d pdal

# Databases
conda install -c conda-forge postgis spatialite

クイックスタート

Sentinel-2 からの NDVI 算出
import rasterio
import numpy as np

with rasterio.open('sentinel2.tif') as src:
    red = src.read(4).astype(float)   # B04
    nir = src.read(8).astype(float)   # B08
    ndvi = (nir - red) / (nir + red + 1e-8)
    ndvi = np.nan_to_num(ndvi, nan=0)

    profile = src.profile
    profile.update(count=1, dtype=rasterio.float32)

    with rasterio.open('ndvi.tif', 'w', **profile) as dst:
        dst.write(ndvi.astype(rasterio.float32), 1)
GeoPandas による空間解析
import geopandas as gpd

# Load and ensure same CRS
zones = gpd.read_file('zones.geojson')
points = gpd.read_file('points.geojson')

if zones.crs != points.crs:
    points = points.to_crs(zones.crs)

# Spatial join and statistics
joined = gpd.sjoin(points, zones, how='inner', predicate='within')
stats = joined.groupby('zone_id').agg({
    'value': ['count', 'mean', 'std', 'min', 'max']
}).round(2)
Google Earth Engine の時系列
import ee
import pandas as pd

ee.Initialize(project='your-project')
roi = ee.Geometry.Point([-122.4, 37.7]).buffer(10000)

s2 = (ee.ImageCollection('COPERNICUS/S2_SR_HARMONIZED')
      .filterBounds(roi)
      .filterDate('2020-01-01', '2023-12-31')
      .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', 20)))

def add_ndvi(img):
    return img.addBands(img.normalizedDifference(['B8', 'B4']).rename('NDVI'))

s2_ndvi = s2.map(add_ndvi)

def extract_series(image):
    stats = image.reduceRegion(ee.Reducer.mean(), roi.centroid(), scale=10, maxPixels=1e9)
    return ee.Feature(None, {'date': image.date().format('YYYY-MM-dd'), 'ndvi': stats.get('NDVI')})

series = s2_ndvi.map(extract_series).getInfo()
df = pd.DataFrame([f['properties'] for f in series['features']])
df['date'] = pd.to_datetime(df['date'])

基本概念

データ型
種類例ライブラリ
ベクターShapefile、GeoJSON、GeoPackageGeoPandas、Fiona、GDAL
ラスターGeoTIFF、NetCDF、COGRasterio、Xarray、GDAL
点群LAS、LAZLaspy、PDAL、Open3D
座標系
  • EPSG:4326(WGS 84)- 地理座標、緯度/経度。保存に使用します
  • EPSG:3857(Web Mercator)- Web マップ専用です(面積や距離の計算には使用しないでください!)
  • EPSG:326xx/327xx(UTM)- メートル単位の計算に使用します。ゾーンごとの歪みは1%未満です
  • UTM を自動検出するには gdf.estimate_utm_crs() を使用します
# Always check CRS before operations
assert gdf1.crs == gdf2.crs, "CRS mismatch!"

# For area/distance calculations, use projected CRS
gdf_metric = gdf.to_crs(gdf.estimate_utm_crs())
area_sqm = gdf_metric.geometry.area
OGC 標準
  • WMS:Web Map Service - ラスター地図
  • WFS:Web Feature Service - ベクターデータ
  • WCS:Web Coverage Service - ラスターカバレッジ
  • STAC:Spatiotemporal Asset Catalog - 最新のメタデータ

一般的な操作

スペクトル指数
def calculate_indices(image_path):
    """NDVI, EVI, SAVI, NDWI from Sentinel-2."""
    with rasterio.open(image_path) as src:
        B02, B03, B04, B08, B11 = [src.read(i).astype(float) for i in [1,2,3,4,5]]

    ndvi = (B08 - B04) / (B08 + B04 + 1e-8)
    evi = 2.5 * (B08 - B04) / (B08 + 6*B04 - 7.5*B02 + 1)
    savi = ((B08 - B04) / (B08 + B04 + 0.5)) * 1.5
    ndwi = (B03 - B08) / (B03 + B08 + 1e-8)

    return {'NDVI': ndvi, 'EVI': evi, 'SAVI': savi, 'NDWI': ndwi}
ベクター操作
# Buffer (use projected CRS!)
gdf_proj = gdf.to_crs(gdf.estimate_utm_crs())
gdf['buffer_1km'] = gdf_proj.geometry.buffer(1000)

# Spatial relationships
intersects = gdf[gdf.geometry.intersects(other_geometry)]
contains = gdf[gdf.geometry.contains(point_geometry)]

# Geometric operations
gdf['centroid'] = gdf.geometry.centroid
gdf['simplified'] = gdf.geometry.simplify(tolerance=0.001)

# Overlay operations
intersection = gpd.overlay(gdf1, gdf2, how='intersection')
union = gpd.overlay(gdf1, gdf2, how='union')
地形解析
def terrain_metrics(dem_path):
    """Calculate slope, aspect, hillshade from DEM."""
    with rasterio.open(dem_path) as src:
        dem = src.read(1)

    dy, dx = np.gradient(dem)
    slope = np.arctan(np.sqrt(dx**2 + dy**2)) * 180 / np.pi
    aspect = (90 - np.arctan2(-dy, dx) * 180 / np.pi) % 360

    # Hillshade
    az_rad, alt_rad = np.radians(315), np.radians(45)
    hillshade = (np.sin(alt_rad) * np.sin(np.radians(slope)) +
                 np.cos(alt_rad) * np.cos(np.radians(slope)) *
                 np.cos(np.radians(aspect) - az_rad))

    return slope, aspect, hillshade
ネットワーク解析
import osmnx as ox
import networkx as nx

# Download and analyze street network
G = ox.graph_from_place('San Francisco, CA', network_type='drive')
G = ox.add_edge_speeds(G).add_edge_travel_times(G)

# Shortest path
orig = ox.distance.nearest_nodes(G, -122.4, 37.7)
dest = ox.distance.nearest_nodes(G, -122.3, 37.8)
route = nx.shortest_path(G, orig, dest, weight='travel_time')

画像分類

from sklearn.ensemble import RandomForestClassifier
import rasterio
from rasterio.features import rasterize

def classify_imagery(raster_path, training_gdf, output_path):
    """Train RF and classify imagery."""
    with rasterio.open(raster_path) as src:
        image = src.read()
        profile = src.profile
        transform = src.transform

    # Extract training data
    X_train, y_train = [], []
    for _, row in training_gdf.iterrows():
        mask = rasterize([(row.geometry, 1)],
                        out_shape=(profile['height'], profile['width']),
                        transform=transform, fill=0, dtype=np.uint8)
        pixels = image[:, mask > 0].T
        X_train.extend(pixels)
        y_train.extend([row['class_id']] * len(pixels))

    # Train and predict
    rf = RandomForestClassifier(n_estimators=100, max_depth=20, n_jobs=-1)
    rf.fit(X_train, y_train)

    prediction = rf.predict(image.reshape(image.shape[0], -1).T)
    prediction = prediction.reshape(profile['height'], profile['width'])

    profile.update(dtype=rasterio.uint8, count=1)
    with rasterio.open(output_path, 'w', **profile) as dst:
        dst.write(prediction.astype(rasterio.uint8), 1)

    return rf

最新のクラウドネイティブなワークフロー

STAC + Planetary Computer
import pystac_client
import planetary_computer
import odc.stac

# Search Sentinel-2 via STAC
catalog = pystac_client.Client.open(
    "https://planetarycomputer.microsoft.com/api/stac/v1",
    modifier=planetary_computer.sign_inplace,
)

search = catalog.search(
    collections=["sentinel-2-l2a"],
    bbox=[-122.5, 37.7, -122.3, 37.9],
    datetime="2023-01-01/2023-12-31",
    query={"eo:cloud_cover": {"lt": 20}},
)

# Load as xarray (cloud-native!)
data = odc.stac.load(
    list(search.get_items())[:5],
    bands=["B02", "B03", "B04", "B08"],
    crs="EPSG:32610",
    resolution=10,
)

# Calculate NDVI on xarray
ndvi = (data.B08 - data.B04) / (data.B08 + data.B04)
クラウド最適化 GeoTIFF(COG)
import rasterio
from rasterio.session import AWSSession

# Read COG directly from cloud (partial reads)
session = AWSSession(aws_access_key_id=..., aws_secret_access_key=...)
with rasterio.open('s3://bucket/path.tif', session=session) as src:
    # Read only window of interest
    window = ((1000, 2000), (1000, 2000))
    subset = src.read(1, window=window)

# Write COG
with rasterio.open('output.tif', 'w', **profile,
                   tiled=True, blockxsize=256, blockysize=256,
                   compress='DEFLATE', predictor=2) as dst:
    dst.write(data)

# Validate COG
from rio_cogeo.cogeo import cog_validate
cog_validate('output.tif')

パフォーマンスのヒント

# 1. Spatial indexing (10-100x faster queries)
gdf.sindex  # Auto-created by GeoPandas

# 2. Chunk large rasters
with rasterio.open('large.tif') as src:
    for i, window in src.block_windows(1):
        block = src.read(1, window=window)

# 3. Dask for big data
import dask.array as da
dask_array = da.from_rasterio('large.tif', chunks=(1, 1024, 1024))

# 4. Use Arrow for I/O
gdf.to_file('output.gpkg', use_arrow=True)

# 5. GDAL caching
from osgeo import gdal
gdal.SetCacheMax(2**30)  # 1GB cache

# 6. Parallel processing
rf = RandomForestClassifier(n_jobs=-1)  # All cores

ベストプラクティス

  1. 空間操作の前に、必ず CRS を確認します
  2. 面積や距離の計算には、投影 CRS を使用します
  3. ジオメトリを検証します:gdf = gdf[gdf.is_valid]
  4. 欠損データを処理します:gdf['geometry'] = gdf['geometry'].fillna(None)
  5. 効率的な形式を使用します:GeoPackage は Shapefile より優れており、大規模データには Parquet を使用します
  6. 光学画像に雲マスキングを適用します
  7. 再現可能な研究のために、データの来歴を保持します
  8. 解析の縮尺に適した解像度を使用します

詳細ドキュメント


GeoMaster は、基本的な GIS 操作から高度なリモートセンシング、機械学習まで、あらゆる内容を網羅しています。

エージェントの作業手順

  1. 環境を確認します。 ライブラリのバージョン、単位、座標系、データ形式(FITS、CIF、HDF5、netCDF)を確認します。
  2. 入力を特定します。 データまたはユーザーから、形式、識別子、パラメーターを確認します。結果を左右する値は推測せず、質問します。
  3. まず小規模に実行します。 小さなグリッド、領域、サブセットで実行し、物理的に妥当か確認します。
  4. 上記の手順と参考情報を使用して、タスク全体を実行します。
  5. 結果を検証します。 単位と次元の整合性、保存則または既知の限界、数値収束を確認します。
  6. 報告します。 実行した内容(バージョン、コマンド、パラメーター)、確認した内容、未確定の事項を明記します。
次のような場合対応方法
結果が既知の物理的限界に反する報告する前に、単位、境界条件、ソルバーの許容誤差を確認します。
これらの手順に記載された関数、フラグ、エンドポイントがインストール済みバージョンにないインストール済みバージョンのドキュメント(help()、--help、公式ドキュメント)を確認し、適宜調整してユーザーに伝えます。API を決して捏造しません。
必須の入力、識別子、パラメーターが曖昧ユーザーに尋ねるか、実行前に仮定を明示します。

完全性に関するルール

  • 結果、パラメーター、識別子、引用、統計情報を決して捏造しません。実行または検証できない場合は、その旨を明確に伝えます。
  • 定量的な結果には、必ず不確実性と数値許容誤差を併記します。
  • ここに記載されたバージョン固有の情報は古くなっている可能性があるものとして扱い、インストール済みバージョンの公式ドキュメントで確認します。
  • 費用が発生する操作、共有 GPU やクラウドクォータを消費する操作、個人データや患者データに触れる操作、または元に戻せない操作を行う前に、ユーザーに確認します。

関連スキル

  • geopandas:GeoPandas 1.1.4 の GeoSeries と GeoDataFrame を使用した平面ベクターデータ向け Python ワークフローのガイダンスとローカル監査 CLI:CRS の処理、g…

コメント