0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Webベースの水理・水文解析プラットフォームを独自に作る構想を立てる

0
Last updated at Posted at 2026-08-12

Webベースの水理・水文解析プラットフォームを独自に作る構想を立てる

はじめに

水文・河川分野の解析では、雨量、流量、水位、地形、河道、氾濫、土砂、ダム操作、人口・建物など、扱うデータが多くなります。

解析ソフトも一つでは済みません。多数のアプリを組み合わせる事により結果を得ることができます。

例えば、雨量を整理して流出解析を行い、その流量を河川解析へ渡し、さらに氾濫解析や被害評価へつなげる場合、実務では次のような作業が発生します。

  • 雨量データを解析用に加工する
  • 流出解析結果をCSVへ出力する
  • 河川解析用の境界条件へ変換する
  • 氾濫解析結果をGISへ読み込む
  • ケースごとに入力ファイルを複製する
  • どのデータ版、モデル版、パラメータで計算したのかを後から確認する
  • 別の担当者へ引き継ぐために、データと計算条件を整理し直す

このあたりを個別のツールでつないでいくと、解析そのものよりもデータ管理やケース管理に時間を取られるようになります。

そこで、個々の解析ソフトを単独で作るのではなく、Project Workspaceと共通データ基盤を中心に、複数の解析アプリケーションを追加できるWebベースの解析プラットフォームを作ることを考えます。

既存の水文・河川解析ソフトウェア群の構成は参考にしますが、特定製品の互換環境を作ることが目的ではありません。

目標は、日本国内の水文・河川データや実務の進め方に合わせて拡張できる、独自の解析基盤です。そして、最終的には、データの取得から、報告書作成までを行う基盤を作成する事です。


1. まず決めたい全体像

最初に考えている構成は次のようなものです。

ChatGPT Image 2026年8月10日 20_57_13.png

ポイントは、解析エンジンを中心にしないことです。

システム全体の中心に置くのは、

Project Workspace
        +
共通データ基盤

です。

解析アプリケーションは、その上でデータを利用し、結果を戻す側と考えます。


2. Projectは「フォルダー」ではなくWorkspaceにする

このプラットフォームでは、Projectを単なる保存先にはしません。

Projectは、

一つの河川・流域・検討業務について、データ、モデル、シナリオ、計算履歴、整備状況をまとめて管理するWorkspace

とします。

例えば、Projectを開いたときに最初に見たいのは、ファイル一覧よりも現在の作業状況です。

解析対象河川
====================================================

概要 | データ | モデル | シナリオ | Run | 履歴

データ整備状況
----------------------------------------------------
流域界              登録済み
河川中心線          登録済み
観測所              12地点
雨量                登録済み
水位                一部不足
流量                登録済み
DEM                 5m
河道断面            未登録
粗度                未登録

解析準備状況
----------------------------------------------------
Rainfall Studio     READY
Runoff Studio       READY
River Studio        NOT READY
Flood Studio        NOT READY

最近のRun
----------------------------------------------------
run-0027            SUCCEEDED
run-0026            FAILED
run-0025            SUCCEEDED

この画面をProject Workspaceの入口にします。


3. Projectで管理するもの

Project配下では、少なくとも次の情報をまとめます。

Project
│
├── ProjectSetting
│
├── ProjectDataset
│   ├── 流域
│   ├── 河川
│   ├── 観測所
│   ├── 雨量
│   ├── 水位
│   ├── 流量
│   └── DEM
│
├── ProjectModel
│   ├── Runoff Model
│   ├── River Model
│   └── Flood Model
│
├── Scenario
│
├── Run
│
├── ProjectReadiness
│
├── ProjectSnapshot
│
└── ProjectActivity

ここで、ProjectDatasetDatasetは同じものではありません。

Projectには「このProjectでどのデータを使用するか」を関連付けます。

データ本体はData Hub側で管理します。


4. ProjectとData Hubは役割を分ける

Project WorkspaceとData Hubを混ぜると、後で責務が分かりにくくなります。

役割は次のように分けます。

機能 役割
Project Workspace このProjectで何を使うか、何が不足しているかを管理
Data Hub データそのものを登録・検索・更新・版管理する
Model 解析モデルとモデル版を管理
Scenario 解析条件の組み合わせを管理
Run 実際の計算実行と履歴を管理
Experiment 複数Runの比較や実験を管理
Workflow 複数解析をつないで実行する

