8 people like it.

Generating GraphViz images using C# wrapper.

How you can programmatically use GraphViz from F#.

 1: 
 2: 
 3: 
 4: 
 5: 
 6: 
 7: 
 8: 
 9: 
10: 
11: 
12: 
13: 
14: 
15: 
16: 
17: 
18: 
19: 
20: 
21: 
22: 
23: 
24: 
25: 
26: 
27: 
28: 
29: 
30: 
31: 
32: 
33: 
34: 
35: 
36: 
37: 
38: 
39: 
40: 
41: 
42: 
43: 
44: 
45: 
46: 
47: 
48: 
49: 
50: 
51: 
52: 
53: 
54: 
55: 
56: 
57: 
58: 
59: 
60: 
61: 
62: 
63: 
64: 
65: 
66: 
67: 
68: 
69: 
70: 
71: 
72: 
73: 
74: 
75: 
76: 
77: 
78: 
79: 
80: 
81: 
82: 
83: 
84: 
85: 
86: 
87: 
88: 
89: 
90: 
91: 
92: 
93: 
94: 
// 1. Install: http://www.graphviz.org/Download..php
//
// 2. Add <appSettings> under <configuration> to app.config/web.config
//    Add Nuget / Paket: GraphViz.NET 
//
// 3. Add under <configuration><appSettings>:
// <add key="graphVizLocation" value="C:\Program Files (x86)\Graphviz2.38\bin" />
//
// Add references to System.Configuration.dll and System.Drawing.dll

module GraphVizSample

open GraphVizWrapper
open GraphVizWrapper.Commands
open GraphVizWrapper.Queries
open System
open System.Configuration
open System.Drawing
open System.IO

/// Creates some pngs
let genereateGraphFile (path:string) graphVizImageData =
    let procqry = GetStartProcessQuery()
    let infoqry = GetProcessStartInfoQuery()
    let wrapper = GraphGeneration(procqry, infoqry, 
                    RegisterLayoutPluginCommand(infoqry, procqry))
    
    // You probably don't need all 7:
    //[1] // different layout of graphs, e.g.: Enums.RenderingEngine.Neato
    [0..7] |> List.map(fun i ->
        wrapper.RenderingEngine <- enum<Enums.RenderingEngine> i
        let output = wrapper.GenerateGraph(graphVizImageData, Enums.GraphReturnType.Png)

        use image = System.Drawing.Image.FromStream(new MemoryStream(output))
        let filename = sprintf "%sgraph-%i-%i.png" path (output.GetHashCode()) i
        do image.Save(filename, System.Drawing.Imaging.ImageFormat.Png)
        let creationtime = File.GetLastWriteTime filename
        filename, creationtime
    )

/// Replace your version of data generation. 
/// This is just a silly example to give some starting point.
/// Note: If you use Guid based Ids, it's better to use some text-prefix!
let sampleGraphData items1 items2 =
    // shapes: box, diamond, circle, ...
    // colors: lightgray, lightblue, goldenrod2, thistle2, ...
    // Click on picture under http://www.graphviz.org/Gallery.php 
    // ...and picture again to get the sample txt-file.
    let idPrefix = "item"
    let nodes1 = 
        let items = items1 |> Array.map(fun (id,name,_) ->
            sprintf "%s%s [label=\"%s\"]; " idPrefix id name)
        "node [shape=box,style=filled,color=lightblue]; " + 
            (items |> String.Concat)

    let nodes2 = 
        let printStr = 
            sprintf "%s%s [label=\"&euro;%s\",color=%s]; " idPrefix
        "node [shape=circle,style=filled]; " + 
            (items2 |> Array.map(function
                | id, name, true,  _ -> printStr id name "goldenrod2"
                | id, name, false, _ -> printStr id name "lightgray"
                ) |> String.Concat)
            
    let graphPart =
        let printArrow aFrom aTo = 
            sprintf "%s%s -> %s%s;" idPrefix aFrom idPrefix aTo
        let arrows1 = 
            items1 |> Array.filter(fun (i,_,lnk) -> lnk<>"") 
            |> Array.map(fun (item,_,lnk) -> printArrow item lnk)
        let arrows2 = 
            items2 |> Array.filter(fun (i,_,_,lnk) -> lnk<>"") 
            |> Array.map(fun (item,_,_,lnk) -> printArrow item lnk)
        (String.Concat arrows1) + (String.Concat arrows2)
            
    "digraph myDiagram { " + nodes1 + nodes2 + graphPart + "overlap=false}"

// Create some data.
let doSample() =
    let genId() = Guid.NewGuid().ToString("N")
    let someId1 = genId()
    let someId2 = genId()
    let someId3 = genId()

    let ten = someId1, "10", true, "";
    let five = genId(), "5", false, someId2;
    let six = someId3, "6", false, "";

    let fork = genId(), "Fork", someId3;
    let spoon = someId2, "Spoon", someId1;
    let knife = genId(), "Knife", someId1;

    let graphdata = sampleGraphData [|fork; spoon; knife|] [|ten; five; six; |]
    genereateGraphFile AppDomain.CurrentDomain.BaseDirectory graphdata
