granite-0.3.0.4: Easy terminal plotting.
Copyright(c) 2025
LicenseMIT
Maintainermschavinda@gmail.com
Stabilityexperimental
PortabilityPOSIX
Safe HaskellNone
LanguageGHC2021

Granite

Description

A terminal-based plotting library that renders beautiful charts using Unicode Braille characters and ANSI colors. Granite provides a variety of chart types including scatter plots, line graphs, bar charts, pie charts, histograms, heatmaps, and box plots.

Basic Usage

Create a simple scatter plot:

{-# LANGUAGE OverloadedStrings #-}
import Granite
import Data.Text.IO as T

main = do
  let points = [(x, sin x) | x <- [0, 0.1 .. 6.28]]
      chart = scatter [series "sin(x)" points] defPlot
  T.putStrLn chart

Customization

Plots can be customized using record update syntax:

let customPlot = defPlot
      { widthChars = 80
      , heightChars = 30
      , plotTitle = "My Chart"
      , legendPos = LegendBottom
      }

Terminal Requirements

This library requires a terminal that supports:

  • Unicode (specifically Braille patterns U+2800-U+28FF)
  • ANSI color codes
  • Monospace font with proper Braille character rendering
Synopsis

Plot Configuration

data Plot Source #

Plot configuration parameters.

Controls the appearance and layout of generated charts.

Constructors

Plot 

Fields

defPlot :: Plot Source #

Default plot configuration.

Creates a 60×20 character plot with reasonable defaults:

defPlot = Plot
  { widthChars   = 60
  , heightChars  = 20
  , leftMargin   = 6
  , bottomMargin = 2
  , titleMargin  = 1
  , xBounds      = (Nothing, Nothing)
  , yBounds      = (Nothing, Nothing)
  , plotTitle    = ""
  , legendPos    = LegendRight
  , colorPalette = [ BrightBlue, BrightMagenta, BrightCyan, BrightGreen, BrightYellow, BrightRed, BrightWhite, BrightBlack]
  , xFormatter   =  _ _ v -> show v
  , yFormatter   =  _ _ v -> show v
  , xNumTicks    = 2
  , yNumTicks    = 2
  }

data LegendPos Source #

Position of the legend in the plot.

Constructors

LegendRight

Display legend on the right side of the plot

LegendBottom

Display legend below the plot

LegendNone

Do not display legend.

Instances

Instances details
Show LegendPos Source # 
Instance details

Defined in Granite

Eq LegendPos Source # 
Instance details

Defined in Granite

Formatting

data Color Source #

Supported ANSI colo(u)rs.

Instances

Instances details
Show Color Source # 
Instance details

Defined in Granite

Methods

showsPrec :: Int -> Color -> ShowS #

show :: Color -> String #

showList :: [Color] -> ShowS #

Eq Color Source # 
Instance details

Defined in Granite

Methods

(==) :: Color -> Color -> Bool #

(/=) :: Color -> Color -> Bool #

type LabelFormatter Source #

Arguments

 = AxisEnv

Axis context (domain, tick index/count, etc)

-> Int

Slot width budget in characters for this tick.

-> Double

Raw data value for the tick

-> Text

Rendered label (if it doesn't fit in the slot it will be truncated)

Axis-aware, width-limited, tick-label formatter.

Given: * axis context * a per-tick width budget (in terminal cells) * and the raw tick value. returns the label to render.

data AxisEnv Source #

What the formatter gets to know about the axis/ticks

Constructors

AxisEnv 

Fields

Data Preparation

series Source #

Arguments

:: Text

Name of the series (appears in legend)

-> [(Double, Double)]

List of (x, y) data points

-> (Text, [(Double, Double)]) 

Create a named data series for multi-series plots.

let s1 = series "Dataset A" [(1,2), (2,4), (3,6)]
    s2 = series "Dataset B" [(1,3), (2,5), (3,7)]
    chart = scatter [s1, s2] defPlot

bins :: Int -> Double -> Double -> Bins Source #

Create a bin configuration for histograms.

bins 10 0 100  -- 10 bins from 0 to 100
bins 20 (-5) 5 -- 20 bins from -5 to 5

data Bins Source #

Defines the binning parameters.

Constructors

Bins 

Fields

Instances

Instances details
Show Bins Source # 
Instance details

Defined in Granite

Methods

showsPrec :: Int -> Bins -> ShowS #

show :: Bins -> String #

showList :: [Bins] -> ShowS #

Eq Bins Source # 
Instance details

Defined in Granite

Methods

(==) :: Bins -> Bins -> Bool #

(/=) :: Bins -> Bins -> Bool #

Chart Types

histogram Source #

Arguments

:: Bins

Binning configuration

-> [Double]

Raw data values to bin

-> Plot

Plot configuration

-> Text

Rendered chart as Text

Create a histogram from numerical data.

Data is binned according to the provided Bins configuration.

Example

Expand
import System.Random

-- Generate random normal-like distribution
let values = take 1000 $ randomRs (0, 100) gen
    chart = histogram (bins 20 0 100) values defPlot

bars Source #

Arguments

:: [(Text, Double)]

List of (category, value) pairs

-> Plot

Plot configuration

-> Text

Rendered chart as Text

Create a bar chart from categorical data.

Each bar is colored differently and labeled with its category name.

Example

Expand
let data = [(Apple, 45.2), (Banana, 38.1), (Orange, 52.7)]
    chart = bars data defPlot { plotTitle = "Fruit Sales" }

scatter Source #

Arguments

:: [(Text, [(Double, Double)])]

List of named data series

-> Plot

Plot configuration

-> Text

Rendered chart as Text

Create a scatter plot from multiple data series.

Each series is rendered with a different color and pattern. Points are plotted using Braille characters for sub-character resolution.

Example

Expand
let points1 = [(x, x^2) | x <- [-3, -2.5 .. 3]]
    points2 = [(x, 2*x + 1) | x <- [-3, -2.5 .. 3]]
    chart = scatter [series "y = x²" points1,
                     series "y = 2x + 1" points2] defPlot

pie Source #

Arguments

:: [(Text, Double)]

List of (category, value) pairs

-> Plot

Plot configuration

-> Text

Rendered chart as Text

Create a pie chart showing proportions.

Values are normalized to sum to 100%. Negative values are treated as zero.

Example

Expand
let data = [(Chrome, 65), (Firefox, 20), (Safari, 10), (Other, 5)]
    chart = pie data defPlot { plotTitle = "Browser Market Share" }

stackedBars Source #

Arguments

:: [(Text, [(Text, Double)])]

Categories with stacked components

-> Plot

Plot configuration

-> Text

Rendered chart as Text

Create a stacked bar chart.

Each category can have multiple stacked components.

Example

Expand
let data = [(Q1, [("Product A", 100), ("Product B", 150)]),
            (Q2, [("Product A", 120), ("Product B", 180)])]
    chart = stackedBars data defPlot

heatmap Source #

Arguments

:: [[Double]]

2D matrix of values (rows × columns)

-> Plot

Plot configuration

-> Text

Rendered chart as Text

Create a heatmap visualization of a 2D matrix.

Values are mapped to a color gradient from blue (low) to red (high).

Example

Expand
let matrix = [[x * y | x <- [1..10]] | y <- [1..10]]
    chart = heatmap matrix defPlot { plotTitle = "Multiplication Table" }

lineGraph Source #

Arguments

:: [(Text, [(Double, Double)])]

List of named data series

-> Plot

Plot configuration

-> Text

Rendered chart as Text

Create a line graph connecting data points.

Similar to scatter but connects consecutive points with lines. Points are automatically sorted by x-coordinate before connecting.

Example

Expand
let sine = [(x, sin x) | x <- [0, 0.1 .. 2*pi]]
    cosine = [(x, cos x) | x <- [0, 0.1 .. 2*pi]]
    chart = lineGraph [series "sin" sine, series "cos" cosine] defPlot

boxPlot Source #

Arguments

:: [(Text, [Double])]

Named datasets

-> Plot

Plot configuration

-> Text

Rendered chart as Text

Create a box plot showing statistical distributions.

Displays quartiles, median, and min/max values for each dataset.

Example

Expand
let data1 = [1.2, 2.3, 2.1, 3.4, 2.8, 4.1, 3.9]
    data2 = [5.1, 4.8, 6.2, 5.9, 7.1, 6.5, 5.5]
    chart = boxPlot [("Group A", data1), ("Group B", data2)] defPlot

The box plot displays:

  • Box: First quartile (Q1) to third quartile (Q3)
  • Line inside box: Median (Q2)
  • Whiskers: Minimum and maximum values