haskell-igraph-0.6.0: src/IGraph/Exporter/GEXF.hs
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE FlexibleInstances #-}
module IGraph.Exporter.GEXF
( NodeAttr(..)
, defaultNodeAttributes
, EdgeAttr(..)
, defaultEdgeAttributes
, genXMLTree
, writeGEXF
) where
import Data.Colour (AlphaColour, alphaChannel, black, opaque,
over)
import Data.Colour.SRGB (channelBlue, channelGreen, channelRed,
toSRGB24)
import Data.Hashable
import Data.Serialize
import Data.Singletons (SingI)
import GHC.Generics
import IGraph
import Text.XML.HXT.Core
instance Serialize (AlphaColour Double) where
get = do
x <- get
return $ read x
put x = put $ show x
data NodeAttr = NodeAttr
{ _size :: Double
, _nodeColour :: AlphaColour Double
, _nodeLabel :: String
, _positionX :: Double
, _positionY :: Double
, _nodeZindex :: Int
} deriving (Show, Read, Eq, Generic)
instance Serialize NodeAttr
instance Hashable NodeAttr where
hashWithSalt salt at = hashWithSalt salt $ _nodeLabel at
defaultNodeAttributes :: NodeAttr
defaultNodeAttributes = NodeAttr
{ _size = 0.15
, _nodeColour = opaque black
, _nodeLabel = ""
, _positionX = 0
, _positionY = 0
, _nodeZindex = 1
}
data EdgeAttr = EdgeAttr
{ _edgeLabel :: String
, _edgeColour :: AlphaColour Double
, _edgeWeight :: Double
, _edgeArrowLength :: Double
, _edgeZindex :: Int
} deriving (Show, Read, Eq, Generic)
instance Serialize EdgeAttr
instance Hashable EdgeAttr where
hashWithSalt salt at = hashWithSalt salt $ _edgeLabel at
defaultEdgeAttributes :: EdgeAttr
defaultEdgeAttributes = EdgeAttr
{ _edgeLabel = ""
, _edgeColour = opaque black
, _edgeWeight = 1.0
, _edgeArrowLength = 10
, _edgeZindex = 2
}
genXMLTree :: (SingI d, ArrowXml a) => Graph d NodeAttr EdgeAttr -> a XmlTree XmlTree
genXMLTree gr = root [] [gexf]
where
gexf = mkelem "gexf" [ attr "version" $ txt "1.2"
, attr "xmlns" $ txt "http://www.gexf.net/1.2draft"
, attr "xmlns:viz" $ txt "http://www.gexf.net/1.2draft/viz"
, attr "xmlns:xsi" $ txt "http://www.w3.org/2001/XMLSchema-instance"
, attr "xsi:schemaLocation" $ txt "http://www.gexf.net/1.2draft http://www.gexf.net/1.2draft/gexf.xsd"
] [graph]
directed | isDirected gr = "directed"
| otherwise = "undirected"
graph = mkelem "graph" [ attr "mode" $ txt "static"
, attr "defaultedgetype" $ txt directed
] [ns, es]
ns = mkelem "nodes" [] $ map mkNode $ nodes gr
es = mkelem "edges" [] $ map mkEdge $ edges gr
mkNode i =
mkelem "node" [ attr "id" $ txt $ show i
, attr "label" $ txt $ _nodeLabel at ]
[ aelem "viz:position" [ attr "x" $ txt $ show $ _positionX at
, attr "y" $ txt $ show $ _positionY at ]
, aelem "viz:color" [ attr "r" $ txt r
, attr "g" $ txt g
, attr "b" $ txt b
, attr "a" $ txt a ]
, aelem "viz:size" [attr "value" $ txt $ show $ _size at]
]
where
at = nodeLab gr i
rgb = toSRGB24 $ _nodeColour at `over` black
r = show (fromIntegral $ channelRed rgb :: Int)
b = show (fromIntegral $ channelBlue rgb :: Int)
g = show (fromIntegral $ channelGreen rgb :: Int)
a = show $ alphaChannel $ _nodeColour at
mkEdge (fr,to) =
mkelem "edge" [ attr "source" $ txt $ show fr
, attr "target" $ txt $ show to
, attr "weight" $ txt $ show $ _edgeWeight at ]
[ aelem "viz:color" [ attr "r" $ txt r
, attr "g" $ txt g
, attr "b" $ txt b
, attr "a" $ txt a ]
]
where
at = edgeLab gr (fr,to)
rgb = toSRGB24 $ _edgeColour at `over` black
r = show (fromIntegral $ channelRed rgb :: Int)
b = show (fromIntegral $ channelBlue rgb :: Int)
g = show (fromIntegral $ channelGreen rgb :: Int)
a = show $ alphaChannel $ _edgeColour at
{-# INLINE genXMLTree #-}
writeGEXF :: SingI d => FilePath -> Graph d NodeAttr EdgeAttr -> IO ()
writeGEXF fl gr = runX (genXMLTree gr >>> writeDocument config fl) >> return ()
where
config = [withIndent yes]