関係は次のようになります。

ChatGPT Image 2026年8月10日 21_02_26.png

Project Workspaceは、

「何を使っているか」

を管理します。

Data Hubは、

「データそのもの」

を管理します。


5. DatasetはProjectごとに物理コピーしない

同じDEMや観測データを複数Projectで利用することがあります。

そのため、

Project A ─┐
Project B ─┼── DatasetVersion DEM-r003
Project C ─┘

という参照構造にします。

データモデルとしては、例えば次のようにします。

Projectをコピーしても、10GBのDEMを複製する必要はありません。


6. Projectコピーを最初から考えておく

解析では、現況ケースを基に改修案や計画案を作ることが多くあります。

例えば、

解析対象河川_現況
     │
     ├── Clone → 解析対象河川_改修案A
     │
     └── Clone → 解析対象河川_改修案B

という使い方です。

Projectコピー時には、何を引き継ぐか選べるようにします。

Projectをコピー

コピー元
  解析対象河川_現況

新しいProject
  解析対象河川_改修案A

コピー対象
  ☑ Project設定
  ☑ Dataset参照
  ☑ Model参照
  ☑ Scenario
  ☐ Run履歴
  ☐ 計算結果

通常は、Run履歴や計算結果まではコピーしません。


7. Project削除はアーカイブを基本にする

ProjectにRunや計算結果が残るようになると、簡単なDELETEは危険です。

そのため通常操作では、

ACTIVE
  ↓
ARCHIVED

とします。

アーカイブしたProjectは復元できます。

完全削除が必要な場合は、

ARCHIVED
  ↓
DELETE_REQUESTED
  ↓
PURGED

のように段階を分けます。

Projectを削除した結果、過去のRunが再現できなくなることは避けます。


8. Project Snapshotを用意する

Projectは時間とともに変化します。

例えば、

DEM       r001 → r002
Rainfall  r004 → r005
Model     r002 → r003
Scenario  r001 → r002

と更新されます。

そこで、Projectのある時点の状態を固定できるProjectSnapshotを持たせます。

ProjectSnapshot
  snapshot-20260810-001

Datasets
  rainfall r005
  dem      r003
  river    r002

Models
  runoff   r004
  river    r002

Scenario
  current-condition-r002

Runを実行するときには、このSnapshotに近い情報を固定します。

これによって、

「この計算を実行したときに、どのデータとモデルを使っていたか」

を後から確認できます。


9. 解析準備状況を自動判定する

Project画面では、各解析アプリケーションが実行可能か確認できるようにします。

判定は手入力だけにせず、必要データのルールから求めます。

例えばRunoff Studioなら、

application: runoff

required:
  - watershed
  - rainfall

recommended:
  - observed_discharge
  - evapotranspiration

River Studioなら、

application: river

required:
  - river_network
  - cross_sections
  - roughness
  - upstream_discharge
  - downstream_boundary

Flood Studioなら、

application: flood

required:
  - dem
  - roughness
  - boundary_condition

recommended:
  - landuse
  - levee
  - buildings

Project Workspaceでは、この定義を基に、

Runoff Studio    READY
River Studio     2項目不足
Flood Studio     3項目不足

と表示します。


10. ポータル型のWebアプリケーションにする

利用者は最初に統合ポータルへアクセスします。

ChatGPT Image 2026年8月10日 21_05_32.png

単なるリンク集にはしません。

どの画面へ移動しても、

Project
Scenario
対象期間
使用Dataset
使用Model
最新Run

などを共有します。


11. 共通データ基盤がシステムの中心

解析アプリケーション同士を直接結合しないようにします。

例えば、流出解析で計算した流量は、CSVを介してRiver Studioへ渡すのではなく、共通データ基盤へ登録します。

ChatGPT Image 2026年8月10日 21_07_41.png

こうしておくと、解析エンジンを交換しても次の解析への接続を保ちやすくなります。


12. データと解析モデルを分離する

例えばDEMはFlood Studio専用にはしません。

DEM
 ├── 流出解析
 ├── 河川解析
 ├── 氾濫解析
 ├── 土砂移動解析
 └── 土石流解析

雨量も同様です。

Rainfall
 ├── 雨量解析
 ├── 流出解析
 ├── 土石流解析
 └── リスク評価

共通データ基盤へ一度登録し、Project側で利用する版を指定します。


13. 日本向けの共通データモデルを作る

独自基盤なので、日本国内の水文・河川データを扱いやすい構造にできます。

例えば観測所です。

station_id
name

provider
provider_station_id

river_system
river_name
watershed_id

longitude
latitude
crs

elevation
vertical_datum

valid_from
valid_to

雨量時系列なら、

series_id
station_id

timestamp
period_start
period_end

value
unit

quality
revision

source
dataset_version

とします。

水位では、観測値と高さ基準を分けます。

station_id
timestamp

gauge_level_m
gauge_zero_elevation_m
vertical_datum

elevation_m

quality
revision

単純な、

timestamp,value

だけではなく、

  • どの地点か
  • 何の物理量か
  • どの単位か
  • どの期間の値か
  • 観測か計算か
  • 品質はどうか
  • 何版か
  • 出典は何か

を追跡できるようにします。


14. 保存形式を一つに統一しない

独自データ基盤だからといって、一つの専用ファイル形式を作る必要はありません。

データの特性ごとに使い分けます。

データ 主な保存方式
Project・Model・Scenario・Run PostgreSQL
観測所・河川・流域 PostGIS
最新観測値 PostgreSQL
長期間の時系列 Parquet
ベクターGIS GeoParquet
GIS検索・集計 DuckDB Spatial
DEM COG
時系列格子 Zarr
元データ MinIO
計算結果原本 MinIO
Web地図 PMTiles / MVT
外部ソフト受け渡し Adapterごとの形式

共通データモデルと保存形式は分けて考えます。


15. Data Hub

Data Hubでは、データそのものを管理します。

主な機能は、

  • データ登録
  • データ検索
  • データ確認
  • DatasetVersion管理
  • 品質管理
  • 出典管理
  • GIS表示
  • 時系列表示
  • Projectへの割り当て

です。

例えば観測所を開くと、

観測所
  ○○雨量観測所

提供元
  ○○県

データ
  10分雨量

期間
  2000/01/01 ~ 2026/08/09

品質
  CHECKED

DatasetVersion
  rainfall-r005

利用Project
  解析対象河川
  ○○川検討業務

といった情報を確認できるようにします。

地図はOpenLayers、時系列グラフはPlotlyなどを利用します。


16. Rainfall Studio

雨量データを確認・加工するアプリケーションです。

対象候補は、

  • 観測雨量
  • レーダ雨量
  • 解析雨量
  • 予測雨量
  • 累積雨量
  • 実効雨量
  • IDW補間
  • 流域平均雨量
  • メッシュ平均雨量

などです。

Rainfall Studioで作成したデータも、DatasetまたはRun Artifactとして共通基盤へ戻します。


17. Runoff Studio

降雨流出解析を行います。

雨量
 ↓
流域
 ↓
パラメータ
 ↓
流出モデル
 ↓
流量

モデルは一種類に固定せず、Engineとして追加できる構造にします。

Tank Model
SCS-CN
Kinematic Wave
XGBoost
LSTM
NeuralHydrology
Differentiable Model

共通インターフェースのイメージは次のようになります。

from __future__ import annotations

from typing import Protocol


class RunoffEngine(Protocol):
    """降雨流出Engineが実装する共通インターフェース。

    Web UIやFastAPIから解析式を直接呼ばないようにし、
    Worker側から共通の呼び出し方で解析Engineを扱うことを目的とする。

    Tank Model、LSTM、GPU実装などに変更しても、
    PortalやRun管理側へ解析固有の実装を持ち込まない構成にする。
    """

    def prepare(
        self,
        project_snapshot,
        scenario,
        parameters: dict[str, float],
    ) -> None:
        """解析入力を準備する。

        Parameters
        ----------
        project_snapshot:
            Run開始時に固定したDatasetVersionやModelVersionを含むSnapshot。
        scenario:
            対象期間や初期条件などをまとめた解析Scenario。
        parameters:
            Engineへ渡すモデルパラメータ。
        """
        ...

    def run(self):
        """解析本体を実行し、Engine固有の計算結果を返す。"""
        ...

    def collect_results(self):
        """共通データ基盤へ保存可能な形で計算結果を整理して返す。"""
        ...

18. River Studio

River Studioでは、河道内の1次元解析を扱います。

上流流量
下流水位
河道断面
粗度
構造物
 ↓
