Changes in / [d76c43a:69363c7] in sasview
- Files:
-
- 4 added
- 4 deleted
- 17 edited
Legend:
- Unmodified
- Added
- Removed
-
sasview/sasview.py
r3b0f8cc r3b0f8cc 99 99 # to ensure a complete Windows executable build. 100 100 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 101 112 # Fitting perspective 102 113 try: -
src/sas/sascalc/fit/AbstractFitEngine.py
ra1b8fee r50fcb09 137 137 that will smear the theory data (slit smearing or resolution 138 138 smearing) when set. 139 139 140 140 The proper way to set the smearing object would be to 141 141 do the following: :: 142 143 from sas.sascalc. data_util.qsmearing import smear_selection142 143 from sas.sascalc.fit.qsmearing import smear_selection 144 144 smearer = smear_selection(some_data) 145 145 fitdata1d = FitData1D( x= [1,3,..,], … … 147 147 dx=None, 148 148 dy=[1,2...], smearer= smearer) 149 149 150 150 :Note: that some_data _HAS_ to be of 151 151 class DataLoader.data_info.Data1D 152 152 Setting it back to None will turn smearing off. 153 153 154 154 """ 155 155 Data1D.__init__(self, x=x, y=y, dx=dx, dy=dy, lam=lam, dlam=dlam) … … 176 176 ## Max Q-value 177 177 self.qmax = max(self.x) 178 178 179 179 # Range used for input to smearing 180 180 self._qmin_unsmeared = self.qmin … … 184 184 self.idx_unsmeared = (self.x >= self._qmin_unsmeared) \ 185 185 & (self.x <= self._qmax_unsmeared) 186 186 187 187 def set_fit_range(self, qmin=None, qmax=None): 188 188 """ to set the fit range""" … … 199 199 self._qmin_unsmeared = self.qmin 200 200 self._qmax_unsmeared = self.qmax 201 201 202 202 self._first_unsmeared_bin = 0 203 203 self._last_unsmeared_bin = len(self.x) - 1 204 204 205 205 if self.smearer is not None: 206 206 self._first_unsmeared_bin, self._last_unsmeared_bin = \ … … 208 208 self._qmin_unsmeared = self.x[self._first_unsmeared_bin] 209 209 self._qmax_unsmeared = self.x[self._last_unsmeared_bin] 210 210 211 211 # Identify the bin range for the unsmeared and smeared spaces 212 212 self.idx = (self.x >= self.qmin) & (self.x <= self.qmax) … … 231 231 """ 232 232 Compute residuals. 233 233 234 234 If self.smearer has been set, use if to smear 235 235 the data before computing chi squared. 236 236 237 237 :param fn: function that return model value 238 238 239 239 :return: residuals 240 240 """ … … 242 242 fx = np.zeros(len(self.x)) 243 243 fx[self.idx_unsmeared] = fn(self.x[self.idx_unsmeared]) 244 244 245 245 ## Smear theory data 246 246 if self.smearer is not None: … … 253 253 raise RuntimeError, msg 254 254 return (self.y[self.idx] - fx[self.idx]) / self.dy[self.idx], fx[self.idx] 255 255 256 256 def residuals_deriv(self, model, pars=[]): 257 257 """ 258 258 :return: residuals derivatives . 259 260 :note: in this case just return empty array 259 260 :note: in this case just return empty array 261 261 """ 262 262 return [] … … 293 293 x_max = max(math.fabs(sas_data2d.xmin), math.fabs(sas_data2d.xmax)) 294 294 y_max = max(math.fabs(sas_data2d.ymin), math.fabs(sas_data2d.ymax)) 295 295 296 296 ## fitting range 297 297 if qmin is None: … … 305 305 self.res_err_data = copy.deepcopy(self.err_data) 306 306 #self.res_err_data[self.res_err_data==0]=1 307 307 308 308 self.radius = np.sqrt(self.qx_data**2 + self.qy_data**2) 309 309 310 310 # Note: mask = True: for MASK while mask = False for NOT to mask 311 311 self.idx = ((self.qmin <= self.radius) &\ … … 368 368 369 369 return res, gn 370 370 371 371 def residuals_deriv(self, model, pars=[]): 372 372 """ 373 373 :return: residuals derivatives . 374 374 375 375 :note: in this case just return empty array 376 376 377 377 """ 378 378 return [] 379 380 379 380 381 381 class FitAbort(Exception): 382 382 """ … … 396 396 self.fit_arrange_dict = {} 397 397 self.fitter_id = None 398 398 399 399 def set_model(self, model, id, pars=[], constraints=[], data=None): 400 400 """ 401 401 set a model on a given in the fit engine. 402 403 :param model: sas.models type 402 403 :param model: sas.models type 404 404 :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 407 407 tuple (name of parameter, value of parameters) 408 408 the value of parameter must be a string to constraint 2 different 409 409 parameters. 410 Example: 410 Example: 411 411 we want to fit 2 model M1 and M2 both have parameters A and B. 412 412 constraints can be ``constraints = [(M1.A, M2.B+2), (M1.B= M2.A *5),...,]`` 413 414 413 414 415 415 :note: pars must contains only name of existing model's parameters 416 416 417 417 """ 418 418 if not pars: … … 445 445 in a FitArrange object and adds that object in a dictionary 446 446 with key id. 447 447 448 448 :param data: data added 449 449 :param id: unique key corresponding to a fitArrange object with data … … 456 456 dx=data.dx, dy=data.dy, smearer=smearer) 457 457 fitdata.sas_data = data 458 458 459 459 fitdata.set_fit_range(qmin=qmin, qmax=qmax) 460 460 #A fitArrange is already created but contains model only at id … … 466 466 fitproblem.add_data(fitdata) 467 467 self.fit_arrange_dict[id] = fitproblem 468 468 469 469 def get_model(self, id): 470 470 """ 471 471 :param id: id is key in the dictionary containing the model to return 472 472 473 473 :return: a model at this id or None if no FitArrange element was 474 474 created with this id … … 478 478 else: 479 479 return None 480 480 481 481 def remove_fit_problem(self, id): 482 482 """remove fitarrange in id""" 483 483 if id in self.fit_arrange_dict: 484 484 del self.fit_arrange_dict[id] 485 485 486 486 def select_problem_for_fit(self, id, value): 487 487 """ 488 488 select a couple of model and data at the id position in dictionary 489 489 and set in self.selected value to value 490 490 491 491 :param value: the value to allow fitting. 492 492 can only have the value one or zero … … 494 494 if id in self.fit_arrange_dict: 495 495 self.fit_arrange_dict[id].set_to_fit(value) 496 496 497 497 def get_problem_to_fit(self, id): 498 498 """ 499 499 return the self.selected value of the fit problem of id 500 500 501 501 :param id: the id of the problem 502 502 """ 503 503 if id in self.fit_arrange_dict: 504 504 self.fit_arrange_dict[id].get_to_fit() 505 506 505 506 507 507 class FitArrange: 508 508 def __init__(self): … … 511 511 to perform the Fit.FitArrange must contain exactly one model 512 512 and at least one data for the fit to be performed. 513 513 514 514 model: the model selected by the user 515 515 Ldata: a list of data what the user wants to fit 516 516 517 517 """ 518 518 self.model = None … … 525 525 """ 526 526 set_model save a copy of the model 527 527 528 528 :param model: the model being set 529 529 """ 530 530 self.model = model 531 531 532 532 def add_data(self, data): 533 533 """ 534 534 add_data fill a self.data_list with data to fit 535 535 536 536 :param data: Data to add in the list 537 537 """ 538 538 if not data in self.data_list: 539 539 self.data_list.append(data) 540 540 541 541 def get_model(self): 542 542 """ … … 544 544 """ 545 545 return self.model 546 546 547 547 def get_data(self): 548 548 """ … … 550 550 """ 551 551 return self.data_list[0] 552 552 553 553 def remove_data(self, data): 554 554 """ 555 555 Remove one element from the list 556 556 557 557 :param data: Data to remove from data_list 558 558 """ 559 559 if data in self.data_list: 560 560 self.data_list.remove(data) 561 561 562 562 def set_to_fit(self, value=0): 563 563 """ 564 564 set self.selected to 0 or 1 for other values raise an exception 565 565 566 566 :param value: integer between 0 or 1 567 567 """ 568 568 self.selected = value 569 569 570 570 def get_to_fit(self): 571 571 """ … … 599 599 if self.model is not None and self.data is not None: 600 600 self.inputs = [(self.model, self.data)] 601 601 602 602 def set_model(self, model): 603 603 """ 604 604 """ 605 605 self.model = model 606 606 607 607 def set_fitness(self, fitness): 608 608 """ 609 609 """ 610 610 self.fitness = fitness 611 611 612 612 def __str__(self): 613 613 """ … … 624 624 msg = [msg1, msg3] + msg2 625 625 return "\n".join(msg) 626 626 627 627 def print_summary(self): 628 628 """ -
src/sas/sascalc/fit/BumpsFitting.py
r9a5097c r1386b2f 15 15 def get_fitter(): 16 16 return FIT_CONFIG.selected_fitter, FIT_CONFIG.selected_values 17 except :17 except ImportError: 18 18 # CRUFT: Bumps changed its handling of fit options around 0.7.5.6 19 19 # Default bumps to use the Levenberg-Marquardt optimizer … … 56 56 header = "=== Steps: %s chisq: %s ETA: %s\n"%(step, chisq, time) 57 57 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]))] 59 59 self.msg = "".join([header]+parameters) 60 60 … … 77 77 self.handler.set_result(Progress(history, self.max_step, self.pars, self.dof)) 78 78 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]: 80 80 self.handler.improvement() 81 81 self.handler.update_fit() … … 97 97 try: 98 98 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)) 104 104 105 105 … … 131 131 132 132 def _reset_pars(self, names, values): 133 for k, v in zip(names, values):133 for k, v in zip(names, values): 134 134 self._pars[k].value = v 135 135 … … 137 137 self._pars = {} 138 138 for k in self.model.getParamList(): 139 name = ".".join((self.name, k))139 name = ".".join((self.name, k)) 140 140 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] 142 142 self._pars[k] = parameter.Parameter(value=value, bounds=bounds, 143 143 fixed=True, name=name) … … 145 145 146 146 def _init_pars(self, kw): 147 for k, v in kw.items():147 for k, v in kw.items(): 148 148 # 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' 153 157 if k not in self._pars: 154 158 formatted_pars = ", ".join(sorted(self._pars.keys())) … … 159 163 elif isinstance(v, parameter.BaseParameter): 160 164 self._pars[k] = v 161 elif isinstance(v, (tuple, list)):165 elif isinstance(v, (tuple, list)): 162 166 low, high = v 163 167 self._pars[k].value = (low+high)/2 164 self._pars[k].range(low, high)168 self._pars[k].range(low, high) 165 169 else: 166 170 self._pars[k].value = v … … 170 174 Flag a set of parameters as fitted parameters. 171 175 """ 172 for k, p in self._pars.items():176 for k, p in self._pars.items(): 173 177 p.fixed = (k not in param_list or k in self.constraints) 174 178 self.fitted_par_names = [k for k in param_list if k not in self.constraints] … … 182 186 183 187 def update(self): 184 for k, v in self._pars.items():188 for k, v in self._pars.items(): 185 189 #print "updating",k,v,v.value 186 self.model.setParam(k, v.value)190 self.model.setParam(k, v.value) 187 191 self._dirty = True 188 192 … … 223 227 symtab = dict((".".join((M.name, k)), p) 224 228 for M in self.models 225 for k, p in M.parameters().items())229 for k, p in M.parameters().items()) 226 230 self.update = compile_constraints(symtab, exprs) 227 231 else: … … 300 304 np.NaN*np.ones(len(fitness.computed_pars)))) 301 305 R.pvec = np.hstack((result['value'][fitted_index], 302 306 [p.value for p in fitness.computed_pars])) 303 307 R.fitness = np.sum(R.residuals**2)/(fitness.numpoints() - len(fitted_index)) 304 308 else: 305 309 R.stderr = np.NaN*np.ones(len(param_list)) 306 R.pvec = np.asarray( 310 R.pvec = np.asarray([p.value for p in fitness.fitted_pars+fitness.computed_pars]) 307 311 R.fitness = np.NaN 308 312 R.convergence = result['convergence'] … … 331 335 steps = options.get('steps', 0) 332 336 if steps == 0: 333 pop = options.get('pop', 0)*len(problem._parameters)337 pop = options.get('pop', 0)*len(problem._parameters) 334 338 samples = options.get('samples', 0) 335 339 steps = (samples+pop-1)/pop if pop != 0 else samples … … 343 347 fitdriver = fitters.FitDriver(fitclass, problem=problem, 344 348 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')) 346 350 mapper = MPMapper if omp_threads == 1 else SerialMapper 347 351 fitdriver.mapper = mapper.start_mapper(problem, None) … … 359 363 convergence_list = options['monitors'][-1].convergence 360 364 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')) 362 366 363 367 success = best is not None … … 376 380 'errors': '\n'.join(errors), 377 381 } 378 -
src/sas/sascalc/pr/fit/AbstractFitEngine.py
ra1b8fee r50fcb09 137 137 that will smear the theory data (slit smearing or resolution 138 138 smearing) when set. 139 139 140 140 The proper way to set the smearing object would be to 141 141 do the following: :: 142 143 from sas.sascalc. data_util.qsmearing import smear_selection142 143 from sas.sascalc.fit.qsmearing import smear_selection 144 144 smearer = smear_selection(some_data) 145 145 fitdata1d = FitData1D( x= [1,3,..,], … … 147 147 dx=None, 148 148 dy=[1,2...], smearer= smearer) 149 149 150 150 :Note: that some_data _HAS_ to be of 151 151 class DataLoader.data_info.Data1D 152 152 Setting it back to None will turn smearing off. 153 153 154 154 """ 155 155 Data1D.__init__(self, x=x, y=y, dx=dx, dy=dy) … … 176 176 ## Max Q-value 177 177 self.qmax = max(self.x) 178 178 179 179 # Range used for input to smearing 180 180 self._qmin_unsmeared = self.qmin … … 184 184 self.idx_unsmeared = (self.x >= self._qmin_unsmeared) \ 185 185 & (self.x <= self._qmax_unsmeared) 186 186 187 187 def set_fit_range(self, qmin=None, qmax=None): 188 188 """ to set the fit range""" … … 199 199 self._qmin_unsmeared = self.qmin 200 200 self._qmax_unsmeared = self.qmax 201 201 202 202 self._first_unsmeared_bin = 0 203 203 self._last_unsmeared_bin = len(self.x) - 1 204 204 205 205 if self.smearer is not None: 206 206 self._first_unsmeared_bin, self._last_unsmeared_bin = \ … … 208 208 self._qmin_unsmeared = self.x[self._first_unsmeared_bin] 209 209 self._qmax_unsmeared = self.x[self._last_unsmeared_bin] 210 210 211 211 # Identify the bin range for the unsmeared and smeared spaces 212 212 self.idx = (self.x >= self.qmin) & (self.x <= self.qmax) … … 231 231 """ 232 232 Compute residuals. 233 233 234 234 If self.smearer has been set, use if to smear 235 235 the data before computing chi squared. 236 236 237 237 :param fn: function that return model value 238 238 239 239 :return: residuals 240 240 """ … … 242 242 fx = np.zeros(len(self.x)) 243 243 fx[self.idx_unsmeared] = fn(self.x[self.idx_unsmeared]) 244 244 245 245 ## Smear theory data 246 246 if self.smearer is not None: … … 253 253 raise RuntimeError, msg 254 254 return (self.y[self.idx] - fx[self.idx]) / self.dy[self.idx], fx[self.idx] 255 255 256 256 def residuals_deriv(self, model, pars=[]): 257 257 """ 258 258 :return: residuals derivatives . 259 260 :note: in this case just return empty array 259 260 :note: in this case just return empty array 261 261 """ 262 262 return [] … … 293 293 x_max = max(math.fabs(sas_data2d.xmin), math.fabs(sas_data2d.xmax)) 294 294 y_max = max(math.fabs(sas_data2d.ymin), math.fabs(sas_data2d.ymax)) 295 295 296 296 ## fitting range 297 297 if qmin is None: … … 305 305 self.res_err_data = copy.deepcopy(self.err_data) 306 306 #self.res_err_data[self.res_err_data==0]=1 307 307 308 308 self.radius = np.sqrt(self.qx_data**2 + self.qy_data**2) 309 309 310 310 # Note: mask = True: for MASK while mask = False for NOT to mask 311 311 self.idx = ((self.qmin <= self.radius) &\ … … 371 371 372 372 return res, gn 373 373 374 374 def residuals_deriv(self, model, pars=[]): 375 375 """ 376 376 :return: residuals derivatives . 377 377 378 378 :note: in this case just return empty array 379 379 380 380 """ 381 381 return [] 382 383 382 383 384 384 class FitAbort(Exception): 385 385 """ … … 399 399 self.fit_arrange_dict = {} 400 400 self.fitter_id = None 401 401 402 402 def set_model(self, model, id, pars=[], constraints=[], data=None): 403 403 """ 404 404 set a model on a given in the fit engine. 405 406 :param model: sas.models type 405 406 :param model: sas.models type 407 407 :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 410 410 tuple (name of parameter, value of parameters) 411 411 the value of parameter must be a string to constraint 2 different 412 412 parameters. 413 Example: 413 Example: 414 414 we want to fit 2 model M1 and M2 both have parameters A and B. 415 415 constraints can be ``constraints = [(M1.A, M2.B+2), (M1.B= M2.A *5),...,]`` 416 417 416 417 418 418 :note: pars must contains only name of existing model's parameters 419 419 420 420 """ 421 421 if not pars: … … 448 448 in a FitArrange object and adds that object in a dictionary 449 449 with key id. 450 450 451 451 :param data: data added 452 452 :param id: unique key corresponding to a fitArrange object with data … … 459 459 dx=data.dx, dy=data.dy, smearer=smearer) 460 460 fitdata.sas_data = data 461 461 462 462 fitdata.set_fit_range(qmin=qmin, qmax=qmax) 463 463 #A fitArrange is already created but contains model only at id … … 469 469 fitproblem.add_data(fitdata) 470 470 self.fit_arrange_dict[id] = fitproblem 471 471 472 472 def get_model(self, id): 473 473 """ 474 474 :param id: id is key in the dictionary containing the model to return 475 475 476 476 :return: a model at this id or None if no FitArrange element was 477 477 created with this id … … 481 481 else: 482 482 return None 483 483 484 484 def remove_fit_problem(self, id): 485 485 """remove fitarrange in id""" 486 486 if id in self.fit_arrange_dict: 487 487 del self.fit_arrange_dict[id] 488 488 489 489 def select_problem_for_fit(self, id, value): 490 490 """ 491 491 select a couple of model and data at the id position in dictionary 492 492 and set in self.selected value to value 493 493 494 494 :param value: the value to allow fitting. 495 495 can only have the value one or zero … … 497 497 if id in self.fit_arrange_dict: 498 498 self.fit_arrange_dict[id].set_to_fit(value) 499 499 500 500 def get_problem_to_fit(self, id): 501 501 """ 502 502 return the self.selected value of the fit problem of id 503 503 504 504 :param id: the id of the problem 505 505 """ 506 506 if id in self.fit_arrange_dict: 507 507 self.fit_arrange_dict[id].get_to_fit() 508 509 508 509 510 510 class FitArrange: 511 511 def __init__(self): … … 514 514 to perform the Fit.FitArrange must contain exactly one model 515 515 and at least one data for the fit to be performed. 516 516 517 517 model: the model selected by the user 518 518 Ldata: a list of data what the user wants to fit 519 519 520 520 """ 521 521 self.model = None … … 528 528 """ 529 529 set_model save a copy of the model 530 530 531 531 :param model: the model being set 532 532 """ 533 533 self.model = model 534 534 535 535 def add_data(self, data): 536 536 """ 537 537 add_data fill a self.data_list with data to fit 538 538 539 539 :param data: Data to add in the list 540 540 """ 541 541 if not data in self.data_list: 542 542 self.data_list.append(data) 543 543 544 544 def get_model(self): 545 545 """ … … 547 547 """ 548 548 return self.model 549 549 550 550 def get_data(self): 551 551 """ … … 553 553 """ 554 554 return self.data_list[0] 555 555 556 556 def remove_data(self, data): 557 557 """ 558 558 Remove one element from the list 559 559 560 560 :param data: Data to remove from data_list 561 561 """ 562 562 if data in self.data_list: 563 563 self.data_list.remove(data) 564 564 565 565 def set_to_fit(self, value=0): 566 566 """ 567 567 set self.selected to 0 or 1 for other values raise an exception 568 568 569 569 :param value: integer between 0 or 1 570 570 """ 571 571 self.selected = value 572 572 573 573 def get_to_fit(self): 574 574 """ … … 602 602 if self.model is not None and self.data is not None: 603 603 self.inputs = [(self.model, self.data)] 604 604 605 605 def set_model(self, model): 606 606 """ 607 607 """ 608 608 self.model = model 609 609 610 610 def set_fitness(self, fitness): 611 611 """ 612 612 """ 613 613 self.fitness = fitness 614 614 615 615 def __str__(self): 616 616 """ … … 627 627 msg = [msg1, msg3] + msg2 628 628 return "\n".join(msg) 629 629 630 630 def print_summary(self): 631 631 """ -
src/sas/sascalc/realspace/VolumeCanvas.py
r235f514 r98e3f24 4 4 Simulation canvas for real-space simulation of SAS scattering intensity. 5 5 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 8 8 Example: 9 9 10 10 import sas.sascalc.realspace.VolumeCanvas as VolumeCanvas 11 11 canvas = VolumeCanvas.VolumeCanvas() 12 12 canvas.setParam('lores_density', 0.01) 13 13 14 14 sphere = SphereDescriptor() 15 15 handle = canvas.addObject(sphere) … … 17 17 output, error = canvas.getIqError(q=0.1) 18 18 output, error = canvas.getIq2DError(0.1, 0.1) 19 19 20 20 or alternatively: 21 21 iq = canvas.run(0.1) 22 22 i2_2D = canvas.run([0.1, 1.57]) 23 23 24 24 """ 25 25 26 from sas. models.BaseComponent import BaseComponent26 from sas.sascalc.calculator.BaseComponent import BaseComponent 27 27 from sas.sascalc.simulation.pointsmodelpy import pointsmodelpy 28 28 from sas.sascalc.simulation.geoshapespy import geoshapespy … … 31 31 import os.path, math 32 32 33 class ShapeDescriptor :33 class ShapeDescriptor(object): 34 34 """ 35 35 Class to hold the information about a shape 36 36 The descriptor holds a dictionary of parameters. 37 37 38 38 Note: if shape parameters are accessed directly 39 39 from outside VolumeCanvas. The getPr method 40 40 should be called before evaluating I(q). 41 41 42 42 """ 43 43 def __init__(self): … … 55 55 self.params['is_lores'] = True 56 56 self.params['order'] = 0 57 57 58 58 def create(self): 59 59 """ … … 65 65 z0 = self.params["center"][2] 66 66 geoshapespy.set_center(self.shapeObject, x0, y0, z0) 67 67 68 68 # Set orientation 69 69 x0 = self.params["orientation"][0] … … 71 71 z0 = self.params["orientation"][2] 72 72 geoshapespy.set_orientation(self.shapeObject, x0, y0, z0) 73 73 74 74 class SphereDescriptor(ShapeDescriptor): 75 75 """ 76 76 Descriptor for a sphere 77 77 78 78 The parameters are: 79 79 - radius [Angstroem] [default = 20 A] 80 80 - Contrast [A-2] [default = 1 A-2] 81 81 82 82 """ 83 83 def __init__(self): 84 84 """ 85 85 Initialization 86 """ 86 """ 87 87 ShapeDescriptor.__init__(self) 88 88 # Default parameters 89 self.params["type"] 89 self.params["type"] = "sphere" 90 90 # Radius of the sphere 91 91 self.params["radius"] = 20.0 … … 100 100 self.shapeObject = geoshapespy.new_sphere(\ 101 101 self.params["radius"]) 102 103 ShapeDescriptor.create(self) 102 103 ShapeDescriptor.create(self) 104 104 return self.shapeObject 105 105 106 106 class CylinderDescriptor(ShapeDescriptor): 107 107 """ 108 108 Descriptor for a cylinder 109 109 Orientation: Default cylinder is along Y 110 110 111 111 Parameters: 112 112 - Length [default = 40 A] … … 117 117 """ 118 118 Initialization 119 """ 119 """ 120 120 ShapeDescriptor.__init__(self) 121 121 # Default parameters 122 self.params["type"] 122 self.params["type"] = "cylinder" 123 123 # Length of the cylinder 124 124 self.params["length"] = 40.0 … … 127 127 # Constrast parameter 128 128 self.params["contrast"] = 1.0 129 129 130 130 def create(self): 131 131 """ … … 138 138 ShapeDescriptor.create(self) 139 139 return self.shapeObject 140 140 141 141 142 142 class EllipsoidDescriptor(ShapeDescriptor): 143 143 """ 144 144 Descriptor for an ellipsoid 145 145 146 146 Parameters: 147 147 - Radius_x along the x-axis [default = 30 A] … … 153 153 """ 154 154 Initialization 155 """ 155 """ 156 156 ShapeDescriptor.__init__(self) 157 157 # Default parameters 158 self.params["type"] 158 self.params["type"] = "ellipsoid" 159 159 self.params["radius_x"] = 30.0 160 160 self.params["radius_y"] = 20.0 161 161 self.params["radius_z"] = 10.0 162 162 self.params["contrast"] = 1.0 163 163 164 164 def create(self): 165 165 """ … … 168 168 """ 169 169 self.shapeObject = geoshapespy.new_ellipsoid(\ 170 self.params["radius_x"], self.params["radius_y"], 170 self.params["radius_x"], self.params["radius_y"], 171 171 self.params["radius_z"]) 172 173 ShapeDescriptor.create(self) 172 173 ShapeDescriptor.create(self) 174 174 return self.shapeObject 175 175 176 176 class HelixDescriptor(ShapeDescriptor): 177 177 """ 178 178 Descriptor for an helix 179 179 180 180 Parameters: 181 181 -radius_helix: the radius of the helix [default = 10 A] … … 188 188 """ 189 189 Initialization 190 """ 190 """ 191 191 ShapeDescriptor.__init__(self) 192 192 # Default parameters 193 self.params["type"] 193 self.params["type"] = "singlehelix" 194 194 self.params["radius_helix"] = 10.0 195 195 self.params["radius_tube"] = 3.0 … … 204 204 """ 205 205 self.shapeObject = geoshapespy.new_singlehelix(\ 206 self.params["radius_helix"], self.params["radius_tube"], 206 self.params["radius_helix"], self.params["radius_tube"], 207 207 self.params["pitch"], self.params["turns"]) 208 209 ShapeDescriptor.create(self) 208 209 ShapeDescriptor.create(self) 210 210 return self.shapeObject 211 211 212 212 class PDBDescriptor(ShapeDescriptor): 213 213 """ 214 214 Descriptor for a PDB set of points 215 215 216 216 Parameter: 217 217 - file = name of the PDB file … … 221 221 Initialization 222 222 @param filename: name of the PDB file to load 223 """ 223 """ 224 224 ShapeDescriptor.__init__(self) 225 225 # Default parameters 226 self.params["type"] 226 self.params["type"] = "pdb" 227 227 self.params["file"] = filename 228 228 self.params['is_lores'] = False … … 234 234 """ 235 235 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) 239 239 return self.shapeObject 240 240 241 241 # Define a dictionary for the shape until we find 242 242 # a better way to create them … … 245 245 'ellipsoid':EllipsoidDescriptor, 246 246 'singlehelix':HelixDescriptor} 247 247 248 248 class VolumeCanvas(BaseComponent): 249 249 """ 250 Class representing an empty space volume to add 250 Class representing an empty space volume to add 251 251 geometrical object to. 252 252 253 253 For 1D I(q) simulation, getPr() is called internally for the 254 254 first call to getIq(). 255 256 """ 257 255 256 """ 257 258 258 def __init__(self): 259 259 """ … … 261 261 """ 262 262 BaseComponent.__init__(self) 263 263 264 264 ## Maximum value of q reachable 265 265 self.params['q_max'] = 0.1 … … 267 267 self.params['scale'] = 1.0 268 268 self.params['background'] = 0.0 269 269 270 270 self.lores_model = pointsmodelpy.new_loresmodel(self.params['lores_density']) 271 271 self.complex_model = pointsmodelpy.new_complexmodel() 272 272 self.shapes = {} 273 self.shapecount = 0 273 self.shapecount = 0 274 274 self.points = None 275 275 self.npts = 0 276 self.hasPr = False 277 276 self.hasPr = False 277 278 278 def _model_changed(self): 279 279 """ 280 Reset internal data members to reflect the fact that the 280 Reset internal data members to reflect the fact that the 281 281 real-space model has changed 282 282 """ 283 self.hasPr 283 self.hasPr = False 284 284 self.points = None 285 286 def addObject(self, shapeDesc, id =None):285 286 def addObject(self, shapeDesc, id=None): 287 287 """ 288 288 Adds a real-space object to the canvas. 289 289 290 290 @param shapeDesc: object to add to the canvas [ShapeDescriptor] 291 291 @param id: string handle for the object [string] [optional] … … 295 295 if id is None: 296 296 id = shapeDesc.params["type"]+str(self.shapecount) 297 297 298 298 # Self the order number 299 299 shapeDesc.params['order'] = self.shapecount … … 307 307 308 308 return id 309 310 311 def add(self, shape, id =None):309 310 311 def add(self, shape, id=None): 312 312 """ 313 313 The intend of this method is to eventually be able to use it … … 315 315 analytical solutions. For instance, if one adds a cylinder and 316 316 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 318 318 simulation has to be performed. 319 319 320 320 This function is deprecated, use addObject(). 321 321 322 322 @param shape: name of the object to add to the canvas [string] 323 323 @param id: string handle for the object [string] [optional] … … 327 327 if id is None: 328 328 id = "shape"+str(self.shapecount) 329 329 330 330 # shapeDesc = ShapeDescriptor(shape.lower()) 331 331 if shape.lower() in shape_dict: … … 336 336 else: 337 337 raise ValueError("VolumeCanvas.add: Unknown shape %s" % shape) 338 338 339 339 return self.addObject(shapeDesc, id) 340 340 … … 354 354 355 355 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. 359 359 Both VolumeCanvas parameters and shape parameters 360 are accessible. 361 360 are accessible. 361 362 362 Note: if shape parameters are accessed directly 363 363 from outside VolumeCanvas. The getPr method 364 364 should be called before evaluating I(q). 365 365 366 366 TODO: implemented a check method to protect 367 367 against that. 368 368 369 369 @param name: name of the parameter to change 370 370 @param value: value to give the parameter 371 371 """ 372 372 373 373 # Lowercase for case insensitivity 374 374 name = name.lower() 375 375 376 376 # Look for shape access 377 377 toks = name.split('.') 378 378 379 379 # If a shape identifier was given, look the shape up 380 380 # in the dictionary … … 390 390 else: 391 391 raise ValueError("Could not find shape %s" % toks[0]) 392 392 393 393 else: 394 # If we are not accessing the parameters of a 394 # If we are not accessing the parameters of a 395 395 # shape, see if the parameter is part of this object 396 396 BaseComponent.setParam(self, name, value) 397 397 self._model_changed() 398 398 399 def getParam(self, name): 399 def getParam(self, name): 400 400 """ 401 401 @param name: name of the parameter to change 402 402 """ 403 403 #TODO: clean this up 404 404 405 405 # Lowercase for case insensitivity 406 406 name = name.lower() 407 407 408 408 # Look for sub-model access 409 409 toks = name.split('.') … … 435 435 else: 436 436 raise ValueError("VolumeCanvas.getParam: Could not find %s" % name) 437 437 438 438 def getParamList(self, shapeid=None): 439 439 """ 440 return a full list of all available parameters from 440 return a full list of all available parameters from 441 441 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: 443 443 [param1,param2,shapeid.param1,shapeid.param2.......] 444 444 … … 456 456 header = key2 + '.' 457 457 for key3 in value2.params: 458 fullname = header + key3 458 fullname = header + key3 459 459 param_list.append(fullname) 460 460 461 461 else: 462 462 if not shapeid in self.shapes: … … 470 470 def getShapeList(self): 471 471 """ 472 Return a list of the shapes 472 Return a list of the shapes 473 473 """ 474 474 return self.shapes.keys() … … 481 481 # Create the object model 482 482 shapeDesc.create() 483 483 484 484 if shapeDesc.params['is_lores']: 485 485 # 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']) 488 489 489 490 def _createVolumeFromList(self): … … 492 493 Whenever we change a parameter of a shape, we have to re-create 493 494 the whole thing. 494 495 495 496 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 497 498 overlapping region belonging to objects with lower 'order' 498 499 will be ignored. 499 500 500 501 Items are added in decreasing 'order' number. 501 502 The item with the highest 'order' will be added *first*. 502 503 [That conventions is prescribed by the realSpaceModeling module] 503 504 """ 504 505 505 506 # Create empty model 506 507 self.lores_model = \ … … 509 510 # Create empty complex model 510 511 self.complex_model = pointsmodelpy.new_complexmodel() 511 512 512 513 # Order the object first 513 514 obj_list = [] 514 515 515 516 for shape in self.shapes: 516 517 order = self.shapes[shape].params['order'] 517 518 # find where to place it in the list 518 519 stored = False 519 520 520 521 for i in range(len(obj_list)): 521 522 if obj_list[i][0] > order: … … 523 524 stored = True 524 525 break 525 526 526 527 if not stored: 527 528 obj_list.append([order, shape]) 528 529 529 530 # Add each shape 530 531 len_list = len(obj_list) … … 533 534 self._addSingleShape(shapedesc) 534 535 535 return 0 536 536 return 0 537 537 538 def getPr(self): 538 539 """ … … 540 541 This method should always be called after the shapes 541 542 on the VolumeCanvas have changed. 542 543 @return: calculation output flag 543 544 @return: calculation output flag 544 545 """ 545 546 # To find a complete example of the correct call order: 546 547 # In LORES2, in actionclass.py, method CalculateAction._get_iq() 547 548 548 549 # If there are not shapes, do nothing 549 550 if len(self.shapes) == 0: 550 551 self._model_changed() 551 552 return 0 552 553 553 554 # generate space filling points from shape list 554 555 self._createVolumeFromList() … … 556 557 self.points = pointsmodelpy.new_point3dvec() 557 558 558 pointsmodelpy.complexmodel_add(self.complex_model, 559 559 pointsmodelpy.complexmodel_add(self.complex_model, 560 self.lores_model, "LORES") 560 561 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, 563 564 self.shapes[shape].shapeObject, "PDB") 564 565 565 566 #pointsmodelpy.get_lorespoints(self.lores_model, self.points) 566 567 self.npts = pointsmodelpy.get_complexpoints(self.complex_model, self.points) 567 568 568 569 # 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 573 574 574 575 return rmax 575 576 def run(self, q =0):576 577 def run(self, q=0): 577 578 """ 578 579 Returns the value of I(q) for a given q-value … … 595 596 else: 596 597 raise ValueError("run(q): bad type for q") 597 598 def runXY(self, q =0):598 599 def runXY(self, q=0): 599 600 """ 600 601 Standard run command for the canvas. 601 Redirects to the correct method 602 Redirects to the correct method 602 603 according to the input type. 603 604 @param q: q-value [float] or [list] [A-1] … … 615 616 else: 616 617 raise ValueError("runXY(q): bad type for q") 617 618 618 619 def _create_modelObject(self): 619 620 """ 620 621 Create the simulation model obejct from the list 621 622 of shapes. 622 623 623 624 This method needs to be called each time a parameter 624 625 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 627 628 refill the space points. 628 629 629 630 TODO: improve that. 630 631 """ 631 632 # To find a complete example of the correct call order: 632 633 # In LORES2, in actionclass.py, method CalculateAction._get_iq() 633 634 634 635 # If there are not shapes, do nothing 635 636 if len(self.shapes) == 0: 636 637 self._model_changed() 637 638 return 0 638 639 639 640 # generate space filling points from shape list 640 641 self._createVolumeFromList() … … 642 643 self.points = pointsmodelpy.new_point3dvec() 643 644 644 pointsmodelpy.complexmodel_add(self.complex_model, 645 645 pointsmodelpy.complexmodel_add(self.complex_model, 646 self.lores_model, "LORES") 646 647 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, 649 650 self.shapes[shape].shapeObject, "PDB") 650 651 651 652 #pointsmodelpy.get_lorespoints(self.lores_model, self.points) 652 653 self.npts = pointsmodelpy.get_complexpoints(self.complex_model, self.points) 653 654 654 655 655 656 def getIq2D(self, qx, qy): 656 657 """ … … 660 661 @return: I(q) [cm-1] 661 662 """ 662 663 663 664 # If this is the first simulation call, we need to generate the 664 665 # space points 665 666 if self.points is None: 666 667 self._create_modelObject() 667 668 668 669 # Protect against empty model 669 670 if self.points is None: 670 671 return 0 671 672 # Evalute I(q) 673 norm = 672 673 # Evalute I(q) 674 norm = 1.0e8/self.params['lores_density']*self.params['scale'] 674 675 return norm*pointsmodelpy.get_complex_iq_2D(self.complex_model, self.points, qx, qy)\ 675 676 + self.params['background'] 676 677 677 678 def write_pr(self, filename): 678 679 """ 679 680 Write P(r) to an output file 680 681 @param filename: file name for P(r) output 681 """ 682 if self.hasPr == False:682 """ 683 if not self.hasPr: 683 684 self.getPr() 684 685 685 686 pointsmodelpy.outputPR(self.complex_model, filename) 686 687 687 688 def getPrData(self): 688 689 """ 689 690 Write P(r) to an output file 690 691 @param filename: file name for P(r) output 691 """ 692 if self.hasPr == False:692 """ 693 if not self.hasPr: 693 694 self.getPr() 694 695 695 696 return pointsmodelpy.get_pr(self.complex_model) 696 697 697 698 def getIq(self, q): 698 699 """ 699 700 Returns the value of I(q) for a given q-value 700 701 701 702 This method should remain internal to the class 702 703 and the run() method should be used instead. 703 704 704 705 @param q: q-value [float] 705 706 @return: I(q) [float] 706 707 """ 707 708 if self.hasPr == False:708 709 if not self.hasPr: 709 710 self.getPr() 710 711 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 713 714 # of points chosen for the simulation is int(density*volume). 714 715 # Propagation of error gives: … … 716 717 # where N is stored in self.npts 717 718 718 norm = 719 norm = 1.0e8/self.params['lores_density']*self.params['scale'] 719 720 #return norm*pointsmodelpy.get_lores_i(self.lores_model, q) 720 721 return norm*pointsmodelpy.get_complex_i(self.complex_model, q)\ 721 722 + self.params['background'] 722 723 723 724 def getError(self, q): 724 725 """ … … 727 728 @return: I(q) [float] 728 729 """ 729 730 if self.hasPr == False:730 731 if not self.hasPr: 731 732 self.getPr() 732 733 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 735 736 # of points chosen for the simulation is int(density*volume). 736 737 # Propagation of error gives: … … 738 739 # where N is stored in self.npts 739 740 740 norm = 741 norm = 1.0e8/self.params['lores_density']*self.params['scale'] 741 742 #return norm*pointsmodelpy.get_lores_i(self.lores_model, q) 742 743 return norm*pointsmodelpy.get_complex_i_error(self.complex_model, q)\ 743 744 + self.params['background'] 744 745 745 746 def getIqError(self, q): 746 747 """ 747 748 Return the simulated value along with its estimated 748 749 error for a given q-value 749 750 750 751 Propagation of errors is used to evaluate the 751 752 uncertainty. 752 753 753 754 @param q: q-value [float] 754 755 @return: mean, error [float, float] … … 765 766 Return the simulated value along with its estimated 766 767 error for a given q-value 767 768 768 769 Propagation of errors is used to evaluate the 769 770 uncertainty. 770 771 771 772 @param qx: qx-value [float] 772 773 @param qy: qy-value [float] … … 774 775 """ 775 776 self._create_modelObject() 776 777 norm = 777 778 norm = 1.0e8/self.params['lores_density']*self.params['scale'] 778 779 val = norm*pointsmodelpy.get_complex_iq_2D(self.complex_model, self.points, qx, qy)\ 779 780 + self.params['background'] 780 781 781 782 # Simulation error (statistical) 782 norm = 783 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 784 785 err = norm*pointsmodelpy.get_complex_iq_2D_err(self.complex_model, self.points, qx, qy) 785 786 # Error on V/N 786 787 simerr = 2*val/self.npts 787 788 788 789 # The error used for the position is over-simplified. 789 790 # The actual error was empirically found to be about 790 791 # an order of magnitude larger. 791 792 return val, 10.0*err+simerr 792 -
src/sas/sasgui/guiframe/CategoryInstaller.py
r235f514 r65f3930 19 19 logger = logging.getLogger(__name__) 20 20 21 class CategoryInstaller :21 class CategoryInstaller(object): 22 22 """ 23 23 Class for making sure all category stuff is installed … … 34 34 returns the dir where installed_models.txt should be 35 35 """ 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() 46 38 47 39 @staticmethod … … 85 77 by_model_dict = defaultdict(list) 86 78 model_enabled_dict = defaultdict(bool) 87 79 88 80 for category in master_category_dict: 89 81 for (model, enabled) in master_category_dict[category]: … … 96 88 def _regenerate_master_dict(by_model_dict, model_enabled_dict): 97 89 """ 98 regenerates master_category_dict from by_model_dict 90 regenerates master_category_dict from by_model_dict 99 91 and model_enabled_dict 100 92 returns the master category dictionary … … 128 120 which are user supplied. 129 121 """ 130 _model_dict = { 122 _model_dict = {model.name: model for model in model_list} 131 123 _model_list = _model_dict.keys() 132 124 … … 150 142 model_name, enabled = master_category_dict[cat][ind] 151 143 if model_name not in _model_list: 152 del_name = True 144 del_name = True 153 145 try: 154 146 by_model_dict.pop(model_name) 155 147 model_enabled_dict.pop(model_name) 156 except :148 except Exception: 157 149 logger.error("CategoryInstaller: %s", sys.exc_value) 158 150 else: … … 160 152 if del_name or (len(add_list) > 0): 161 153 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): 164 158 by_model_dict[model].append('Uncategorized') 165 159 else: -
src/sas/sasgui/perspectives/calculator/model_editor.py
r23359ccb r23359ccb 31 31 import re 32 32 import logging 33 import datetime 34 33 35 from wx.py.editwindow import EditWindow 36 34 37 from sas.sasgui.guiframe.documentation_window import DocumentationWindow 38 35 39 from .pyconsole import show_model_output, check_model 36 40 37 41 logger = logging.getLogger(__name__) 38 39 42 40 43 if sys.platform.count("win32") > 0: … … 78 81 a Modal Dialog. 79 82 80 :TODO the buil din compiler currently balks at when it tries to import83 :TODO the built in compiler currently balks at when it tries to import 81 84 a model whose name contains spaces or symbols (such as + ... underscore 82 85 should be fine). Have fixed so the editor cannot save such a file name … … 335 338 list_fnames = os.listdir(self.plugin_dir) 336 339 # 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] 338 341 list_fnames.append(m_list) 339 342 if t_fname in list_fnames and title != mname: … … 533 536 desc_line = "\nmodel_info.description = '{}'".format(description) 534 537 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, 536 539 model2=model2_name, operator=self._operator, desc_line=desc_line) 537 540 with open(self.fname, 'w') as out_f: … … 789 792 exec "float(math.%s)" % item 790 793 self.math_combo.Append(str(item)) 791 except :794 except Exception: 792 795 self.math_combo.Append(str(item) + "()") 793 796 self.math_combo.Bind(wx.EVT_COMBOBOX, self._on_math_select) … … 914 917 msg = "Name exists already." 915 918 916 # Prepare the messagebox919 # 917 920 if self.base is not None and not msg: 918 921 self.base.update_custom_combo() 919 # Passed exception in import test as it will fail for sasmodels.sasview_model class920 # Should add similar test for new style?921 Model = None922 try:923 exec "from %s import Model" % name924 except:925 logger.error(sys.exc_value)926 922 927 923 # Prepare the messagebox … … 956 952 :param func_str: content of func; Strings 957 953 """ 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 982 964 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') 1027 988 for func_line in func_str.split('\n'): 1028 989 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 1032 999 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') 1040 1006 1041 1007 out_f.close() 1042 1008 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)] 1065 1023 1066 1024 def set_function_helper(self, line): … … 1096 1054 running "file:///...." 1097 1055 1098 :param evt: Triggers on clicking the help button1099 """1056 :param evt: Triggers on clicking the help button 1057 """ 1100 1058 1101 1059 _TreeLocation = "user/sasgui/perspectives/fitting/fitting_help.html" … … 1140 1098 ## Templates for plugin models 1141 1099 1142 CUSTOM_TEMPLATE = """ 1100 CUSTOM_TEMPLATE = '''\ 1101 r""" 1102 Definition 1103 ---------- 1104 1105 Calculates %(name)s. 1106 1107 %(description)s 1108 1109 References 1110 ---------- 1111 1112 Authorship 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 1143 1120 from 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 """ 1121 from numpy import inf 1122 1123 name = "%(name)s" 1124 title = "%(title)s" 1125 description = """%(description)s""" 1126 1127 ''' 1128 1129 CUSTOM_TEMPLATE_PD = '''\ 1130 def 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 1137 def 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 1145 def 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 1212 1154 SUM_TEMPLATE = """ 1213 1155 from sasmodels.core import load_model_info … … 1219 1161 """ 1220 1162 if __name__ == "__main__": 1221 # app = wx.PySimpleApp()1222 1163 main_app = wx.App() 1223 1164 main_frame = TextDialog(id=1, model_list=["SphereModel", "CylinderModel"], 1224 plugin_dir='../fitting/plugin_models')1165 plugin_dir='../fitting/plugin_models') 1225 1166 main_frame.ShowModal() 1226 1167 main_app.MainLoop() 1227 1228 #if __name__ == "__main__":1229 # from sas.sasgui.perspectives.fitting import models1230 # 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 6 6 import sys 7 7 import os 8 import wx9 import numpy as np10 8 import time 11 9 import copy … … 14 12 import logging 15 13 import traceback 16 17 14 from collections import defaultdict 15 16 import numpy as np 17 18 import wx 18 19 from wx.lib.scrolledpanel import ScrolledPanel 19 20 21 from sasmodels.sasview_model import MultiplicationModel 20 22 from sasmodels.weights import MODELS as POLYDISPERSITY_MODELS 23 from sasmodels.weights import GaussianDispersion 24 25 from sas.sascalc.dataloader.data_info import Detector 26 from sas.sascalc.dataloader.data_info import Source 27 from sas.sascalc.fit.pagestate import PageState 28 from sas.sascalc.fit.models import PLUGIN_NAME_BASE 21 29 22 30 from sas.sasgui.guiframe.panel_base import PanelBase … … 30 38 from sas.sasgui.guiframe.dataFitting import check_data_validity 31 39 from sas.sasgui.guiframe.gui_style import GUIFRAME_ID 32 from sas.sascalc.dataloader.data_info import Detector33 from sas.sascalc.dataloader.data_info import Source34 from sas.sasgui.perspectives.fitting.pagestate import PageState35 40 from sas.sasgui.guiframe.CategoryInstaller import CategoryInstaller 36 41 from sas.sasgui.guiframe.documentation_window import DocumentationWindow 42 43 from .report_dialog import ReportDialog 44 from .utils import get_weight 37 45 38 46 logger = logging.getLogger(__name__) … … 153 161 self.disp_cb_dict = {} 154 162 155 # self.state = PageState( parent=parent)163 # self.state = PageState() 156 164 # dictionary containing list of models 157 165 self.model_list_box = {} … … 200 208 self.fitrange = True 201 209 # 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) 204 211 # flag to determine if state has change 205 212 self.state_change = False … … 282 289 """ 283 290 x = np.linspace(start=self.qmin_x, stop=self.qmax_x, 284 291 num=self.npts_x, endpoint=True) 285 292 self.data = Data1D(x=x) 286 293 self.data.xaxis('\\rm{Q}', "A^{-1}") … … 308 315 309 316 x = np.logspace(start=qmin, stop=qmax, 310 317 num=self.npts_x, endpoint=True, base=10.0) 311 318 self.data = Data1D(x=x) 312 319 self.data.xaxis('\\rm{Q}', "A^{-1}") … … 497 504 self.state.manager = manager 498 505 499 def populate_box(self, model_ dict):506 def populate_box(self, model_list_box): 500 507 """ 501 508 Store list of model 502 509 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 508 513 self.initialize_combox() 509 514 510 def set_model_dictionary(self, model_dict ):515 def set_model_dictionary(self, model_dictionary): 511 516 """ 512 517 Store a dictionary linking model name -> model object 513 518 514 :param model_dict : dictionary containing list ofmodels515 """ 516 self.model_dict = model_dict519 :param model_dictionary: dictionary containing all models 520 """ 521 self.model_dictionary = model_dictionary 517 522 518 523 def initialize_combox(self): … … 520 525 put default value in the combo box 521 526 """ 522 if self.model_list_box is not None and len(self.model_list_box) > 0:527 if self.model_list_box: 523 528 self._populate_box(self.structurebox, 524 529 self.model_list_box["Structure Factors"]) … … 619 624 # Get plot image from plotpanel 620 625 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 623 672 624 673 def on_save(self, event): … … 842 891 self.state.disable_disp = self.disable_disp.GetValue() 843 892 844 self.state.smearer = copy.deepcopy(self.current_smearer)845 893 if hasattr(self, "enable_smearer"): 846 894 self.state.enable_smearer = \ … … 858 906 if len(self._disp_obj_dict) > 0: 859 907 for k, v in self._disp_obj_dict.iteritems(): 860 self.state. _disp_obj_dict[k] = v.type908 self.state.disp_obj_dict[k] = v.type 861 909 862 910 self.state.values = copy.deepcopy(self.values) … … 876 924 self.state.str_parameters) 877 925 self._copy_parameters_state(self.orientation_params, 878 926 self.state.orientation_params) 879 927 self._copy_parameters_state(self.orientation_params_disp, 880 928 self.state.orientation_params_disp) … … 907 955 self.state.disable_disp = self.disable_disp.GetValue() 908 956 909 self.state.smearer = copy.deepcopy(self.current_smearer)910 957 if hasattr(self, "enable_smearer"): 911 958 self.state.enable_smearer = \ … … 931 978 try: 932 979 self.state.disp_cb_dict[k] = v.GetValue() 933 except :980 except Exception: 934 981 self.state.disp_cb_dict[k] = None 935 982 if len(self._disp_obj_dict) > 0: 936 983 for k, v in self._disp_obj_dict.iteritems(): 937 self.state. _disp_obj_dict[k] = v.type984 self.state.disp_obj_dict[k] = v.type 938 985 939 986 self.state.values = copy.deepcopy(self.values) … … 977 1024 # to support older version 978 1025 category_pos = int(state.categorycombobox) 979 except :1026 except Exception: 980 1027 category_pos = 0 981 1028 for ind_cat in range(self.categorybox.GetCount()): … … 989 1036 # to support older version 990 1037 formfactor_pos = int(state.formfactorcombobox) 991 except :1038 except Exception: 992 1039 formfactor_pos = 0 993 1040 for ind_form in range(self.formfactorbox.GetCount()): … … 1002 1049 # to support older version 1003 1050 structfactor_pos = int(state.structurecombobox) 1004 except :1051 except Exception: 1005 1052 structfactor_pos = 0 1006 1053 for ind_struct in range(self.structurebox.GetCount()): … … 1169 1216 self.categorybox.Select(category_pos) 1170 1217 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): 1174 1220 state.formfactorcombobox = \ 1175 1221 PLUGIN_NAME_BASE + state.formfactorcombobox 1176 1222 formfactor_pos = 0 1177 1223 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): 1180 1226 formfactor_pos = int(ind_form) 1181 1227 break … … 1187 1233 state.structurecombobox = unicode(state.structurecombobox) 1188 1234 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): 1191 1237 structfactor_pos = int(ind_struct) 1192 1238 break … … 1239 1285 self.dI_sqrdata.SetValue(state.dI_sqrdata) 1240 1286 self.dI_idata.SetValue(state.dI_idata) 1241 except :1287 except Exception: 1242 1288 # to support older state file formats 1243 1289 self.dI_noweight.SetValue(False) … … 1295 1341 self.weights = copy.deepcopy(state.weights) 1296 1342 1297 for key, disp_type in state. _disp_obj_dict.iteritems():1343 for key, disp_type in state.disp_obj_dict.iteritems(): 1298 1344 # disp_model = disp 1299 1345 disp_model = POLYDISPERSITY_MODELS[disp_type]() … … 1529 1575 try: 1530 1576 self.npts_x = float(self.Npts_total.GetValue()) 1531 except :1577 except Exception: 1532 1578 flag = False 1533 1579 return flag … … 1570 1616 return 1571 1617 1572 for j in range(len(listtorestore)):1618 for item_page in listtorestore: 1573 1619 for param in statelist: 1574 if param[1] == listtorestore[j][1]: 1575 item_page = listtorestore[j] 1620 if param[1] == item_page[1]: 1576 1621 item_page_info = param 1577 1622 if (item_page_info[1] == "theta" or item_page_info[1] == … … 1619 1664 listtorestore = copy.deepcopy(statelist) 1620 1665 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): 1624 1667 # change the state of the check box for simple parameters 1625 1626 1668 if item_page[0] is not None: 1627 1669 item_page[0].SetValue(format_number(item_page_info[0], True)) … … 1711 1753 temp_smear = self.current_smearer 1712 1754 # compute weight for the current data 1713 from sas.sasgui.perspectives.fitting.utils import get_weight1714 1755 flag = self.get_weight_flag() 1715 1756 weight = get_weight(data=self.data, is2d=self._is_2D(), flag=flag) … … 1737 1778 1738 1779 from sas.sasgui.plottools import Data1D as pf_data1d 1739 # from sas.sasgui.perspectives.theory.profile_dialog import SLDPanel1740 1780 from sas.sasgui.guiframe.local_perspectives.plotting.profile_dialog \ 1741 1781 import SLDPanel … … 1798 1838 if mod_cat == CUSTOM_MODEL: 1799 1839 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]) 1801 1841 else: 1802 1842 cat_dic = self.master_category_dict[mod_cat] 1803 for (model, enabled)in cat_dic:1843 for model, enabled in cat_dic: 1804 1844 if enabled: 1805 m_list.append(self.model_dict [model])1845 m_list.append(self.model_dictionary[model]) 1806 1846 except Exception: 1807 1847 msg = traceback.format_exc() … … 1875 1915 wx.PostEvent(self.parent, StatusEvent(status=msg)) 1876 1916 return 1877 except :1917 except Exception: 1878 1918 tcrtl.SetBackgroundColour("pink") 1879 1919 msg = "Model Error: wrong value entered: %s" % sys.exc_info()[1] … … 1932 1972 wx.PostEvent(self._manager.parent, StatusEvent(status=msg)) 1933 1973 return 1934 except :1974 except Exception: 1935 1975 tcrtl.SetBackgroundColour("pink") 1936 1976 msg = "Model Error: wrong value entered: %s" % sys.exc_info()[1] … … 2032 2072 2033 2073 if struct_factor is not None: 2034 from sasmodels.sasview_model import MultiplicationModel2035 2074 self.model = MultiplicationModel(form_factor(self.multi_factor), 2036 2075 struct_factor()) … … 2110 2149 # q value from qx and qy 2111 2150 radius = np.sqrt(data.qx_data * data.qx_data + 2112 2151 data.qy_data * data.qy_data) 2113 2152 # get unmasked index 2114 2153 index_data = (float(self.qmin.GetValue()) <= radius) & \ … … 2339 2378 put gaussian dispersity into current model 2340 2379 """ 2341 if len(self.param_toFit) > 0:2380 if self.param_toFit: 2342 2381 for item in self.fittable_param: 2343 2382 if item in self.param_toFit: … … 2354 2393 self.weights = {} 2355 2394 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: 2360 2396 self.sizer4_4.Clear(True) 2361 self.Layout() 2362 return 2363 if (len(self.disp_cb_dict) > 0): 2397 else: 2364 2398 for p in self.disp_cb_dict: 2365 2399 # The parameter was un-selected. … … 2434 2468 self._disp_obj_dict[name1] = disp_model 2435 2469 self.model.set_dispersion(param_name, disp_model) 2436 self.state. _disp_obj_dict[name1] = disp_model.type2470 self.state.disp_obj_dict[name1] = disp_model.type 2437 2471 2438 2472 value1 = str(format_number(self.model.getParam(name1), True)) … … 2549 2583 self._disp_obj_dict[name] = disp 2550 2584 self.model.set_dispersion(name.split('.')[0], disp) 2551 self.state. _disp_obj_dict[name] = disp.type2585 self.state.disp_obj_dict[name] = disp.type 2552 2586 self.values[name] = values 2553 2587 self.weights[name] = weights … … 2907 2941 # go through the parameters 2908 2942 strings = self._get_copy_helper(self.parameters, 2909 self.orientation_params)2943 self.orientation_params) 2910 2944 content += strings 2911 2945 2912 2946 # go through the fittables 2913 2947 strings = self._get_copy_helper(self.fittable_param, 2914 self.orientation_params_disp)2948 self.orientation_params_disp) 2915 2949 content += strings 2916 2950 2917 2951 # go through the fixed params 2918 2952 strings = self._get_copy_helper(self.fixed_param, 2919 self.orientation_params_disp)2953 self.orientation_params_disp) 2920 2954 content += strings 2921 2955 2922 2956 # go through the str params 2923 2957 strings = self._get_copy_helper(self.str_parameters, 2924 self.orientation_params)2958 self.orientation_params) 2925 2959 content += strings 2926 2960 return content … … 2935 2969 the names of parameters that have been fitted 2936 2970 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 2938 2972 self.parameters 2939 2973 :returns: fitted_par_names - A list of the names of parameters that have … … 3012 3046 # Only print errors for fitted parameters 3013 3047 content += param[4].GetValue() 3014 content += tab 3048 content += tab 3015 3049 3016 3050 return content … … 3032 3066 # Do nothing if self.parameters doesn't exist 3033 3067 return False 3034 3035 content = '\\begin{table}'3036 content += '\\begin{tabular}[h]'3068 3069 content = r'\begin{table}' 3070 content += r'\begin{tabular}[h]' 3037 3071 3038 3072 crlf = chr(13) + chr(10) … … 3044 3078 for param in all_params: 3045 3079 content += 'l|l|' 3046 content += '}\hline'3080 content += r'}\hline' 3047 3081 content += crlf 3048 3082 … … 3050 3084 for index, param in enumerate(all_params): 3051 3085 name = param[1] # Parameter name 3052 content += name.replace('_', '\_') # Escape underscores3086 content += name.replace('_', r'\_') # Escape underscores 3053 3087 if name in fitted_param_names: 3054 3088 # Only print errors for fitted parameters 3055 3089 content += ' & ' 3056 content += name.replace('_', '\_') +"\_err"3090 content += name.replace('_', r'\_') + r"\_err" 3057 3091 if index < len(all_params) - 1: 3058 3092 content += ' & ' 3059 3093 3060 content += '\\\\ \\hline'3094 content += r'\\ \hline' 3061 3095 content += crlf 3062 3096 … … 3077 3111 if index < len(all_params) - 1: 3078 3112 content += ' & ' 3079 3080 content += '\\\\ \\hline'3113 3114 content += r'\\ \hline' 3081 3115 content += crlf 3082 content += '\\end{tabular}'3083 content += '\\end{table}'3116 content += r'\end{tabular}' 3117 content += r'\end{table}' 3084 3118 3085 3119 return content … … 3338 3372 if name.endswith('.npts'): 3339 3373 pd = int(pd) 3340 except :3374 except Exception: 3341 3375 # continue 3342 3376 if not pd and pd != '': … … 3424 3458 self._disp_obj_dict[name] = disp_model 3425 3459 self.model.set_dispersion(param_name, disp_model) 3426 self.state. _disp_obj_dict[name] = disp_model.type3460 self.state.disp_obj_dict[name] = disp_model.type 3427 3461 # TODO: It's not an array, why update values and weights? 3428 3462 self.model._persistency_dict[param_name] = \ … … 3524 3558 self.model_box.Clear() 3525 3559 3526 if category == 'Plugin Models':3560 if category == CUSTOM_MODEL: 3527 3561 for model in self.model_list_box[category]: 3528 3562 str_m = str(model).split(".")[0] … … 3530 3564 3531 3565 else: 3532 for (model, enabled)in sorted(self.master_category_dict[category],3533 3534 if (enabled):3566 for model, enabled in sorted(self.master_category_dict[category], 3567 key=lambda name: name[0]): 3568 if enabled: 3535 3569 self.model_box.Append(model) 3536 3570 … … 3773 3807 self.Bind(wx.EVT_SET_FOCUS, self._on_set_focus) 3774 3808 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) 3776 3810 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) 3778 3812 if not ON_MAC: 3779 3813 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) 3781 3815 3782 3816 def _on_set_focus(self, event): -
src/sas/sasgui/perspectives/fitting/batchfitpage.py
r7432acb r50fcb09 5 5 import wx.lib.newevent 6 6 import math 7 8 from sas.sascalc.fit.qsmearing import smear_selection 9 7 10 from sas.sasgui.guiframe.events import StatusEvent 8 11 from sas.sasgui.guiframe.events import NewPlotEvent 12 from sas.sasgui.perspectives.fitting.basepage import PageInfoEvent 13 from sas.sasgui.perspectives.fitting.fitpage import FitPage 14 from sas.sasgui.perspectives.fitting.fitpage import check_data_validity 9 15 10 16 (Chi2UpdateEvent, EVT_CHI2_UPDATE) = wx.lib.newevent.NewEvent() … … 13 19 SMEAR_SIZE_L = 0.00 14 20 SMEAR_SIZE_H = 0.00 15 16 from sas.sasgui.perspectives.fitting.basepage import PageInfoEvent17 from sas.sascalc.data_util.qsmearing import smear_selection18 from sas.sasgui.perspectives.fitting.fitpage import FitPage19 from sas.sasgui.perspectives.fitting.fitpage import check_data_validity20 21 21 22 class BatchFitPage(FitPage): … … 76 77 # """ 77 78 # is_2Ddata = False 78 # 79 # 79 80 # # Check if data is 2D 80 81 # if self.data.__class__.__name__ == "Data2D" or \ 81 82 # self.enable2D: 82 83 # is_2Ddata = True 83 # 84 # title = "Fitting" 84 # 85 # title = "Fitting" 85 86 # self._get_smear_info() 86 # 87 # 87 88 # #Sizers 88 89 # 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) 90 91 # self.sizer_set_smearer = wx.BoxSizer(wx.VERTICAL) 91 92 # #sizer_smearer = wx.BoxSizer(wx.HORIZONTAL) … … 93 94 # self.sizer_set_masking = wx.BoxSizer(wx.HORIZONTAL) 94 95 # sizer_chi2 = wx.BoxSizer(wx.VERTICAL) 95 # 96 # 96 97 # sizer_fit = wx.GridSizer(2, 4, 2, 6) 97 98 # #Fit button … … 100 101 # self.btFit.Bind(wx.EVT_BUTTON, self._onFit, id= self.btFit.GetId()) 101 102 # self.btFit.SetToolTipString("Start fitting.") 102 # 103 # 103 104 # # Update and Draw button 104 105 # self.draw_button = wx.Button(self, self._ids.next(), 'Compute', size=(88, 24)) 105 106 # self.draw_button.Bind(wx.EVT_BUTTON, \ 106 107 # self._onDraw,id=self.draw_button.GetId()) 107 # self.draw_button.SetToolTipString("Compute and Draw.") 108 # self.draw_button.SetToolTipString("Compute and Draw.") 108 109 # sizer_fit.Add(self.draw_button, 0, 0) 109 # sizer_fit.Add(self.btFit, 0, 0) 110 # sizer_fit.Add(self.btFit, 0, 0) 110 111 # sizer_chi2.Add((-1, 5)) 111 112 # # get smear_selection … … 114 115 # #2D data? default 115 116 # is_2Ddata = False 116 # 117 # 117 118 # #check if it is 2D data 118 119 # if self.data.__class__.__name__ == "Data2D" or \ 119 120 # self.enable2D: 120 121 # is_2Ddata = True 121 # 122 # 122 123 # self.sizer5.Clear(True) 123 # 124 # 124 125 # self.qmin = ModelTextCtrl(self, wx.ID_ANY, size=(_BOX_WIDTH, 20), 125 # style=wx.TE_PROCESS_ENTER, 126 # style=wx.TE_PROCESS_ENTER, 126 127 # text_enter_callback = self._onQrangeEnter) 127 128 # self.qmin.SetValue(str(self.qmin_x)) 128 129 # self.qmin.SetToolTipString("Minimun value of Q in linear scale.") 129 # 130 # 130 131 # self.qmax = ModelTextCtrl(self, wx.ID_ANY, size=(_BOX_WIDTH, 20), 131 # style=wx.TE_PROCESS_ENTER, 132 # style=wx.TE_PROCESS_ENTER, 132 133 # text_enter_callback=self._onQrangeEnter) 133 134 # self.qmax.SetValue(str(self.qmax_x)) 134 135 # self.qmax.SetToolTipString("Maximum value of Q in linear scale.") 135 # 136 # 136 137 # id = self._ids.next() 137 138 # self.reset_qrange =wx.Button(self, id, 'Reset', size=(77, 20)) 138 # 139 # 139 140 # self.reset_qrange.Bind(wx.EVT_BUTTON, self.on_reset_clicked, id=id) 140 141 # self.reset_qrange.SetToolTipString(\ 141 142 # "Reset Q range to the default values") 142 # 143 # 143 144 # sizer_horizontal = wx.BoxSizer(wx.HORIZONTAL) 144 145 # sizer = wx.GridSizer(2, 4, 2, 6) 145 # 146 # 146 147 # 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, 148 149 # self._onMask,id=self.btEditMask.GetId()) 149 150 # self.btEditMask.SetToolTipString("Edit Mask.") 150 151 # self.EditMask_title = wx.StaticText(self, wx.ID_ANY, ' Masking(2D)') 151 # 152 # 152 153 # sizer.Add(wx.StaticText(self, wx.ID_ANY, 'Q range')) 153 154 # sizer.Add(wx.StaticText(self, wx.ID_ANY, ' Min[1/A]')) 154 155 # sizer.Add(wx.StaticText(self, wx.ID_ANY, ' Max[1/A]')) 155 156 # sizer.Add(self.EditMask_title) 156 # 157 # sizer.Add(self.reset_qrange) 157 # 158 # sizer.Add(self.reset_qrange) 158 159 # sizer.Add(self.qmin) 159 160 # sizer.Add(self.qmax) 160 # 161 # 161 162 # sizer.Add(self.btEditMask) 162 # boxsizer_range.Add(sizer_chi2) 163 # boxsizer_range.Add(sizer_chi2) 163 164 # boxsizer_range.Add((10, 10)) 164 165 # boxsizer_range.Add(sizer) 165 # 166 # 166 167 # boxsizer_range.Add((10, 15)) 167 168 # boxsizer_range.Add(sizer_fit) 168 169 # if is_2Ddata: 169 # self.btEditMask.Enable() 170 # self.EditMask_title.Enable() 170 # self.btEditMask.Enable() 171 # self.EditMask_title.Enable() 171 172 # else: 172 # self.btEditMask.Disable() 173 # self.btEditMask.Disable() 173 174 # self.EditMask_title.Disable() 174 # 175 # 175 176 # ## save state 176 177 # #self.save_current_state() 177 # 178 # 178 179 # self.sizer5.Add(boxsizer_range, 0, wx.EXPAND | wx.ALL, 10) 179 180 # self.sizer5.Layout() 180 # 181 # def _on_select_model(self, event=None): 181 # 182 # def _on_select_model(self, event=None): 182 183 # """ 183 184 # 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) 189 190 # if self.model is None: 190 191 # self._set_bookmark_flag(False) … … 199 200 # self.state.structurecombobox = self.structurebox.GetCurrentSelection() 200 201 # self.state.formfactorcombobox = self.formfactorbox.GetCurrentSelection() 201 # 202 # 202 203 # if self.model is not None: 203 204 # self._set_copy_flag(True) … … 206 207 # self._set_bookmark_flag(False) 207 208 # self._keep.Enable(False) 208 # 209 # 209 210 # temp_smear = None 210 211 # ## event to post model to fit to fitting plugins 211 212 # (ModelEventbox, _) = wx.lib.newevent.NewEvent() 212 # 213 # ## set smearing value whether or not 213 # 214 # ## set smearing value whether or not 214 215 # # 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, 217 218 # qmin=float(self.qmin_x), 218 219 # uid=self.uid, 219 # qmax=float(self.qmax_x)) 220 # 220 # qmax=float(self.qmax_x)) 221 # 221 222 # self._manager._on_model_panel(evt=evt) 222 223 # self.mbox_description.SetLabel("Model [%s]" % str(self.model.name)) 223 224 # self.state.model = self.model.clone() 224 225 # self.state.model.name = self.model.name 225 # 226 # 226 # 227 # 227 228 # if event is not None: 228 229 # ## post state to fit panel 229 230 # new_event = PageInfoEvent(page = self) 230 # wx.PostEvent(self.parent, new_event) 231 # wx.PostEvent(self.parent, new_event) 231 232 # #update list of plugins if new plugin is available 232 233 # if self.plugin_rbutton.GetValue(): … … 243 244 # self._draw_model() 244 245 # self.SetupScrolling() 245 # self.Show(True) 246 # 246 # self.Show(True) 247 # 247 248 # def _update_paramv_on_fit(self): 248 249 # """ … … 253 254 # self.fitrange = True 254 255 # is_modified = False 255 # 256 # 256 257 # if self.model is not None: 257 258 # ##Check the values … … 259 260 # self._check_value_enter( self.fixed_param) 260 261 # 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 263 264 # # 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 265 266 # # set the is_modified flag to True 266 267 # self.fitrange = self._validate_qrange(self.qmin, self.qmax) … … 273 274 # self.qmax_x = tempmax 274 275 # if tempmax == tempmin: 275 # flag = False 276 # flag = False 276 277 # #temp_smearer = None 277 278 # if self._is_2D(): 278 # # only 2D case set mask 279 # # only 2D case set mask 279 280 # flag = self._validate_Npts() 280 281 # if not flag: 281 282 # return flag 282 283 # else: flag = False 283 # else: 284 # else: 284 285 # 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. 287 288 # if not self.fitrange: 288 289 # #self.btFit.Disable() … … 293 294 # if self._is_2D() and self.data is not None: 294 295 # self.btEditMask.Enable(True) 295 # 296 # 296 297 # if not flag: 297 298 # msg = "Cannot Plot or Fit :Must select a " 298 299 # msg += " model or Fitting range is not valid!!! " 299 300 # wx.PostEvent(self.parent.parent, StatusEvent(status=msg)) 300 # 301 # 301 302 # self.save_current_state() 302 # 303 # return flag 303 # 304 # return flag 304 305 # def save_current_state(self): 305 306 # """ 306 307 # Currently no save option implemented for batch page 307 308 # """ 308 # pass 309 # pass 309 310 # def save_current_state_fit(self): 310 311 # """ … … 314 315 # def set_data(self, data): 315 316 # """ 316 # reset the current data 317 # reset the current data 317 318 # """ 318 319 # #id = None … … 340 341 # self._set_save_flag(False) 341 342 # self._set_preview_flag(True) 342 # 343 # 343 344 # self.formfactorbox.Enable() 344 345 # self.structurebox.Enable() … … 346 347 # #set maximum range for x in linear scale 347 348 # if not hasattr(self.data,"data"): #Display only for 1D data fit 348 # # Minimum value of data 349 # # Minimum value of data 349 350 # data_min = min(self.data.x) 350 # # Maximum value of data 351 # # Maximum value of data 351 352 # data_max = max(self.data.x) 352 # self.btEditMask.Disable() 353 # self.btEditMask.Disable() 353 354 # self.EditMask_title.Disable() 354 355 # else: 355 # 356 # ## Minimum value of data 356 # 357 # ## Minimum value of data 357 358 # 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)) 359 360 # y = max(math.fabs(self.data.ymin), math.fabs(self.data.ymax)) 360 # ## Maximum value of data 361 # ## Maximum value of data 361 362 # 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 # 365 366 # self.dataSource.SetValue(data_name) 366 367 # self.qmin_x = data_min … … 375 376 # self.state.qmin = self.qmin_x 376 377 # self.state.qmax = self.qmax_x 377 # 378 # 378 379 # #update model plot with new data information 379 380 # if flag: … … 385 386 # self.enable2D = False 386 387 # self.model_view.SetLabel("1D Mode") 387 # 388 # 388 389 # self.model_view.Disable() 389 # 390 # wx.PostEvent(self._manager.parent, 390 # 391 # wx.PostEvent(self._manager.parent, 391 392 # NewPlotEvent(group_id=group_id, 392 393 # action="delete")) 393 394 # #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, 395 396 # title=str(self.data.title))) 396 397 # self._manager.store_data(uid=self.uid, data=data, -
src/sas/sasgui/perspectives/fitting/fit_thread.py
r959eb01 rba8d326 29 29 worktime=0.03, 30 30 reset_flag=False): 31 CalcThread.__init__(self, 32 completefn, 33 updatefn, 34 yieldtime, 35 worktime) 31 CalcThread.__init__(self, completefn, updatefn, yieldtime, worktime) 36 32 self.handler = handler 37 33 self.fitter = fn … … 93 89 # Real code should not print, but this is an example... 94 90 #print "keyboard exception" 95 #Stop on exception during fitting. Todo: need to put 91 #Stop on exception during fitting. Todo: need to put 96 92 #some mssg and reset progress bar. 97 93 … … 100 96 if self.handler is not None: 101 97 self.handler.stop(msg=msg) 102 except: 98 except: # catch-all: show every exception which stops the thread 103 99 import traceback 104 100 if self.handler is not None: -
src/sas/sasgui/perspectives/fitting/fitpage.py
r79e6a33 r79e6a33 14 14 from sasmodels.weights import MODELS as POLYDISPERSITY_MODELS 15 15 16 from sas.sascalc.fit.qsmearing import smear_selection 17 16 18 from sas.sasgui.guiframe.events import StatusEvent, NewPlotEvent, \ 17 19 PlotQrangeEvent … … 23 25 from sas.sasgui.perspectives.fitting.basepage import PageInfoEvent as \ 24 26 PageInfoEvent 25 from sas.sascalc.data_util.qsmearing import smear_selection26 27 from .basepage import ModelTextCtrl 27 28 … … 1142 1143 self.model.name = "M" + str(self.index_model) 1143 1144 1144 def _on_select_model(self, event=None ):1145 def _on_select_model(self, event=None, keep_pars=False): 1145 1146 """ 1146 1147 call back for model selection 1147 1148 """ 1148 1149 self.Show(False) 1149 copy_flag = False1150 is_poly_enabled = None1151 1150 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 1158 1165 try: 1159 1166 self._on_select_model_helper() … … 1177 1184 try: 1178 1185 self.set_dispers_sizer() 1179 except :1186 except Exception: 1180 1187 pass 1181 1188 self.state.enable_disp = self.enable_disp.GetValue() … … 1238 1245 self.state.model.name = self.model.name 1239 1246 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 1240 1259 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) 1241 1275 # post state to fit panel 1242 1276 new_event = PageInfoEvent(page=self) 1243 1277 wx.PostEvent(self.parent, new_event) 1244 # update list of plugins if new plugin is available1245 mod_cat = self.categorybox.GetStringSelection()1246 if mod_cat == CUSTOM_MODEL:1247 temp_id = self.model.id1248 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 break1253 if temp:1254 self.model_list_box = temp1255 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/button1261 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 values1269 if copy_flag:1270 self.get_paste_params(copy_flag)1271 1278 wx.CallAfter(self._onDraw, None) 1272 1279 … … 1719 1726 and not self.temp_multi_functional: 1720 1727 return None 1728 print("_set_fun_box_list", self.model.name) 1721 1729 # Get the func name list 1722 1730 list = self.model.fun_list … … 1726 1734 ind = 0 1727 1735 while(ind < len(list)): 1728 for key, val in list.ite ritems():1729 if (val == ind):1736 for key, val in list.items(): 1737 if val == ind: 1730 1738 fun_box.Append(key, val) 1731 1739 break -
src/sas/sasgui/perspectives/fitting/fitpanel.py
rc9ecd1b rc9ecd1b 9 9 from wx.aui import AuiNotebook as nb 10 10 11 from sas.sascalc.fit.models import ModelManager 12 11 13 from sas.sasgui.guiframe.panel_base import PanelBase 12 14 from sas.sasgui.guiframe.events import PanelOnFocusEvent, StatusEvent 13 15 from 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 18 from . import basepage 19 from .fitpage import FitPage 20 from .simfitpage import SimultaneousFitPage 21 from .batchfitpage import BatchFitPage 22 from .fitting_widgets import BatchDataDialog 23 18 24 _BOX_WIDTH = 80 19 25 … … 46 52 self.event_owner = None 47 53 # dictionary of miodel {model class name, model class} 48 self.menu_mng = models.ModelManager()54 self.menu_mng = ModelManager() 49 55 self.model_list_box = self.menu_mng.get_model_list() 50 56 # pageClosedEvent = nb.EVT_FLATNOTEBOOK_PAGE_CLOSING … … 114 120 """ 115 121 temp = self.menu_mng.update() 116 if len(temp):122 if temp: 117 123 self.model_list_box = temp 118 124 return temp … … 121 127 """ 122 128 """ 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 127 131 128 132 def get_page_by_id(self, uid): … … 298 302 self.model_list_box = dict 299 303 300 def set_model_dict (self, m_dict):304 def set_model_dictionary(self, model_dictionary): 301 305 """ 302 306 copy a dictionary of model name -> model object 303 307 304 :param m _dict: dictionary linking model name -> model object308 :param model_dictionary: dictionary linking model name -> model object 305 309 """ 306 310 … … 316 320 Add the simultaneous fit page 317 321 """ 318 from simfitpage import SimultaneousFitPage319 322 page_finder = self._manager.get_page_finder() 320 323 if caption == "Const & Simul Fit": … … 344 347 """ 345 348 if self.batch_on: 346 from batchfitpage import BatchFitPage347 349 panel = BatchFitPage(parent=self) 348 350 self.batch_page_index += 1 … … 351 353 else: 352 354 # Increment index of fit page 353 from fitpage import FitPage354 355 panel = FitPage(parent=self) 355 356 self.fit_page_index += 1 … … 359 360 panel._set_save_flag(not panel.batch_on) 360 361 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) 362 363 panel.formfactor_combo_init() 363 364 panel.set_manager(self._manager) … … 445 446 if data_1d_list and data_2d_list: 446 447 # need to warning the user that this batch is a special case 447 from sas.sasgui.perspectives.fitting.fitting_widgets import \448 BatchDataDialog449 448 dlg = BatchDataDialog(self) 450 449 if dlg.ShowModal() == wx.ID_OK: -
src/sas/sasgui/perspectives/fitting/fitproblem.py
r959eb01 r251ef684 14 14 ################################################################################ 15 15 import copy 16 from sas.sascalc.data_util.qsmearing import smear_selection 17 18 class FitProblemComponent(object): 16 17 from sas.sascalc.fit.qsmearing import smear_selection 18 19 class FitProblem(object): 19 20 """ 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. 23 23 """ 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 24 55 def enable_smearing(self, flag=False): 25 56 """ … … 27 58 flag is 0 ingore smear value. 28 59 """ 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 29 70 30 71 def get_smearer(self): … … 32 73 return smear object 33 74 """ 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 34 84 def save_model_name(self, name): 35 85 """ 36 86 """ 87 self.name_per_page = name 37 88 38 89 def get_name(self): 39 90 """ 40 91 """ 92 return self.name_per_page 41 93 42 94 def set_model(self, model): … … 46 98 :param name: name created for model 47 99 """ 100 self.model = model 101 self.smearer_computer_value = smear_selection(self.fit_data, 102 self.model) 103 self.smearer_computed = True 48 104 49 105 def get_model(self): … … 51 107 :return: saved model 52 108 """ 109 return self.model 53 110 54 111 def set_residuals(self, residuals): … … 57 114 :param data: data selected 58 115 """ 116 self.residuals = residuals 59 117 60 118 def get_residuals(self): … … 62 120 :return: residuals 63 121 """ 122 return self.residuals 64 123 65 124 def set_theory_data(self, data): 66 125 """ 67 126 save a copy of the data select to fit 127 68 128 :param data: data selected 69 """ 129 130 """ 131 self.theory_data = copy.deepcopy(data) 70 132 71 133 def get_theory_data(self): 72 134 """ 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 75 138 76 139 def set_fit_data(self, data): 77 140 """ 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 81 142 :param data: list of data selected 82 143 """ 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 83 153 84 154 def get_fit_data(self): 85 155 """ 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 87 197 88 198 def set_model_param(self, name, value=None): … … 92 202 :param value: value of that parameter 93 203 """ 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]) 105 205 106 206 def get_model_param(self): … … 108 208 return list of couple of parameter name and value 109 209 """ 210 return self.list_param 110 211 111 212 def schedule_tofit(self, schedule=0): … … 113 214 set schedule to true to decide if this fit must be performed 114 215 """ 216 self.schedule = schedule 115 217 116 218 def get_scheduled(self): … … 118 220 return true or false if a problem as being schedule for fitting 119 221 """ 222 return self.schedule 120 223 121 224 def set_range(self, qmin=None, qmax=None): 122 225 """ 123 226 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 125 232 126 233 def get_range(self): 127 234 """ 128 235 :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 140 239 141 240 def clear_model_param(self): … … 143 242 clear constraint info 144 243 """ 244 self.list_param = [] 145 245 146 246 def set_fit_tab_caption(self, caption): 147 247 """ 148 store the caption of the page associated with object149 """248 """ 249 self.fit_tab_caption = str(caption) 150 250 151 251 def get_fit_tab_caption(self): 152 252 """ 153 Return the caption of the page associated with object154 """253 """ 254 return self.fit_tab_caption 155 255 156 256 def set_graph_id(self, id): … … 158 258 Set graph id (from data_group_id at the time the graph produced) 159 259 """ 260 self.graph_id = id 160 261 161 262 def get_graph_id(self): … … 163 264 Get graph_id 164 265 """ 266 return self.graph_id 165 267 166 268 def set_result(self, result): 167 269 """ 168 270 """ 271 self.result = result 169 272 170 273 def get_result(self): … … 172 275 get result 173 276 """ 174 175 176 class FitProblemDictionary(FitProblemComponent, dict): 277 return self.result 278 279 280 class FitProblemDictionary(dict): 177 281 """ 178 282 This module implements a dictionary of fitproblem objects 179 283 """ 180 284 def __init__(self): 181 FitProblemComponent.__init__(self)182 285 dict.__init__(self) 183 286 ## the current model … … 206 309 self._smear_on = flag 207 310 if fid is None: 208 for value in self. itervalues():311 for value in self.values(): 209 312 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) 213 315 214 316 def set_smearer(self, smearer, fid=None): … … 218 320 """ 219 321 if fid is None: 220 for value in self. itervalues():322 for value in self.values(): 221 323 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) 225 326 226 327 def get_smearer(self, fid=None): … … 228 329 return smear object 229 330 """ 230 if fid in self .iterkeys():331 if fid in self: 231 332 return self[fid].get_smearer() 232 333 … … 235 336 """ 236 337 if fid is None: 237 for value in self. itervalues():338 for value in self.values(): 238 339 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) 242 342 243 343 def get_name(self, fid=None): … … 246 346 result = [] 247 347 if fid is None: 248 for value in self. itervalues():348 for value in self.values(): 249 349 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()) 253 352 return result 254 353 … … 261 360 self.model = model 262 361 if fid is None: 263 for value in self. itervalues():362 for value in self.values(): 264 363 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) 268 366 269 367 def get_model(self, fid): … … 271 369 :return: saved model 272 370 """ 273 if fid in self .iterkeys():371 if fid in self: 274 372 return self[fid].get_model() 275 373 … … 291 389 :param data: data selected 292 390 """ 293 if fid in self .iterkeys():391 if fid in self: 294 392 self[fid].set_residuals(residuals) 295 393 … … 298 396 :return: residuals 299 397 """ 300 if fid in self .iterkeys():398 if fid in self: 301 399 return self[fid].get_residuals() 302 400 … … 306 404 :param data: data selected 307 405 """ 308 if fid in self .iterkeys():406 if fid in self: 309 407 self[fid].set_theory_data(data) 310 408 … … 313 411 :return: list of data dList 314 412 """ 315 if fid in self .iterkeys():413 if fid in self: 316 414 return self[fid].get_theory_data() 317 415 … … 322 420 :note: only data changes in the fit problem 323 421 """ 324 if data.id not in self .iterkeys():422 if data.id not in self: 325 423 self[data.id] = FitProblem() 326 424 self[data.id].set_fit_data(data) … … 336 434 data = [] 337 435 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: 340 438 self[d.id] = FitProblem() 341 439 self[d.id].set_fit_data(d) … … 348 446 :param fid: key representing a fitproblem, usually extract from data id 349 447 """ 350 if fid in self .iterkeys():448 if fid in self: 351 449 return self[fid].get_fit_data() 352 450 … … 358 456 """ 359 457 if fid is None: 360 for value in self. itervalues():458 for value in self.values(): 361 459 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) 365 462 366 463 def get_model_param(self, fid): … … 368 465 return list of couple of parameter name and value 369 466 """ 370 if fid in self .iterkeys():467 if fid in self: 371 468 return self[fid].get_model_param() 372 469 … … 389 486 """ 390 487 self.scheduled = schedule 391 for value in self. itervalues():488 for value in self.values(): 392 489 value.schedule_tofit(schedule) 393 490 … … 405 502 self.qmax = qmax 406 503 if fid is None: 407 for value in self. itervalues():504 for value in self.values(): 408 505 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) 412 508 413 509 def get_range(self, fid): … … 415 511 :return: fitting range 416 512 """ 417 if fid in self .iterkeys():513 if fid in self: 418 514 return self[fid].get_range() 419 515 … … 423 519 """ 424 520 if fid is None: 425 for value in self. itervalues():521 for value in self.values(): 426 522 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) 430 525 431 526 def get_weight(self, fid=None): … … 433 528 return fit weight 434 529 """ 435 if fid in self .iterkeys():530 if fid in self: 436 531 return self[fid].get_weight() 437 532 … … 441 536 """ 442 537 if fid is None: 443 for value in self. itervalues():538 for value in self.values(): 444 539 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() 448 542 449 543 def get_fit_problem(self): … … 451 545 return fitproblem contained in this dictionary 452 546 """ 453 return self. itervalues()547 return self.values() 454 548 455 549 def set_result(self, result, fid): 456 550 """ 457 551 """ 458 if fid in self .iterkeys():552 if fid in self: 459 553 self[fid].set_result(result) 460 554 … … 470 564 get result 471 565 """ 472 if fid in self .iterkeys():566 if fid in self: 473 567 return self[fid].get_result() 474 568 … … 490 584 """ 491 585 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 fit504 """505 ## data used for fitting506 self.fit_data = None507 self.theory_data = None508 self.residuals = None509 # original data: should not be modified510 self.original_data = None511 ## the current model512 self.model = None513 ## if 1 this fit problem will be selected to fit , if 0514 ## it will not be selected for fit515 self.schedule = 0516 ##list containing parameter name and value517 self.list_param = []518 ## smear object to smear or not data1D519 self.smearer_computed = False520 self.smearer_enable = False521 self.smearer_computer_value = None522 ## fitting range523 self.qmin = None524 self.qmax = None525 # fit weight526 self.weight = None527 self.result = None528 529 def enable_smearing(self, flag=False):530 """531 :param flag: bool.When flag is 1 get the computer smear value. When532 flag is 0 ingore smear value.533 """534 self.smearer_enable = flag535 536 def set_smearer(self, smearer):537 """538 save reference of smear object on fitdata539 540 :param smear: smear object from DataLoader541 542 """543 self.smearer_computer_value = smearer544 545 def get_smearer(self):546 """547 return smear object548 """549 if not self.smearer_enable:550 return None551 if not self.smearer_computed:552 #smeari_selection should be call only once per fitproblem553 self.smearer_computer_value = smear_selection(self.fit_data,554 self.model)555 self.smearer_computed = True556 return self.smearer_computer_value557 558 def save_model_name(self, name):559 """560 """561 self.name_per_page = name562 563 def get_name(self):564 """565 """566 return self.name_per_page567 568 def set_model(self, model):569 """570 associates each model with its new created name571 :param model: model selected572 :param name: name created for model573 """574 self.model = model575 self.smearer_computer_value = smear_selection(self.fit_data,576 self.model)577 self.smearer_computed = True578 579 def get_model(self):580 """581 :return: saved model582 """583 return self.model584 585 def set_residuals(self, residuals):586 """587 save a copy of residual588 :param data: data selected589 """590 self.residuals = residuals591 592 def get_residuals(self):593 """594 :return: residuals595 """596 return self.residuals597 598 def set_theory_data(self, data):599 """600 save a copy of the data select to fit601 602 :param data: data selected603 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 class610 """611 return self.theory_data612 613 def set_fit_data(self, data):614 """615 Store data associated with this class616 :param data: list of data selected617 """618 self.original_data = None619 self.fit_data = None620 # original data: should not be modified621 self.original_data = data622 # fit data: used for fit and can be modified for convenience623 self.fit_data = copy.deepcopy(data)624 self.smearer_computer_value = smear_selection(self.fit_data,625 self.model)626 self.smearer_computed = True627 self.result = None628 629 def get_fit_data(self):630 """631 :return: data associate with this class632 """633 return self.fit_data634 635 def get_origin_data(self):636 """637 """638 return self.original_data639 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 Data645 """646 from sas.sasgui.perspectives.fitting.utils import get_weight647 # send original data for weighting648 self.weight = get_weight(data=self.original_data, is2d=is2d, flag=flag)649 if is2d:650 self.fit_data.err_data = self.weight651 else:652 self.fit_data.dy = self.weight653 654 def get_weight(self):655 """656 returns weight array657 """658 return self.weight659 660 def set_param2fit(self, list):661 """662 Store param names to fit (checked)663 :param list: list of the param names664 """665 self.list_param2fit = list666 667 def get_param2fit(self):668 """669 return the list param names to fit670 """671 return self.list_param2fit672 673 def set_model_param(self, name, value=None):674 """675 Store the name and value of a parameter of this fitproblem's model676 :param name: name of the given parameter677 :param value: value of that parameter678 """679 self.list_param.append([name, value])680 681 def get_model_param(self):682 """683 return list of couple of parameter name and value684 """685 return self.list_param686 687 def schedule_tofit(self, schedule=0):688 """689 set schedule to true to decide if this fit must be performed690 """691 self.schedule = schedule692 693 def get_scheduled(self):694 """695 return true or false if a problem as being schedule for fitting696 """697 return self.schedule698 699 def set_range(self, qmin=None, qmax=None):700 """701 set fitting range702 :param qmin: minimum value to consider for the fit range703 :param qmax: maximum value to consider for the fit range704 """705 self.qmin = qmin706 self.qmax = qmax707 708 def get_range(self):709 """710 :return: fitting range711 712 """713 return self.qmin, self.qmax714 715 def clear_model_param(self):716 """717 clear constraint info718 """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_caption730 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 = id736 737 def get_graph_id(self):738 """739 Get graph_id740 """741 return self.graph_id742 743 def set_result(self, result):744 """745 """746 self.result = result747 748 def get_result(self):749 """750 get result751 """752 return self.result -
src/sas/sasgui/perspectives/fitting/fitting.py
r2504b5a r2504b5a 23 23 import traceback 24 24 25 import bumps.options 26 from bumps.gui.fit_dialog import show_fit_config 27 try: 28 from bumps.gui.fit_dialog import EVT_FITTER_CHANGED 29 except ImportError: 30 # CRUFT: bumps 0.7.5.8 and below 31 EVT_FITTER_CHANGED = None # type: wx.PyCommandEvent 32 25 33 from sas.sascalc.dataloader.loader import Loader 34 from sas.sascalc.fit.BumpsFitting import BumpsFit as Fit 35 from sas.sascalc.fit.pagestate import Reader, PageState, SimFitPageState 36 from sas.sascalc.fit import models 37 26 38 from sas.sasgui.guiframe.dataFitting import Data2D 27 39 from sas.sasgui.guiframe.dataFitting import Data1D … … 34 46 from sas.sasgui.guiframe.plugin_base import PluginBase 35 47 from 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 48 from sas.sasgui.guiframe.gui_manager import MDIFrame 49 from sas.sasgui.guiframe.documentation_window import DocumentationWindow 50 45 51 from sas.sasgui.perspectives.calculator.model_editor import TextDialog 46 52 from 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 54 from .fitting_widgets import DataDialog 55 from .fit_thread import FitThread 56 from .fitpage import Chi2UpdateEvent 57 from .console import ConsoleUpdate 58 from .fitproblem import FitProblemDictionary 59 from .fitpanel import FitPanel 60 from .model_thread import Calc1D, Calc2D 61 from .resultpanel import ResultPanel, PlotResultEvent 62 from .gpu_options import GpuOptions 52 63 53 64 logger = logging.getLogger(__name__) … … 63 74 ON_MAC = True 64 75 65 import bumps.options66 from bumps.gui.fit_dialog import show_fit_config67 try:68 from bumps.gui.fit_dialog import EVT_FITTER_CHANGED69 except ImportError:70 # CRUFT: bumps 0.7.5.8 and below71 EVT_FITTER_CHANGED = None # type: wx.PyCommandEvent72 76 73 77 class Plugin(PluginBase): … … 238 242 Get the python editor panel 239 243 """ 244 from sas.sasgui.perspectives.calculator.pyconsole import PyConsole 245 240 246 event_id = event.GetId() 241 247 label = self.edit_menu.GetLabel(event_id) 242 from sas.sasgui.perspectives.calculator.pyconsole import PyConsole243 248 filename = os.path.join(models.find_plugins_dir(), label) 244 249 frame = PyConsole(parent=self.parent, manager=self, … … 290 295 break 291 296 except Exception: 292 import traceback;traceback.print_exc()297 traceback.print_exc() 293 298 msg = 'Delete Error: \nCould not delete the file; Check if in use.' 294 299 wx.MessageBox(msg, 'Error') … … 300 305 event_id = event.GetId() 301 306 model_manager = models.ModelManager() 302 model_list = model_manager. get_model_name_list()307 model_list = model_manager.composable_models() 303 308 plug_dir = models.find_plugins_dir() 304 309 textdial = TextDialog(None, self, wx.ID_ANY, 'Easy Sum/Multi(p1, p2) Editor', … … 340 345 self.set_edit_menu_helper(self.parent, self.edit_custom_model) 341 346 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: 371 382 logger.error("update_custom_combo: %s", sys.exc_value) 372 383 … … 378 389 #new_model_menu = wx.Menu() 379 390 self.edit_model_menu.Append(wx_id, 'New Plugin Model', 380 'Add a new model function')391 'Add a new model function') 381 392 wx.EVT_MENU(owner, wx_id, self.make_new_model) 382 393 … … 575 586 else: 576 587 if len(data_list) > MAX_NBR_DATA: 577 from fitting_widgets import DataDialog578 588 dlg = DataDialog(data_list=data_list, nb_data=MAX_NBR_DATA) 579 589 if dlg.ShowModal() == wx.ID_OK: … … 620 630 : param datainfo: data 621 631 """ 622 from pagestate import PageState623 from simfitpage import SimFitPageState624 632 if isinstance(state, PageState): 625 633 state = state.clone() 626 634 self.temp_state.append(state) 627 635 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) 629 639 else: 630 640 self.temp_state = [] … … 661 671 self.parent.add_data(data_list={data.id: data}) 662 672 wx.PostEvent(self.parent, NewPlotEvent(plot=data, 663 673 title=data.title)) 664 674 #need to be fix later make sure we are sendind guiframe.data 665 675 #to panel … … 672 682 self.parent.add_data(data_list={data.id: data}) 673 683 wx.PostEvent(self.parent, NewPlotEvent(plot=data, 674 684 title=data.title)) 675 685 page = self.add_fit_page([data]) 676 686 caption = page.window_caption 677 687 self.store_data(uid=page.uid, data_list=page.get_data_list(), 678 caption=caption)688 caption=caption) 679 689 self.mypanels.append(page) 680 690 … … 793 803 """ 794 804 if item.find(".") >= 0: 795 param_names = re.split( "\.", item)805 param_names = re.split(r"\.", item) 796 806 model_name = param_names[0] 797 807 ##Assume max len is 3; eg., M0.radius.width … … 896 906 897 907 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) 900 910 901 911 def draw_model(self, model, page_id, data=None, smearer=None, … … 940 950 ## draw model 2D with no initial data 941 951 self._draw_model2D(model=model, 942 943 944 945 946 947 948 949 950 951 952 953 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) 954 964 955 965 def onFit(self, uid): … … 960 970 :param uid: id related to the panel currently calling this fit function. 961 971 """ 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 963 974 964 975 sim_page_uid = getattr(self.sim_page, 'uid', None) … … 994 1005 page = self.fit_panel.get_page_by_id(page_id) 995 1006 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()) 998 1009 if not page.param_toFit: 999 1010 msg = "No fitting parameters for %s" % page.window_caption … … 1019 1030 fitter = sim_fitter 1020 1031 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) 1024 1035 fit_id += 1 1025 1036 list_page_id.append(page_id) … … 1068 1079 ## Perform more than 1 fit at the time 1069 1080 calc_fit = FitThread(handler=handler, 1070 1071 1072 1073 1074 1075 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) 1076 1087 #self.fit_thread_list[current_page_id] = calc_fit 1077 1088 self.fit_thread_list[uid] = calc_fit … … 1134 1145 evt = StatusEvent(status=msg, info="warning") 1135 1146 wx.PostEvent(self.parent, evt) 1136 except :1147 except Exception: 1137 1148 msg = "Creating Fit page: %s" % sys.exc_value 1138 1149 wx.PostEvent(self.parent, StatusEvent(status=msg, info="error")) … … 1158 1169 group_id = str(page.uid) + " Model1D" 1159 1170 wx.PostEvent(self.parent, 1160 NewPlotEvent(group_id=group_id,1161 1171 NewPlotEvent(group_id=group_id, 1172 action="delete")) 1162 1173 self.parent.update_data(prev_data=theory_data, 1163 1174 new_data=data) 1164 1175 else: 1165 1176 if theory_data is not None: … … 1167 1178 data.group_id = theory_data.group_id 1168 1179 wx.PostEvent(self.parent, 1169 NewPlotEvent(group_id=group_id,1170 1180 NewPlotEvent(group_id=group_id, 1181 action="delete")) 1171 1182 self.parent.update_data(prev_data=theory_data, 1172 1183 new_data=data) 1173 1184 self.store_data(uid=page.uid, data_list=page.get_data_list(), 1174 1185 caption=page.window_caption) … … 1479 1490 if "Data" not in batch_outputs.keys(): 1480 1491 batch_outputs["Data"] = [] 1481 from sas.sasgui.guiframe.data_processor import BatchCell1482 1492 cell = BatchCell() 1483 1493 cell.label = data.name … … 1579 1589 except KeyboardInterrupt: 1580 1590 fit_msg += "\nSingular point: Fitting stopped." 1581 except :1591 except Exception: 1582 1592 fit_msg += "\nSingular point: Fitting error occurred." 1583 1593 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: 1588 1598 msg = ("Fit completed but the following error occurred: %s" 1589 1599 % sys.exc_value) 1590 # import traceback;msg = "\n".join((traceback.format_exc(), msg))1600 #msg = "\n".join((traceback.format_exc(), msg)) 1591 1601 evt = StatusEvent(status=msg, info="warning", type="stop") 1592 1602 wx.PostEvent(self.parent, evt) … … 1743 1753 fid=data.id) 1744 1754 self.parent.update_theory(data_id=data.id, theory=new_plot, 1745 1755 state=state) 1746 1756 return new_plot 1747 1757 … … 1759 1769 @param unsmeared_error: data error, rescaled to unsmeared model 1760 1770 """ 1771 <<<<<<< HEAD 1772 1773 ======= 1774 >>>>>>> master 1761 1775 number_finite = np.count_nonzero(np.isfinite(y)) 1762 1776 np.nan_to_num(y) … … 1767 1781 # Create the new theories 1768 1782 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, 1770 1784 page_id, model, data, state, 1771 1785 data_description=model.name + " unsmeared", … … 1774 1788 1775 1789 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, 1777 1791 page_id, model, data, state, 1778 1792 data_description="Data unsmeared", … … 1792 1806 plots_to_update.append(pq_plot) 1793 1807 # 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, 1795 1809 action='update')) 1796 1810 … … 1808 1822 1809 1823 self.page_finder[page_id].set_theory_data(data=new_plot, 1810 1824 fid=data.id) 1811 1825 if toggle_mode_on: 1812 1826 wx.PostEvent(self.parent, 1813 1827 NewPlotEvent(group_id=str(page_id) + " Model2D", 1814 1828 action="Hide")) 1815 1829 else: 1816 1830 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)) 1824 1837 else: 1825 1838 self._plot_residuals(page_id=page_id, data=data, fid=fid, … … 1829 1842 logger.error("Using the present parameters the model does not return any finite value. ") 1830 1843 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")) 1832 1845 else: 1833 1846 msg = "Computation completed!" … … 1854 1867 1855 1868 def _complete2D(self, image, data, model, page_id, elapsed, index, qmin, 1856 qmax, fid=None, weight=None, toggle_mode_on=False, state=None,1857 1869 qmax, fid=None, weight=None, toggle_mode_on=False, state=None, 1870 update_chisqr=True, source='model', plot_result=True): 1858 1871 """ 1859 1872 Complete get the result of modelthread and create model 2D … … 1896 1909 fid=data.id) 1897 1910 self.parent.update_theory(data_id=data.id, 1898 1899 1911 theory=new_plot, 1912 state=state) 1900 1913 current_pg = self.fit_panel.get_page_by_id(page_id) 1901 1914 title = new_plot.title 1902 1915 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)) 1905 1917 if toggle_mode_on: 1906 1918 wx.PostEvent(self.parent, 1907 1908 1919 NewPlotEvent(group_id=str(page_id) + " Model1D", 1920 action="Hide")) 1909 1921 else: 1910 1922 # Chisqr in fitpage 1911 1923 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)) 1918 1930 else: 1919 1931 self._plot_residuals(page_id=page_id, data=data, fid=fid, 1920 1932 index=index, weight=weight) 1921 1933 1922 1934 if not number_finite: 1923 1935 logger.error("Using the present parameters the model does not return any finite value. ") 1924 1936 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")) 1926 1938 else: 1927 1939 msg = "Computation completed!" … … 1939 1951 weight=None, 1940 1952 toggle_mode_on=False, 1941 1953 update_chisqr=True, source='model'): 1942 1954 """ 1943 1955 draw model in 2D … … 1954 1966 return None 1955 1967 try: 1956 from model_thread import Calc2D1957 1968 ## If a thread is already started, stop it 1958 1969 if (self.calc_2D is not None) and self.calc_2D.isrunning(): … … 1986 1997 def _draw_model1D(self, model, page_id, data, 1987 1998 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): 1993 2002 """ 1994 2003 Draw model 1D from loaded data1D … … 2001 2010 return 2002 2011 try: 2003 from model_thread import Calc1D2004 2012 ## If a thread is already started, stop it 2005 2013 if (self.calc_1D is not None) and self.calc_1D.isrunning(): -
src/sas/sasgui/perspectives/fitting/model_thread.py
r0f9ea1c r0f9ea1c 1 1 """ 2 2 Calculation thread for modeling 3 3 """ 4 4 5 5 import time 6 import math 7 6 8 import numpy as np 7 import math 9 8 10 from sas.sascalc.data_util.calcthread import CalcThread 9 11 from sas.sascalc.fit.MultiplicationModel import MultiplicationModel … … 28 30 worktime=0.04, 29 31 exception_handler=None, 30 32 ): 31 33 CalcThread.__init__(self, completefn, updatefn, yieldtime, worktime, 32 34 exception_handler=exception_handler) … … 57 59 if self.qmax is None: 58 60 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) 64 64 65 65 if self.data is None: … … 68 68 69 69 # 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) 72 71 73 72 # For theory, qmax is based on 1d qmax 74 73 # so that must be mulitified by sqrt(2) to get actual max for 2d 75 74 index_model = (self.qmin <= radius) & (radius <= self.qmax) 76 index_model = index_model &self.data.mask77 index_model = index_model &np.isfinite(self.data.data)75 index_model &= self.data.mask 76 index_model &= np.isfinite(self.data.data) 78 77 79 78 if self.smearer is not None: … … 101 100 elapsed = time.time() - self.starttime 102 101 self.complete(image=output, 103 104 105 106 107 108 109 110 111 112 113 114 115 116 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) 117 116 118 117 … … 138 137 worktime=0.01, 139 138 exception_handler=None, 140 139 ): 141 140 """ 142 141 """ … … 193 192 * unsmeared_output[first_bin:last_bin+1]\ 194 193 / output[first_bin:last_bin+1] 195 unsmeared_output =unsmeared_output[index]196 unsmeared_data =unsmeared_data[index]197 unsmeared_error =unsmeared_error194 unsmeared_output = unsmeared_output[index] 195 unsmeared_data = unsmeared_data[index] 196 unsmeared_error = unsmeared_error 198 197 else: 199 198 output[index] = self.model.evalDistribution(self.data.x[index]) … … 243 242 class CalcCommandline: 244 243 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])) 252 251 253 252 qmax = 0.01 … … 258 257 y = numpy.arange(-qmax, qmax+qstep*0.01, qstep) 259 258 260 261 259 calc_thread_2D = Calc2D(x, y, None, model.clone(),None, 262 260 -qmax, qmax,qstep, 263 264 265 261 completefn=self.complete, 262 updatefn=self.update , 263 yieldtime=0.0) 266 264 267 265 calc_thread_2D.queue() … … 272 270 273 271 def update(self,output): 274 print "update"272 print("update") 275 273 276 274 def complete(self, image, data, model, elapsed, qmin, qmax,index, qstep ): 277 print "complete"275 print("complete") 278 276 self.done = True 279 277 -
src/sas/sasgui/perspectives/fitting/report_dialog.py
r7432acb r78312f7 38 38 # number of images of plot 39 39 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] 58 41 # layout 59 42 self._setup_layout() … … 105 88 elif self.nimages == 3: 106 89 html = report_frame % (str(pic_fname[0]), str(pic_fname[1]), 107 90 str(pic_fname[2])) 108 91 109 92 # make/open file in case of absence … … 118 101 #Windows 119 102 os.startfile(str(fName)) 120 except :103 except Exception: 121 104 try: 122 105 #Mac 123 106 os.system("open %s" % fName) 124 except :107 except Exception: 125 108 #DO not open 126 109 pass -
src/sas/sasgui/perspectives/fitting/simfitpage.py
ra9f9ca4 r00f7ff1 2 2 Simultaneous or Batch fit page 3 3 """ 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 5 5 # 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 7 7 # if not batch_on: 8 8 # xxxx … … 11 11 # This is just wrong but dont have time to fix this go. Proper approach would be 12 12 # 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 14 14 # batch page inherit. 15 15 # … … 23 23 from wx.lib.scrolledpanel import ScrolledPanel 24 24 25 from sas.sascalc.fit.pagestate import SimFitPageState 25 26 from sas.sasgui.guiframe.events import StatusEvent, PanelOnFocusEvent 26 27 from sas.sasgui.guiframe.panel_base import PanelBase … … 60 61 61 62 return fittable_param 62 63 63 64 64 class SimultaneousFitPage(ScrolledPanel, PanelBase): … … 157 157 return self.state 158 158 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 159 215 def draw_page(self): 160 216 """ 161 217 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 163 219 and models. Then fills sizer2 with the checkbox for adding 164 220 constraints, and finally fills sizer3 with the fit button and … … 1043 1099 cbox.Append(name, value) 1044 1100 cbox.SetStringSelection(selected) 1045 1046 1047 class SimFitPageState:1048 """1049 State of the simultaneous fit page for saving purposes1050 """1051 1052 def __init__(self):1053 # Sim Fit Page Number1054 self.fit_page_no = None1055 # Select all data1056 self.select_all = False1057 # Data sets sent to fit page1058 self.model_list = []1059 # Data sets to be fit1060 self.model_to_fit = []1061 # Number of constraints1062 self.no_constraint = 01063 # Dictionary of constraints1064 self.constraint_dict = {}1065 # List of constraints1066 self.constraints_list = []1067 1068 def load_from_save_state(self, fit):1069 """1070 Load in a simultaneous/constrained fit from a save state1071 :param fit: Fitpanel object1072 :return: None1073 """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_page1079 1080 # Process each model and associate old M# with new M#1081 i = 01082 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_id1087 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].name1091 check = bool(saved_model.pop('checked'))1092 sim_page.model_list[i][0].SetValue(check)1093 break1094 i += 11095 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_page1119 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.