hgg-core-0.2.0.0: src/Graphics/Hgg/Spec/Constructors.hs
-- |
-- Module : Graphics.Hgg.Spec.Constructors
-- Description : Layer constructors for plot marks (the mark catalogue)
-- Copyright : (c) 2026 Aelysce Project (Toshiaki Honda)
-- License : BSD-3-Clause
--
-- [日本語]: 'Graphics.Hgg.Spec' の module 分割で切り出し。 mark ごとの Layer
-- 構築子 ('scatter' / 'line' / 'bar' / ... / 'customMark') と mark 固有 setter
-- ('binCount' / 'jitterX' / 'shape' / 'statLm' 系等)、 hexbin の binning
-- ('HexCell') を持つ。 中身は等質な mark カタログ (辞書的) ゆえ 1 module に
-- まとめる (user 合意)。 公開 API は従来どおり
-- 'Graphics.Hgg.Spec' (facade) が re-export する。 挙動・出力は完全に不変。
-- [English]: Split out of 'Graphics.Hgg.Spec' as part of its module split.
-- Holds the per-mark Layer constructors ('scatter' / 'line' / 'bar' / ... /
-- 'customMark'), mark-specific setters ('binCount' / 'jitterX' / 'shape' /
-- the 'statLm' family, etc.), and hexbin binning ('HexCell'). Since the
-- contents form a homogeneous mark catalogue (dictionary-like), they are
-- kept in a single module (agreed with the user). The public API is
-- unchanged: 'Graphics.Hgg.Spec' (the facade) still re-exports everything.
-- Behavior and output are fully unchanged.
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE OverloadedStrings #-}
module Graphics.Hgg.Spec.Constructors
( -- * 基本 mark
scatter, line, bar, histogram, histogramDensity
, heatmap, boxplot, density, densityFill, freqpoly
, scatterPoints, linePoints, unzipPoint2
-- * custom mark
, customMark, customMarkWith, encX, encY, encZ
, ternaryScatter, ternaryLine -- ★ Phase 69 A3: 三角座標 mark 束ね
-- * 統計 / 分布 mark
, trace, traceLines, forest, forestNull, funnel, autocorr, autocorrMaxLag, ess
, violin, strip, swarm, raincloud, ridge
, qq, ecdf, lineRange, pointRange, crossbar
, statMean, statMedian, statLm, statLmLevel, statSmooth, statSmoothCI
, statPoly, statResid, statFunction
-- * 特化 mark
, band, step, stem, stream, pie, waterfall, parallelCoords
, countXY, quiver, contour, contourFilled, bin2d, bin2dCount, tile
, hexbin, hexbinBins, HexCell(..), hexbinCells, hexbinLayerCells
, dag, dagNode, dagNodeDist, dagEdge, dagFromLists, dagFromListsWithPlates
-- * mark 固有 setter / 補助
, (<+>)
, alphaBy, arrowColorByMagnitude, arrowScale
, binCount, binWidth, histBinning, histBorder, hollow
, chain, colorCats, orderedCats, compositeLanes, densityNorm
, contourBreaks, contourLevels
, groupBy, jitterX, jitterY, label
, linetype, linetypeBy, markWidth, nudge, position
, shape, shapeBy, shapeMapEntry, side, sizeBy, text
) where
import Data.Aeson (Value)
import qualified Data.Aeson as Aeson
import qualified Data.List
import Data.Monoid (First (..), Last (..))
import Data.Text (Text)
import Data.Vector (Vector)
import qualified Data.Vector as V
import Graphics.Hgg.Color (fromHex)
import Graphics.Hgg.Primitive (Primitive)
import Graphics.Hgg.Spec.Column
import Graphics.Hgg.Spec.CustomMark
import Graphics.Hgg.Spec.Layer
import Graphics.Hgg.Spec.Mark
-- ===========================================================================
-- Layer constructors (= 各 mark の最小起点)
-- ===========================================================================
scatter, line, bar :: ColRef -> ColRef -> Layer
scatter x y = mempty
{ lyKind = First (Just MScatter), lyEncX = Last (Just x), lyEncY = Last (Just y) }
line x y = mempty
{ lyKind = First (Just MLine), lyEncX = Last (Just x), lyEncY = Last (Just y) }
bar x y = mempty
{ lyKind = First (Just MBar), lyEncX = Last (Just x), lyEncY = Last (Just y) }
-- | [日本語]: custom mark を定義する公開 API。 core (@MarkKind@ の閉列挙) を触らず
-- 新しいプロット型を足す拡張点。 @cid@ = 安定 mark 識別子 (PS registry dispatch の
-- 鍵)、 @draw@ = 'RenderCtx' を受け取り 'Primitive' 列を返す描画 closure。 データは
-- closure に閉じ込めても、 'rcResolver' 経由で layer 束縛列を引いてもよい。
--
-- HS は closure を直接呼んで描く (SVG/PDF/Rasterific)。 PS canvas で parity が欲しい
-- 時は同じ @cid@ で PS registry に draw 関数を手登録する (無ければ HS 専用)。
-- [English]: The public API for defining a custom mark. An extension
-- point for adding new plot types without touching the core (the closed
-- @MarkKind@ enum). @cid@ is the stable mark identifier (the key for PS
-- registry dispatch); @draw@ is a drawing closure that takes a
-- 'RenderCtx' and returns a list of 'Primitive'. Data can either be
-- captured in the closure or pulled from the layer's bound columns via
-- 'rcResolver'.
--
-- HS calls the closure directly to draw (SVG/PDF/Rasterific). When
-- parity with the PS canvas is needed, register a draw function by hand
-- in the PS registry under the same @cid@ (otherwise the mark is
-- HS-only).
--
-- > customMark "myElbow" $ \ctx -> [ PLine (uncurry Point (rcProjectXY ctx 0 0)) ... ]
customMark :: Text -> (RenderCtx -> [Primitive]) -> Layer
customMark cid draw = mempty
{ lyKind = First (Just MCustom)
, lyCustom = Last (Just (CustomMark cid Aeson.Null draw)) }
-- | [日本語]: option 付き 'customMark'。 @opts@ は PS registry の draw 関数へ渡る
-- serializable JSON。
-- [English]: 'customMark' with options. @opts@ is serializable JSON
-- passed through to the PS registry's draw function.
customMarkWith :: Text -> Value -> (RenderCtx -> [Primitive]) -> Layer
customMarkWith cid opts draw = mempty
{ lyKind = First (Just MCustom)
, lyCustom = Last (Just (CustomMark cid opts draw)) }
-- | [日本語]: x / y encoding 列を単独で束ねる 'Layer' setter。 mark 種別に依らず
-- 合成でき、 custom mark を「一級 mark」化する (= 軸 range が 'lyEncX'/'lyEncY'
-- から自動計算され、 @df |>>@ とも連携)。 既存 mark の encoding 上書きにも使える。
-- custom mark の名前付き combinator は普通こう書く:
-- [English]: A 'Layer' setter that binds the x / y encoding column on its
-- own. It composes with any mark kind and turns a custom mark into a
-- "first-class mark" (axis ranges are computed automatically from
-- 'lyEncX'/'lyEncY', and it works with @df |>>@ too). It can also
-- override the encoding of an existing mark. A named custom-mark
-- combinator is typically written like this:
--
-- > dendrogram :: ColRef -> ColRef -> Layer
-- > dendrogram x y = customMark "dendrogram" (drawFromCols x y) <> encX x <> encY y
-- > -- usage: layer (dendrogram "leaf" "height") -- same feel as scatter x y
encX :: ColRef -> Layer
encX x = mempty { lyEncX = Last (Just x) }
encY :: ColRef -> Layer
encY y = mempty { lyEncY = Last (Just y) }
-- | [日本語]: 三角座標 (ternary) の第 3 成分 aesthetic (= Phase 64 A11)。 encX/encY
-- と合わせ 3 成分 (a,b,c) を直接受ける。 'coordTernary' と併用したときのみ意味を
-- 持つ (直交/極座標では未使用)。 正規化 (合計→1) は library 側 ('normalizeTernary')。
-- [English]: The third-component aesthetic of ternary coordinates (Phase 64
-- A11). Together with encX/encY it takes the three components (a,b,c)
-- directly. It only has meaning when combined with 'coordTernary' (unused in
-- Cartesian / polar). Normalization (summing to 1) is done library-side
-- ('normalizeTernary').
encZ :: ColRef -> Layer
encZ z = mempty { lyEncZ = Last (Just z) }
-- | [日本語]: ★ Phase 69 A3: 三角座標の散布 mark 束ね。 @scatter a b <> encZ c@ の sugar
-- で、 3 成分 (a=上/b=左下/c=右下) を mark 1 個で受ける。 coord は 'coordOf' が encZ から
-- 'CoordTernary' と推論するので @coordTernary@ は不要 (向きを変える時だけ 'coordTernaryWith')。
-- → 最小形 @layer (ternaryScatter a b c)@。
-- [English]: ★ Phase 69 A3: the ternary scatter mark, sugar for
-- @scatter a b <> encZ c@, taking the three components (a=top / b=bottom-left /
-- c=bottom-right) as one mark. The coord is inferred as 'CoordTernary' from encZ
-- by 'coordOf', so @coordTernary@ is unnecessary (use 'coordTernaryWith' only to
-- change orientation). Minimal form: @layer (ternaryScatter a b c)@.
ternaryScatter :: ColRef -> ColRef -> ColRef -> Layer
ternaryScatter a b c = scatter a b <> encZ c
-- | [日本語]: ★ Phase 69 A3: 三角座標の折れ線 mark 束ね (@line a b <> encZ c@ の sugar)。
-- [English]: ★ Phase 69 A3: the ternary line mark (sugar for @line a b <> encZ c@).
ternaryLine :: ColRef -> ColRef -> ColRef -> Layer
ternaryLine a b c = line a b <> encZ c
-- | [日本語]: 2D scatter ('Point2' 直入れ・3D
-- 'Graphics.Hgg.ThreeD.Spec.scatter3DPoints' と対称)。 内部は
-- @scatter (inline xs) (inline ys)@ に等価 (= x/y を inline 列に分解) なので
-- Render/JSON/PS 無改修。
-- [English]: 2D scatter that takes 'Point2' values directly (the
-- counterpart of the 3D 'Graphics.Hgg.ThreeD.Spec.scatter3DPoints').
-- Internally equivalent to @scatter (inline xs) (inline ys)@ (x/y are
-- split into inline columns), so Render/JSON/PS need no changes.
--
-- > scatterPoints [Point2 1 2, Point2 3 4]
scatterPoints :: [Point2] -> Layer
scatterPoints pts = scatter (inline xs) (inline ys)
where (xs, ys) = unzipPoint2 pts
-- | [日本語]: 2D line ('Point2' 直入れ・3D 'Graphics.Hgg.ThreeD.Spec.line3DPoints' と
-- 対称)。 内部は @line (inline xs) (inline ys)@ に等価。
-- [English]: 2D line that takes 'Point2' values directly (the
-- counterpart of the 3D 'Graphics.Hgg.ThreeD.Spec.line3DPoints').
-- Internally equivalent to @line (inline xs) (inline ys)@.
linePoints :: [Point2] -> Layer
linePoints pts = line (inline xs) (inline ys)
where (xs, ys) = unzipPoint2 pts
-- | [日本語]: '[Point2]' を x / y の 'Double' リストに分解 ('scatterPoints' /
-- 'linePoints' 用)。
-- [English]: Splits a '[Point2]' into separate x / y 'Double' lists (used
-- by 'scatterPoints' / 'linePoints').
unzipPoint2 :: [Point2] -> ([Double], [Double])
unzipPoint2 = unzip . map (\(Point2 x y) -> (x, y))
-- | [日本語]: vector field (quiver)。 各 (x,y) に成分 (u,v) の矢印を描く
-- (= matplotlib @quiver@)。 矢印長は autoscale (= 最長矢印がデータ対角の ~8%)
-- に 'arrowScale' 倍を掛けた長さ。 列バインドは
-- @df |>> quiver \"x\" \"y\" \"u\" \"v\"@。 矢印を magnitude (= √(u²+v²)) で
-- 連続色マップするには 'arrowColorByMagnitude'。
-- [English]: A vector field (quiver). Draws an arrow with components
-- (u,v) at each (x,y), like matplotlib's @quiver@. Arrow length is the
-- autoscale length (the longest arrow is ~8% of the data diagonal)
-- multiplied by 'arrowScale'. Column binding looks like
-- @df |>> quiver \"x\" \"y\" \"u\" \"v\"@. Use 'arrowColorByMagnitude' to
-- map arrows to a continuous color by magnitude (= √(u²+v²)).
quiver :: ColRef -> ColRef -> ColRef -> ColRef -> Layer
quiver x y u v = mempty
{ lyKind = First (Just MQuiver)
, lyEncX = Last (Just x), lyEncY = Last (Just y)
, lyEncU = Last (Just u), lyEncV = Last (Just v) }
-- | [日本語]: quiver 矢印長の倍率 (autoscale × この値・既定 1)。 値を上げると矢印が
-- 長く。
-- [English]: The scale factor for quiver arrow length (autoscale × this
-- value, default 1). Raising it makes arrows longer.
arrowScale :: Double -> Layer
arrowScale s = mempty { lyArrowScale = Last (Just s) }
-- | [日本語]: quiver の矢印を magnitude (= √(u²+v²)) で連続色マップする (既定
-- OFF)。 色は連続パレット (viridis 系)。 OFF 時は単色 ('color' / theme)。
-- [English]: Maps quiver arrows to a continuous color by magnitude
-- (= √(u²+v²)); default OFF. The color uses a continuous (viridis-family)
-- palette. When OFF, arrows use a single color ('color' / theme).
arrowColorByMagnitude :: Layer
arrowColorByMagnitude = mempty { lyArrowMagnitude = Last (Just True) }
-- | [日本語]: データ駆動テキストラベル (= ggplot @geom_text@)。 各 (x,y) 点に lab
-- 列の文字を描く。 'Graphics.Hgg.Spec.Setters.annotate' (固定 1 点) と違い列駆動で点数ぶん出る。
-- [English]: A data-driven text label (like ggplot's @geom_text@). Draws
-- the text of the lab column at each (x,y) point. Unlike 'Graphics.Hgg.Spec.Setters.annotate'
-- (a single fixed point), it is column-driven and produces one label per
-- row.
text :: ColRef -> ColRef -> ColRef -> Layer
text x y lab = mempty
{ lyKind = First (Just MText), lyEncX = Last (Just x), lyEncY = Last (Just y)
, lyLabel = Last (Just lab) }
-- | [日本語]: 背景付きテキストラベル (= ggplot @geom_label@)。 'text' と同じだが
-- 各文字の背後に角丸矩形を敷く (= 重なる点の上でも読みやすい)。
-- [English]: A text label with a background (like ggplot's
-- @geom_label@). Same as 'text' but draws a rounded rectangle behind
-- each label (readable even over overlapping points).
label :: ColRef -> ColRef -> ColRef -> Layer
label x y lab = mempty
{ lyKind = First (Just MLabel), lyEncX = Last (Just x), lyEncY = Last (Just y)
, lyLabel = Last (Just lab) }
-- | [日本語]: Q-Q plot (= ggplot @stat_qq@ / @geom_qq@)。 sample 列のみを取り、
-- ソートした order statistic y_(i) を y、 理論正規分位点 Φ⁻¹((i-0.5)/n) を x に
-- 置いて点を描く (= 正規性の視覚診断)。 理論分位点は render / range 側で算出する
-- ため、 ここでは sample を encY に保持するだけ (encX 列は持たない)。
-- [English]: A Q-Q plot (like ggplot's @stat_qq@ / @geom_qq@). Takes only
-- a sample column and plots points with the sorted order statistic
-- y_(i) as y and the theoretical normal quantile Φ⁻¹((i-0.5)/n) as x
-- (a visual diagnostic for normality). Since the theoretical quantiles
-- are computed on the render / range side, this only stores sample in
-- encY (there is no encX column).
qq :: ColRef -> Layer
qq sample = mempty
{ lyKind = First (Just MQQ), lyEncY = Last (Just sample) }
-- | [日本語]: ECDF plot (= ggplot @stat_ecdf@)。 sample 列 (encX) をソートして
-- 右連続の経験累積分布 F(x)=#(≤x)/n を階段状に描く (y∈[0,1])。
-- [English]: An ECDF plot (like ggplot's @stat_ecdf@). Sorts the sample
-- column (encX) and draws the right-continuous empirical CDF
-- F(x)=#(≤x)/n as a step curve (y∈[0,1]).
ecdf :: ColRef -> Layer
ecdf sample = mempty
{ lyKind = First (Just MEcdf), lyEncX = Last (Just sample) }
-- | [日本語]: linerange (= ggplot @geom_linerange@)。 各 (x,y) に縦線 y±err を描く。
-- [English]: A linerange (like ggplot's @geom_linerange@). Draws a
-- vertical segment y±err at each (x,y).
lineRange :: ColRef -> ColRef -> ColRef -> Layer
lineRange x y err = mempty
{ lyKind = First (Just MLineRange), lyEncX = Last (Just x)
, lyEncY = Last (Just y), lyErrorY = Last (Just err) }
-- | [日本語]: pointrange (= ggplot @geom_pointrange@)。 linerange + 中心点。
-- [English]: A pointrange (like ggplot's @geom_pointrange@): a linerange
-- plus a center point.
pointRange :: ColRef -> ColRef -> ColRef -> Layer
pointRange x y err = mempty
{ lyKind = First (Just MPointRange), lyEncX = Last (Just x)
, lyEncY = Last (Just y), lyErrorY = Last (Just err) }
-- | [日本語]: crossbar (= ggplot @geom_crossbar@)。 幅付き箱 (y±err) + 中央水平線。
-- [English]: A crossbar (like ggplot's @geom_crossbar@): a box of width
-- y±err with a horizontal center line.
crossbar :: ColRef -> ColRef -> ColRef -> Layer
crossbar x y err = mempty
{ lyKind = First (Just MCrossbar), lyEncX = Last (Just x)
, lyEncY = Last (Just y), lyErrorY = Last (Just err) }
-- | [日本語]: stat_function (= ggplot @stat_function@ / @geom_function@)。
-- 関数 f を [xLo, xHi] で n 点サンプルし、 inline 列の line layer を生成する。
-- 関数自体は JSON 化できないため __構成時にサンプル点へ焼き込む__ (= spec には
-- 点列が入り、 canvas backend は通常の line として描く)。 n<2 は 2 に切り上げ。
-- [English]: stat_function (like ggplot's @stat_function@ /
-- @geom_function@). Samples the function f at n points over
-- [xLo, xHi] and produces a line layer with inline columns. Since the
-- function itself cannot be serialized to JSON, __the sample points are baked in at construction time__
-- (the spec holds the point series, and the canvas backend draws it as
-- an ordinary line). n<2 is rounded up to 2.
statFunction :: (Double -> Double) -> Double -> Double -> Int -> Layer
statFunction f xLo xHi n =
let m = max 2 n
xs = [ xLo + (xHi - xLo) * fromIntegral i / fromIntegral (m - 1) | i <- [0 .. m - 1] ]
ys = map f xs
in line (ColNum (V.fromList xs)) (ColNum (V.fromList ys))
histogram :: ColRef -> Layer
histogram x = mempty
{ lyKind = First (Just MHistogram), lyEncX = Last (Just x) }
-- | [日本語]: 頻度多角形 (Ch10 EDA): @geom_freqpoly(aes(x = …))@ 相当。 histogram
-- と同じ bin 化で各 bin の count を求め、 bin 中心を折れ線で結ぶ。 bin 幅は
-- 'binWidth' / 'binCount'、 after_stat(density) は 'histogramDensity' True で
-- 流用 (= histogram と同じフラグ)。 color aesthetic ('colorBy') で群分割すると
-- 群ごとに別色の折れ線を重ねる (cut 別 price 分布の比較等)。
-- [English]: A frequency polygon (Ch10 EDA): the equivalent of
-- @geom_freqpoly(aes(x = …))@. Uses the same binning as histogram to
-- compute each bin's count, then connects the bin centers with a line.
-- Bin width follows 'binWidth' / 'binCount', and after_stat(density) is
-- reused via 'histogramDensity' True (the same flag as histogram). When
-- split by a color aesthetic ('colorBy'), overlays one differently
-- colored line per group (e.g. comparing price distributions by cut).
freqpoly :: ColRef -> Layer
freqpoly x = mempty
{ lyKind = First (Just MFreqPoly), lyEncX = Last (Just x) }
-- | [日本語]: Ch10 EDA: 2 カテゴリ変数の件数 (= ggplot @geom_count()@ /
-- @stat_sum@)。 @countXY x y@ は (x,y) のカテゴリ組合せごとに観測件数を集計し、
-- 各セル中心に面積 ∝ 件数 (= 半径 ∝ √件数) の点を描く。 'size' で最大半径 px を
-- 上書き可。
-- [English]: Ch10 EDA: counts for two categorical variables (like
-- ggplot's @geom_count()@ / @stat_sum@). @countXY x y@ tallies the
-- observed count for each (x,y) category combination and draws a point
-- at each cell center with area ∝ count (radius ∝ √count). 'size'
-- overrides the maximum radius in px.
countXY :: ColRef -> ColRef -> Layer
countXY x y = mempty
{ lyKind = First (Just MCount), lyEncX = Last (Just x), lyEncY = Last (Just y) }
-- | [日本語]: MCMC autocorrelation plot (P19): 1 列の時系列から lag-k 自己相関
-- r(τ) を計算し bar chart で表示。 max lag は 'autocorrMaxLag'、 default は 40。
-- ±1.96/√N の significance band も同時描画。
--
-- r(τ) = Σ(x_t - μ)(x_{t+τ} - μ) / Σ(x_t - μ)²
--
-- matplotlib との対応: `plt.acorr(x, maxlags=40)` 相当 (= 但し片側のみ)。
-- [English]: MCMC autocorrelation plot (P19): computes the lag-k
-- autocorrelation r(τ) from a single time-series column and displays it
-- as a bar chart. The max lag is set with 'autocorrMaxLag' (default 40),
-- and the ±1.96/√N significance band is drawn alongside.
--
-- r(τ) = Σ(x_t - μ)(x_{t+τ} - μ) / Σ(x_t - μ)²
--
-- Corresponds to matplotlib's `plt.acorr(x, maxlags=40)` (one-sided
-- only).
autocorr :: ColRef -> Layer
autocorr c = mempty
{ lyKind = First (Just MAutocorr)
, lyEncX = Last (Just c)
}
-- | [日本語]: autocorr の max lag (= 'autocorr' と '<>' で組合せ)。 default 40。
-- [English]: The max lag for autocorr (combine with 'autocorr' via
-- '<>'). Default 40.
autocorrMaxLag :: Int -> Layer
autocorrMaxLag n = mempty { lyMaxLag = Last (Just n) }
-- | [日本語]: Effective Sample Size plot (P20): chain ごとに ESS bar を描画。
-- chain group は 'chain' で指定 (= 'ess vals <> chain chainCol')。
-- chain 未指定なら全体を 1 chain として 1 bar。
--
-- ESS = N / (1 + 2 Σ |r(τ)|) (= τ=1 から r(τ) > 0 まで)
--
-- matplotlib / arviz 対応: `az.plot_ess(idata)` の chain ごと bar (= 簡略版)。
-- [English]: Effective Sample Size plot (P20): draws an ESS bar per
-- chain. The chain group is set with 'chain' (= 'ess vals <> chain
-- chainCol'); with no chain specified, the whole series is treated as a
-- single chain with a single bar.
--
-- ESS = N / (1 + 2 Σ |r(τ)|) (from τ=1 up to where r(τ) > 0)
--
-- Corresponds to arviz/matplotlib's `az.plot_ess(idata)`, per-chain bars
-- (a simplified version).
-- | [日本語]: ESS 棒グラフ: encX = パラメータ/chain 名 (categorical)、
-- encY = 計算済み ESS 値。 ESS の計算は統計ライブラリ (analyze 側) の責務で、
-- plot は値を棒にするだけ (= ggplot/bayesplot mcmc_neff 流の「計算と描画の
-- 分離」)。
-- [English]: ESS bar chart: encX is the parameter/chain name
-- (categorical), encY is the precomputed ESS value. Computing ESS is the
-- responsibility of the statistics library (the analyze side); plot
-- merely turns the values into bars (the same separation of computation
-- and drawing as ggplot/bayesplot's mcmc_neff).
ess :: ColRef -> ColRef -> Layer
ess nameCol essCol = mempty
{ lyKind = First (Just MEss)
, lyEncX = Last (Just nameCol)
, lyEncY = Last (Just essCol)
}
-- | [日本語]: chain group 列を設定 (= 'autocorr' / 'ess' で chain 分け、 MTrace でも
-- 将来使用)。
-- [English]: Sets the chain-group column (used by 'autocorr' / 'ess' to
-- split by chain; will also be used by MTrace in the future).
chain :: ColRef -> Layer
chain c = mempty { lyChain = Last (Just c) }
-- | [日本語]: Forest plot: 各 row が「label + 点推定 + CI」 の horizontal CI bar
-- 群。
--
-- 引数: label 列 (= categorical/text)、 点推定 列、 ± 半幅 列 (= 対称 CI)。
--
-- * y 軸: label
-- * x 軸: estimate
-- * 中央 vertical 線: 'forestNull' (= default 0、 メタ解析慣例で OR は 1)
--
-- asymmetric CI (= lo / hi 個別) は将来。 現状は対称 CI のみ。
-- [English]: A forest plot: a group of horizontal CI bars, one row per
-- "label + point estimate + CI".
--
-- Arguments: the label column (categorical/text), the point-estimate
-- column, and the ± half-width column (a symmetric CI).
--
-- * y axis: label
-- * x axis: estimate
-- * center vertical line: 'forestNull' (default 0; meta-analysis
-- convention uses 1 for an odds ratio)
--
-- Asymmetric CI (separate lo / hi) is a future addition; only symmetric
-- CI is supported today.
forest :: ColRef -> ColRef -> ColRef -> Layer
forest labelCol estCol errCol = mempty
{ lyKind = First (Just MForest)
, lyEncX = Last (Just estCol)
, lyEncY = Last (Just labelCol)
, lyErrorX = Last (Just errCol)
}
-- | [日本語]: Forest plot の null effect 位置 (= 縦 0 線、 メタ解析の reference)。
-- default 0。 リスク比 / オッズ比 を log scale で扱う場合は 0 (= log 1)、 線形なら
-- 0 (= 差)。
-- [English]: The null-effect position for a forest plot (the vertical
-- reference line at 0, the meta-analysis reference). Default 0. When
-- handling risk ratios / odds ratios on a log scale, 0 (= log 1); on a
-- linear scale, 0 (= no difference).
forestNull :: Double -> Layer
forestNull v = mempty { lyMaxLag = Last (Just (round v)) }
-- 流用: lyMaxLag を null position の Int で再利用 (= round)。
-- TODO: Double-precision null position field を別途 (= 当面 Int で十分)
-- | [日本語]: Funnel plot: 効果量 vs 標準誤差の散布図 + 95% 信頼区間 envelope。
--
-- 引数: 効果量 (effect) 列、 標準誤差 (SE) 列。 出版 bias 確認に使う。
--
-- * x 軸: effect (= estimate)
-- * y 軸: SE (= 上方が精度高、 下方が精度低)
-- * 中央 vertical 線: pooled mean (= データから算出)
-- * diagonal 線: pooled ± 1.96 * SE の envelope
-- [English]: A funnel plot: a scatter of effect size vs. standard error
-- plus a 95% confidence envelope.
--
-- Arguments: the effect-size (effect) column and the standard-error (SE)
-- column. Used to check for publication bias.
--
-- * x axis: effect (the estimate)
-- * y axis: SE (higher = more precise, lower = less precise)
-- * center vertical line: the pooled mean (computed from the data)
-- * diagonal lines: the pooled ± 1.96 * SE envelope
funnel :: ColRef -> ColRef -> Layer
funnel effectCol seCol = mempty
{ lyKind = First (Just MFunnel)
, lyEncX = Last (Just effectCol)
, lyEncY = Last (Just seCol)
}
-- | [日本語]: Box plot。 ★ 値 1 列を受ける。 群分けは @<> groupBy "g"@ (色一律) /
-- @<> colorBy "g"@ (群色+凡例) で付ける (ggplot 同型)。 群指定なしなら単一 box。
-- [English]: A box plot. Takes a single value column. Grouping is added
-- with @<> groupBy "g"@ (uniform color) / @<> colorBy "g"@ (per-group
-- color + legend), matching ggplot. With no group specified, it draws a
-- single box.
boxplot :: ColRef -> Layer
boxplot vals = mempty
{ lyKind = First (Just MBox), lyEncY = Last (Just vals) }
-- | [日本語]: ★ 群で分けて配置するチャネル (= ggplot @aes(group=)@)。 色は付けない
-- (一律。 色は 'color' / 'colorBy' で別途)。 distribution mark (boxplot/violin
-- 等) では群ごとに集約を作りカテゴリ x に並べる。 内部表現は encX (= 既存の
-- 群配置機構を流用)。 ⚠ @Data.List.groupBy@ と同名なので、 両方 import する場合は
-- qualified 推奨。
-- [English]: A channel for grouping and positioning marks (like
-- ggplot's @aes(group=)@). It does not add color (uniform; use 'color' /
-- 'colorBy' separately for that). Distribution marks (boxplot/violin,
-- etc.) build one aggregate per group and lay them out along categorical
-- x. Internally represented as encX (reusing the existing group-layout
-- mechanism). ⚠ Shares a name with @Data.List.groupBy@; use a qualified
-- import if importing both.
groupBy :: ColRef -> Layer
groupBy g = mempty { lyEncX = Last (Just g) }
-- | [日本語]: Density plot: x 列の値ベクターで Gaussian KDE 曲線。
-- [English]: A density plot: a Gaussian KDE curve over the x column's
-- values.
density :: ColRef -> Layer
density x = mempty
{ lyKind = First (Just MDensity), lyEncX = Last (Just x) }
-- | [日本語]: pairs 対角用 density。 y 軸目盛りは値範囲 (= 行の変数値、 散布図行と
-- 共有)、 KDE 曲線は panel 高さに独立正規化して描く (= seaborn pairplot 対角の
-- 挙動)。
-- [English]: A density mark for the diagonal of a pairs plot. The y-axis
-- ticks use the value range (the row's variable values, shared with the
-- scatter row), while the KDE curve is independently normalized to the
-- panel height (matching seaborn pairplot's diagonal behavior).
densityNorm :: ColRef -> Layer
densityNorm x = mempty
{ lyKind = First (Just MDensity), lyEncX = Last (Just x)
, lyDensityNorm = Last (Just True) }
-- | [日本語]: Pie chart (= encX cat, encY 値合計の扇)。
-- [English]: A pie chart (encX gives the category, encY the value whose
-- sum defines each slice).
pie :: ColRef -> ColRef -> Layer
pie x y = mempty
{ lyKind = First (Just MPie), lyEncX = Last (Just x), lyEncY = Last (Just y) }
-- | [日本語]: Waterfall chart (= encX cat, encY delta、 累積 bar)。
-- [English]: A waterfall chart (encX gives the category, encY the
-- delta; bars accumulate).
waterfall :: ColRef -> ColRef -> Layer
waterfall x y = mempty
{ lyKind = First (Just MWaterfall), lyEncX = Last (Just x), lyEncY = Last (Just y) }
-- | [日本語]: (= Heatmap): x = カテゴリ, y = カテゴリ, value = 数値。 各 (x,y) セルを
-- value の連続色 (Viridis) で塗る。 value は ColorByContinuous で表現。 PS heatmap
-- と対応。
-- [English]: A heatmap: x is a category, y is a category, value is
-- numeric. Each (x,y) cell is colored using value's continuous color
-- (Viridis); value is represented via ColorByContinuous. Corresponds to
-- the PS heatmap.
heatmap :: ColRef -> ColRef -> ColRef -> Layer
heatmap x y v = mempty
{ lyKind = First (Just MHeatmap)
, lyEncX = Last (Just x), lyEncY = Last (Just y)
, lyColor = Last (Just (ColorByContinuous v))
}
-- | [日本語]: Contour / binned heatmap (= 連続 x/y/z、 grid 化してセル平均を
-- Viridis 色マッピング)。 ResponseSurface の基盤。 color は ColorByContinuous で
-- z 列を表現。
-- [English]: Contour / binned heatmap (continuous x/y/z, gridded and
-- the per-cell average mapped to a Viridis color). The foundation for
-- ResponseSurface. color represents the z column via ColorByContinuous.
contour :: ColRef -> ColRef -> ColRef -> Layer
contour x y z = mempty
{ lyKind = First (Just MContour)
, lyEncX = Last (Just x), lyEncY = Last (Just y)
, lyColor = Last (Just (ColorByContinuous z))
}
-- | [日本語]: filled contour (= matplotlib @contourf@ / ggplot
-- @geom_contour_filled@)。 等値帯を Viridis 連続色で塗る。 入力が規則 grid
-- (x 固有値 × y 固有値が全組存在) なら補間せず直入力、 散布なら k 近傍 IDW で
-- 格子化 ('Graphics.Hgg.Math.Griddata')。 線の 'contour' と重畳すると
-- matplotlib の contourf+contour 同等。
-- [English]: A filled contour (like matplotlib's @contourf@ / ggplot's
-- @geom_contour_filled@). Fills iso-bands with a continuous Viridis
-- color. If the input is a regular grid (every combination of the x and
-- y distinct values is present), it is used as-is with no
-- interpolation; scattered input is gridded via k-nearest-neighbor IDW
-- ('Graphics.Hgg.Math.Griddata'). Overlaying it with the line-based
-- 'contour' matches matplotlib's contourf+contour.
contourFilled :: ColRef -> ColRef -> ColRef -> Layer
contourFilled x y z = mempty
{ lyKind = First (Just MContourFilled)
, lyEncX = Last (Just x), lyEncY = Last (Just y)
, lyColor = Last (Just (ColorByContinuous z))
}
-- | [日本語]: 等高線の本数 (既定 8)。 @contour x y z <> contourLevels 12@。
-- [English]: The number of contour levels (default 8). Example:
-- @contour x y z <> contourLevels 12@.
contourLevels :: Int -> Layer
contourLevels n = mempty { lyContourLevels = Last (Just n) }
-- | [日本語]: 等高線レベルの明示指定 (本数指定より優先)。
-- [English]: Explicitly specifies contour levels (takes priority over
-- the level-count setting).
contourBreaks :: [Double] -> Layer
contourBreaks bs = mempty { lyContourBreaks = Last (Just bs) }
-- | [日本語]: binned heatmap (= ggplot geom_bin2d / stat_summary_2d)。 連続
-- x/y/z を nBins×nBins の grid に binning し、 各セルの z 平均を連続色
-- (Viridis) で塗る。 'contour' (等高線) の塗り版。 ResponseSurface の塗り基盤。
-- [English]: A binned heatmap (like ggplot's geom_bin2d /
-- stat_summary_2d). Bins continuous x/y/z into an nBins×nBins grid and
-- colors each cell by its z average using a continuous (Viridis) color.
-- The filled counterpart of the contour-line 'contour'; the foundation
-- for the filled ResponseSurface.
bin2d :: ColRef -> ColRef -> ColRef -> Layer
bin2d x y z = mempty
{ lyKind = First (Just MBin2d)
, lyEncX = Last (Just x), lyEncY = Last (Just y)
, lyColor = Last (Just (ColorByContinuous z))
}
-- | [日本語]: Ch10 EDA: 2D bin の__件数__を連続色で塗る (= ggplot @geom_bin2d()@
-- 既定)。 @bin2dCount x y@ は連続 x/y を 12×12 grid に binning し、 各セルの
-- __観測件数__を Viridis で塗る (z 列なし = 'bin2d' の count 版)。 'bin2d'
-- (z 平均) は stat_summary_2d 相当。
-- [English]: Ch10 EDA: colors the __count__ of a 2D bin with a
-- continuous color (ggplot's @geom_bin2d()@ default). @bin2dCount x y@
-- bins continuous x/y into a 12×12 grid and colors each cell by its
-- __observed count__ using Viridis (no z column — the count version of
-- 'bin2d'). 'bin2d' (z average) corresponds to stat_summary_2d.
bin2dCount :: ColRef -> ColRef -> Layer
bin2dCount x y = mempty
{ lyKind = First (Just MBin2d)
, lyEncX = Last (Just x), lyEncY = Last (Just y)
}
-- | [日本語]: geom_tile / geom_raster 相当。 連続 x/y を__セル中心__、 fill を
-- __離散カテゴリ__として矩形をベタ塗りする (幅/高さは格子間隔から自動・隙間
-- なし)。 bin2d と違い再ビニングせず 1 行=1 セルをそのまま塗る (= 決定境界の
-- res×res グリッド塗り)。 fill の離散色と離散凡例は colorBy 経路で自動 (重ねる
-- 散布点と同じカテゴリ空間ならパレット一致)。 連続 fill の塗りは 'bin2d'
-- (再ビニング) を使う。
-- [English]: The equivalent of geom_tile / geom_raster. Treats
-- continuous x/y as a __cell center__ and fill as a __discrete category__,
-- filling rectangles solidly (width/height are derived
-- automatically from the grid spacing, with no gaps). Unlike bin2d, it
-- does not re-bin — one row is drawn as one cell as-is (used for
-- painting a decision-boundary res×res grid). The discrete fill color
-- and legend are handled automatically via the colorBy path (palettes
-- match an overlaid scatter's category space). For continuous fill, use
-- 'bin2d' (which re-bins).
tile :: ColRef -> ColRef -> ColRef -> Layer
tile x y fill = mempty
{ lyKind = First (Just MTile)
, lyEncX = Last (Just x), lyEncY = Last (Just y)
, lyColor = Last (Just (ColorByCol fill))
}
-- | [日本語]: hexbin (= matplotlib @hexbin@ / ggplot @geom_hex@)。 連続 x/y を
-- __六角格子__で binning し、 各セルの__観測件数__を Viridis 連続色で塗る (=
-- 散布過密の密度可視化)。 セル分割数は 'hexbinBins' で上書き (既定 30)。 矩形
-- ビンの 'bin2dCount' の六角版。 アルゴは d3-hexbin (Carr 1987) を binwidth
-- 正規化空間で適用 (pointy-top)。
-- [English]: hexbin (like matplotlib's @hexbin@ / ggplot's @geom_hex@).
-- Bins continuous x/y into a __hexagonal grid__ and colors each cell by
-- its __observed count__ using a continuous Viridis color (a density
-- visualization for dense scatter). The number of cell divisions is
-- overridden via 'hexbinBins' (default 30); the hexagonal counterpart of
-- the rectangular-bin 'bin2dCount'. The algorithm applies d3-hexbin
-- (Carr 1987) in binwidth-normalized space (pointy-top).
hexbin :: ColRef -> ColRef -> Layer
hexbin x y = mempty
{ lyKind = First (Just MHexbin)
, lyEncX = Last (Just x), lyEncY = Last (Just y)
}
-- | [日本語]: hexbin の x 方向セル分割数を指定 (= ggplot @bins@ / matplotlib
-- @gridsize@)。 既定 30。 'hexbin' に @<>@ で重ねる:
-- @layer (hexbin "x" "y" <> hexbinBins 40)@。 内部は 'lyBinCount' を流用
-- (histogram と共有フィールド)。
-- [English]: Sets the number of x-direction cell divisions for hexbin
-- (like ggplot's @bins@ / matplotlib's @gridsize@). Default 30. Layer it
-- onto 'hexbin' with @<>@: @layer (hexbin "x" "y" <> hexbinBins 40)@.
-- Internally reuses 'lyBinCount' (a field shared with histogram).
hexbinBins :: Int -> Layer
hexbinBins n = mempty { lyBinCount = Last (Just n) }
-- | [日本語]: P12: step plot (= 階段状 line)。
-- [English]: P12: a step plot (a staircase-shaped line).
step :: ColRef -> ColRef -> Layer
step x y = mempty
{ lyKind = First (Just MStep), lyEncX = Last (Just x), lyEncY = Last (Just y) }
-- | [日本語]: stat-in 線形回帰 (= ggplot @geom_smooth(method="lm")@)。 純タグ
-- Layer。 回帰 fit は描画前に analyze-bridge の @resolveStats@ が hanalyze で
-- 行い、 信頼帯 (band) + 回帰線 (line) に展開する。 装飾は通常 geom と同じ:
-- @statLm "x" "y" <> color N.red <> stroke 2@。 ★単体では描画されない (renderer
-- は MStatLM を skip)。 必ず bridge の saveSVGBoundStats 等で解決する。
-- [English]: An in-place (stat-in) linear regression (like ggplot's
-- @geom_smooth(method="lm")@). A pure tag Layer. Before drawing, the
-- analyze-bridge's @resolveStats@ performs the fit via hanalyze and
-- expands it into a confidence band (band) plus a regression line
-- (line). Decoration works the same as an ordinary geom:
-- @statLm "x" "y" <> color N.red <> stroke 2@. It is never drawn on its
-- own (the renderer skips MStatLM) — it must be resolved via the
-- bridge's saveSVGBoundStats or similar.
statLm :: ColRef -> ColRef -> Layer
statLm x y = mempty
{ lyKind = First (Just MStatLM), lyEncX = Last (Just x), lyEncY = Last (Just y) }
-- | [日本語]: 信頼水準を指定できる線形回帰 stat。 'statLm' は 0.95 固定だが、
-- こちらは @lvl@ (例 0.99) を 'lyStatLevel' に持たせる。 resolveStats が band
-- 幅に反映する。
-- [English]: A linear-regression stat that lets you specify the
-- confidence level. Whereas 'statLm' is fixed at 0.95, this one stores
-- @lvl@ (e.g. 0.99) in 'lyStatLevel'; resolveStats reflects it in the
-- band width.
statLmLevel :: ColRef -> ColRef -> Double -> Layer
statLmLevel x y lvl = (statLm x y)
{ lyStatLevel = Last (Just lvl) }
-- | [日本語]: stat-in B-spline 平滑 (= ggplot @geom_smooth()@)。 knot 数 n。
-- 曲線のみ (帯なし)。 resolveStats が hanalyze で fit し line に展開。 装飾は
-- line に引き継がれる。
-- [English]: An in-place (stat-in) B-spline smoother (like ggplot's
-- @geom_smooth()@), with n knots. Curve only (no band). resolveStats fits
-- it via hanalyze and expands it into a line; decoration carries over to
-- the line.
statSmooth :: ColRef -> ColRef -> Int -> Layer
statSmooth x y n = mempty
{ lyKind = First (Just MStatSmooth), lyEncX = Last (Just x), lyEncY = Last (Just y)
, lyBinCount = Last (Just n) }
-- | [日本語]: 信頼帯つき B-spline 平滑。 'statSmooth' は曲線のみだが、 こちらは
-- 'lyStatLevel' を Just にして「帯あり」を signal する。 resolveStats が bs
-- 設計行列の confidenceBand で band+line に展開する。 既定水準は 0.95
-- (@statSmoothCI x y n@)。
-- [English]: A B-spline smoother with a confidence band. Whereas
-- 'statSmooth' is curve-only, this one sets 'lyStatLevel' to Just to
-- signal "band included". resolveStats expands it into band+line via the
-- bs design matrix's confidenceBand. The default level is 0.95
-- (@statSmoothCI x y n@).
statSmoothCI :: ColRef -> ColRef -> Int -> Layer
statSmoothCI x y n = (statSmooth x y n)
{ lyStatLevel = Last (Just 0.95) }
-- | [日本語]: 多項式回帰 stat
-- (= ggplot @geom_smooth(method="lm", formula=y~poly(x,deg))@)。 次数 deg は
-- 'lyBinCount' を流用。 resolveStats が @y ~ poly(x,deg)@ で fit し band+line に
-- 展開。 信頼帯の水準は 'lyStatLevel' (既定 0.95)。 ★単体では描画されない
-- (renderer は MStatPoly を skip)。
-- [English]: A polynomial-regression stat (like ggplot's
-- @geom_smooth(method="lm", formula=y~poly(x,deg))@). The degree deg
-- reuses 'lyBinCount'. resolveStats fits @y ~ poly(x,deg)@ and expands it
-- into band+line; the confidence band's level is 'lyStatLevel' (default
-- 0.95). It is never drawn on its own (the renderer skips MStatPoly).
statPoly :: ColRef -> ColRef -> Int -> Layer
statPoly x y deg = mempty
{ lyKind = First (Just MStatPoly), lyEncX = Last (Just x), lyEncY = Last (Just y)
, lyBinCount = Last (Just deg) }
-- | [日本語]: 残差 vs fitted 診断散布 (= base R @plot(lm)@ #1)。 @y ~ x@ で fit し
-- 各点を (fitted, residual) に写した scatter に展開する (回帰診断)。 装飾は
-- scatter に引き継ぐ。 ★単体では描画されない (renderer は MStatResid を
-- skip)。 bridge resolveStats が必要。
-- [English]: A residual-vs-fitted diagnostic scatter (base R's
-- @plot(lm)@ #1). Fits @y ~ x@ and expands each point into a scatter
-- mapped to (fitted, residual) — a regression diagnostic. Decoration
-- carries over to the scatter. It is never drawn on its own (the
-- renderer skips MStatResid); it requires the bridge's resolveStats.
statResid :: ColRef -> ColRef -> Layer
statResid x y = mempty
{ lyKind = First (Just MStatResid), lyEncX = Last (Just x), lyEncY = Last (Just y) }
-- | [日本語]: P11: stem / lollipop plot。
-- [English]: P11: a stem / lollipop plot.
stem :: ColRef -> ColRef -> Layer
stem x y = mempty
{ lyKind = First (Just MStem), lyEncX = Last (Just x), lyEncY = Last (Just y) }
-- | [日本語]: TODO-11 (2026-05-27): area band (= 信頼区間 / 予測帯)。
-- x = 共通 x 軸
-- yLow = 下境界 y
-- yHigh = 上境界 y
-- Render は PPath fill 1 枚 (= forward x-yLow + backward x-yHigh + close)。
-- alpha は layer modifier の `alpha` で指定 (= default 0.2)。
-- [English]: TODO-11 (2026-05-27): an area band (a confidence interval /
-- prediction band).
-- x = the shared x axis
-- yLow = the lower bound y
-- yHigh = the upper bound y
-- Rendered as a single PPath fill (forward along x-yLow, backward along
-- x-yHigh, then close). alpha is set via the layer modifier `alpha`
-- (default 0.2).
band :: ColRef -> ColRef -> ColRef -> Layer
band x yLow yHigh = mempty
{ lyKind = First (Just MBand)
, lyEncX = Last (Just x)
, lyEncY = Last (Just yLow)
, lyEncY2 = Last (Just yHigh)
}
-- | [日本語]: streamgraph (= 中心化積層 area)。
-- x = 共通 x 軸 (連続、 例: 時間)
-- y = 各系列の値
-- 系列分割は color aesthetic で行う (= 'bar' の群分けと同じ機構)。
--
-- > stream "t" "value" <> colorBy "series"
--
-- 各 x 点で系列を積層し baseline を -(Σy)/2 から開始する (silhouette 中心化)。
-- wiggle 最小化 (ThemeRiver) は行わない。
-- [English]: A streamgraph (a centered, stacked area).
-- x = the shared x axis (continuous, e.g. time)
-- y = each series' value
-- Series are split via the color aesthetic (the same mechanism used for
-- grouping in 'bar').
--
-- > stream "t" "value" <> colorBy "series"
--
-- At each x point, series are stacked with the baseline starting at
-- -(Σy)/2 (silhouette centering). Wiggle minimization (ThemeRiver) is not
-- performed.
stream :: ColRef -> ColRef -> Layer
stream x y = mempty
{ lyKind = First (Just MStream), lyEncX = Last (Just x), lyEncY = Last (Just y) }
-- | [日本語]: P2: violin plot。 ★ boxplot と同じく __値 1 列__を受ける。 群分けは
-- @<> groupBy "g"@ (色一律) / @<> colorBy "g"@ (群色+凡例) で付ける (ggplot
-- 同型)。 群指定なしなら単一 violin。
-- [English]: P2: a violin plot. Like boxplot, it takes a __single value column__.
-- Grouping is added with @<> groupBy "g"@ (uniform color) /
-- @<> colorBy "g"@ (per-group color + legend), matching ggplot. With no
-- group specified, it draws a single violin.
violin :: ColRef -> Layer
violin v = mempty { lyKind = First (Just MViolin), lyEncY = Last (Just v) }
-- | [日本語]: P3: strip plot。 ★ 値 1 列 + groupBy/colorBy で群分け。
-- [English]: P3: a strip plot. A single value column, grouped via
-- groupBy/colorBy.
strip :: ColRef -> Layer
strip v = mempty { lyKind = First (Just MStrip), lyEncY = Last (Just v) }
-- | [日本語]: P3: swarm plot。 ★ 値 1 列 + groupBy/colorBy で群分け。
-- [English]: P3: a swarm plot. A single value column, grouped via
-- groupBy/colorBy.
swarm :: ColRef -> Layer
swarm v = mempty { lyKind = First (Just MSwarm), lyEncY = Last (Just v) }
-- | [日本語]: P22: raincloud (= violin + box + strip 合成)。 ★ 値 1 列 +
-- groupBy/colorBy。 mark 直結合成。 @a \<+\> b@ は a を base、 b を重畳
-- sub-mark とする __単一 Layer__ を返す (= 戻り型 Layer 維持ゆえ
-- @raincloud v \<+\> ... \<\> groupBy g@ のような群修飾が従来どおり効く)。
-- b 側の overlay も平坦化して取り込む。 render は base + 各 overlay を
-- 「親の群 (encX)・色 (colorBy)・値 (encY) を継承・自前の
-- kind/nudge/markWidth/side で」 描く。 1D 分布 mark (box/violin/strip/swarm)
-- の重畳を想定 (= raincloud / 自作 composite)。
-- [English]: P22: raincloud (a composite of violin + box + strip). A
-- single value column, grouped via groupBy/colorBy. A direct mark
-- combinator: @a \<+\> b@ returns a __single Layer__ with a as the base
-- and b as the overlaid sub-mark (since the return type stays Layer,
-- group modifiers such as @raincloud v \<+\> ... \<\> groupBy g@ keep
-- working as before). b's own overlays are flattened in as well.
-- Rendering draws the base plus each overlay by "inheriting the
-- parent's group (encX), color (colorBy) and value (encY), with its own
-- kind/nudge/markWidth/side". Intended for overlaying 1D distribution
-- marks (box/violin/strip/swarm) — used by raincloud / custom
-- composites.
infixl 7 <+>
(<+>) :: Layer -> Layer -> Layer
a <+> b = a { lyOverlay = lyOverlay a ++ [b { lyOverlay = [] }] ++ lyOverlay b }
-- | [日本語]: P22: raincloud (= 半 violin + box + jitter strip の合成)。 ★ 専用
-- mark を廃し '<+>' による 3 sub-mark 合成の preset に降格 (= 位置決めは D1
-- つまみ nudge/markWidth/side に委譲)。 戻り型は Layer なので
-- @raincloud v \<\> groupBy g@ / @\<\> colorBy g@ は従来どおり群分けする。
-- [English]: P22: raincloud (a composite of a half violin + box +
-- jitter strip). Retired as a dedicated mark and demoted to a preset
-- built from a 3-sub-mark composite via '<+>' (positioning is delegated
-- to the D1 knobs nudge/markWidth/side). Since the return type is Layer,
-- @raincloud v \<\> groupBy g@ / @\<\> colorBy g@ still group as before.
raincloud :: ColRef -> Layer
raincloud v =
(violin v <> side SideRight <> nudge 0.15 <> markWidth 0.40)
<+> (boxplot v <> nudge 0.00 <> markWidth 0.10)
<+> (strip v <> nudge (-0.25) <> markWidth 0.18)
-- | [日本語]: 合成 Layer (base + overlay sub-mark) の値列レーン (= encY の
-- distinct・base 先頭・'colRefName' で重複除去)。 描画/Layout は各マークの
-- slot を「自 encY が此のレーン列の何番目か」で決める。 同一列なら 1 レーン
-- (= raincloud の重畳)、 複数列なら横並び (= distCols)。
-- [English]: The value-column lanes of a composite Layer (base + overlay
-- sub-marks) — the distinct encY values, base first, deduplicated via
-- 'colRefName'. Drawing/layout decides each mark's slot by "which
-- position its own encY occupies among these lane columns". The same
-- column collapses to a single lane (raincloud's overlay); different
-- columns lay out side by side (distCols).
compositeLanes :: Layer -> [ColRef]
compositeLanes ly = foldl add [] [ c | l <- ly : lyOverlay ly, Just c <- [getLast (lyEncY l)] ]
where add acc c = if any ((== colRefName c) . colRefName) acc then acc else acc ++ [c]
-- | [日本語]: P21: ridge / joyplot。 ★ 他 distribution mark と統一して
-- __値 1 列__を受ける。 群分けは @<> groupBy "g"@ / @<> colorBy "g"@ (=
-- box/violin と同じ)。 群指定なしは単一 density 風。 ridge は値→x・群→y の
-- 向きが要るため、 ridge レイヤを含む spec は 'Graphics.Hgg.Spec.Setters.ridgeAutoFlip' で coord_flip
-- を自動適用する (値が x、 群が y に回る)。 内部表現は violin と同じ encY=値。
-- [English]: P21: ridge / joyplot. Unified with the other distribution
-- marks, it takes a __single value column__. Grouping is added via
-- @<> groupBy "g"@ / @<> colorBy "g"@ (the same as box/violin); with no
-- group specified it looks like a single density curve. Since ridge
-- needs value→x and group→y, a spec containing a ridge layer
-- automatically applies coord_flip via 'Graphics.Hgg.Spec.Setters.ridgeAutoFlip' (value becomes x,
-- group becomes y). Internally represented the same way as violin,
-- encY=value.
ridge :: ColRef -> Layer
ridge v = mempty { lyKind = First (Just MRidge), lyEncY = Last (Just v) }
-- | [日本語]: P14: scatter jitter (= plotArea 比率 0..1)。
-- [English]: P14: scatter jitter (a plotArea ratio in 0..1).
jitterX, jitterY :: Double -> Layer
jitterX a = mempty { lyJitterX = Last (Just a) }
jitterY a = mempty { lyJitterY = Last (Just a) }
-- | [日本語]: frontend-settings v0.1 §2.4: histogram の bin 数 (= default 10)。
-- [English]: frontend-settings v0.1 §2.4: the number of histogram bins
-- (default 10).
binCount :: Int -> Layer
binCount n = mempty { lyBinCount = Last (Just n) }
-- | [日本語]: histogram の bin 幅 (= ggplot @geom_histogram(binwidth = w)@)。
-- 'binWidth' を指定すると 'binCount' より優先され、 'histBinning' が ggplot
-- 流 (boundary = w/2 で bin 原点を定める) の bin 化を行う。
-- [English]: The histogram bin width (like ggplot's
-- @geom_histogram(binwidth = w)@). Specifying 'binWidth' takes priority
-- over 'binCount', and 'histBinning' bins in the ggplot style
-- (determining the bin origin with boundary = w/2).
binWidth :: Double -> Layer
binWidth w = mempty { lyBinWidth = Last (Just w) }
-- | [日本語]: histogram の bin 化パラメタ (origin, binW, nBin) を決める単一
-- 情報源。 render (Render.Basic) と y/x range (Layout.RangeOf) の双方がこれを
-- 使い、 bin 境界・棒高・軸範囲を一致させる。
--
-- * 'lyBinWidth' 指定時: ggplot @bin_breaks_width@ と同式。 boundary = w/2 とし、
-- origin = boundary + floor((lo - boundary)/w) * w、 nBin = ceil((hi - origin)/w)。
-- これで R4DS の @binwidth=@ と同じ bin 境界・棒高になる。
-- * 未指定時: 従来どおり 'lyBinCount' (既定 30) で [lo,hi] を等分。
--
-- bin i は @[origin + i*binW, origin + (i+1)*binW)@、 値 v の所属は
-- @clamp 0 (nBin-1) (floor ((v - origin)/binW))@。
-- [English]: The single source of truth that determines the histogram
-- binning parameters (origin, binW, nBin). Both render (Render.Basic)
-- and the y/x range (Layout.RangeOf) use it, so bin boundaries, bar
-- heights and axis ranges stay consistent.
--
-- * When 'lyBinWidth' is given: the same formula as ggplot's
-- @bin_breaks_width@. With boundary = w/2, origin = boundary +
-- floor((lo - boundary)/w) * w and nBin = ceil((hi - origin)/w). This
-- gives the same bin boundaries and bar heights as R4DS's
-- @binwidth=@.
-- * When unspecified: as before, divides [lo,hi] evenly using
-- 'lyBinCount' (default 30).
--
-- Bin i is @[origin + i*binW, origin + (i+1)*binW)@; a value v belongs to
-- @clamp 0 (nBin-1) (floor ((v - origin)/binW))@.
histBinning :: Layer -> (Double, Double) -> (Double, Double, Int)
histBinning ly (lo, hi) =
case getLast (lyBinWidth ly) of
Just w | w > 0 ->
let boundary = w / 2
shift = fromIntegral (floor ((lo - boundary) / w) :: Int)
origin = boundary + shift * w
nBin = max 1 (ceiling ((hi - origin) / w))
in (origin, w, nBin)
_ ->
let nBin = case getLast (lyBinCount ly) of
Just n | n > 0 -> n
_ -> 30
binW = if hi > lo then (hi - lo) / fromIntegral nBin else 1
in (lo, binW, nBin)
-- | [日本語]: hexbin の六角セル (中心 + 件数 + 6 頂点、 すべてデータ座標)。
-- [English]: A hexbin hex cell (center + count + six vertices, all in
-- data coordinates).
data HexCell = HexCell
{ hexCx :: !Double -- ^ [日本語]: セル中心 x (データ座標)。 [English]: Cell center x (data coordinates).
, hexCy :: !Double -- ^ [日本語]: セル中心 y。 [English]: Cell center y.
, hexCount :: !Int -- ^ [日本語]: セルに入った点数。 [English]: Number of points in the cell.
, hexVerts :: ![(Double, Double)] -- ^ [日本語]: 6 頂点 (pointy-top、 データ座標)。 [English]: The six vertices (pointy-top, data coordinates).
} deriving (Show, Eq)
-- | [日本語]: 六角ビニング (d3-hexbin = Carr 1987)。 @bins@ = x 方向セル分割数。
-- (xmin,xmax)/(ymin,ymax) = データ範囲、 @pts@ = (x,y) 点列。 binwidth で正規化
-- した (u,v) 空間で点を六角セルに割当て件数を数え、 中心・6 頂点をデータ座標で
-- 返す (= scale パイプラインでそのまま screen へ。 pointy-top)。 ★HS/PS で同式・
-- JS Math.round (= @floor (z+0.5)@) を使い byte 一致させる。
-- [English]: Hexagonal binning (d3-hexbin = Carr 1987). @bins@ is the
-- number of x-direction cell divisions; (xmin,xmax)/(ymin,ymax) is the
-- data range and @pts@ is the list of (x,y) points. Points are assigned
-- to hex cells in (u,v) space normalized by binwidth, counted, and
-- returned with center + six vertices in data coordinates (fed straight
-- into the scale pipeline to reach screen space; pointy-top). HS and PS
-- use the identical formula and JS Math.round (= @floor (z+0.5)@) to
-- match byte-for-byte.
hexbinCells :: Int -> (Double, Double) -> (Double, Double)
-> [(Double, Double)] -> [HexCell]
hexbinCells bins (xmin, xmax) (ymin, ymax) pts
| bins <= 0 || bwx <= 0 || bwy <= 0 || null pts = []
| otherwise =
[ mkCell (head grp) (length grp)
| grp <- Data.List.group (Data.List.sort (map assign pts)) ]
where
bwx = (xmax - xmin) / fromIntegral bins
bwy = (ymax - ymin) / fromIntegral bins
dyv = sqrt 3 / 2 -- = 1.5·r (r = 1/√3、 dx=√3·r=1 に正規化)
ruv = 1 / sqrt 3
jsRound z = floor (z + 0.5) :: Int -- JS Math.round (half-up)・HS=PS 一致用
-- 点 → セルキー (pi, pj) (d3-hexbin verbatim)
assign :: (Double, Double) -> (Int, Int)
assign (x, y) =
let u = (x - xmin) / bwx
v = (y - ymin) / bwy
py = v / dyv
pj = jsRound py
px = u - (if odd pj then 0.5 else 0) -- dx=1、 奇数行 0.5 シフト
pii = jsRound px
py1 = py - fromIntegral pj
in if abs py1 * 3 > 1
then let px1 = px - fromIntegral pii
pi2 = fromIntegral pii + (if px < fromIntegral pii then -1 else 1) / 2 :: Double
pj2 = pj + (if py < fromIntegral pj then -1 else 1)
px2 = px - pi2
py2 = py - fromIntegral pj2
in if px1 * px1 + py1 * py1 > px2 * px2 + py2 * py2
then (jsRound (pi2 + (if odd pj then 1 else -1) / 2), pj2)
else (pii, pj)
else (pii, pj)
-- セルキー → HexCell (中心・頂点をデータ座標へ)
mkCell :: (Int, Int) -> Int -> HexCell
mkCell (pii, pj) n =
let cu = fromIntegral pii + (if odd pj then 0.5 else 0) -- × dx(=1)
cv = fromIntegral pj * dyv
cx = xmin + cu * bwx
cy = ymin + cv * bwy
vert k = let ang = fromIntegral k * pi / 3
vu = sin ang * ruv
vv = negate (cos ang) * ruv
in (xmin + (cu + vu) * bwx, ymin + (cv + vv) * bwy)
in HexCell cx cy n (map vert [0 .. 5 :: Int])
-- | [日本語]: hexbin layer を解決して六角セルを返す (renderHexbin と count
-- colorbar が共有)。 x/y を 'resolveNum' で取り NaN を除いて zip、 bins (既定
-- 30) で 'hexbinCells'。 render と凡例で__同じ count 域__を得るために 1 本に
-- 集約する。
-- [English]: Resolves a hexbin layer and returns its hex cells (shared
-- by renderHexbin and the count colorbar). Takes x/y via 'resolveNum',
-- drops NaN, zips them, and calls 'hexbinCells' with bins (default 30).
-- Consolidated into a single function so render and the legend see the
-- __same count domain__.
hexbinLayerCells :: Resolver -> Layer -> [HexCell]
hexbinLayerCells r ly =
case (getLast (lyEncX ly), getLast (lyEncY ly)) of
(Just xr, Just yr) ->
case (resolveNum r xr, resolveNum r yr) of
(Just xv, Just yv) ->
let pts = [ (x, y) | (x, y) <- zip (V.toList xv) (V.toList yv)
, not (isNaN x), not (isNaN y) ]
bins = case getLast (lyBinCount ly) of Just b | b > 0 -> b; _ -> 30
in if null pts then []
else let xs = map fst pts; ys = map snd pts
in hexbinCells bins (minimum xs, maximum xs) (minimum ys, maximum ys) pts
_ -> []
_ -> []
-- | [日本語]: TODO-3a (2026-05-29): histogram の y 軸を密度
-- (= count / (total * binW)) に正規化。 PS Spec.histogramDensity と同等。
-- SVG export でも動くように HS 側にも実装 (= 旧来 HS は count のみで density
-- mode が機能しなかった)。
-- [English]: TODO-3a (2026-05-29): normalizes the histogram's y axis to
-- density (count / (total * binW)). Equivalent to PS's
-- Spec.histogramDensity. Also implemented on the HS side so it works for
-- SVG export too (previously HS only supported count, so density mode
-- didn't work).
histogramDensity :: Bool -> Layer
histogramDensity b = mempty { lyHistDensity = Last (Just b) }
-- | [日本語]: histogram / bar の bin 境界線 (= 各バーの白枠) を表示するか。
-- デフォルトは False (= ggplot 流フラットバー、 枠なし)。 True で bin 区切りが
-- 見える。
-- [English]: Whether to show the bin border lines (a white outline per
-- bar) for histogram / bar. Default False (a flat ggplot-style bar with
-- no border); True makes the bin boundaries visible.
histBorder :: Bool -> Layer
histBorder b = mempty { lyHistBorder = Last (Just b) }
-- | [日本語]: density 曲線の下を塗りつぶす (= ggplot
-- @geom_density(aes(fill = …))@)。 群別 ('color') と 'alpha' を併用すると、
-- 各群を群色 × alpha で塗る (R4DS Ch1 §1.5)。 既定 (未指定/False) は ggplot
-- 同様 fill=NA = 線のみ。
-- [English]: Fills below the density curve (like ggplot's
-- @geom_density(aes(fill = …))@). Combined with per-group color
-- ('color') and 'alpha', each group is filled with its group color ×
-- alpha (R4DS Ch1 §1.5). The default (unspecified/False) is fill=NA as
-- in ggplot — line only.
densityFill :: Bool -> Layer
densityFill b = mempty { lyDensityFill = Last (Just b) }
-- | [日本語]: マーカーを中抜き (= ggplot @shape="circle open"@ /
-- @geom_point(fill = NA)@)。 塗りを透明にし、 点色で輪郭 (stroke) のみ描く。
-- 'size' で輪郭円の直径、 'stroke' で線幅 (既定 1pt)。 重畳して「点を輪で
-- 囲む」 強調に使う (R4DS Ch9 §9.6)。
-- [English]: Makes markers hollow (like ggplot's
-- @shape="circle open"@ / @geom_point(fill = NA)@). Fill is made
-- transparent, drawing only the outline (stroke) in the point color.
-- 'size' controls the outline circle's diameter, 'stroke' its line
-- width (default 1pt). Used as an overlay to emphasize points by
-- "circling" them (R4DS Ch9 §9.6).
hollow :: Layer
hollow = mempty { lyHollow = Last (Just True) }
-- | [日本語]: 分布 mark (box/violin/strip/swarm) の slot 内横 offset。 値は
-- __slot 幅比__ (= ggplot @position_nudge@)。 正で右、 負で左。 raincloud の
-- 「box を中央・strip を左・雲を右」のような重畳配置を組むのに使う (= 旧
-- raincloud のハードコード offset を置換)。
-- [English]: The horizontal offset within a slot for distribution marks
-- (box/violin/strip/swarm). The value is a __ratio of the slot width__
-- (like ggplot's @position_nudge@); positive moves right, negative
-- moves left. Used to build raincloud-style overlaid layouts such as
-- "box centered, strip to the left, cloud to the right" (replacing the
-- old hardcoded offsets in raincloud).
nudge :: Double -> Layer
nudge x = mempty { lyNudge = Last (Just x) }
-- | [日本語]: 分布 mark の幅 (= __slot 幅比・占有率__)。 各 mark の既定占有率
-- (box 0.5 / violin 0.7 / strip 0.4 / swarm 0.8) を上書きする。 raincloud
-- では box を細く (= 0.1 等) するのに使う。
-- [English]: The width of a distribution mark (a __ratio of the slot width — its occupancy__).
-- Overrides each mark's default occupancy
-- (box 0.5 / violin 0.7 / strip 0.4 / swarm 0.8). Used in raincloud to
-- thin the box (e.g. to 0.1).
markWidth :: Double -> Layer
markWidth w = mempty { lyMarkWidth = Last (Just w) }
-- | [日本語]: violin の片側化 (= 半 violin)。 @violin "v" <> side SideRight@ で
-- 右半分のみ。 raincloud の「雲」 (= 片側 violin) に使う。 box/strip 等には
-- 影響しない。
-- [English]: Makes a violin one-sided (a half violin). Example:
-- @violin "v" <> side SideRight@ shows only the right half. Used for
-- raincloud's "cloud" (a one-sided violin); has no effect on box/strip,
-- etc.
side :: Side -> Layer
side s = mempty { lySide = Last (Just s) }
-- | [日本語]: bar の position adjustment (= ggplot `position`)。 群分け (=
-- color/group aesthetic) があるとき 'PosDodge' / 'PosStack' / 'PosFill' で
-- 並べ方を選ぶ。 既定 ('PosIdentity') は従来通り単色棒 (color を見ない)。
-- [English]: The position adjustment for bar (like ggplot's `position`).
-- When there is grouping (a color/group aesthetic), choose the layout
-- with 'PosDodge' / 'PosStack' / 'PosFill'. The default ('PosIdentity')
-- draws a single-color bar as before (ignoring color).
--
-- > bar "cat" "y" <> colorBy "grp" <> position PosDodge
position :: Position -> Layer
position p = mempty { lyPosition = Last (Just p) }
-- | [日本語]: 固定 shape (= layer 全体に適用・ggplot @shape=@)。 bare=固定。
-- 'shapeBy' (列で map) より優先される ('Graphics.Hgg.Render.Common.pointShapeAt' 参照)。
-- [English]: A fixed shape (applies to the whole layer; like ggplot's
-- @shape=@). A bare value is fixed and takes priority over 'shapeBy'
-- (which maps from a column) — see 'Graphics.Hgg.Render.Common.pointShapeAt'.
shape :: MarkShape -> Layer
shape s = mempty { lyShape = Last (Just s) }
-- | [日本語]: C-6: shape categorical encoding 列。
-- [English]: C-6: the shape categorical-encoding column.
shapeBy :: ColRef -> Layer
shapeBy c = mempty { lyShapeBy = Last (Just c) }
-- | [日本語]: C-6: cat 名 → MarkShape 1 件追加 (= 複数 entry は <> で合成)。
-- [English]: C-6: adds a single cat name → MarkShape entry (combine
-- multiple entries with <>).
shapeMapEntry :: Text -> MarkShape -> Layer
shapeMapEntry v s = mempty { lyShapeMap = [ ShapeMapEntry { smeValue = v, smeShape = s } ] }
-- | [日本語]: C-6: size continuous encoding 列。
-- [English]: C-6: the size continuous-encoding column.
sizeBy :: ColRef -> Layer
sizeBy c = mempty { lySizeBy = Last (Just c) }
-- | [日本語]: alpha (= 不透明度) を連続値の列で encode する (= ggplot
-- @scale_alpha@・@aes(alpha = col)@)。 列値 min..max を alpha
-- @[0.1, 1.0]@ に線形 map (ggplot 既定 range)。 固定 alpha は bare 'alpha'
-- (案2 = bare 固定 / `*By` = map)。
-- [English]: Encodes alpha (opacity) from a continuous-valued column
-- (like ggplot's @scale_alpha@ / @aes(alpha = col)@). Linearly maps the
-- column's min..max to alpha @[0.1, 1.0]@ (ggplot's default range). A
-- fixed alpha uses the bare 'alpha' (convention: bare = fixed, `*By` =
-- mapped).
--
-- > scatter "x" "y" <> alphaBy "weight"
alphaBy :: ColRef -> Layer
alphaBy c = mempty { lyAlphaBy = Last (Just c) }
-- | [日本語]: 固定 linetype (= ggplot linetype="dashed")。 line 系 mark に適用。
-- 例: @line "x" "y" <> linetype LtDashed@
-- [English]: A fixed linetype (like ggplot's linetype="dashed"), applied
-- to line-family marks. Example: @line "x" "y" <> linetype LtDashed@
linetype :: LineType -> Layer
linetype lt = mempty { lyLinetype = Last (Just lt) }
-- | [日本語]: categorical linetype encoding 列 (= ggplot linetype=factor(g))。
-- line を群ごとに分割し各群へ巡回 LineType ('lineTypeForIndex') を割当。
-- 例: @line "x" "y" <> linetypeBy (ColByName "grp")@
-- [English]: A categorical linetype-encoding column (like ggplot's
-- linetype=factor(g)). Splits the line by group and assigns each group
-- a cycled LineType ('lineTypeForIndex'). Example:
-- @line "x" "y" <> linetypeBy (ColByName "grp")@
linetypeBy :: ColRef -> Layer
linetypeBy c = mempty { lyLinetypeBy = Last (Just c) }
-- | [日本語]: C-step trellis 色一貫性: 全データ cat 出現順を Layer に注入。
-- [English]: C-step trellis color consistency: injects the full
-- dataset's category order into the Layer.
colorCats :: [Text] -> Layer
colorCats cs = mempty { lyColorCats = cs }
-- | [日本語]: categorical 水準の既定順 (= ggplot2 の factor 既定 = アルファベット
-- 順)。 色 / x 軸 / shape の distinct を取るときに使い、 R4DS と凡例・色・並びを
-- 一致させる。 明示順が要るとき (fct_infreq 等) は 'colorCats' / @xCatOrder@ で
-- 上書きする。
-- [English]: The default order of categorical levels (matching
-- ggplot2's factor default — alphabetical). Used when taking distinct
-- values for color / x axis / shape, to keep legend, color and ordering
-- consistent with R4DS. When an explicit order is needed (e.g.
-- fct_infreq), override it with 'colorCats' / @xCatOrder@.
orderedCats :: [Text] -> [Text]
orderedCats = Data.List.sort . Data.List.nub
-- | [日本語]: 列の平均値を水平線として描画 (= PlotConfig.showMean)。
-- [English]: Draws the column's mean as a horizontal line
-- (PlotConfig.showMean).
statMean :: ColRef -> Layer
statMean c = mempty
{ lyKind = First (Just MStatMean), lyEncY = Last (Just c) }
-- | [日本語]: 列の中央値を水平線として描画 (= PlotConfig.showMedian)。
-- [English]: Draws the column's median as a horizontal line
-- (PlotConfig.showMedian).
statMedian :: ColRef -> Layer
statMedian c = mempty
{ lyKind = First (Just MStatMedian), lyEncY = Last (Just c) }
-- | [日本語]: parallel coordinates plot。 各 col が縦軸となり、 各 row を全軸
-- cross する折線で表現。 hover で row 強調 (= 後追い)。
-- [English]: A parallel-coordinates plot. Each col becomes a vertical
-- axis, and each row is drawn as a polyline crossing all axes. Row
-- highlighting on hover is a follow-up feature.
parallelCoords :: [ColRef] -> Layer
parallelCoords cols = mempty
{ lyKind = First (Just MParallel), lyHover = cols }
-- | [日本語]: HBM ModelGraph DAG を描画する layer。 内部 builder で使う直接
-- constructor。 ユーザは 'Graphics.Hgg.DAG.dagPlot' (= Graph a + ~> 経由) を
-- 使う方が良い。
-- [English]: A layer that draws an HBM ModelGraph DAG. A direct
-- constructor used by the internal builder. Users are better off using
-- 'Graphics.Hgg.DAG.dagPlot' (via Graph a + ~>).
dagFromLists :: [DAGNode] -> [DAGEdge] -> DAGLayoutAlgorithm -> Layer
dagFromLists nodes edges algo = mempty
{ lyKind = First (Just MDAG)
, lyDAG = Last (Just (DAGSpec nodes edges algo [])) }
-- | [日本語]: dsPlates も指定する版。
-- [English]: The variant that also specifies dsPlates.
dagFromListsWithPlates
:: [DAGNode] -> [DAGEdge] -> DAGLayoutAlgorithm -> [DAGPlate] -> Layer
dagFromListsWithPlates nodes edges algo plates = mempty
{ lyKind = First (Just MDAG)
, lyDAG = Last (Just (DAGSpec nodes edges algo plates)) }
-- | [日本語]: DAGNode constructor (= kind + 分布名なし)。
-- [English]: A DAGNode constructor (kind, with no distribution name).
dagNode :: Text -> Text -> DAGNodeKind -> Double -> Double -> DAGNode
dagNode i l k x y = DAGNode i l k Nothing x y
-- | [日本語]: 分布名付き DAGNode constructor (= PyMC 風 "name ~ dist" 表示用)。
-- [English]: A DAGNode constructor with a distribution name (for a
-- PyMC-style "name ~ dist" display).
dagNodeDist :: Text -> Text -> DAGNodeKind -> Text -> Double -> Double -> DAGNode
dagNodeDist i l k dist x y = DAGNode i l k (Just dist) x y
-- | [日本語]: DAGEdge constructor。
-- [English]: A DAGEdge constructor.
dagEdge :: Text -> Text -> DAGEdge
dagEdge f t = DAGEdge f t Nothing Nothing
-- | [日本語]: 互換用 shortcut: 既存 demo / test 用 (= NodeLatent +
-- LayoutManual)。 新規 API は Graphics.Hgg.DAG.dagPlot を使う。
-- [English]: A compatibility shortcut for existing demos / tests
-- (NodeLatent + LayoutManual). New code should use
-- Graphics.Hgg.DAG.dagPlot.
dag :: [DAGNode] -> [DAGEdge] -> Layer
dag nodes edges = dagFromLists nodes edges LayoutManual
-- | [日本語]: MCMC trace plot (single chain)。 iteration vs parameter 値の
-- line。 mark kind は MTrace (= alias for MLine、 frontend で区別可能)。
-- [English]: An MCMC trace plot (single chain): a line of iteration vs.
-- parameter value. Its mark kind is MTrace (an alias for MLine,
-- distinguishable by the frontend).
trace :: ColRef -> ColRef -> Layer
trace iterCol valCol = mempty
{ lyKind = First (Just MTrace)
, lyEncX = Last (Just iterCol)
, lyEncY = Last (Just valCol)
}
-- | [日本語]: multi-chain trace。 chain 列で色分け、 connect group も chain 列
-- (= chain 内で連結、 chain 跨ぎ無し)。 PlotConfig.StreamingTracePlot 等価。
-- [English]: A multi-chain trace. Colored by the chain column; the
-- connect group is also the chain column (connected within a chain, no
-- crossing between chains). Equivalent to
-- PlotConfig.StreamingTracePlot.
traceLines :: ColRef -> ColRef -> ColRef -> Layer
traceLines iterCol valCol chainCol =
trace iterCol valCol
<> colorBy chainCol
<> connectGroup chainCol
<> stroke 1.0