Changing the index mapper on a pre-existing plot

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

Changing the index mapper on a pre-existing plot

Adam Hughes
I have a chaco Plot() which updates many of its components (LabelAxis, plot.plots etc...) dynamically in response to user interaction.  One thing I noticed is that the index_mapper and value_mapper attributes of Plot() are set upon initialization, and don't appear to automatically update when line plots are added, removed or changed.  As such, my range_selection tool still maps the indicies of the original plot index.

I've tried to update the mapper upon changes to the plot.plots list.  Witthout getting into the code, suffice to say it is not behaving as expected.  This also has to do with me not quite understanding the deep relations between LinearMapper, DataRange1D and ArrayDataSource.  In any case, I wondered if there was a prescribed method for doing this?  EG, does Plot, or LinearMapper or some other class have a method the purpose of which is to do what I'm describing.  I saw that there are several "refresh methods" but can't quite get my head around them entirely.

The implementation below works, but doesn't give me correct values for the range selection after I change the index.  The index is literally the index values of a dataframe.

    def _update_rangeselect(self):
        ''' Overwrites range selection tool in current plot.'''
           
        #### Remove current overlay
        self.plot.overlays=[obj for obj in self.plot.overlays if not isinstance(obj, RangeSelectionOverlay)]
            
        mycomp=self.plot.plots.itervalues().next()[0] #Quick wayt to get first value in dictionary
        
        inds=range(len(self.df.index))
        idx=ArrayDataSource(inds)
        vals=ArrayDataSource(df.index.values)
        
        index_range = DataRange1D(idx)        
        val_range=DataRange1D(vals)
        imap=LinearMapper(range=index_range)
        vmap=LinearMapper(range=val_range)
        
        mycomp.index_mapper=imap        
        mycomp.value_mapper=vmap
        
        self.rangeselect=RangeSelection(mycomp, axis=self.selection_axis)
        self.plot.active_tool = self.rangeselect
        self.plot.overlays.append(RangeSelectionOverlay(component=mycomp)) 
        self.rangeselect.on_trait_change(self.on_selection_changed, "selection")

--
Adam Hughes
Physics Ph.D Candidate
George Washington University

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

Re: Changing the index mapper on a pre-existing plot

Roan LaPlante
I am not sure of the "best" way of doing it, but I found one of the easiest ways for dealing with changing the data bounds in my program was not to change the mapper but to discard and recreate the axis, which was very quick.

R

On Fri, Mar 1, 2013 at 7:12 PM, Adam Hughes <[hidden email]> wrote:
I have a chaco Plot() which updates many of its components (LabelAxis, plot.plots etc...) dynamically in response to user interaction.  One thing I noticed is that the index_mapper and value_mapper attributes of Plot() are set upon initialization, and don't appear to automatically update when line plots are added, removed or changed.  As such, my range_selection tool still maps the indicies of the original plot index.

I've tried to update the mapper upon changes to the plot.plots list.  Witthout getting into the code, suffice to say it is not behaving as expected.  This also has to do with me not quite understanding the deep relations between LinearMapper, DataRange1D and ArrayDataSource.  In any case, I wondered if there was a prescribed method for doing this?  EG, does Plot, or LinearMapper or some other class have a method the purpose of which is to do what I'm describing.  I saw that there are several "refresh methods" but can't quite get my head around them entirely.

The implementation below works, but doesn't give me correct values for the range selection after I change the index.  The index is literally the index values of a dataframe.

    def _update_rangeselect(self):
        ''' Overwrites range selection tool in current plot.'''
           
        #### Remove current overlay
        self.plot.overlays=[obj for obj in self.plot.overlays if not isinstance(obj, RangeSelectionOverlay)]
            
        mycomp=self.plot.plots.itervalues().next()[0] #Quick wayt to get first value in dictionary
        
        inds=range(len(self.df.index))
        idx=ArrayDataSource(inds)
        vals=ArrayDataSource(df.index.values)
        
        index_range = DataRange1D(idx)        
        val_range=DataRange1D(vals)
        imap=LinearMapper(range=index_range)
        vmap=LinearMapper(range=val_range)
        
        mycomp.index_mapper=imap        
        mycomp.value_mapper=vmap
        
        self.rangeselect=RangeSelection(mycomp, axis=self.selection_axis)
        self.plot.active_tool = self.rangeselect
        self.plot.overlays.append(RangeSelectionOverlay(component=mycomp)) 
        self.rangeselect.on_trait_change(self.on_selection_changed, "selection")

