<jupyter_start><jupyter_text>Charting from feature notebook Angara and some other server side charting lib did not work from mono so skipping it JS based stuff looks more promisining, so lets try this out<jupyter_code>@"<script src=""https://d3js.org/d3.v3.js""></script>" |> Util.Html |> Display
type D3Op = {
    Op: string
    Style: List<string * string>
    Attr: List<string * int>
    On: List<string * List<D3Op>>
}

type D3 = List<D3Op>

let d3op = {Op = ""; Style = []; Attr = []; On = []}

let mapConcat s f xs = 
    xs |> List.map f |> String.concat s

let rec D3OpPrinter (op: D3Op) =
    sprintf 
        "%s%s%s%s"
        (if op.Op.Length > 0 then
            sprintf "\t.append(\"%s\")\n" op.Op
        else
            "")
        (op.Style |> mapConcat "\t" (fun (k, v) -> sprintf ".style(\"%s\", \"%s\")\n" k v ) )
        (op.Attr |> mapConcat "\t" (fun (k, v) -> sprintf ".attr(\"%s\", %d)\n" k v))
        (op.On
            |> mapConcat "\t" (fun (k, v) ->
                sprintf 
                    ".on(\"%s\",\n\tfunction(){\n\td3.select(this)\n%s\t})\n"
                    k
                    (v |> mapConcat "" D3OpPrinter)
                ))

let D3Printer (d3: D3) =
    sprintf 
        """
<div id="viz"></div>
<script type="text/javascript">

d3.select("#viz")
%s
"""
        (d3 |> mapConcat "" D3OpPrinter)

App.AddDisplayPrinter (fun (d3: D3) ->
  { ContentType = "text/html"
    Data = D3Printer d3 }
  )
[
    {d3op with 
        Op = "svg"
        Attr = [("width", 100); ("height", 100)] }
    {d3op with
        Op = "circle"
        Style = [("stroke", "grey"); ("fill", "white")]
        Attr = [("r", 40); ("cx", 50); ("cy", 50)]
        On = 
          [ ("mouseover", [{d3op with Style = [("fill", "blue")]}])
            ("mouseout", [{d3op with Style = [("fill", "white")]}]) ] }
]<jupyter_output><empty_output><jupyter_text>D3 works out of the box, so let's try other libs, which provide easier to use API  Trying out Rickshaw and Chartjs<jupyter_code>"""
<script>
var dom = document.getElementById('container');
var myChart = echarts.init(dom);
var app = {};
option = null;
option = {
    xAxis: {
        type: 'category',
        boundaryGap: false,
        data: ['Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun']
    },
    yAxis: {
        type: 'value'
    },
    series: [{
        data: [820, 932, 901, 934, 1290, 1330, 1320],
        type: 'line',
        areaStyle: {}
    }]
};
;
if (option && typeof option === 'object') {
    myChart.setOption(option, true);
}
</script>
""" |> Util.Html |> Display
""" 
<div id='chart'></div> 
 