1D河川計算
 ↓
水位
流量
流速

Runoff Studioの結果は、共通データ基盤に保存されたRun Resultを境界条件として利用します。


19. Flood Studio

2次元氾濫解析を担当します。

入力候補は、

DEM
土地利用
粗度
河川水位
河川流量
降雨
堤防
構造物

です。

出力は、

最大浸水深
最大流速
到達時間
浸水継続時間

などです。

大きな格子結果はCOGやZarrへ保存し、WebではOpenLayersから表示します。


20. Sediment / Debris Flow Studio

土砂移動や土石流も、同じプラットフォーム上の解析アプリとして追加します。

DEM
雨量
流量
粒径
河床条件
土砂量
 ↓
解析Engine
 ↓
流動深
流速
侵食量
堆積量
到達範囲

Python、Fortran、C++、GPU、MPIといったEngine実装の違いは、PortalやProject管理から切り離します。


21. Reservoir Studio

ダム、調節池、ゲート、ポンプなどの施設操作を扱います。

流入量
貯水位
放流規則
ゲート操作
 ↓
施設操作モデル
 ↓
放流量
貯水位

Workflow上では、RunoffとRiverの間に入るケースもあります。


22. Impact Studio

解析結果と社会データを組み合わせて、影響を整理します。

例えば、

浸水深
人口
建物
道路
重要施設

から、

浸水人口
浸水建物数
建物被害
道路影響
重要施設影響

などを集計します。

e-Stat、PLATEAU、国土数値情報などもData Hub経由で利用できる構成を考えます。


23. Workflow Studio

各解析が揃ってきた段階で、複数解析を連続実行できるようにします。

ChatGPT Image 2026年8月10日 21_26_02.png

WorkflowはYAMLやJSONでも定義できるようにします。

workflow:
  name: flood_analysis

  steps:
    - id: runoff
      engine: runoff
      model: runoff-r003

    - id: river
      engine: river_1d
      model: river-r002
      inputs:
        upstream_discharge: runoff.discharge

    - id: flood
      engine: flood_2d
      model: flood-r004
      inputs:
        boundary: river.water_level

    - id: impact
      engine: damage
      inputs:
        water_depth: flood.max_depth

ProjectやScenarioを変えても、同じWorkflow定義を再利用できる形を目指します。


24. 解析処理はWorkerで実行する

解析処理をFastAPIのHTTPリクエスト内で直接実行しません。

ChatGPT Image 2026年8月10日 21_27_29.png

数秒の解析でも、数時間かかる解析でも、Runとして同じ流れで扱います。


25. Runを共通概念にする

すべての解析はRunとして管理します。

QUEUED
 ↓
PREPARING
 ↓
RUNNING
 ↓
POSTPROCESSING
 ↓
SUCCEEDED

異常終了は、

FAILED

とします。

Runには最低でも次を保存します。

run_id
project_id
project_snapshot_id
scenario_id

engine
engine_version
model_version

input_dataset_versions
parameters

started_at
finished_at

status
progress

logs
artifacts

これによって、計算結果と入力条件を追跡できます。


26. Experiment & Calibration Studio

解析モデルを増やすと、「計算できる」だけでは足りなくなります。

例えば、

  • パラメータを変えた結果を比較したい
  • NSEやRMSEを一覧で比較したい
  • 計算時間を比較したい
  • CPU版とGPU版を比べたい
  • 最良パラメータを正式なModelVersionとして保存したい

といった作業が必要になります。

そこで、

Experiment Tracking
    └─ MLflow

Calibration / Optimization
    └─ Optuna

を拡張機能として接続します。

MLflowやOptunaをHydro Platform本体の必須機能にはしません。

ChatGPT Image 2026年8月10日 21_30_29.png


27. MLflowは実験履歴の比較に使う

MLflowには、

Parameters
Metrics
Artifacts
Tags

を記録します。

例えば、

Parameters
  k1
  k2
  mesh_size
  dt
  roughness

Metrics
  NSE
  KGE
  RMSE
  MAE
  Bias
  computation_time

Artifacts
  hydrograph.png
  comparison.csv
  parameters.json
  run.log

Tags
  project_id
  scenario_id
  hydro_run_id
  model_version
  dataset_version

といった情報です。

Hydro PlatformのRunとMLflowのRunは同一視しません。

Hydro Platform Run
    run-20260810-0001
          │
          └── mlflow_run_id