--
Adam Hughes
Physics Ph.D Candidate
George Washington University

_______________________________________________
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: Changing the index mapper on a pre-existing plot

Adam Hughes
Do you do this with a call to PlotAxis?  Can you post an snippet from your code if you get a chance?

Thanks

On Fri, Mar 1, 2013 at 9:37 PM, Roan LaPlante <[hidden email]> wrote:
I am not sure of the "best" way of doing it, but I found one of the easiest ways for dealing with changing the data bounds in my program was not to change the mapper but to discard and recreate the axis, which was very quick.

R

On Fri, Mar 1, 2013 at 7:12 PM, Adam Hughes <[hidden email]> wrote:
I have a chaco Plot() which updates many of its components (LabelAxis, plot.plots etc...) dynamically in response to user interaction.  One thing I noticed is that the index_mapper and value_mapper attributes of Plot() are set upon initialization, and don't appear to automatically update when line plots are added, removed or changed.  As such, my range_selection tool still maps the indicies of the original plot index.

I've tried to update the mapper upon changes to the plot.plots list.  Witthout getting into the code, suffice to say it is not behaving as expected.  This also has to do with me not quite understanding the deep relations between LinearMapper, DataRange1D and ArrayDataSource.  In any case, I wondered if there was a prescribed method for doing this?  EG, does Plot, or LinearMapper or some other class have a method the purpose of which is to do what I'm describing.  I saw that there are several "refresh methods" but can't quite get my head around them entirely.

The implementation below works, but doesn't give me correct values for the range selection after I change the index.  The index is literally the index values of a dataframe.

    def _update_rangeselect(self):
        ''' Overwrites range selection tool in current plot.'''
           
        #### Remove current overlay
        self.plot.overlays=[obj for obj in self.plot.overlays if not isinstance(obj, RangeSelectionOverlay)]
            
        mycomp=self.plot.plots.itervalues().next()[0] #Quick wayt to get first value in dictionary
        
        inds=range(len(self.df.index))
        idx=ArrayDataSource(inds)
        vals=ArrayDataSource(df.index.values)
        
        index_range = DataRange1D(idx)        
        val_range=DataRange1D(vals)
        imap=LinearMapper(range=index_range)
        vmap=LinearMapper(range=val_range)
        
        mycomp.index_mapper=imap        
        mycomp.value_mapper=vmap
        
        self.rangeselect=RangeSelection(mycomp, axis=self.selection_axis)
        self.plot.active_tool = self.rangeselect
        self.plot.overlays.append(RangeSelectionOverlay(component=mycomp)) 
        self.rangeselect.on_trait_change(self.on_selection_changed, "selection")

--
Adam Hughes
Physics Ph.D Candidate
George Washington University

_______________________________________________
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




--
Adam Hughes
Physics Ph.D Candidate
George Washington University

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

Re: Changing the index mapper on a pre-existing plot

Roan LaPlante
Actually, I apologize.  I tried to give a solution for code I wrote a month ago, and I forgot what I had done, and my previous email suggests a wrong answer.  I ran into the same or a similar issue as you did; the size of the data bounds being plotted changes, and the mapper displays the wrong size.  My program does recreate the axes every iteration of the data changing, but this is because the axis extends LabelAxis to display labels in specific colors that depend on the data.

The thing that does update the data bounds in my application is not recreating the axes, but actually recreating and replacing the entire plot, which was okay in my application.

This function is called within __init__ and whenever the data is updated (ColorAxis and ConnmatPanClickTool extend LabelAxis and PanTool, respectively)

def chaco_gen(self):
        # set the diagonal of the adjmat to lower threshold rather than 0
        # otherwise the color scheme is a mess for non-sparse matrices
        self.conn_mat = Plot(ArrayPlotData(imagedata=self.adj_thresdiag))
        self.conn_mat.img_plot("imagedata",name='conmatplot',
            colormap=cmap_reverse(RdYlBu))
        self.conn_mat.tools.append(ZoomTool(self.conn_mat))
        self.conn_mat.tools.append(ConnmatPanClickTool(self,self.conn_mat))
        self.xa=color_axis.ColorfulAxis(self.conn_mat,self.node_colors,'x')
        self.ya=color_axis.ColorfulAxis(self.conn_mat,self.node_colors,'y')
        self.conn_mat.underlays=[self.xa,self.ya]


Sorry if its not as much help as I thought it would be.

R

On Fri, Mar 1, 2013 at 9:38 PM, Adam Hughes <[hidden email]> wrote:
Do you do this with a call to PlotAxis?  Can you post an snippet from your code if you get a chance?

Thanks


On Fri, Mar 1, 2013 at 9:37 PM, Roan LaPlante <[hidden email]> wrote:
I am not sure of the "best" way of doing it, but I found one of the easiest ways for dealing with changing the data bounds in my program was not to change the mapper but to discard and recreate the axis, which was very quick.

R

On Fri, Mar 1, 2013 at 7:12 PM, Adam Hughes <[hidden email]> wrote:
I have a chaco Plot() which updates many of its components (LabelAxis, plot.plots etc...) dynamically in response to user interaction.  One thing I noticed is that the index_mapper and value_mapper attributes of Plot() are set upon initialization, and don't appear to automatically update when line plots are added, removed or changed.  As such, my range_selection tool still maps the indicies of the original plot index.

I've tried to update the mapper upon changes to the plot.plots list.  Witthout getting into the code, suffice to say it is not behaving as expected.  This also has to do with me not quite understanding the deep relations between LinearMapper, DataRange1D and ArrayDataSource.  In any case, I wondered if there was a prescribed method for doing this?  EG, does Plot, or LinearMapper or some other class have a method the purpose of which is to do what I'm describing.  I saw that there are several "refresh methods" but can't quite get my head around them entirely.

The implementation below works, but doesn't give me correct values for the range selection after I change the index.  The index is literally the index values of a dataframe.

    def _update_rangeselect(self):
        ''' Overwrites range selection tool in current plot.'''
           
        #### Remove current overlay
        self.plot.overlays=[obj for obj in self.plot.overlays if not isinstance(obj, RangeSelectionOverlay)]
            
        mycomp=self.plot.plots.itervalues().next()[0] #Quick wayt to get first value in dictionary
        
        inds=range(len(self.df.index))
        idx=ArrayDataSource(inds)
        vals=ArrayDataSource(df.index.values)
        
        index_range = DataRange1D(idx)        
        val_range=DataRange1D(vals)
        imap=LinearMapper(range=index_range)
        vmap=LinearMapper(range=val_range)
        
        mycomp.index_mapper=imap        
        mycomp.value_mapper=vmap
        
        self.rangeselect=RangeSelection(mycomp, axis=self.selection_axis)
        self.plot.active_tool = self.rangeselect
        self.plot.overlays.append(RangeSelectionOverlay(component=mycomp)) 
        self.rangeselect.on_trait_change(self.on_selection_changed, "selection")

--
Adam Hughes
Physics Ph.D Candidate
George Washington University

_______________________________________________
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




--
Adam Hughes
Physics Ph.D Candidate
George Washington University

_______________________________________________
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: Changing the index mapper on a pre-existing plot

Adam Hughes
Thanks for the help Roan.  Yes, unfortunately it is unfeasible for me to redraw the entire plot object (although I could do it as a temp fix).  For now, it's not the biggest problem anyway, will just put it on the backburner.  

