Changeset 1c94a9f1 in sasview for guitools


Ignore:
Timestamp:
Jul 8, 2008 11:40:33 AM (16 years ago)
Author:
Mathieu Doucet <doucetm@…>
Branches:
master, ESS_GUI, ESS_GUI_Docs, ESS_GUI_batch_fitting, ESS_GUI_bumps_abstraction, ESS_GUI_iss1116, ESS_GUI_iss879, ESS_GUI_iss959, ESS_GUI_opencl, ESS_GUI_ordering, ESS_GUI_sync_sascalc, costrafo411, magnetic_scatt, release-4.1.1, release-4.1.2, release-4.2.2, release_4.0.1, ticket-1009, ticket-1094-headless, ticket-1242-2d-resolution, ticket-1243, ticket-1249, ticket885, unittest-saveload
Children:
792db7d5
Parents:
9a3adab
Message:

Fixed all sorts of bugs: replotting problems, bad logic in rescaling function, removed buggy field in dialog box, improved usability for linear fit.

Location:
guitools
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • guitools/PlotPanel.py

    ra17ffdf r1c94a9f1  
    150150        self.axes = [self.subplot] 
    151151         
     152        ## Fit dialog 
     153        self._fit_dialog = None 
     154         
    152155        # Interactor 
    153156        self.connect = BindArtist(self.subplot.figure) 
     
    163166        self.xminView=0.0 
    164167        self.xmaxView=0.0 
     168        self._scale_xlo = None 
     169        self._scale_xhi = None 
     170        self._scale_ylo = None 
     171        self._scale_yhi = None 
    165172        self.Avalue=None 
    166173        self.Bvalue=None 
     
    224231                self.dragHelper(0,0) 
    225232                 
     233    def _offset_graph(self): 
     234        """ 
     235             Zoom and offset the graph to the last known  
     236             settings  
     237        """ 
     238 
     239        for ax in self.axes: 
     240            if self._scale_xhi is not None and self._scale_xlo is not None: 
     241                ax.set_xlim(self._scale_xlo, self._scale_xhi) 
     242            if self._scale_yhi is not None and self._scale_ylo is not None: 
     243                ax.set_ylim(self._scale_ylo, self._scale_yhi) 
     244             
     245             
    226246    def dragHelper(self,xdelta,ydelta): 
    227247        """ dragging occurs here""" 
     
    238258                    newhi= math.log10(hi)-xdelta 
    239259            if self.xscale=='log': 
     260                self._scale_xlo = math.pow(10,newlo) 
     261                self._scale_xhi = math.pow(10,newhi) 
    240262                ax.set_xlim(math.pow(10,newlo),math.pow(10,newhi)) 
    241263            else: 
     264                self._scale_xlo = newlo 
     265                self._scale_xhi = newhi 
    242266                ax.set_xlim(newlo,newhi) 
    243267            #print "new lo %f and new hi %f"%(newlo,newhi) 
     
    253277                #print "new lo %f and new hi %f"%(newlo,newhi) 
    254278            if  self.yscale=='log': 
     279                self._scale_ylo = math.pow(10,newlo) 
     280                self._scale_yhi = math.pow(10,newhi) 
    255281                ax.set_ylim(math.pow(10,newlo),math.pow(10,newhi)) 
    256282            else: 
     283                self._scale_ylo = newlo 
     284                self._scale_yhi = newhi 
    257285                ax.set_ylim(newlo,newhi) 
    258286        self.canvas.draw_idle() 
     
    268296        self.xminView=0.0 
    269297        self.xmaxView=0.0 
     298        self._scale_xlo = None 
     299        self._scale_xhi = None 
     300        self._scale_ylo = None 
     301        self._scale_yhi = None 
    270302        self.Avalue=None 
    271303        self.Bvalue=None 
     
    287319            lo,hi = _rescale(lo,hi,step,pt=event.xdata,scale=ax.get_xscale()) 
    288320            if not self.xscale=='log' or lo>0: 
     321                self._scale_xlo = lo 
     322                self._scale_xhi = hi 
    289323                ax.set_xlim((lo,hi)) 
    290324 
     
    292326            lo,hi = _rescale(lo,hi,step,pt=event.ydata,scale=ax.get_yscale()) 
    293327            if not self.yscale=='log' or lo>0: 
     328                self._scale_ylo = lo 
     329                self._scale_yhi = hi 
    294330                ax.set_ylim((lo,hi)) 
    295331        else: 
     
    309345                lo,hi = _rescale(lo,hi,step,bal=xdata,scale=ax.get_xscale()) 
    310346                if not self.xscale=='log' or lo>0: 
     347                    self._scale_xlo = lo 
     348                    self._scale_xhi = hi 
    311349                    ax.set_xlim((lo,hi)) 
    312350            if ydata is not None: 
     
    314352                lo,hi = _rescale(lo,hi,step,bal=ydata,scale=ax.get_yscale()) 
    315353                if not self.yscale=='log' or lo>0: 
     354                    self._scale_ylo = lo 
     355                    self._scale_yhi = hi 
    316356                    ax.set_ylim((lo,hi)) 
    317357                
     
    354394        """ 
    355395            when clicking on linear Fit on context menu , display Fitting Dialog 
     396            @param plot: PlotPanel owning the graph 
    356397        """ 
    357398        from fitDialog import LinearFit 
    358399         
    359         dlg = LinearFit( None, plot, self.onFitDisplay,self.returnTrans, -1, 'Linear Fit') 
    360         
    361         if (self.xmin !=0.0 )and ( self.xmax !=0.0)\ 
    362             and(self.xminView !=0.0 )and ( self.xmaxView !=0.0): 
    363             dlg.setFitRange(self.xminView,self.xmaxView,self.xmin,self.xmax) 
    364         dlg.ShowModal()  
     400        if self._fit_dialog is not None: 
     401            return 
     402         
     403        self._fit_dialog = LinearFit( None, plot, self.onFitDisplay,self.returnTrans, -1, 'Linear Fit') 
     404         
     405        # Set the zoom area  
     406        if self._scale_xhi is not None and self._scale_xlo is not None: 
     407            self._fit_dialog.set_fit_region(self._scale_xlo, self._scale_xhi) 
     408         
     409        # Register the close event 
     410        self._fit_dialog.register_close(self._linear_fit_close) 
     411         
     412        # Show a non-model dialog 
     413        self._fit_dialog.Show()  
     414 
     415    def _linear_fit_close(self): 
     416        """ 
     417            A fit dialog was closed 
     418        """ 
     419        self._fit_dialog = None 
     420         
    365421 
    366422    def _onProperties(self, event): 
     
    369425            The user selects a transformation for x or y value and a new plot is displayed 
    370426        """ 
     427        if self._fit_dialog is not None: 
     428            self._fit_dialog.Destroy() 
     429            self._fit_dialog = None 
     430             
    371431        list =[] 
    372432        list = self.graph.returnPlottable() 
     
    641701        return self.symbollist[s%len(self.symbollist)] 
    642702    
    643     def _replot(self): 
     703    def _replot(self, remove_fit=False): 
    644704        """ 
    645705            Rescale the plottables according to the latest 
    646706            user selection and update the plot 
     707             
     708            @param remove_fit: Fit line will be removed if True 
    647709        """ 
    648710        self.graph.reset_scale() 
    649         self._onEVT_FUNC_PROPERTY(remove_fit=False) 
     711        self._onEVT_FUNC_PROPERTY(remove_fit=remove_fit) 
    650712         
    651713        #TODO: Why do we have to have the following line? 
     
    660722              and set the scale     
    661723        """  
     724        # The logic should be in the right order 
     725        # Delete first, and then get the whole list... 
     726        if remove_fit: 
     727            self.graph.delete(self.fit_result) 
     728             
    662729        list =[] 
    663730        list = self.graph.returnPlottable() 
    664731         
    665         if remove_fit: 
    666             self.fit_result.x =[]   
    667             self.fit_result.y =[]  
    668             self.fit_result.dx=None 
    669             self.fit_result.dy=None 
    670             self.graph.delete(self.fit_result) 
     732        # Changing the scale might be incompatible with 
     733        # currently displayed data (for instance, going  
     734        # from ln to log when all plotted values have 
     735        # negative natural logs).  
     736        # Go linear and only change the scale at the end. 
     737        self.set_xscale("linear") 
     738        self.set_yscale("linear") 
     739        _xscale = 'linear' 
     740        _yscale = 'linear' 
     741         
    671742         
    672743        for item in list: 
     744            print item.name 
    673745            item.setLabel(self.xLabel,self.yLabel) 
    674746            if ( self.xLabel=="x" ): 
    675747                item.transformX(transform.toX,transform.errToX) 
    676                 self.set_xscale("linear") 
    677748                name, units = item.get_xaxis() 
    678749                self.graph.xaxis("%s" % name,  "%s" % units) 
     
    681752            if ( self.xLabel=="x^(2)" ): 
    682753                item.transformX(transform.toX2,transform.errToX2) 
    683                 self.set_xscale('linear') 
    684754                name, units = item.get_xaxis() 
    685755                units=convertUnit(2,units)  
     
    689759            if (self.xLabel=="log10(x)" ): 
    690760                item.transformX(transform.toX_pos,transform.errToX_pos) 
    691                 self.set_xscale("log") 
     761                _xscale = 'log' 
    692762                name, units = item.get_xaxis()  
    693763                self.graph.xaxis("\log_{10}\ \  (%s)" % name,  "%s" % units) 
     
    696766            if ( self.yLabel=="ln(y)" ): 
    697767                item.transformY(transform.toLogX,transform.errToLogX) 
    698                 self.set_yscale("linear") 
    699768                name, units = item.get_yaxis() 
    700769                self.graph.yaxis("\log\ \ %s" % name,  "%s" % units) 
     
    703772            if ( self.yLabel=="y" ): 
    704773                item.transformY(transform.toX,transform.errToX) 
    705                 self.set_yscale("linear") 
    706774                name, units = item.get_yaxis() 
    707775                self.graph.yaxis("%s" % name,  "%s" % units) 
     
    710778            if ( self.yLabel=="log10(y)" ):  
    711779                item.transformY(transform.toX_pos,transform.errToX_pos) 
    712                 self.set_yscale("log")   
     780                _yscale = 'log'   
    713781                name, units = item.get_yaxis() 
    714782                self.graph.yaxis("\log_{10}\ \ (%s)" % name,  "%s" % units) 
     
    717785            if ( self.yLabel=="y^(2)" ): 
    718786                item.transformY( transform.toX2,transform.errToX2 )     
    719                 self.set_yscale("linear") 
    720787                name, units = item.get_yaxis() 
    721788                units=convertUnit(2,units)  
     
    725792            if ( self.yLabel =="1/y"): 
    726793                item.transformY(transform.toOneOverX,transform.errOneOverX ) 
    727                 self.set_yscale("linear") 
    728794                name, units = item.get_yaxis() 
    729795                units=convertUnit(-1,units) 
     
    732798            if ( self.yLabel =="1/sqrt(y)" ): 
    733799                item.transformY(transform.toOneOverSqrtX,transform.errOneOverSqrtX ) 
    734                 self.set_yscale("linear") 
    735800                name, units = item.get_yaxis() 
    736801                units=convertUnit(-0.5,units) 
     
    739804            if ( self.yLabel =="ln(y*x)"): 
    740805                item.transformY( transform.toLogXY,transform.errToLogXY) 
    741                 self.set_yscale("linear") 
    742806                yname, yunits = item.get_yaxis() 
    743807                xname, xunits = item.get_xaxis() 
     
    747811            if ( self.yLabel =="ln(y*x^(2))"): 
    748812                item.transformY( transform.toLogYX2,transform.errToLogYX2) 
    749                 self.set_yscale("linear") 
    750813                yname, yunits = item.get_yaxis() 
    751814                xname, xunits = item.get_xaxis()  
     
    756819            if ( self.yLabel =="ln(y*x^(4))"): 
    757820                item.transformY(transform.toLogYX4,transform.errToLogYX4) 
    758                 self.set_yscale("linear") 
    759821                yname, yunits = item.get_yaxis() 
    760822                xname, xunits = item.get_xaxis() 
     
    765827                 
    766828                item.transformX(transform.toX2,transform.errToX2) 
    767                 self.set_xscale('linear') 
    768829                name, units = item.get_xaxis() 
    769830                units = convertUnit(2,units)  
     
    772833                 
    773834                item.transformY(transform.toLogX,transform.errToLogX ) 
    774                 self.set_yscale("linear") 
    775835                name, units = item.get_yaxis() 
    776836                self.graph.yaxis("\log\ \ %s" % name,  "%s" % units) 
     
    779839            item.transformView() 
    780840             
    781           
    782841        self.resetFitView()    
    783842        self.prevXtrans = self.xLabel  
    784843        self.prevYtrans = self.yLabel   
    785844        self.graph.render(self) 
     845         
     846        self.set_xscale(_xscale) 
     847        self.set_yscale(_yscale) 
     848          
    786849        self.subplot.figure.canvas.draw_idle() 
    787850         
     
    824887        self.graph.add(self.fit_result)  
    825888        self.graph.render(self) 
     889        self._offset_graph() 
    826890        self.subplot.figure.canvas.draw_idle() 
    827891         
  • guitools/fitDialog.py

    rad8bcd6 r1c94a9f1  
    2727class LinearFit(wx.Dialog): 
    2828    def __init__(self, parent, plottable, push_data,transform, id, title): 
    29         wx.Dialog.__init__(self, parent, id, title, size=(400, 380)) 
     29        wx.Dialog.__init__(self, parent, id, title, size=(400, 350)) 
    3030 
    3131        """ 
     
    3535        self.parent = parent 
    3636        self.transform = transform 
     37         
     38        # Registered owner for close event 
     39        self._registered_close = None 
    3740         
    3841        #dialog panel self call function to plot the fitting function 
     
    6568        self.xmaxFit  = wx.TextCtrl(self,-1,size=(_BOX_WIDTH,20)) 
    6669        self.xmaxFit.SetToolTipString("Enter the maximum value on the x-axis to be included in the fit.") 
    67         self.xminTransFit = wx.TextCtrl(self,-1,size=(_BOX_WIDTH,20)) 
    68         self.xminTransFit.SetToolTipString("Minimum value on the x-axis for the plotted data.") 
    69         self.xmaxTransFit = wx.TextCtrl(self,-1,size=(_BOX_WIDTH,20)) 
    70         self.xmaxTransFit.SetToolTipString("Maximum value on the x-axis for the plotted data.") 
    7170        self.initXmin = wx.TextCtrl(self,-1,size=(_BOX_WIDTH,20)) 
    72         self.initXmin.SetToolTipString("Minimum value available on the x-axis for the plotted data.") 
     71        self.initXmin.SetToolTipString("Minimum value on the x-axis for the plotted data.") 
    7372        self.initXmax = wx.TextCtrl(self,-1,size=(_BOX_WIDTH,20)) 
    74         self.initXmax.SetToolTipString("Maximum value available on the x-axis for the plotted data.") 
     73        self.initXmax.SetToolTipString("Maximum value on the x-axis for the plotted data.") 
    7574 
    7675        # Make the info box not editable 
    7776        #_BACKGROUND_COLOR = '#ffdf85' 
    7877        _BACKGROUND_COLOR = self.GetBackgroundColour() 
    79         self.xminTransFit.SetEditable(False) 
    80         self.xminTransFit.SetBackgroundColour(_BACKGROUND_COLOR) 
    81         self.xmaxTransFit.SetEditable(False) 
    82         self.xmaxTransFit.SetBackgroundColour(_BACKGROUND_COLOR) 
    8378        self.initXmin.SetEditable(False) 
    8479        self.initXmin.SetBackgroundColour(_BACKGROUND_COLOR) 
     
    9388        self.btFit.SetToolTipString("Perform fit.") 
    9489        self.btClose =wx.Button(self, wx.ID_CANCEL,'Close') 
     90        self.btClose.Bind(wx.EVT_BUTTON, self._on_close) 
    9591         
    9692        # Intro 
     
    136132        iy += 1 
    137133        ix = 0 
    138         sizer.Add(wx.StaticText(self, -1, 'Maximum range'),(iy, ix),(1,1),\ 
     134        sizer.Add(wx.StaticText(self, -1, 'Maximum range (linear scale)'),(iy, ix),(1,1),\ 
    139135                   wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15) 
    140136        ix +=1 
     
    147143        ix = 0 
    148144        sizer.Add(wx.StaticText(self, -1, 'Fit range of '+self.xLabel),(iy, ix),(1,1),\ 
    149                    wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15) 
    150         ix += 1 
    151         sizer.Add(self.xminTransFit, (iy, ix),(1,1),\ 
    152                    wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
    153         ix += 2 
    154         sizer.Add(self.xmaxTransFit, (iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
    155        
    156         iy += 1 
    157         ix = 0 
    158         sizer.Add(wx.StaticText(self, -1, 'Fit range of x'),(iy, ix),(1,1),\ 
    159145                   wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15) 
    160146        ix += 1 
     
    216202            self.tcChi.SetLabel(format_number(self.Chivalue)) 
    217203        if self.plottable.x !=[]: 
    218             self.mini =min(self.plottable.x) 
    219             self.maxi =max(self.plottable.x) 
    220204            #store the values of View in self.x,self.y,self.dx,self.dy 
    221205            self.x,self.y,self.dx,self.dy= self.plottable.returnValuesOfView() 
    222206             
    223              
    224             self.xminTransFit.SetLabel(format_number(min(self.x))) 
    225             self.xmaxTransFit.SetLabel(format_number(max(self.x))) 
    226              
    227             self.initXmin.SetValue(format_number(self.mini)) 
    228             self.initXmax.SetValue(format_number(self.maxi)) 
     207            self.mini =min(self.x) 
     208            self.maxi =max(self.x) 
     209             
     210             
     211            self.initXmin.SetValue(format_number(min(self.plottable.x))) 
     212            self.initXmax.SetValue(format_number(max(self.plottable.x))) 
    229213             
    230214            self.xminFit.SetLabel(format_number(self.mini)) 
     
    232216         
    233217       
     218    def register_close(self, owner): 
     219        """ 
     220            Method to register the close event to a parent 
     221            window that needs notification when the dialog 
     222            is closed 
     223            @param owner: parent window 
     224        """ 
     225        self._registered_close = owner 
     226         
     227    def _on_close(self, event): 
     228        """ 
     229            Close event.  
     230            Notify registered owner if available. 
     231        """ 
     232        event.Skip() 
     233        if self._registered_close is not None: 
     234            self._registered_close() 
     235         
    234236    def _onFit(self ,event): 
    235237        """ 
     
    252254            if(self.checkFitValues(self.xminFit) == True): 
    253255                #Check if the field of Fit Dialog contain values and use the x max and min of the user 
    254                 xmin,xmax = self._checkVal(self.xminFit.GetValue(),self.xmaxFit.GetValue()) 
    255                  
    256                 xminView=self.floatTransform(xmin) 
    257                 xmaxView=self.floatTransform(xmax) 
    258                 if (self.xLabel=="log10(x)"): 
    259                     self.xminTransFit.SetValue(format_number(math.log10(xminView))) 
    260                     self.xmaxTransFit.SetValue(format_number(math.log10(xmaxView))) 
    261                 else: 
    262                     self.xminTransFit.SetValue(format_number(xminView)) 
    263                     self.xmaxTransFit.SetValue(format_number(xmaxView)) 
     256                xminView,xmaxView = self._checkVal(self.xminFit.GetValue(),self.xmaxFit.GetValue()) 
     257                xmin = self.floatInvTransform(xminView) 
     258                xmax = self.floatInvTransform(xmaxView) 
     259                 
     260                 
    264261                # Store the transformed values of view x, y,dy in variables  before the fit 
    265262                if  self.yLabel.lower() == "log10(y)": 
     
    402399             not in x 
    403400        """ 
     401        #TODO: refactor this with proper object-oriented design 
     402        # This code stinks. 
     403         
    404404        if ( self.xLabel=="x" ): 
    405405            return transform.toX(x) 
     
    413413            else: 
    414414                raise ValueError,"cannot compute log of a negative number" 
     415             
     416    def floatInvTransform(self,x): 
     417        """ 
     418             transform a float.It is use to determine the x.View min and x.View max for values 
     419             not in x 
     420        """ 
     421        #TODO: refactor this. This is just a hack to make the 
     422        # functionality work without rewritting the whole code 
     423        # with good design (which really should be done...). 
     424         
     425        if ( self.xLabel=="x^(2)" ):  
     426            return math.sqrt(x) 
     427         
     428        elif (self.xLabel=="log10(x)" ): 
     429            return math.pow(10, x) 
     430         
     431        return x 
    415432             
    416433    def checkFitValues(self,item): 
     
    438455        self.xminFit.SetValue(format_number(xmin)) 
    439456        self.xmaxFit.SetValue(format_number(xmax)) 
    440         self.xminTransFit.SetValue(format_number(xminTrans)) 
    441         self.xmaxTransFit.SetValue(format_number(xmaxTrans)) 
    442          
     457         
     458    def set_fit_region(self, xmin, xmax): 
     459        """ 
     460            Set the fit region 
     461            @param xmin: minimum x-value to be included in fit 
     462            @param xmax: maximum x-value to be included in fit  
     463        """ 
     464        # Check values 
     465        try: 
     466            float(xmin) 
     467            float(xmax) 
     468        except: 
     469            raise ValueError, "LinearFit.set_fit_region: fit range must be floats" 
     470        self.xminFit.SetValue(format_number(xmin)) 
     471        self.xmaxFit.SetValue(format_number(xmax)) 
    443472   
    444473class MyApp(wx.App): 
  • guitools/fittings.py

    r5789654 r1c94a9f1  
    6868    p = [param() for param in pars] 
    6969    out, cov_x, info, mesg, success = optimize.leastsq(f, p, full_output=1, warning=True) 
    70     print info, mesg, success 
    7170    # Calculate chi squared 
    7271    if len(pars)>1: 
Note: See TracChangeset for help on using the changeset viewer.