Install any skill in seconds. Free to start, no credit card required.
Get Started Free →GIS analysis and remote sensing workflows for geospatial research applications
.claude/skills/brycewang-stanford-gis-remote-sensing-guide/SKILL.md| Test case | Without → With | Effect | Δ tokens | Δ turns |
|---|---|---|---|---|
| case-14 | ✗→✓ | ▲ Improved | 189% | 0% |
| case-16 | ✗→✓ | ▲ Improved | 12% | 0% |
| case-15 | ✓→✓ | = Same ✓ | 49% | 0% |
| case-01 | ✓→✓ | = Same ✓ | 17% | 0% |
| case-05 | ✓→✓ | = Same ✓ | 19% | 0% |
A comprehensive skill for conducting geospatial analysis and remote sensing research. Covers data acquisition from satellite platforms, spatial analysis with open-source tools, and publication-quality map production.
| Platform | Provider | Spatial Res. | Revisit | Free? | Use Case | |----------|----------|-------------|---------|-------|----------| | Landsat 8/9 | USGS/NASA | 30m (MS), 15m (pan) | 16 days | Yes | Land cover, NDVI time series | | Sentinel-2 | ESA/Copernicus | 10m | 5 days | Yes | Agriculture, urban mapping | | MODIS | NASA | 250m-1km | 1-2 days | Yes | Large-scale vegetation, fire | | Sentinel-1 | ESA | 5-20m | 6 days | Yes | SAR, flood mapping, deformation | | SRTM/ASTER | NASA | 30m | N/A | Yes | Digital elevation models |
pythonimport ee # Initialize Google Earth Engine ee.Initialize() def get_sentinel2_composite(aoi: ee.Geometry, start: str, end: str, cloud_max: int = 20) -> ee.Image: """ Create a cloud-free Sentinel-2 composite. Args: aoi: Area of interest as ee.Geometry start: Start date (YYYY-MM-DD) end: End date (YYYY-MM-DD) cloud_max: Maximum cloud cover percentage """ collection = (ee.ImageCollection('COPERNICUS/S2_SR_HARMONIZED') .filterBounds(aoi) .filterDate(start, end) .filter(ee.Filter.lt('CLOUDY_PIXEL_PERCENTAGE', cloud_max))) # Cloud masking using SCL band def mask_clouds(image): scl = image.select('SCL') mask = scl.neq(3).And(scl.neq(8)).And(scl.neq(9)).And(scl.neq(10)) return image.updateMask(mask) return collection.map(mask_clouds).median().clip(aoi) # Define study area study_area = ee.Geometry.Rectangle([116.0, 39.5, 117.0, 40.5]) # Beijing region composite = get_sentinel2_composite(study_area, '2024-06-01', '2024-09-30')
pythonimport geopandas as gpd from shapely.geometry import Point def spatial_join_analysis(points_gdf: gpd.GeoDataFrame, polygons_gdf: gpd.GeoDataFrame, agg_col: str) -> gpd.GeoDataFrame: """ Perform spatial join and aggregate point data within polygons. """ joined = gpd.sjoin(points_gdf, polygons_gdf, how='inner', predicate='within') summary = joined.groupby('index_right').agg( count=(agg_col, 'count'), mean_value=(agg_col, 'mean'), std_value=(agg_col, 'std') ).reset_index() result = polygons_gdf.merge(summary, left_index=True, right_on='index_right') return result # Example: aggregate soil samples within administrative boundaries soil_samples = gpd.read_file('soil_data.geojson') admin_bounds = gpd.read_file('admin_boundaries.shp') result = spatial_join_analysis(soil_samples, admin_bounds, 'pH_value')
pythonimport rasterio import numpy as np def compute_indices(image_path: str) -> dict: """Compute common remote sensing spectral indices.""" with rasterio.open(image_path) as src: red = src.read(3).astype(float) # Band 4 in Sentinel-2 nir = src.read(4).astype(float) # Band 8 green = src.read(2).astype(float) # Band 3 swir = src.read(5).astype(float) # Band 11 # Normalized Difference Vegetation Index ndvi = (nir - red) / (nir + red + 1e-10) # Normalized Difference Water Index ndwi = (green - nir) / (green + nir + 1e-10) # Normalized Burn Ratio nbr = (nir - swir) / (nir + swir + 1e-10) return {'NDVI': ndvi, 'NDWI': ndwi, 'NBR': nbr}
For publication-quality maps, always include: scale bar, north arrow, coordinate reference system label, legend, and data source attribution. Use matplotlib with cartopy for projected maps, or folium for interactive web maps. Export at 300 DPI minimum for journal submissions.
Always verify and document the CRS. Use EPSG codes (e.g., EPSG:4326 for WGS84, EPSG:32650 for UTM Zone 50N). Reproject all layers to a common CRS before spatial operations to avoid misalignment errors.
| Case | Status | Duration (ms) | Turns | Tokens | Tool calls | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Without | With | Δ | Without | With | Δ | Without | With | Δ | Without | With | Δ | ||
case-15 | pass→pass | 9,600 | 6,961 | -27% | 1 | 1 | 0% | 1,660 | 2,472 | +49% | 0 | 0 | — |
case-01 | pass→pass | 16,375 | 18,440 | +13% | 1 | 1 | 0% | 3,054 | 3,588 | +17% | 0 | 0 | — |
case-02 | fail→fail | 14,854 | 12,701 | -14% | 1 | 1 | 0% | 3,130 | 3,917 | +25% | 0 | 0 | — |
case-03 | fail→fail | 13,805 | 14,817 | +7% | 1 | 1 | 0% | 2,844 | 4,245 | +49% | 0 | 0 | — |
case-04 | fail→fail | 16,479 | 12,591 | -24% | 1 | 1 | 0% | 2,998 | 3,820 | +27% | 0 | 0 | — |
case-05 | pass→pass | 10,472 | 4,348 | -58% | 1 | 1 | 0% | 1,632 | 1,944 | +19% | 0 | 0 | — |
case-06 | pass→pass | 13,899 | 12,339 | -11% | 1 | 1 | 0% | 2,416 | 3,507 | +45% | 0 | 0 | — |
case-07 | pass→pass | 7,300 | 3,457 | -53% | 1 | 1 | 0% | 1,325 | 1,839 | +39% | 0 | 0 | — |
case-08 | pass→pass | 4,129 | 3,339 | -19% | 1 | 1 | 0% | 725 | 1,839 | +154% | 0 | 0 | — |
case-09 | pass→pass | 11,162 | 10,652 | -5% | 1 | 1 | 0% | 1,948 | 3,169 | +63% | 0 | 0 | — |
case-10 | pass→pass | 14,500 | 14,734 | +2% | 1 | 1 | 0% | 2,169 | 3,532 | +63% | 0 | 0 | — |
case-11 | pass→pass | 13,191 | 11,178 | -15% | 1 | 1 | 0% | 2,003 | 3,074 | +53% | 0 | 0 | — |
case-12 | pass→pass | 6,470 | 4,694 | -27% | 1 | 1 | 0% | 1,120 | 2,090 | +87% | 0 | 0 | — |
case-13 | pass→pass | 6,132 | 6,053 | -1% | 1 | 1 | 0% | 930 | 2,348 | +152% | 0 | 0 | — |
case-14 | fail→pass | 6,604 | 9,171 | +39% | 1 | 1 | 0% | 937 | 2,708 | +189% | 0 | 0 | — |
case-16 | fail→pass | 9,351 | 3,316 | -65% | 1 | 1 | 0% | 1,694 | 1,903 | +12% | 0 | 0 | — |
case-17 | pass→pass | 8,505 | 3,866 | -55% | 1 | 1 | 0% | 1,506 | 1,971 | +31% | 0 | 0 | — |
case-18 | pass→pass | 8,183 | 8,390 | +3% | 1 | 1 | 0% | 1,613 | 2,836 | +76% | 0 | 0 | — |
case-19 | pass→pass | 11,497 | 13,364 | +16% | 1 | 1 | 0% | 2,026 | 3,713 | +83% | 0 | 0 | — |
case-20 | pass→pass | 25,721 | 20,431 | -21% | 1 | 1 | 0% | 4,754 | 5,418 | +14% | 0 | 0 | — |
case-21 | pass→pass | 16,626 | 16,627 | +0% | 1 | 1 | 0% | 3,240 | 4,199 | +30% | 0 | 0 | — |
case-22 | pass→pass | 15,239 | 15,874 | +4% | 1 | 1 | 0% | 2,415 | 3,678 | +52% | 0 | 0 | — |
DecimalAI ran this skill against gemini-3.6-flash twice over the same eval suite — once with the skill loaded and once without — and compared the two runs case by case. 22 cases were attempted. The headline lift of +9 percentage points is the difference between those two pass rates over the 22 comparable cases.
Without the skill loaded, the model failed this case. With it loaded, the same prompt on the same model passed. This is one improved case from the latest verified run; every case, including any that regressed, is in the table above.
Other measured skills in the registry, with their headline benchmark lift.