source: sasview/prview/perspectives/pr/pr.py @ 52725d6

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalccostrafo411magnetic_scattrelease-4.1.1release-4.1.2release-4.2.2release_4.0.1ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249ticket885unittest-saveload
Last change on this file since 52725d6 was 8994b6b, checked in by Gervaise Alina <gervyh@…>, 14 years ago

rewmove unused method

  • Property mode set to 100644
File size: 47.5 KB
RevLine 
[9ff861b]1
[7116b6e0]2################################################################################
3#This software was developed by the University of Tennessee as part of the
4#Distributed Data Analysis of Neutron Scattering Experiments (DANSE)
5#project funded by the US National Science Foundation.
6#
7#See the license text in license.txt
8#
9#copyright 2009, University of Tennessee
10################################################################################
[9ff861b]11
12
[f3d51f6]13# Make sure the option of saving each curve is available
14# Use the I(q) curve as input and compare the output to P(r)
15
16import os
[4a5de6f]17import sys
[f3d51f6]18import wx
[aa4b8379]19import logging
[302510b]20import time
[75df58b]21import copy
22import math
23import numpy
24import pylab
25from sans.guiframe.dataFitting import Data1D
26from sans.guiframe.dataFitting import Theory1D
27from sans.guiframe.events import NewPlotEvent
28from sans.guiframe.events import StatusEvent   
29
[f3d51f6]30from sans.pr.invertor import Invertor
[aab8ad7]31from DataLoader.loader import Loader
[75df58b]32from DataLoader.data_info import Data1D as LoaderData1D
[80d2872]33import DataLoader
[af91b68]34from pr_widgets import load_error
[75df58b]35from sans.guiframe.plugin_base import PluginBase
[f3d51f6]36
[0d88a09]37
[f1181977]38PR_FIT_LABEL       = r"$P_{fit}(r)$"
39PR_LOADED_LABEL    = r"$P_{loaded}(r)$"
40IQ_DATA_LABEL      = r"$I_{obs}(q)$"
41IQ_FIT_LABEL       = r"$I_{fit}(q)$"
42IQ_SMEARED_LABEL   = r"$I_{smeared}(q)$"
[aa4b8379]43
[75df58b]44#import wx.lib
45#(NewPrFileEvent, EVT_PR_FILE) = wx.lib.newevent.NewEvent()
46
[aa4b8379]47
48
[3e41f43]49class Plugin(PluginBase):
[7116b6e0]50    """
51    """
[b659551]52    DEFAULT_ALPHA = 0.0001
53    DEFAULT_NFUNC = 10
54    DEFAULT_DMAX  = 140.0
55   
[d2ee6f6]56    def __init__(self, standalone=True):
[3e41f43]57        PluginBase.__init__(self, name="Pr inversion", standalone=standalone)
[f3d51f6]58        ## Simulation window manager
59        self.simview = None
[3e41f43]60       
[f3d51f6]61        ## State data
[b659551]62        self.alpha      = self.DEFAULT_ALPHA
63        self.nfunc      = self.DEFAULT_NFUNC
64        self.max_length = self.DEFAULT_DMAX
[634f1cf]65        self.q_min      = None
66        self.q_max      = None
[a4bd2ac]67        self.has_bck    = False
[2a92852]68        self.slit_height = 0
69        self.slit_width  = 0
[f3d51f6]70        ## Remember last plottable processed
71        self.last_data  = "sphere_60_q0_2.txt"
[0bae207]72        self._current_file_data = None
[f3d51f6]73        ## Time elapsed for last computation [sec]
74        # Start with a good default
75        self.elapsed = 0.022
[aa4b8379]76        self.iq_data_shown = False
[f3d51f6]77       
78        ## Current invertor
79        self.invertor    = None
[3fd1ebc]80        self.pr          = None
[feb21d8]81        # Copy of the last result in case we need to display it.
82        self._last_pr    = None
83        self._last_out   = None
84        self._last_cov   = None
[f3d51f6]85        ## Calculation thread
86        self.calc_thread = None
87        ## Estimation thread
88        self.estimation_thread = None
89        ## Result panel
90        self.control_panel = None
91        ## Currently views plottable
92        self.current_plottable = None
[b659551]93        ## Number of P(r) points to display on the output plot
94        self._pr_npts = 51
[aa4b8379]95        ## Flag to let the plug-in know that it is running standalone
[d2ee6f6]96        self.standalone = standalone
[feb21d8]97        self._normalize_output = False
98        self._scale_output_unity = False
[aa4b8379]99       
[f1181977]100        ## List of added P(r) plots
101        self._added_plots = {}
102        self._default_Iq  = {}
103       
[6f1f129]104        # Associate the inversion state reader with .prv files
105        from DataLoader.loader import Loader
106        from inversion_state import Reader
107         
[0d88a09]108        # Create a CanSAS/Pr reader
109        self.state_reader = Reader(self.set_state)
[6f1f129]110        l = Loader()
[410aad8]111        l.associate_file_reader('.prv', self.state_reader)
[b35d3d1]112        l.associate_file_reader(".sav", self.state_reader)
[6f1f129]113               
[aa4b8379]114        # Log startup
115        logging.info("Pr(r) plug-in started")
116       
[410aad8]117    def set_state(self, state, datainfo=None):
[6f1f129]118        """
[7116b6e0]119        Call-back method for the inversion state reader.
120        This method is called when a .prv file is loaded.
121       
122        :param state: InversionState object
123        :param datainfo: Data1D object [optional]
124       
[6f1f129]125        """
[410aad8]126        try:
[0d88a09]127            if datainfo is None:
128                raise RuntimeError, "Pr.set_state: datainfo parameter cannot be None in standalone mode"
[302510b]129
[0d88a09]130            # Ensuring that plots are coordinated correctly
131            t = time.localtime(datainfo.meta_data['prstate'].timestamp)
132            time_str = time.strftime("%b %d %H:%M", t)
133           
134            # Check that no time stamp is already appended
135            max_char = datainfo.meta_data['prstate'].file.find("[")
136            if max_char < 0:
137                max_char = len(datainfo.meta_data['prstate'].file)
138           
139            datainfo.meta_data['prstate'].file = datainfo.meta_data['prstate'].file[0:max_char] +' [' + time_str + ']'
140            datainfo.filename = datainfo.meta_data['prstate'].file
[410aad8]141               
[0d88a09]142            self.current_plottable = datainfo
143            self.current_plottable.group_id = datainfo.meta_data['prstate'].file
144           
[410aad8]145            # Load the P(r) results
146            self.control_panel.set_state(state)
147                       
148            # Make sure the user sees the P(r) panel after loading
149            self.parent.set_perspective(self.perspective)           
150
151        except:
152            logging.error("prview.set_state: %s" % sys.exc_value)
[f3d51f6]153
[8994b6b]154 
[119a11d]155    def help(self, evt):
156        """
[7116b6e0]157        Show a general help dialog.
158       
159        :TODO: replace the text with a nice image
160       
[119a11d]161        """
162        from inversion_panel import HelpDialog
163        dialog = HelpDialog(None, -1)
164        if dialog.ShowModal() == wx.ID_OK:
165            dialog.Destroy()
166        else:
167            dialog.Destroy()
168   
[f3d51f6]169    def _fit_pr(self, evt):
[7116b6e0]170        """
171        """
[f3d51f6]172        from sans.pr.invertor import Invertor
[75df58b]173           
174        from danse.common.plottools import Data1D as PlotData1D
175        from danse.common.plottools import Theory1D as Theory1D
[f3d51f6]176       
177        # Generate P(r) for sphere
178        radius = 60.0
179        d_max  = 2*radius
180       
181        r = pylab.arange(0.01, d_max, d_max/51.0)
182        M = len(r)
183        y = numpy.zeros(M)
184        pr_err = numpy.zeros(M)
185       
186        sum = 0.0
187        for j in range(M):
188            value = self.pr_theory(r[j], radius)
189            sum += value
190            y[j] = value
191            pr_err[j] = math.sqrt(y[j])
192
193        y = y/sum*d_max/len(r)
194
195        # Perform fit
196        pr = Invertor()
197        pr.d_max = d_max
198        pr.alpha = 0
199        pr.x = r
200        pr.y = y
201        pr.err = pr_err
202        out, cov = pr.pr_fit()
203        for i in range(len(out)):
204            print "%g +- %g" % (out[i], math.sqrt(cov[i][i]))
205
206        # Show input P(r)
[75df58b]207        new_plot = PlotData1D(pr.x, pr.y, dy=pr.err)
[f3d51f6]208        new_plot.name = "P_{obs}(r)"
209        new_plot.xaxis("\\rm{r}", 'A')
210        new_plot.yaxis("\\rm{P(r)} ","cm^{-3}")
[75df58b]211        print "_fit_pr"
[f3d51f6]212        wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot, title="Pr"))
213
214        # Show P(r) fit
215        self.show_pr(out, pr)
216       
217        # Show I(q) fit
218        q = pylab.arange(0.001, 0.1, 0.01/51.0)
219        self.show_iq(out, pr, q)
220       
221    def show_shpere(self, x, radius=70.0, x_range=70.0):
[7116b6e0]222        """
223        """
[75df58b]224        from danse.common.plottools import Theory1D as PlotTheory1D
[f3d51f6]225        # Show P(r)
226        y_true = numpy.zeros(len(x))
227
228        sum_true = 0.0
229        for i in range(len(x)):
230            y_true[i] = self.pr_theory(x[i], radius)           
231            sum_true += y_true[i]
232           
233        y_true = y_true/sum_true*x_range/len(x)
234       
235        # Show the theory P(r)
[75df58b]236        new_plot = PlotTheory1D(x, y_true)
[f3d51f6]237        new_plot.name = "P_{true}(r)"
238        new_plot.xaxis("\\rm{r}", 'A')
239        new_plot.yaxis("\\rm{P(r)} ","cm^{-3}")
240       
241        #Put this call in plottables/guitools   
242        wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot, title="Sphere P(r)"))
[75df58b]243       
[f3d51f6]244       
[b659551]245    def get_npts(self):
246        """
[7116b6e0]247        Returns the number of points in the I(q) data
[b659551]248        """
249        try:
250            return len(self.pr.x)
251        except:
252            return 0
253       
[f3d51f6]254    def show_iq(self, out, pr, q=None):
[7116b6e0]255        """
[75df58b]256        """ 
257        from danse.common.plottools import Theory1D as PlotTheory1D
[f3d51f6]258
259        qtemp = pr.x
260        if not q==None:
261            qtemp = q
262
263        # Make a plot
264        maxq = -1
265        for q_i in qtemp:
266            if q_i>maxq:
267                maxq=q_i
268               
[634f1cf]269        minq = 0.001
270       
271        # Check for user min/max
272        if not pr.q_min==None:
273            minq = pr.q_min
274        if not pr.q_max==None:
275            maxq = pr.q_max
276               
277        x = pylab.arange(minq, maxq, maxq/301.0)
[f3d51f6]278        y = numpy.zeros(len(x))
279        err = numpy.zeros(len(x))
280        for i in range(len(x)):
281            value = pr.iq(out, x[i])
282            y[i] = value
283            try:
284                err[i] = math.sqrt(math.fabs(value))
285            except:
286                err[i] = 1.0
287                print "Error getting error", value, x[i]
288               
[75df58b]289        new_plot = PlotTheory1D(x, y)
[2a92852]290        new_plot.name = IQ_FIT_LABEL
[f3d51f6]291        new_plot.xaxis("\\rm{Q}", 'A^{-1}')
292        new_plot.yaxis("\\rm{Intensity} ","cm^{-1}")
[d2ee6f6]293       
294        title = "I(q)"
295        # If we have a group ID, use it
296        if pr.info.has_key("plot_group_id"):
297            new_plot.group_id = pr.info["plot_group_id"]
298            title = pr.info["plot_group_id"]
299           
300        wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot, title=title))
[f3d51f6]301       
[2a92852]302        # If we have used slit smearing, plot the smeared I(q) too
303        if pr.slit_width>0 or pr.slit_height>0:
304            x = pylab.arange(minq, maxq, maxq/301.0)
305            y = numpy.zeros(len(x))
306            err = numpy.zeros(len(x))
307            for i in range(len(x)):
308                value = pr.iq_smeared(out, x[i])
309                y[i] = value
310                try:
311                    err[i] = math.sqrt(math.fabs(value))
312                except:
313                    err[i] = 1.0
314                    print "Error getting error", value, x[i]
315                   
316            new_plot = Theory1D(x, y)
317            new_plot.name = IQ_SMEARED_LABEL
318            new_plot.xaxis("\\rm{Q}", 'A^{-1}')
319            new_plot.yaxis("\\rm{Intensity} ","cm^{-1}")
[f0ff8d65]320            # If we have a group ID, use it
321            if pr.info.has_key("plot_group_id"):
322                new_plot.group_id = pr.info["plot_group_id"]
323            wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot, title=title))
[2a92852]324       
[f3d51f6]325       
[b659551]326    def _on_pr_npts(self, evt):
327        """
[7116b6e0]328        Redisplay P(r) with a different number of points
[b659551]329        """   
330        from inversion_panel import PrDistDialog
331        dialog = PrDistDialog(None, -1)
332        dialog.set_content(self._pr_npts)
333        if dialog.ShowModal() == wx.ID_OK:
334            self._pr_npts= dialog.get_content()
335            dialog.Destroy()
[feb21d8]336            self.show_pr(self._last_out, self._last_pr, self._last_cov)
[b659551]337        else:
338            dialog.Destroy()
[f3d51f6]339       
340       
341    def show_pr(self, out, pr, cov=None):
[7116b6e0]342        """
[75df58b]343        """     
344        from danse.common.plottools import Data1D as PlotData1D
345        from danse.common.plottools import Theory1D as PlotTheory1D
[f3d51f6]346       
347        # Show P(r)
[b659551]348        x = pylab.arange(0.0, pr.d_max, pr.d_max/self._pr_npts)
[f3d51f6]349   
350        y = numpy.zeros(len(x))
351        dy = numpy.zeros(len(x))
352        y_true = numpy.zeros(len(x))
353
354        sum = 0.0
[feb21d8]355        pmax = 0.0
[dfb58f8]356        cov2 = numpy.ascontiguousarray(cov)
357       
[f3d51f6]358        for i in range(len(x)):
[dfb58f8]359            if cov2==None:
[f3d51f6]360                value = pr.pr(out, x[i])
361            else:
[dfb58f8]362                (value, dy[i]) = pr.pr_err(out, cov2, x[i])
[660b1e6]363            sum += value*pr.d_max/len(x)
[f3d51f6]364           
[feb21d8]365            # keep track of the maximum P(r) value
366            if value>pmax:
367                pmax = value
368               
369            y[i] = value
370               
371        if self._normalize_output==True:
372            y = y/sum
373            dy = dy/sum
374        elif self._scale_output_unity==True:
375            y = y/pmax
376            dy = dy/pmax
[f3d51f6]377       
[dfb58f8]378        if cov2==None:
[75df58b]379            new_plot = PlotTheory1D(x, y)
[f3d51f6]380        else:
[75df58b]381            new_plot = PlotData1D(x, y, dy=dy)
[f1181977]382        new_plot.name = PR_FIT_LABEL
[f3d51f6]383        new_plot.xaxis("\\rm{r}", 'A')
384        new_plot.yaxis("\\rm{P(r)} ","cm^{-3}")
[75df58b]385        new_plot.title = "P(r) fit"
[d2ee6f6]386        # Make sure that the plot is linear
387        new_plot.xtransform="x"
388        new_plot.ytransform="y"                 
[f3d51f6]389        wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot, title="P(r) fit"))
390       
391        return x, pr.d_max
392       
393               
[75df58b]394    def load(self, data):
[0bae207]395        """
[7116b6e0]396        Load data. This will eventually be replaced
397        by our standard DataLoader class.
[0bae207]398        """
399        class FileData:
400            x = None
401            y = None
402            err = None
403            path = None
404           
405            def __init__(self, path):
406                self.path = path
407               
[75df58b]408        self._current_file_data = FileData(data.path)
[0bae207]409       
[aab8ad7]410        # Use data loader to load file
[75df58b]411        #dataread = Loader().load(path)
412        dataread = data
[ceaf16e]413        # Notify the user if we could not read the file
414        if dataread is None:
415            raise RuntimeError, "Invalid data"
416           
[aab8ad7]417        x = None
418        y = None
419        err = None
420        if dataread.__class__.__name__ == 'Data1D':
421            x = dataread.x
422            y = dataread.y
423            err = dataread.dy
424        else:
[e43c012]425            if isinstance(dataread, list) and len(dataread)>0:
426                x = dataread[0].x
427                y = dataread[0].y
428                err = dataread[0].dy
429                msg = "PrView only allows a single data set at a time. "
430                msg += "Only the first data set was loaded." 
431                wx.PostEvent(self.parent, StatusEvent(status=msg))
432            else:
[6f1f129]433                if dataread is None:
434                    return x, y, err
[e43c012]435                raise RuntimeError, "This tool can only read 1D data"
[aab8ad7]436       
[0bae207]437        self._current_file_data.x = x
438        self._current_file_data.y = y
439        self._current_file_data.err = err
440        return x, y, err
441               
442    def load_columns(self, path = "sphere_60_q0_2.txt"):
443        """
[7116b6e0]444        Load 2- or 3- column ascii
[0bae207]445        """
[f3d51f6]446        import numpy, math, sys
447        # Read the data from the data file
448        data_x   = numpy.zeros(0)
449        data_y   = numpy.zeros(0)
450        data_err = numpy.zeros(0)
[b659551]451        scale    = None
452        min_err  = 0.0
[f3d51f6]453        if not path == None:
454            input_f = open(path,'r')
455            buff    = input_f.read()
456            lines   = buff.split('\n')
457            for line in lines:
458                try:
459                    toks = line.split()
460                    x = float(toks[0])
461                    y = float(toks[1])
[b659551]462                    if len(toks)>2:
463                        err = float(toks[2])
464                    else:
465                        if scale==None:
466                            scale = 0.05*math.sqrt(y)
467                            #scale = 0.05/math.sqrt(y)
468                            min_err = 0.01*y
469                        err = scale*math.sqrt(y)+min_err
470                        #err = 0
471                       
[4a5de6f]472                    data_x = numpy.append(data_x, x)
473                    data_y = numpy.append(data_y, y)
[b659551]474                    data_err = numpy.append(data_err, err)
[f3d51f6]475                except:
[b659551]476                    pass
[f3d51f6]477                   
[357b79b]478        if not scale==None:
479            message = "The loaded file had no error bars, statistical errors are assumed."
480            wx.PostEvent(self.parent, StatusEvent(status=message))
481        else:
482            wx.PostEvent(self.parent, StatusEvent(status=''))
483                       
[b659551]484        return data_x, data_y, data_err     
[f3d51f6]485       
[0bae207]486    def load_abs(self, path):
487        """
[7116b6e0]488        Load an IGOR .ABS reduced file
489       
490        :param path: file path
491       
492        :return: x, y, err vectors
493       
[0bae207]494        """
495        import numpy, math, sys
496        # Read the data from the data file
497        data_x   = numpy.zeros(0)
498        data_y   = numpy.zeros(0)
499        data_err = numpy.zeros(0)
500        scale    = None
501        min_err  = 0.0
502       
503        data_started = False
504        if not path == None:
505            input_f = open(path,'r')
506            buff    = input_f.read()
507            lines   = buff.split('\n')
508            for line in lines:
509                if data_started==True:
510                    try:
511                        toks = line.split()
512                        x = float(toks[0])
513                        y = float(toks[1])
514                        if len(toks)>2:
515                            err = float(toks[2])
516                        else:
517                            if scale==None:
518                                scale = 0.05*math.sqrt(y)
519                                #scale = 0.05/math.sqrt(y)
520                                min_err = 0.01*y
521                            err = scale*math.sqrt(y)+min_err
522                            #err = 0
523                           
524                        data_x = numpy.append(data_x, x)
525                        data_y = numpy.append(data_y, y)
526                        data_err = numpy.append(data_err, err)
527                    except:
528                        pass
529                elif line.find("The 6 columns")>=0:
530                    data_started = True     
531                   
532        if not scale==None:
533            message = "The loaded file had no error bars, statistical errors are assumed."
534            wx.PostEvent(self.parent, StatusEvent(status=message))
535        else:
536            wx.PostEvent(self.parent, StatusEvent(status=''))
537                       
538        return data_x, data_y, data_err     
539       
[f3d51f6]540    def pr_theory(self, r, R):
[7116b6e0]541        """ 
[f3d51f6]542        """
543        if r<=2*R:
544            return 12.0* ((0.5*r/R)**2) * ((1.0-0.5*r/R)**2) * ( 2.0 + 0.5*r/R )
545        else:
546            return 0.0
547
[660b1e6]548    def get_context_menu(self, graph=None):
[f3d51f6]549        """
[7116b6e0]550        Get the context menu items available for P(r)
551       
552        :param graph: the Graph object to which we attach the context menu
553       
554        :return: a list of menu items with call-back function
555       
[f3d51f6]556        """
[660b1e6]557        # Look whether this Graph contains P(r) data
[aa4b8379]558        #if graph.selected_plottable==IQ_DATA_LABEL:
[660b1e6]559        for item in graph.plottables:
[75df58b]560            if item.name == PR_FIT_LABEL:
561                #add_data_hint = "Load a data file and display it on this plot"
562                #["Add P(r) data",add_data_hint , self._on_add_data],
563                change_n_hint = "Change the number of"
564                change_n_hint += " points on the P(r) output"
565                change_n_label = "Change number of P(r) points"
566                m_list = [[change_n_label, change_n_hint , self._on_pr_npts]]
[aa4b8379]567
[75df58b]568                if self._scale_output_unity or self._normalize_output:
569                    hint = "Let the output P(r) keep the scale of the data"
570                    m_list.append(["Disable P(r) scaling", hint, 
[900c787]571                                   self._on_disable_scaling])
[75df58b]572                if not self._scale_output_unity:
[feb21d8]573                    m_list.append(["Scale P_max(r) to unity", 
574                                   "Scale P(r) so that its maximum is 1", 
575                                   self._on_scale_unity])
[75df58b]576                if not self._normalize_output:
[feb21d8]577                    m_list.append(["Normalize P(r) to unity", 
578                                   "Normalize the integral of P(r) to 1", 
579                                   self._on_normalize])
580                   
581                return m_list
[75df58b]582                #return [["Add P(r) data",
583                #"Load a data file and display it on this plot",
584                # self._on_add_data],
585                #       ["Change number of P(r) points",
586                # "Change the number of points on the P(r) output",
587                # self._on_pr_npts]]
[feb21d8]588
[75df58b]589            elif item.name == graph.selected_plottable:
590                    #TODO: we might want to check that the units are
591                    #     consistent with I(q) before allowing this menu item
592                if not self.standalone and \
593                issubclass(item.__class__, DataLoader.data_info.Data1D):
594                    return [["Compute P(r)", 
595                             "Compute P(r) from distribution", 
596                             self._on_context_inversion]]     
[660b1e6]597               
[aa4b8379]598        return []
[660b1e6]599
[feb21d8]600    def _on_disable_scaling(self, evt):
601        """
[7116b6e0]602        Disable P(r) scaling
603           
604        :param evt: Menu event
605       
[feb21d8]606        """
607        self._normalize_output = False
608        self._scale_output_unity = False
609        self.show_pr(self._last_out, self._last_pr, self._last_cov)
610       
[f1181977]611        # Now replot the original added data
612        for plot in self._added_plots:
613            self._added_plots[plot].y = numpy.copy(self._default_Iq[plot])
[75df58b]614            wx.PostEvent(self.parent, 
615                         NewPlotEvent(plot=self._added_plots[plot], 
616                                      title=self._added_plots[plot].name,
[f1181977]617                                                   update=True))       
618       
619        # Need the update flag in the NewPlotEvent to protect against
620        # the plot no longer being there...
621       
[feb21d8]622    def _on_normalize(self, evt):
623        """
[7116b6e0]624        Normalize the area under the P(r) curve to 1.
625        This operation is done for all displayed plots.
626       
627        :param evt: Menu event
628       
[feb21d8]629        """
630        self._normalize_output = True
631        self._scale_output_unity = False
632           
633        self.show_pr(self._last_out, self._last_pr, self._last_cov)
634       
[f1181977]635        # Now scale the added plots too
636        for plot in self._added_plots:
637            sum = numpy.sum(self._added_plots[plot].y)
638            npts = len(self._added_plots[plot].x)
639            sum *= self._added_plots[plot].x[npts-1]/npts
640            y = self._added_plots[plot].y/sum
641           
642            new_plot = Theory1D(self._added_plots[plot].x, y)
643            new_plot.name = self._added_plots[plot].name
644            new_plot.xaxis("\\rm{r}", 'A')
645            new_plot.yaxis("\\rm{P(r)} ","cm^{-3}")
646           
[75df58b]647            wx.PostEvent(self.parent, 
648                         NewPlotEvent(plot=new_plot, update=True,
649                                         title=self._added_plots[plot].name))
[f1181977]650       
[feb21d8]651    def _on_scale_unity(self, evt):
652        """
[7116b6e0]653        Scale the maximum P(r) value on each displayed plot to 1.
654       
655        :param evt: Menu event
656       
[feb21d8]657        """
658        self._scale_output_unity = True
659        self._normalize_output = False
660           
661        self.show_pr(self._last_out, self._last_pr, self._last_cov)
662       
[f1181977]663        # Now scale the added plots too
664        for plot in self._added_plots:
665            _max = 0
666            for y in self._added_plots[plot].y:
667                if y>_max: 
668                    _max = y
669            y = self._added_plots[plot].y/_max
670           
671            new_plot = Theory1D(self._added_plots[plot].x, y)
672            new_plot.name = self._added_plots[plot].name
673            new_plot.xaxis("\\rm{r}", 'A')
674            new_plot.yaxis("\\rm{P(r)} ","cm^{-3}")
675           
[75df58b]676            wx.PostEvent(self.parent, 
677                         NewPlotEvent(plot=new_plot, update=True,
678                                title=self._added_plots[plot].name))       
[f1181977]679       
680       
[660b1e6]681    def _on_add_data(self, evt):
682        """
[7116b6e0]683        Add a data curve to the plot
684       
685        :WARNING: this will be removed once guiframe.plotting has
686             its full functionality
[660b1e6]687        """
688        path = self.choose_file()
689        if path==None:
690            return
691       
[14d05ba]692        #x, y, err = self.parent.load_ascii_1D(path)
693        # Use data loader to load file
694        try:
695            dataread = Loader().load(path)
696            x = None
697            y = None
698            err = None
699            if dataread.__class__.__name__ == 'Data1D':
700                x = dataread.x
701                y = dataread.y
702                err = dataread.dy
703            else:
[e43c012]704                if isinstance(dataread, list) and len(dataread)>0:
705                    x = dataread[0].x
706                    y = dataread[0].y
707                    err = dataread[0].dy
708                    msg = "PrView only allows a single data set at a time. "
709                    msg += "Only the first data set was loaded." 
710                    wx.PostEvent(self.parent, StatusEvent(status=msg))
711                else:
[75df58b]712                    msg = "This tool can only read 1D data"
713                    wx.PostEvent(self.parent, StatusEvent(status=msg))
[e43c012]714                    return
715           
[14d05ba]716        except:
717            wx.PostEvent(self.parent, StatusEvent(status=sys.exc_value))
718            return
[660b1e6]719       
[f1181977]720        filename = os.path.basename(path)
721       
[b659551]722        #new_plot = Data1D(x, y, dy=err)
723        new_plot = Theory1D(x, y)
[f1181977]724        new_plot.name = filename
[660b1e6]725        new_plot.xaxis("\\rm{r}", 'A')
726        new_plot.yaxis("\\rm{P(r)} ","cm^{-3}")
727           
[f1181977]728        # Store a ref to the plottable for later use
729        self._added_plots[filename] = new_plot
730        self._default_Iq[filename]  = numpy.copy(y)
731       
732        wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot, title=filename))
[660b1e6]733       
734       
[f3d51f6]735
736    def start_thread(self):
[7116b6e0]737        """
738        """
[f3d51f6]739        from pr_thread import CalcPr
740        from copy import deepcopy
741       
742        # If a thread is already started, stop it
743        if self.calc_thread != None and self.calc_thread.isrunning():
744            self.calc_thread.stop()
745               
746        pr = self.pr.clone()
[75df58b]747        self.calc_thread = CalcPr(pr, self.nfunc,
748                                   error_func=self._thread_error, 
749                                   completefn=self._completed, updatefn=None)
[f3d51f6]750        self.calc_thread.queue()
751        self.calc_thread.ready(2.5)
752   
753    def _thread_error(self, error):
[7116b6e0]754        """
755        """
[f3d51f6]756        wx.PostEvent(self.parent, StatusEvent(status=error))
757   
[32dffae4]758    def _estimate_completed(self, alpha, message, elapsed):
[f3d51f6]759        """
[7116b6e0]760        Parameter estimation completed,
761        display the results to the user
762       
763        :param alpha: estimated best alpha
764        :param elapsed: computation time
765       
[f3d51f6]766        """
767        # Save useful info
768        self.elapsed = elapsed
769        self.control_panel.alpha_estimate = alpha
[32dffae4]770        if not message==None:
771            wx.PostEvent(self.parent, StatusEvent(status=str(message)))
[35adaf6]772           
773        self.perform_estimateNT()
774   
775
776   
777    def _estimateNT_completed(self, nterms, alpha, message, elapsed):
778        """
[7116b6e0]779        Parameter estimation completed,
780        display the results to the user
781       
782        :param alpha: estimated best alpha
783        :param nterms: estimated number of terms
784        :param elapsed: computation time
785       
[35adaf6]786        """
787        # Save useful info
788        self.elapsed = elapsed
789        self.control_panel.nterms_estimate = nterms
790        self.control_panel.alpha_estimate = alpha
791        if not message==None:
792            wx.PostEvent(self.parent, StatusEvent(status=str(message)))
[f3d51f6]793   
794    def _completed(self, out, cov, pr, elapsed):
795        """
[7116b6e0]796        Method called with the results when the inversion
797        is done
798       
799        :param out: output coefficient for the base functions
800        :param cov: covariance matrix
801        :param pr: Invertor instance
802        :param elapsed: time spent computing
803       
[f3d51f6]804        """
[dfb58f8]805        from copy import deepcopy
[f3d51f6]806        # Save useful info
807        self.elapsed = elapsed
[feb21d8]808        # Keep a copy of the last result
809        self._last_pr  = pr.clone()
810        self._last_out = out
811        self._last_cov = cov
812       
[b659551]813        # Save Pr invertor
814        self.pr = pr
815       
[75df58b]816        #message = "Computation completed in"
817        #message +=  %g seconds [chi2=%g]" % (elapsed, pr.chi2)
[d6113849]818        #wx.PostEvent(self.parent, StatusEvent(status=message))
[f3d51f6]819
[dfb58f8]820        cov = numpy.ascontiguousarray(cov)
821
[f3d51f6]822        # Show result on control panel
823        self.control_panel.chi2 = pr.chi2
824        self.control_panel.elapsed = elapsed
825        self.control_panel.oscillation = pr.oscillations(out)
826        #print "OSCILL", pr.oscillations(out)
[d6113849]827        #print "PEAKS:", pr.get_peaks(out)
[dfb58f8]828        self.control_panel.positive = pr.get_positive(out)
829        self.control_panel.pos_err  = pr.get_pos_err(out, cov)
[a4bd2ac]830        self.control_panel.rg = pr.rg(out)
831        self.control_panel.iq0 = pr.iq0(out)
832        self.control_panel.bck = pr.background
[f3d51f6]833       
[aa4b8379]834        if False:
[0bae207]835            for i in range(len(out)):
836                try:
[75df58b]837                    print "%d: %g +- %g" % (i, out[i],
838                                             math.sqrt(math.fabs(cov[i][i])))
[0bae207]839                except: 
840                    print sys.exc_value
841                    print "%d: %g +- ?" % (i, out[i])       
842       
843            # Make a plot of I(q) data
[aa4b8379]844            new_plot = Data1D(self.pr.x, self.pr.y, dy=self.pr.err)
[f1181977]845            new_plot.name = IQ_DATA_LABEL
[aa4b8379]846            new_plot.xaxis("\\rm{Q}", 'A^{-1}')
847            new_plot.yaxis("\\rm{Intensity} ","cm^{-1}")
848            #new_plot.group_id = "test group"
849            wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot, title="Iq"))
[f3d51f6]850               
851        # Show I(q) fit
852        self.show_iq(out, self.pr)
853       
854        # Show P(r) fit
[dfb58f8]855        x_values, x_range = self.show_pr(out, self.pr, cov) 
[f3d51f6]856       
857        # Popup result panel
[75df58b]858        #result_panel = InversionResults(self.parent,
859        #-1, style=wx.RAISED_BORDER)
[f3d51f6]860       
[75df58b]861    def show_data(self, path=None, data=None, reset=False):
[2a92852]862        """
[7116b6e0]863        Show data read from a file
864       
865        :param path: file path
866        :param reset: if True all other plottables will be cleared
867       
[2a92852]868        """
[75df58b]869        print "show_data", data.name
870        #if path is not None:
871        if data is not None:
[ea5551f]872            try:
[75df58b]873                #pr = self._create_file_pr(path)
874                pr = self._create_file_pr(data)
[ceaf16e]875            except:
[75df58b]876                status = "Problem reading data: %s" % sys.exc_value
[ceaf16e]877                wx.PostEvent(self.parent, StatusEvent(status=status))
878                raise RuntimeError, status
[6f1f129]879               
[ceaf16e]880            # If the file contains nothing, just return
881            if pr is None:
882                raise RuntimeError, "Loaded data is invalid"
883           
884            self.pr = pr
[75df58b]885       
[660b1e6]886        # Make a plot of I(q) data
[357b79b]887        if self.pr.err==None:
888            new_plot = Theory1D(self.pr.x, self.pr.y)
889        else:
890            new_plot = Data1D(self.pr.x, self.pr.y, dy=self.pr.err)
[f1181977]891        new_plot.name = IQ_DATA_LABEL
[660b1e6]892        new_plot.xaxis("\\rm{Q}", 'A^{-1}')
893        new_plot.yaxis("\\rm{Intensity} ","cm^{-1}")
[aa4b8379]894        new_plot.interactive = True
[660b1e6]895        #new_plot.group_id = "test group"
[75df58b]896        wx.PostEvent(self.parent, 
897                     NewPlotEvent(plot=new_plot, title="I(q)", reset=reset))
[660b1e6]898       
[0d88a09]899        self.current_plottable = new_plot
900        self.current_plottable.group_id = IQ_DATA_LABEL
901       
902       
[aa4b8379]903        # Get Q range
904        self.control_panel.q_min = self.pr.x.min()
905        self.control_panel.q_max = self.pr.x.max()
906           
[410aad8]907    def save_data(self, filepath, prstate=None):
908        """
[7116b6e0]909        Save data in provided state object.
910       
911        :TODO: move the state code away from inversion_panel and move it here.
912                Then remove the "prstate" input and make this method private.
913               
914        :param filepath: path of file to write to
915        :param prstate: P(r) inversion state
916       
[410aad8]917        """
918        #TODO: do we need this or can we use DataLoader.loader.save directly?
919       
920        # Add output data and coefficients to state
921        prstate.coefficients = self._last_out
922        prstate.covariance = self._last_cov
923       
924        # Write the output to file
[0ab485b]925        # First, check that the data is of the right type
[75df58b]926        if issubclass(self.current_plottable.__class__,
927                       DataLoader.data_info.Data1D):
[0ab485b]928            self.state_reader.write(filepath, self.current_plottable, prstate)
929        else:
[75df58b]930            msg = "pr.save_data: the data being saved is not a"
931            msg += " DataLoader.data_info.Data1D object" 
932            raise RuntimeError, msg
[410aad8]933       
[660b1e6]934       
[2a92852]935    def setup_plot_inversion(self, alpha, nfunc, d_max, q_min=None, q_max=None, 
936                             bck=False, height=0, width=0):
[7116b6e0]937        """
938        """
[f3d51f6]939        self.alpha = alpha
940        self.nfunc = nfunc
941        self.max_length = d_max
[634f1cf]942        self.q_min = q_min
943        self.q_max = q_max
[a4bd2ac]944        self.has_bck = bck
[2a92852]945        self.slit_height = height
946        self.slit_width  = width
[f3d51f6]947       
[4a5de6f]948        try:
[2a92852]949            pr = self._create_plot_pr()
950            if not pr==None:
951                self.pr = pr
952                self.perform_inversion()
[4a5de6f]953        except:
954            wx.PostEvent(self.parent, StatusEvent(status=sys.exc_value))
[f3d51f6]955
[75df58b]956    def estimate_plot_inversion(self, alpha, nfunc, d_max, 
957                                q_min=None, q_max=None, 
[2a92852]958                                bck=False, height=0, width=0):
[7116b6e0]959        """
960        """
[f3d51f6]961        self.alpha = alpha
962        self.nfunc = nfunc
963        self.max_length = d_max
[634f1cf]964        self.q_min = q_min
965        self.q_max = q_max
[a4bd2ac]966        self.has_bck = bck
[2a92852]967        self.slit_height = height
968        self.slit_width  = width
[f3d51f6]969       
[4a5de6f]970        try:
[2a92852]971            pr = self._create_plot_pr()
972            if not pr==None:
973                self.pr = pr
974                self.perform_estimate()
[4a5de6f]975        except:
976            wx.PostEvent(self.parent, StatusEvent(status=sys.exc_value))           
[f3d51f6]977
[2a92852]978    def _create_plot_pr(self, estimate=False):
[f3d51f6]979        """
[7116b6e0]980        Create and prepare invertor instance from
981        a plottable data set.
982       
983        :param path: path of the file to read in
984       
[f3d51f6]985        """
[ceaf16e]986        # Sanity check
987        if self.current_plottable is None:
988            msg = "Please load a valid data set before proceeding."
989            wx.PostEvent(self.parent, StatusEvent(status=msg)) 
990            return None   
991       
[f3d51f6]992        # Get the data from the chosen data set and perform inversion
993        pr = Invertor()
994        pr.d_max = self.max_length
995        pr.alpha = self.alpha
[634f1cf]996        pr.q_min = self.q_min
997        pr.q_max = self.q_max
[f3d51f6]998        pr.x = self.current_plottable.x
999        pr.y = self.current_plottable.y
[a4bd2ac]1000        pr.has_bck = self.has_bck
[2a92852]1001        pr.slit_height = self.slit_height
1002        pr.slit_width = self.slit_width
[f3d51f6]1003       
[d2ee6f6]1004        # Keep track of the plot window title to ensure that
1005        # we can overlay the plots
1006        if hasattr(self.current_plottable, "group_id"):
1007            pr.info["plot_group_id"] = self.current_plottable.group_id
1008       
[f3d51f6]1009        # Fill in errors if none were provided
[d2ee6f6]1010        err = self.current_plottable.dy
1011        all_zeros = True
1012        if err == None:
[d483799]1013            err = numpy.zeros(len(pr.y)) 
[d2ee6f6]1014        else:   
1015            for i in range(len(err)):
1016                if err[i]>0:
1017                    all_zeros = False
1018       
1019        if all_zeros:       
1020            scale = None
1021            min_err = 0.0
[f3d51f6]1022            for i in range(len(pr.y)):
[d2ee6f6]1023                # Scale the error so that we can fit over several decades of Q
1024                if scale==None:
1025                    scale = 0.05*math.sqrt(pr.y[i])
1026                    min_err = 0.01*pr.y[i]
1027                err[i] = scale*math.sqrt( math.fabs(pr.y[i]) ) + min_err
[75df58b]1028            message = "The loaded file had no error bars, "
1029            message += "statistical errors are assumed."
[d2ee6f6]1030            wx.PostEvent(self.parent, StatusEvent(status=message))
1031
1032        pr.err = err
[2a92852]1033       
1034        return pr
[f3d51f6]1035
1036         
[75df58b]1037    def setup_file_inversion(self, alpha, nfunc, d_max, data,
1038                             path=None, q_min=None, q_max=None, 
[2a92852]1039                             bck=False, height=0, width=0):
[7116b6e0]1040        """
1041        """
[f3d51f6]1042        self.alpha = alpha
1043        self.nfunc = nfunc
1044        self.max_length = d_max
[634f1cf]1045        self.q_min = q_min
1046        self.q_max = q_max
[a4bd2ac]1047        self.has_bck = bck
[2a92852]1048        self.slit_height = height
1049        self.slit_width  = width
[f3d51f6]1050       
[4a5de6f]1051        try:
[75df58b]1052            #pr = self._create_file_pr(path)
1053            pr = self._create_file_pr(data)
[2a92852]1054            if not pr==None:
1055                self.pr = pr
[4a5de6f]1056                self.perform_inversion()
1057        except:
1058            wx.PostEvent(self.parent, StatusEvent(status=sys.exc_value))
[f3d51f6]1059         
[75df58b]1060    def estimate_file_inversion(self, alpha, nfunc, d_max, data,
1061                                path=None, q_min=None, q_max=None, 
[2a92852]1062                                bck=False, height=0, width=0):
[7116b6e0]1063        """
1064        """
[f3d51f6]1065        self.alpha = alpha
1066        self.nfunc = nfunc
1067        self.max_length = d_max
[634f1cf]1068        self.q_min = q_min
1069        self.q_max = q_max
[a4bd2ac]1070        self.has_bck = bck
[2a92852]1071        self.slit_height = height
1072        self.slit_width  = width
[f3d51f6]1073       
[4a5de6f]1074        try:
[75df58b]1075            pr = self._create_file_pr(data)
1076            #pr = self._create_file_pr(path)
1077            if not pr is None:
[2a92852]1078                self.pr = pr
[4a5de6f]1079                self.perform_estimate()
1080        except:
1081            wx.PostEvent(self.parent, StatusEvent(status=sys.exc_value))
1082               
[f3d51f6]1083         
[75df58b]1084    def _create_file_pr(self, data):
[f3d51f6]1085        """
[7116b6e0]1086        Create and prepare invertor instance from
1087        a file data set.
1088       
1089        :param path: path of the file to read in
1090       
[f3d51f6]1091        """
1092        # Load data
[75df58b]1093        #if os.path.isfile(path):
1094        """   
1095        if self._current_file_data is not None \
1096            and self._current_file_data.path==path:
1097            # Protect against corrupted data from
1098            # previous failed load attempt
1099            if self._current_file_data.x is None:
1100                return None
1101            x = self._current_file_data.x
1102            y = self._current_file_data.y
1103            err = self._current_file_data.err
[357b79b]1104           
[75df58b]1105            message = "The data from this file has already been loaded."
1106            wx.PostEvent(self.parent, StatusEvent(status=message))
1107        else:
1108        """
1109        # Reset the status bar so that we don't get mixed up
1110        # with old messages.
1111        #TODO: refactor this into a proper status handling
1112        wx.PostEvent(self.parent, StatusEvent(status=''))
1113        try:
1114            class FileData:
1115                x = None
1116                y = None
1117                err = None
1118                path = None
1119                def __init__(self, path):
1120                    self.path = path
[6f1f129]1121               
[75df58b]1122            self._current_file_data = FileData(data.path)
1123            self._current_file_data.x = data.x
1124            self._current_file_data.y = data.y
1125            self._current_file_data.err = data.dy
1126            x, y, err = data.x, data.y, data.dy
1127        except:
1128            load_error(sys.exc_value)
1129            return None
1130       
1131        # If the file contains no data, just return
1132        if x is None or len(x) == 0:
1133            load_error("The loaded file contains no data")
1134            return None
1135       
1136        # If we have not errors, add statistical errors
1137        if err is not None and y is not None:
1138            err = numpy.zeros(len(y))
1139            scale = None
1140            min_err = 0.0
1141            for i in range(len(y)):
1142                # Scale the error so that we can fit over several decades of Q
1143                if scale == None:
1144                    scale = 0.05 * math.sqrt(y[i])
1145                    min_err = 0.01 * y[i]
1146                err[i] = scale * math.sqrt(math.fabs(y[i])) + min_err
1147            message = "The loaded file had no error bars, "
1148            message += "statistical errors are assumed."
1149            wx.PostEvent(self.parent, StatusEvent(status=message))
1150       
1151        try:
1152            # Get the data from the chosen data set and perform inversion
1153            pr = Invertor()
1154            pr.d_max = self.max_length
1155            pr.alpha = self.alpha
1156            pr.q_min = self.q_min
1157            pr.q_max = self.q_max
1158            pr.x = x
1159            pr.y = y
1160            pr.err = err
1161            pr.has_bck = self.has_bck
1162            pr.slit_height = self.slit_height
1163            pr.slit_width = self.slit_width
1164            return pr
1165        except:
1166            load_error(sys.exc_value)
[2a92852]1167        return None
[f3d51f6]1168       
1169    def perform_estimate(self):
[7116b6e0]1170        """
1171        """
[f3d51f6]1172        from pr_thread import EstimatePr
1173        from copy import deepcopy
1174       
1175        # If a thread is already started, stop it
[75df58b]1176        if self.estimation_thread != None and \
1177            self.estimation_thread.isrunning():
[f3d51f6]1178            self.estimation_thread.stop()
1179               
1180        pr = self.pr.clone()
[75df58b]1181        self.estimation_thread = EstimatePr(pr, self.nfunc,
1182                                             error_func=self._thread_error, 
1183                                         completefn = self._estimate_completed, 
[f3d51f6]1184                                            updatefn   = None)
1185        self.estimation_thread.queue()
1186        self.estimation_thread.ready(2.5)
[35adaf6]1187   
1188    def perform_estimateNT(self):
[7116b6e0]1189        """
1190        """
[35adaf6]1191        from pr_thread import EstimateNT
1192        from copy import deepcopy
1193       
1194        # If a thread is already started, stop it
1195        if self.estimation_thread != None and self.estimation_thread.isrunning():
1196            self.estimation_thread.stop()
1197               
1198        pr = self.pr.clone()
[2a92852]1199        # Skip the slit settings for the estimation
1200        # It slows down the application and it doesn't change the estimates
1201        pr.slit_height = 0.0
1202        pr.slit_width  = 0.0
[75df58b]1203        self.estimation_thread = EstimateNT(pr, self.nfunc, 
1204                                            error_func=self._thread_error, 
1205                                        completefn = self._estimateNT_completed, 
[35adaf6]1206                                            updatefn   = None)
1207        self.estimation_thread.queue()
1208        self.estimation_thread.ready(2.5)
[f3d51f6]1209       
1210    def perform_inversion(self):
[7116b6e0]1211        """
1212        """
[f3d51f6]1213        # Time estimate
1214        #estimated = self.elapsed*self.nfunc**2
[2a92852]1215        #message = "Computation time may take up to %g seconds" % self.elapsed
1216        #wx.PostEvent(self.parent, StatusEvent(status=message))
[f3d51f6]1217       
1218        # Start inversion thread
1219        self.start_thread()
1220        return
1221       
1222        out, cov = self.pr.lstsq(self.nfunc)
1223       
1224        # Save useful info
1225        self.elapsed = self.pr.elapsed
1226       
1227        for i in range(len(out)):
1228            try:
[75df58b]1229                print "%d: %g +- %g" % (i, out[i],
1230                                         math.sqrt(math.fabs(cov[i][i])))
[f3d51f6]1231            except: 
1232                print "%d: %g +- ?" % (i, out[i])       
1233       
1234        # Make a plot of I(q) data
1235        new_plot = Data1D(self.pr.x, self.pr.y, dy=self.pr.err)
1236        new_plot.name = "I_{obs}(q)"
1237        new_plot.xaxis("\\rm{Q}", 'A^{-1}')
1238        new_plot.yaxis("\\rm{Intensity} ","cm^{-1}")
1239        wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot, title="Iq"))
1240        # Show I(q) fit
1241        self.show_iq(out, self.pr)
1242        # Show P(r) fit
1243        x_values, x_range = self.show_pr(out, self.pr, cov=cov)
1244       
1245    def _on_context_inversion(self, event):
[75df58b]1246        """
1247        """
[f3d51f6]1248        panel = event.GetEventObject()
1249
1250        # If we have more than one displayed plot, make the user choose
[75df58b]1251        if len(panel.plots) > 1 and \
1252            panel.graph.selected_plottable in panel.plots:
[aa4b8379]1253            dataset = panel.graph.selected_plottable
[75df58b]1254        elif len(panel.plots) == 1:
[f3d51f6]1255            dataset = panel.plots.keys()[0]
1256        else:
[75df58b]1257            logging.info("Prview Error: No data is available")
[f3d51f6]1258            return
1259       
1260        # Store a reference to the current plottable
[3fd1ebc]1261        # If we have a suggested value, use it.
1262        try:
1263            estimate = float(self.control_panel.alpha_estimate)
1264            self.control_panel.alpha = estimate
1265        except:
1266            self.control_panel.alpha = self.alpha
[75df58b]1267            logging.info("Prview :Alpha Not estimate yet")
[3fd1ebc]1268            pass
[d6113849]1269        try:
1270            estimate = int(self.control_panel.nterms_estimate)
1271            self.control_panel.nfunc = estimate
1272        except:
1273            self.control_panel.nfunc = self.nfunc
[75df58b]1274            logging.info("Prview : ntemrs Not estimate yet")
[d6113849]1275            pass
[3fd1ebc]1276       
[f3d51f6]1277        self.current_plottable = panel.plots[dataset]
1278        self.control_panel.plotname = dataset
[d6113849]1279        #self.control_panel.nfunc = self.nfunc
[f3d51f6]1280        self.control_panel.d_max = self.max_length
1281        self.parent.set_perspective(self.perspective)
[aa4b8379]1282        self.control_panel._on_invert(None)
[f3d51f6]1283           
1284    def get_panels(self, parent):
1285        """
1286            Create and return a list of panel objects
1287        """
1288        from inversion_panel import InversionControl
1289       
1290        self.parent = parent
[aa4b8379]1291        self.control_panel = InversionControl(self.parent, -1, 
1292                                              style=wx.RAISED_BORDER,
1293                                              standalone=self.standalone)
[f3d51f6]1294        self.control_panel.set_manager(self)
1295        self.control_panel.nfunc = self.nfunc
1296        self.control_panel.d_max = self.max_length
1297        self.control_panel.alpha = self.alpha
1298        self.perspective = []
1299        self.perspective.append(self.control_panel.window_name)
[75df58b]1300     
[f3d51f6]1301        return [self.control_panel]
1302   
[75df58b]1303    def set_data(self, data_list):
[aa4b8379]1304        """
[75df58b]1305        receive a list of data to compute pr
[aa4b8379]1306        """
[75df58b]1307        if len(data_list) > 1:
[75a7ece]1308            msg = "Pr panel does not allow multiple Data.\n"
1309            msg += "Please select one!\n"
1310            from pr_widgets import DataDialog
1311            dlg = DataDialog(data_list=data_list, text=msg)
1312            if dlg.ShowModal() == wx.ID_OK:
1313                data = dlg.get_data()
1314                if issubclass(data.__class__, LoaderData1D):
1315                    self.control_panel._change_file(evt=None, data=data)
1316                else:   
1317                    msg = "Pr cannot be computed for data of "
1318                    msg += "type %s" % (data_list[0].__class__.__name__)
1319                    wx.PostEvent(self.parent, 
1320                             StatusEvent(status=msg, info='error'))
[75df58b]1321        elif len(data_list) == 1:
1322            if issubclass(data_list[0].__class__, LoaderData1D):
1323                self.control_panel._change_file(evt=None, data=data_list[0])
1324            else:
1325                msg = "Pr cannot be computed for"
1326                msg += " data of type %s" % (data_list[0].__class__.__name__)
[75a7ece]1327                wx.PostEvent(self.parent, 
1328                             StatusEvent(status=msg, info='error'))
1329        else:
1330            msg = "Pr contain no data"
1331            wx.PostEvent(self.parent, StatusEvent(status=msg, info='warning'))
[75df58b]1332           
[f3d51f6]1333    def post_init(self):
1334        """
1335            Post initialization call back to close the loose ends
1336            [Somehow openGL needs this call]
1337        """
[3e41f43]1338        if self.standalone:
[d2ee6f6]1339            self.parent.set_perspective(self.perspective)
[35adaf6]1340 
1341if __name__ == "__main__":
1342    i = Plugin()
1343    print i.perform_estimateNT()
1344   
1345   
1346   
[660b1e6]1347   
Note: See TracBrowser for help on using the repository browser.