{-# OPTIONS_GHC -fno-warn-missing-signatures #-}

-----------------------------------------------------------------------------
-- |
-- Module      :  Graphics.Plot
-- Copyright   :  (c) Alberto Ruiz 2005-8
-- License     :  GPL-style
--
-- Maintainer  :  Alberto Ruiz (aruiz at um dot es)
-- Stability   :  provisional
-- Portability :  uses gnuplot and ImageMagick
--
-- This module is deprecated. It can be replaced by improved drawing tools
-- available in the plot\\plot-gtk packages by Vivian McPhail or Gnuplot by Henning Thielemann.
-----------------------------------------------------------------------------
{-# OPTIONS_HADDOCK hide #-}

module Graphics.Plot(

    mplot,

    plot, parametricPlot, 

    splot, mesh, meshdom,

    matrixToPGM, imshow,

    gnuplotX, gnuplotpdf, gnuplotWin

) where

import Numeric.LinearAlgebra.HMatrix
import Data.List(intersperse)
import System.Process (system)

-- | From vectors x and y, it generates a pair of matrices to be used as x and y arguments for matrix functions.
meshdom :: Vector Double -> Vector Double -> (Matrix Double , Matrix Double)
meshdom :: Vector Double -> Vector Double -> (Matrix Double, Matrix Double)
meshdom r1 :: Vector Double
r1 r2 :: Vector Double
r2 = (Vector Double -> Vector Double -> Matrix Double
forall t. Product t => Vector t -> Vector t -> Matrix t
outer Vector Double
r1 (Double -> Int -> Vector Double
forall e d (c :: * -> *). Konst e d c => e -> d -> c e
konst 1 (Vector Double -> IndexOf Vector
forall (c :: * -> *) t. Container c t => c t -> IndexOf c
size Vector Double
r2)), Vector Double -> Vector Double -> Matrix Double
forall t. Product t => Vector t -> Vector t -> Matrix t
outer (Double -> Int -> Vector Double
forall e d (c :: * -> *). Konst e d c => e -> d -> c e
konst 1 (Vector Double -> IndexOf Vector
forall (c :: * -> *) t. Container c t => c t -> IndexOf c
size Vector Double
r1)) Vector Double
r2)


{- | Draws a 3D surface representation of a real matrix.

> > mesh $ build (10,10) (\\i j -> i + (j-5)^2)

In certain versions you can interactively rotate the graphic using the mouse.

-}
mesh :: Matrix Double -> IO ()
mesh :: Matrix Double -> IO ()
mesh m :: Matrix Double
m = String -> IO ()
gnuplotX (String
commandString -> String -> String
forall a. [a] -> [a] -> [a]
++String
dat) where
    command :: String
command = "splot "String -> String -> String
forall a. [a] -> [a] -> [a]
++String
datafollowsString -> String -> String
forall a. [a] -> [a] -> [a]
++" matrix with lines\n"
    dat :: String
dat = [[Double]] -> String
prep ([[Double]] -> String) -> [[Double]] -> String
forall a b. (a -> b) -> a -> b
$ Matrix Double -> [[Double]]
forall t. Element t => Matrix t -> [[t]]
toLists Matrix Double
m

{- | Draws the surface represented by the function f in the desired ranges and number of points, internally using 'mesh'.

> > let f x y = cos (x + y) 
> > splot f (0,pi) (0,2*pi) 50    

-}
splot :: (Matrix Double->Matrix Double->Matrix Double) -> (Double,Double) -> (Double,Double) -> Int -> IO () 
splot :: (Matrix Double -> Matrix Double -> Matrix Double)
-> (Double, Double) -> (Double, Double) -> Int -> IO ()
splot f :: Matrix Double -> Matrix Double -> Matrix Double
f rx :: (Double, Double)
rx ry :: (Double, Double)
ry n :: Int
n = Matrix Double -> IO ()
mesh Matrix Double
z where
    (x :: Matrix Double
x,y :: Matrix Double
y) = Vector Double -> Vector Double -> (Matrix Double, Matrix Double)
meshdom (Int -> (Double, Double) -> Vector Double
forall e.
(Fractional e, Container Vector e) =>
Int -> (e, e) -> Vector e
linspace Int
n (Double, Double)
rx) (Int -> (Double, Double) -> Vector Double
forall e.
(Fractional e, Container Vector e) =>
Int -> (e, e) -> Vector e
linspace Int
n (Double, Double)
ry)
    z :: Matrix Double
z = Matrix Double -> Matrix Double -> Matrix Double
f Matrix Double
x Matrix Double
y

{- | plots several vectors against the first one 

> > let t = linspace 100 (-3,3) in mplot [t, sin t, exp (-t^2)]

-}
mplot :: [Vector Double] -> IO ()
mplot :: [Vector Double] -> IO ()
mplot m :: [Vector Double]
m = String -> IO ()
gnuplotX (String
commandsString -> String -> String
forall a. [a] -> [a] -> [a]
++String
dats) where
    commands :: String
commands = if [Vector Double] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Vector Double]
m Int -> Int -> Bool
forall a. Eq a => a -> a -> Bool
== 1 then String
command1 else String
commandmore
    command1 :: String
command1 = "plot "String -> String -> String
forall a. [a] -> [a] -> [a]
++String
datafollowsString -> String -> String
forall a. [a] -> [a] -> [a]
++" with lines\n" String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
dat
    commandmore :: String
commandmore = "plot " String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
plots String -> String -> String
forall a. [a] -> [a] -> [a]
++ "\n"
    plots :: String
plots = [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat ([String] -> String) -> [String] -> String
forall a b. (a -> b) -> a -> b
$ String -> [String] -> [String]
forall a. a -> [a] -> [a]
intersperse ", " ((Int -> String) -> [Int] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map Int -> String
forall a. Show a => a -> String
cmd [2 .. [Vector Double] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Vector Double]
m])
    cmd :: a -> String
cmd k :: a
k = String
datafollowsString -> String -> String
forall a. [a] -> [a] -> [a]
++" using 1:"String -> String -> String
forall a. [a] -> [a] -> [a]
++a -> String
forall a. Show a => a -> String
show a
kString -> String -> String
forall a. [a] -> [a] -> [a]
++" with lines"
    dat :: String
dat = [[Double]] -> String
prep ([[Double]] -> String) -> [[Double]] -> String
forall a b. (a -> b) -> a -> b
$ Matrix Double -> [[Double]]
forall t. Element t => Matrix t -> [[t]]
toLists (Matrix Double -> [[Double]]) -> Matrix Double -> [[Double]]
forall a b. (a -> b) -> a -> b
$ [Vector Double] -> Matrix Double
forall t. Element t => [Vector t] -> Matrix t
fromColumns [Vector Double]
m
    dats :: String
dats = [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat (Int -> String -> [String]
forall a. Int -> a -> [a]
replicate ([Vector Double] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [Vector Double]
mInt -> Int -> Int
forall a. Num a => a -> a -> a
-1) String
dat)


{- | Draws a list of functions over a desired range and with a desired number of points 

> > plot [sin, cos, sin.(3*)] (0,2*pi) 1000

-}
plot :: [Vector Double->Vector Double] -> (Double,Double) -> Int -> IO ()
plot :: [Vector Double -> Vector Double]
-> (Double, Double) -> Int -> IO ()
plot fs :: [Vector Double -> Vector Double]
fs rx :: (Double, Double)
rx n :: Int
n = [Vector Double] -> IO ()
mplot (Vector Double
xVector Double -> [Vector Double] -> [Vector Double]
forall a. a -> [a] -> [a]
: [Vector Double -> Vector Double]
-> Vector Double -> [Vector Double]
forall a b. [a -> b] -> a -> [b]
mapf [Vector Double -> Vector Double]
fs Vector Double
x)
    where x :: Vector Double
x = Int -> (Double, Double) -> Vector Double
forall e.
(Fractional e, Container Vector e) =>
Int -> (e, e) -> Vector e
linspace Int
n (Double, Double)
rx
          mapf :: [a -> b] -> a -> [b]
mapf gs :: [a -> b]
gs y :: a
y = ((a -> b) -> b) -> [a -> b] -> [b]
forall a b. (a -> b) -> [a] -> [b]
map ((a -> b) -> a -> b
forall a b. (a -> b) -> a -> b
$ a
y) [a -> b]
gs

{- | Draws a parametric curve. For instance, to draw a spiral we can do something like:

> > parametricPlot (\t->(t * sin t, t * cos t)) (0,10*pi) 1000

-}
parametricPlot :: (Vector Double->(Vector Double,Vector Double)) -> (Double, Double) -> Int -> IO ()
parametricPlot :: (Vector Double -> (Vector Double, Vector Double))
-> (Double, Double) -> Int -> IO ()
parametricPlot f :: Vector Double -> (Vector Double, Vector Double)
f rt :: (Double, Double)
rt n :: Int
n = [Vector Double] -> IO ()
mplot [Vector Double
fx, Vector Double
fy]
    where t :: Vector Double
t = Int -> (Double, Double) -> Vector Double
forall e.
(Fractional e, Container Vector e) =>
Int -> (e, e) -> Vector e
linspace Int
n (Double, Double)
rt
          (fx :: Vector Double
fx,fy :: Vector Double
fy) = Vector Double -> (Vector Double, Vector Double)
f Vector Double
t


-- | writes a matrix to pgm image file
matrixToPGM :: Matrix Double -> String
matrixToPGM :: Matrix Double -> String
matrixToPGM m :: Matrix Double
m = String
header String -> String -> String
forall a. [a] -> [a] -> [a]
++ [String] -> String
unlines (([String] -> String) -> [[String]] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map [String] -> String
unwords [[String]]
ll) where
    c :: Int
c = Matrix Double -> Int
forall t. Matrix t -> Int
cols Matrix Double
m
    r :: Int
r = Matrix Double -> Int
forall t. Matrix t -> Int
rows Matrix Double
m
    header :: String
header = "P2 "String -> String -> String
forall a. [a] -> [a] -> [a]
++Int -> String
forall a. Show a => a -> String
show Int
cString -> String -> String
forall a. [a] -> [a] -> [a]
++" "String -> String -> String
forall a. [a] -> [a] -> [a]
++Int -> String
forall a. Show a => a -> String
show Int
rString -> String -> String
forall a. [a] -> [a] -> [a]
++" "String -> String -> String
forall a. [a] -> [a] -> [a]
++Int -> String
forall a. Show a => a -> String
show (Double -> Int
forall a b. (RealFrac a, Integral b) => a -> b
round Double
maxgray :: Int)String -> String -> String
forall a. [a] -> [a] -> [a]
++"\n"
    maxgray :: Double
maxgray = 255.0
    maxval :: Double
maxval = Matrix Double -> Double
forall (c :: * -> *) e. Container c e => c e -> e
maxElement Matrix Double
m
    minval :: Double
minval = Matrix Double -> Double
forall (c :: * -> *) e. Container c e => c e -> e
minElement Matrix Double
m
    scale' :: Double
scale' = if Double
maxval Double -> Double -> Bool
forall a. Eq a => a -> a -> Bool
== Double
minval
        then 0.0
        else Double
maxgray Double -> Double -> Double
forall a. Fractional a => a -> a -> a
/ (Double
maxval Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
minval)
    f :: Double -> String
f x :: Double
x = Int -> String
forall a. Show a => a -> String
show ( Double -> Int
forall a b. (RealFrac a, Integral b) => a -> b
round ( Double
scale' Double -> Double -> Double
forall a. Num a => a -> a -> a
*(Double
x Double -> Double -> Double
forall a. Num a => a -> a -> a
- Double
minval) ) :: Int )
    ll :: [[String]]
ll = ([Double] -> [String]) -> [[Double]] -> [[String]]
forall a b. (a -> b) -> [a] -> [b]
map ((Double -> String) -> [Double] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map Double -> String
f) (Matrix Double -> [[Double]]
forall t. Element t => Matrix t -> [[t]]
toLists Matrix Double
m)

-- | imshow shows a representation of a matrix as a gray level image using ImageMagick's display.
imshow :: Matrix Double -> IO ()
imshow :: Matrix Double -> IO ()
imshow m :: Matrix Double
m = do
    ExitCode
_ <- String -> IO ExitCode
system (String -> IO ExitCode) -> String -> IO ExitCode
forall a b. (a -> b) -> a -> b
$ "echo \""String -> String -> String
forall a. [a] -> [a] -> [a]
++ Matrix Double -> String
matrixToPGM Matrix Double
m String -> String -> String
forall a. [a] -> [a] -> [a]
++"\"| display -antialias -resize 300 - &"
    () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()

----------------------------------------------------

gnuplotX :: String -> IO ()
gnuplotX :: String -> IO ()
gnuplotX command :: String
command = do { ExitCode
_ <- String -> IO ExitCode
system String
cmdstr; () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return()} where
    cmdstr :: String
cmdstr = "echo \""String -> String -> String
forall a. [a] -> [a] -> [a]
++String
commandString -> String -> String
forall a. [a] -> [a] -> [a]
++"\" | gnuplot -persist"

datafollows :: String
datafollows = "\\\"-\\\""

prep :: [[Double]] -> String
prep = (String -> String -> String
forall a. [a] -> [a] -> [a]
++"e\n\n") (String -> String)
-> ([[Double]] -> String) -> [[Double]] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [String] -> String
unlines ([String] -> String)
-> ([[Double]] -> [String]) -> [[Double]] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Double] -> String) -> [[Double]] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map ([String] -> String
unwords ([String] -> String)
-> ([Double] -> [String]) -> [Double] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Double -> String) -> [Double] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map Double -> String
forall a. Show a => a -> String
show)


