Adjusting the color range in an image plot

classic Classic list List threaded Threaded
6 messages Options
Reply | Threaded
Open this post in threaded view
|

Adjusting the color range in an image plot

Martin Gustafsson
Hello,

I have a Chaco image plot and would like to use the full dynamic range of the color scale to represent the data that are visible. For example, let's say my 2d data array has a range of +-4, but there is a subset of the plot which only has a range of +-1. When the whole dataset is visible I want blue to mean +4 and red to mean -4, but when I zoom in on the subset, I want red to mean +1 and blue to mean -1. It seems I can use CMapImagePlot.value_range.set_bounds(min, max) to set the range, but I am not sure how to capture zooming and panning events, and how to find out what data are within the bounds of the plot. Can someone please recommend a neat way to do this?

Best wishes
Martin
_______________________________________________
Enthought-Dev mailing list
[hidden email]
https://mail.enthought.com/mailman/listinfo/enthought-dev
Reply | Threaded
Open this post in threaded view
|

Re: Adjusting the color range in an image plot

Roan LaPlante
For capturing and customizing zoom/pan events, you can write your own Tools (e.g. CustomPanTool extends PanTool) that do custom processing (such as dynamically changing the ColorMapper).

Here is an example of a custom PanTool that overwrites the default panning behavior if the user clicks and then releases without moving the mouse and calls an application-specific display_node() method in this case, and otherwise reverts to the default panning behavior.

class ConnmatPanClickTool(PanTool):
    cvu=Instance(CvuPlaceholder)

    event_state=Enum("normal","deciding","panning")
    drag_pointer=Pointer("arrow")

    def __init__(self,holder,*args,**kwargs):
        super(PanTool,self).__init__(component=holder.conn_mat,**kwargs)
        self.cvu=holder

    def normal_left_down(self,event):
        self.event_state='deciding'
        self._original_xy=(event.x,event.y)
        return

    def normal_right_down(self,event):
        self.cvu.display_all()

    # the click is a node selection
    def deciding_left_up(self,event):
        self.event_state='normal'
        x,y=self.cvu.conn_mat.map_data((event.x,event.y))
        self.cvu.display_node(int(np.floor(y)))
        return

    # the click is a pan
    # the only thing of real interest in _start_pan() is change to the panning state
    def deciding_mouse_move(self,event):
        self.event_state='panning'
        return self.panning_mouse_move(event)





For your other question -- deciding whether the data is within the bounds of the plot -- I'm not sure quite what you're asking, but look at plot.map_screen and plot.map_data.  You can dynamically compare these results to plot's range.


On Sat, Jul 20, 2013 at 9:49 PM, Martin Gustafsson <[hidden email]> wrote:
Hello,

I have a Chaco image plot and would like to use the full dynamic range of the color scale to represent the data that are visible. For example, let's say my 2d data array has a range of +-4, but there is a subset of the plot which only has a range of +-1. When the whole dataset is visible I want blue to mean +4 and red to mean -4, but when I zoom in on the subset, I want red to mean +1 and blue to mean -1. It seems I can use CMapImagePlot.value_range.set_bounds(min, max) to set the range, but I am not sure how to capture zooming and panning events, and how to find out what data are within the bounds of the plot. Can someone please recommend a neat way to do this?

Best wishes
Martin
_______________________________________________
Enthought-Dev mailing list
[hidden email]
https://mail.enthought.com/mailman/listinfo/enthought-dev


The information in this e-mail is intended only for the person to whom it is
addressed. If you believe this e-mail was sent to you in error and the e-mail
contains patient information, please contact the Partners Compliance HelpLine at
http://www.partners.org/complianceline . If the e-mail was sent to you in error
but does not contain patient information, please contact the sender and properly
dispose of the e-mail.




--
Roan LaPlante
Athinoula A. Martinos Center for Biomedical Imaging


_______________________________________________
Enthought-Dev mailing list
[hidden email]
https://mail.enthought.com/mailman/listinfo/enthought-dev
Reply | Threaded
Open this post in threaded view
|

Re: Adjusting the color range in an image plot

Robert Kern
In reply to this post by Martin Gustafsson
On Sun, Jul 21, 2013 at 2:49 AM, Martin Gustafsson
<[hidden email]> wrote:
> Hello,
>
> I have a Chaco image plot and would like to use the full dynamic range of the color scale to represent the data that are visible. For example, let's say my 2d data array has a range of +-4, but there is a subset of the plot which only has a range of +-1. When the whole dataset is visible I want blue to mean +4 and red to mean -4, but when I zoom in on the subset, I want red to mean +1 and blue to mean -1. It seems I can use CMapImagePlot.value_range.set_bounds(min, max) to set the range, but I am not sure how to capture zooming and panning events, and how to find out what data are within the bounds of the plot. Can someone please recommend a neat way to do this?

You don't need to listen to the pan/zoom events per se. You just need
to know when the `CMapImagePlot.index_mapper` gets updated range data.
Listen to the `updated` trait on the index_mapper. That will fire
whenever the ranges get changed. `CMapImagePlot.index_mapper.range`
will be a `DataRange2D` that will give you the lower and upper bounds
that is being currently viewed.

  https://github.com/enthought/chaco/blob/master/chaco/data_range_2d.py#L24

You take a look at those, find the subset of your data that fits in
those bounds, determine the appropriate colormap range for that
subset, and set it using `CMapImagePlot.value_range.set_bounds()` as
above.

--
Robert Kern
Enthought
_______________________________________________
Enthought-Dev mailing list
[hidden email]
https://mail.enthought.com/mailman/listinfo/enthought-dev
Reply | Threaded
Open this post in threaded view
|

Re: Adjusting the color range in an image plot

Martin Gustafsson
Thanks Robert, that's nice and it works! It's just a little bit slow to update, and it seems that the 'updated' trait on the index mapper fires many times for each time the plot is re-rendered. My home-built arithmetic to find out what subset of the 2D-data is within the plot boundaries is probably a bit slow. It seems to me that the CMapImagePlot must already have computed this subset though. I didn't find anything in the Chaco class definitions that I could obviously interface to, but the plot has to somehow know what data are getting rendered, no?

Best wishes
Martin


22 jul 2013 kl. 12.36 skrev Robert Kern:

> On Sun, Jul 21, 2013 at 2:49 AM, Martin Gustafsson
> <[hidden email]> wrote:
>> Hello,
>>
>> I have a Chaco image plot and would like to use the full dynamic range of the color scale to represent the data that are visible. For example, let's say my 2d data array has a range of +-4, but there is a subset of the plot which only has a range of +-1. When the whole dataset is visible I want blue to mean +4 and red to mean -4, but when I zoom in on the subset, I want red to mean +1 and blue to mean -1. It seems I can use CMapImagePlot.value_range.set_bounds(min, max) to set the range, but I am not sure how to capture zooming and panning events, and how to find out what data are within the bounds of the plot. Can someone please recommend a neat way to do this?
>
> You don't need to listen to the pan/zoom events per se. You just need
> to know when the `CMapImagePlot.index_mapper` gets updated range data.
> Listen to the `updated` trait on the index_mapper. That will fire
> whenever the ranges get changed. `CMapImagePlot.index_mapper.range`
> will be a `DataRange2D` that will give you the lower and upper bounds
> that is being currently viewed.
>
>  https://github.com/enthought/chaco/blob/master/chaco/data_range_2d.py#L24
>
> You take a look at those, find the subset of your data that fits in
> those bounds, determine the appropriate colormap range for that
> subset, and set it using `CMapImagePlot.value_range.set_bounds()` as
> above.
>
> --
> Robert Kern
> Enthought
> _______________________________________________
> Enthought-Dev mailing list
> [hidden email]
> https://mail.enthought.com/mailman/listinfo/enthought-dev

_______________________________________________
Enthought-Dev mailing list
[hidden email]
https://mail.enthought.com/mailman/listinfo/enthought-dev
Reply | Threaded
Open this post in threaded view
|

Re: Adjusting the color range in an image plot

Robert Kern
On Mon, Jul 22, 2013 at 10:19 PM, Martin Gustafsson
<[hidden email]> wrote:
> Thanks Robert, that's nice and it works! It's just a little bit slow to update, and it seems that the 'updated' trait on the index mapper fires many times for each time the plot is re-rendered.

True. You can narrow this down by listening to the `updated` event on
just the `index_range` itself, rather than the mapper.

> My home-built arithmetic to find out what subset of the 2D-data is within the plot boundaries is probably a bit slow. It seems to me that the CMapImagePlot must already have computed this subset though. I didn't find anything in the Chaco class definitions that I could obviously interface to, but the plot has to somehow know what data are getting rendered, no?

Not really. We do the naive approach of colormapping the whole dataset
to an RGB(A) image and then letting our renderer decide what bits go
where.

--
Robert Kern
Enthought
_______________________________________________
Enthought-Dev mailing list
[hidden email]
https://mail.enthought.com/mailman/listinfo/enthought-dev
Reply | Threaded
Open this post in threaded view
|

Re: Adjusting the color range in an image plot

Martin Gustafsson
I see. In any case, it's fast enough now and looks nice. Thanks a lot!

Best wishes
Martin


23 jul 2013 kl. 00.28 skrev Robert Kern:

> On Mon, Jul 22, 2013 at 10:19 PM, Martin Gustafsson
> <[hidden email]> wrote:
>> Thanks Robert, that's nice and it works! It's just a little bit slow to update, and it seems that the 'updated' trait on the index mapper fires many times for each time the plot is re-rendered.
>
> True. You can narrow this down by listening to the `updated` event on
> just the `index_range` itself, rather than the mapper.
>
>> My home-built arithmetic to find out what subset of the 2D-data is within the plot boundaries is probably a bit slow. It seems to me that the CMapImagePlot must already have computed this subset though. I didn't find anything in the Chaco class definitions that I could obviously interface to, but the plot has to somehow know what data are getting rendered, no?
>
> Not really. We do the naive approach of colormapping the whole dataset
> to an RGB(A) image and then letting our renderer decide what bits go
> where.
>
> --
> Robert Kern
> Enthought
> _______________________________________________
> Enthought-Dev mailing list
> [hidden email]
> https://mail.enthought.com/mailman/listinfo/enthought-dev

_______________________________________________
Enthought-Dev mailing list
[hidden email]
https://mail.enthought.com/mailman/listinfo/enthought-dev