{
  "plugins": [
    {
      "id": "boundary-fetcher",
      "path": "boundary-fetcher",
      "name": "行政区划边界",
      "name_en": "Boundary Fetcher",
      "version": "0.2.0",
      "category": "data",
      "type": "model",
      "description": "调用高德/百度行政区划 API 获取省/市/县边界，自动将 GCJ-02 / BD-09 坐标转换为 WGS84，输出标准 GeoJSON（含 CRS 元数据）。\n",
      "description_en": "Fetch administrative boundaries (province/city/district) from AMap/Baidu APIs. Auto-converts to WGS84.",
      "readme": "boundary-fetcher/README.md",
      "runner": "scripts/run.py",
      "inputs": [
        {
          "name": "keywords",
          "type": "string",
          "label": "行政区划名称",
          "label_en": "Region Names",
          "required": true,
          "default": "北京市",
          "description": "支持多个用逗号分隔，如：北京市,上海市\n",
          "description_en": "Comma-separated region names, e.g. Beijing,Shanghai"
        },
        {
          "name": "level",
          "type": "select",
          "label": "行政级别",
          "label_en": "Admin Level",
          "default": "city",
          "options": [
            "province",
            "city",
            "district"
          ],
          "description": "省 / 市 / 区县",
          "description_en": "Province / City / District"
        },
        {
          "name": "source",
          "type": "select",
          "label": "数据源",
          "label_en": "Data Source",
          "default": "amap",
          "options": [
            "amap",
            "baidu"
          ],
          "description": "高德 API（GCJ-02）或百度 API（BD-09），输出统一为 WGS84",
          "description_en": "AMap API (GCJ-02) or Baidu API (BD-09), output is WGS84"
        },
        {
          "name": "subdistricts",
          "type": "bool",
          "label": "包含下级边界",
          "label_en": "Include Sub-districts",
          "default": false,
          "description": "同时获取下级行政区划的独立边界。 例：keywords=北京市, level=city, subdistricts=true → 输出 16 个区各自的独立边界\n",
          "description_en": "Also fetch boundaries of sub-districts. e.g. keywords=Beijing, level=city, subdistricts=true → outputs 16 district boundaries\n"
        }
      ],
      "outputs": [
        {
          "name": "boundary",
          "type": "file",
          "format": "geojson",
          "description": "行政区划边界 GeoJSON（WGS84）",
          "description_en": "Administrative boundary GeoJSON (WGS84)"
        }
      ]
    },
    {
      "id": "calc",
      "path": "vector-basic/calc",
      "name": "字段计算器",
      "name_en": "Field Calculator",
      "version": "0.2.1",
      "category": "processing",
      "type": "model",
      "description": "新增或修改属性字段，支持常量赋值和字段间运算",
      "description_en": "Add or modify attribute fields with constant values or field expressions",
      "readme": "vector-basic/calc/README.md",
      "runner": "scripts/run.py",
      "inputs": [
        {
          "name": "source",
          "type": "file",
          "label": "输入矢量文件",
          "label_en": "Input Vector File",
          "required": true
        },
        {
          "name": "field_name",
          "type": "field_select",
          "label": "字段名",
          "label_en": "Field Name",
          "required": true,
          "schema_source": "source",
          "allow_custom": true,
          "description": "目标字段名（新字段或已有字段）",
          "description_en": "Target field name (new or existing field)"
        },
        {
          "name": "expression",
          "type": "expression",
          "label": "表达式",
          "label_en": "Expression",
          "required": true,
          "schema_source": "source",
          "field_template": "[{field}]",
          "description": "常量值（如 100）或字段运算（如 [field_a] + [field_b]）",
          "description_en": "Constant value (e.g. 100) or field expression (e.g. [field_a] + [field_b])"
        },
        {
          "name": "field_type",
          "type": "select",
          "label": "字段类型",
          "label_en": "Field Type",
          "default": "float",
          "options": [
            "float",
            "int",
            "str"
          ]
        },
        {
          "name": "output_format",
          "type": "select",
          "label": "输出格式",
          "label_en": "Output Format",
          "default": "geojson",
          "options": [
            "geojson",
            "csv"
          ],
          "description": "写出文件的格式",
          "description_en": "Output file format"
        }
      ],
      "outputs": [
        {
          "name": "result",
          "type": "file",
          "formats": [
            "geojson",
            "csv"
          ],
          "description": "计算结果",
          "description_en": "Calculation result"
        }
      ],
      "builtin": true
    },
    {
      "id": "clip",
      "path": "vector-basic/clip",
      "name": "矢量裁剪",
      "name_en": "Vector Clip",
      "version": "0.3.1",
      "category": "processing",
      "type": "model",
      "description": "使用多边形边界裁剪矢量要素，自动处理 CRS 不匹配",
      "description_en": "Clip vector features by polygon boundary, auto-handle CRS mismatch",
      "readme": "vector-basic/clip/README.md",
      "runner": "scripts/run.py",
      "inputs": [
        {
          "name": "source",
          "type": "file",
          "label": "输入矢量文件",
          "label_en": "Input Vector File",
          "required": true
        },
        {
          "name": "boundary",
          "type": "boundary_draw",
          "label": "裁剪边界",
          "label_en": "Clip Boundary",
          "required": true,
          "description": "输入边界文件路径，或从目录选择已有文件，或在地图上绘制",
          "description_en": "Enter boundary file path, select from directory, or draw on map"
        },
        {
          "name": "keep_attrs",
          "type": "bool",
          "label": "保留边界属性",
          "label_en": "Keep Boundary Attributes",
          "default": false,
          "description": "将边界的属性字段合并到裁剪结果",
          "description_en": "Merge boundary attribute fields into clip result"
        }
      ],
      "outputs": [
        {
          "name": "clipped",
          "type": "file",
          "format": "geojson",
          "description": "裁剪后的要素 GeoJSON",
          "description_en": "Clipped feature GeoJSON"
        }
      ],
      "builtin": true
    },
    {
      "id": "crop",
      "path": "raster-basic/crop",
      "name": "通用栅格裁剪",
      "name_en": "Raster Crop",
      "version": "0.2.0",
      "category": "processing",
      "type": "model",
      "description": "通用栅格裁剪工具。使用矢量边界（GeoJSON）对任意 GeoTIFF 栅格进行裁剪， 自动处理 CRS 不匹配（将矢量重投影到栅格 CRS）。\n",
      "description_en": "General-purpose raster clipping using vector boundaries. Automatically handles CRS mismatches.",
      "readme": "raster-basic/crop/README.md",
      "runner": "scripts/run.py",
      "inputs": [
        {
          "name": "raster",
          "type": "file",
          "label": "输入栅格 (GeoTIFF)",
          "label_en": "Input Raster (GeoTIFF)",
          "required": false,
          "description": "待裁剪的栅格文件（与栅格目录二选一）",
          "description_en": "Raster file to clip (mutually exclusive with raster directory)"
        },
        {
          "name": "rasters_dir",
          "type": "directory",
          "label": "栅格目录",
          "label_en": "Raster Directory",
          "required": false,
          "description": "批量裁剪：输入目录路径，自动处理所有 GeoTIFF（与单栅格二选一）",
          "description_en": "Batch mode: process all GeoTIFFs in directory (mutually exclusive with single raster)"
        },
        {
          "name": "boundary",
          "type": "file",
          "label": "裁剪边界 (GeoJSON)",
          "label_en": "Clip Boundary (GeoJSON)",
          "required": true,
          "description": "矢量边界文件，支持 MultiPolygon",
          "description_en": "Vector boundary file, supports MultiPolygon"
        },
        {
          "name": "attribute_filter",
          "type": "string",
          "label": "属性过滤",
          "label_en": "Attribute Filter",
          "default": "",
          "description": "如 ADM1_NAME=北京市，从边界中选择单个要素。 格式：字段名=字段值\n",
          "description_en": "e.g. ADM1_NAME=Beijing, select a single feature from boundary. Format: field_name=field_value\n"
        },
        {
          "name": "output_prefix",
          "type": "string",
          "label": "输出前缀",
          "label_en": "Output Prefix",
          "default": "",
          "description": "批量模式下输出文件的前缀（可选）",
          "description_en": "Prefix for output files in batch mode (optional)"
        },
        {
          "name": "keep_crs",
          "type": "bool",
          "label": "保持原始 CRS",
          "label_en": "Keep Original CRS",
          "default": true,
          "description": "输出栅格保持与输入相同的 CRS",
          "description_en": "Output raster keeps the same CRS as input"
        }
      ],
      "outputs": [
        {
          "name": "cropped",
          "type": "file",
          "format": "geotiff",
          "description": "裁剪后的栅格文件（单文件模式）；批量模式下为输出目录路径",
          "description_en": "Cropped raster file (single mode); output directory path (batch mode)"
        }
      ],
      "builtin": true
    },
    {
      "id": "filter",
      "path": "vector-basic/filter",
      "name": "矢量过滤",
      "name_en": "Vector Filter",
      "version": "0.3.1",
      "category": "processing",
      "type": "model",
      "description": "按属性表达式和/或空间范围对矢量要素进行过滤",
      "description_en": "Filter vector features by attribute expression and/or spatial bounding box",
      "readme": "vector-basic/filter/README.md",
      "runner": "scripts/run.py",
      "inputs": [
        {
          "name": "source",
          "type": "file",
          "label": "输入矢量文件",
          "label_en": "Input Vector File",
          "required": true,
          "description": "GeoJSON / CSV / Shapefile"
        },
        {
          "name": "expression",
          "type": "expression",
          "label": "属性过滤表达式",
          "label_en": "Attribute Filter Expression",
          "default": "",
          "schema_source": "source",
          "field_template": "{field}",
          "description": "如 field=value, 或 field>100。支持 =, !=, >, <, >=, <=",
          "description_en": "e.g. field=value or field>100. Supports =, !=, >, <, >=, <="
        },
        {
          "name": "output_format",
          "type": "select",
          "label": "输出格式",
          "label_en": "Output Format",
          "default": "geojson",
          "options": [
            "geojson",
            "csv"
          ],
          "description": "写出文件的格式",
          "description_en": "Output file format"
        }
      ],
      "outputs": [
        {
          "name": "filtered",
          "type": "file",
          "formats": [
            "geojson",
            "csv"
          ],
          "description": "过滤后的要素",
          "description_en": "Filtered features"
        }
      ],
      "builtin": true
    },
    {
      "id": "geocoder",
      "path": "geocoder",
      "name": "地址转坐标",
      "name_en": "Geocoder",
      "version": "0.2.0",
      "category": "processing",
      "type": "model",
      "description": "读取地址文件（CSV 或纯文本），调用高德/百度地理编码 API 将地址转换为经纬度坐标，统一输出 WGS84 格式的 GeoJSON / CSV。 输出的坐标可直接接入 projection 模型做投影变换。\n",
      "description_en": "Convert addresses to coordinates via AMap/Baidu geocoding API. Outputs WGS84 GeoJSON/CSV.",
      "readme": "geocoder/README.md",
      "runner": "scripts/run.py",
      "inputs": [
        {
          "name": "file",
          "type": "file",
          "label": "地址文件",
          "label_en": "Address File",
          "required": true,
          "description": "包含地址的 CSV 文件，或每行一个地址的纯文本文件（.txt）",
          "description_en": "CSV file with addresses, or plain text file with one address per line (.txt)"
        },
        {
          "name": "address_column",
          "type": "string",
          "label": "地址列名",
          "label_en": "Address Column",
          "required": false,
          "default": "address",
          "description": "CSV 中地址所在的列名（纯文本文件忽略此项）",
          "description_en": "Column name for addresses in CSV (ignored for plain text files)"
        },
        {
          "name": "source",
          "type": "select",
          "label": "地理编码服务",
          "label_en": "Geocoding Service",
          "required": true,
          "default": "amap",
          "options": [
            "amap",
            "baidu"
          ],
          "description": "amap=高德地图 / baidu=百度地图",
          "description_en": "amap=AMap / baidu=Baidu Maps"
        },
        {
          "name": "city",
          "type": "string",
          "label": "城市",
          "label_en": "City",
          "required": false,
          "default": "",
          "description": "城市名称，用于地址消歧（可选，留空由 API 自动判断）",
          "description_en": "City name for address disambiguation (optional)"
        },
        {
          "name": "batch_delay",
          "type": "number",
          "label": "调用间隔(ms)",
          "label_en": "Call Interval (ms)",
          "required": false,
          "default": 200,
          "description": "每次 API 调用间隔毫秒数，避免触发频率限制",
          "description_en": "Milliseconds between API calls to avoid rate limiting"
        },
        {
          "name": "output_format",
          "type": "select",
          "label": "输出格式",
          "label_en": "Output Format",
          "required": false,
          "default": "geojson",
          "options": [
            "geojson",
            "csv",
            "both"
          ],
          "description": "geojson=GeoJSON / csv=CSV / both=两者",
          "description_en": "geojson=GeoJSON / csv=CSV / both=both"
        }
      ],
      "outputs": [
        {
          "name": "result",
          "type": "file",
          "format": "geojson/csv",
          "description": "地理编码结果文件",
          "description_en": "Geocoding result file"
        }
      ]
    },
    {
      "id": "join",
      "path": "vector-basic/join",
      "name": "属性连接",
      "name_en": "Attribute Join",
      "version": "0.3.1",
      "category": "processing",
      "type": "model",
      "description": "按字段对两个矢量数据集进行属性表连接",
      "description_en": "Join attributes from one vector dataset to another by key field",
      "readme": "vector-basic/join/README.md",
      "runner": "scripts/run.py",
      "inputs": [
        {
          "name": "target",
          "type": "file",
          "label": "目标图层",
          "label_en": "Target Layer",
          "required": true,
          "description": "主图层，保留其全部要素",
          "description_en": "Primary layer, all features are retained"
        },
        {
          "name": "source",
          "type": "file",
          "label": "连接图层",
          "label_en": "Join Layer",
          "required": true,
          "description": "附图层，提供待连接的属性",
          "description_en": "Secondary layer providing attributes to join"
        },
        {
          "name": "target_field",
          "type": "field_select",
          "label": "目标图层的连接字段",
          "label_en": "Target Layer Key Field",
          "required": true,
          "schema_source": "target"
        },
        {
          "name": "source_field",
          "type": "field_select",
          "label": "连接图层的连接字段",
          "label_en": "Join Layer Key Field",
          "required": true,
          "schema_source": "source"
        },
        {
          "name": "how",
          "type": "select",
          "label": "连接方式",
          "label_en": "Join Method",
          "default": "left",
          "options": [
            {
              "label": "保留全部记录（左连接）",
              "label_en": "Keep all records (left join)",
              "value": "left"
            },
            {
              "label": "仅保留匹配记录（内连接）",
              "label_en": "Keep only matched records (inner join)",
              "value": "inner"
            }
          ]
        }
      ],
      "outputs": [
        {
          "name": "joined",
          "type": "file",
          "format": "geojson",
          "description": "连接后的 GeoJSON",
          "description_en": "Joined GeoJSON"
        }
      ],
      "builtin": true
    },
    {
      "id": "poi-grabber",
      "path": "poi-grabber",
      "name": "POI 抓取器",
      "name_en": "POI Grabber",
      "version": "0.2.0",
      "category": "data",
      "type": "model",
      "description": "调用高德 / 百度 / OpenStreetMap API， 按城市和关键词抓取 POI（兴趣点），输出 CSV 和 GeoJSON。 支持自动分页抓取与坐标去重。\n",
      "description_en": "Fetch POI (Points of Interest) from AMap / Baidu Maps / OpenStreetMap by keyword search. Supports automatic pagination and coordinate deduplication.",
      "readme": "poi-grabber/README.md",
      "runner": "scripts/run.py",
      "inputs": [
        {
          "name": "city",
          "type": "string",
          "label": "城市名称",
          "label_en": "City Name",
          "required": true,
          "default": "北京",
          "description": "搜索目标城市，如 北京、上海、广州",
          "description_en": "Target city for search, e.g. Beijing, Shanghai"
        },
        {
          "name": "keyword",
          "type": "string",
          "label": "搜索关键词",
          "label_en": "Search Keyword",
          "required": true,
          "default": "咖啡厅",
          "description": "POI 关键词，如 咖啡厅、医院、学校、博物馆",
          "description_en": "POI keyword, e.g. cafe, hospital, school, museum"
        },
        {
          "name": "source",
          "type": "select",
          "label": "数据源",
          "label_en": "Data Source",
          "required": true,
          "default": "amap",
          "options": [
            "amap",
            "baidu",
            "osm"
          ],
          "description": "高德地图 / 百度地图 / OpenStreetMap",
          "description_en": "AMap / Baidu Maps / OpenStreetMap"
        },
        {
          "name": "page_size",
          "type": "number",
          "label": "每页大小",
          "label_en": "Page Size",
          "default": 20,
          "description": "每次 API 请求返回的最大记录数",
          "description_en": "Max records per API request"
        },
        {
          "name": "max_pages",
          "type": "number",
          "label": "最大页数",
          "label_en": "Max Pages",
          "default": 10,
          "description": "最大分页请求次数，控制总抓取量",
          "description_en": "Maximum pagination requests, controls total fetch volume"
        },
        {
          "name": "fetch_all",
          "type": "bool",
          "label": "获取全部",
          "label_en": "Fetch All",
          "default": false,
          "description": "开启后自动翻页获取 API 允许的全部结果（覆盖最大页数设置），适用于需要完整数据集时",
          "description_en": "Auto-fetch all results from API (overrides max pages), suitable when a complete dataset is needed"
        },
        {
          "name": "output_format",
          "type": "select",
          "label": "输出格式",
          "label_en": "Output Format",
          "default": "geojson",
          "options": [
            "geojson",
            "csv",
            "both"
          ],
          "description": "GeoJSON（默认，含空间字段）/ CSV（含经纬度字段）/ 两者都输出",
          "description_en": "GeoJSON (default, with spatial fields) / CSV (with lat/lng fields) / both"
        }
      ],
      "outputs": [
        {
          "name": "result",
          "type": "file",
          "format": "geojson/csv",
          "description": "POI 数据文件（output_format 决定格式）",
          "description_en": "POI data file (format determined by output_format)"
        }
      ]
    },
    {
      "id": "poi-kde",
      "path": "poi/poi-kde",
      "name": "POI 核密度分析",
      "name_en": "POI Kernel Density Estimation",
      "version": "0.2.0",
      "category": "visualization",
      "type": "model",
      "description": "基于 POI 点数据生成核密度估计热力图，识别空间聚集区域。 输入应为投影坐标（推荐前置 projection 模型预处理）， 支持交互式 HTML 和静态 PNG 输出。\n",
      "description_en": "Generate kernel density estimation heatmaps from POI point data to identify spatial clustering areas.",
      "readme": "poi/poi-kde/README.md",
      "runner": "scripts/run.py",
      "inputs": [
        {
          "name": "points",
          "type": "file",
          "label": "POI 点数据 (CSV 或 GeoJSON)",
          "label_en": "POI Point Data (CSV or GeoJSON)",
          "required": true,
          "description": "含投影坐标的点数据（projection 模型输出）",
          "description_en": "Point data with projected coordinates (output from projection model)"
        },
        {
          "name": "x_col",
          "type": "string",
          "label": "X 坐标列名",
          "label_en": "X Coordinate Column",
          "default": "x",
          "description": "投影坐标系下的 X 坐标列名",
          "description_en": "X coordinate column name in projected CRS"
        },
        {
          "name": "y_col",
          "type": "string",
          "label": "Y 坐标列名",
          "label_en": "Y Coordinate Column",
          "default": "y",
          "description": "投影坐标系下的 Y 坐标列名",
          "description_en": "Y coordinate column name in projected CRS"
        },
        {
          "name": "crs",
          "type": "string",
          "label": "输入 CRS (EPSG 代码或 auto)",
          "label_en": "Input CRS (EPSG code or auto)",
          "default": "auto",
          "description": "'auto' = 从 dst_epsg 列自动检测， 或手动指定如 3857, 32650\n",
          "description_en": "'auto' = auto-detect from dst_epsg column, or manually specify e.g. 3857, 32650\n"
        },
        {
          "name": "bandwidth",
          "type": "number",
          "label": "带宽 (米)",
          "label_en": "Bandwidth (m)",
          "default": 500,
          "description": "核密度带宽，单位米（投影坐标系距离）",
          "description_en": "KDE bandwidth in meters (projected CRS distance)"
        },
        {
          "name": "grid_size",
          "type": "number",
          "label": "网格大小",
          "label_en": "Grid Size",
          "default": 200,
          "description": "密度栅格的边长像素数（越大越精细但越慢）",
          "description_en": "Density grid pixel size per side (larger = finer but slower)"
        },
        {
          "name": "output_format",
          "type": "select",
          "label": "输出格式",
          "label_en": "Output Format",
          "default": "html",
          "options": [
            "html",
            "png",
            "all"
          ],
          "description": "交互式 HTML（folium）/ 静态 PNG（matplotlib）/ 全部输出",
          "description_en": "Interactive HTML (folium) / Static PNG (matplotlib) / all"
        }
      ],
      "outputs": [
        {
          "name": "heatmap",
          "type": "file",
          "format": "html/png",
          "description": "核密度热力图",
          "description_en": "KDE heatmap"
        }
      ]
    },
    {
      "id": "poi-pipeline",
      "path": "poi/poi-pipeline",
      "name": "设施抓取与核密度分析",
      "name_en": "POI Pipeline",
      "version": "0.2.0",
      "category": "analysis",
      "type": "pipeline",
      "description": "依次执行 POI 抓取、坐标投影、核密度分析，一键生成设施分布热力图。 适用于城市设施集聚度分析、服务半径评估等场景。\n",
      "description_en": "Sequentially executes POI fetch → coordinate projection → kernel density estimation to generate facility distribution heatmaps in one click.\n",
      "readme": "poi/poi-pipeline/README.md",
      "runner": "",
      "inputs": [
        {
          "name": "city",
          "type": "string",
          "label": "城市名称",
          "label_en": "City Name",
          "required": true,
          "default": "上海市"
        },
        {
          "name": "keyword",
          "type": "string",
          "label": "搜索关键词",
          "label_en": "Search Keyword",
          "required": true,
          "default": "中学"
        }
      ],
      "outputs": [
        {
          "name": "heatmap",
          "type": "file",
          "format": "html",
          "description": "核密度热力图",
          "description_en": "KDE heatmap"
        }
      ]
    },
    {
      "id": "population-age-extractor",
      "path": "population/population-age-extractor",
      "name": "人口年龄结构提取",
      "name_en": "Population Age Structure Extractor",
      "version": "0.2.0",
      "category": "analysis",
      "type": "model",
      "description": "从 WorldPop 年龄性别栅格目录中批量提取各年龄段人口数。 输入为 population-downloader 年龄性别模式输出的栅格目录 + 区域边界， 输出带年龄和性别维度的结构化 CSV，可直接用于人口金字塔绘制。\n",
      "description_en": "Batch-extract population counts by age group from WorldPop age-sex raster directories.",
      "readme": "population/population-age-extractor/README.md",
      "runner": "scripts/run.py",
      "inputs": [
        {
          "name": "rasters_dir",
          "type": "directory",
          "label": "年龄性别栅格目录",
          "label_en": "Age-Sex Raster Directory",
          "required": true,
          "description": "包含所有年龄分组 GeoTIFF 的目录（population-downloader age_sex 模式输出）",
          "description_en": "Directory of per-age-group GeoTIFFs (output from population-downloader age_sex mode)"
        },
        {
          "name": "zones",
          "type": "file",
          "label": "分区边界 (GeoJSON)",
          "label_en": "Zone Boundary (GeoJSON)",
          "required": true,
          "description": "统计区域边界多边形",
          "description_en": "Zonal boundary polygons"
        },
        {
          "name": "zone_id_field",
          "type": "string",
          "label": "区域标识字段",
          "label_en": "Zone ID Field",
          "default": "name",
          "description": "边界 GeoJSON 中标识区域的属性字段名",
          "description_en": "Attribute field name identifying zones in boundary GeoJSON"
        },
        {
          "name": "statistics",
          "type": "select",
          "label": "统计量",
          "label_en": "Statistics",
          "default": "sum",
          "options": [
            "sum",
            "sum_mean",
            "all"
          ],
          "description": "输出的统计指标：sum=人口总和；sum_mean=总和+均值；all=全部指标",
          "description_en": "Output statistics: sum=total; sum_mean=total+mean; all=all metrics"
        }
      ],
      "outputs": [
        {
          "name": "age_sex_stats",
          "type": "file",
          "format": "csv",
          "description": "年龄性别分区统计 CSV",
          "description_en": "Age-sex zonal statistics CSV"
        }
      ]
    },
    {
      "id": "population-aggregator",
      "path": "population/population-aggregator",
      "name": "人口分区统计",
      "name_en": "Population Aggregator",
      "version": "0.2.0",
      "category": "analysis",
      "type": "model",
      "description": "对人口栅格进行分区聚合统计。输入人口栅格和分区边界（GeoJSON）， 输出各区域的人口统计汇总，支持总和、均值等多种统计量。\n",
      "description_en": "Compute zonal statistics from population rasters. Outputs per-zone population summaries.",
      "readme": "population/population-aggregator/README.md",
      "runner": "scripts/run.py",
      "inputs": [
        {
          "name": "raster",
          "type": "file",
          "label": "人口栅格 (GeoTIFF)",
          "label_en": "Population Raster (GeoTIFF)",
          "required": true,
          "description": "人口分布栅格文件",
          "description_en": "Population distribution raster file"
        },
        {
          "name": "zones",
          "type": "file",
          "label": "分区边界 (GeoJSON)",
          "label_en": "Zone Boundary (GeoJSON)",
          "required": true,
          "description": "统计区域边界多边形",
          "description_en": "Zonal boundary polygons"
        },
        {
          "name": "zone_id_field",
          "type": "string",
          "label": "区域标识字段",
          "label_en": "Zone ID Field",
          "default": "name",
          "description": "边界 GeoJSON 中标识区域的属性字段名",
          "description_en": "Attribute field name identifying zones in boundary GeoJSON"
        },
        {
          "name": "statistics",
          "type": "select",
          "label": "统计量",
          "label_en": "Statistics",
          "default": "sum",
          "options": [
            "sum",
            "sum_mean",
            "all"
          ],
          "description": "输出的统计指标：sum=人口总和；sum_mean=总和+均值；all=全部指标",
          "description_en": "Output statistics: sum=total population; sum_mean=total+mean; all=all metrics"
        }
      ],
      "outputs": [
        {
          "name": "statistics",
          "type": "file",
          "format": "csv",
          "description": "分区人口统计结果 CSV",
          "description_en": "Zonal population statistics CSV"
        }
      ]
    },
    {
      "id": "population-downloader",
      "path": "population-downloader",
      "name": "人口栅格下载器",
      "name_en": "Population Raster Downloader",
      "version": "0.2.0",
      "category": "data",
      "type": "model",
      "description": "从 WorldPop 下载高分辨率人口分布栅格数据。支持总人口分布和分年龄/性别的人口结构数据， 提供约束版（联合国校准）和未约束版两种数据集。\n",
      "description_en": "Download high-resolution population distribution rasters from WorldPop. Supports total population and age/sex structure data.",
      "readme": "population-downloader/README.md",
      "runner": "scripts/run.py",
      "inputs": [
        {
          "name": "country",
          "type": "select",
          "label": "国家/地区",
          "label_en": "Country / Region",
          "required": true,
          "default": "CHN",
          "options": [
            "CHN",
            "JPN",
            "KOR",
            "IDN",
            "VNM",
            "THA",
            "PHL",
            "MYS",
            "MMR",
            "KHM",
            "LAO",
            "MNG",
            "NPL",
            "BGD",
            "IND",
            "PAK",
            "LKA",
            "AFG"
          ],
          "description": "ISO3 国家代码",
          "description_en": "ISO3 country code"
        },
        {
          "name": "year",
          "type": "number",
          "label": "年份",
          "label_en": "Year",
          "default": 2020,
          "description": "数据年份 (2000-2020)",
          "description_en": "Data year (2000-2020)"
        },
        {
          "name": "resolution",
          "type": "select",
          "label": "分辨率",
          "label_en": "Resolution",
          "default": "100m",
          "options": [
            "100m",
            "1km"
          ],
          "description": "栅格分辨率（当前仅支持 100m 原生分辨率）",
          "description_en": "Raster resolution (currently only 100m native supported)"
        },
        {
          "name": "dataset",
          "type": "select",
          "label": "数据类型",
          "label_en": "Dataset Type",
          "default": "population",
          "options": [
            "population",
            "age_sex"
          ],
          "description": "总人口或分年龄性别数据",
          "description_en": "Total population or age/sex structure data"
        },
        {
          "name": "constrained",
          "type": "bool",
          "label": "约束版数据",
          "label_en": "Constrained Data",
          "default": true,
          "description": "约束版（联合国校准）或未约束版",
          "description_en": "Constrained (UN calibrated) or unconstrained version"
        },
        {
          "name": "max_workers",
          "type": "number",
          "label": "并行下载数",
          "label_en": "Parallel Downloads",
          "default": 12,
          "description": "年龄性别模式下同时下载的文件数（越大越快，但可能触发服务器限流）",
          "description_en": "Concurrent downloads in age_sex mode (higher = faster but may trigger rate limiting)"
        }
      ],
      "outputs": [
        {
          "name": "rasters",
          "type": "file",
          "format": "geotiff",
          "description": "总人口栅格文件；年龄性别模式下为包含所有分文件的目录",
          "description_en": "Total population raster; or directory of per-age rasters in age_sex mode"
        }
      ]
    },
    {
      "id": "population-pyramid",
      "path": "population/population-pyramid",
      "name": "人口金字塔",
      "name_en": "Population Pyramid",
      "version": "0.2.0",
      "category": "visualization",
      "type": "model",
      "description": "根据人口年龄结构数据绘制人口金字塔图。 输入 population-age-extractor 输出的结构化 CSV， 输出交互式 HTML 或静态 PNG 图像，支持按区域筛选。\n",
      "description_en": "Generate population pyramid charts from age structure data with interactive HTML or static PNG output.",
      "readme": "population/population-pyramid/README.md",
      "runner": "scripts/run.py",
      "inputs": [
        {
          "name": "age_sex_data",
          "type": "file",
          "label": "年龄性别统计数据 (CSV)",
          "label_en": "Age-Sex Statistics (CSV)",
          "required": true,
          "description": "包含 zone_id, age_group, sex, population_sum 等列的结构化 CSV",
          "description_en": "Structured CSV with zone_id, age_group, sex, population_sum columns"
        },
        {
          "name": "zone_id",
          "type": "string",
          "label": "区域筛选",
          "label_en": "Zone Filter",
          "default": "",
          "description": "指定要绘制的区域 ID（留空则不筛选，使用 CSV 中的第一个区域）",
          "description_en": "Zone ID to plot (leave empty for first zone in CSV)"
        },
        {
          "name": "title",
          "type": "string",
          "label": "图表标题",
          "label_en": "Chart Title",
          "default": "人口金字塔",
          "description": "图表标题",
          "description_en": "Chart title"
        },
        {
          "name": "output_format",
          "type": "select",
          "label": "输出格式",
          "label_en": "Output Format",
          "default": "html",
          "options": [
            "html",
            "png",
            "all"
          ],
          "description": "可视化输出格式",
          "description_en": "Visualization output format"
        }
      ],
      "outputs": [
        {
          "name": "visualization",
          "type": "file",
          "format": "html/png",
          "description": "人口金字塔可视化文件",
          "description_en": "Population pyramid visualization file"
        }
      ]
    },
    {
      "id": "population-visualizer",
      "path": "population/population-visualizer",
      "name": "人口分布可视化",
      "name_en": "Population Visualizer",
      "version": "0.2.0",
      "category": "visualization",
      "type": "model",
      "description": "将人口栅格或分区统计数据渲染为可视化地图。支持栅格直接渲染和分区统计分级图两种模式， 输出交互式 HTML 或静态 PNG。\n",
      "description_en": "Render population rasters or zonal statistics as interactive HTML maps or static PNG images.",
      "readme": "population/population-visualizer/README.md",
      "runner": "scripts/run.py",
      "inputs": [
        {
          "name": "data",
          "type": "file",
          "label": "输入数据",
          "label_en": "Input Data",
          "required": true,
          "description": "人口栅格 (GeoTIFF) 或分区统计 (CSV)",
          "description_en": "Population raster (GeoTIFF) or zonal statistics (CSV)"
        },
        {
          "name": "data_type",
          "type": "select",
          "label": "数据类型",
          "label_en": "Data Type",
          "default": "raster",
          "options": [
            "raster",
            "zonal_csv"
          ],
          "description": "输入数据的类型",
          "description_en": "Type of input data"
        },
        {
          "name": "boundary",
          "type": "file",
          "label": "边界文件 (GeoJSON)",
          "label_en": "Boundary File (GeoJSON)",
          "required": false,
          "description": "zonal_csv 模式下用于分级统计图的边界文件",
          "description_en": "Boundary file for choropleth map in zonal_csv mode"
        },
        {
          "name": "output_format",
          "type": "select",
          "label": "输出格式",
          "label_en": "Output Format",
          "default": "html",
          "options": [
            "html",
            "png",
            "all"
          ],
          "description": "可视化输出格式",
          "description_en": "Visualization output format"
        },
        {
          "name": "title",
          "type": "string",
          "label": "图表标题",
          "label_en": "Chart Title",
          "default": "人口分布",
          "description": "地图标题",
          "description_en": "Map title"
        }
      ],
      "outputs": [
        {
          "name": "visualization",
          "type": "file",
          "format": "html/png",
          "description": "可视化文件",
          "description_en": "Visualization file"
        }
      ]
    },
    {
      "id": "projection",
      "path": "vector-basic/projection",
      "name": "坐标投影",
      "name_en": "Coordinate Projection",
      "version": "0.2.0",
      "category": "processing",
      "type": "model",
      "description": "将 WGS84 经纬度点数据转换为投影坐标系（EPSG:3857 Web Mercator、 自动 UTM 或自定义 CRS），输出 GeoJSON / CSV。作为 poi-grabber 下游，为 poi-kde 等需要平面距离的模型提供前置处理。\n",
      "description_en": "Transform WGS84 point data to projected coordinate systems. Supports Web Mercator, automatic UTM, and custom CRS.",
      "readme": "vector-basic/projection/README.md",
      "runner": "scripts/run.py",
      "inputs": [
        {
          "name": "points",
          "type": "file",
          "label": "POI 点数据 (CSV 或 GeoJSON)",
          "label_en": "POI Point Data (CSV or GeoJSON)",
          "required": true,
          "description": "包含经纬度字段的 POI 数据文件",
          "description_en": "POI data file containing longitude/latitude fields"
        },
        {
          "name": "lng_col",
          "type": "string",
          "label": "经度列名",
          "label_en": "Longitude Column",
          "default": "lng",
          "description": "CSV 文件中的经度字段名（GeoJSON 忽略此参数）",
          "description_en": "Longitude column name in CSV (ignored for GeoJSON)"
        },
        {
          "name": "lat_col",
          "type": "string",
          "label": "纬度列名",
          "label_en": "Latitude Column",
          "default": "lat",
          "description": "CSV 文件中的纬度字段名（GeoJSON 忽略此参数）",
          "description_en": "Latitude column name in CSV (ignored for GeoJSON)"
        },
        {
          "name": "target_crs",
          "type": "string",
          "label": "目标 CRS (EPSG 代码或 auto-utm)",
          "label_en": "Target CRS (EPSG code or auto-utm)",
          "default": "3857",
          "description": "目标投影坐标系。常用值: 3857 (Web Mercator), auto-utm (根据数据质心自动选择 UTM 分带), 或任意 EPSG 代码如 32650。\n",
          "description_en": "Target projected CRS. Common values: 3857 (Web Mercator), auto-utm (auto-select UTM zone by data centroid), or any EPSG code like 32650.\n"
        },
        {
          "name": "output_format",
          "type": "select",
          "label": "输出格式",
          "label_en": "Output Format",
          "default": "geojson",
          "options": [
            "geojson",
            "csv",
            "both"
          ],
          "description": "GeoJSON（默认）/ CSV（保留原字段+新增x/y/epsg列）/ 两者都输出",
          "description_en": "GeoJSON (default) / CSV (retain fields + add x/y/epsg) / both"
        }
      ],
      "outputs": [
        {
          "name": "projected",
          "type": "file",
          "format": "geojson/csv",
          "description": "投影后的数据文件（output_format 决定格式）",
          "description_en": "Projected data file (format determined by output_format)"
        }
      ],
      "builtin": true
    }
  ]
}