という関連付けにします。


28. MLflow連携コードの考え方

解析Engineから直接MLflowを呼ばず、Worker側のAdapterで記録します。

サンプルのPythonコード全文を表示する
from __future__ import annotations

from pathlib import Path
from typing import Mapping

import mlflow


class ExperimentTracker:
    """解析結果をMLflowへ記録するためのAdapter。

    Hydro Platform本体のRun管理とMLflow固有処理を分離する。
    Engine側にはMLflowへの依存を持たせず、
    Workerが解析結果を受け取った後で実験情報を記録する。
    """

    def __init__(
        self,
        tracking_uri: str,
        experiment_name: str,
    ) -> None:
        """MLflow Tracking ServerとExperimentを設定する。

        Parameters
        ----------
        tracking_uri:
            MLflow Tracking Serverの接続先URL。
        experiment_name:
            MLflow上で使用するExperiment名。
        """
        mlflow.set_tracking_uri(tracking_uri)
        mlflow.set_experiment(experiment_name)

    def log_analysis(
        self,
        *,
        run_name: str,
        parameters: Mapping[str, float | int | str],
        metrics: Mapping[str, float],
        tags: Mapping[str, str],
        artifacts: list[Path],
    ) -> str:
        """解析条件、指標、成果物を1つのMLflow Runとして登録する。

        Parameters
        ----------
        run_name:
            MLflow画面上で識別するRun名。
        parameters:
            モデル係数、時間刻み、メッシュサイズなどの実験条件。
        metrics:
            NSE、KGE、RMSE、計算時間などの比較指標。
        tags:
            Hydro Platform側のProject ID、Run ID、ModelVersionなど。
        artifacts:
            グラフ、CSV、ログなど、保存したい成果物。

        Returns
        -------
        str
            MLflow Run ID。
        """

        with mlflow.start_run(run_name=run_name) as active_run:
            # 比較対象となる解析条件を登録する。
            mlflow.log_params(dict(parameters))

            # 各評価指標を個別に登録し、MLflow UI上で比較できるようにする。
            for metric_name, metric_value in metrics.items():
                mlflow.log_metric(metric_name, float(metric_value))

            # Hydro Platform側のIDをTagへ残し、相互参照できるようにする。
            mlflow.set_tags(dict(tags))

            # Artifactは存在するものだけ登録する。
            # グラフ生成に失敗した場合でもRun全体を失敗扱いにしないため。
            for artifact_path in artifacts:
                if artifact_path.exists():
                    mlflow.log_artifact(str(artifact_path))

            return active_run.info.run_id

29. Optunaはパラメータ同定に使う

例えば流出モデルなら、

ChatGPT Image 2026年8月10日 21_32_42.png

という流れになります。

目的関数には、

NSE
KGE
RMSE
ピーク流量誤差
ピーク時刻誤差
総流出量誤差

などを利用できます。

最良パラメータは一時値で終わらせず、

OptimizationStudy
      ↓
Best Trial
      ↓
CalibrationResult
      ↓
ModelVersion

として保存します。


30. Optuna連携コードの考え方

Optunaも解析Engineと分離します。

サンプルのPythonコード全文を表示する
from __future__ import annotations

from dataclasses import dataclass

import numpy as np
import optuna


@dataclass(frozen=True)
class CalibrationData:
    """パラメータ同定に使用する観測データ。

    Attributes
    ----------
    rainfall:
        対象期間の雨量時系列。
    observed_discharge:
        評価対象となる観測流量。
    """

    rainfall: np.ndarray
    observed_discharge: np.ndarray


def calculate_nse(
    observed: np.ndarray,
    simulated: np.ndarray,
) -> float:
    """Nash-Sutcliffe Efficiencyを計算する。

    欠測処理や品質判定は、この関数の中ではなく、
    Data HubまたはCalibration前処理で済ませておく。

    Parameters
    ----------
    observed:
        観測流量。
    simulated:
        同じ時刻に対応する計算流量。

    Returns
    -------
    float
        NSE。
    """

    if observed.shape != simulated.shape:
        raise ValueError("observedとsimulatedのshapeが一致していません。")

    denominator = np.sum((observed - np.mean(observed)) ** 2)

    # 観測値の分散が0の場合はNSEを定義できない。
    if denominator == 0:
        raise ValueError("観測値の分散が0のためNSEを計算できません。")

    numerator = np.sum((observed - simulated) ** 2)

    return float(1.0 - numerator / denominator)


