I'm trying to include a legend in an Incanter chart, but I'm having some troubles getting what I want:
I want to be able to instantiate a chart with no data first (using
[] []
as my x y arguments), then add the data points in a separate step. However the only way to add a legend is to specify:legend true
after the initial x y points are given in the constructor. Cannot specify:legend true
without x y arguments, and I have not found anyadd-legend
function.The legend option captures the code I use when adding the chart data, which means if I don't want ugly code to appear in the legend I have to create a nice-looking vars for the X and Y points, rather than just calling a function in line.
Therefore the legend that is created includes the
[][]
used when creating the blank plot, it includes the function calls used when getting the data for the points, and it includes the name-mangled anonymous function(fn*[p1__3813#](second p1__3813#))
which is non-communicative to consumers of my chart.I just want to be able to associate a string with each group of points in the legend like in matlab, excel, etc.
Here is my current code;
(def lux-ratios-plot
(doto (scatter-plot [] [] :legend true
:title "Lux/CH0 vs. CH1/CH0"
:x-label "CH1/CH0"
:y-label "Lux/CH0")
(view)))
(doseq [dut [incs hals cfls leds]]
(add-points lux-ratios-plot (get-vals :CH1/CH0 dut) (get-vals :Lux/CH0 dut) :points true))
; Show the trend line for each bulb
(doseq [fit [inc-fit hal-fit cfl-fit led-fit]]
(add-lines lux-ratios-plot (map #(second %) (:x fit)) (:fitted fit)))
Therefore is there any way in Incanter plots to specify a legend string with each (add-lines ...)
or (add-points ...)
call?
Thanks a lot
Michael
Every Incanter chart is also a JFreeChart object. So you could use any of the JFreeChart methods to manipulate your Incanter chart.
For example to remove the legend you can do (.removeLegend lux-ratios-plot). There is also an addLegend method. Haven't tried that one myself. Hope this helps.
To associate nice names with series of points, or lines, use the keyword
:series-label
in the command that adds that data to the chart. For example:This doesn't address the other problem in your question: In order to create a bare scatter plot that has a legend, you have to pass empty data to
scatter-plot
, i.e. withx
andy
as empty sequences above, since Incanter doesn't allow you to specify:legend
without passing data toscatter-plot
. Ifx
andy
are empty (e.g. they arenil
), the empty data shows up in as an element the legend, too. I don't believe that this problem can be overcome directly currently (version 1.5.7).One solution is to pass real data in the scatter-plot call, along with a
:series-label
parameter. However, that may make it more awkward to programmatically generate a scatter plot when the number of datasets is unknown in advance, since you have to treat the first dataset differently than the others.Another, kludgey solution is this:
Using the empty string as the value of
:series-label
means that the label in the legend for the first, empty dataset will not display. Theset-stroke-color
call makes the color of the empty dataset (i.e. dataset 0) transparent. Otherwise, you'll have a red dot for this dataset in your legend. You will have a small empty space in the legend where the red dot and the empty string belong, but that's less confusing than seeing a red dot there.