On Mon, Mar 4, 2013 at 10:31 AM, Roan LaPlante <[hidden email]> wrote:
Actually, I apologize.  I tried to give a solution for code I wrote a month ago, and I forgot what I had done, and my previous email suggests a wrong answer.  I ran into the same or a similar issue as you did; the size of the data bounds being plotted changes, and the mapper displays the wrong size.  My program does recreate the axes every iteration of the data changing, but this is because the axis extends LabelAxis to display labels in specific colors that depend on the data.

The thing that does update the data bounds in my application is not recreating the axes, but actually recreating and replacing the entire plot, which was okay in my application.

This function is called within __init__ and whenever the data is updated (ColorAxis and ConnmatPanClickTool extend LabelAxis and PanTool, respectively)

def chaco_gen(self):
        # set the diagonal of the adjmat to lower threshold rather than 0
        # otherwise the color scheme is a mess for non-sparse matrices
        self.conn_mat = Plot(ArrayPlotData(imagedata=self.adj_thresdiag))
        self.conn_mat.img_plot("imagedata",name='conmatplot',
            colormap=cmap_reverse(RdYlBu))
        self.conn_mat.tools.append(ZoomTool(self.conn_mat))
        self.conn_mat.tools.append(ConnmatPanClickTool(self,self.conn_mat))
        self.xa=color_axis.ColorfulAxis(self.conn_mat,self.node_colors,'x')
        self.ya=color_axis.ColorfulAxis(self.conn_mat,self.node_colors,'y')
        self.conn_mat.underlays=[self.xa,self.ya]


Sorry if its not as much help as I thought it would be.

R


On Fri, Mar 1, 2013 at 9:38 PM, Adam Hughes <[hidden email]> wrote:
Do you do this with a call to PlotAxis?  Can you post an snippet from your code if you get a chance?

Thanks


On Fri, Mar 1, 2013 at 9:37 PM, Roan LaPlante <[hidden email]> wrote:
I am not sure of the "best" way of doing it, but I found one of the easiest ways for dealing with changing the data bounds in my program was not to change the mapper but to discard and recreate the axis, which was very quick.

R

On Fri, Mar 1, 2013 at 7:12 PM, Adam Hughes <[hidden email]> wrote:
I have a chaco Plot() which updates many of its components (LabelAxis, plot.plots etc...) dynamically in response to user interaction.  One thing I noticed is that the index_mapper and value_mapper attributes of Plot() are set upon initialization, and don't appear to automatically update when line plots are added, removed or changed.  As such, my range_selection tool still maps the indicies of the original plot index.

I've tried to update the mapper upon changes to the plot.plots list.  Witthout getting into the code, suffice to say it is not behaving as expected.  This also has to do with me not quite understanding the deep relations between LinearMapper, DataRange1D and ArrayDataSource.  In any case, I wondered if there was a prescribed method for doing this?  EG, does Plot, or LinearMapper or some other class have a method the purpose of which is to do what I'm describing.  I saw that there are several "refresh methods" but can't quite get my head around them entirely.

The implementation below works, but doesn't give me correct values for the range selection after I change the index.  The index is literally the index values of a dataframe.

    def _update_rangeselect(self):
        ''' Overwrites range selection tool in current plot.'''
           
        #### Remove current overlay
        self.plot.overlays=[obj for obj in self.plot.overlays if not isinstance(obj, RangeSelectionOverlay)]
            
        mycomp=self.plot.plots.itervalues().next()[0] #Quick wayt to get first value in dictionary
        
        inds=range(len(self.df.index))
        idx=ArrayDataSource(inds)
        vals=ArrayDataSource(df.index.values)
        
        index_range = DataRange1D(idx)        
        val_range=DataRange1D(vals)
        imap=LinearMapper(range=index_range)
        vmap=LinearMapper(range=val_range)
        
        mycomp.index_mapper=imap        
        mycomp.value_mapper=vmap
        
        self.rangeselect=RangeSelection(mycomp, axis=self.selection_axis)
        self.plot.active_tool = self.rangeselect
        self.plot.overlays.append(RangeSelectionOverlay(component=mycomp)) 
        self.rangeselect.on_trait_change(self.on_selection_changed, "selection")

