1

好的,我被 Haskell Chart库难住了。我已经想出这种方法来制作VectorKronos Haskell 中的 a 值的对数折线图:

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)

这确实会呈现一个合理的对数折线图,并根据数据自动选择 x 轴和 y 轴的范围。一个示例(在 Kronos Haskell 中呈现):

对数图表示例

问题是我有一个专门的应用程序,我需要这两件事:

  1. 两个轴的范围需要相同。(由于我的 x 轴是 a 的基于 1 的索引Vector,因此可以将其简化为 y 轴的范围由 x 轴的范围确定。)
  2. 渲染图表的尺寸应该是方形的,而不是上面例子中的矩形。

我尝试查看该库的文档,但它让我完全被难住了。任何指针?

4

1 回答 1

1

这会做,但可以大大改进(尤其是通过删除 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
于 2015-01-25T17:13:26.803 回答