packages feed

hanalyze-viz-0.2.0.1: src/Hanalyze/Viz/GP.hs

-- |
-- Module      : Hanalyze.Viz.GP
-- Description : ガウス過程回帰結果 (訓練データ・事後平均・信用区間) の可視化
-- Copyright   : (c) 2026 Aelysce Project (Toshiaki Honda)
-- License     : BSD-3-Clause
--
{-# LANGUAGE OverloadedStrings #-}
-- | Visualization of Gaussian-process regression results.
--
-- Plots training data (scatter), the posterior mean (curve), and a 95 %
-- credible band.
module Hanalyze.Viz.GP
  ( gpPlot
  , gpPlotFile
  ) where

import Hanalyze.Model.GP     (GPResult (..))
import Hanalyze.Viz.Core     (PlotConfig (..), OutputFormat, writeSpec)
import Data.Text    (Text)
import Graphics.Vega.VegaLite

-- | [日本語]: GP 予測プロットを構築する。
--
--   描画要素:
--     - 散布点: 訓練データ (trainData)
--     - 青い曲線: 事後平均
--     - 青い帯: 平均 ± 2σ (≈95% 信用区間)
--   [English]: Builds the GP prediction plot.
--
--   Rendered elements:
--     - Scatter points: training data (trainData)
--     - Blue curve: posterior mean
--     - Blue band: mean ± 2σ (≈95% credible interval)
gpPlot
  :: PlotConfig
  -> Text              -- ^ [日本語]: x 軸の列名ラベル。 [English]: X-axis column-name label.
  -> Text              -- ^ [日本語]: y 軸の列名ラベル。 [English]: Y-axis column-name label.
  -> [(Double, Double)] -- ^ [日本語]: 訓練データ (x, y)。 [English]: Training data (x, y).
  -> GPResult
  -> VegaLite
gpPlot cfg xCol yCol trainData res =
  toVegaLite
    [ title (plotTitle cfg) []
    , layer [bandLayer, meanLayer, pointLayer]
    , width  (plotWidth  cfg)
    , height (plotHeight cfg)
    ]
  where
    (trnX, trnY) = unzip trainData
    testXs = gpTestX  res
    means  = gpMean   res
    lowers = gpLower  res
    uppers = gpUpper  res

    -- 訓練点
    pointLayer = asSpec
      [ dataFromColumns []
          . dataColumn xCol (Numbers trnX)
          . dataColumn yCol (Numbers trnY)
          $ []
      , mark Point [MTooltip TTEncoding, MColor "black", MOpacity 0.8, MSize 40]
      , encoding
          . position X [PName xCol, PmType Quantitative, PAxis [AxTitle xCol]]
          . position Y [PName yCol, PmType Quantitative, PAxis [AxTitle yCol]]
          $ []
      ]

    -- 事後平均曲線
    meanLayer = asSpec
      [ dataFromColumns []
          . dataColumn xCol   (Numbers testXs)
          . dataColumn "mean" (Numbers means)
          $ []
      , mark Line [MColor "steelblue", MStrokeWidth 2.5]
      , encoding
          . position X [PName xCol,   PmType Quantitative]
          . position Y [PName "mean", PmType Quantitative, PAxis [AxTitle yCol]]
          $ []
      ]

    -- 95% 信用区間バンド
    bandLayer = asSpec
      [ dataFromColumns []
          . dataColumn xCol    (Numbers testXs)
          . dataColumn "lower" (Numbers lowers)
          . dataColumn "upper" (Numbers uppers)
          $ []
      , mark Area [MOpacity 0.2, MColor "steelblue"]
      , encoding
          . position X  [PName xCol,    PmType Quantitative]
          . position Y  [PName "lower", PmType Quantitative]
          . position Y2 [PName "upper"]
          $ []
      ]

-- | [日本語]: ファイルに書き出す。
--   [English]: Writes the plot to a file.
gpPlotFile
  :: OutputFormat
  -> FilePath
  -> PlotConfig
  -> Text
  -> Text
  -> [(Double, Double)]
  -> GPResult
  -> IO ()
gpPlotFile fmt path cfg xCol yCol trainData res =
  writeSpec fmt path (gpPlot cfg xCol yCol trainData res)