diff options
author | Alberto Ruiz <aruiz@um.es> | 2007-06-22 17:33:17 +0000 |
---|---|---|
committer | Alberto Ruiz <aruiz@um.es> | 2007-06-22 17:33:17 +0000 |
commit | 978e6d038239af50d70bae2c303f4e45b1879b7a (patch) | |
tree | 571b2060f388d0693820f808b40089acb100a5d9 /lib/Data/Packed/Plot.hs | |
parent | 989bdf7e88c13500bd1986dcde36f6cc4f467efb (diff) |
refactoring
Diffstat (limited to 'lib/Data/Packed/Plot.hs')
-rw-r--r-- | lib/Data/Packed/Plot.hs | 167 |
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 | |||
15 | module 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 | |||
27 | import Data.Packed.Vector | ||
28 | import Data.Packed.Matrix | ||
29 | import GSL.Vector(FunCodeS(Max,Min),toScalarR) | ||
30 | import Data.List(intersperse) | ||
31 | import System | ||
32 | import Data.IORef | ||
33 | import System.Exit | ||
34 | import Foreign hiding (rotate) | ||
35 | |||
36 | |||
37 | size = 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 | ||
44 | toFile :: FilePath -> Matrix Double -> IO () | ||
45 | toFile 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. | ||
51 | meshdom :: Vector Double -> Vector Double -> (Matrix Double , Matrix Double) | ||
52 | meshdom r1 r2 = (outer r1 (constant 1 (size r2)), outer (constant 1 (size r1)) r2) | ||
53 | |||
54 | |||
55 | gnuplotX command = do {system cmdstr; return()} where | ||
56 | cmdstr = "echo \""++command++"\" | gnuplot -persist" | ||
57 | |||
58 | datafollows = "\\\"-\\\"" | ||
59 | |||
60 | prep = (++"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 | |||
67 | In certain versions you can interactively rotate the graphic using the mouse. | ||
68 | |||
69 | -} | ||
70 | mesh :: Matrix Double -> IO () | ||
71 | mesh m = gnuplotX (command++dat) where | ||
72 | command = "splot "++datafollows++" matrix with lines\n" | ||
73 | dat = prep $ toLists $ m | ||
74 | |||
75 | mesh' 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 | -} | ||
89 | splot :: (Matrix Double->Matrix Double->Matrix Double) -> (Double,Double) -> (Double,Double) -> Int -> IO () | ||
90 | splot 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 -} | ||
95 | mplot :: [Vector Double] -> IO () | ||
96 | mplot 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 | |||
110 | mplot' 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 | ||
126 | mapf 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 | -} | ||
133 | plot :: [Vector Double->Vector Double] -> (Double,Double) -> Int -> IO () | ||
134 | plot 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 | -} | ||
142 | parametricPlot :: (Vector Double->(Vector Double,Vector Double)) -> (Double, Double) -> Int -> IO () | ||
143 | parametricPlot 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 | ||
149 | matrixToPGM :: Matrix Double -> String | ||
150 | matrixToPGM 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. | ||
164 | imshow :: Matrix Double -> IO () | ||
165 | imshow m = do | ||
166 | system $ "echo \""++ matrixToPGM m ++"\"| display -antialias -resize 300 - &" | ||
167 | return () | ||