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