summaryrefslogtreecommitdiff
path: root/lib/Data/Packed/Plot.hs
diff options
context:
space:
mode:
Diffstat (limited to 'lib/Data/Packed/Plot.hs')
-rw-r--r--lib/Data/Packed/Plot.hs167
1 files changed, 167 insertions, 0 deletions
diff --git a/lib/Data/Packed/Plot.hs b/lib/Data/Packed/Plot.hs
new file mode 100644
index 0000000..9eddc9f
--- /dev/null
+++ b/lib/Data/Packed/Plot.hs
@@ -0,0 +1,167 @@
1-----------------------------------------------------------------------------
2-- |
3-- Module : Data.Packed.Plot
4-- Copyright : (c) Alberto Ruiz 2005
5-- License : GPL-style
6--
7-- Maintainer : Alberto Ruiz (aruiz at um dot es)
8-- Stability : provisional
9-- Portability : uses gnuplot and ImageMagick
10--
11-- Very basic (and provisional) drawing tools.
12--
13-----------------------------------------------------------------------------
14
15module Data.Packed.Plot(
16
17 gnuplotX, mplot,
18
19 plot, parametricPlot,
20
21 splot, mesh, mesh', meshdom,
22
23 matrixToPGM, imshow,
24
25) where
26
27import Data.Packed.Vector
28import Data.Packed.Matrix
29import GSL.Vector(FunCodeS(Max,Min),toScalarR)
30import Data.List(intersperse)
31import System
32import Data.IORef
33import System.Exit
34import Foreign hiding (rotate)
35
36
37size = dim
38
39-- | Loads a real matrix from a formatted ASCII text file
40--fromFile :: FilePath -> IO Matrix
41--fromFile filename = readFile filename >>= return . readMatrix read
42
43-- | Saves a real matrix to a formatted ascii text file
44toFile :: FilePath -> Matrix Double -> IO ()
45toFile filename matrix = writeFile filename (unlines . map unwords. map (map show) . toLists $ matrix)
46
47------------------------------------------------------------------------
48
49
50-- | From vectors x and y, it generates a pair of matrices to be used as x and y arguments for matrix functions.
51meshdom :: Vector Double -> Vector Double -> (Matrix Double , Matrix Double)
52meshdom r1 r2 = (outer r1 (constant 1 (size r2)), outer (constant 1 (size r1)) r2)
53
54
55gnuplotX command = do {system cmdstr; return()} where
56 cmdstr = "echo \""++command++"\" | gnuplot -persist"
57
58datafollows = "\\\"-\\\""
59
60prep = (++"e\n\n") . unlines . map (unwords . (map show))
61
62
63{- | Draws a 3D surface representation of a real matrix.
64
65> > mesh (hilb 20)
66
67In certain versions you can interactively rotate the graphic using the mouse.
68
69-}
70mesh :: Matrix Double -> IO ()
71mesh m = gnuplotX (command++dat) where
72 command = "splot "++datafollows++" matrix with lines\n"
73 dat = prep $ toLists $ m
74
75mesh' m = do
76 writeFile "splot-gnu-command" "splot \"splot-tmp.txt\" matrix with lines; pause -1";
77 toFile "splot-tmp.txt" m
78 putStr "Press [Return] to close the graphic and continue... "
79 system "gnuplot -persist splot-gnu-command"
80 system "rm splot-tmp.txt splot-gnu-command"
81 return ()
82
83{- | Draws the surface represented by the function f in the desired ranges and number of points, internally using 'mesh'.
84
85> > let f x y = cos (x + y)
86> > splot f (0,pi) (0,2*pi) 50
87
88-}
89splot :: (Matrix Double->Matrix Double->Matrix Double) -> (Double,Double) -> (Double,Double) -> Int -> IO ()
90splot f rx ry n = mesh' z where
91 (x,y) = meshdom (linspace n rx) (linspace n ry)
92 z = f x y
93
94{- | plots several vectors against the first one -}
95mplot :: [Vector Double] -> IO ()
96mplot m = gnuplotX (commands++dats) where
97 commands = if length m == 1 then command1 else commandmore
98 command1 = "plot "++datafollows++" with lines\n" ++ dat
99 commandmore = "plot " ++ plots ++ "\n"
100 plots = concat $ intersperse ", " (map cmd [2 .. length m])
101 cmd k = datafollows++" using 1:"++show k++" with lines"
102 dat = prep $ toLists $ fromColumns m
103 dats = concat (replicate (length m-1) dat)
104
105
106
107
108
109
110mplot' m = do
111 writeFile "plot-gnu-command" (commands++endcmd)
112 toFile "plot-tmp.txt" (fromColumns m)
113 putStr "Press [Return] to close the graphic and continue... "
114 system "gnuplot plot-gnu-command"
115 system "rm plot-tmp.txt plot-gnu-command"
116 return ()
117 where
118 commands = if length m == 1 then command1 else commandmore
119 command1 = "plot \"plot-tmp.txt\" with lines\n"
120 commandmore = "plot " ++ plots ++ "\n"
121 plots = concat $ intersperse ", " (map cmd [2 .. length m])
122 cmd k = "\"plot-tmp.txt\" using 1:"++show k++" with lines"
123 endcmd = "pause -1"
124
125-- apply several functions to one object
126mapf fs x = map ($ x) fs
127
128{- | Draws a list of functions over a desired range and with a desired number of points
129
130> > plot [sin, cos, sin.(3*)] (0,2*pi) 1000
131
132-}
133plot :: [Vector Double->Vector Double] -> (Double,Double) -> Int -> IO ()
134plot fs rx n = mplot (x: mapf fs x)
135 where x = linspace n rx
136
137{- | Draws a parametric curve. For instance, to draw a spiral we can do something like:
138
139> > parametricPlot (\t->(t * sin t, t * cos t)) (0,10*pi) 1000
140
141-}
142parametricPlot :: (Vector Double->(Vector Double,Vector Double)) -> (Double, Double) -> Int -> IO ()
143parametricPlot f rt n = mplot [fx, fy]
144 where t = linspace n rt
145 (fx,fy) = f t
146
147
148-- | writes a matrix to pgm image file
149matrixToPGM :: Matrix Double -> String
150matrixToPGM m = header ++ unlines (map unwords ll) where
151 c = cols m
152 r = rows m
153 header = "P2 "++show c++" "++show r++" "++show (round maxgray :: Int)++"\n"
154 maxgray = 255.0
155 maxval = toScalarR Max $ flatten $ m
156 minval = toScalarR Min $ flatten $ m
157 scale = if (maxval == minval)
158 then 0.0
159 else maxgray / (maxval - minval)
160 f x = show ( round ( scale *(x - minval) ) :: Int )
161 ll = map (map f) (toLists m)
162
163-- | imshow shows a representation of a matrix as a gray level image using ImageMagick's display.
164imshow :: Matrix Double -> IO ()
165imshow m = do
166 system $ "echo \""++ matrixToPGM m ++"\"| display -antialias -resize 300 - &"
167 return ()