module GraphVizSample
namespace GraphVizWrapper
namespace GraphVizWrapper.Commands
namespace GraphVizWrapper.Queries
namespace System
namespace System.Configuration
namespace System.Drawing
namespace System.IO
val genereateGraphFile : path:string -> graphVizImageData:string -> (string * DateTime) list

Full name: GraphVizSample.genereateGraphFile


 Creates some pngs
val path : string
Multiple items
val string : value:'T -> string

Full name: Microsoft.FSharp.Core.Operators.string

--------------------
type string = String

Full name: Microsoft.FSharp.Core.string
val graphVizImageData : string
val procqry : GetStartProcessQuery
Multiple items
type GetStartProcessQuery =
  new : unit -> GetStartProcessQuery
  member Invoke : processStartInfo:ProcessStartInfo -> Process

Full name: GraphVizWrapper.Queries.GetStartProcessQuery

--------------------
GetStartProcessQuery() : unit
val infoqry : GetProcessStartInfoQuery
Multiple items
type GetProcessStartInfoQuery =
  new : unit -> GetProcessStartInfoQuery
  member Invoke : startInfoWrapper:IProcessStartInfoWrapper -> ProcessStartInfo

Full name: GraphVizWrapper.Queries.GetProcessStartInfoQuery

--------------------
GetProcessStartInfoQuery() : unit
val wrapper : GraphGeneration
Multiple items
type GraphGeneration =
  new : startProcessQuery:IGetStartProcessQuery * getProcessStartInfoQuery:IGetProcessStartInfoQuery * registerLayoutPlugincommand:IRegisterLayoutPluginCommand -> GraphGeneration
  member GenerateGraph : dotFile:string * returnType:GraphReturnType -> byte[]
  member GraphvizPath : string with get, set
  member RenderingEngine : RenderingEngine with get, set

Full name: GraphVizWrapper.GraphGeneration

--------------------
GraphGeneration(startProcessQuery: IGetStartProcessQuery, getProcessStartInfoQuery: IGetProcessStartInfoQuery, registerLayoutPlugincommand: IRegisterLayoutPluginCommand) : unit
Multiple items
type RegisterLayoutPluginCommand =
  new : getProcessStartInfoQuery:IGetProcessStartInfoQuery * getStartProcessQuery:IGetStartProcessQuery -> RegisterLayoutPluginCommand
  member Invoke : unit -> unit + 1 overload

Full name: GraphVizWrapper.Commands.RegisterLayoutPluginCommand

--------------------
RegisterLayoutPluginCommand(getProcessStartInfoQuery: IGetProcessStartInfoQuery, getStartProcessQuery: IGetStartProcessQuery) : unit
Multiple items
module List

from Microsoft.FSharp.Collections

--------------------
type List<'T> =
  | ( [] )
  | ( :: ) of Head: 'T * Tail: 'T list
  interface IEnumerable
  interface IEnumerable<'T>
  member GetSlice : startIndex:int option * endIndex:int option -> 'T list
  member Head : 'T
  member IsEmpty : bool
  member Item : index:int -> 'T with get
  member Length : int
  member Tail : 'T list
  static member Cons : head:'T * tail:'T list -> 'T list
  static member Empty : 'T list

Full name: Microsoft.FSharp.Collections.List<_>
val map : mapping:('T -> 'U) -> list:'T list -> 'U list

Full name: Microsoft.FSharp.Collections.List.map
val i : int
property GraphGeneration.RenderingEngine: Enums.RenderingEngine
val enum : value:int32 -> 'U (requires enum)

Full name: Microsoft.FSharp.Core.Operators.enum
type Enums =
  nested type GraphReturnType
  nested type RenderingEngine

Full name: GraphVizWrapper.Enums
type RenderingEngine =
  | Dot = 0
  | Neato = 1
  | Twopi = 2
  | Circo = 3
  | Fdp = 4
  | Sfdp = 5
  | Patchwork = 6
  | Osage = 7

Full name: GraphVizWrapper.Enums.RenderingEngine
val output : byte []
GraphGeneration.GenerateGraph(dotFile: string, returnType: Enums.GraphReturnType) : byte []
type GraphReturnType =
  | Pdf = 0
  | Jpg = 1
  | Png = 2
  | Plain = 3
  | PlainExt = 4
  | Svg = 5

