Skip to content

Instantly share code, notes, and snippets.

@jonmmease
Forked from kMutagene/Kaleido.FSharp.fsx
Last active July 5, 2020 23:01
Show Gist options
  • Save jonmmease/2616440ebea523b83f25100f5c6a9a7f to your computer and use it in GitHub Desktop.
Save jonmmease/2616440ebea523b83f25100f5c6a9a7f to your computer and use it in GitHub Desktop.
Kaleido.FSharp POC
//Use F#5 preview to use "#r:nuget..."
#r "nuget:FSharp.Plotly,Version=2.0.0-alpha"
#r "nuget:Fake.Core.Process"
open System
open System.Diagnostics
open Fake.IO
open FSharp.Plotly
open Newtonsoft.Json
open System.Collections.Generic
let randomPoints =
let rnd = new System.Random()
[for i = 0 to 999 do yield rnd.NextDouble(),rnd.NextDouble()]
let testFig =
Chart.Point(
randomPoints
)
|> Chart.withX_AxisStyle("TestTitle_X",Showgrid=false)
|> Chart.withY_AxisStyle("TestTitle_Y",Showgrid=false)
testFig |> Chart.Show
module Kaleido =
let stringFormats = Set.ofList ["svg"; "eps"; "json"]
//input and output should most likely be dynamic objects themselves instead of record types
type KaleidoInput () =
inherit DynamicObj()
///This function makes it possible to render Charts
///generated with FSharp.Plotly
static member ofChart
(
format:string,
gChart:GenericChart.GenericChart
) =
let data = GenericChart.getTraces gChart
let layout = GenericChart.getLayout gChart
let dict = new Dictionary<string, Object>()
dict.Add("data", data)
dict.Add("layout", layout)
let kI = KaleidoInput()
dict |> DynObj.setValue kI "data"
format |> DynObj.setValue kI "format"
kI
//TODO: Extend with all fields possibly returned by Kaleido and handle null properly
type KaleidoResponse = {
Code : int
Message : string
Format : string
Result : string
}
with
static member fromJsonString (jsonString) =
jsonString |> JsonConvert.DeserializeObject<KaleidoResponse>
///Starts a process using the kaleido executable and a scope name
//TODO: abstract scopes as types
let start executablePath scopeName =
let startInfo =
new ProcessStartInfo(
UseShellExecute = false,
RedirectStandardOutput = true,
RedirectStandardInput = true,
RedirectStandardError = false,
FileName = executablePath,
Arguments = scopeName
)
let kaleidoProcess = new Process(StartInfo = startInfo)
if kaleidoProcess.Start() then
let startupMsg = kaleidoProcess.StandardOutput.ReadLine()
printfn "startup response: %s" startupMsg
kaleidoProcess
else
failwith "Error starting Kaleido process"
let stop (kaleidoProcess:System.Diagnostics.Process) =
kaleidoProcess.Kill()
kaleidoProcess.Dispose()
///Render the given KaleidoInput using the given process.
///use keepRunning = true if you want to use the process again afterwards.
let render (kaleidoProcess:System.Diagnostics.Process) (keepRunning:bool) (input:KaleidoInput) =
input
|> JsonConvert.SerializeObject
|> kaleidoProcess.StandardInput.WriteLine
let result =
kaleidoProcess.StandardOutput.ReadLine()
|> KaleidoResponse.fromJsonString
if not keepRunning then stop kaleidoProcess
result
//Example usage:
printfn "Hello World from F#!"
//Path to kaleido executable.
let kaleidoPath = @"/media/jmmease/SSD1/kaleido/repos/build/kaleido/kaleido"
// let kaleidoPath = @"path/to/kaleido.cmd"
//Start a kaleido process
let proc = Kaleido.start kaleidoPath "plotly"
//Formats dont seem to work as I expected. Changing format here does nothing.
let input = Kaleido.KaleidoInput.ofChart("json", testFig)
//Render the chart with the started process. Save image using FAKE
input
|> Kaleido.render proc true
|> fun r ->
//save result as image
r.Result
|> (if Kaleido.stringFormats.Contains(r.Format)
then System.Text.Encoding.ASCII.GetBytes
else Convert.FromBase64String)
|> File.writeBytes (
sprintf
@"testFigure.%s"
r.Format
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment