More Complex Example Graph

Here, we can look at a more colorful example to understand the functionality of Cytoscape.NET. The example is translated from here to cover different styling capabilities.

Adding nodes and edges with data

After including the necessary dependancies, we can add the elements with data to our graph. Additionaly, the withClass function adds a class identifier (CyParam.cyClass "questionable") to the respective edge. This can be used for individual styling, that you will see later...

open Cytoscape.NET
open Elements

let complexGraph = 
    CyGraph.initEmpty ()
    |> CyGraph.withElements [
            node "j" [ CyParam.label "Jerry"  ; CyParam.weight 65; CyParam.color "#6FB1FC"; CyParam.shape "triangle"  ]
            node "e" [ CyParam.label "Elaine" ; CyParam.weight 45; CyParam.color "#EDA1ED"; CyParam.shape "ellipse"  ]
            node "k" [ CyParam.label "Kramer" ; CyParam.weight 75; CyParam.color "#86B342"; CyParam.shape "octagon"  ]
            node "g" [ CyParam.label "George" ; CyParam.weight 70; CyParam.color "#F5A45D"; CyParam.shape "rectangle"  ]

            edge  "1" "j" "e" [CyParam.color "#6FB1FC"; CyParam.weight 90]
            edge  "2" "j" "e" [CyParam.color "#6FB1FC"; CyParam.weight 120]
            edge  "3" "j" "k" [CyParam.color "#6FB1FC"; CyParam.weight 70]
            edge  "4" "j" "g" [CyParam.color "#6FB1FC"; CyParam.weight 80]
     
            edge  "5" "e" "j" [CyParam.color "#EDA1ED"; CyParam.weight 95]
            edge  "6" "e" "k" [CyParam.color "#EDA1ED"; CyParam.weight 60] 
                |> withClass (CyParam.cyClass "questionable") // classes: 'questionable'
             
            edge  "7" "k" "j" [CyParam.color "#86B342"; CyParam.weight 100]
            edge  "8" "k" "e" [CyParam.color "#86B342"; CyParam.weight 100]
            edge  "9" "k" "g" [CyParam.color "#86B342"; CyParam.weight 100]
     
            edge "10" "g" "j" [CyParam.color "#F5A45D"; CyParam.weight 90]
            edge "11" "g" "g" [CyParam.color "#F5A45D"; CyParam.weight 90]
            edge "12" "g" "g" [CyParam.color "#F5A45D"; CyParam.weight 90]
            edge "13" "g" "g" [CyParam.color "#F5A45D"; CyParam.weight 90]

        ]

Styling nodes

Using the withStyle function we use a selector string (here: node) to specify the target that we want to style. Second, we provide a list of style paramerts CyStyleParam to set the design. attention Style mapper =. specifies a direct mapping or a linear mapping <=. to an element’s data field.

let cgStylingNodes = 
    complexGraph
    |> CyGraph.withStyle "node"     
            [
                CyParam.shape =. CyParam.shape
                // Style mapper can also be used untyped in string form: CyParam.shape "data(shape)"
                CyParam.width <=. (CyParam.weight, 40, 80, 20, 60)
                // A linear style mapper like this: CyParam.width "mapData(weight, 40, 80, 20, 60)"
                CyParam.content =. CyParam.label
                CyParam.Text.Align.center
                CyParam.Text.Outline.width 2
                CyParam.Text.Outline.color =. CyParam.color  //=. CyParam.color
                CyParam.Background.color   =. CyParam.color  //=. CyParam.color
                CyParam.color "#fff"
            ]  

Interactivity

Here, the active selector :selected is used to select and style the activly selected node.

let cgInteractivity =
    cgStylingNodes
    |> CyGraph.withStyle ":selected"     
            [
                CyParam.Border.width 3
                CyParam.Border.color "#333"
            ]

Styling edges

Styling the edges is analogous to adapting the node style.

let cgStylingEdges = 
    cgInteractivity
    |> CyGraph.withStyle "edge"     
            [
                CyParam.Curve.style "bezier"
                CyParam.opacity 0.666
                CyParam.width <=. (CyParam.weight, 70, 100, 2, 6)
                CyParam.Target.Arrow.shape "triangle"
                CyParam.Source.Arrow.shape "circle"
                CyParam.Line.color =. CyParam.color
                CyParam.Target.Arrow.color =. CyParam.color
                CyParam.Source.Arrow.color =. CyParam.color
            ]

Edge styling with class identifier

The class identifier questionable can be used to select and style the respective edge(s).

let cgStylingEdgesWci = 
    cgStylingEdges
    |> CyGraph.withStyle "edge.questionable"     
            [
                CyParam.Line.style "dotted"
                CyParam.Target.Arrow.shape "diamond"
            ]
    |> CyGraph.withStyle ".faded"     
            [
                CyParam.opacity 0.666
                CyParam.Text.opacity 0
            ]

Using a graph layout

To draw the graph nicly, withLayout applies CoSE (Compound graph Spring Embedder) layout, an algorithm based on the traditional force-directed layout scheme with extensions to handle multi-level nesting, edges between nodes of arbitrary nesting level, varying node sizes, and other possible application-specific constraints.

Layouts can be specified with LayoutOptions applied. Here, we use ComponentSpacing, which adds extra spacing between components in non-compound graphs.

let cgLayout = 
    cgStylingEdgesWci
    |> CyGraph.withLayout (
        Layout.initCose (Layout.LayoutOptions.Cose(ComponentSpacing=40)) 
        )  
    |> CyGraph.withSize(800, 800) 
cgLayout
|> CyGraph.show

And here is what happened after applying the styles from above:

namespace Cytoscape
namespace Cytoscape.NET
module Defaults from Cytoscape.NET
<summary> Contains mutable global default values. Changing these values will apply the default values to all consecutive Graph generations. </summary>
val mutable DefaultDisplayOptions: DisplayOptions
Multiple items
type DisplayOptions = inherit DynamicObj new: unit -> DisplayOptions static member addAdditionalHeadTags: additionalHeadTags: XmlNode list -> (DisplayOptions -> DisplayOptions) static member addDescription: description: XmlNode list -> (DisplayOptions -> DisplayOptions) static member getAdditionalHeadTags: displayOpts: DisplayOptions -> XmlNode list static member getCytoscapeReference: displayOpts: DisplayOptions -> CytoscapeJSReference static member getDescription: displayOpts: DisplayOptions -> XmlNode list static member init: ?AdditionalHeadTags: XmlNode list * ?Description: XmlNode list * ?CytoscapeJSReference: CytoscapeJSReference -> DisplayOptions static member initCDNOnly: unit -> DisplayOptions static member initDefault: unit -> DisplayOptions ...