--
Adam Hughes
Physics Ph.D Candidate
George Washington University

_______________________________________________
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




--
Adam Hughes
Physics Ph.D Candidate
George Washington University

_______________________________________________
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




--
Adam Hughes
Physics Ph.D Candidate
George Washington University

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

Re: Changing the index mapper on a pre-existing plot

Peter Wang-2
In reply to this post by Adam Hughes
On Fri, Mar 1, 2013 at 6:12 PM, Adam Hughes <[hidden email]> wrote:
I have a chaco Plot() which updates many of its components (LabelAxis, plot.plots etc...) dynamically in response to user interaction.  One thing I noticed is that the index_mapper and value_mapper attributes of Plot() are set upon initialization, and don't appear to automatically update when line plots are added, removed or changed.  As such, my range_selection tool still maps the indicies of the original plot index.
I've tried to update the mapper upon changes to the plot.plots list.  Witthout getting into the code, suffice to say it is not behaving as expected.  

You need to make sure that the data sources are getting added to the DataRange objects.  So, for each line plot, the index data source should be added to your Plot's .index_range.sources list, and likewise for the value data source and the .value_range.sources.

You should not need to manually recreate Axis objects or anything like that.

-Peter


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

Re: Changing the index mapper on a pre-existing plot

Adam Hughes
On Mon, Mar 4, 2013 at 12:50 PM, Peter Wang <[hidden email]> wrote:
On Fri, Mar 1, 2013 at 6:12 PM, Adam Hughes <[hidden email]> wrote:
I have a chaco Plot() which updates many of its components (LabelAxis, plot.plots etc...) dynamically in response to user interaction.  One thing I noticed is that the index_mapper and value_mapper attributes of Plot() are set upon initialization, and don't appear to automatically update when line plots are added, removed or changed.  As such, my range_selection tool still maps the indicies of the original plot index.
I've tried to update the mapper upon changes to the plot.plots list.  Witthout getting into the code, suffice to say it is not behaving as expected.  


Thanks Peter. 
 
You need to make sure that the data sources are getting added to the DataRange objects.

These are inherent DataRange attributes of the Plot() class, right?  Eg there is a single attribute in my plot called self.plot.index_range.sources?  If so, should I just clear the list and update with each new data cycle, or is there a special way that these need updated?  IE a special method or way of doing it?
 
 So, for each line plot, the index data source should be added to your Plot's .index_range.sources list, and likewise for the value data source and the .value_range.sources. 


You should not need to manually recreate Axis objects or anything like that.

-Peter


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




--
Adam Hughes
Physics Ph.D Candidate
George Washington University

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

Re: Changing the index mapper on a pre-existing plot

Peter Wang-2
On Mon, Mar 4, 2013 at 12:24 PM, Adam Hughes <[hidden email]> wrote:
You need to make sure that the data sources are getting added to the DataRange objects.

These are inherent DataRange attributes of the Plot() class, right?  Eg there is a single attribute in my plot called self.plot.index_range.sources?

Yes.
 
If so, should I just clear the list and update with each new data cycle, or is there a special way that these need updated?  IE a special method or way of doing it?

