Changes in / [d76c43a:69363c7] in sasview


Ignore:
Files:
4 added
4 deleted
17 edited

Legend:

Unmodified
Added
Removed
  • sasview/sasview.py

    r3b0f8cc r3b0f8cc  
    9999        # to ensure a complete Windows executable build. 
    100100 
     101        # Rebuild .sasview/categories.json.  This triggers a load of sasmodels 
     102        # and all the plugins. 
     103        try: 
     104            from sas.sascalc.fit.models import ModelManager 
     105            from sas.sasgui.guiframe.CategoryInstaller import CategoryInstaller 
     106            model_list = ModelManager().cat_model_list() 
     107            CategoryInstaller.check_install(model_list=model_list) 
     108        except Exception: 
     109            logger.error("%s: could not load SasView models") 
     110            logger.error(traceback.format_exc()) 
     111 
    101112        # Fitting perspective 
    102113        try: 
  • src/sas/sascalc/fit/AbstractFitEngine.py

    ra1b8fee r50fcb09  
    137137               that will smear the theory data (slit smearing or resolution 
    138138               smearing) when set. 
    139              
     139 
    140140            The proper way to set the smearing object would be to 
    141141            do the following: :: 
    142              
    143                 from sas.sascalc.data_util.qsmearing import smear_selection 
     142 
     143                from sas.sascalc.fit.qsmearing import smear_selection 
    144144                smearer = smear_selection(some_data) 
    145145                fitdata1d = FitData1D( x= [1,3,..,], 
     
    147147                                        dx=None, 
    148148                                        dy=[1,2...], smearer= smearer) 
    149             
     149 
    150150            :Note: that some_data _HAS_ to be of 
    151151                class DataLoader.data_info.Data1D 
    152152                Setting it back to None will turn smearing off. 
    153                  
     153 
    154154        """ 
    155155        Data1D.__init__(self, x=x, y=y, dx=dx, dy=dy, lam=lam, dlam=dlam) 
     
    176176        ## Max Q-value 
    177177        self.qmax = max(self.x) 
    178          
     178 
    179179        # Range used for input to smearing 
    180180        self._qmin_unsmeared = self.qmin 
     
    184184        self.idx_unsmeared = (self.x >= self._qmin_unsmeared) \ 
    185185                            & (self.x <= self._qmax_unsmeared) 
    186    
     186 
    187187    def set_fit_range(self, qmin=None, qmax=None): 
    188188        """ to set the fit range""" 
     
    199199        self._qmin_unsmeared = self.qmin 
    200200        self._qmax_unsmeared = self.qmax 
    201          
     201 
    202202        self._first_unsmeared_bin = 0 
    203203        self._last_unsmeared_bin = len(self.x) - 1 
    204          
     204 
    205205        if self.smearer is not None: 
    206206            self._first_unsmeared_bin, self._last_unsmeared_bin = \ 
     
    208208            self._qmin_unsmeared = self.x[self._first_unsmeared_bin] 
    209209            self._qmax_unsmeared = self.x[self._last_unsmeared_bin] 
    210              
     210 
    211211        # Identify the bin range for the unsmeared and smeared spaces 
    212212        self.idx = (self.x >= self.qmin) & (self.x <= self.qmax) 
     
    231231        """ 
    232232            Compute residuals. 
    233              
     233 
    234234            If self.smearer has been set, use if to smear 
    235235            the data before computing chi squared. 
    236              
     236 
    237237            :param fn: function that return model value 
    238              
     238 
    239239            :return: residuals 
    240240        """ 
     
    242242        fx = np.zeros(len(self.x)) 
    243243        fx[self.idx_unsmeared] = fn(self.x[self.idx_unsmeared]) 
    244         
     244 
    245245        ## Smear theory data 
    246246        if self.smearer is not None: 
     
    253253            raise RuntimeError, msg 
    254254        return (self.y[self.idx] - fx[self.idx]) / self.dy[self.idx], fx[self.idx] 
    255              
     255 
    256256    def residuals_deriv(self, model, pars=[]): 
    257257        """ 
    258258            :return: residuals derivatives . 
    259              
    260             :note: in this case just return empty array  
     259 
     260            :note: in this case just return empty array 
    261261        """ 
    262262        return [] 
     
    293293        x_max = max(math.fabs(sas_data2d.xmin), math.fabs(sas_data2d.xmax)) 
    294294        y_max = max(math.fabs(sas_data2d.ymin), math.fabs(sas_data2d.ymax)) 
    295          
     295 
    296296        ## fitting range 
    297297        if qmin is None: 
     
    305305            self.res_err_data = copy.deepcopy(self.err_data) 
    306306        #self.res_err_data[self.res_err_data==0]=1 
    307          
     307 
    308308        self.radius = np.sqrt(self.qx_data**2 + self.qy_data**2) 
    309          
     309 
    310310        # Note: mask = True: for MASK while mask = False for NOT to mask 
    311311        self.idx = ((self.qmin <= self.radius) &\ 
     
    368368 
    369369        return res, gn 
    370          
     370 
    371371    def residuals_deriv(self, model, pars=[]): 
    372372        """ 
    373373        :return: residuals derivatives . 
    374          
     374 
    375375        :note: in this case just return empty array 
    376          
     376 
    377377        """ 
    378378        return [] 
    379      
    380      
     379 
     380 
    381381class FitAbort(Exception): 
    382382    """ 
     
    396396        self.fit_arrange_dict = {} 
    397397        self.fitter_id = None 
    398          
     398 
    399399    def set_model(self, model, id, pars=[], constraints=[], data=None): 
    400400        """ 
    401401        set a model on a given  in the fit engine. 
    402          
    403         :param model: sas.models type  
     402 
     403        :param model: sas.models type 
    404404        :param id: is the key of the fitArrange dictionary where model is saved as a value 
    405         :param pars: the list of parameters to fit  
    406         :param constraints: list of  
     405        :param pars: the list of parameters to fit 
     406        :param constraints: list of 
    407407            tuple (name of parameter, value of parameters) 
    408408            the value of parameter must be a string to constraint 2 different 
    409409            parameters. 
    410             Example:   
     410            Example: 
    411411            we want to fit 2 model M1 and M2 both have parameters A and B. 
    412412            constraints can be ``constraints = [(M1.A, M2.B+2), (M1.B= M2.A *5),...,]`` 
    413              
    414               
     413 
     414 
    415415        :note: pars must contains only name of existing model's parameters 
    416          
     416 
    417417        """ 
    418418        if not pars: 
     
    445445        in a FitArrange object and adds that object in a dictionary 
    446446        with key id. 
    447          
     447 
    448448        :param data: data added 
    449449        :param id: unique key corresponding to a fitArrange object with data 
     
    456456                                 dx=data.dx, dy=data.dy, smearer=smearer) 
    457457        fitdata.sas_data = data 
    458         
     458 
    459459        fitdata.set_fit_range(qmin=qmin, qmax=qmax) 
    460460        #A fitArrange is already created but contains model only at id 
     
    466466            fitproblem.add_data(fitdata) 
    467467            self.fit_arrange_dict[id] = fitproblem 
    468     
     468 
    469469    def get_model(self, id): 
    470470        """ 
    471471        :param id: id is key in the dictionary containing the model to return 
    472          
     472 
    473473        :return:  a model at this id or None if no FitArrange element was 
    474474            created with this id 
     
    478478        else: 
    479479            return None 
    480      
     480 
    481481    def remove_fit_problem(self, id): 
    482482        """remove   fitarrange in id""" 
    483483        if id in self.fit_arrange_dict: 
    484484            del self.fit_arrange_dict[id] 
    485              
     485 
    486486    def select_problem_for_fit(self, id, value): 
    487487        """ 
    488488        select a couple of model and data at the id position in dictionary 
    489489        and set in self.selected value to value 
    490          
     490 
    491491        :param value: the value to allow fitting. 
    492492                can only have the value one or zero 
     
    494494        if id in self.fit_arrange_dict: 
    495495            self.fit_arrange_dict[id].set_to_fit(value) 
    496               
     496 
    497497    def get_problem_to_fit(self, id): 
    498498        """ 
    499499        return the self.selected value of the fit problem of id 
    500          
     500 
    501501        :param id: the id of the problem 
    502502        """ 
    503503        if id in self.fit_arrange_dict: 
    504504            self.fit_arrange_dict[id].get_to_fit() 
    505      
    506      
     505 
     506 
    507507class FitArrange: 
    508508    def __init__(self): 
     
    511511        to perform the Fit.FitArrange must contain exactly one model 
    512512        and at least one data for the fit to be performed. 
    513          
     513 
    514514        model: the model selected by the user 
    515515        Ldata: a list of data what the user wants to fit 
    516              
     516 
    517517        """ 
    518518        self.model = None 
     
    525525        """ 
    526526        set_model save a copy of the model 
    527          
     527 
    528528        :param model: the model being set 
    529529        """ 
    530530        self.model = model 
    531          
     531 
    532532    def add_data(self, data): 
    533533        """ 
    534534        add_data fill a self.data_list with data to fit 
    535          
     535 
    536536        :param data: Data to add in the list 
    537537        """ 
    538538        if not data in self.data_list: 
    539539            self.data_list.append(data) 
    540              
     540 
    541541    def get_model(self): 
    542542        """ 
     
    544544        """ 
    545545        return self.model 
    546       
     546 
    547547    def get_data(self): 
    548548        """ 
     
    550550        """ 
    551551        return self.data_list[0] 
    552        
     552 
    553553    def remove_data(self, data): 
    554554        """ 
    555555        Remove one element from the list 
    556          
     556 
    557557        :param data: Data to remove from data_list 
    558558        """ 
    559559        if data in self.data_list: 
    560560            self.data_list.remove(data) 
    561              
     561 
    562562    def set_to_fit(self, value=0): 
    563563        """ 
    564564        set self.selected to 0 or 1  for other values raise an exception 
    565          
     565 
    566566        :param value: integer between 0 or 1 
    567567        """ 
    568568        self.selected = value 
    569          
     569 
    570570    def get_to_fit(self): 
    571571        """ 
     
    599599        if self.model is not None and self.data is not None: 
    600600            self.inputs = [(self.model, self.data)] 
    601       
     601 
    602602    def set_model(self, model): 
    603603        """ 
    604604        """ 
    605605        self.model = model 
    606          
     606 
    607607    def set_fitness(self, fitness): 
    608608        """ 
    609609        """ 
    610610        self.fitness = fitness 
    611          
     611 
    612612    def __str__(self): 
    613613        """ 
     
    624624        msg = [msg1, msg3] + msg2 
    625625        return "\n".join(msg) 
    626      
     626 
    627627    def print_summary(self): 
    628628        """ 
  • src/sas/sascalc/fit/BumpsFitting.py

    r9a5097c r1386b2f  
    1515    def get_fitter(): 
    1616        return FIT_CONFIG.selected_fitter, FIT_CONFIG.selected_values 
    17 except: 
     17except ImportError: 
    1818    # CRUFT: Bumps changed its handling of fit options around 0.7.5.6 
    1919    # Default bumps to use the Levenberg-Marquardt optimizer 
     
    5656        header = "=== Steps: %s  chisq: %s  ETA: %s\n"%(step, chisq, time) 
    5757        parameters = ["%15s: %-10.3g%s"%(k,v,("\n" if i%3==2 else " | ")) 
    58                       for i,(k,v) in enumerate(zip(pars,history.point[0]))] 
     58                      for i, (k, v) in enumerate(zip(pars, history.point[0]))] 
    5959        self.msg = "".join([header]+parameters) 
    6060 
     
    7777        self.handler.set_result(Progress(history, self.max_step, self.pars, self.dof)) 
    7878        self.handler.progress(history.step[0], self.max_step) 
    79         if len(history.step)>1 and history.step[1] > history.step[0]: 
     79        if len(history.step) > 1 and history.step[1] > history.step[0]: 
    8080            self.handler.improvement() 
    8181        self.handler.update_fit() 
     
    9797        try: 
    9898            p = history.population_values[0] 
    99             n,p = len(p), np.sort(p) 
    100             QI,Qmid, = int(0.2*n),int(0.5*n) 
    101             self.convergence.append((best, p[0],p[QI],p[Qmid],p[-1-QI],p[-1])) 
    102         except: 
    103             self.convergence.append((best, best,best,best,best,best)) 
     99            n, p = len(p), np.sort(p) 
     100            QI, Qmid = int(0.2*n), int(0.5*n) 
     101            self.convergence.append((best, p[0], p[QI], p[Qmid], p[-1-QI], p[-1])) 
     102        except Exception: 
     103            self.convergence.append((best, best, best, best, best, best)) 
    104104 
    105105 
     
    131131 
    132132    def _reset_pars(self, names, values): 
    133         for k,v in zip(names, values): 
     133        for k, v in zip(names, values): 
    134134            self._pars[k].value = v 
    135135 
     
    137137        self._pars = {} 
    138138        for k in self.model.getParamList(): 
    139             name = ".".join((self.name,k)) 
     139            name = ".".join((self.name, k)) 
    140140            value = self.model.getParam(k) 
    141             bounds = self.model.details.get(k,["",None,None])[1:3] 
     141            bounds = self.model.details.get(k, ["", None, None])[1:3] 
    142142            self._pars[k] = parameter.Parameter(value=value, bounds=bounds, 
    143143                                                fixed=True, name=name) 
     
    145145 
    146146    def _init_pars(self, kw): 
    147         for k,v in kw.items(): 
     147        for k, v in kw.items(): 
    148148            # dispersion parameters initialized with _field instead of .field 
    149             if k.endswith('_width'): k = k[:-6]+'.width' 
    150             elif k.endswith('_npts'): k = k[:-5]+'.npts' 
    151             elif k.endswith('_nsigmas'): k = k[:-7]+'.nsigmas' 
    152             elif k.endswith('_type'): k = k[:-5]+'.type' 
     149            if k.endswith('_width'): 
     150                k = k[:-6]+'.width' 
     151            elif k.endswith('_npts'): 
     152                k = k[:-5]+'.npts' 
     153            elif k.endswith('_nsigmas'): 
     154                k = k[:-7]+'.nsigmas' 
     155            elif k.endswith('_type'): 
     156                k = k[:-5]+'.type' 
    153157            if k not in self._pars: 
    154158                formatted_pars = ", ".join(sorted(self._pars.keys())) 
     
    159163            elif isinstance(v, parameter.BaseParameter): 
    160164                self._pars[k] = v 
    161             elif isinstance(v, (tuple,list)): 
     165            elif isinstance(v, (tuple, list)): 
    162166                low, high = v 
    163167                self._pars[k].value = (low+high)/2 
    164                 self._pars[k].range(low,high) 
     168                self._pars[k].range(low, high) 
    165169            else: 
    166170                self._pars[k].value = v 
     
    170174        Flag a set of parameters as fitted parameters. 
    171175        """ 
    172         for k,p in self._pars.items(): 
     176        for k, p in self._pars.items(): 
    173177            p.fixed = (k not in param_list or k in self.constraints) 
    174178        self.fitted_par_names = [k for k in param_list if k not in self.constraints] 
     
    182186 
    183187    def update(self): 
    184         for k,v in self._pars.items(): 
     188        for k, v in self._pars.items(): 
    185189            #print "updating",k,v,v.value 
    186             self.model.setParam(k,v.value) 
     190            self.model.setParam(k, v.value) 
    187191        self._dirty = True 
    188192 
     
    223227            symtab = dict((".".join((M.name, k)), p) 
    224228                          for M in self.models 
    225                           for k,p in M.parameters().items()) 
     229                          for k, p in M.parameters().items()) 
    226230            self.update = compile_constraints(symtab, exprs) 
    227231        else: 
     
    300304                                          np.NaN*np.ones(len(fitness.computed_pars)))) 
    301305                R.pvec = np.hstack((result['value'][fitted_index], 
    302                                       [p.value for p in fitness.computed_pars])) 
     306                                    [p.value for p in fitness.computed_pars])) 
    303307                R.fitness = np.sum(R.residuals**2)/(fitness.numpoints() - len(fitted_index)) 
    304308            else: 
    305309                R.stderr = np.NaN*np.ones(len(param_list)) 
    306                 R.pvec = np.asarray( [p.value for p in fitness.fitted_pars+fitness.computed_pars]) 
     310                R.pvec = np.asarray([p.value for p in fitness.fitted_pars+fitness.computed_pars]) 
    307311                R.fitness = np.NaN 
    308312            R.convergence = result['convergence'] 
     
    331335    steps = options.get('steps', 0) 
    332336    if steps == 0: 
    333         pop = options.get('pop',0)*len(problem._parameters) 
     337        pop = options.get('pop', 0)*len(problem._parameters) 
    334338        samples = options.get('samples', 0) 
    335339        steps = (samples+pop-1)/pop if pop != 0 else samples 
     
    343347    fitdriver = fitters.FitDriver(fitclass, problem=problem, 
    344348                                  abort_test=abort_test, **options) 
    345     omp_threads = int(os.environ.get('OMP_NUM_THREADS','0')) 
     349    omp_threads = int(os.environ.get('OMP_NUM_THREADS', '0')) 
    346350    mapper = MPMapper if omp_threads == 1 else SerialMapper 
    347351    fitdriver.mapper = mapper.start_mapper(problem, None) 
     
    359363    convergence_list = options['monitors'][-1].convergence 
    360364    convergence = (2*np.asarray(convergence_list)/problem.dof 
    361                    if convergence_list else np.empty((0,1),'d')) 
     365                   if convergence_list else np.empty((0, 1), 'd')) 
    362366 
    363367    success = best is not None 
     
    376380        'errors': '\n'.join(errors), 
    377381        } 
    378  
  • src/sas/sascalc/pr/fit/AbstractFitEngine.py

    ra1b8fee r50fcb09  
    137137               that will smear the theory data (slit smearing or resolution 
    138138               smearing) when set. 
    139              
     139 
    140140            The proper way to set the smearing object would be to 
    141141            do the following: :: 
    142              
    143                 from sas.sascalc.data_util.qsmearing import smear_selection 
     142 
     143                from sas.sascalc.fit.qsmearing import smear_selection 
    144144                smearer = smear_selection(some_data) 
    145145                fitdata1d = FitData1D( x= [1,3,..,], 
     
    147147                                        dx=None, 
    148148                                        dy=[1,2...], smearer= smearer) 
    149             
     149 
    150150            :Note: that some_data _HAS_ to be of 
    151151                class DataLoader.data_info.Data1D 
    152152                Setting it back to None will turn smearing off. 
    153                  
     153 
    154154        """ 
    155155        Data1D.__init__(self, x=x, y=y, dx=dx, dy=dy) 
     
    176176        ## Max Q-value 
    177177        self.qmax = max(self.x) 
    178          
     178 
    179179        # Range used for input to smearing 
    180180        self._qmin_unsmeared = self.qmin 
     
    184184        self.idx_unsmeared = (self.x >= self._qmin_unsmeared) \ 
    185185                            & (self.x <= self._qmax_unsmeared) 
    186    
     186 
    187187    def set_fit_range(self, qmin=None, qmax=None): 
    188188        """ to set the fit range""" 
     
    199199        self._qmin_unsmeared = self.qmin 
    200200        self._qmax_unsmeared = self.qmax 
    201          
     201 
    202202        self._first_unsmeared_bin = 0 
    203203        self._last_unsmeared_bin = len(self.x) - 1 
    204          
     204 
    205205        if self.smearer is not None: 
    206206            self._first_unsmeared_bin, self._last_unsmeared_bin = \ 
     
    208208            self._qmin_unsmeared = self.x[self._first_unsmeared_bin] 
    209209            self._qmax_unsmeared = self.x[self._last_unsmeared_bin] 
    210              
     210 
    211211        # Identify the bin range for the unsmeared and smeared spaces 
    212212        self.idx = (self.x >= self.qmin) & (self.x <= self.qmax) 
     
    231231        """ 
    232232            Compute residuals. 
    233              
     233 
    234234            If self.smearer has been set, use if to smear 
    235235            the data before computing chi squared. 
    236              
     236 
    237237            :param fn: function that return model value 
    238              
     238 
    239239            :return: residuals 
    240240        """ 
     
    242242        fx = np.zeros(len(self.x)) 
    243243        fx[self.idx_unsmeared] = fn(self.x[self.idx_unsmeared]) 
    244         
     244 
    245245        ## Smear theory data 
    246246        if self.smearer is not None: 
     
    253253            raise RuntimeError, msg 
    254254        return (self.y[self.idx] - fx[self.idx]) / self.dy[self.idx], fx[self.idx] 
    255              
     255 
    256256    def residuals_deriv(self, model, pars=[]): 
    257257        """ 
    258258            :return: residuals derivatives . 
    259              
    260             :note: in this case just return empty array  
     259 
     260            :note: in this case just return empty array 
    261261        """ 
    262262        return [] 
     
    293293        x_max = max(math.fabs(sas_data2d.xmin), math.fabs(sas_data2d.xmax)) 
    294294        y_max = max(math.fabs(sas_data2d.ymin), math.fabs(sas_data2d.ymax)) 
    295          
     295 
    296296        ## fitting range 
    297297        if qmin is None: 
     
    305305            self.res_err_data = copy.deepcopy(self.err_data) 
    306306        #self.res_err_data[self.res_err_data==0]=1 
    307          
     307 
    308308        self.radius = np.sqrt(self.qx_data**2 + self.qy_data**2) 
    309          
     309 
    310310        # Note: mask = True: for MASK while mask = False for NOT to mask 
    311311        self.idx = ((self.qmin <= self.radius) &\ 
     
    371371 
    372372        return res, gn 
    373          
     373 
    374374    def residuals_deriv(self, model, pars=[]): 
    375375        """ 
    376376        :return: residuals derivatives . 
    377          
     377 
    378378        :note: in this case just return empty array 
    379          
     379 
    380380        """ 
    381381        return [] 
    382      
    383      
     382 
     383 
    384384class FitAbort(Exception): 
    385385    """ 
     
    399399        self.fit_arrange_dict = {} 
    400400        self.fitter_id = None 
    401          
     401 
    402402    def set_model(self, model, id, pars=[], constraints=[], data=None): 
    403403        """ 
    404404        set a model on a given  in the fit engine. 
    405          
    406         :param model: sas.models type  
     405 
     406        :param model: sas.models type 
    407407        :param id: is the key of the fitArrange dictionary where model is saved as a value 
    408         :param pars: the list of parameters to fit  
    409         :param constraints: list of  
     408        :param pars: the list of parameters to fit 
     409        :param constraints: list of 
    410410            tuple (name of parameter, value of parameters) 
    411411            the value of parameter must be a string to constraint 2 different 
    412412            parameters. 
    413             Example:   
     413            Example: 
    414414            we want to fit 2 model M1 and M2 both have parameters A and B. 
    415415            constraints can be ``constraints = [(M1.A, M2.B+2), (M1.B= M2.A *5),...,]`` 
    416              
    417               
     416 
     417 
    418418        :note: pars must contains only name of existing model's parameters 
    419          
     419 
    420420        """ 
    421421        if not pars: 
     
    448448        in a FitArrange object and adds that object in a dictionary 
    449449        with key id. 
    450          
     450 
    451451        :param data: data added 
    452452        :param id: unique key corresponding to a fitArrange object with data 
     
    459459                                 dx=data.dx, dy=data.dy, smearer=smearer) 
    460460        fitdata.sas_data = data 
    461         
     461 
    462462        fitdata.set_fit_range(qmin=qmin, qmax=qmax) 
    463463        #A fitArrange is already created but contains model only at id 
     
    469469            fitproblem.add_data(fitdata) 
    470470            self.fit_arrange_dict[id] = fitproblem 
    471     
     471 
    472472    def get_model(self, id): 
    473473        """ 
    474474        :param id: id is key in the dictionary containing the model to return 
    475          
     475 
    476476        :return:  a model at this id or None if no FitArrange element was 
    477477            created with this id 
     
    481481        else: 
    482482            return None 
    483      
     483 
    484484    def remove_fit_problem(self, id): 
    485485        """remove   fitarrange in id""" 
    486486        if id in self.fit_arrange_dict: 
    487487            del self.fit_arrange_dict[id] 
    488              
     488 
    489489    def select_problem_for_fit(self, id, value): 
    490490        """ 
    491491        select a couple of model and data at the id position in dictionary 
    492492        and set in self.selected value to value 
    493          
     493 
    494494        :param value: the value to allow fitting. 
    495495                can only have the value one or zero 
     
    497497        if id in self.fit_arrange_dict: 
    498498            self.fit_arrange_dict[id].set_to_fit(value) 
    499               
     499 
    500500    def get_problem_to_fit(self, id): 
    501501        """ 
    502502        return the self.selected value of the fit problem of id 
    503          
     503 
    504504        :param id: the id of the problem 
    505505        """ 
    506506        if id in self.fit_arrange_dict: 
    507507            self.fit_arrange_dict[id].get_to_fit() 
    508      
    509      
     508 
     509 
    510510class FitArrange: 
    511511    def __init__(self): 
     
    514514        to perform the Fit.FitArrange must contain exactly one model 
    515515        and at least one data for the fit to be performed. 
    516          
     516 
    517517        model: the model selected by the user 
    518518        Ldata: a list of data what the user wants to fit 
    519              
     519 
    520520        """ 
    521521        self.model = None 
     
    528528        """ 
    529529        set_model save a copy of the model 
    530          
     530 
    531531        :param model: the model being set 
    532532        """ 
    533533        self.model = model 
    534          
     534 
    535535    def add_data(self, data): 
    536536        """ 
    537537        add_data fill a self.data_list with data to fit 
    538          
     538 
    539539        :param data: Data to add in the list 
    540540        """ 
    541541        if not data in self.data_list: 
    542542            self.data_list.append(data) 
    543              
     543 
    544544    def get_model(self): 
    545545        """ 
     
    547547        """ 
    548548        return self.model 
    549       
     549 
    550550    def get_data(self): 
    551551        """ 
     
    553553        """ 
    554554        return self.data_list[0] 
    555        
     555 
    556556    def remove_data(self, data): 
    557557        """ 
    558558        Remove one element from the list 
    559          
     559 
    560560        :param data: Data to remove from data_list 
    561561        """ 
    562562        if data in self.data_list: 
    563563            self.data_list.remove(data) 
    564              
     564 
    565565    def set_to_fit(self, value=0): 
    566566        """ 
    567567        set self.selected to 0 or 1  for other values raise an exception 
    568          
     568 
    569569        :param value: integer between 0 or 1 
    570570        """ 
    571571        self.selected = value 
    572          
     572 
    573573    def get_to_fit(self): 
    574574        """ 
     
    602602        if self.model is not None and self.data is not None: 
    603603            self.inputs = [(self.model, self.data)] 
    604       
     604 
    605605    def set_model(self, model): 
    606606        """ 
    607607        """ 
    608608        self.model = model 
    609          
     609 
    610610    def set_fitness(self, fitness): 
    611611        """ 
    612612        """ 
    613613        self.fitness = fitness 
    614          
     614 
    615615    def __str__(self): 
    616616        """ 
     
    627627        msg = [msg1, msg3] + msg2 
    628628        return "\n".join(msg) 
    629      
     629 
    630630    def print_summary(self): 
    631631        """ 
  • src/sas/sascalc/realspace/VolumeCanvas.py

    r235f514 r98e3f24  
    44    Simulation canvas for real-space simulation of SAS scattering intensity. 
    55    The user can create an arrangement of basic shapes and estimate I(q) and 
    6     I(q_x, q_y). Error estimates on the simulation are also available.  
    7      
     6    I(q_x, q_y). Error estimates on the simulation are also available. 
     7 
    88    Example: 
    9      
     9 
    1010    import sas.sascalc.realspace.VolumeCanvas as VolumeCanvas 
    1111    canvas = VolumeCanvas.VolumeCanvas() 
    1212    canvas.setParam('lores_density', 0.01) 
    13      
     13 
    1414    sphere = SphereDescriptor() 
    1515    handle = canvas.addObject(sphere) 
     
    1717    output, error = canvas.getIqError(q=0.1) 
    1818    output, error = canvas.getIq2DError(0.1, 0.1) 
    19      
     19 
    2020    or alternatively: 
    2121    iq = canvas.run(0.1) 
    2222    i2_2D = canvas.run([0.1, 1.57]) 
    23      
     23 
    2424""" 
    2525 
    26 from sas.models.BaseComponent import BaseComponent 
     26from sas.sascalc.calculator.BaseComponent import BaseComponent 
    2727from sas.sascalc.simulation.pointsmodelpy import pointsmodelpy 
    2828from sas.sascalc.simulation.geoshapespy import geoshapespy 
     
    3131import os.path, math 
    3232 
    33 class ShapeDescriptor: 
     33class ShapeDescriptor(object): 
    3434    """ 
    3535        Class to hold the information about a shape 
    3636        The descriptor holds a dictionary of parameters. 
    37          
     37 
    3838        Note: if shape parameters are accessed directly 
    3939        from outside VolumeCanvas. The getPr method 
    4040        should be called before evaluating I(q). 
    41                  
     41 
    4242    """ 
    4343    def __init__(self): 
     
    5555        self.params['is_lores'] = True 
    5656        self.params['order'] = 0 
    57              
     57 
    5858    def create(self): 
    5959        """ 
     
    6565        z0 = self.params["center"][2] 
    6666        geoshapespy.set_center(self.shapeObject, x0, y0, z0) 
    67          
     67 
    6868        # Set orientation 
    6969        x0 = self.params["orientation"][0] 
     
    7171        z0 = self.params["orientation"][2] 
    7272        geoshapespy.set_orientation(self.shapeObject, x0, y0, z0) 
    73                 
     73 
    7474class SphereDescriptor(ShapeDescriptor): 
    7575    """ 
    7676        Descriptor for a sphere 
    77          
     77 
    7878        The parameters are: 
    7979            - radius [Angstroem] [default = 20 A] 
    8080            - Contrast [A-2] [default = 1 A-2] 
    81              
     81 
    8282    """ 
    8383    def __init__(self): 
    8484        """ 
    8585            Initialization 
    86         """  
     86        """ 
    8787        ShapeDescriptor.__init__(self) 
    8888        # Default parameters 
    89         self.params["type"]   = "sphere" 
     89        self.params["type"] = "sphere" 
    9090        # Radius of the sphere 
    9191        self.params["radius"] = 20.0 
     
    100100        self.shapeObject = geoshapespy.new_sphere(\ 
    101101            self.params["radius"]) 
    102          
    103         ShapeDescriptor.create(self)    
     102 
     103        ShapeDescriptor.create(self) 
    104104        return self.shapeObject 
    105      
     105 
    106106class CylinderDescriptor(ShapeDescriptor): 
    107107    """ 
    108108        Descriptor for a cylinder 
    109109        Orientation: Default cylinder is along Y 
    110          
     110 
    111111        Parameters: 
    112112            - Length [default = 40 A] 
     
    117117        """ 
    118118            Initialization 
    119         """  
     119        """ 
    120120        ShapeDescriptor.__init__(self) 
    121121        # Default parameters 
    122         self.params["type"]   = "cylinder" 
     122        self.params["type"] = "cylinder" 
    123123        # Length of the cylinder 
    124124        self.params["length"] = 40.0 
     
    127127        # Constrast parameter 
    128128        self.params["contrast"] = 1.0 
    129          
     129 
    130130    def create(self): 
    131131        """ 
     
    138138        ShapeDescriptor.create(self) 
    139139        return self.shapeObject 
    140          
     140 
    141141 
    142142class EllipsoidDescriptor(ShapeDescriptor): 
    143143    """ 
    144144        Descriptor for an ellipsoid 
    145          
     145 
    146146        Parameters: 
    147147            - Radius_x along the x-axis [default = 30 A] 
     
    153153        """ 
    154154            Initialization 
    155         """  
     155        """ 
    156156        ShapeDescriptor.__init__(self) 
    157157        # Default parameters 
    158         self.params["type"]   = "ellipsoid" 
     158        self.params["type"] = "ellipsoid" 
    159159        self.params["radius_x"] = 30.0 
    160160        self.params["radius_y"] = 20.0 
    161161        self.params["radius_z"] = 10.0 
    162162        self.params["contrast"] = 1.0 
    163          
     163 
    164164    def create(self): 
    165165        """ 
     
    168168        """ 
    169169        self.shapeObject = geoshapespy.new_ellipsoid(\ 
    170             self.params["radius_x"], self.params["radius_y"],  
     170            self.params["radius_x"], self.params["radius_y"], 
    171171            self.params["radius_z"]) 
    172          
    173         ShapeDescriptor.create(self)    
     172 
     173        ShapeDescriptor.create(self) 
    174174        return self.shapeObject 
    175          
     175 
    176176class HelixDescriptor(ShapeDescriptor): 
    177177    """ 
    178178        Descriptor for an helix 
    179          
     179 
    180180        Parameters: 
    181181            -radius_helix: the radius of the helix [default = 10 A] 
     
    188188        """ 
    189189            Initialization 
    190         """  
     190        """ 
    191191        ShapeDescriptor.__init__(self) 
    192192        # Default parameters 
    193         self.params["type"]   = "singlehelix" 
     193        self.params["type"] = "singlehelix" 
    194194        self.params["radius_helix"] = 10.0 
    195195        self.params["radius_tube"] = 3.0 
     
    204204        """ 
    205205        self.shapeObject = geoshapespy.new_singlehelix(\ 
    206             self.params["radius_helix"], self.params["radius_tube"],  
     206            self.params["radius_helix"], self.params["radius_tube"], 
    207207            self.params["pitch"], self.params["turns"]) 
    208          
    209         ShapeDescriptor.create(self)    
     208 
     209        ShapeDescriptor.create(self) 
    210210        return self.shapeObject 
    211          
     211 
    212212class PDBDescriptor(ShapeDescriptor): 
    213213    """ 
    214214        Descriptor for a PDB set of points 
    215          
     215 
    216216        Parameter: 
    217217            - file = name of the PDB file 
     
    221221            Initialization 
    222222            @param filename: name of the PDB file to load 
    223         """  
     223        """ 
    224224        ShapeDescriptor.__init__(self) 
    225225        # Default parameters 
    226         self.params["type"]   = "pdb" 
     226        self.params["type"] = "pdb" 
    227227        self.params["file"] = filename 
    228228        self.params['is_lores'] = False 
     
    234234        """ 
    235235        self.shapeObject = pointsmodelpy.new_pdbmodel() 
    236         pointsmodelpy.pdbmodel_add(self.shapeObject, self.params['file'])        
    237          
    238         #ShapeDescriptor.create(self)    
     236        pointsmodelpy.pdbmodel_add(self.shapeObject, self.params['file']) 
     237 
     238        #ShapeDescriptor.create(self) 
    239239        return self.shapeObject 
    240          
     240 
    241241# Define a dictionary for the shape until we find 
    242242# a better way to create them 
     
    245245              'ellipsoid':EllipsoidDescriptor, 
    246246              'singlehelix':HelixDescriptor} 
    247          
     247 
    248248class VolumeCanvas(BaseComponent): 
    249249    """ 
    250         Class representing an empty space volume to add  
     250        Class representing an empty space volume to add 
    251251        geometrical object to. 
    252          
     252 
    253253        For 1D I(q) simulation, getPr() is called internally for the 
    254254        first call to getIq(). 
    255          
    256     """ 
    257      
     255 
     256    """ 
     257 
    258258    def __init__(self): 
    259259        """ 
     
    261261        """ 
    262262        BaseComponent.__init__(self) 
    263          
     263 
    264264        ## Maximum value of q reachable 
    265265        self.params['q_max'] = 0.1 
     
    267267        self.params['scale'] = 1.0 
    268268        self.params['background'] = 0.0 
    269          
     269 
    270270        self.lores_model = pointsmodelpy.new_loresmodel(self.params['lores_density']) 
    271271        self.complex_model = pointsmodelpy.new_complexmodel() 
    272272        self.shapes = {} 
    273         self.shapecount = 0         
     273        self.shapecount = 0 
    274274        self.points = None 
    275275        self.npts = 0 
    276         self.hasPr = False         
    277          
     276        self.hasPr = False 
     277 
    278278    def _model_changed(self): 
    279279        """ 
    280             Reset internal data members to reflect the fact that the  
     280            Reset internal data members to reflect the fact that the 
    281281            real-space model has changed 
    282282        """ 
    283         self.hasPr  = False 
     283        self.hasPr = False 
    284284        self.points = None 
    285          
    286     def addObject(self, shapeDesc, id = None): 
     285 
     286    def addObject(self, shapeDesc, id=None): 
    287287        """ 
    288288            Adds a real-space object to the canvas. 
    289          
     289 
    290290            @param shapeDesc: object to add to the canvas [ShapeDescriptor] 
    291291            @param id: string handle for the object [string] [optional] 
     
    295295        if id is None: 
    296296            id = shapeDesc.params["type"]+str(self.shapecount) 
    297           
     297 
    298298        # Self the order number 
    299299        shapeDesc.params['order'] = self.shapecount 
     
    307307 
    308308        return id 
    309              
    310      
    311     def add(self, shape, id = None): 
     309 
     310 
     311    def add(self, shape, id=None): 
    312312        """ 
    313313            The intend of this method is to eventually be able to use it 
     
    315315            analytical solutions. For instance, if one adds a cylinder and 
    316316            it is the only shape on the canvas, the analytical solution 
    317             could be called. If multiple shapes are involved, then  
     317            could be called. If multiple shapes are involved, then 
    318318            simulation has to be performed. 
    319              
     319 
    320320            This function is deprecated, use addObject(). 
    321          
     321 
    322322            @param shape: name of the object to add to the canvas [string] 
    323323            @param id: string handle for the object [string] [optional] 
     
    327327        if id is None: 
    328328            id = "shape"+str(self.shapecount) 
    329   
     329 
    330330        # shapeDesc = ShapeDescriptor(shape.lower()) 
    331331        if shape.lower() in shape_dict: 
     
    336336        else: 
    337337            raise ValueError("VolumeCanvas.add: Unknown shape %s" % shape) 
    338          
     338 
    339339        return self.addObject(shapeDesc, id) 
    340340 
     
    354354 
    355355 
    356     def setParam(self, name, value):     
    357         """ 
    358             Function to set the value of a parameter.  
     356    def setParam(self, name, value): 
     357        """ 
     358            Function to set the value of a parameter. 
    359359            Both VolumeCanvas parameters and shape parameters 
    360             are accessible.  
    361              
     360            are accessible. 
     361 
    362362            Note: if shape parameters are accessed directly 
    363363            from outside VolumeCanvas. The getPr method 
    364364            should be called before evaluating I(q). 
    365          
     365 
    366366            TODO: implemented a check method to protect 
    367367            against that. 
    368          
     368 
    369369            @param name: name of the parameter to change 
    370370            @param value: value to give the parameter 
    371371        """ 
    372          
     372 
    373373        # Lowercase for case insensitivity 
    374374        name = name.lower() 
    375          
     375 
    376376        # Look for shape access 
    377377        toks = name.split('.') 
    378          
     378 
    379379        # If a shape identifier was given, look the shape up 
    380380        # in the dictionary 
     
    390390            else: 
    391391                raise ValueError("Could not find shape %s" % toks[0]) 
    392          
     392 
    393393        else: 
    394             # If we are not accessing the parameters of a  
     394            # If we are not accessing the parameters of a 
    395395            # shape, see if the parameter is part of this object 
    396396            BaseComponent.setParam(self, name, value) 
    397397            self._model_changed() 
    398398 
    399     def getParam(self, name):     
     399    def getParam(self, name): 
    400400        """ 
    401401            @param name: name of the parameter to change 
    402402        """ 
    403403        #TODO: clean this up 
    404          
     404 
    405405        # Lowercase for case insensitivity 
    406406        name = name.lower() 
    407          
     407 
    408408        # Look for sub-model access 
    409409        toks = name.split('.') 
     
    435435        else: 
    436436            raise ValueError("VolumeCanvas.getParam: Could not find %s" % name) 
    437              
     437 
    438438    def getParamList(self, shapeid=None): 
    439439        """ 
    440                return a full list of all available parameters from  
     440               return a full list of all available parameters from 
    441441           self.params.keys(). If a key in self.params is a instance 
    442            of ShapeDescriptor, extend the return list to:  
     442           of ShapeDescriptor, extend the return list to: 
    443443           [param1,param2,shapeid.param1,shapeid.param2.......] 
    444444 
     
    456456                header = key2 + '.' 
    457457                for key3 in value2.params: 
    458                     fullname = header + key3                  
     458                    fullname = header + key3 
    459459                    param_list.append(fullname) 
    460       
     460 
    461461        else: 
    462462            if not shapeid in self.shapes: 
     
    470470    def getShapeList(self): 
    471471        """ 
    472             Return a list of the shapes  
     472            Return a list of the shapes 
    473473        """ 
    474474        return self.shapes.keys() 
     
    481481        # Create the object model 
    482482        shapeDesc.create() 
    483                      
     483 
    484484        if shapeDesc.params['is_lores']: 
    485485            # Add the shape to the lores_model 
    486             pointsmodelpy.lores_add(self.lores_model,  
    487                 shapeDesc.shapeObject, shapeDesc.params['contrast'])   
     486            pointsmodelpy.lores_add(self.lores_model, 
     487                                    shapeDesc.shapeObject, 
     488                                    shapeDesc.params['contrast']) 
    488489 
    489490    def _createVolumeFromList(self): 
     
    492493            Whenever we change a parameter of a shape, we have to re-create 
    493494            the whole thing. 
    494              
     495 
    495496            Items with higher 'order' number take precedence for regions 
    496             of space that are shared with other objects. Points in the  
     497            of space that are shared with other objects. Points in the 
    497498            overlapping region belonging to objects with lower 'order' 
    498499            will be ignored. 
    499              
     500 
    500501            Items are added in decreasing 'order' number. 
    501502            The item with the highest 'order' will be added *first*. 
    502503            [That conventions is prescribed by the realSpaceModeling module] 
    503504        """ 
    504          
     505 
    505506        # Create empty model 
    506507        self.lores_model = \ 
     
    509510        # Create empty complex model 
    510511        self.complex_model = pointsmodelpy.new_complexmodel() 
    511         
     512 
    512513        # Order the object first 
    513514        obj_list = [] 
    514      
     515 
    515516        for shape in self.shapes: 
    516517            order = self.shapes[shape].params['order'] 
    517518            # find where to place it in the list 
    518519            stored = False 
    519              
     520 
    520521            for i in range(len(obj_list)): 
    521522                if obj_list[i][0] > order: 
     
    523524                    stored = True 
    524525                    break 
    525              
     526 
    526527            if not stored: 
    527528                obj_list.append([order, shape]) 
    528                  
     529 
    529530        # Add each shape 
    530531        len_list = len(obj_list) 
     
    533534            self._addSingleShape(shapedesc) 
    534535 
    535         return 0      
    536      
     536        return 0 
     537 
    537538    def getPr(self): 
    538539        """ 
     
    540541            This method should always be called after the shapes 
    541542            on the VolumeCanvas have changed. 
    542              
    543             @return: calculation output flag  
     543 
     544            @return: calculation output flag 
    544545        """ 
    545546        # To find a complete example of the correct call order: 
    546547        # In LORES2, in actionclass.py, method CalculateAction._get_iq() 
    547          
     548 
    548549        # If there are not shapes, do nothing 
    549550        if len(self.shapes) == 0: 
    550551            self._model_changed() 
    551552            return 0 
    552          
     553 
    553554        # generate space filling points from shape list 
    554555        self._createVolumeFromList() 
     
    556557        self.points = pointsmodelpy.new_point3dvec() 
    557558 
    558         pointsmodelpy.complexmodel_add(self.complex_model,  
    559                                         self.lores_model, "LORES") 
     559        pointsmodelpy.complexmodel_add(self.complex_model, 
     560                                       self.lores_model, "LORES") 
    560561        for shape in self.shapes: 
    561             if self.shapes[shape].params['is_lores'] == False: 
    562                 pointsmodelpy.complexmodel_add(self.complex_model,  
     562            if not self.shapes[shape].params['is_lores']: 
     563                pointsmodelpy.complexmodel_add(self.complex_model, 
    563564                    self.shapes[shape].shapeObject, "PDB") 
    564          
     565 
    565566        #pointsmodelpy.get_lorespoints(self.lores_model, self.points) 
    566567        self.npts = pointsmodelpy.get_complexpoints(self.complex_model, self.points) 
    567          
     568 
    568569        # expecting the rmax is a positive float or 0. The maximum distance. 
    569         #rmax = pointsmodelpy.get_lores_pr(self.lores_model, self.points)    
    570           
    571         rmax = pointsmodelpy.get_complex_pr(self.complex_model, self.points)  
    572         self.hasPr = True    
     570        #rmax = pointsmodelpy.get_lores_pr(self.lores_model, self.points) 
     571 
     572        rmax = pointsmodelpy.get_complex_pr(self.complex_model, self.points) 
     573        self.hasPr = True 
    573574 
    574575        return rmax 
    575          
    576     def run(self, q = 0): 
     576 
     577    def run(self, q=0): 
    577578        """ 
    578579            Returns the value of I(q) for a given q-value 
     
    595596        else: 
    596597            raise ValueError("run(q): bad type for q") 
    597      
    598     def runXY(self, q = 0): 
     598 
     599    def runXY(self, q=0): 
    599600        """ 
    600601            Standard run command for the canvas. 
    601             Redirects to the correct method  
     602            Redirects to the correct method 
    602603            according to the input type. 
    603604            @param q: q-value [float] or [list] [A-1] 
     
    615616        else: 
    616617            raise ValueError("runXY(q): bad type for q") 
    617      
     618 
    618619    def _create_modelObject(self): 
    619620        """ 
    620621            Create the simulation model obejct from the list 
    621622            of shapes. 
    622              
     623 
    623624            This method needs to be called each time a parameter 
    624625            changes because of the way the underlying library 
    625             was (badly) written. It is impossible to change a  
    626             parameter, or remove a shape without having to  
     626            was (badly) written. It is impossible to change a 
     627            parameter, or remove a shape without having to 
    627628            refill the space points. 
    628              
     629 
    629630            TODO: improve that. 
    630631        """ 
    631632        # To find a complete example of the correct call order: 
    632633        # In LORES2, in actionclass.py, method CalculateAction._get_iq() 
    633          
     634 
    634635        # If there are not shapes, do nothing 
    635636        if len(self.shapes) == 0: 
    636637            self._model_changed() 
    637638            return 0 
    638          
     639 
    639640        # generate space filling points from shape list 
    640641        self._createVolumeFromList() 
     
    642643        self.points = pointsmodelpy.new_point3dvec() 
    643644 
    644         pointsmodelpy.complexmodel_add(self.complex_model,  
    645                                         self.lores_model, "LORES") 
     645        pointsmodelpy.complexmodel_add(self.complex_model, 
     646                                       self.lores_model, "LORES") 
    646647        for shape in self.shapes: 
    647             if self.shapes[shape].params['is_lores'] == False: 
    648                 pointsmodelpy.complexmodel_add(self.complex_model,  
     648            if not self.shapes[shape].params['is_lores']: 
     649                pointsmodelpy.complexmodel_add(self.complex_model, 
    649650                    self.shapes[shape].shapeObject, "PDB") 
    650          
     651 
    651652        #pointsmodelpy.get_lorespoints(self.lores_model, self.points) 
    652653        self.npts = pointsmodelpy.get_complexpoints(self.complex_model, self.points) 
    653          
    654          
     654 
     655 
    655656    def getIq2D(self, qx, qy): 
    656657        """ 
     
    660661            @return: I(q) [cm-1] 
    661662        """ 
    662          
     663 
    663664        # If this is the first simulation call, we need to generate the 
    664665        # space points 
    665666        if self.points is None: 
    666667            self._create_modelObject() 
    667              
     668 
    668669            # Protect against empty model 
    669670            if self.points is None: 
    670671                return 0 
    671                 
    672         # Evalute I(q)  
    673         norm =  1.0e8/self.params['lores_density']*self.params['scale'] 
     672 
     673        # Evalute I(q) 
     674        norm = 1.0e8/self.params['lores_density']*self.params['scale'] 
    674675        return norm*pointsmodelpy.get_complex_iq_2D(self.complex_model, self.points, qx, qy)\ 
    675676            + self.params['background'] 
    676                  
     677 
    677678    def write_pr(self, filename): 
    678679        """ 
    679680            Write P(r) to an output file 
    680681            @param filename: file name for P(r) output 
    681         """    
    682         if self.hasPr == False: 
     682        """ 
     683        if not self.hasPr: 
    683684            self.getPr() 
    684       
     685 
    685686        pointsmodelpy.outputPR(self.complex_model, filename) 
    686       
     687 
    687688    def getPrData(self): 
    688689        """ 
    689690            Write P(r) to an output file 
    690691            @param filename: file name for P(r) output 
    691         """    
    692         if self.hasPr == False: 
     692        """ 
     693        if not self.hasPr: 
    693694            self.getPr() 
    694       
     695 
    695696        return pointsmodelpy.get_pr(self.complex_model) 
    696       
     697 
    697698    def getIq(self, q): 
    698699        """ 
    699700            Returns the value of I(q) for a given q-value 
    700              
     701 
    701702            This method should remain internal to the class 
    702703            and the run() method should be used instead. 
    703              
     704 
    704705            @param q: q-value [float] 
    705706            @return: I(q) [float] 
    706707        """ 
    707          
    708         if self.hasPr == False: 
     708 
     709        if not self.hasPr: 
    709710            self.getPr() 
    710711 
    711         # By dividing by the density instead of the actuall V/N,  
    712         # we have an uncertainty of +-1 on N because the number  
     712        # By dividing by the density instead of the actuall V/N, 
     713        # we have an uncertainty of +-1 on N because the number 
    713714        # of points chosen for the simulation is int(density*volume). 
    714715        # Propagation of error gives: 
     
    716717        # where N is stored in self.npts 
    717718 
    718         norm =  1.0e8/self.params['lores_density']*self.params['scale'] 
     719        norm = 1.0e8/self.params['lores_density']*self.params['scale'] 
    719720        #return norm*pointsmodelpy.get_lores_i(self.lores_model, q) 
    720721        return norm*pointsmodelpy.get_complex_i(self.complex_model, q)\ 
    721722            + self.params['background'] 
    722      
     723 
    723724    def getError(self, q): 
    724725        """ 
     
    727728            @return: I(q) [float] 
    728729        """ 
    729          
    730         if self.hasPr == False: 
     730 
     731        if not self.hasPr: 
    731732            self.getPr() 
    732733 
    733         # By dividing by the density instead of the actual V/N,  
    734         # we have an uncertainty of +-1 on N because the number  
     734        # By dividing by the density instead of the actual V/N, 
     735        # we have an uncertainty of +-1 on N because the number 
    735736        # of points chosen for the simulation is int(density*volume). 
    736737        # Propagation of error gives: 
     
    738739        # where N is stored in self.npts 
    739740 
    740         norm =  1.0e8/self.params['lores_density']*self.params['scale'] 
     741        norm = 1.0e8/self.params['lores_density']*self.params['scale'] 
    741742        #return norm*pointsmodelpy.get_lores_i(self.lores_model, q) 
    742743        return norm*pointsmodelpy.get_complex_i_error(self.complex_model, q)\ 
    743744            + self.params['background'] 
    744      
     745 
    745746    def getIqError(self, q): 
    746747        """ 
    747748            Return the simulated value along with its estimated 
    748749            error for a given q-value 
    749              
     750 
    750751            Propagation of errors is used to evaluate the 
    751752            uncertainty. 
    752              
     753 
    753754            @param q: q-value [float] 
    754755            @return: mean, error [float, float] 
     
    765766            Return the simulated value along with its estimated 
    766767            error for a given q-value 
    767              
     768 
    768769            Propagation of errors is used to evaluate the 
    769770            uncertainty. 
    770              
     771 
    771772            @param qx: qx-value [float] 
    772773            @param qy: qy-value [float] 
     
    774775        """ 
    775776        self._create_modelObject() 
    776                  
    777         norm =  1.0e8/self.params['lores_density']*self.params['scale'] 
     777 
     778        norm = 1.0e8/self.params['lores_density']*self.params['scale'] 
    778779        val = norm*pointsmodelpy.get_complex_iq_2D(self.complex_model, self.points, qx, qy)\ 
    779780            + self.params['background'] 
    780          
     781 
    781782        # Simulation error (statistical) 
    782         norm =  1.0e8/self.params['lores_density']*self.params['scale'] \ 
    783                 * math.pow(self.npts/self.params['lores_density'], 1.0/3.0)/self.npts 
     783        norm = 1.0e8/self.params['lores_density']*self.params['scale'] \ 
     784               * math.pow(self.npts/self.params['lores_density'], 1.0/3.0)/self.npts 
    784785        err = norm*pointsmodelpy.get_complex_iq_2D_err(self.complex_model, self.points, qx, qy) 
    785786        # Error on V/N 
    786787        simerr = 2*val/self.npts 
    787          
     788 
    788789        # The error used for the position is over-simplified. 
    789790        # The actual error was empirically found to be about 
    790791        # an order of magnitude larger. 
    791792        return val, 10.0*err+simerr 
    792          
  • src/sas/sasgui/guiframe/CategoryInstaller.py

    r235f514 r65f3930  
    1919logger = logging.getLogger(__name__) 
    2020 
    21 class CategoryInstaller: 
     21class CategoryInstaller(object): 
    2222    """ 
    2323    Class for making sure all category stuff is installed 
     
    3434        returns the dir where installed_models.txt should be 
    3535        """ 
    36         import sas.sascalc.dataloader.readers 
    37         return sas.sascalc.dataloader.readers.get_data_path() 
    38  
    39     @staticmethod 
    40     def _get_models_py_dir(): 
    41         """ 
    42         returns the dir where models.py should be 
    43         """ 
    44         import sas.sasgui.perspectives.fitting.models 
    45         return sas.sasgui.perspectives.fitting.models.get_model_python_path() 
     36        from sas.sascalc.dataloader.readers import get_data_path 
     37        return get_data_path() 
    4638 
    4739    @staticmethod 
     
    8577        by_model_dict = defaultdict(list) 
    8678        model_enabled_dict = defaultdict(bool) 
    87          
     79 
    8880        for category in master_category_dict: 
    8981            for (model, enabled) in master_category_dict[category]: 
     
    9688    def _regenerate_master_dict(by_model_dict, model_enabled_dict): 
    9789        """ 
    98         regenerates master_category_dict from by_model_dict  
     90        regenerates master_category_dict from by_model_dict 
    9991        and model_enabled_dict 
    10092        returns the master category dictionary 
     
    128120               which are user supplied. 
    129121        """ 
    130         _model_dict = { model.name: model for model in model_list} 
     122        _model_dict = {model.name: model for model in model_list} 
    131123        _model_list = _model_dict.keys() 
    132124 
     
    150142                model_name, enabled = master_category_dict[cat][ind] 
    151143                if model_name not in _model_list: 
    152                     del_name = True  
     144                    del_name = True 
    153145                    try: 
    154146                        by_model_dict.pop(model_name) 
    155147                        model_enabled_dict.pop(model_name) 
    156                     except: 
     148                    except Exception: 
    157149                        logger.error("CategoryInstaller: %s", sys.exc_value) 
    158150                else: 
     
    160152        if del_name or (len(add_list) > 0): 
    161153            for model in add_list: 
    162                 model_enabled_dict[model]= True 
    163                 if _model_dict[model].category is None or len(str(_model_dict[model].category.capitalize())) == 0: 
     154                model_enabled_dict[model] = True 
     155                # TODO: should be:  not _model_dict[model].category 
     156                if (_model_dict[model].category is None 
     157                        or len(str(_model_dict[model].category.capitalize())) == 0): 
    164158                    by_model_dict[model].append('Uncategorized') 
    165159                else: 
  • src/sas/sasgui/perspectives/calculator/model_editor.py

    r23359ccb r23359ccb  
    3131import re 
    3232import logging 
     33import datetime 
     34 
    3335from wx.py.editwindow import EditWindow 
     36 
    3437from sas.sasgui.guiframe.documentation_window import DocumentationWindow 
     38 
    3539from .pyconsole import show_model_output, check_model 
    3640 
    3741logger = logging.getLogger(__name__) 
    38  
    3942 
    4043if sys.platform.count("win32") > 0: 
     
    7881    a Modal Dialog. 
    7982 
    80     :TODO the build in compiler currently balks at when it tries to import 
     83    :TODO the built in compiler currently balks at when it tries to import 
    8184    a model whose name contains spaces or symbols (such as + ... underscore 
    8285    should be fine).  Have fixed so the editor cannot save such a file name 
     
    335338            list_fnames = os.listdir(self.plugin_dir) 
    336339            # fake existing regular model name list 
    337             m_list = [model + ".py" for model in self.model_list] 
     340            m_list = [model.name + ".py" for model in self.model_list] 
    338341            list_fnames.append(m_list) 
    339342            if t_fname in list_fnames and title != mname: 
     
    533536            desc_line = "\nmodel_info.description = '{}'".format(description) 
    534537        name = os.path.splitext(os.path.basename(self.fname))[0] 
    535         output = SUM_TEMPLATE.format(name=name, model1=model1_name,  
     538        output = SUM_TEMPLATE.format(name=name, model1=model1_name, 
    536539            model2=model2_name, operator=self._operator, desc_line=desc_line) 
    537540        with open(self.fname, 'w') as out_f: 
     
    789792                    exec "float(math.%s)" % item 
    790793                    self.math_combo.Append(str(item)) 
    791                 except: 
     794                except Exception: 
    792795                    self.math_combo.Append(str(item) + "()") 
    793796        self.math_combo.Bind(wx.EVT_COMBOBOX, self._on_math_select) 
     
    914917            msg = "Name exists already." 
    915918 
    916         # Prepare the messagebox 
     919        # 
    917920        if self.base is not None and not msg: 
    918921            self.base.update_custom_combo() 
    919             # Passed exception in import test as it will fail for sasmodels.sasview_model class 
    920             # Should add similar test for new style? 
    921             Model = None 
    922             try: 
    923                 exec "from %s import Model" % name 
    924             except: 
    925                 logger.error(sys.exc_value) 
    926922 
    927923        # Prepare the messagebox 
     
    956952        :param func_str: content of func; Strings 
    957953        """ 
    958         try: 
    959             out_f = open(fname, 'w') 
    960         except: 
    961             raise 
    962         # Prepare the content of the function 
    963         lines = CUSTOM_TEMPLATE.split('\n') 
    964  
    965         has_scipy = func_str.count("scipy.") 
    966         if has_scipy: 
    967             lines.insert(0, 'import scipy') 
    968  
    969         # Think about 2D later 
    970         #self.is_2d = func_str.count("#self.ndim = 2") 
    971         #line_2d = '' 
    972         #if self.is_2d: 
    973         #    line_2d = CUSTOM_2D_TEMP.split('\n') 
    974  
    975         # Also think about test later 
    976         #line_test = TEST_TEMPLATE.split('\n') 
    977         #local_params = '' 
    978         #spaces = '        '#8spaces 
    979         spaces4  = ' '*4 
    980         spaces13 = ' '*13 
    981         spaces16 = ' '*16 
     954        out_f = open(fname, 'w') 
     955 
     956        out_f.write(CUSTOM_TEMPLATE % { 
     957            'name': name, 
     958            'title': 'User model for ' + name, 
     959            'description': desc_str, 
     960            'date': datetime.datetime.now().strftime('%YYYY-%mm-%dd'), 
     961        }) 
     962 
     963        # Write out parameters 
    982964        param_names = []    # to store parameter names 
    983         has_scipy = func_str.count("scipy.") 
    984         if has_scipy: 
    985             lines.insert(0, 'import scipy') 
    986  
    987         # write function here 
    988         for line in lines: 
    989             # The location where to put the strings is 
    990             # hard-coded in the template as shown below. 
    991             out_f.write(line + '\n') 
    992             if line.count('#name'): 
    993                 out_f.write('name = "%s" \n' % name) 
    994             elif line.count('#title'): 
    995                 out_f.write('title = "User model for %s"\n' % name) 
    996             elif line.count('#description'): 
    997                 out_f.write('description = "%s"\n' % desc_str) 
    998             elif line.count('#parameters'): 
    999                 out_f.write('parameters = [ \n') 
    1000                 for param_line in param_str.split('\n'): 
    1001                     p_line = param_line.lstrip().rstrip() 
    1002                     if p_line: 
    1003                         pname, pvalue, desc = self.get_param_helper(p_line) 
    1004                         param_names.append(pname) 
    1005                         out_f.write("%s['%s', '', %s, [-numpy.inf, numpy.inf], '', '%s'],\n" % (spaces16, pname, pvalue, desc)) 
    1006                 for param_line in pd_param_str.split('\n'): 
    1007                     p_line = param_line.lstrip().rstrip() 
    1008                     if p_line: 
    1009                         pname, pvalue, desc = self.get_param_helper(p_line) 
    1010                         param_names.append(pname) 
    1011                         out_f.write("%s['%s', '', %s, [-numpy.inf, numpy.inf], 'volume', '%s'],\n" % (spaces16, pname, pvalue, desc)) 
    1012                 out_f.write('%s]\n' % spaces13) 
    1013  
    1014         # No form_volume or ER available in simple model editor 
    1015         out_f.write('def form_volume(*arg): \n') 
    1016         out_f.write('    return 1.0 \n') 
    1017         out_f.write('\n') 
    1018         out_f.write('def ER(*arg): \n') 
    1019         out_f.write('    return 1.0 \n') 
    1020  
    1021         # function to compute 
    1022         out_f.write('\n') 
    1023         out_f.write('def Iq(x ') 
    1024         for name in param_names: 
    1025             out_f.write(', %s' % name) 
    1026         out_f.write('):\n') 
     965        pd_params = [] 
     966        out_f.write('parameters = [ \n') 
     967        out_f.write('#   ["name", "units", default, [lower, upper], "type", "description"],\n') 
     968        for pname, pvalue, desc in self.get_param_helper(param_str): 
     969            param_names.append(pname) 
     970            out_f.write("    ['%s', '', %s, [-inf, inf], '', '%s'],\n" 
     971                        % (pname, pvalue, desc)) 
     972        for pname, pvalue, desc in self.get_param_helper(pd_param_str): 
     973            param_names.append(pname) 
     974            pd_params.append(pname) 
     975            out_f.write("    ['%s', '', %s, [-inf, inf], 'volume', '%s'],\n" 
     976                        % (pname, pvalue, desc)) 
     977        out_f.write('    ]\n') 
     978 
     979        # Write out function definition 
     980        out_f.write('def Iq(%s):\n' % ', '.join(['x'] + param_names)) 
     981        out_f.write('    """Absolute scattering"""\n') 
     982        if "scipy." in func_str: 
     983            out_f.write('    import scipy') 
     984        if "numpy." in func_str: 
     985            out_f.write('    import numpy') 
     986        if "np." in func_str: 
     987            out_f.write('    import numpy as np') 
    1027988        for func_line in func_str.split('\n'): 
    1028989            out_f.write('%s%s\n' % (spaces4, func_line)) 
    1029  
    1030         Iqxy_string = 'return Iq(numpy.sqrt(x**2+y**2) ' 
    1031  
     990        out_f.write('## uncomment the following if Iq works for vector x\n') 
     991        out_f.write('#Iq.vectorized = True\n') 
     992 
     993        # If polydisperse, create place holders for form_volume, ER and VR 
     994        if pd_params: 
     995            out_f.write('\n') 
     996            out_f.write(CUSTOM_TEMPLATE_PD % {'args': ', '.join(pd_params)}) 
     997 
     998        # Create place holder for Iqxy 
    1032999        out_f.write('\n') 
    1033         out_f.write('def Iqxy(x, y ') 
    1034         for name in param_names: 
    1035             out_f.write(', %s' % name) 
    1036             Iqxy_string += ', ' + name 
    1037         out_f.write('):\n') 
    1038         Iqxy_string += ')' 
    1039         out_f.write('%s%s\n' % (spaces4, Iqxy_string)) 
     1000        out_f.write('#def Iqxy(%s):\n' % ', '.join(["x", "y"] + param_names)) 
     1001        out_f.write('#    """Absolute scattering of oriented particles."""\n') 
     1002        out_f.write('#    ...\n') 
     1003        out_f.write('#    return oriented_form(x, y, args)\n') 
     1004        out_f.write('## uncomment the following if Iqxy works for vector x, y\n') 
     1005        out_f.write('#Iqxy.vectorized = True\n') 
    10401006 
    10411007        out_f.close() 
    10421008 
    1043     def get_param_helper(self, line): 
    1044         """ 
    1045         Get string in line to define the params dictionary 
    1046  
    1047         :param line: one line of string got from the param_str 
    1048         """ 
    1049         items = line.split(";") 
    1050         for item in items: 
    1051             name = item.split("=")[0].strip() 
    1052             description = "" 
    1053             try: 
    1054                 value = item.split("=")[1].strip() 
    1055                 if value.count("#"): 
    1056                     # If line ends in a comment, remove it before parsing float 
    1057                     index = value.index("#") 
    1058                     description = value[(index + 1):].strip() 
    1059                     value = value[:value.index("#")].strip() 
    1060                 float(value) 
    1061             except ValueError: 
    1062                 value = 1.0 # default 
    1063  
    1064         return name, value, description 
     1009    def get_param_helper(self, param_str): 
     1010        """ 
     1011        yield a sequence of name, value pairs for the parameters in param_str 
     1012 
     1013        Parameters can be defined by one per line by name=value, or multiple 
     1014        on the same line by separating the pairs by semicolon or comma.  The 
     1015        value is optional and defaults to "1.0". 
     1016        """ 
     1017        for line in param_str.replace(';', ',').split('\n'): 
     1018            for item in line.split(','): 
     1019                defn, desc = item.split('#', 1) if '#' in item else (item, '') 
     1020                name, value = defn.split('=', 1) if '=' in defn else (defn, '1.0') 
     1021                if name: 
     1022                    yield [v.strip() for v in (name, value, desc)] 
    10651023 
    10661024    def set_function_helper(self, line): 
     
    10961054        running "file:///...." 
    10971055 
    1098     :param evt: Triggers on clicking the help button 
    1099     """ 
     1056        :param evt: Triggers on clicking the help button 
     1057        """ 
    11001058 
    11011059        _TreeLocation = "user/sasgui/perspectives/fitting/fitting_help.html" 
     
    11401098## Templates for plugin models 
    11411099 
    1142 CUSTOM_TEMPLATE = """ 
     1100CUSTOM_TEMPLATE = '''\ 
     1101r""" 
     1102Definition 
     1103---------- 
     1104 
     1105Calculates %(name)s. 
     1106 
     1107%(description)s 
     1108 
     1109References 
     1110---------- 
     1111 
     1112Authorship and Verification 
     1113--------------------------- 
     1114 
     1115* **Author:** --- **Date:** %(date)s 
     1116* **Last Modified by:** --- **Date:** %(date)s 
     1117* **Last Reviewed by:** --- **Date:** %(date)s 
     1118""" 
     1119 
    11431120from math import * 
    1144 import os 
    1145 import sys 
    1146 import numpy 
    1147  
    1148 #name 
    1149  
    1150 #title 
    1151  
    1152 #description 
    1153  
    1154 #parameters 
    1155  
    1156 """ 
    1157  
    1158 CUSTOM_2D_TEMP = """ 
    1159     def run(self, x=0.0, y=0.0): 
    1160         if x.__class__.__name__ == 'list': 
    1161             x_val = x[0] 
    1162             y_val = y[0]*0.0 
    1163             return self.function(x_val, y_val) 
    1164         elif x.__class__.__name__ == 'tuple': 
    1165             msg = "Tuples are not allowed as input to BaseComponent models" 
    1166             raise ValueError, msg 
    1167         else: 
    1168             return self.function(x, 0.0) 
    1169     def runXY(self, x=0.0, y=0.0): 
    1170         if x.__class__.__name__ == 'list': 
    1171             return self.function(x, y) 
    1172         elif x.__class__.__name__ == 'tuple': 
    1173             msg = "Tuples are not allowed as input to BaseComponent models" 
    1174             raise ValueError, msg 
    1175         else: 
    1176             return self.function(x, y) 
    1177     def evalDistribution(self, qdist): 
    1178         if qdist.__class__.__name__ == 'list': 
    1179             msg = "evalDistribution expects a list of 2 ndarrays" 
    1180             if len(qdist)!=2: 
    1181                 raise RuntimeError, msg 
    1182             if qdist[0].__class__.__name__ != 'ndarray': 
    1183                 raise RuntimeError, msg 
    1184             if qdist[1].__class__.__name__ != 'ndarray': 
    1185                 raise RuntimeError, msg 
    1186             v_model = numpy.vectorize(self.runXY, otypes=[float]) 
    1187             iq_array = v_model(qdist[0], qdist[1]) 
    1188             return iq_array 
    1189         elif qdist.__class__.__name__ == 'ndarray': 
    1190             v_model = numpy.vectorize(self.runXY, otypes=[float]) 
    1191             iq_array = v_model(qdist) 
    1192             return iq_array 
    1193 """ 
    1194 TEST_TEMPLATE = """ 
    1195 ###################################################################### 
    1196 ## THIS IS FOR TEST. DO NOT MODIFY THE FOLLOWING LINES!!!!!!!!!!!!!!!! 
    1197 if __name__ == "__main__": 
    1198     m= Model() 
    1199     out1 = m.runXY(0.0) 
    1200     out2 = m.runXY(0.01) 
    1201     isfine1 = numpy.isfinite(out1) 
    1202     isfine2 = numpy.isfinite(out2) 
    1203     print "Testing the value at Q = 0.0:" 
    1204     print out1, " : finite? ", isfine1 
    1205     print "Testing the value at Q = 0.01:" 
    1206     print out2, " : finite? ", isfine2 
    1207     if isfine1 and isfine2: 
    1208         print "===> Simple Test: Passed!" 
    1209     else: 
    1210         print "===> Simple Test: Failed!" 
    1211 """ 
     1121from numpy import inf 
     1122 
     1123name = "%(name)s" 
     1124title = "%(title)s" 
     1125description = """%(description)s""" 
     1126 
     1127''' 
     1128 
     1129CUSTOM_TEMPLATE_PD = '''\ 
     1130def form_volume(%(args)s): 
     1131    """ 
     1132    Volume of the particles used to compute absolute scattering intensity 
     1133    and to weight polydisperse parameter contributions. 
     1134    """ 
     1135    return 0.0 
     1136 
     1137def ER(%(args)s): 
     1138    """ 
     1139    Effective radius of particles to be used when computing structure factors. 
     1140 
     1141    Input parameters are vectors ranging over the mesh of polydispersity values. 
     1142    """ 
     1143    return 0.0 
     1144 
     1145def VR(%(args)s): 
     1146    """ 
     1147    Volume ratio of particles to be used when computing structure factors. 
     1148 
     1149    Input parameters are vectors ranging over the mesh of polydispersity values. 
     1150    """ 
     1151    return 1.0 
     1152''' 
     1153 
    12121154SUM_TEMPLATE = """ 
    12131155from sasmodels.core import load_model_info 
     
    12191161""" 
    12201162if __name__ == "__main__": 
    1221 #    app = wx.PySimpleApp() 
    12221163    main_app = wx.App() 
    12231164    main_frame = TextDialog(id=1, model_list=["SphereModel", "CylinderModel"], 
    1224                        plugin_dir='../fitting/plugin_models') 
     1165                            plugin_dir='../fitting/plugin_models') 
    12251166    main_frame.ShowModal() 
    12261167    main_app.MainLoop() 
    1227  
    1228 #if __name__ == "__main__": 
    1229 #    from sas.sasgui.perspectives.fitting import models 
    1230 #    dir_path = models.find_plugins_dir() 
    1231 #    app = wx.App() 
    1232 #    window = EditorWindow(parent=None, base=None, path=dir_path, title="Editor") 
    1233 #    app.MainLoop() 
  • src/sas/sasgui/perspectives/fitting/basepage.py

    r33dc18f r33dc18f  
    66import sys 
    77import os 
    8 import wx 
    9 import numpy as np 
    108import time 
    119import copy 
     
    1412import logging 
    1513import traceback 
    16  
    1714from collections import defaultdict 
     15 
     16import numpy as np 
     17 
     18import wx 
    1819from wx.lib.scrolledpanel import ScrolledPanel 
    1920 
     21from sasmodels.sasview_model import MultiplicationModel 
    2022from sasmodels.weights import MODELS as POLYDISPERSITY_MODELS 
     23from sasmodels.weights import GaussianDispersion 
     24 
     25from sas.sascalc.dataloader.data_info import Detector 
     26from sas.sascalc.dataloader.data_info import Source 
     27from sas.sascalc.fit.pagestate import PageState 
     28from sas.sascalc.fit.models import PLUGIN_NAME_BASE 
    2129 
    2230from sas.sasgui.guiframe.panel_base import PanelBase 
     
    3038from sas.sasgui.guiframe.dataFitting import check_data_validity 
    3139from sas.sasgui.guiframe.gui_style import GUIFRAME_ID 
    32 from sas.sascalc.dataloader.data_info import Detector 
    33 from sas.sascalc.dataloader.data_info import Source 
    34 from sas.sasgui.perspectives.fitting.pagestate import PageState 
    3540from sas.sasgui.guiframe.CategoryInstaller import CategoryInstaller 
    3641from sas.sasgui.guiframe.documentation_window import DocumentationWindow 
     42 
     43from .report_dialog import ReportDialog 
     44from .utils import get_weight 
    3745 
    3846logger = logging.getLogger(__name__) 
     
    153161        self.disp_cb_dict = {} 
    154162 
    155         # self.state = PageState(parent=parent) 
     163        # self.state = PageState() 
    156164        # dictionary containing list of models 
    157165        self.model_list_box = {} 
     
    200208        self.fitrange = True 
    201209        # Create memento to save the current state 
    202         self.state = PageState(parent=self.parent, 
    203                                model=self.model, data=self.data) 
     210        self.state = PageState(model=self.model, data=self.data) 
    204211        # flag to determine if state has change 
    205212        self.state_change = False 
     
    282289        """ 
    283290        x = np.linspace(start=self.qmin_x, stop=self.qmax_x, 
    284                            num=self.npts_x, endpoint=True) 
     291                        num=self.npts_x, endpoint=True) 
    285292        self.data = Data1D(x=x) 
    286293        self.data.xaxis('\\rm{Q}', "A^{-1}") 
     
    308315 
    309316        x = np.logspace(start=qmin, stop=qmax, 
    310                            num=self.npts_x, endpoint=True, base=10.0) 
     317                        num=self.npts_x, endpoint=True, base=10.0) 
    311318        self.data = Data1D(x=x) 
    312319        self.data.xaxis('\\rm{Q}', "A^{-1}") 
     
    497504        self.state.manager = manager 
    498505 
    499     def populate_box(self, model_dict): 
     506    def populate_box(self, model_list_box): 
    500507        """ 
    501508        Store list of model 
    502509 
    503         :param model_dict: dictionary containing list of models 
    504  
    505         """ 
    506         self.model_list_box = model_dict 
    507         self.state.model_list_box = self.model_list_box 
     510        :param model_list_box: dictionary containing categorized models 
     511        """ 
     512        self.model_list_box = model_list_box 
    508513        self.initialize_combox() 
    509514 
    510     def set_model_dictionary(self, model_dict): 
     515    def set_model_dictionary(self, model_dictionary): 
    511516        """ 
    512517        Store a dictionary linking model name -> model object 
    513518 
    514         :param model_dict: dictionary containing list of models 
    515         """ 
    516         self.model_dict = model_dict 
     519        :param model_dictionary: dictionary containing all models 
     520        """ 
     521        self.model_dictionary = model_dictionary 
    517522 
    518523    def initialize_combox(self): 
     
    520525        put default value in the combo box 
    521526        """ 
    522         if self.model_list_box is not None and len(self.model_list_box) > 0: 
     527        if self.model_list_box: 
    523528            self._populate_box(self.structurebox, 
    524529                               self.model_list_box["Structure Factors"]) 
     
    619624        # Get plot image from plotpanel 
    620625        images, canvases = self.get_images() 
    621         # get the report dialog 
    622         self.state.report(images, canvases) 
     626        imgRAM, images, refs = self._build_plots_for_report(images, canvases) 
     627 
     628        # get the strings for report 
     629        report_str, text_str = self.state.report(fig_urls=refs) 
     630 
     631        # Show the dialog 
     632        report_list = [report_str, text_str, images] 
     633        dialog = ReportDialog(report_list, None, wx.ID_ANY, "") 
     634        dialog.Show() 
     635 
     636    def _build_plots_for_report(self, figs, canvases): 
     637        """ 
     638        Build image state that wx.html understand 
     639        by plotting, putting it into wx.FileSystem image object 
     640        """ 
     641        images = [] 
     642        refs = [] 
     643 
     644        # For no figures in the list, prepare empty plot 
     645        if figs is None or len(figs) == 0: 
     646            figs = [None] 
     647 
     648        # Loop over the list of figures 
     649        # use wx.MemoryFSHandler 
     650        imgRAM = wx.MemoryFSHandler() 
     651        for fig in figs: 
     652            if fig is not None: 
     653                ind = figs.index(fig) 
     654                canvas = canvases[ind] 
     655 
     656            # store the image in wx.FileSystem Object 
     657            wx.FileSystem.AddHandler(wx.MemoryFSHandler()) 
     658 
     659            # index of the fig 
     660            ind = figs.index(fig) 
     661 
     662            # AddFile, image can be retrieved with 'memory:filename' 
     663            name = 'img_fit%s.png' % ind 
     664            refs.append('memory:' + name) 
     665            imgRAM.AddFile(name, canvas.bitmap, wx.BITMAP_TYPE_PNG) 
     666 
     667            # append figs 
     668            images.append(fig) 
     669 
     670        return imgRAM, images, refs 
     671 
    623672 
    624673    def on_save(self, event): 
     
    842891            self.state.disable_disp = self.disable_disp.GetValue() 
    843892 
    844         self.state.smearer = copy.deepcopy(self.current_smearer) 
    845893        if hasattr(self, "enable_smearer"): 
    846894            self.state.enable_smearer = \ 
     
    858906        if len(self._disp_obj_dict) > 0: 
    859907            for k, v in self._disp_obj_dict.iteritems(): 
    860                 self.state._disp_obj_dict[k] = v.type 
     908                self.state.disp_obj_dict[k] = v.type 
    861909 
    862910            self.state.values = copy.deepcopy(self.values) 
     
    876924                                    self.state.str_parameters) 
    877925        self._copy_parameters_state(self.orientation_params, 
    878                                      self.state.orientation_params) 
     926                                    self.state.orientation_params) 
    879927        self._copy_parameters_state(self.orientation_params_disp, 
    880928                                    self.state.orientation_params_disp) 
     
    907955            self.state.disable_disp = self.disable_disp.GetValue() 
    908956 
    909         self.state.smearer = copy.deepcopy(self.current_smearer) 
    910957        if hasattr(self, "enable_smearer"): 
    911958            self.state.enable_smearer = \ 
     
    931978                        try: 
    932979                            self.state.disp_cb_dict[k] = v.GetValue() 
    933                         except: 
     980                        except Exception: 
    934981                            self.state.disp_cb_dict[k] = None 
    935982            if len(self._disp_obj_dict) > 0: 
    936983                for k, v in self._disp_obj_dict.iteritems(): 
    937                     self.state._disp_obj_dict[k] = v.type 
     984                    self.state.disp_obj_dict[k] = v.type 
    938985 
    939986            self.state.values = copy.deepcopy(self.values) 
     
    9771024            # to support older version 
    9781025            category_pos = int(state.categorycombobox) 
    979         except: 
     1026        except Exception: 
    9801027            category_pos = 0 
    9811028            for ind_cat in range(self.categorybox.GetCount()): 
     
    9891036            # to support older version 
    9901037            formfactor_pos = int(state.formfactorcombobox) 
    991         except: 
     1038        except Exception: 
    9921039            formfactor_pos = 0 
    9931040            for ind_form in range(self.formfactorbox.GetCount()): 
     
    10021049            # to support older version 
    10031050            structfactor_pos = int(state.structurecombobox) 
    1004         except: 
     1051        except Exception: 
    10051052            structfactor_pos = 0 
    10061053            for ind_struct in range(self.structurebox.GetCount()): 
     
    11691216        self.categorybox.Select(category_pos) 
    11701217        self._show_combox(None) 
    1171         from models import PLUGIN_NAME_BASE 
    1172         if self.categorybox.GetValue() == CUSTOM_MODEL \ 
    1173                 and PLUGIN_NAME_BASE not in state.formfactorcombobox: 
     1218        if (self.categorybox.GetValue() == CUSTOM_MODEL 
     1219                and PLUGIN_NAME_BASE not in state.formfactorcombobox): 
    11741220            state.formfactorcombobox = \ 
    11751221                PLUGIN_NAME_BASE + state.formfactorcombobox 
    11761222        formfactor_pos = 0 
    11771223        for ind_form in range(self.formfactorbox.GetCount()): 
    1178             if self.formfactorbox.GetString(ind_form) == \ 
    1179                                                 (state.formfactorcombobox): 
     1224            if (self.formfactorbox.GetString(ind_form) 
     1225                    == state.formfactorcombobox): 
    11801226                formfactor_pos = int(ind_form) 
    11811227                break 
     
    11871233            state.structurecombobox = unicode(state.structurecombobox) 
    11881234            for ind_struct in range(self.structurebox.GetCount()): 
    1189                 if self.structurebox.GetString(ind_struct) == \ 
    1190                                                 (state.structurecombobox): 
     1235                if (self.structurebox.GetString(ind_struct) 
     1236                        == state.structurecombobox): 
    11911237                    structfactor_pos = int(ind_struct) 
    11921238                    break 
     
    12391285            self.dI_sqrdata.SetValue(state.dI_sqrdata) 
    12401286            self.dI_idata.SetValue(state.dI_idata) 
    1241         except: 
     1287        except Exception: 
    12421288            # to support older state file formats 
    12431289            self.dI_noweight.SetValue(False) 
     
    12951341        self.weights = copy.deepcopy(state.weights) 
    12961342 
    1297         for key, disp_type in state._disp_obj_dict.iteritems(): 
     1343        for key, disp_type in state.disp_obj_dict.iteritems(): 
    12981344            # disp_model = disp 
    12991345            disp_model = POLYDISPERSITY_MODELS[disp_type]() 
     
    15291575                        try: 
    15301576                            self.npts_x = float(self.Npts_total.GetValue()) 
    1531                         except: 
     1577                        except Exception: 
    15321578                            flag = False 
    15331579                            return flag 
     
    15701616            return 
    15711617 
    1572         for j in range(len(listtorestore)): 
     1618        for item_page in listtorestore: 
    15731619            for param in statelist: 
    1574                 if param[1] == listtorestore[j][1]: 
    1575                     item_page = listtorestore[j] 
     1620                if param[1] == item_page[1]: 
    15761621                    item_page_info = param 
    15771622                    if (item_page_info[1] == "theta" or item_page_info[1] == 
     
    16191664        listtorestore = copy.deepcopy(statelist) 
    16201665 
    1621         for j in range(len(listtorestore)): 
    1622             item_page = listtorestore[j] 
    1623             item_page_info = statelist[j] 
     1666        for item_page, item_page_info in zip(listtorestore, statelist): 
    16241667            # change the state of the check box for simple parameters 
    1625  
    16261668            if item_page[0] is not None: 
    16271669                item_page[0].SetValue(format_number(item_page_info[0], True)) 
     
    17111753                    temp_smear = self.current_smearer 
    17121754            # compute weight for the current data 
    1713             from sas.sasgui.perspectives.fitting.utils import get_weight 
    17141755            flag = self.get_weight_flag() 
    17151756            weight = get_weight(data=self.data, is2d=self._is_2D(), flag=flag) 
     
    17371778 
    17381779        from sas.sasgui.plottools import Data1D as pf_data1d 
    1739         # from sas.sasgui.perspectives.theory.profile_dialog import SLDPanel 
    17401780        from sas.sasgui.guiframe.local_perspectives.plotting.profile_dialog \ 
    17411781            import SLDPanel 
     
    17981838            if mod_cat == CUSTOM_MODEL: 
    17991839                for model in self.model_list_box[mod_cat]: 
    1800                     m_list.append(self.model_dict[model.name]) 
     1840                    m_list.append(self.model_dictionary[model.name]) 
    18011841            else: 
    18021842                cat_dic = self.master_category_dict[mod_cat] 
    1803                 for (model, enabled) in cat_dic: 
     1843                for model, enabled in cat_dic: 
    18041844                    if enabled: 
    1805                         m_list.append(self.model_dict[model]) 
     1845                        m_list.append(self.model_dictionary[model]) 
    18061846        except Exception: 
    18071847            msg = traceback.format_exc() 
     
    18751915                    wx.PostEvent(self.parent, StatusEvent(status=msg)) 
    18761916                    return 
    1877             except: 
     1917            except Exception: 
    18781918                tcrtl.SetBackgroundColour("pink") 
    18791919                msg = "Model Error: wrong value entered: %s" % sys.exc_info()[1] 
     
    19321972                    wx.PostEvent(self._manager.parent, StatusEvent(status=msg)) 
    19331973                    return 
    1934             except: 
     1974            except Exception: 
    19351975                tcrtl.SetBackgroundColour("pink") 
    19361976                msg = "Model Error: wrong value entered: %s" % sys.exc_info()[1] 
     
    20322072 
    20332073        if struct_factor is not None: 
    2034             from sasmodels.sasview_model import MultiplicationModel 
    20352074            self.model = MultiplicationModel(form_factor(self.multi_factor), 
    20362075                                             struct_factor()) 
     
    21102149            # q value from qx and qy 
    21112150            radius = np.sqrt(data.qx_data * data.qx_data + 
    2112                                 data.qy_data * data.qy_data) 
     2151                             data.qy_data * data.qy_data) 
    21132152            # get unmasked index 
    21142153            index_data = (float(self.qmin.GetValue()) <= radius) & \ 
     
    23392378        put gaussian dispersity into current model 
    23402379        """ 
    2341         if len(self.param_toFit) > 0: 
     2380        if self.param_toFit: 
    23422381            for item in self.fittable_param: 
    23432382                if item in self.param_toFit: 
     
    23542393        self.weights = {} 
    23552394 
    2356         # from sas.models.dispersion_models import GaussianDispersion 
    2357         from sasmodels.weights import GaussianDispersion 
    2358         if len(self.disp_cb_dict) == 0: 
    2359             self.save_current_state() 
     2395        if not self.disp_cb_dict: 
    23602396            self.sizer4_4.Clear(True) 
    2361             self.Layout() 
    2362             return 
    2363         if (len(self.disp_cb_dict) > 0): 
     2397        else: 
    23642398            for p in self.disp_cb_dict: 
    23652399                # The parameter was un-selected. 
     
    24342468                self._disp_obj_dict[name1] = disp_model 
    24352469                self.model.set_dispersion(param_name, disp_model) 
    2436                 self.state._disp_obj_dict[name1] = disp_model.type 
     2470                self.state.disp_obj_dict[name1] = disp_model.type 
    24372471 
    24382472                value1 = str(format_number(self.model.getParam(name1), True)) 
     
    25492583        self._disp_obj_dict[name] = disp 
    25502584        self.model.set_dispersion(name.split('.')[0], disp) 
    2551         self.state._disp_obj_dict[name] = disp.type 
     2585        self.state.disp_obj_dict[name] = disp.type 
    25522586        self.values[name] = values 
    25532587        self.weights[name] = weights 
     
    29072941            # go through the parameters 
    29082942            strings = self._get_copy_helper(self.parameters, 
    2909                                            self.orientation_params) 
     2943                                            self.orientation_params) 
    29102944            content += strings 
    29112945 
    29122946            # go through the fittables 
    29132947            strings = self._get_copy_helper(self.fittable_param, 
    2914                                            self.orientation_params_disp) 
     2948                                            self.orientation_params_disp) 
    29152949            content += strings 
    29162950 
    29172951            # go through the fixed params 
    29182952            strings = self._get_copy_helper(self.fixed_param, 
    2919                                            self.orientation_params_disp) 
     2953                                            self.orientation_params_disp) 
    29202954            content += strings 
    29212955 
    29222956            # go through the str params 
    29232957            strings = self._get_copy_helper(self.str_parameters, 
    2924                                            self.orientation_params) 
     2958                                            self.orientation_params) 
    29252959            content += strings 
    29262960            return content 
     
    29352969        the names of parameters that have been fitted 
    29362970 
    2937         :returns: all_params - A list of all parameters, in the format of  
     2971        :returns: all_params - A list of all parameters, in the format of 
    29382972        self.parameters 
    29392973        :returns: fitted_par_names - A list of the names of parameters that have 
     
    30123046                # Only print errors for fitted parameters 
    30133047                content += param[4].GetValue() 
    3014                 content += tab  
     3048                content += tab 
    30153049 
    30163050        return content 
     
    30323066            # Do nothing if self.parameters doesn't exist 
    30333067            return False 
    3034          
    3035         content = '\\begin{table}' 
    3036         content += '\\begin{tabular}[h]' 
     3068 
     3069        content = r'\begin{table}' 
     3070        content += r'\begin{tabular}[h]' 
    30373071 
    30383072        crlf = chr(13) + chr(10) 
     
    30443078        for param in all_params: 
    30453079            content += 'l|l|' 
    3046         content += '}\hline' 
     3080        content += r'}\hline' 
    30473081        content += crlf 
    30483082 
     
    30503084        for index, param in enumerate(all_params): 
    30513085            name = param[1] # Parameter name 
    3052             content += name.replace('_', '\_')  # Escape underscores 
     3086            content += name.replace('_', r'\_')  # Escape underscores 
    30533087            if name in fitted_param_names: 
    30543088                # Only print errors for fitted parameters 
    30553089                content += ' & ' 
    3056                 content += name.replace('_', '\_') + "\_err" 
     3090                content += name.replace('_', r'\_') + r"\_err" 
    30573091            if index < len(all_params) - 1: 
    30583092                content += ' & ' 
    30593093 
    3060         content += '\\\\ \\hline' 
     3094        content += r'\\ \hline' 
    30613095        content += crlf 
    30623096 
     
    30773111            if index < len(all_params) - 1: 
    30783112                content += ' & ' 
    3079          
    3080         content += '\\\\ \\hline' 
     3113 
     3114        content += r'\\ \hline' 
    30813115        content += crlf 
    3082         content += '\\end{tabular}' 
    3083         content += '\\end{table}' 
     3116        content += r'\end{tabular}' 
     3117        content += r'\end{table}' 
    30843118 
    30853119        return content 
     
    33383372                                if name.endswith('.npts'): 
    33393373                                    pd = int(pd) 
    3340                             except: 
     3374                            except Exception: 
    33413375                                # continue 
    33423376                                if not pd and pd != '': 
     
    34243458                self._disp_obj_dict[name] = disp_model 
    34253459                self.model.set_dispersion(param_name, disp_model) 
    3426                 self.state._disp_obj_dict[name] = disp_model.type 
     3460                self.state.disp_obj_dict[name] = disp_model.type 
    34273461                # TODO: It's not an array, why update values and weights? 
    34283462                self.model._persistency_dict[param_name] = \ 
     
    35243558        self.model_box.Clear() 
    35253559 
    3526         if category == 'Plugin Models': 
     3560        if category == CUSTOM_MODEL: 
    35273561            for model in self.model_list_box[category]: 
    35283562                str_m = str(model).split(".")[0] 
     
    35303564 
    35313565        else: 
    3532             for (model, enabled) in sorted(self.master_category_dict[category], 
    3533                                            key=lambda name: name[0]): 
    3534                 if(enabled): 
     3566            for model, enabled in sorted(self.master_category_dict[category], 
     3567                                         key=lambda name: name[0]): 
     3568                if enabled: 
    35353569                    self.model_box.Append(model) 
    35363570 
     
    37733807        self.Bind(wx.EVT_SET_FOCUS, self._on_set_focus) 
    37743808        self.Bind(wx.EVT_KILL_FOCUS, self._silent_kill_focus 
    3775         if kill_focus_callback is None else kill_focus_callback) 
     3809                  if kill_focus_callback is None else kill_focus_callback) 
    37763810        self.Bind(wx.EVT_TEXT_ENTER, parent._onparamEnter 
    3777         if text_enter_callback is None else text_enter_callback) 
     3811                  if text_enter_callback is None else text_enter_callback) 
    37783812        if not ON_MAC: 
    37793813            self.Bind(wx.EVT_LEFT_UP, self._highlight_text 
    3780             if mouse_up_callback is None else mouse_up_callback) 
     3814                      if mouse_up_callback is None else mouse_up_callback) 
    37813815 
    37823816    def _on_set_focus(self, event): 
  • src/sas/sasgui/perspectives/fitting/batchfitpage.py

    r7432acb r50fcb09  
    55import wx.lib.newevent 
    66import math 
     7 
     8from sas.sascalc.fit.qsmearing import smear_selection 
     9 
    710from sas.sasgui.guiframe.events import StatusEvent 
    811from sas.sasgui.guiframe.events import NewPlotEvent 
     12from sas.sasgui.perspectives.fitting.basepage import PageInfoEvent 
     13from sas.sasgui.perspectives.fitting.fitpage import FitPage 
     14from sas.sasgui.perspectives.fitting.fitpage import check_data_validity 
    915 
    1016(Chi2UpdateEvent, EVT_CHI2_UPDATE) = wx.lib.newevent.NewEvent() 
     
    1319SMEAR_SIZE_L = 0.00 
    1420SMEAR_SIZE_H = 0.00 
    15  
    16 from sas.sasgui.perspectives.fitting.basepage import PageInfoEvent 
    17 from sas.sascalc.data_util.qsmearing import smear_selection 
    18 from sas.sasgui.perspectives.fitting.fitpage import FitPage 
    19 from sas.sasgui.perspectives.fitting.fitpage import check_data_validity 
    2021 
    2122class BatchFitPage(FitPage): 
     
    7677#         """ 
    7778#         is_2Ddata = False 
    78 #          
     79# 
    7980#         # Check if data is 2D 
    8081#         if self.data.__class__.__name__ ==  "Data2D" or \ 
    8182#                         self.enable2D: 
    8283#             is_2Ddata = True 
    83 #              
    84 #         title = "Fitting"      
     84# 
     85#         title = "Fitting" 
    8586#         self._get_smear_info() 
    86 #          
     87# 
    8788#         #Sizers 
    8889#         box_description_range = wx.StaticBox(self, wx.ID_ANY, str(title)) 
    89 #         boxsizer_range = wx.StaticBoxSizer(box_description_range, wx.VERTICAL)       
     90#         boxsizer_range = wx.StaticBoxSizer(box_description_range, wx.VERTICAL) 
    9091#         self.sizer_set_smearer = wx.BoxSizer(wx.VERTICAL) 
    9192#         #sizer_smearer = wx.BoxSizer(wx.HORIZONTAL) 
     
    9394#         self.sizer_set_masking = wx.BoxSizer(wx.HORIZONTAL) 
    9495#         sizer_chi2 = wx.BoxSizer(wx.VERTICAL) 
    95 #  
     96# 
    9697#         sizer_fit = wx.GridSizer(2, 4, 2, 6) 
    9798#         #Fit button 
     
    100101#         self.btFit.Bind(wx.EVT_BUTTON, self._onFit, id= self.btFit.GetId()) 
    101102#         self.btFit.SetToolTipString("Start fitting.") 
    102 #  
     103# 
    103104#         # Update and Draw button 
    104105#         self.draw_button = wx.Button(self, self._ids.next(), 'Compute', size=(88, 24)) 
    105106#         self.draw_button.Bind(wx.EVT_BUTTON, \ 
    106107#                               self._onDraw,id=self.draw_button.GetId()) 
    107 #         self.draw_button.SetToolTipString("Compute and Draw.")   
     108#         self.draw_button.SetToolTipString("Compute and Draw.") 
    108109#         sizer_fit.Add(self.draw_button, 0, 0) 
    109 #         sizer_fit.Add(self.btFit, 0, 0)  
     110#         sizer_fit.Add(self.btFit, 0, 0) 
    110111#         sizer_chi2.Add((-1, 5)) 
    111112#         # get smear_selection 
     
    114115#          #2D data? default 
    115116#         is_2Ddata = False 
    116 #          
     117# 
    117118#         #check if it is 2D data 
    118119#         if self.data.__class__.__name__ ==  "Data2D" or \ 
    119120#                         self.enable2D: 
    120121#             is_2Ddata = True 
    121 #              
     122# 
    122123#         self.sizer5.Clear(True) 
    123 #       
     124# 
    124125#         self.qmin  = ModelTextCtrl(self, wx.ID_ANY, size=(_BOX_WIDTH, 20), 
    125 #                                           style=wx.TE_PROCESS_ENTER,  
     126#                                           style=wx.TE_PROCESS_ENTER, 
    126127#                                     text_enter_callback = self._onQrangeEnter) 
    127128#         self.qmin.SetValue(str(self.qmin_x)) 
    128129#         self.qmin.SetToolTipString("Minimun value of Q in linear scale.") 
    129 #       
     130# 
    130131#         self.qmax  = ModelTextCtrl(self, wx.ID_ANY, size=(_BOX_WIDTH, 20), 
    131 #                                           style=wx.TE_PROCESS_ENTER,  
     132#                                           style=wx.TE_PROCESS_ENTER, 
    132133#                                         text_enter_callback=self._onQrangeEnter) 
    133134#         self.qmax.SetValue(str(self.qmax_x)) 
    134135#         self.qmax.SetToolTipString("Maximum value of Q in linear scale.") 
    135 #          
     136# 
    136137#         id = self._ids.next() 
    137138#         self.reset_qrange =wx.Button(self, id, 'Reset', size=(77, 20)) 
    138 #        
     139# 
    139140#         self.reset_qrange.Bind(wx.EVT_BUTTON, self.on_reset_clicked, id=id) 
    140141#         self.reset_qrange.SetToolTipString(\ 
    141142#                                     "Reset Q range to the default values") 
    142 #       
     143# 
    143144#         sizer_horizontal = wx.BoxSizer(wx.HORIZONTAL) 
    144145#         sizer = wx.GridSizer(2, 4, 2, 6) 
    145 #  
     146# 
    146147#         self.btEditMask = wx.Button(self, self._ids.next(),'Editor', size=(88, 23)) 
    147 #         self.btEditMask.Bind(wx.EVT_BUTTON,  
     148#         self.btEditMask.Bind(wx.EVT_BUTTON, 
    148149#                              self._onMask,id=self.btEditMask.GetId()) 
    149150#         self.btEditMask.SetToolTipString("Edit Mask.") 
    150151#         self.EditMask_title = wx.StaticText(self, wx.ID_ANY, ' Masking(2D)') 
    151 #  
     152# 
    152153#         sizer.Add(wx.StaticText(self, wx.ID_ANY, 'Q range')) 
    153154#         sizer.Add(wx.StaticText(self, wx.ID_ANY, ' Min[1/A]')) 
    154155#         sizer.Add(wx.StaticText(self, wx.ID_ANY, ' Max[1/A]')) 
    155156#         sizer.Add(self.EditMask_title) 
    156 #   
    157 #         sizer.Add(self.reset_qrange)    
     157# 
     158#         sizer.Add(self.reset_qrange) 
    158159#         sizer.Add(self.qmin) 
    159160#         sizer.Add(self.qmax) 
    160 #  
     161# 
    161162#         sizer.Add(self.btEditMask) 
    162 #         boxsizer_range.Add(sizer_chi2)  
     163#         boxsizer_range.Add(sizer_chi2) 
    163164#         boxsizer_range.Add((10, 10)) 
    164165#         boxsizer_range.Add(sizer) 
    165 #          
     166# 
    166167#         boxsizer_range.Add((10, 15)) 
    167168#         boxsizer_range.Add(sizer_fit) 
    168169#         if is_2Ddata: 
    169 #             self.btEditMask.Enable()   
    170 #             self.EditMask_title.Enable()  
     170#             self.btEditMask.Enable() 
     171#             self.EditMask_title.Enable() 
    171172#         else: 
    172 #             self.btEditMask.Disable()   
     173#             self.btEditMask.Disable() 
    173174#             self.EditMask_title.Disable() 
    174 #  
     175# 
    175176#         ## save state 
    176177#         #self.save_current_state() 
    177 #  
     178# 
    178179#         self.sizer5.Add(boxsizer_range, 0, wx.EXPAND | wx.ALL, 10) 
    179180#         self.sizer5.Layout() 
    180 #         
    181 #     def _on_select_model(self, event=None):  
     181# 
     182#     def _on_select_model(self, event=None): 
    182183#         """ 
    183184#         call back for model selection 
    184 #         """   
    185 #          
    186 #         self.Show(False)     
    187 #         self._on_select_model_helper()  
    188 #         self.set_model_param_sizer(self.model)                    
     185#         """ 
     186# 
     187#         self.Show(False) 
     188#         self._on_select_model_helper() 
     189#         self.set_model_param_sizer(self.model) 
    189190#         if self.model is None: 
    190191#             self._set_bookmark_flag(False) 
     
    199200#         self.state.structurecombobox = self.structurebox.GetCurrentSelection() 
    200201#         self.state.formfactorcombobox = self.formfactorbox.GetCurrentSelection() 
    201 #        
     202# 
    202203#         if self.model is not None: 
    203204#             self._set_copy_flag(True) 
     
    206207#                 self._set_bookmark_flag(False) 
    207208#                 self._keep.Enable(False) 
    208 #                  
     209# 
    209210#             temp_smear = None 
    210211#             ## event to post model to fit to fitting plugins 
    211212#             (ModelEventbox, _) = wx.lib.newevent.NewEvent() 
    212 #           
    213 #             ## set smearing value whether or not  
     213# 
     214#             ## set smearing value whether or not 
    214215#             #    the data contain the smearing info 
    215 #             evt = ModelEventbox(model=self.model,  
    216 #                                         smearer=temp_smear,  
     216#             evt = ModelEventbox(model=self.model, 
     217#                                         smearer=temp_smear, 
    217218#                                         qmin=float(self.qmin_x), 
    218219#                                         uid=self.uid, 
    219 #                                      qmax=float(self.qmax_x))  
    220 #     
     220#                                      qmax=float(self.qmax_x)) 
     221# 
    221222#             self._manager._on_model_panel(evt=evt) 
    222223#             self.mbox_description.SetLabel("Model [%s]" % str(self.model.name)) 
    223224#             self.state.model = self.model.clone() 
    224225#             self.state.model.name = self.model.name 
    225 #  
    226 #              
     226# 
     227# 
    227228#         if event is not None: 
    228229#             ## post state to fit panel 
    229230#             new_event = PageInfoEvent(page = self) 
    230 #             wx.PostEvent(self.parent, new_event)  
     231#             wx.PostEvent(self.parent, new_event) 
    231232#             #update list of plugins if new plugin is available 
    232233#             if self.plugin_rbutton.GetValue(): 
     
    243244#             self._draw_model() 
    244245#         self.SetupScrolling() 
    245 #         self.Show(True)    
    246 #          
     246#         self.Show(True) 
     247# 
    247248#     def _update_paramv_on_fit(self): 
    248249#         """ 
     
    253254#         self.fitrange = True 
    254255#         is_modified = False 
    255 #  
     256# 
    256257#         if self.model is not None: 
    257258#             ##Check the values 
     
    259260#             self._check_value_enter( self.fixed_param) 
    260261#             self._check_value_enter( self.parameters) 
    261 #  
    262 #             # If qmin and qmax have been modified, update qmin and qmax and  
     262# 
     263#             # If qmin and qmax have been modified, update qmin and qmax and 
    263264#              # Here we should check whether the boundaries have been modified. 
    264 #             # If qmin and qmax have been modified, update qmin and qmax and  
     265#             # If qmin and qmax have been modified, update qmin and qmax and 
    265266#             # set the is_modified flag to True 
    266267#             self.fitrange = self._validate_qrange(self.qmin, self.qmax) 
     
    273274#                     self.qmax_x = tempmax 
    274275#                 if tempmax == tempmin: 
    275 #                     flag = False     
     276#                     flag = False 
    276277#                 #temp_smearer = None 
    277278#                 if self._is_2D(): 
    278 #                     # only 2D case set mask   
     279#                     # only 2D case set mask 
    279280#                     flag = self._validate_Npts() 
    280281#                     if not flag: 
    281282#                         return flag 
    282283#             else: flag = False 
    283 #         else:  
     284#         else: 
    284285#             flag = False 
    285 #  
    286 #         #For invalid q range, disable the mask editor and fit button, vs.     
     286# 
     287#         #For invalid q range, disable the mask editor and fit button, vs. 
    287288#         if not self.fitrange: 
    288289#             #self.btFit.Disable() 
     
    293294#             if self._is_2D() and  self.data is not None: 
    294295#                 self.btEditMask.Enable(True) 
    295 #  
     296# 
    296297#         if not flag: 
    297298#             msg = "Cannot Plot or Fit :Must select a " 
    298299#             msg += " model or Fitting range is not valid!!!  " 
    299300#             wx.PostEvent(self.parent.parent, StatusEvent(status=msg)) 
    300 #          
     301# 
    301302#         self.save_current_state() 
    302 #     
    303 #         return flag   
     303# 
     304#         return flag 
    304305#     def save_current_state(self): 
    305306#         """ 
    306307#         Currently no save option implemented for batch page 
    307308#         """ 
    308 #         pass  
     309#         pass 
    309310#     def save_current_state_fit(self): 
    310311#         """ 
     
    314315#     def set_data(self, data): 
    315316#         """ 
    316 #         reset the current data  
     317#         reset the current data 
    317318#         """ 
    318319#         #id = None 
     
    340341#             self._set_save_flag(False) 
    341342#             self._set_preview_flag(True) 
    342 #    
     343# 
    343344#             self.formfactorbox.Enable() 
    344345#             self.structurebox.Enable() 
     
    346347#             #set maximum range for x in linear scale 
    347348#             if not hasattr(self.data,"data"): #Display only for 1D data fit 
    348 #                 # Minimum value of data    
     349#                 # Minimum value of data 
    349350#                 data_min = min(self.data.x) 
    350 #                 # Maximum value of data   
     351#                 # Maximum value of data 
    351352#                 data_max = max(self.data.x) 
    352 #                 self.btEditMask.Disable()   
     353#                 self.btEditMask.Disable() 
    353354#                 self.EditMask_title.Disable() 
    354355#             else: 
    355 #                  
    356 #                 ## Minimum value of data  
     356# 
     357#                 ## Minimum value of data 
    357358#                 data_min = 0 
    358 #                 x = max(math.fabs(self.data.xmin), math.fabs(self.data.xmax))  
     359#                 x = max(math.fabs(self.data.xmin), math.fabs(self.data.xmax)) 
    359360#                 y = max(math.fabs(self.data.ymin), math.fabs(self.data.ymax)) 
    360 #                 ## Maximum value of data   
     361#                 ## Maximum value of data 
    361362#                 data_max = math.sqrt(x*x + y*y) 
    362 #                 self.btEditMask.Enable()   
    363 #                 self.EditMask_title.Enable()  
    364 #  
     363#                 self.btEditMask.Enable() 
     364#                 self.EditMask_title.Enable() 
     365# 
    365366#         self.dataSource.SetValue(data_name) 
    366367#         self.qmin_x = data_min 
     
    375376#         self.state.qmin = self.qmin_x 
    376377#         self.state.qmax = self.qmax_x 
    377 #          
     378# 
    378379#         #update model plot with new data information 
    379380#         if flag: 
     
    385386#                 self.enable2D = False 
    386387#                 self.model_view.SetLabel("1D Mode") 
    387 #                  
     388# 
    388389#             self.model_view.Disable() 
    389 #              
    390 #             wx.PostEvent(self._manager.parent,  
     390# 
     391#             wx.PostEvent(self._manager.parent, 
    391392#                              NewPlotEvent(group_id=group_id, 
    392393#                                                action="delete")) 
    393394#             #plot the current selected data 
    394 #             wx.PostEvent(self._manager.parent, NewPlotEvent(plot=self.data,  
     395#             wx.PostEvent(self._manager.parent, NewPlotEvent(plot=self.data, 
    395396#                                                     title=str(self.data.title))) 
    396397#             self._manager.store_data(uid=self.uid, data=data, 
  • src/sas/sasgui/perspectives/fitting/fit_thread.py

    r959eb01 rba8d326  
    2929                 worktime=0.03, 
    3030                 reset_flag=False): 
    31         CalcThread.__init__(self, 
    32                  completefn, 
    33                  updatefn, 
    34                  yieldtime, 
    35                  worktime) 
     31        CalcThread.__init__(self, completefn, updatefn, yieldtime, worktime) 
    3632        self.handler = handler 
    3733        self.fitter = fn 
     
    9389            # Real code should not print, but this is an example... 
    9490            #print "keyboard exception" 
    95             #Stop on exception during fitting. Todo: need to put  
     91            #Stop on exception during fitting. Todo: need to put 
    9692            #some mssg and reset progress bar. 
    9793 
     
    10096            if self.handler is not None: 
    10197                self.handler.stop(msg=msg) 
    102         except: 
     98        except:  # catch-all: show every exception which stops the thread 
    10399            import traceback 
    104100            if self.handler is not None: 
  • src/sas/sasgui/perspectives/fitting/fitpage.py

    r79e6a33 r79e6a33  
    1414from sasmodels.weights import MODELS as POLYDISPERSITY_MODELS 
    1515 
     16from sas.sascalc.fit.qsmearing import smear_selection 
     17 
    1618from sas.sasgui.guiframe.events import StatusEvent, NewPlotEvent, \ 
    1719    PlotQrangeEvent 
     
    2325from sas.sasgui.perspectives.fitting.basepage import PageInfoEvent as \ 
    2426    PageInfoEvent 
    25 from sas.sascalc.data_util.qsmearing import smear_selection 
    2627from .basepage import ModelTextCtrl 
    2728 
     
    11421143            self.model.name = "M" + str(self.index_model) 
    11431144 
    1144     def _on_select_model(self, event=None): 
     1145    def _on_select_model(self, event=None, keep_pars=False): 
    11451146        """ 
    11461147        call back for model selection 
    11471148        """ 
    11481149        self.Show(False) 
    1149         copy_flag = False 
    1150         is_poly_enabled = None 
    11511150        if event is not None: 
    1152             if (event.GetEventObject() == self.formfactorbox 
    1153                     and self.structurebox.GetLabel() != 'None')\ 
    1154                     or event.GetEventObject() == self.structurebox\ 
    1155                     or event.GetEventObject() == self.multifactorbox: 
    1156                 copy_flag = self.get_copy_params() 
    1157                 is_poly_enabled = self.enable_disp.GetValue() 
     1151            control = event.GetEventObject() 
     1152            if ((control == self.formfactorbox 
     1153                 and self.structurebox.GetLabel() != 'None') 
     1154                    or control == self.structurebox 
     1155                    or control == self.multifactorbox): 
     1156                keep_pars = True 
     1157 
     1158        if keep_pars: 
     1159            saved_pars = self.get_copy_params() 
     1160            is_poly_enabled = self.enable_disp.GetValue() 
     1161        else: 
     1162            saved_pars = None 
     1163            is_poly_enabled = None 
     1164 
    11581165        try: 
    11591166            self._on_select_model_helper() 
     
    11771184        try: 
    11781185            self.set_dispers_sizer() 
    1179         except: 
     1186        except Exception: 
    11801187            pass 
    11811188        self.state.enable_disp = self.enable_disp.GetValue() 
     
    12381245            self.state.model.name = self.model.name 
    12391246 
     1247        # when select a model only from guictr/button 
     1248        if is_poly_enabled is not None: 
     1249            self.enable_disp.SetValue(is_poly_enabled) 
     1250            self.disable_disp.SetValue(not is_poly_enabled) 
     1251            self._set_dipers_Param(event=None) 
     1252            self.state.enable_disp = self.enable_disp.GetValue() 
     1253            self.state.disable_disp = self.disable_disp.GetValue() 
     1254 
     1255        # Keep the previous param values 
     1256        if saved_pars: 
     1257            self.get_paste_params(saved_pars) 
     1258 
    12401259        if event is not None: 
     1260            # update list of plugins if new plugin is available 
     1261            # mod_cat = self.categorybox.GetStringSelection() 
     1262            # if mod_cat == CUSTOM_MODEL: 
     1263            #     temp = self.parent.update_model_list() 
     1264            #     for v in self.parent.model_dictionary.values(): 
     1265            #         if v.id == self.model.id: 
     1266            #             self.model = v() 
     1267            #             break 
     1268            #     if temp: 
     1269            #         self.model_list_box = temp 
     1270            #         current_val = self.formfactorbox.GetLabel() 
     1271            #         pos = self.formfactorbox.GetSelection() 
     1272            #         self._show_combox_helper() 
     1273            #         self.formfactorbox.SetStringSelection(current_val) 
     1274            #         self.formfactorbox.SetValue(current_val) 
    12411275            # post state to fit panel 
    12421276            new_event = PageInfoEvent(page=self) 
    12431277            wx.PostEvent(self.parent, new_event) 
    1244             # update list of plugins if new plugin is available 
    1245             mod_cat = self.categorybox.GetStringSelection() 
    1246             if mod_cat == CUSTOM_MODEL: 
    1247                 temp_id = self.model.id 
    1248                 temp = self.parent.update_model_list() 
    1249                 for v in self.parent.model_dictionary.values(): 
    1250                     if v.id == temp_id: 
    1251                         self.model = v() 
    1252                         break 
    1253                 if temp: 
    1254                     self.model_list_box = temp 
    1255                     current_val = self.formfactorbox.GetLabel() 
    1256                     pos = self.formfactorbox.GetSelection() 
    1257                     self._show_combox_helper() 
    1258                     self.formfactorbox.SetSelection(pos) 
    1259                     self.formfactorbox.SetValue(current_val) 
    1260             # when select a model only from guictr/button 
    1261             if is_poly_enabled is not None: 
    1262                 self.enable_disp.SetValue(is_poly_enabled) 
    1263                 self.disable_disp.SetValue(not is_poly_enabled) 
    1264                 self._set_dipers_Param(event=None) 
    1265                 self.state.enable_disp = self.enable_disp.GetValue() 
    1266                 self.state.disable_disp = self.disable_disp.GetValue() 
    1267  
    1268             # Keep the previous param values 
    1269             if copy_flag: 
    1270                 self.get_paste_params(copy_flag) 
    12711278            wx.CallAfter(self._onDraw, None) 
    12721279 
     
    17191726                and not self.temp_multi_functional: 
    17201727            return None 
     1728        print("_set_fun_box_list", self.model.name) 
    17211729        # Get the func name list 
    17221730        list = self.model.fun_list 
     
    17261734        ind = 0 
    17271735        while(ind < len(list)): 
    1728             for key, val in list.iteritems(): 
    1729                 if (val == ind): 
     1736            for key, val in list.items(): 
     1737                if val == ind: 
    17301738                    fun_box.Append(key, val) 
    17311739                    break 
  • src/sas/sasgui/perspectives/fitting/fitpanel.py

    rc9ecd1b rc9ecd1b  
    99from wx.aui import AuiNotebook as nb 
    1010 
     11from sas.sascalc.fit.models import ModelManager 
     12 
    1113from sas.sasgui.guiframe.panel_base import PanelBase 
    1214from sas.sasgui.guiframe.events import PanelOnFocusEvent, StatusEvent 
    1315from sas.sasgui.guiframe.dataFitting import check_data_validity 
    14 from sas.sasgui.perspectives.fitting.simfitpage import SimultaneousFitPage 
    15  
    16 import basepage 
    17 import models 
     16 
     17 
     18from . import basepage 
     19from .fitpage import FitPage 
     20from .simfitpage import SimultaneousFitPage 
     21from .batchfitpage import BatchFitPage 
     22from .fitting_widgets import BatchDataDialog 
     23 
    1824_BOX_WIDTH = 80 
    1925 
     
    4652        self.event_owner = None 
    4753        # dictionary of miodel {model class name, model class} 
    48         self.menu_mng = models.ModelManager() 
     54        self.menu_mng = ModelManager() 
    4955        self.model_list_box = self.menu_mng.get_model_list() 
    5056        # pageClosedEvent = nb.EVT_FLATNOTEBOOK_PAGE_CLOSING 
     
    114120        """ 
    115121        temp = self.menu_mng.update() 
    116         if len(temp): 
     122        if temp: 
    117123            self.model_list_box = temp 
    118124        return temp 
     
    121127        """ 
    122128        """ 
    123         temp = self.menu_mng.plugins_reset() 
    124         if len(temp): 
    125             self.model_list_box = temp 
    126         return temp 
     129        self.model_list_box = self.menu_mng.plugins_reset() 
     130        return self.model_list_box 
    127131 
    128132    def get_page_by_id(self, uid): 
     
    298302        self.model_list_box = dict 
    299303 
    300     def set_model_dict(self, m_dict): 
     304    def set_model_dictionary(self, model_dictionary): 
    301305        """ 
    302306        copy a dictionary of model name -> model object 
    303307 
    304         :param m_dict: dictionary linking model name -> model object 
     308        :param model_dictionary: dictionary linking model name -> model object 
    305309        """ 
    306310 
     
    316320        Add the simultaneous fit page 
    317321        """ 
    318         from simfitpage import SimultaneousFitPage 
    319322        page_finder = self._manager.get_page_finder() 
    320323        if caption == "Const & Simul Fit": 
     
    344347        """ 
    345348        if self.batch_on: 
    346             from batchfitpage import BatchFitPage 
    347349            panel = BatchFitPage(parent=self) 
    348350            self.batch_page_index += 1 
     
    351353        else: 
    352354            # Increment index of fit page 
    353             from fitpage import FitPage 
    354355            panel = FitPage(parent=self) 
    355356            self.fit_page_index += 1 
     
    359360        panel._set_save_flag(not panel.batch_on) 
    360361        panel.set_model_dictionary(self.model_dictionary) 
    361         panel.populate_box(model_dict=self.model_list_box) 
     362        panel.populate_box(model_list_box=self.model_list_box) 
    362363        panel.formfactor_combo_init() 
    363364        panel.set_manager(self._manager) 
     
    445446        if data_1d_list and data_2d_list: 
    446447            # need to warning the user that this batch is a special case 
    447             from sas.sasgui.perspectives.fitting.fitting_widgets import \ 
    448                 BatchDataDialog 
    449448            dlg = BatchDataDialog(self) 
    450449            if dlg.ShowModal() == wx.ID_OK: 
  • src/sas/sasgui/perspectives/fitting/fitproblem.py

    r959eb01 r251ef684  
    1414################################################################################ 
    1515import copy 
    16 from sas.sascalc.data_util.qsmearing import smear_selection 
    17  
    18 class FitProblemComponent(object): 
     16 
     17from sas.sascalc.fit.qsmearing import smear_selection 
     18 
     19class FitProblem(object): 
    1920    """ 
    20     Inferface containing information to store data, model, range of data, etc... 
    21     and retreive this information. This is an inferface 
    22     for a fitProblem i.e relationship between data and model. 
     21    Define the relationship between data and model, including range, weights, 
     22    etc. 
    2323    """ 
     24    def __init__(self): 
     25        """ 
     26        contains information about data and model to fit 
     27        """ 
     28        ## data used for fitting 
     29        self.fit_data = None 
     30        self.theory_data = None 
     31        self.residuals = None 
     32        # original data: should not be modified 
     33        self.original_data = None 
     34        ## the current model 
     35        self.model = None 
     36        ## if 1 this fit problem will be selected to fit , if 0 
     37        ## it will not be selected for fit 
     38        self.schedule = 0 
     39        ##list containing parameter name and value 
     40        self.list_param = [] 
     41        self.list_param2fit = [] 
     42        ## smear object to smear or not data1D 
     43        self.smearer_computed = False 
     44        self.smearer_enable = False 
     45        self.smearer_computer_value = None 
     46        ## fitting range 
     47        self.qmin = None 
     48        self.qmax = None 
     49        # fit weight 
     50        self.weight = None 
     51        self.result = None 
     52        self.fit_tab_caption = None 
     53        self.name_per_page = None 
     54 
    2455    def enable_smearing(self, flag=False): 
    2556        """ 
     
    2758            flag is 0 ingore smear value. 
    2859        """ 
     60        self.smearer_enable = flag 
     61 
     62    def set_smearer(self, smearer): 
     63        """ 
     64        save reference of  smear object on fitdata 
     65 
     66        :param smear: smear object from DataLoader 
     67 
     68        """ 
     69        self.smearer_computer_value = smearer 
    2970 
    3071    def get_smearer(self): 
     
    3273        return smear object 
    3374        """ 
     75        if not self.smearer_enable: 
     76            return None 
     77        if not self.smearer_computed: 
     78            #smeari_selection should be call only once per fitproblem 
     79            self.smearer_computer_value = smear_selection(self.fit_data, 
     80                                                          self.model) 
     81            self.smearer_computed = True 
     82        return self.smearer_computer_value 
     83 
    3484    def save_model_name(self, name): 
    3585        """ 
    3686        """ 
     87        self.name_per_page = name 
    3788 
    3889    def get_name(self): 
    3990        """ 
    4091        """ 
     92        return self.name_per_page 
    4193 
    4294    def set_model(self, model): 
     
    4698        :param name: name created for model 
    4799        """ 
     100        self.model = model 
     101        self.smearer_computer_value = smear_selection(self.fit_data, 
     102                                                      self.model) 
     103        self.smearer_computed = True 
    48104 
    49105    def get_model(self): 
     
    51107        :return: saved model 
    52108        """ 
     109        return self.model 
    53110 
    54111    def set_residuals(self, residuals): 
     
    57114        :param data: data selected 
    58115        """ 
     116        self.residuals = residuals 
    59117 
    60118    def get_residuals(self): 
     
    62120        :return: residuals 
    63121        """ 
     122        return self.residuals 
    64123 
    65124    def set_theory_data(self, data): 
    66125        """ 
    67126        save a copy of the data select to fit 
     127 
    68128        :param data: data selected 
    69         """ 
     129 
     130        """ 
     131        self.theory_data = copy.deepcopy(data) 
    70132 
    71133    def get_theory_data(self): 
    72134        """ 
    73         :return: list of data dList 
    74         """ 
     135        :return: theory generated with the current model and data of this class 
     136        """ 
     137        return self.theory_data 
    75138 
    76139    def set_fit_data(self, data): 
    77140        """ 
    78         Store of list of data and create  by create new fitproblem of each data 
    79         id, if there was existing information about model, this information 
    80         get copy to the new fitproblem 
     141        Store data associated with this class 
    81142        :param data: list of data selected 
    82143        """ 
     144        self.original_data = None 
     145        self.fit_data = None 
     146        # original data: should not be modified 
     147        self.original_data = data 
     148        # fit data: used for fit and can be modified for convenience 
     149        self.fit_data = copy.deepcopy(data) 
     150        self.smearer_computer_value = smear_selection(self.fit_data, self.model) 
     151        self.smearer_computed = True 
     152        self.result = None 
    83153 
    84154    def get_fit_data(self): 
    85155        """ 
    86         """ 
     156        :return: data associate with this class 
     157        """ 
     158        return self.fit_data 
     159 
     160    def get_origin_data(self): 
     161        """ 
     162        """ 
     163        return self.original_data 
     164 
     165    def set_weight(self, is2d, flag=None): 
     166        """ 
     167        Received flag and compute error on data. 
     168        :param flag: flag to transform error of data. 
     169        :param is2d: flag to distinguish 1D to 2D Data 
     170        """ 
     171        from sas.sasgui.perspectives.fitting.utils import get_weight 
     172        # send original data for weighting 
     173        self.weight = get_weight(data=self.original_data, is2d=is2d, flag=flag) 
     174        if is2d: 
     175            self.fit_data.err_data = self.weight 
     176        else: 
     177            self.fit_data.dy = self.weight 
     178 
     179    def get_weight(self): 
     180        """ 
     181        returns weight array 
     182        """ 
     183        return self.weight 
     184 
     185    def set_param2fit(self, list): 
     186        """ 
     187        Store param names to fit (checked) 
     188        :param list: list of the param names 
     189        """ 
     190        self.list_param2fit = list 
     191 
     192    def get_param2fit(self): 
     193        """ 
     194        return the list param names to fit 
     195        """ 
     196        return self.list_param2fit 
    87197 
    88198    def set_model_param(self, name, value=None): 
     
    92202        :param value: value of that parameter 
    93203        """ 
    94  
    95     def set_param2fit(self, list): 
    96         """ 
    97         Store param names to fit (checked) 
    98         :param list: list of the param names 
    99         """ 
    100  
    101     def get_param2fit(self): 
    102         """ 
    103         return the list param names to fit 
    104         """ 
     204        self.list_param.append([name, value]) 
    105205 
    106206    def get_model_param(self): 
     
    108208        return list of couple of parameter name and value 
    109209        """ 
     210        return self.list_param 
    110211 
    111212    def schedule_tofit(self, schedule=0): 
     
    113214        set schedule to true to decide if this fit  must be performed 
    114215        """ 
     216        self.schedule = schedule 
    115217 
    116218    def get_scheduled(self): 
     
    118220        return true or false if a problem as being schedule for fitting 
    119221        """ 
     222        return self.schedule 
    120223 
    121224    def set_range(self, qmin=None, qmax=None): 
    122225        """ 
    123226        set fitting range 
    124         """ 
     227        :param qmin: minimum value to consider for the fit range 
     228        :param qmax: maximum value to consider for the fit range 
     229        """ 
     230        self.qmin = qmin 
     231        self.qmax = qmax 
    125232 
    126233    def get_range(self): 
    127234        """ 
    128235        :return: fitting range 
    129         """ 
    130  
    131     def set_weight(self, flag=None): 
    132         """ 
    133         set fitting range 
    134         """ 
    135  
    136     def get_weight(self): 
    137         """ 
    138         get fitting weight 
    139         """ 
     236 
     237        """ 
     238        return self.qmin, self.qmax 
    140239 
    141240    def clear_model_param(self): 
     
    143242        clear constraint info 
    144243        """ 
     244        self.list_param = [] 
    145245 
    146246    def set_fit_tab_caption(self, caption): 
    147247        """ 
    148         store the caption of the page associated with object 
    149         """ 
     248        """ 
     249        self.fit_tab_caption = str(caption) 
    150250 
    151251    def get_fit_tab_caption(self): 
    152252        """ 
    153         Return the caption of the page associated with object 
    154         """ 
     253        """ 
     254        return self.fit_tab_caption 
    155255 
    156256    def set_graph_id(self, id): 
     
    158258        Set graph id (from data_group_id at the time the graph produced) 
    159259        """ 
     260        self.graph_id = id 
    160261 
    161262    def get_graph_id(self): 
     
    163264        Get graph_id 
    164265        """ 
     266        return self.graph_id 
    165267 
    166268    def set_result(self, result): 
    167269        """ 
    168270        """ 
     271        self.result = result 
    169272 
    170273    def get_result(self): 
     
    172275        get result 
    173276        """ 
    174  
    175  
    176 class FitProblemDictionary(FitProblemComponent, dict): 
     277        return self.result 
     278 
     279 
     280class FitProblemDictionary(dict): 
    177281    """ 
    178282    This module implements a dictionary of fitproblem objects 
    179283    """ 
    180284    def __init__(self): 
    181         FitProblemComponent.__init__(self) 
    182285        dict.__init__(self) 
    183286        ## the current model 
     
    206309        self._smear_on = flag 
    207310        if fid is None: 
    208             for value in self.itervalues(): 
     311            for value in self.values(): 
    209312                value.enable_smearing(flag) 
    210         else: 
    211             if fid in self.iterkeys(): 
    212                 self[fid].enable_smearing(flag) 
     313        elif fid in self: 
     314            self[fid].enable_smearing(flag) 
    213315 
    214316    def set_smearer(self, smearer, fid=None): 
     
    218320        """ 
    219321        if fid is None: 
    220             for value in self.itervalues(): 
     322            for value in self.values(): 
    221323                value.set_smearer(smearer) 
    222         else: 
    223             if fid in self.iterkeys(): 
    224                 self[fid].set_smearer(smearer) 
     324        elif fid in self: 
     325            self[fid].set_smearer(smearer) 
    225326 
    226327    def get_smearer(self, fid=None): 
     
    228329        return smear object 
    229330        """ 
    230         if fid in self.iterkeys(): 
     331        if fid in self: 
    231332            return self[fid].get_smearer() 
    232333 
     
    235336        """ 
    236337        if fid is None: 
    237             for value in self.itervalues(): 
     338            for value in self.values(): 
    238339                value.save_model_name(name) 
    239         else: 
    240             if fid in self.iterkeys(): 
    241                 self[fid].save_model_name(name) 
     340        elif fid in self: 
     341            self[fid].save_model_name(name) 
    242342 
    243343    def get_name(self, fid=None): 
     
    246346        result = [] 
    247347        if fid is None: 
    248             for value in self.itervalues(): 
     348            for value in self.values(): 
    249349                result.append(value.get_name()) 
    250         else: 
    251             if fid in self.iterkeys(): 
    252                 result.append(self[fid].get_name()) 
     350        elif fid in self: 
     351            result.append(self[fid].get_name()) 
    253352        return result 
    254353 
     
    261360        self.model = model 
    262361        if fid is None: 
    263             for value in self.itervalues(): 
     362            for value in self.values(): 
    264363                value.set_model(self.model) 
    265         else: 
    266             if fid in self.iterkeys(): 
    267                 self[fid].set_model(self.model) 
     364        elif fid in self: 
     365            self[fid].set_model(self.model) 
    268366 
    269367    def get_model(self, fid): 
     
    271369        :return: saved model 
    272370        """ 
    273         if fid in self.iterkeys(): 
     371        if fid in self: 
    274372            return self[fid].get_model() 
    275373 
     
    291389        :param data: data selected 
    292390        """ 
    293         if fid in self.iterkeys(): 
     391        if fid in self: 
    294392            self[fid].set_residuals(residuals) 
    295393 
     
    298396        :return: residuals 
    299397        """ 
    300         if fid in self.iterkeys(): 
     398        if fid in self: 
    301399            return self[fid].get_residuals() 
    302400 
     
    306404        :param data: data selected 
    307405        """ 
    308         if fid in self.iterkeys(): 
     406        if fid in self: 
    309407            self[fid].set_theory_data(data) 
    310408 
     
    313411        :return: list of data dList 
    314412        """ 
    315         if fid in self.iterkeys(): 
     413        if fid in self: 
    316414            return self[fid].get_theory_data() 
    317415 
     
    322420        :note: only data changes in the fit problem 
    323421        """ 
    324         if data.id not in self.iterkeys(): 
     422        if data.id not in self: 
    325423            self[data.id] = FitProblem() 
    326424        self[data.id].set_fit_data(data) 
     
    336434            data = [] 
    337435        for d in data: 
    338             if (d is not None): 
    339                 if (d.id not in self.iterkeys()): 
     436            if d is not None: 
     437                if d.id not in self: 
    340438                    self[d.id] = FitProblem() 
    341439                self[d.id].set_fit_data(d) 
     
    348446        :param fid: key representing a fitproblem, usually extract from data id 
    349447        """ 
    350         if fid in self.iterkeys(): 
     448        if fid in self: 
    351449            return self[fid].get_fit_data() 
    352450 
     
    358456        """ 
    359457        if fid is None: 
    360             for value in self.itervalues(): 
     458            for value in self.values(): 
    361459                value.set_model_param(name, value) 
    362         else: 
    363             if fid in self.iterkeys(): 
    364                 self[fid].set_model_param(name, value) 
     460        elif fid in self: 
     461            self[fid].set_model_param(name, value) 
    365462 
    366463    def get_model_param(self, fid): 
     
    368465        return list of couple of parameter name and value 
    369466        """ 
    370         if fid in self.iterkeys(): 
     467        if fid in self: 
    371468            return self[fid].get_model_param() 
    372469 
     
    389486        """ 
    390487        self.scheduled = schedule 
    391         for value in self.itervalues(): 
     488        for value in self.values(): 
    392489            value.schedule_tofit(schedule) 
    393490 
     
    405502        self.qmax = qmax 
    406503        if fid is None: 
    407             for value in self.itervalues(): 
     504            for value in self.values(): 
    408505                value.set_range(self.qmin, self.qmax) 
    409         else: 
    410             if fid in self.iterkeys(): 
    411                 self[fid].value.set_range(self.qmin, self.qmax) 
     506        elif fid in self: 
     507            self[fid].value.set_range(self.qmin, self.qmax) 
    412508 
    413509    def get_range(self, fid): 
     
    415511        :return: fitting range 
    416512        """ 
    417         if fid in self.iterkeys(): 
     513        if fid in self: 
    418514            return self[fid].get_range() 
    419515 
     
    423519        """ 
    424520        if fid is None: 
    425             for value in self.itervalues(): 
     521            for value in self.values(): 
    426522                value.set_weight(flag=flag, is2d=is2d) 
    427         else: 
    428             if fid in self.iterkeys(): 
    429                 self[fid].set_weight(flag=flag, is2d=is2d) 
     523        elif fid in self: 
     524            self[fid].set_weight(flag=flag, is2d=is2d) 
    430525 
    431526    def get_weight(self, fid=None): 
     
    433528        return fit weight 
    434529        """ 
    435         if fid in self.iterkeys(): 
     530        if fid in self: 
    436531            return self[fid].get_weight() 
    437532 
     
    441536        """ 
    442537        if fid is None: 
    443             for value in self.itervalues(): 
     538            for value in self.values(): 
    444539                value.clear_model_param() 
    445         else: 
    446             if fid in self.iterkeys(): 
    447                 self[fid].clear_model_param() 
     540        elif fid in self: 
     541            self[fid].clear_model_param() 
    448542 
    449543    def get_fit_problem(self): 
     
    451545        return fitproblem contained in this dictionary 
    452546        """ 
    453         return self.itervalues() 
     547        return self.values() 
    454548 
    455549    def set_result(self, result, fid): 
    456550        """ 
    457551        """ 
    458         if fid in self.iterkeys(): 
     552        if fid in self: 
    459553            self[fid].set_result(result) 
    460554 
     
    470564        get result 
    471565        """ 
    472         if fid in self.iterkeys(): 
     566        if fid in self: 
    473567            return self[fid].get_result() 
    474568 
     
    490584        """ 
    491585        return self.graph_id 
    492  
    493  
    494 class FitProblem(FitProblemComponent): 
    495     """ 
    496     FitProblem class allows to link a model with the new name created in _on_model, 
    497     a name theory created with that model  and the data fitted with the model. 
    498     FitProblem is mostly used  as value of the dictionary by fitting module. 
    499     """ 
    500     def __init__(self): 
    501         FitProblemComponent.__init__(self) 
    502         """ 
    503         contains information about data and model to fit 
    504         """ 
    505         ## data used for fitting 
    506         self.fit_data = None 
    507         self.theory_data = None 
    508         self.residuals = None 
    509         # original data: should not be modified 
    510         self.original_data = None 
    511         ## the current model 
    512         self.model = None 
    513         ## if 1 this fit problem will be selected to fit , if 0 
    514         ## it will not be selected for fit 
    515         self.schedule = 0 
    516         ##list containing parameter name and value 
    517         self.list_param = [] 
    518         ## smear object to smear or not data1D 
    519         self.smearer_computed = False 
    520         self.smearer_enable = False 
    521         self.smearer_computer_value = None 
    522         ## fitting range 
    523         self.qmin = None 
    524         self.qmax = None 
    525         # fit weight 
    526         self.weight = None 
    527         self.result = None 
    528  
    529     def enable_smearing(self, flag=False): 
    530         """ 
    531         :param flag: bool.When flag is 1 get the computer smear value. When 
    532             flag is 0 ingore smear value. 
    533         """ 
    534         self.smearer_enable = flag 
    535  
    536     def set_smearer(self, smearer): 
    537         """ 
    538         save reference of  smear object on fitdata 
    539  
    540         :param smear: smear object from DataLoader 
    541  
    542         """ 
    543         self.smearer_computer_value = smearer 
    544  
    545     def get_smearer(self): 
    546         """ 
    547         return smear object 
    548         """ 
    549         if not self.smearer_enable: 
    550             return None 
    551         if not self.smearer_computed: 
    552             #smeari_selection should be call only once per fitproblem 
    553             self.smearer_computer_value = smear_selection(self.fit_data, 
    554                                                            self.model) 
    555             self.smearer_computed = True 
    556         return self.smearer_computer_value 
    557  
    558     def save_model_name(self, name): 
    559         """ 
    560         """ 
    561         self.name_per_page = name 
    562  
    563     def get_name(self): 
    564         """ 
    565         """ 
    566         return self.name_per_page 
    567  
    568     def set_model(self, model): 
    569         """ 
    570         associates each model with its new created name 
    571         :param model: model selected 
    572         :param name: name created for model 
    573         """ 
    574         self.model = model 
    575         self.smearer_computer_value = smear_selection(self.fit_data, 
    576                                                            self.model) 
    577         self.smearer_computed = True 
    578  
    579     def get_model(self): 
    580         """ 
    581         :return: saved model 
    582         """ 
    583         return self.model 
    584  
    585     def set_residuals(self, residuals): 
    586         """ 
    587         save a copy of residual 
    588         :param data: data selected 
    589         """ 
    590         self.residuals = residuals 
    591  
    592     def get_residuals(self): 
    593         """ 
    594         :return: residuals 
    595         """ 
    596         return self.residuals 
    597  
    598     def set_theory_data(self, data): 
    599         """ 
    600         save a copy of the data select to fit 
    601  
    602         :param data: data selected 
    603  
    604         """ 
    605         self.theory_data = copy.deepcopy(data) 
    606  
    607     def get_theory_data(self): 
    608         """ 
    609         :return: theory generated with the current model and data of this class 
    610         """ 
    611         return self.theory_data 
    612  
    613     def set_fit_data(self, data): 
    614         """ 
    615         Store data associated with this class 
    616         :param data: list of data selected 
    617         """ 
    618         self.original_data = None 
    619         self.fit_data = None 
    620         # original data: should not be modified 
    621         self.original_data = data 
    622         # fit data: used for fit and can be modified for convenience 
    623         self.fit_data = copy.deepcopy(data) 
    624         self.smearer_computer_value = smear_selection(self.fit_data, 
    625                                                            self.model) 
    626         self.smearer_computed = True 
    627         self.result = None 
    628  
    629     def get_fit_data(self): 
    630         """ 
    631         :return: data associate with this class 
    632         """ 
    633         return self.fit_data 
    634  
    635     def get_origin_data(self): 
    636         """ 
    637         """ 
    638         return self.original_data 
    639  
    640     def set_weight(self, is2d, flag=None): 
    641         """ 
    642         Received flag and compute error on data. 
    643         :param flag: flag to transform error of data. 
    644         :param is2d: flag to distinguish 1D to 2D Data 
    645         """ 
    646         from sas.sasgui.perspectives.fitting.utils import get_weight 
    647         # send original data for weighting 
    648         self.weight = get_weight(data=self.original_data, is2d=is2d, flag=flag) 
    649         if is2d: 
    650             self.fit_data.err_data = self.weight 
    651         else: 
    652             self.fit_data.dy = self.weight 
    653  
    654     def get_weight(self): 
    655         """ 
    656         returns weight array 
    657         """ 
    658         return self.weight 
    659  
    660     def set_param2fit(self, list): 
    661         """ 
    662         Store param names to fit (checked) 
    663         :param list: list of the param names 
    664         """ 
    665         self.list_param2fit = list 
    666  
    667     def get_param2fit(self): 
    668         """ 
    669         return the list param names to fit 
    670         """ 
    671         return self.list_param2fit 
    672  
    673     def set_model_param(self, name, value=None): 
    674         """ 
    675         Store the name and value of a parameter of this fitproblem's model 
    676         :param name: name of the given parameter 
    677         :param value: value of that parameter 
    678         """ 
    679         self.list_param.append([name, value]) 
    680  
    681     def get_model_param(self): 
    682         """ 
    683         return list of couple of parameter name and value 
    684         """ 
    685         return self.list_param 
    686  
    687     def schedule_tofit(self, schedule=0): 
    688         """ 
    689         set schedule to true to decide if this fit  must be performed 
    690         """ 
    691         self.schedule = schedule 
    692  
    693     def get_scheduled(self): 
    694         """ 
    695         return true or false if a problem as being schedule for fitting 
    696         """ 
    697         return self.schedule 
    698  
    699     def set_range(self, qmin=None, qmax=None): 
    700         """ 
    701         set fitting range 
    702         :param qmin: minimum value to consider for the fit range 
    703         :param qmax: maximum value to consider for the fit range 
    704         """ 
    705         self.qmin = qmin 
    706         self.qmax = qmax 
    707  
    708     def get_range(self): 
    709         """ 
    710         :return: fitting range 
    711  
    712         """ 
    713         return self.qmin, self.qmax 
    714  
    715     def clear_model_param(self): 
    716         """ 
    717         clear constraint info 
    718         """ 
    719         self.list_param = [] 
    720  
    721     def set_fit_tab_caption(self, caption): 
    722         """ 
    723         """ 
    724         self.fit_tab_caption = str(caption) 
    725  
    726     def get_fit_tab_caption(self): 
    727         """ 
    728         """ 
    729         return self.fit_tab_caption 
    730  
    731     def set_graph_id(self, id): 
    732         """ 
    733         Set graph id (from data_group_id at the time the graph produced) 
    734         """ 
    735         self.graph_id = id 
    736  
    737     def get_graph_id(self): 
    738         """ 
    739         Get graph_id 
    740         """ 
    741         return self.graph_id 
    742  
    743     def set_result(self, result): 
    744         """ 
    745         """ 
    746         self.result = result 
    747  
    748     def get_result(self): 
    749         """ 
    750         get result 
    751         """ 
    752         return self.result 
  • src/sas/sasgui/perspectives/fitting/fitting.py

    r2504b5a r2504b5a  
    2323import traceback 
    2424 
     25import bumps.options 
     26from bumps.gui.fit_dialog import show_fit_config 
     27try: 
     28    from bumps.gui.fit_dialog import EVT_FITTER_CHANGED 
     29except ImportError: 
     30    # CRUFT: bumps 0.7.5.8 and below 
     31    EVT_FITTER_CHANGED = None  # type: wx.PyCommandEvent 
     32 
    2533from sas.sascalc.dataloader.loader import Loader 
     34from sas.sascalc.fit.BumpsFitting import BumpsFit as Fit 
     35from sas.sascalc.fit.pagestate import Reader, PageState, SimFitPageState 
     36from sas.sascalc.fit import models 
     37 
    2638from sas.sasgui.guiframe.dataFitting import Data2D 
    2739from sas.sasgui.guiframe.dataFitting import Data1D 
     
    3446from sas.sasgui.guiframe.plugin_base import PluginBase 
    3547from sas.sasgui.guiframe.data_processor import BatchCell 
    36 from sas.sascalc.fit.BumpsFitting import BumpsFit as Fit 
    37 from sas.sasgui.perspectives.fitting.console import ConsoleUpdate 
    38 from sas.sasgui.perspectives.fitting.fitproblem import FitProblemDictionary 
    39 from sas.sasgui.perspectives.fitting.fitpanel import FitPanel 
    40 from sas.sasgui.perspectives.fitting.resultpanel import ResultPanel, PlotResultEvent 
    41  
    42 from sas.sasgui.perspectives.fitting.fit_thread import FitThread 
    43 from sas.sasgui.perspectives.fitting.pagestate import Reader 
    44 from sas.sasgui.perspectives.fitting.fitpage import Chi2UpdateEvent 
     48from sas.sasgui.guiframe.gui_manager import MDIFrame 
     49from sas.sasgui.guiframe.documentation_window import DocumentationWindow 
     50 
    4551from sas.sasgui.perspectives.calculator.model_editor import TextDialog 
    4652from sas.sasgui.perspectives.calculator.model_editor import EditorWindow 
    47 from sas.sasgui.guiframe.gui_manager import MDIFrame 
    48 from sas.sasgui.guiframe.documentation_window import DocumentationWindow 
    49 from sas.sasgui.perspectives.fitting.gpu_options import GpuOptions 
    50  
    51 from . import models 
     53 
     54from .fitting_widgets import DataDialog 
     55from .fit_thread import FitThread 
     56from .fitpage import Chi2UpdateEvent 
     57from .console import ConsoleUpdate 
     58from .fitproblem import FitProblemDictionary 
     59from .fitpanel import FitPanel 
     60from .model_thread import Calc1D, Calc2D 
     61from .resultpanel import ResultPanel, PlotResultEvent 
     62from .gpu_options import GpuOptions 
    5263 
    5364logger = logging.getLogger(__name__) 
     
    6374    ON_MAC = True 
    6475 
    65 import bumps.options 
    66 from bumps.gui.fit_dialog import show_fit_config 
    67 try: 
    68     from bumps.gui.fit_dialog import EVT_FITTER_CHANGED 
    69 except ImportError: 
    70     # CRUFT: bumps 0.7.5.8 and below 
    71     EVT_FITTER_CHANGED = None  # type: wx.PyCommandEvent 
    7276 
    7377class Plugin(PluginBase): 
     
    238242        Get the python editor panel 
    239243        """ 
     244        from sas.sasgui.perspectives.calculator.pyconsole import PyConsole 
     245 
    240246        event_id = event.GetId() 
    241247        label = self.edit_menu.GetLabel(event_id) 
    242         from sas.sasgui.perspectives.calculator.pyconsole import PyConsole 
    243248        filename = os.path.join(models.find_plugins_dir(), label) 
    244249        frame = PyConsole(parent=self.parent, manager=self, 
     
    290295                        break 
    291296        except Exception: 
    292             import traceback; traceback.print_exc() 
     297            traceback.print_exc() 
    293298            msg = 'Delete Error: \nCould not delete the file; Check if in use.' 
    294299            wx.MessageBox(msg, 'Error') 
     
    300305        event_id = event.GetId() 
    301306        model_manager = models.ModelManager() 
    302         model_list = model_manager.get_model_name_list() 
     307        model_list = model_manager.composable_models() 
    303308        plug_dir = models.find_plugins_dir() 
    304309        textdial = TextDialog(None, self, wx.ID_ANY, 'Easy Sum/Multi(p1, p2) Editor', 
     
    340345            self.set_edit_menu_helper(self.parent, self.edit_custom_model) 
    341346            self.set_edit_menu_helper(self.parent, self.delete_custom_model) 
    342             temp = self.fit_panel.reset_pmodel_list() 
    343             if temp: 
    344                 # Set the new plugin model list for all fit pages 
    345                 for uid, page in self.fit_panel.opened_pages.iteritems(): 
    346                     if hasattr(page, "formfactorbox"): 
    347                         page.model_list_box = temp 
    348                         current_val = page.formfactorbox.GetLabel() 
    349                         #if page.plugin_rbutton.GetValue(): 
    350                         mod_cat = page.categorybox.GetStringSelection() 
    351                         if mod_cat == custom_model: 
    352                             #pos = page.formfactorbox.GetSelection() 
    353                             page._show_combox_helper() 
    354                             new_val = page.formfactorbox.GetLabel() 
    355                             if current_val != new_val and new_val != '': 
    356                                 page.formfactorbox.SetLabel(new_val) 
    357                             else: 
    358                                 page.formfactorbox.SetLabel(current_val) 
    359                         if hasattr(page, 'structurebox'): 
    360                             selected_name = page.structurebox.GetStringSelection() 
    361  
    362                             page.structurebox.Clear() 
    363                             page.initialize_combox() 
    364  
    365                             index = page.structurebox.FindString(selected_name) 
    366                             if index == -1: 
    367                                 index = 0 
    368                             page.structurebox.SetSelection(index) 
    369                             page._on_select_model() 
    370         except: 
     347            new_pmodel_list = self.fit_panel.reset_pmodel_list() 
     348            if not new_pmodel_list: 
     349                return 
     350            # Set the new plugin model list for all fit pages 
     351            for uid, page in self.fit_panel.opened_pages.iteritems(): 
     352                if hasattr(page, "formfactorbox"): 
     353                    page.model_list_box = new_pmodel_list 
     354                    mod_cat = page.categorybox.GetStringSelection() 
     355                    if mod_cat == custom_model: 
     356                        box = page.formfactorbox 
     357                        model_name = box.GetValue() 
     358                        model = (box.GetClientData(box.GetCurrentSelection()) 
     359                                 if model_name else None) 
     360                        page._show_combox_helper() 
     361                        new_index = box.FindString(model_name) 
     362                        new_model = (box.GetClientData(new_index) 
     363                                     if new_index >= 0 else None) 
     364                        if new_index >= 0: 
     365                            box.SetStringSelection(model_name) 
     366                        else: 
     367                            box.SetStringSelection('') 
     368                        if model and new_model != model: 
     369                            page._on_select_model(keep_pars=True) 
     370                    if hasattr(page, 'structurebox'): 
     371                        selected_name = page.structurebox.GetStringSelection() 
     372 
     373                        page.structurebox.Clear() 
     374                        page.initialize_combox() 
     375 
     376                        index = page.structurebox.FindString(selected_name) 
     377                        if index == -1: 
     378                            index = 0 
     379                        page.structurebox.SetSelection(index) 
     380                        page._on_select_model() 
     381        except Exception: 
    371382            logger.error("update_custom_combo: %s", sys.exc_value) 
    372383 
     
    378389        #new_model_menu = wx.Menu() 
    379390        self.edit_model_menu.Append(wx_id, 'New Plugin Model', 
    380                                    'Add a new model function') 
     391                                    'Add a new model function') 
    381392        wx.EVT_MENU(owner, wx_id, self.make_new_model) 
    382393 
     
    575586        else: 
    576587            if len(data_list) > MAX_NBR_DATA: 
    577                 from fitting_widgets import DataDialog 
    578588                dlg = DataDialog(data_list=data_list, nb_data=MAX_NBR_DATA) 
    579589                if dlg.ShowModal() == wx.ID_OK: 
     
    620630        : param datainfo: data 
    621631        """ 
    622         from pagestate import PageState 
    623         from simfitpage import SimFitPageState 
    624632        if isinstance(state, PageState): 
    625633            state = state.clone() 
    626634            self.temp_state.append(state) 
    627635        elif isinstance(state, SimFitPageState): 
    628             state.load_from_save_state(self) 
     636            if self.fit_panel.sim_page is None: 
     637                self.fit_panel.add_sim_page() 
     638            self.fit_panel.sim_page.load_from_save_state(state) 
    629639        else: 
    630640            self.temp_state = [] 
     
    661671                self.parent.add_data(data_list={data.id: data}) 
    662672                wx.PostEvent(self.parent, NewPlotEvent(plot=data, 
    663                                         title=data.title)) 
     673                             title=data.title)) 
    664674                #need to be fix later make sure we are sendind guiframe.data 
    665675                #to panel 
     
    672682                self.parent.add_data(data_list={data.id: data}) 
    673683                wx.PostEvent(self.parent, NewPlotEvent(plot=data, 
    674                                         title=data.title)) 
     684                             title=data.title)) 
    675685                page = self.add_fit_page([data]) 
    676686                caption = page.window_caption 
    677687                self.store_data(uid=page.uid, data_list=page.get_data_list(), 
    678                         caption=caption) 
     688                                caption=caption) 
    679689                self.mypanels.append(page) 
    680690 
     
    793803        """ 
    794804        if item.find(".") >= 0: 
    795             param_names = re.split("\.", item) 
     805            param_names = re.split(r"\.", item) 
    796806            model_name = param_names[0] 
    797807            ##Assume max len is 3; eg., M0.radius.width 
     
    896906 
    897907            self.draw_model(model=model, data=data, page_id=uid, smearer=smear, 
    898                 enable1D=enable1D, enable2D=enable2D, 
    899                 qmin=qmin, qmax=qmax, weight=weight) 
     908                            enable1D=enable1D, enable2D=enable2D, 
     909                            qmin=qmin, qmax=qmax, weight=weight) 
    900910 
    901911    def draw_model(self, model, page_id, data=None, smearer=None, 
     
    940950            ## draw model 2D with no initial data 
    941951            self._draw_model2D(model=model, 
    942                                 page_id=page_id, 
    943                                 data=data, 
    944                                 enable2D=enable2D, 
    945                                 smearer=smearer, 
    946                                 qmin=qmin, 
    947                                 qmax=qmax, 
    948                                 fid=fid, 
    949                                 weight=weight, 
    950                                 state=state, 
    951                                 toggle_mode_on=toggle_mode_on, 
    952                                 update_chisqr=update_chisqr, 
    953                                 source=source) 
     952                               page_id=page_id, 
     953                               data=data, 
     954                               enable2D=enable2D, 
     955                               smearer=smearer, 
     956                               qmin=qmin, 
     957                               qmax=qmax, 
     958                               fid=fid, 
     959                               weight=weight, 
     960                               state=state, 
     961                               toggle_mode_on=toggle_mode_on, 
     962                               update_chisqr=update_chisqr, 
     963                               source=source) 
    954964 
    955965    def onFit(self, uid): 
     
    960970        :param uid: id related to the panel currently calling this fit function. 
    961971        """ 
    962         if uid is None: raise RuntimeError("no page to fit") # Should never happen 
     972        if uid is None: 
     973            raise RuntimeError("no page to fit") # Should never happen 
    963974 
    964975        sim_page_uid = getattr(self.sim_page, 'uid', None) 
     
    9941005                    page = self.fit_panel.get_page_by_id(page_id) 
    9951006                    self.set_fit_weight(uid=page.uid, 
    996                                      flag=page.get_weight_flag(), 
    997                                      is2d=page._is_2D()) 
     1007                                        flag=page.get_weight_flag(), 
     1008                                        is2d=page._is_2D()) 
    9981009                    if not page.param_toFit: 
    9991010                        msg = "No fitting parameters for %s" % page.window_caption 
     
    10191030                            fitter = sim_fitter 
    10201031                        self._add_problem_to_fit(fitproblem=fitproblem, 
    1021                                              pars=pars, 
    1022                                              fitter=fitter, 
    1023                                              fit_id=fit_id) 
     1032                                                 pars=pars, 
     1033                                                 fitter=fitter, 
     1034                                                 fit_id=fit_id) 
    10241035                        fit_id += 1 
    10251036                    list_page_id.append(page_id) 
     
    10681079            ## Perform more than 1 fit at the time 
    10691080            calc_fit = FitThread(handler=handler, 
    1070                                     fn=fitter_list, 
    1071                                     batch_inputs=batch_inputs, 
    1072                                     batch_outputs=batch_outputs, 
    1073                                     page_id=list_page_id, 
    1074                                     updatefn=handler.update_fit, 
    1075                                     completefn=self._fit_completed) 
     1081                                 fn=fitter_list, 
     1082                                 batch_inputs=batch_inputs, 
     1083                                 batch_outputs=batch_outputs, 
     1084                                 page_id=list_page_id, 
     1085                                 updatefn=handler.update_fit, 
     1086                                 completefn=self._fit_completed) 
    10761087        #self.fit_thread_list[current_page_id] = calc_fit 
    10771088        self.fit_thread_list[uid] = calc_fit 
     
    11341145                evt = StatusEvent(status=msg, info="warning") 
    11351146                wx.PostEvent(self.parent, evt) 
    1136         except: 
     1147        except Exception: 
    11371148            msg = "Creating Fit page: %s" % sys.exc_value 
    11381149            wx.PostEvent(self.parent, StatusEvent(status=msg, info="error")) 
     
    11581169                    group_id = str(page.uid) + " Model1D" 
    11591170                    wx.PostEvent(self.parent, 
    1160                              NewPlotEvent(group_id=group_id, 
    1161                                                action="delete")) 
     1171                                 NewPlotEvent(group_id=group_id, 
     1172                                              action="delete")) 
    11621173                    self.parent.update_data(prev_data=theory_data, 
    1163                                              new_data=data) 
     1174                                            new_data=data) 
    11641175            else: 
    11651176                if theory_data is not None: 
     
    11671178                    data.group_id = theory_data.group_id 
    11681179                    wx.PostEvent(self.parent, 
    1169                              NewPlotEvent(group_id=group_id, 
    1170                                                action="delete")) 
     1180                                 NewPlotEvent(group_id=group_id, 
     1181                                              action="delete")) 
    11711182                    self.parent.update_data(prev_data=theory_data, 
    1172                                              new_data=data) 
     1183                                            new_data=data) 
    11731184        self.store_data(uid=page.uid, data_list=page.get_data_list(), 
    11741185                        caption=page.window_caption) 
     
    14791490        if "Data" not in batch_outputs.keys(): 
    14801491            batch_outputs["Data"] = [] 
    1481         from sas.sasgui.guiframe.data_processor import BatchCell 
    14821492        cell = BatchCell() 
    14831493        cell.label = data.name 
     
    15791589                    except KeyboardInterrupt: 
    15801590                        fit_msg += "\nSingular point: Fitting stopped." 
    1581                     except: 
     1591                    except Exception: 
    15821592                        fit_msg += "\nSingular point: Fitting error occurred." 
    15831593                if fit_msg: 
    1584                    evt = StatusEvent(status=fit_msg, info="warning", type="stop") 
    1585                    wx.PostEvent(self.parent, evt) 
    1586  
    1587         except: 
     1594                    evt = StatusEvent(status=fit_msg, info="warning", type="stop") 
     1595                    wx.PostEvent(self.parent, evt) 
     1596 
     1597        except Exception: 
    15881598            msg = ("Fit completed but the following error occurred: %s" 
    15891599                   % sys.exc_value) 
    1590             #import traceback; msg = "\n".join((traceback.format_exc(), msg)) 
     1600            #msg = "\n".join((traceback.format_exc(), msg)) 
    15911601            evt = StatusEvent(status=msg, info="warning", type="stop") 
    15921602            wx.PostEvent(self.parent, evt) 
     
    17431753                                                  fid=data.id) 
    17441754        self.parent.update_theory(data_id=data.id, theory=new_plot, 
    1745                                    state=state) 
     1755                                  state=state) 
    17461756        return new_plot 
    17471757 
     
    17591769            @param unsmeared_error: data error, rescaled to unsmeared model 
    17601770        """ 
     1771<<<<<<< HEAD 
     1772 
     1773======= 
     1774>>>>>>> master 
    17611775        number_finite = np.count_nonzero(np.isfinite(y)) 
    17621776        np.nan_to_num(y) 
     
    17671781        # Create the new theories 
    17681782        if unsmeared_model is not None: 
    1769             unsmeared_model_plot = self.create_theory_1D(x, unsmeared_model,  
     1783            unsmeared_model_plot = self.create_theory_1D(x, unsmeared_model, 
    17701784                                  page_id, model, data, state, 
    17711785                                  data_description=model.name + " unsmeared", 
     
    17741788 
    17751789            if unsmeared_data is not None and unsmeared_error is not None: 
    1776                 unsmeared_data_plot = self.create_theory_1D(x, unsmeared_data,  
     1790                unsmeared_data_plot = self.create_theory_1D(x, unsmeared_data, 
    17771791                                      page_id, model, data, state, 
    17781792                                      data_description="Data unsmeared", 
     
    17921806            plots_to_update.append(pq_plot) 
    17931807        # Update the P(Q), S(Q) and unsmeared theory plots if they exist 
    1794         wx.PostEvent(self.parent, NewPlotEvent(plots=plots_to_update,  
     1808        wx.PostEvent(self.parent, NewPlotEvent(plots=plots_to_update, 
    17951809                                              action='update')) 
    17961810 
     
    18081822 
    18091823        self.page_finder[page_id].set_theory_data(data=new_plot, 
    1810                                                       fid=data.id) 
     1824                                                  fid=data.id) 
    18111825        if toggle_mode_on: 
    18121826            wx.PostEvent(self.parent, 
    18131827                         NewPlotEvent(group_id=str(page_id) + " Model2D", 
    1814                                           action="Hide")) 
     1828                                      action="Hide")) 
    18151829        else: 
    18161830            if update_chisqr: 
    1817                 wx.PostEvent(current_pg, 
    1818                              Chi2UpdateEvent(output=self._cal_chisqr( 
    1819                                                                 data=data, 
    1820                                                                 fid=fid, 
    1821                                                                 weight=weight, 
    1822                                                                 page_id=page_id, 
    1823                                                                 index=index))) 
     1831                output = self._cal_chisqr(data=data, 
     1832                                          fid=fid, 
     1833                                          weight=weight, 
     1834                                          page_id=page_id, 
     1835                                          index=index) 
     1836                wx.PostEvent(current_pg, Chi2UpdateEvent(output=output)) 
    18241837            else: 
    18251838                self._plot_residuals(page_id=page_id, data=data, fid=fid, 
     
    18291842            logger.error("Using the present parameters the model does not return any finite value. ") 
    18301843            msg = "Computing Error: Model did not return any finite value." 
    1831             wx.PostEvent(self.parent, StatusEvent(status = msg, info="error")) 
     1844            wx.PostEvent(self.parent, StatusEvent(status=msg, info="error")) 
    18321845        else: 
    18331846            msg = "Computation  completed!" 
     
    18541867 
    18551868    def _complete2D(self, image, data, model, page_id, elapsed, index, qmin, 
    1856                 qmax, fid=None, weight=None, toggle_mode_on=False, state=None, 
    1857                      update_chisqr=True, source='model', plot_result=True): 
     1869                    qmax, fid=None, weight=None, toggle_mode_on=False, state=None, 
     1870                    update_chisqr=True, source='model', plot_result=True): 
    18581871        """ 
    18591872        Complete get the result of modelthread and create model 2D 
     
    18961909                                                  fid=data.id) 
    18971910        self.parent.update_theory(data_id=data.id, 
    1898                                        theory=new_plot, 
    1899                                        state=state) 
     1911                                  theory=new_plot, 
     1912                                  state=state) 
    19001913        current_pg = self.fit_panel.get_page_by_id(page_id) 
    19011914        title = new_plot.title 
    19021915        if not source == 'fit' and plot_result: 
    1903             wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot, 
    1904                                                title=title)) 
     1916            wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot, title=title)) 
    19051917        if toggle_mode_on: 
    19061918            wx.PostEvent(self.parent, 
    1907                              NewPlotEvent(group_id=str(page_id) + " Model1D", 
    1908                                                action="Hide")) 
     1919                         NewPlotEvent(group_id=str(page_id) + " Model1D", 
     1920                                      action="Hide")) 
    19091921        else: 
    19101922            # Chisqr in fitpage 
    19111923            if update_chisqr: 
    1912                 wx.PostEvent(current_pg, 
    1913                              Chi2UpdateEvent(output=self._cal_chisqr(data=data, 
    1914                                                                     weight=weight, 
    1915                                                                     fid=fid, 
    1916                                                          page_id=page_id, 
    1917                                                          index=index))) 
     1924                output = self._cal_chisqr(data=data, 
     1925                                          weight=weight, 
     1926                                          fid=fid, 
     1927                                          page_id=page_id, 
     1928                                          index=index) 
     1929                wx.PostEvent(current_pg, Chi2UpdateEvent(output=output)) 
    19181930            else: 
    19191931                self._plot_residuals(page_id=page_id, data=data, fid=fid, 
    1920                                       index=index, weight=weight) 
     1932                                     index=index, weight=weight) 
    19211933 
    19221934        if not number_finite: 
    19231935            logger.error("Using the present parameters the model does not return any finite value. ") 
    19241936            msg = "Computing Error: Model did not return any finite value." 
    1925             wx.PostEvent(self.parent, StatusEvent(status = msg, info="error")) 
     1937            wx.PostEvent(self.parent, StatusEvent(status=msg, info="error")) 
    19261938        else: 
    19271939            msg = "Computation  completed!" 
     
    19391951                      weight=None, 
    19401952                      toggle_mode_on=False, 
    1941                        update_chisqr=True, source='model'): 
     1953                      update_chisqr=True, source='model'): 
    19421954        """ 
    19431955        draw model in 2D 
     
    19541966            return None 
    19551967        try: 
    1956             from model_thread import Calc2D 
    19571968            ## If a thread is already started, stop it 
    19581969            if (self.calc_2D is not None) and self.calc_2D.isrunning(): 
     
    19861997    def _draw_model1D(self, model, page_id, data, 
    19871998                      qmin, qmax, smearer=None, 
    1988                 state=None, 
    1989                 weight=None, 
    1990                 fid=None, 
    1991                 toggle_mode_on=False, update_chisqr=True, source='model', 
    1992                 enable1D=True): 
     1999                      state=None, weight=None, fid=None, 
     2000                      toggle_mode_on=False, update_chisqr=True, source='model', 
     2001                      enable1D=True): 
    19932002        """ 
    19942003        Draw model 1D from loaded data1D 
     
    20012010            return 
    20022011        try: 
    2003             from model_thread import Calc1D 
    20042012            ## If a thread is already started, stop it 
    20052013            if (self.calc_1D is not None) and self.calc_1D.isrunning(): 
  • src/sas/sasgui/perspectives/fitting/model_thread.py

    r0f9ea1c r0f9ea1c  
    11""" 
    2     Calculation thread for modeling 
     2Calculation thread for modeling 
    33""" 
    44 
    55import time 
     6import math 
     7 
    68import numpy as np 
    7 import math 
     9 
    810from sas.sascalc.data_util.calcthread import CalcThread 
    911from sas.sascalc.fit.MultiplicationModel import MultiplicationModel 
     
    2830                 worktime=0.04, 
    2931                 exception_handler=None, 
    30                  ): 
     32                ): 
    3133        CalcThread.__init__(self, completefn, updatefn, yieldtime, worktime, 
    3234                            exception_handler=exception_handler) 
     
    5759        if self.qmax is None: 
    5860            if self.data is not None: 
    59                 newx = math.pow(max(math.fabs(self.data.xmax), 
    60                                    math.fabs(self.data.xmin)), 2) 
    61                 newy = math.pow(max(math.fabs(self.data.ymax), 
    62                                    math.fabs(self.data.ymin)), 2) 
    63                 self.qmax = math.sqrt(newx + newy) 
     61                newx = max(math.fabs(self.data.xmax), math.fabs(self.data.xmin)) 
     62                newy = max(math.fabs(self.data.ymax), math.fabs(self.data.ymin)) 
     63                self.qmax = math.sqrt(newx**2 + newy**2) 
    6464 
    6565        if self.data is None: 
     
    6868 
    6969        # Define matrix where data will be plotted 
    70         radius = np.sqrt((self.data.qx_data * self.data.qx_data) + \ 
    71                     (self.data.qy_data * self.data.qy_data)) 
     70        radius = np.sqrt(self.data.qx_data**2 + self.data.qy_data**2) 
    7271 
    7372        # For theory, qmax is based on 1d qmax 
    7473        # so that must be mulitified by sqrt(2) to get actual max for 2d 
    7574        index_model = (self.qmin <= radius) & (radius <= self.qmax) 
    76         index_model = index_model & self.data.mask 
    77         index_model = index_model & np.isfinite(self.data.data) 
     75        index_model &= self.data.mask 
     76        index_model &= np.isfinite(self.data.data) 
    7877 
    7978        if self.smearer is not None: 
     
    101100        elapsed = time.time() - self.starttime 
    102101        self.complete(image=output, 
    103                        data=self.data, 
    104                        page_id=self.page_id, 
    105                        model=self.model, 
    106                        state=self.state, 
    107                        toggle_mode_on=self.toggle_mode_on, 
    108                        elapsed=elapsed, 
    109                        index=index_model, 
    110                        fid=self.fid, 
    111                        qmin=self.qmin, 
    112                        qmax=self.qmax, 
    113                        weight=self.weight, 
    114                        #qstep=self.qstep, 
    115                        update_chisqr=self.update_chisqr, 
    116                        source=self.source) 
     102                      data=self.data, 
     103                      page_id=self.page_id, 
     104                      model=self.model, 
     105                      state=self.state, 
     106                      toggle_mode_on=self.toggle_mode_on, 
     107                      elapsed=elapsed, 
     108                      index=index_model, 
     109                      fid=self.fid, 
     110                      qmin=self.qmin, 
     111                      qmax=self.qmax, 
     112                      weight=self.weight, 
     113                      #qstep=self.qstep, 
     114                      update_chisqr=self.update_chisqr, 
     115                      source=self.source) 
    117116 
    118117 
     
    138137                 worktime=0.01, 
    139138                 exception_handler=None, 
    140                  ): 
     139                ): 
    141140        """ 
    142141        """ 
     
    193192                                                        * unsmeared_output[first_bin:last_bin+1]\ 
    194193                                                        / output[first_bin:last_bin+1] 
    195                 unsmeared_output=unsmeared_output[index] 
    196                 unsmeared_data=unsmeared_data[index] 
    197                 unsmeared_error=unsmeared_error 
     194                unsmeared_output = unsmeared_output[index] 
     195                unsmeared_data = unsmeared_data[index] 
     196                unsmeared_error = unsmeared_error 
    198197        else: 
    199198            output[index] = self.model.evalDistribution(self.data.x[index]) 
     
    243242    class CalcCommandline: 
    244243        def __init__(self, n=20000): 
    245             #print thread.get_ident() 
    246             from sas.models.CylinderModel import CylinderModel 
    247  
    248             model = CylinderModel() 
    249  
    250  
    251             print model.runXY([0.01, 0.02]) 
     244            #print(thread.get_ident()) 
     245 
     246            from sasmodels.sasview_model import _make_standard_model 
     247            cylinder = _make_standard_model('cylinder') 
     248            model = cylinder() 
     249 
     250            print(model.runXY([0.01, 0.02])) 
    252251 
    253252            qmax = 0.01 
     
    258257            y = numpy.arange(-qmax, qmax+qstep*0.01, qstep) 
    259258 
    260  
    261259            calc_thread_2D = Calc2D(x, y, None, model.clone(),None, 
    262260                                    -qmax, qmax,qstep, 
    263                                             completefn=self.complete, 
    264                                             updatefn=self.update , 
    265                                             yieldtime=0.0) 
     261                                    completefn=self.complete, 
     262                                    updatefn=self.update , 
     263                                    yieldtime=0.0) 
    266264 
    267265            calc_thread_2D.queue() 
     
    272270 
    273271        def update(self,output): 
    274             print "update" 
     272            print("update") 
    275273 
    276274        def complete(self, image, data, model, elapsed, qmin, qmax,index, qstep ): 
    277             print "complete" 
     275            print("complete") 
    278276            self.done = True 
    279277 
  • src/sas/sasgui/perspectives/fitting/report_dialog.py

    r7432acb r78312f7  
    3838        # number of images of plot 
    3939        self.nimages = len(self.report_list[2]) 
    40  
    41         if self.report_list[2] is not None: 
    42             # put image path in the report string 
    43             if len(self.report_list[2]) == 1: 
    44                 self.report_html = self.report_list[0] % \ 
    45                                     "memory:img_fit0.png" 
    46             elif len(self.report_list[2]) == 2: 
    47                 self.report_html = self.report_list[0] % \ 
    48                                     ("memory:img_fit0.png", 
    49                                      "memory:img_fit1.png") 
    50             # allows up to three images 
    51             else: 
    52                 self.report_html = self.report_list[0] % \ 
    53                                     ("memory:img_fit0.png", 
    54                                      "memory:img_fit1.png", 
    55                                      "memory:img_fit2.png") 
    56         else: 
    57             self.report_html = self.report_list[0] 
     40        self.report_html = self.report_list[0] 
    5841        # layout 
    5942        self._setup_layout() 
     
    10588            elif self.nimages == 3: 
    10689                html = report_frame % (str(pic_fname[0]), str(pic_fname[1]), 
    107                                           str(pic_fname[2])) 
     90                                       str(pic_fname[2])) 
    10891 
    10992            # make/open file in case of absence 
     
    118101                    #Windows 
    119102                    os.startfile(str(fName)) 
    120                 except: 
     103                except Exception: 
    121104                    try: 
    122105                        #Mac 
    123106                        os.system("open %s" % fName) 
    124                     except: 
     107                    except Exception: 
    125108                        #DO not open 
    126109                        pass 
  • src/sas/sasgui/perspectives/fitting/simfitpage.py

    ra9f9ca4 r00f7ff1  
    22    Simultaneous or Batch fit page 
    33""" 
    4 # Note that this is used for both Simultaneous/Constrained fit AND for  
     4# Note that this is used for both Simultaneous/Constrained fit AND for 
    55# combined batch fit.  This is done through setting of the batch_on parameter. 
    6 # There are the a half dozen or so places where an if statement is used as in  
     6# There are the a half dozen or so places where an if statement is used as in 
    77# if not batch_on: 
    88#     xxxx 
     
    1111# This is just wrong but dont have time to fix this go. Proper approach would be 
    1212# to strip all parts of the code that depend on batch_on and create the top 
    13 # level class from which a contrained/simultaneous fit page and a combined  
     13# level class from which a contrained/simultaneous fit page and a combined 
    1414# batch page inherit. 
    1515# 
     
    2323from wx.lib.scrolledpanel import ScrolledPanel 
    2424 
     25from sas.sascalc.fit.pagestate import SimFitPageState 
    2526from sas.sasgui.guiframe.events import StatusEvent, PanelOnFocusEvent 
    2627from sas.sasgui.guiframe.panel_base import PanelBase 
     
    6061 
    6162    return fittable_param 
    62  
    6363 
    6464class SimultaneousFitPage(ScrolledPanel, PanelBase): 
     
    157157        return self.state 
    158158 
     159    def load_from_save_state(self, sim_state): 
     160        """ 
     161        Load in a simultaneous/constrained fit from a save state 
     162        :param fit: Fitpanel object 
     163        :return: None 
     164        """ 
     165        model_map = {} 
     166        # Process each model and associate old M# with new M# 
     167        i = 0 
     168        for model in self.model_list: 
     169            model_id = self._format_id(model[1].keys()[0]) 
     170            for saved_model in sim_state.model_list: 
     171                save_id = saved_model.pop('name') 
     172                saved_model['name'] = save_id 
     173                save_id = self._format_id(save_id) 
     174                if save_id == model_id: 
     175                    model_map[saved_model.pop('fit_page_source')] = \ 
     176                        model[3].name 
     177                    check = bool(saved_model.pop('checked')) 
     178                    self.model_list[i][0].SetValue(check) 
     179                    break 
     180            i += 1 
     181 
     182        self.check_model_name(None) 
     183 
     184        if len(sim_state.constraints_list) > 0: 
     185            self.hide_constraint.SetValue(False) 
     186            self.show_constraint.SetValue(True) 
     187            self._display_constraint(None) 
     188 
     189        for index, item in enumerate(sim_state.constraints_list): 
     190            model_cbox = item.pop('model_cbox') 
     191            if model_cbox != "": 
     192                constraint_value = item.pop('constraint') 
     193                param = item.pop('param_cbox') 
     194                equality = item.pop('egal_txt') 
     195                for key, value in model_map.iteritems(): 
     196                    model_cbox.replace(key, value) 
     197                    constraint_value.replace(key, value) 
     198 
     199                self.constraints_list[index][0].SetValue(model_cbox) 
     200                self._on_select_model(None) 
     201                self.constraints_list[index][1].SetValue(param) 
     202                self.constraints_list[index][2].SetLabel(equality) 
     203                self.constraints_list[index][3].SetValue(constraint_value) 
     204                self._on_add_constraint(None) 
     205                self._manager.sim_page = self 
     206 
     207    def _format_id(self, original_id): 
     208        original_id = original_id.rstrip('1234567890.') 
     209        new_id_list = original_id.split() 
     210        new_id = ' '.join(new_id_list) 
     211        return new_id 
     212 
     213 
     214 
    159215    def draw_page(self): 
    160216        """ 
    161217        Construct the Simultaneous/Constrained fit page. fills the first 
    162         region (sizer1) with the list of available fit page pairs of data  
     218        region (sizer1) with the list of available fit page pairs of data 
    163219        and models.  Then fills sizer2 with the checkbox for adding 
    164220        constraints, and finally fills sizer3 with the fit button and 
     
    10431099        cbox.Append(name, value) 
    10441100    cbox.SetStringSelection(selected) 
    1045  
    1046  
    1047 class SimFitPageState: 
    1048     """ 
    1049     State of the simultaneous fit page for saving purposes 
    1050     """ 
    1051  
    1052     def __init__(self): 
    1053         # Sim Fit Page Number 
    1054         self.fit_page_no = None 
    1055         # Select all data 
    1056         self.select_all = False 
    1057         # Data sets sent to fit page 
    1058         self.model_list = [] 
    1059         # Data sets to be fit 
    1060         self.model_to_fit = [] 
    1061         # Number of constraints 
    1062         self.no_constraint = 0 
    1063         # Dictionary of constraints 
    1064         self.constraint_dict = {} 
    1065         # List of constraints 
    1066         self.constraints_list = [] 
    1067  
    1068     def load_from_save_state(self, fit): 
    1069         """ 
    1070         Load in a simultaneous/constrained fit from a save state 
    1071         :param fit: Fitpanel object 
    1072         :return: None 
    1073         """ 
    1074  
    1075         model_map = {} 
    1076         if fit.fit_panel.sim_page is None: 
    1077             fit.fit_panel.add_sim_page() 
    1078         sim_page = fit.fit_panel.sim_page 
    1079  
    1080         # Process each model and associate old M# with new M# 
    1081         i = 0 
    1082         for model in sim_page.model_list: 
    1083             model_id = self._format_id(model[1].keys()[0]) 
    1084             for saved_model in self.model_list: 
    1085                 save_id = saved_model.pop('name') 
    1086                 saved_model['name'] = save_id 
    1087                 save_id = self._format_id(save_id) 
    1088                 if save_id == model_id: 
    1089                     model_map[saved_model.pop('fit_page_source')] = \ 
    1090                         model[3].name 
    1091                     check = bool(saved_model.pop('checked')) 
    1092                     sim_page.model_list[i][0].SetValue(check) 
    1093                     break 
    1094             i += 1 
    1095         sim_page.check_model_name(None) 
    1096  
    1097         if len(self.constraints_list) > 0: 
    1098             sim_page.hide_constraint.SetValue(False) 
    1099             sim_page.show_constraint.SetValue(True) 
    1100             sim_page._display_constraint(None) 
    1101  
    1102         for index, item in enumerate(self.constraints_list): 
    1103             model_cbox = item.pop('model_cbox') 
    1104             if model_cbox != "": 
    1105                 constraint_value = item.pop('constraint') 
    1106                 param = item.pop('param_cbox') 
    1107                 equality = item.pop('egal_txt') 
    1108                 for key, value in model_map.iteritems(): 
    1109                     model_cbox.replace(key, value) 
    1110                     constraint_value.replace(key, value) 
    1111  
    1112                 sim_page.constraints_list[index][0].SetValue(model_cbox) 
    1113                 sim_page._on_select_model(None) 
    1114                 sim_page.constraints_list[index][1].SetValue(param) 
    1115                 sim_page.constraints_list[index][2].SetLabel(equality) 
    1116                 sim_page.constraints_list[index][3].SetValue(constraint_value) 
    1117                 sim_page._on_add_constraint(None) 
    1118                 sim_page._manager.sim_page = sim_page 
    1119  
    1120     def _format_id(self, original_id): 
    1121         original_id = original_id.rstrip('1234567890.') 
    1122         new_id_list = original_id.split() 
    1123         new_id = ' '.join(new_id_list) 
    1124         return new_id 
Note: See TracChangeset for help on using the changeset viewer.