--------------------
new: unit -> DisplayOptions
static member DisplayOptions.init: ?AdditionalHeadTags: Giraffe.ViewEngine.HtmlElements.XmlNode list * ?Description: Giraffe.ViewEngine.HtmlElements.XmlNode list * ?CytoscapeJSReference: CytoscapeJSReference -> DisplayOptions
type CytoscapeJSReference = | CDN of string | Full | Require of string | NoReference
<summary> Sets how cytoscape is referenced in the head of html docs. </summary>
union case CytoscapeJSReference.NoReference: CytoscapeJSReference
module Elements from Cytoscape.NET
val complexGraph: CyGraph.CyGraph
module CyGraph from Cytoscape.NET
val initEmpty: unit -> CyGraph.CyGraph
val withElements: elems: seq<CytoscapeModel.Element> -> cy: CyGraph.CyGraph -> CyGraph.CyGraph
val node: id: string -> dataAttributes: CyParam.CyStyleParam list -> Node
module CyParam from Cytoscape.NET
val label: v: 'a -> CyParam.CyStyleParam
val weight: v: 'a -> CyParam.CyStyleParam
val color: v: 'a -> CyParam.CyStyleParam
val shape: v: 'a -> CyParam.CyStyleParam
val edge: id: string -> sourceId: string -> targetId: string -> dataAttributes: CyParam.CyStyleParam list -> Edge
val withClass: cyClass: CyParam.CyStyleClass -> elem: 'a -> 'a (requires 'a :> CytoscapeModel.Element)
val cyClass: name: string -> CyParam.CyStyleClass
val cgStylingNodes: CyGraph.CyGraph
val withStyle: selector: string -> cyStyles: seq<CyParam.CyStyleParam> -> cy: CyGraph.CyGraph -> CyGraph.CyGraph
val width: v: 'a -> CyParam.CyStyleParam
val content: v: 'a -> CyParam.CyStyleParam
module Text from Cytoscape.NET.CyParam
module Align from Cytoscape.NET.CyParam.Text
val center: CyParam.CyStyleParam
module Outline from Cytoscape.NET.CyParam.Text
module Background from Cytoscape.NET.CyParam
val cgInteractivity: CyGraph.CyGraph
module Border from Cytoscape.NET.CyParam
val cgStylingEdges: CyGraph.CyGraph
module Curve from Cytoscape.NET.CyParam
val style: v: 'a -> CyParam.CyStyleParam
val opacity: v: 'a -> CyParam.CyStyleParam
module Target from Cytoscape.NET.CyParam
module Arrow from Cytoscape.NET.CyParam.Target
module Source from Cytoscape.NET.CyParam
module Arrow from Cytoscape.NET.CyParam.Source
module Line from Cytoscape.NET.CyParam
val cgStylingEdgesWci: CyGraph.CyGraph
val cgLayout: CyGraph.CyGraph
val withLayout: ly: Layout -> cy: CyGraph.CyGraph -> CyGraph.CyGraph
Multiple items
module Layout from Cytoscape.NET

--------------------
type Layout = inherit DynamicObj new: name: string -> Layout member name: string
<summary> Layout type inherits from dynamic object </summary>

--------------------
new: name: string -> Layout
val initCose: applyOption: (Layout -> Layout) -> Layout
<summary> initializes a layout of type "cose" applying the givin layout option function. The cose (Compound Spring Embedder) layout uses a physics simulation to lay out graphs. </summary>
Multiple items
type LayoutOptions = new: unit -> LayoutOptions static member Cose: ?Refresh: int * ?BoundingBox: 'a * ?NodeDimensionsIncludeLabels: bool * ?Randomize: bool * ?ComponentSpacing: int * ?NodeRepulsion: 'b * ?NodeOverlap: int * ?IdealEdgeLength: 'c * ?EdgeElasticity: 'd * ?NestingFactor: float * ?Gravity: int * ?NumIter: int * ?InitialTemp: int * ?CoolingFactor: float * ?MinTemp: float -> ('L -> 'L) (requires 'L :> Layout) static member Generic: ?Positions: 'a0 * ?Zoom: 'a1 * ?Pan: 'a2 * ?Fit: bool * ?Padding: int * ?Animate: bool * ?AnimationDuration: int * ?AnimationEasing: 'a3 * ?AnimateFilter: 'a4 * ?AnimationThreshold: int * ?Ready: 'a5 * ?Stop: 'a6 * ?Transform: 'a7 -> ('L -> 'L) (requires 'L :> Layout)
<summary> Functions provide the options of the Layout objects </summary>

--------------------
new: unit -> Layout.LayoutOptions
static member Layout.LayoutOptions.Cose: ?Refresh: int * ?BoundingBox: 'a * ?NodeDimensionsIncludeLabels: bool * ?Randomize: bool * ?ComponentSpacing: int * ?NodeRepulsion: 'b * ?NodeOverlap: int * ?IdealEdgeLength: 'c * ?EdgeElasticity: 'd * ?NestingFactor: float * ?Gravity: int * ?NumIter: int * ?InitialTemp: int * ?CoolingFactor: float * ?MinTemp: float -> ('L -> 'L) (requires 'L :> Layout)
val withSize: width: int * height: int -> cy: CyGraph.CyGraph -> CyGraph.CyGraph
val show: cy: CyGraph.CyGraph -> unit
type HTML = static member CreateGraphHTML: graphData: string * zooming: string * divId: string * cytoscapeReference: CytoscapeJSReference * ?Width: int * ?Height: int -> XmlNode list static member CreateGraphScript: graphData: string * zooming: string * cytoscapeReference: CytoscapeJSReference -> XmlNode static member Doc: graphHTML: XmlNode list * cytoscapeReference: CytoscapeJSReference * ?AdditionalHeadTags: XmlNode list -> XmlNode static member show: cy: Cytoscape * ?DisplayOpts: DisplayOptions -> unit static member toEmbeddedHTML: ?DisplayOpts: DisplayOptions -> (Cytoscape -> string) static member toGraphHTML: ?DisplayOpts: DisplayOptions -> (Cytoscape -> string) static member toGraphHTMLNodes: ?DisplayOpts: DisplayOptions -> (Cytoscape -> XmlNode list)
<summary> HTML template for Cytoscape </summary>
static member HTML.toGraphHTML: ?DisplayOpts: DisplayOptions -> (CytoscapeModel.Cytoscape -> string)