6

When run in F# Interactive, I expect the following code to create a simple pie chart and save it to disk:

let pie = FSharpChart.Pie([("Apples",1);("Oranges",2);("Bananas",3)])
FSharpChart.SaveAs "test.png" ChartImageFormat.Png pie

However, what actually gets saved in "test.png" is a blank image. The same happens if I pipe the chart into the FShartChart.SaveAs function. But if I first execute only the chart creation code and give the chart time to render before manually executing SaveAs, the image gets saved as expected.

Is there a way to block the call to FSharpChart.Pie until the rendering is complete? I'm using FSharpChart.fsx version 0.60 in Visual Studio 2013.

Tomas Petricek
  • 240,744
  • 19
  • 378
  • 553
Kevin D.
  • 911
  • 1
  • 6
  • 18

2 Answers2

8

The problem is that the underlying chart control first needs to be displayed before it can save the chart to a file (this is pretty silly, but sadly, F# chart is just a lightweight wrapper over underlying .NET chart libraries).

I think you can either run the two lines separately in F# interactive, or you need to explicitly call some method that displays the chart (I believe there is FSharpChart.Show or something like that)

I tested this using F# Charting which is a newer version of the library (with some API changes, but very similar ideas) and the following works (even when executed all in a single command):

#load @"packages\FSharp.Charting.0.87\FSharp.Charting.fsx"
open FSharp.Charting

let pie = Chart.Pie([("Apples",1);("Oranges",2);("Bananas",3)])
pie.ShowChart()
pie.SaveChartAs("D:\\temp\\test.png", ChartTypes.ChartImageFormat.Png)
Tomas Petricek
  • 240,744
  • 19
  • 378
  • 553
  • Thanks for pointing me towards F# Charting. The only minor issue I see is that the above code snippet will result in two chart windows being displayed, presumably one from Chart.Pie and one from pie.ShowChart(). However it saves me the trouble of manually executing code snippets for about a dozen charts, which is what I was after. – Kevin D. Oct 29 '13 at 16:49
1

I have found the following to work well, requiring no need to display. (FSharp.Charting, v 0.90.14, .net 4.5)

open FSharp.Charting
// etc
let prices = getPriceData ()
let chart = Chart.Candlestick(prices)
Chart.Save @"C:\Charts\prices.png" chart

Update

let renderChart ch = 
    let frm = new Form(Visible = false, TopMost = true, Width = 700, Height = 500)
    let ctl = new ChartControl(ch, Dock = DockStyle.Fill)
    frm.Controls.Add(ctl)

calling this on your given chart will allow you to render the chart without any forms pop ups.

rbonallo
  • 970
  • 1
  • 9
  • 21