def create_objective(calibration_data: CalibrationData, runoff_engine):
    """Optunaへ渡す目的関数を生成する。

    Optuna固有のTrial管理はこの層で扱い、
    Runoff Engine側にはOptunaへの依存を持たせない。
    """

    def objective(trial: optuna.Trial) -> float:
        """1 Trial分のパラメータ候補を評価する。"""

        # 探索範囲は最終的にはModel定義側へ持たせる。
        k1 = trial.suggest_float("k1", 0.01, 1.00)
        k2 = trial.suggest_float("k2", 0.001, 0.50)

        result = runoff_engine.run(
            rainfall=calibration_data.rainfall,
            parameters={
                "k1": k1,
                "k2": k2,
            },
        )

        return calculate_nse(
            observed=calibration_data.observed_discharge,
            simulated=result.discharge,
        )

    return objective

31. 外部解析ソフトとの接続

独自Engineだけに限定しません。

Common Data Platform
       ↓
External Adapter
       ↓
External Model
       ↓
Result Adapter
       ↓
Common Data Platform

という形で外部ソフトを接続します。

共通インターフェースの例です。

class ExternalModelAdapter:
    """外部解析ソフトとHydro Platformを接続するための共通Adapter。"""

    def prepare_input(self, run_context):
        """共通データを外部モデル用入力へ変換する。"""
        ...

    def execute(self, run_context):
        """外部モデルの計算を実行する。"""
        ...

    def collect_results(self, run_context):
        """外部モデルが出力した結果ファイルを取得する。"""
        ...

    def convert_results(self, run_context):
        """外部形式の結果を共通データモデルへ変換する。"""
        ...

この仕組みなら、

外部水文モデル
外部河川モデル
SWMM
Fortran Solver
C++ Solver
GPU Solver

などを同じ枠組みで接続できます。

特定形式が必要な場合は、その形式用のExport / Import Adapterを追加します。


32. Docker Composeを基本環境にする

Web/API/DB/WorkerはDocker Composeで動かします。

ChatGPT Image 2026年8月10日 21_35_09.png

標準環境は、

Ubuntu 24.04
Docker Engine
Docker Compose

を想定します。

Windows環境ではWSL2やDocker Desktopを利用できます。

GPU解析はGPU Workerとして分離します。


33. MLflow / Optunaを追加したDocker構成

解析支援機能を追加する段階では次のように拡張します。

ChatGPT Image 2026年8月10日 21_36_47.png

MLflowやOptunaは、最初から必須コンテナにはしません。

必要なStepで追加します。


34. フロントエンド

初期段階では一つのWebフロントエンドとしてまとめます。

候補は、

Vite
TypeScript
React
OpenLayers
Plotly

です。

frontend/
└── src/
    ├── app/
    │
    ├── modules/
    │   ├── portal/
    │   ├── project_workspace/
    │   ├── data_hub/
    │   ├── rainfall/
    │   ├── runoff/
    │   ├── river/
    │   ├── flood/
    │   ├── debris_flow/
    │   ├── experiment/
    │   ├── impact/
    │   └── workflow/
    │
    ├── components/
    │   ├── map/
    │   ├── chart/
    │   ├── table/
    │   └── forms/
    │
    └── api/

最初からマイクロフロントエンドには分割しません。


35. バックエンド

FastAPIを中心にしたモジュラーモノリスから始めます。

backend/
└── app/
    ├── core/
    │
    ├── modules/
    │   ├── projects/
    │   ├── project_datasets/
    │   ├── readiness/
    │   ├── snapshots/
    │   ├── activities/
    │   ├── datasets/
    │   ├── models/
    │   ├── scenarios/
    │   ├── runs/
    │   ├── experiments/
    │   ├── optimizations/
    │   ├── workflows/
    │   └── artifacts/
    │
    ├── api/
    └── main.py

必要になった機能だけ、後からサービス分割します。


36. リポジトリ構成案

当初は一つのリポジトリで管理します。

リポジトリの全文を表示する
hydro_platform/
│
├── apps/
│   ├── portal_web/
│   └── core_api/
│
├── modules/
│   ├── project_workspace/
│   ├── data_hub/
│   ├── rainfall/
│   ├── runoff/
│   ├── river/
│   ├── flood/
│   ├── sediment/
│   ├── debris_flow/
│   ├── reservoir/
│   ├── experiment/
│   ├── impact/
│   └── workflow/
│
├── engines/
│   ├── rainfall/
│   ├── runoff/
│   ├── river/
│   ├── flood/
│   ├── sediment/
│   ├── debris_flow/
│   ├── reservoir/
│   └── damage/
│
├── workers/
│   ├── common/
│   ├── analysis_worker/
│   ├── gpu_worker/
│   └── external_model_worker/
│
├── data_platform/
│   ├── catalog/
│   ├── timeseries/
│   ├── spatial/
│   ├── grid/
│   ├── quality/
│   ├── versioning/
│   └── storage/
│
├── adapters/
│   ├── jma/
│   ├── mlit/
│   ├── gsi/
│   ├── estat/
│   ├── csv/
│   └── external_models/
│
├── packages/
│   ├── common_models/
│   ├── common_gis/
│   ├── common_timeseries/
│   ├── common_units/
│   ├── common_logging/
│   └── common_validation/
│
├── schemas/
│   ├── projects/
│   ├── datasets/
│   ├── models/
│   ├── scenarios/
│   ├── runs/
│   ├── experiments/
│   └── workflows/
│
├── deploy/
│   ├── docker/
│   ├── nginx/
│   └── scripts/
│
├── tests/
│   ├── unit/
│   ├── integration/
│   └── reference_cases/
│
├── docker-compose.yml
├── .env.example
└── README.md

37. 開発ステップ

Project管理はStep 0とStep 1の時点から中心に置きます。


Step 0:共通基盤・Project Workspace基本設計

最初に実装対象と責務を確定します。

対象は、

Project
ProjectSetting
ProjectDataset
ProjectModel
ProjectReadiness
ProjectSnapshot
ProjectActivity

Dataset
DatasetVersion
Feature
Series

Model
ModelVersion

Scenario

Run
Artifact

Workflow

Experiment
OptimizationStudy
Trial
CalibrationResult

です。

さらに、

時刻
単位
品質
欠測
座標系
高さ基準
版管理
出典

を決めます。

Step 0では、これらをすべて実装する必要はありません。

関係と責務を先に決めることが目的です。


Step 1:開発基盤・Portal・Project Workspace

Docker Composeによる開発基盤とProject Workspaceを作ります。

Vite + React + TypeScript
FastAPI
PostgreSQL / PostGIS
MinIO
Redis
Nginx
Docker Compose

Project管理としては、

Project Dashboard
Project作成
Project編集
Projectコピー
Archive
Restore
Project Activity
Dataset一覧枠
Readiness表示枠
Snapshot一覧枠

まで作ります。

この時点では実データ登録は最小限にします。


Step 2:Data Hub

ここで実データ管理を本格的に実装します。

最初の対象は、

流域界
観測所
10分雨量
水位
流量
DEM

です。

CSV登録
GIS登録
DatasetVersion
品質情報
出典情報
時系列検索
OpenLayers表示
Plotly表示
Projectへの割当

まで実装します。

Data Hubでデータを登録すると、Project WorkspaceのReadinessが更新されるところまでつなげます。


Step 3:Model / Scenario / Run管理

次に計算管理基盤を作ります。

Model
ModelVersion
Scenario
Run
Artifact
ProjectSnapshot

を実装します。

Runの状態は、

QUEUED
 ↓
PREPARING
 ↓
RUNNING
 ↓
POSTPROCESSING
 ↓
SUCCEEDED / FAILED

とします。


Step 4:Runoff Studio

最初の解析アプリケーションです。

初期版は簡易2段タンクモデル程度から始めます。

ChatGPT Image 2026年8月10日 21_39_18.png

ここで、

Project
 ↓
Dataset
 ↓
Scenario
 ↓
Run
 ↓
Queue
 ↓
Worker
 ↓
Engine
 ↓
Result

の最初の解析処理の流れを完成させます。


Step 5:Experiment Tracking / MLflow

Runoff Studioが動いた段階で、実験比較を追加します。

Parameters
Metrics
Artifacts
Tags

を記録します。

最初は、

NSE
RMSE
MAE
計算時間

程度から始めます。


Step 6:Calibration / Optuna

流出モデルのパラメータ同定を追加します。

観測雨量
観測流量
 ↓