<script type='text/javascript'> 
var graph = new Rickshaw.Graph( {
    element: document.querySelector('#chart'), 
    width: 300, 
    height: 200, 
    series: [{
        color: 'steelblue',
        data: [ 
            { x: 0, y: 40 }, 
            { x: 1, y: 49 }, 
            { x: 2, y: 38 }, 
            { x: 3, y: 30 }, 
            { x: 4, y: 32 } ]
    }]
}); 
graph.render();
"""
|> Util.Html |> Display<jupyter_output><empty_output><jupyter_text>Both examples don't show any output. It turns out these libs must use either js require or a frame wrapper (check errors from js console of your browser)  Wrapping with frametaking an approach from this lib:https://github.com/niloch/iplotter/tree/0403486d8633f601a33c4d2b9c9fa3ec88e9327binstallation<jupyter_code>// wrap html generating code
let chartjs data = 
    sprintf """
        <canvas id='myChart'></canvas> 
        <script src='https://cdnjs.cloudflare.com/ajax/libs/Chart.js/2.5.0/Chart.bundle.min.js'></script>

        <script>

        var ctx = document.getElementById('myChart').getContext('2d');

        var chart = new Chart(ctx, {
            // The type of chart we want to create
            type: 'line',

            // The data for our dataset
            data: %s,

            // Configuration options go here
            options: {}
          });

        </script>
        """  data

// how do we want frame to be displayed
type Options = {
    Height: int
    Width: int
  }
  with 
      static member Default = {
              Width = 800
              Height  = 400
          }
// wrapping charting related code in a frame
let frame options c = 
    sprintf """
            <iframe srcdoc="%s" height = "%d px" width="%d px" sandbox="allow-scripts" frameborder="0"></iframe>
            """ c options.Height options.Width
// An attempt make chartJs interop more strongly typed. 
// Colors could be further typed but I'm not building a lib yet :)
type ChartJsDataset = {
    label: string
    backgroundColor: string
    borderColor: string
    data: int seq
}

type ChartJsData = {
    labels: string seq
    datasets: ChartJsDataset seq
}

// "render" dataset by wrapping it in HTML and then ina frame
let chartLine options labels datasets = 
   let data = {
       labels = labels
       datasets = datasets
   }
   let stringifiedData = Newtonsoft.Json.JsonConvert.SerializeObject(data).Replace("\"","'")
   chartjs stringifiedData |> frame options |> Util.Html |> Display
   
// Datasets. 
let first = {
        label = "My First dataset"
        backgroundColor = "rgba(255, 99, 132, 0.2)"
        borderColor = "rgba(255, 99, 132, 1"
        data = [0;10;5;2;20;30;45]
    }
let second = {
        label = "My Second dataset"
        backgroundColor = "rgba(54, 162, 235, 0.2)"
        borderColor = "rgba(54, 162, 235, 1)"
        data = [23;0;0;0;0;10;45]
    }
chartLine Options.Default
    ["January";"February";"March";"April";"May";"June";"July"]
    [first; second]<jupyter_output><empty_output><jupyter_text>Frame works!!! Let's check alternatives  Google chart work out of the boxfrom here http://markibrahim.me/musings/notebooks/beautiful_javascript_charts.html<jupyter_code>"""
<html>
  <head>
    <script type="text/javascript" src="https://www.gstatic.com/charts/loader.js"></script>
    <script type="text/javascript">
      google.charts.load("current", {packages:["corechart"]});
      google.charts.setOnLoadCallback(drawChart);
      function drawChart() {
        var data = google.visualization.arrayToDataTable([
          ['Task', 'Hours per Day'],
          ['Work',     11],
          ['Eat',      2],
          ['Commute',  2],
          ['Watch TV', 2],
          ['Sleep',    7]
]);

        var options = {
          title: "test",
          pieHole: 0.4,
        };

        var chart = new google.visualization.PieChart(document.getElementById('donutchart'));
        chart.draw(data, options);
      }
    </script>
  </head>
  <body>
    <div id="donutchart" style="width: 900px; height: 520px;"></div>
  </body>
</html>
""" |> Util.Html |> Display<jupyter_output><empty_output><jupyter_text>11 hours of work plus 2 hours of sleep does not look healthy :(<jupyter_code>"""<script src='https://cdnjs.cloudflare.com/ajax/libs/vis/4.21.0/vis.min.js'></script>
<link href='https://cdnjs.cloudflare.com/ajax/libs/vis/4.21.0/vis.min.css" rel='stylesheet' type='text/css'>
""".Replace("\"", "'")
    |> Util.Html |> Display
"""

<script src='https://cdnjs.cloudflare.com/ajax/libs/vis/4.21.0/vis.min.js'></script>
<style type='text/css'>
    #mynetwork {
      width: 600px;
      height: 380px;
      border: 1px solid lightgray;
    }
</style>
<div id='mynetwork' width='100%' height='100%'>Hello</div>
<script type='text/javascript'>
  // create an array with nodes
  var nodes = new vis.DataSet([
    {id: 1, label: 'Node 1'},
    {id: 2, label: 'Node 2'},
    {id: 3, label: 'Node 3'},
    {id: 4, label: 'Node 4'},
    {id: 5, label: 'Node 5'}
  ]);

  // create an array with edges
  var edges = new vis.DataSet([
    {from: 1, to: 3, label: 'edge 1 to 3', arrows: 'to', font: {align: 'bottom'}},
    {from: 1, to: 2},
    {from: 2, to: 4},
    {from: 2, to: 5},
    {from: 3, to: 3, label: '3 to 3', arrows: 'to'}
  ]);

  // create a network
  var container = document.getElementById('mynetwork');
  var data = {
    nodes: nodes,
    edges: edges
  };
  var options = {};
  var network = new vis.Network(container, data, options);
</script>


"""
|> frame Options.Default |> Util.Html |> Display<jupyter_output><empty_output>
StarcoderdataJupyterStructuredCleanDedup