No, you just add the ArrayDataSource to it once.  There is no need to update the list of sources each cycle.  It's not always obvious from the object model, but the Chaco approach is to construct a visualization pipeline, and upstream elements inform downstream elements of the need to update via Traits events.  So, when you add the DataSource to a DataRange's .sources list, the DataRange hooks up listeners to the DataSource (see https://github.com/enthought/chaco/blob/master/chaco/data_range_1d.py#L375).  Whenever you update the data values in the DataSource, the DataRange send a "data_changed" event, which ultimately bubbles up to invalidating the current rendering and requesting a redraw from the underlying GUI system.

-Peter

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

Re: Changing the index mapper on a pre-existing plot

Adam Hughes
Thanks for this explanation.  It helps a lot.

On Mon, Mar 4, 2013 at 5:48 PM, Peter Wang <[hidden email]> wrote:
On Mon, Mar 4, 2013 at 12:24 PM, Adam Hughes <[hidden email]> wrote:
You need to make sure that the data sources are getting added to the DataRange objects.

These are inherent DataRange attributes of the Plot() class, right?  Eg there is a single attribute in my plot called self.plot.index_range.sources?

Yes.
 
If so, should I just clear the list and update with each new data cycle, or is there a special way that these need updated?  IE a special method or way of doing it?

No, you just add the ArrayDataSource to it once.  There is no need to update the list of sources each cycle.  It's not always obvious from the object model, but the Chaco approach is to construct a visualization pipeline, and upstream elements inform downstream elements of the need to update via Traits events.  So, when you add the DataSource to a DataRange's .sources list, the DataRange hooks up listeners to the DataSource (see https://github.com/enthought/chaco/blob/master/chaco/data_range_1d.py#L375).  Whenever you update the data values in the DataSource, the DataRange send a "data_changed" event, which ultimately bubbles up to invalidating the current rendering and requesting a redraw from the underlying GUI system.

-Peter

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




--
Adam Hughes
Physics Ph.D Candidate
George Washington University

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

Re: Changing the index mapper on a pre-existing plot

Adam Hughes
Peter,

I was wondering if you could look at the code below and tell me if I did not follow your suggestion in the proper way.  I am trying to add the values of a dataframe (self.df) index and columns, which are numerical values.  Instead of calling df.index.values, I do np.array(list(df.index.values)).  This changes the dtype of the underlying array from object to float.  Just pointing this out before I post the code so it's not confusing:

        ### Remove old sources in index/value ranges
        todump=[s for s in self.plot.index_range.sources]
        for s in todump:
            self.plot.index_range.remove(s)
            
        todump=[s for s in self.plot.value_range.sources]
        for s in todump:
            self.plot.value_range.remove(s)        
            
        ### Add new ones    
        self.plot.index_range.add(ArrayDataSource(np.array(list(self.df.index.values))))
        self.plot.value_range.add(ArrayDataSource(np.array(list(self.df.columns.values))))           


Although this works, it is giving me odd behavior, such as index errors on redraw.  I've traced these errors but am having a tough time seeing what is causing them, so I thought I'd ask if I've implemented your suggestion correctly before trying to track down the source of the error.

Somewhere along the line, the _wrapit() method in fromnumeric.py gets string values (maybe from a call to the string-valued LabelAxis or from my plotdatasource... it's hard to say at this point).

On Mon, Mar 4, 2013 at 5:53 PM, Adam Hughes <[hidden email]> wrote:
Thanks for this explanation.  It helps a lot.

On Mon, Mar 4, 2013 at 5:48 PM, Peter Wang <[hidden email]> wrote:
On Mon, Mar 4, 2013 at 12:24 PM, Adam Hughes <[hidden email]> wrote:
You need to make sure that the data sources are getting added to the DataRange objects.

These are inherent DataRange attributes of the Plot() class, right?  Eg there is a single attribute in my plot called self.plot.index_range.sources?

Yes.
 
If so, should I just clear the list and update with each new data cycle, or is there a special way that these need updated?  IE a special method or way of doing it?

No, you just add the ArrayDataSource to it once.  There is no need to update the list of sources each cycle.  It's not always obvious from the object model, but the Chaco approach is to construct a visualization pipeline, and upstream elements inform downstream elements of the need to update via Traits events.  So, when you add the DataSource to a DataRange's .sources list, the DataRange hooks up listeners to the DataSource (see https://github.com/enthought/chaco/blob/master/chaco/data_range_1d.py#L375).  Whenever you update the data values in the DataSource, the DataRange send a "data_changed" event, which ultimately bubbles up to invalidating the current rendering and requesting a redraw from the underlying GUI system.

-Peter

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




--
Adam Hughes
Physics Ph.D Candidate
George Washington University



--
Adam Hughes
Physics Ph.D Candidate
George Washington University

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