Optuna
 ↓
パラメータ候補
 ↓
Runoff Engine
 ↓
評価指標
 ↓
次のTrial

Best TrialはModelVersionへ登録します。


Step 7:River Studio

1D河川解析を追加します。

Runoff Studioの結果を共通データ基盤経由で境界条件に利用します。


Step 8:Flood Studio

2D氾濫解析を追加します。

結果はCOG / Zarrへ保存し、OpenLayersで表示します。


Step 9:Workflow Studio

Runoff → River → Floodなどの連続計算を実装します。


Step 10:Reservoir / Sediment / Debris Flow

専門解析を追加します。

必要に応じてGPU WorkerやMPI Workerへ分けます。


Step 11:Impact Studio

人口、建物、道路、重要施設などと解析結果を組み合わせて影響評価を行います。


Step 12:外部モデル連携

External Adapterを使って外部解析ソフトを接続します。

最初はファイル交換から始めます。


Step 13:リアルタイム化

観測データ自動取得
予測雨量取得
自動Run
結果更新
通知

へ進めます。


Step 14:GPU / MPI / 分散計算

最後に計算資源管理を拡張します。

複数Worker
GPU Worker
MPI
複数サーバ
クラウド
ジョブ優先度
計算資源管理

最初からKubernetesは前提にしません。


38. 開発ステップ全体

ChatGPT Image 2026年8月10日 21_41_03.png


39. 最初のプロトタイプはどこまで作るか

プロトタイプは2段階に分けて作成します。

第1段階
  Step 0
  Step 1
  Step 2
  Step 3
  Step 4

第2段階
  Step 5
  Step 6

第1段階で、

第1段階

Projectを作る

必要データが表示される

Data Hubで雨量や流域を登録する

ProjectのReadinessが更新される

Scenarioを作る

Runoff StudioでRunを開始する

Workerで解析する

流量を共通データ基盤へ保存する

Webで結果を確認する

までを完成させます。

第2段階で、

第2段階

実験を残す
比較する
パラメータを同定する
Best TrialをModelVersionとして保存する

ところまで進めます。


40. 最初から作り込みすぎない

初期段階では、次のものは後回しにします。

Kubernetes
大規模認証基盤
複数組織向けマルチテナント
全国規模データ
複雑な権限管理
完全リアルタイム運用
大規模分散計算
外部モデルの完全自動制御

まずは、

一つのProjectで、データ整備状況を確認し、必要データを登録し、一つの解析を実行して結果をWebで確認できる

ところまでを優先します。


41. この構成の利点

Projectの状態が分かる

「何が揃っていて、何が不足しているか」をProjectトップで確認できます。

データを再利用できる

同じDEMや雨量DatasetVersionを複数Projectで利用できます。

Projectを安全に複製できる

現況から改修案を作る場合も、大容量データを物理コピーせずにProjectを作れます。

解析モデルを交換できる

PortalやRun管理を変えずに、Engineだけを差し替えやすくなります。

実験履歴を残せる

MLflowを使ってパラメータや評価指標を比較できます。

パラメータ同定を組み込める

Optunaで探索し、Best Trialを正式なModelVersionへ戻せます。

外部ソフトも接続できる

Adapterを追加することで、既存解析ソフトや独自Solverを利用できます。

WebとDockerで環境を揃えやすい

利用者側の入口をブラウザへ寄せ、サーバ側の実行環境をコンテナで揃えられます。


42. おわりに

今回考えているのは、単独の流出解析ソフトや河川解析ソフトではありません。

目標は、

Project Workspaceと共通データ基盤を中心に、水文・河川・氾濫・土砂・被害評価などの解析アプリケーションを追加していけるWebベースの解析プラットフォーム

です。

全体を簡単に表すと、

全体構成

Portal

Project Workspace

Data / Model / Scenario / Run

Common Data Platform

Analysis Engine

Result

Project Workspace

となります。

特に最初の段階では、解析式を増やすことより、

Project
ProjectDataset
DatasetVersion
ModelVersion
Scenario
Run
Snapshot
Readiness

の関係をきちんと決めることが重要です。

この構想を基準にして、次はStep 0を設計し、どこまでをStep 0で確定し、どこからをStep 1で実装するかを整理してから実装へ進めます。

全体を通して、何かご意見などあれば、是非コメントなどいただければと考えています。


0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?