gnuplotpdf :: String -> String -> [([[Double]], String)] -> IO ()
gnuplotpdf :: String -> String -> [([[Double]], String)] -> IO ()
gnuplotpdf title :: String
title command :: String
command ds :: [([[Double]], String)]
ds = String -> IO ()
gnuplot (String
prelude String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
command String -> String -> String
forall a. [a] -> [a] -> [a]
++" "String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
draw) IO () -> IO () -> IO ()
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> IO ()
postproc where
    prelude :: String
prelude = "set terminal epslatex color; set output '"String -> String -> String
forall a. [a] -> [a] -> [a]
++String
titleString -> String -> String
forall a. [a] -> [a] -> [a]
++".tex';"
    (dats :: [[[Double]]]
dats,defs :: [String]
defs) = [([[Double]], String)] -> ([[[Double]]], [String])
forall a b. [(a, b)] -> ([a], [b])
unzip [([[Double]], String)]
ds
    draw :: String
draw = [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat (String -> [String] -> [String]
forall a. a -> [a] -> [a]
intersperse ", " ((String -> String) -> [String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map ("\"-\" "String -> String -> String
forall a. [a] -> [a] -> [a]
++) [String]
defs)) String -> String -> String
forall a. [a] -> [a] -> [a]
++ "\n" String -> String -> String
forall a. [a] -> [a] -> [a]
++
           ([[Double]] -> String) -> [[[Double]]] -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap [[Double]] -> String
pr [[[Double]]]
dats
    postproc :: IO ()
postproc = do
        ExitCode
_ <- String -> IO ExitCode
system (String -> IO ExitCode) -> String -> IO ExitCode
forall a b. (a -> b) -> a -> b
$ "epstopdf "String -> String -> String
forall a. [a] -> [a] -> [a]
++String
titleString -> String -> String
forall a. [a] -> [a] -> [a]
++".eps"
        IO ()
mklatex
        ExitCode
_ <- String -> IO ExitCode
system (String -> IO ExitCode) -> String -> IO ExitCode
forall a b. (a -> b) -> a -> b
$ "pdflatex "String -> String -> String
forall a. [a] -> [a] -> [a]
++String
titleString -> String -> String
forall a. [a] -> [a] -> [a]
++"aux.tex > /dev/null"
        ExitCode
_ <- String -> IO ExitCode
system (String -> IO ExitCode) -> String -> IO ExitCode
forall a b. (a -> b) -> a -> b
$ "pdfcrop "String -> String -> String
forall a. [a] -> [a] -> [a]
++String
titleString -> String -> String
forall a. [a] -> [a] -> [a]
++"aux.pdf > /dev/null"
        ExitCode
_ <- String -> IO ExitCode
system (String -> IO ExitCode) -> String -> IO ExitCode
forall a b. (a -> b) -> a -> b
$ "mv "String -> String -> String
forall a. [a] -> [a] -> [a]
++String
titleString -> String -> String
forall a. [a] -> [a] -> [a]
++"aux-crop.pdf "String -> String -> String
forall a. [a] -> [a] -> [a]
++String
titleString -> String -> String
forall a. [a] -> [a] -> [a]
++".pdf"
        ExitCode
_ <- String -> IO ExitCode
system (String -> IO ExitCode) -> String -> IO ExitCode
forall a b. (a -> b) -> a -> b
$ "rm "String -> String -> String
forall a. [a] -> [a] -> [a]
++String
titleString -> String -> String
forall a. [a] -> [a] -> [a]
++"aux.* "String -> String -> String
forall a. [a] -> [a] -> [a]
++String
titleString -> String -> String
forall a. [a] -> [a] -> [a]
++".eps "String -> String -> String
forall a. [a] -> [a] -> [a]
++String
titleString -> String -> String
forall a. [a] -> [a] -> [a]
++".tex"
        () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()

    mklatex :: IO ()
mklatex = String -> String -> IO ()
writeFile (String
titleString -> String -> String
forall a. [a] -> [a] -> [a]
++"aux.tex") (String -> IO ()) -> String -> IO ()
forall a b. (a -> b) -> a -> b
$
       "\\documentclass{article}\n"String -> String -> String
forall a. [a] -> [a] -> [a]
++
       "\\usepackage{graphics}\n"String -> String -> String
forall a. [a] -> [a] -> [a]
++
       "\\usepackage{nopageno}\n"String -> String -> String
forall a. [a] -> [a] -> [a]
++
       "\\usepackage{txfonts}\n"String -> String -> String
forall a. [a] -> [a] -> [a]
++
       "\\renewcommand{\\familydefault}{phv}\n"String -> String -> String
forall a. [a] -> [a] -> [a]
++
       "\\usepackage[usenames]{color}\n"String -> String -> String
forall a. [a] -> [a] -> [a]
++

       "\\begin{document}\n"String -> String -> String
forall a. [a] -> [a] -> [a]
++

       "\\begin{center}\n"String -> String -> String
forall a. [a] -> [a] -> [a]
++
       "  \\input{./"String -> String -> String
forall a. [a] -> [a] -> [a]
++String
titleString -> String -> String
forall a. [a] -> [a] -> [a]
++".tex}\n"String -> String -> String
forall a. [a] -> [a] -> [a]
++
       "\\end{center}\n"String -> String -> String
forall a. [a] -> [a] -> [a]
++

       "\\end{document}"

    pr :: [[Double]] -> String
pr = (String -> String -> String
forall a. [a] -> [a] -> [a]
++"e\n") (String -> String)
-> ([[Double]] -> String) -> [[Double]] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [String] -> String
unlines ([String] -> String)
-> ([[Double]] -> [String]) -> [[Double]] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Double] -> String) -> [[Double]] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map ([String] -> String
unwords ([String] -> String)
-> ([Double] -> [String]) -> [Double] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Double -> String) -> [Double] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map Double -> String
forall a. Show a => a -> String
show)

    gnuplot :: String -> IO ()
