[Chart] Heat map/image support

Ben Gamari bgamari at gmail.com
Wed May 9 16:00:43 BST 2012


Tim Docker <tim at dockerz.net> writes:

> Hi Ben,
>
> It's good to here that you are finding the Chart library useful.
>
Absolutely. Thanks for this wonderful library.

>>  My first thought (option A) was the following,
>> 
>>        data HeatMap z x y = HeatMap { heat_map_values_ :: [(x,y,z)]
>>                                     , heat_map_cell_size_ :: (x,y)
>>                                     }
>> 
>> Unfortunately, it seems that this isn't going to work so well as I can't
>> ensure that types x and y have a Num instance (for addition)
>
> Why is this? The toPlot type class might be problematic, but you can
> just write a non-polymorphic function:
>
Sure; there is no reason why that wouldn't work. I guess the toPlot type
class isn't strictly necessary. That being said, if you were willing to
use more language extensions, you could always add a constraint to the class.

>     data HeatMap z x y = HeatMap { heat_map_values_ :: [(x,y,z)]
>                                  , heat_map_cell_size_ :: (x,y)
>                                  }
>
>     heatMapToPlot:: (Num x, Num y) => HeadMap x y z -> Plot x y
>
>
> Another possible representation might be:
>
>     data HeatMap z x y = HeatMap { heat_map_x_values_ :: [x]
>                                  , heat_map_y_values_ :: [y]
>                                  , heat_map_z_values_ :: [AlphaColour Double]]
>                                  }
>
This is another possibility.

>
>> The last option (option C) would be to use the approach taken by
>> matplotlib, viewing a heatmap as an image. This has the disadvantage of
>> requiring the user to ensure the image properly positioned and scaled on
>> the axes (although this could be wrapped) but avoids the costly task of
>> drawing each rectangular cell individually (which takes 12s on my
>> machine for a 500x500 cell map).
>
> That sounds disappointingly slow. Which version of cairo are you using? I seem
> to remember on haskell-cafe a post indicating that there were some recent significant
> speed improvements.
>
I am on cairo 1.10.2. I'm honestly not sure what to expect in terms of
performance. Granted 12s sounds a bit slow, but I am doing 25k small
fills, which as far as I know is pretty much the worst case for the
driver (on Intel graphics at least).

>> That being said, I think image support
>> would be useful (perhaps from a Repa array?), even if it is decided that
>> this is not the proper way to handle heat-maps.
>
> Yes. I think image support could be useful. However, I'm pretty unfamiliar with
> the available haskell array libraries. For chart I'd want something sufficiently
> fast, but also with a stable API.
>
I actually spent a while yesterday working on this. The current status
of things can be found here[1]. I have yet to get scaling working
properly. Unfortunately, it seems that cairo doesn't support
nearest-neighbor resampling, which I think is the most reasonable choice
for plotting applications. I guess I can implement this myself.

>> Lastly, after the interface issues have been decided and the code
>> settled a bit, I'd happy to submit the code for merge into
>> Chart-proper.
>
> I'm happy to accept patches for Chart - there's been many from various people
> over the years. My acceptance criteria are:
>
>      - the code is clean and fits with the existing style (I'm not too fussy
>         here)
>      - there's a test case
>      - we don't introduce substantial additional dependencies
>
Good to know. For this reason I think the image support may want to
remain a separate module (due to the repa dependency). That being said,
once histogram support is stable, I'd be happy to clean it up for
merging.

Cheers,

- Ben

[1] https://github.com/bgamari/chart-image




More information about the Chart mailing list