Full name: GraphVizWrapper.Enums.GraphReturnType
field Enums.GraphReturnType.Png = 2
val image : Image
type Image =
  inherit MarshalByRefObject
  member Clone : unit -> obj
  member Dispose : unit -> unit
  member Flags : int
  member FrameDimensionsList : Guid[]
  member GetBounds : pageUnit:GraphicsUnit -> RectangleF
  member GetEncoderParameterList : encoder:Guid -> EncoderParameters
  member GetFrameCount : dimension:FrameDimension -> int
  member GetPropertyItem : propid:int -> PropertyItem
  member GetThumbnailImage : thumbWidth:int * thumbHeight:int * callback:GetThumbnailImageAbort * callbackData:nativeint -> Image
  member Height : int
  ...
  nested type GetThumbnailImageAbort

Full name: System.Drawing.Image
Image.FromStream(stream: Stream) : Image
Image.FromStream(stream: Stream, useEmbeddedColorManagement: bool) : Image
Image.FromStream(stream: Stream, useEmbeddedColorManagement: bool, validateImageData: bool) : Image
Multiple items
type MemoryStream =
  inherit Stream
  new : unit -> MemoryStream + 6 overloads
  member CanRead : bool
  member CanSeek : bool
  member CanWrite : bool
  member Capacity : int with get, set
  member Flush : unit -> unit
  member GetBuffer : unit -> byte[]
  member Length : int64
  member Position : int64 with get, set
  member Read : buffer:byte[] * offset:int * count:int -> int
  ...

Full name: System.IO.MemoryStream

--------------------
MemoryStream() : unit
MemoryStream(capacity: int) : unit
MemoryStream(buffer: byte []) : unit
MemoryStream(buffer: byte [], writable: bool) : unit
MemoryStream(buffer: byte [], index: int, count: int) : unit
MemoryStream(buffer: byte [], index: int, count: int, writable: bool) : unit
MemoryStream(buffer: byte [], index: int, count: int, writable: bool, publiclyVisible: bool) : unit
val filename : string
val sprintf : format:Printf.StringFormat<'T> -> 'T

Full name: Microsoft.FSharp.Core.ExtraTopLevelOperators.sprintf
Object.GetHashCode() : int
Image.Save(filename: string) : unit
Image.Save(stream: Stream, format: Imaging.ImageFormat) : unit
Image.Save(filename: string, format: Imaging.ImageFormat) : unit
Image.Save(stream: Stream, encoder: Imaging.ImageCodecInfo, encoderParams: Imaging.EncoderParameters) : unit
Image.Save(filename: string, encoder: Imaging.ImageCodecInfo, encoderParams: Imaging.EncoderParameters) : unit
namespace System.Drawing.Imaging
Multiple items
type ImageFormat =
  new : guid:Guid -> ImageFormat
  member Equals : o:obj -> bool
  member GetHashCode : unit -> int
  member Guid : Guid
  member ToString : unit -> string
  static member Bmp : ImageFormat
  static member Emf : ImageFormat
  static member Exif : ImageFormat
  static member Gif : ImageFormat
  static member Icon : ImageFormat
  ...

Full name: System.Drawing.Imaging.ImageFormat

--------------------
Imaging.ImageFormat(guid: Guid) : unit
property Imaging.ImageFormat.Png: Imaging.ImageFormat
val creationtime : DateTime
type File =
  static member AppendAllLines : path:string * contents:IEnumerable<string> -> unit + 1 overload
  static member AppendAllText : path:string * contents:string -> unit + 1 overload
  static member AppendText : path:string -> StreamWriter
  static member Copy : sourceFileName:string * destFileName:string -> unit + 1 overload
  static member Create : path:string -> FileStream + 3 overloads
  static member CreateText : path:string -> StreamWriter
  static member Decrypt : path:string -> unit
  static member Delete : path:string -> unit
  static member Encrypt : path:string -> unit
  static member Exists : path:string -> bool
  ...

Full name: System.IO.File
File.GetLastWriteTime(path: string) : DateTime
val sampleGraphData : items1:(string * string * string) [] -> items2:(string * string * bool * string) [] -> string

Full name: GraphVizSample.sampleGraphData


 Replace your version of data generation.
 This is just a silly example to give some starting point.
 Note: If you use Guid based Ids, it's better to use some text-prefix!
val items1 : (string * string * string) []
val items2 : (string * string * bool * string) []
val idPrefix : string
val nodes1 : string
val items : string []
type Array =
  member Clone : unit -> obj
  member CopyTo : array:Array * index:int -> unit + 1 overload
  member GetEnumerator : unit -> IEnumerator
  member GetLength : dimension:int -> int
  member GetLongLength : dimension:int -> int64
  member GetLowerBound : dimension:int -> int
  member GetUpperBound : dimension:int -> int
  member GetValue : [<ParamArray>] indices:int[] -> obj + 7 overloads
  member Initialize : unit -> unit
  member IsFixedSize : bool
  ...

Full name: System.Array
val map : mapping:('T -> 'U) -> array:'T [] -> 'U []

Full name: Microsoft.FSharp.Collections.Array.map
val id : string
val name : string
Multiple items
type String =
  new : value:char -> string + 7 overloads
  member Chars : int -> char
  member Clone : unit -> obj
  member CompareTo : value:obj -> int + 1 overload
  member Contains : value:string -> bool
  member CopyTo : sourceIndex:int * destination:char[] * destinationIndex:int * count:int -> unit
  member EndsWith : value:string -> bool + 2 overloads
  member Equals : obj:obj -> bool + 2 overloads
  member GetEnumerator : unit -> CharEnumerator
  member GetHashCode : unit -> int
  ...

Full name: System.String

--------------------
String(value: nativeptr<char>) : unit
String(value: nativeptr<sbyte>) : unit
String(value: char []) : unit
String(c: char, count: int) : unit
String(value: nativeptr<char>, startIndex: int, length: int) : unit
String(value: nativeptr<sbyte>, startIndex: int, length: int) : unit
String(value: char [], startIndex: int, length: int) : unit
String(value: nativeptr<sbyte>, startIndex: int, length: int, enc: Text.Encoding) : unit
String.Concat([<ParamArray>] values: string []) : string
   (+0 other overloads)
String.Concat(values: Collections.Generic.IEnumerable<string>) : string
   (+0 other overloads)
String.Concat<'T>(values: Collections.Generic.IEnumerable<'T>) : string
   (+0 other overloads)
String.Concat([<ParamArray>] args: obj []) : string
   (+0 other overloads)
String.Concat(arg0: obj) : string
   (+0 other overloads)
String.Concat(str0: string, str1: string) : string
   (+0 other overloads)
String.Concat(arg0: obj, arg1: obj) : string
   (+0 other overloads)
String.Concat(str0: string, str1: string, str2: string) : string
   (+0 other overloads)
String.Concat(arg0: obj, arg1: obj, arg2: obj) : string
   (+0 other overloads)
String.Concat(str0: string, str1: string, str2: string, str3: string) : string
   (+0 other overloads)
val nodes2 : string
val printStr : (string -> string -> string -> string)
val graphPart : string
val printArrow : (string -> string -> string)
val aFrom : string
val aTo : string
val arrows1 : string []
val filter : predicate:('T -> bool) -> array:'T [] -> 'T []

Full name: Microsoft.FSharp.Collections.Array.filter
val i : string
val lnk : string
val item : string
val arrows2 : string []
val doSample : unit -> (string * DateTime) list

Full name: GraphVizSample.doSample
val genId : (unit -> string)
Multiple items
type Guid =
  struct
    new : b:byte[] -> Guid + 4 overloads
    member CompareTo : value:obj -> int + 1 overload
    member Equals : o:obj -> bool + 1 overload
    member GetHashCode : unit -> int
    member ToByteArray : unit -> byte[]
    member ToString : unit -> string + 2 overloads
    static val Empty : Guid
    static member NewGuid : unit -> Guid
    static member Parse : input:string -> Guid
    static member ParseExact : input:string * format:string -> Guid
    ...
  end

Full name: System.Guid

--------------------
Guid()
Guid(b: byte []) : unit
Guid(g: string) : unit
Guid(a: int, b: int16, c: int16, d: byte []) : unit
Guid(a: uint32, b: uint16, c: uint16, d: byte, e: byte, f: byte, g: byte, h: byte, i: byte, j: byte, k: byte) : unit
Guid(a: int, b: int16, c: int16, d: byte, e: byte, f: byte, g: byte, h: byte, i: byte, j: byte, k: byte) : unit
Guid.NewGuid() : Guid
val someId1 : string
val someId2 : string
val someId3 : string
val ten : string * string * bool * string
val five : string * string * bool * string
val six : string * string * bool * string
val fork : string * string * string
val spoon : string * string * string
val knife : string * string * string
val graphdata : string
type AppDomain =
  inherit MarshalByRefObject
  member ActivationContext : ActivationContext
  member AppendPrivatePath : path:string -> unit
  member ApplicationIdentity : ApplicationIdentity
  member ApplicationTrust : ApplicationTrust
  member ApplyPolicy : assemblyName:string -> string
  member BaseDirectory : string
  member ClearPrivatePath : unit -> unit
  member ClearShadowCopyPath : unit -> unit
  member CreateComInstanceFrom : assemblyName:string * typeName:string -> ObjectHandle + 1 overload
  member CreateInstance : assemblyName:string * typeName:string -> ObjectHandle + 3 overloads
  ...

Full name: System.AppDomain
property AppDomain.CurrentDomain: AppDomain
property AppDomain.BaseDirectory: string
Raw view Test code New version

More information

Link:http://fssnip.net/7Rf
Posted:8 years ago
Author:Tuomas Hietanen
Tags: charting , graph , graphs