Haskell 图表库:制作 log-log 具有相同 x 轴和 y 轴的折线图
Haskell Chart library: make log-log line chart with identical x and y axes
好吧,我被 Haskell Chart 库难住了。我想出这种方法来制作 Kronos Haskell:
中 Vector
个值的 log-log 折线图
import Data.Vector (Vector, (!))
import qualified Data.Vector as V
import Graphics.Rendering.Chart.Easy hiding (Vector)
logLogChart name points = toRenderable $ execEC $ plot chart
where chart = line name [V.toList $ V.imap makePoint points]
makePoint x y = (LogValue (fromIntegral (x+1)), LogValue y)
这确实呈现了一个合理的 log-log 折线图,并根据数据自动选择了 x 轴和 y 轴的范围。一个示例(在 Kronos Haskell 中呈现):
问题是我有一个专门的应用程序,我需要这两件事:
- 两个轴的范围需要相同。 (由于我的 x-axis 是基于 1 的索引到
Vector
,这可以简化为 y-axis 的范围由 x-axis 的范围确定。)
- 渲染图表的尺寸应该是正方形,而不是上例中的矩形。
我尝试查看该库的文档,但完全被难住了。有什么指点吗?
这可以,但可以大大改进(尤其是通过删除 unsafePerformIO)。
{-# OPTIONS_GHC -Wall #-}
{-# OPTIONS_GHC -fno-warn-name-shadowing #-}
{-# OPTIONS_GHC -fno-warn-type-defaults #-}
{-# OPTIONS_GHC -fno-warn-unused-do-bind #-}
{-# OPTIONS_GHC -fno-warn-missing-methods #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
import Graphics.Rendering.Chart hiding ( translate )
import Graphics.Rendering.Chart.Backend.Diagrams
import Diagrams.Backend.Cairo.CmdLine
import Diagrams.Prelude hiding ( render, Renderable )
import Data.Default.Class
import Diagrams.Backend.CmdLine
import System.IO.Unsafe
pointVals :: [(Double, Double)]
pointVals = map (\(x,y) -> (log x, log y)) [(1,10), (10, 100), (100, 1000)]
dataPts :: PlotPoints Double Double
dataPts = plot_points_style .~ filledCircles 2 (opaque red)
$ plot_points_values .~ pointVals
$ plot_points_title .~ "Data points"
$ def
layout :: Layout Double Double
layout = layout_title .~ "Log vs Log"
$ layout_y_axis . laxis_generate .~ scaledAxis def (0,10)
$ layout_x_axis . laxis_generate .~ scaledAxis def (0,10)
$ layout_plots .~ [toPlot dataPts]
$ def
myChart :: Renderable ()
myChart = toRenderable layout
denv :: DEnv
denv = unsafePerformIO $ defaultEnv vectorAlignmentFns 500 500
displayHeader :: FilePath -> Diagram B R2 -> IO ()
displayHeader fn =
mainRender ( DiagramOpts (Just 900) (Just 700) fn
, DiagramLoopOpts False Nothing 0
)
myDiagram :: Diagram Cairo R2
myDiagram = fst $ runBackend denv (render myChart (500, 500))
main :: IO ()
main = displayHeader "LogChart.png" myDiagram
好吧,我被 Haskell Chart 库难住了。我想出这种方法来制作 Kronos Haskell:
中Vector
个值的 log-log 折线图
import Data.Vector (Vector, (!))
import qualified Data.Vector as V
import Graphics.Rendering.Chart.Easy hiding (Vector)
logLogChart name points = toRenderable $ execEC $ plot chart
where chart = line name [V.toList $ V.imap makePoint points]
makePoint x y = (LogValue (fromIntegral (x+1)), LogValue y)
这确实呈现了一个合理的 log-log 折线图,并根据数据自动选择了 x 轴和 y 轴的范围。一个示例(在 Kronos Haskell 中呈现):
问题是我有一个专门的应用程序,我需要这两件事:
- 两个轴的范围需要相同。 (由于我的 x-axis 是基于 1 的索引到
Vector
,这可以简化为 y-axis 的范围由 x-axis 的范围确定。) - 渲染图表的尺寸应该是正方形,而不是上例中的矩形。
我尝试查看该库的文档,但完全被难住了。有什么指点吗?
这可以,但可以大大改进(尤其是通过删除 unsafePerformIO)。
{-# OPTIONS_GHC -Wall #-}
{-# OPTIONS_GHC -fno-warn-name-shadowing #-}
{-# OPTIONS_GHC -fno-warn-type-defaults #-}
{-# OPTIONS_GHC -fno-warn-unused-do-bind #-}
{-# OPTIONS_GHC -fno-warn-missing-methods #-}
{-# OPTIONS_GHC -fno-warn-orphans #-}
import Graphics.Rendering.Chart hiding ( translate )
import Graphics.Rendering.Chart.Backend.Diagrams
import Diagrams.Backend.Cairo.CmdLine
import Diagrams.Prelude hiding ( render, Renderable )
import Data.Default.Class
import Diagrams.Backend.CmdLine
import System.IO.Unsafe
pointVals :: [(Double, Double)]
pointVals = map (\(x,y) -> (log x, log y)) [(1,10), (10, 100), (100, 1000)]
dataPts :: PlotPoints Double Double
dataPts = plot_points_style .~ filledCircles 2 (opaque red)
$ plot_points_values .~ pointVals
$ plot_points_title .~ "Data points"
$ def
layout :: Layout Double Double
layout = layout_title .~ "Log vs Log"
$ layout_y_axis . laxis_generate .~ scaledAxis def (0,10)
$ layout_x_axis . laxis_generate .~ scaledAxis def (0,10)
$ layout_plots .~ [toPlot dataPts]
$ def
myChart :: Renderable ()
myChart = toRenderable layout
denv :: DEnv
denv = unsafePerformIO $ defaultEnv vectorAlignmentFns 500 500
displayHeader :: FilePath -> Diagram B R2 -> IO ()
displayHeader fn =
mainRender ( DiagramOpts (Just 900) (Just 700) fn
, DiagramLoopOpts False Nothing 0
)
myDiagram :: Diagram Cairo R2
myDiagram = fst $ runBackend denv (render myChart (500, 500))
main :: IO ()
main = displayHeader "LogChart.png" myDiagram