gnuplot cmd :: String
cmd = do
        String -> String -> IO ()
writeFile "gnuplotcommand" String
cmd
        ExitCode
_ <- String -> IO ExitCode
system "gnuplot gnuplotcommand"
        ExitCode
_ <- String -> IO ExitCode
system "rm gnuplotcommand"
        () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()

gnuplotWin :: String -> String -> [([[Double]], String)] -> IO ()
gnuplotWin :: String -> String -> [([[Double]], String)] -> IO ()
gnuplotWin title :: String
title command :: String
command ds :: [([[Double]], String)]
ds = String -> IO ()
gnuplot (String
prelude String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
command String -> String -> String
forall a. [a] -> [a] -> [a]
++" "String -> String -> String
forall a. [a] -> [a] -> [a]
++ String
draw) where
    (dats :: [[[Double]]]
dats,defs :: [String]
defs) = [([[Double]], String)] -> ([[[Double]]], [String])
forall a b. [(a, b)] -> ([a], [b])
unzip [([[Double]], String)]
ds
    draw :: String
draw = [String] -> String
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat (String -> [String] -> [String]
forall a. a -> [a] -> [a]
intersperse ", " ((String -> String) -> [String] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map ("\"-\" "String -> String -> String
forall a. [a] -> [a] -> [a]
++) [String]
defs)) String -> String -> String
forall a. [a] -> [a] -> [a]
++ "\n" String -> String -> String
forall a. [a] -> [a] -> [a]
++
           ([[Double]] -> String) -> [[[Double]]] -> String
forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
concatMap [[Double]] -> String
pr [[[Double]]]
dats

    pr :: [[Double]] -> String
pr = (String -> String -> String
forall a. [a] -> [a] -> [a]
++"e\n") (String -> String)
-> ([[Double]] -> String) -> [[Double]] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [String] -> String
unlines ([String] -> String)
-> ([[Double]] -> [String]) -> [[Double]] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ([Double] -> String) -> [[Double]] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map ([String] -> String
unwords ([String] -> String)
-> ([Double] -> [String]) -> [Double] -> String
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Double -> String) -> [Double] -> [String]
forall a b. (a -> b) -> [a] -> [b]
map Double -> String
forall a. Show a => a -> String
show)

    prelude :: String
prelude = "set title \""String -> String -> String
forall a. [a] -> [a] -> [a]
++String
titleString -> String -> String
forall a. [a] -> [a] -> [a]
++"\";"

    gnuplot :: String -> IO ()
gnuplot cmd :: String
cmd = do
        String -> String -> IO ()
writeFile "gnuplotcommand" String
cmd
        ExitCode
_ <- String -> IO ExitCode
system "gnuplot -persist gnuplotcommand"
        ExitCode
_ <- String -> IO ExitCode
system "rm gnuplotcommand"
        () -> IO ()
forall (m :: * -> *) a. Monad m => a -> m a
return ()