Changes in / [83db1cc:9be22cd] in sasview
- Files:
-
- 4 added
- 4 deleted
- 32 edited
Legend:
- Unmodified
- Added
- Removed
-
installers/setup_exe.py
r92df9cbd rb963b20 46 46 sys.path.insert(0, build_path) 47 47 48 from sas.sasview import local_config49 48 from installer_generator import generate_installer 50 49 … … 74 73 sys.exc_value) 75 74 75 from sas import get_local_config 76 local_config = get_local_config() 76 77 77 78 # Solution taken from here: http://www.py2exe.org/index.cgi/win32com.shell -
installers/setup_mac.py
r67d8b1b rb963b20 45 45 import macholib_patch 46 46 47 from sas.sasview import local_config 47 from sas import get_local_config 48 local_config = get_local_config() 48 49 49 50 ICON = local_config.SetupIconFile_mac -
src/sas/__init__.py
r79492222 rb963b20 1 __all__ = ['get_app_dir', 'get_user_dir', 2 'get_local_config', 'get_custom_config'] 3 4 _APP_DIR = None 5 def get_app_dir(): 6 """ 7 The directory where the sasview application is found. 8 9 Returns the path to sasview if running in place or installed with setup. 10 If the application is frozen, returns the parent directory of the 11 application resources such as test files and images. 12 """ 13 global _APP_DIR 14 if not _APP_DIR: 15 from ._config import find_app_dir 16 _APP_DIR = find_app_dir() 17 return _APP_DIR 18 19 _USER_DIR = None 20 def get_user_dir(): 21 """ 22 The directory where the per-user configuration is stored. 23 24 Returns ~/.sasview, creating it if it does not already exist. 25 """ 26 global _USER_DIR 27 if not _USER_DIR: 28 from ._config import make_user_dir 29 _USER_DIR = make_user_dir() 30 return _USER_DIR 31 32 def make_custom_config_path(): 33 from ._config import make_custom_config_path as _make_path 34 return _make_path(get_user_dir()) 35 36 _CUSTOM_CONFIG = None 37 def get_custom_config(): 38 """ 39 Setup the custom config dir and cat file 40 """ 41 global _CUSTOM_CONFIG 42 if not _CUSTOM_CONFIG: 43 from ._config import setup_custom_config 44 _CUSTOM_CONFIG = setup_custom_config(get_app_dir(), get_user_dir()) 45 return _CUSTOM_CONFIG 46 47 48 _LOCAL_CONFIG = None 49 def get_local_config(): 50 """ 51 Loads the local config file. 52 """ 53 global _LOCAL_CONFIG 54 if not _LOCAL_CONFIG: 55 from ._config import load_local_config 56 _LOCAL_CONFIG = load_local_config(get_app_dir()) 57 return _LOCAL_CONFIG -
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/__init__.py
rc6bdb3b rb963b20 1 import sys2 import os3 from os.path import exists, expanduser, dirname, realpath, join as joinpath4 5 6 def dirn(path, n):7 path = realpath(path)8 for _ in range(n):9 path = dirname(path)10 return path11 12 # Set up config directories13 def make_user_folder():14 path = joinpath(expanduser("~"),'.sasview')15 if not exists(path):16 os.mkdir(path)17 return path18 19 20 def find_app_folder():21 # We are starting out with the following info:22 # __file__ = .../sas/sasgui/__init__.pyc23 # Check if the sister path .../sas/sasview exists, and use it as the24 # app directory. This will only be the case if the app is not frozen.25 path = joinpath(dirn(__file__, 2), 'sasview')26 if exists(path):27 return path28 29 # If we are running frozen, then root is a parent directory30 if sys.platform == 'darwin':31 # Here is the path to the file on the mac:32 # .../Sasview.app/Contents/Resources/lib/python2.7/site-packages.zip/sas/sasgui/__init__.pyc33 # We want the path to the Resources directory.34 path = dirn(__file__, 6)35 elif os.name == 'nt':36 # Here is the path to the file on windows:37 # ../Sasview/library.zip/sas/sasgui/__init__.pyc38 # We want the path to the Sasview directory.39 path = dirn(__file__, 4)40 else:41 raise RuntimeError("Couldn't find the app directory")42 return path43 44 USER_FOLDER = make_user_folder()45 APP_FOLDER = find_app_folder()46 47 48 def get_app_dir():49 return APP_FOLDER50 51 def get_user_dir():52 return USER_FOLDER53 54 def get_custom_config_path():55 dirname = os.path.join(get_user_dir(), 'config')56 # If the directory doesn't exist, create it57 if not os.path.exists(dirname):58 os.makedirs(dirname)59 path = os.path.join(dirname, "custom_config.py")60 return path61 62 _config_cache = None63 def get_local_config():64 global _config_cache65 if not _config_cache:66 _config_cache = _load_config()67 return _config_cache68 69 def _load_config():70 import os71 import sys72 import logging73 from sasmodels.custom import load_module_from_path74 75 logger = logging.getLogger(__name__)76 dirname = get_app_dir()77 filename = 'local_config.py'78 path = os.path.join(dirname, filename)79 try:80 module = load_module_from_path('sas.sasgui.local_config', path)81 logger.info("GuiManager loaded %s", path)82 return module83 except Exception as exc:84 logger.critical("Error loading %s: %s", path, exc)85 sys.exit() -
src/sas/sasgui/guiframe/CategoryInstaller.py
r6e50a8d rb963b20 15 15 from collections import defaultdict, OrderedDict 16 16 17 from sas .sasguiimport get_user_dir17 from sas import get_user_dir 18 18 19 19 USER_FILE = 'categories.json' … … 27 27 Note - class is entirely static! 28 28 """ 29 30 @staticmethod 31 def _get_installed_model_dir(): 32 """ 33 returns the dir where installed_models.txt should be 34 """ 35 from sas.sascalc.dataloader.readers import get_data_path 36 return get_data_path() 37 38 @staticmethod 39 def _get_default_cat_file_dir(): 40 """ 41 returns the dir where default_cat.j should be 42 """ 43 # The default categories file is usually found with the code, except 44 # when deploying using py2app (it will be in Contents/Resources), or 45 # py2exe (it will be in the exec dir). 46 import sas.sasview 47 cat_file = "default_categories.json" 48 49 possible_cat_file_paths = [ 50 os.path.join(os.path.split(sas.sasview.__file__)[0], cat_file), # Source 51 os.path.join(os.path.dirname(sys.executable), '..', 'Resources', cat_file), # Mac 52 os.path.join(os.path.dirname(sys.executable), cat_file) # Windows 53 ] 54 55 for path in possible_cat_file_paths: 56 if os.path.isfile(path): 57 return os.path.dirname(path) 58 59 raise RuntimeError('CategoryInstaller: Could not find folder containing default categories') 60 61 @staticmethod 62 def _get_home_dir(): 63 """ 64 returns the users sasview config dir 65 """ 66 return os.path.join(os.path.expanduser("~"), ".sasview") 29 67 30 68 @staticmethod … … 81 119 which are user supplied. 82 120 """ 83 _model_dict = { 121 _model_dict = {model.name: model for model in model_list} 84 122 _model_list = _model_dict.keys() 85 123 … … 107 145 by_model_dict.pop(model_name) 108 146 model_enabled_dict.pop(model_name) 109 except :147 except Exception: 110 148 logger.error("CategoryInstaller: %s", sys.exc_value) 111 149 else: … … 113 151 if del_name or (len(add_list) > 0): 114 152 for model in add_list: 115 model_enabled_dict[model]= True 116 if _model_dict[model].category is None or len(str(_model_dict[model].category.capitalize())) == 0: 153 model_enabled_dict[model] = True 154 # TODO: should be: not _model_dict[model].category 155 if (_model_dict[model].category is None 156 or len(str(_model_dict[model].category.capitalize())) == 0): 117 157 by_model_dict[model].append('Uncategorized') 118 158 else: -
src/sas/sasgui/guiframe/aboutbox.py
r959eb01 rb963b20 25 25 import os 26 26 27 from sas .sasguiimport get_local_config27 from sas import get_local_config 28 28 config = get_local_config() 29 29 -
src/sas/sasgui/guiframe/acknowledgebox.py
r74c8cd0 rb963b20 13 13 from wx.lib.expando import ExpandoTextCtrl 14 14 15 from sas .sasguiimport get_local_config15 from sas import get_local_config 16 16 config = get_local_config() 17 17 -
src/sas/sasgui/guiframe/config.py
rd908932 rb963b20 145 145 UPDATE_TIMEOUT = 2 146 146 147 #OpenCL option148 SAS_OPENCL = None149 150 147 # Time out for updating sasview 151 148 UPDATE_TIMEOUT = 2 -
src/sas/sasgui/guiframe/data_panel.py
rc6bdb3b rb963b20 33 33 from sas.sasgui.guiframe.local_perspectives.plotting.SimplePlot \ 34 34 import PlotFrame as QucikPlotDialog 35 from sas .sasguiimport get_local_config35 from sas import get_local_config 36 36 37 37 config = get_local_config() -
src/sas/sasgui/guiframe/documentation_window.py
r2746eab rb963b20 27 27 WX_SUPPORTS_HTML2 = False 28 28 29 from sas .sasguiimport get_app_dir29 from sas import get_app_dir 30 30 31 31 # Don't use wx html renderer on windows. -
src/sas/sasgui/guiframe/gui_manager.py
r2f22db9 rb963b20 28 28 from matplotlib import _pylab_helpers 29 29 30 from sas .sasgui import get_local_config, get_app_dir, get_user_dir30 from sas import get_local_config, get_custom_config, get_app_dir, get_user_dir 31 31 from sas.sasgui.guiframe.events import EVT_CATEGORY 32 32 from sas.sasgui.guiframe.events import EVT_STATUS … … 47 47 from sas.sascalc.dataloader.loader import Loader 48 48 from sas.sasgui.guiframe.proxy import Connection 49 from sas.sasgui.guiframe.customdir import setup_custom_config50 49 51 50 logger = logging.getLogger(__name__) … … 53 52 54 53 config = get_local_config() 55 custom_config = setup_custom_config()54 custom_config = get_custom_config() 56 55 57 56 # read some constants from config … … 63 62 SPLASH_SCREEN_HEIGHT = config.SPLASH_SCREEN_HEIGHT 64 63 SS_MAX_DISPLAY_TIME = config.SS_MAX_DISPLAY_TIME 65 SAS_OPENCL = config.SAS_OPENCL66 64 if not WELCOME_PANEL_ON: 67 65 WELCOME_PANEL_SHOW = False … … 138 136 PARENT_FRAME = wx.Frame 139 137 CHILD_FRAME = wx.Frame 140 141 #Initiliaze enviromental variable with custom setting but only if variable not set142 if SAS_OPENCL and not "SAS_OPENCL" in os.environ:143 os.environ["SAS_OPENCL"] = SAS_OPENCL144 138 145 139 class ViewerFrame(PARENT_FRAME): -
src/sas/sasgui/guiframe/local_perspectives/data_loader/data_loader.py
rdcb91cf rb963b20 10 10 logger = logging.getLogger(__name__) 11 11 12 from sas import get_local_config 13 12 14 from sas.sascalc.dataloader.loader import Loader 13 15 from sas.sascalc.dataloader.loader_exceptions import NoKnownLoaderException 14 16 15 from sas.sasgui import get_local_config16 17 from sas.sasgui.guiframe.plugin_base import PluginBase 17 18 from sas.sasgui.guiframe.events import StatusEvent -
src/sas/sasgui/guiframe/report_dialog.py
r463e7ffc r69a6897 13 13 if sys.platform == "win32": 14 14 _STATICBOX_WIDTH = 450 15 PANEL_WIDTH = 500 15 PANEL_WIDTH = 500 16 16 PANEL_HEIGHT = 700 17 17 FONT_VARIANT = 0 … … 26 26 27 27 class BaseReportDialog(wx.Dialog): 28 28 29 29 def __init__(self, report_list, *args, **kwds): 30 30 """ 31 31 Initialization. The parameters added to Dialog are: 32 32 33 33 :param report_list: list of html_str, text_str, image for report 34 34 """ … … 48 48 self.report_list = report_list 49 49 # wild card 50 # pdf supporting only on MAC 51 if self.is_pdf: 52 self.wild_card = ' PDF files (*.pdf)|*.pdf|' 50 if self.is_pdf: # pdf writer is available 51 self.wild_card = 'PDF files (*.pdf)|*.pdf|' 53 52 self.index_offset = 0 54 53 else: … … 63 62 """ 64 63 hbox = wx.BoxSizer(wx.HORIZONTAL) 65 64 66 65 # buttons 67 66 button_close = wx.Button(self, wx.ID_OK, "Close") … … 75 74 id=button_print.GetId()) 76 75 hbox.Add(button_print) 77 76 78 77 button_save = wx.Button(self, wx.NewId(), "Save") 79 78 button_save.SetToolTipString("Save this report.") 80 79 button_save.Bind(wx.EVT_BUTTON, self.onSave, id=button_save.GetId()) 81 80 hbox.Add(button_save) 82 81 83 82 # panel for report page 84 83 vbox = wx.BoxSizer(wx.VERTICAL) … … 87 86 # set the html page with the report string 88 87 self.hwindow.SetPage(self.report_html) 89 88 90 89 # add panels to boxsizers 91 90 vbox.Add(hbox) … … 103 102 previewh = html.HtmlEasyPrinting(name="Printing", parentWindow=self) 104 103 previewh.PreviewText(self.report_html) 105 104 106 105 def onPrint(self, event=None): 107 106 """ … … 118 117 """ 119 118 self.Close() 120 119 121 120 def HTML2PDF(self, data, filename): 122 121 """ 123 122 Create a PDF file from html source string. 124 Returns True is the file creation was successful. 123 Returns True is the file creation was successful. 125 124 : data: html string 126 125 : filename: name of file to be saved … … 136 135 self.Update() 137 136 return pisaStatus.err 138 except :137 except Exception: 139 138 logger.error("Error creating pdf: %s" % sys.exc_value) 140 139 return False 141 -
src/sas/sasgui/guiframe/startup_configuration.py
r7432acb rb963b20 13 13 import wx 14 14 15 from sas .sasgui import get_custom_config_path15 from sas import make_custom_config_path 16 16 from sas.sasgui.guiframe.events import StatusEvent 17 17 from sas.sasgui.guiframe.gui_style import GUIFRAME … … 194 194 Write custom configuration 195 195 """ 196 path = get_custom_config_path()196 path = make_custom_config_path() 197 197 with open(path, 'w') as out_f: 198 198 out_f.write("#Application appearance custom configuration\n") -
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 Queue import Queue 18 15 from threading import Thread 19 16 from collections import defaultdict 17 18 import numpy as np 19 20 import wx 20 21 from wx.lib.scrolledpanel import ScrolledPanel 21 22 23 from sasmodels.sasview_model import MultiplicationModel 22 24 from sasmodels.weights import MODELS as POLYDISPERSITY_MODELS 25 from sasmodels.weights import GaussianDispersion 26 27 from sas.sascalc.dataloader.data_info import Detector 28 from sas.sascalc.dataloader.data_info import Source 29 from sas.sascalc.fit.pagestate import PageState 30 from sas.sascalc.fit.models import PLUGIN_NAME_BASE 23 31 24 32 from sas.sasgui.guiframe.panel_base import PanelBase … … 32 40 from sas.sasgui.guiframe.dataFitting import check_data_validity 33 41 from sas.sasgui.guiframe.gui_style import GUIFRAME_ID 34 from sas.sascalc.dataloader.data_info import Detector35 from sas.sascalc.dataloader.data_info import Source36 from sas.sasgui.perspectives.fitting.pagestate import PageState37 42 from sas.sasgui.guiframe.CategoryInstaller import CategoryInstaller 38 43 from sas.sasgui.guiframe.documentation_window import DocumentationWindow 44 45 from .report_dialog import ReportDialog 46 from .utils import get_weight 39 47 40 48 logger = logging.getLogger(__name__) … … 155 163 self.disp_cb_dict = {} 156 164 157 # self.state = PageState( parent=parent)165 # self.state = PageState() 158 166 # dictionary containing list of models 159 167 self.model_list_box = {} … … 202 210 self.fitrange = True 203 211 # Create memento to save the current state 204 self.state = PageState(parent=self.parent, 205 model=self.model, data=self.data) 212 self.state = PageState(model=self.model, data=self.data) 206 213 # flag to determine if state has change 207 214 self.state_change = False … … 295 302 """ 296 303 x = np.linspace(start=self.qmin_x, stop=self.qmax_x, 297 304 num=self.npts_x, endpoint=True) 298 305 self.data = Data1D(x=x) 299 306 self.data.xaxis('\\rm{Q}', "A^{-1}") … … 321 328 322 329 x = np.logspace(start=qmin, stop=qmax, 323 330 num=self.npts_x, endpoint=True, base=10.0) 324 331 self.data = Data1D(x=x) 325 332 self.data.xaxis('\\rm{Q}', "A^{-1}") … … 510 517 self.state.manager = manager 511 518 512 def populate_box(self, model_ dict):519 def populate_box(self, model_list_box): 513 520 """ 514 521 Store list of model 515 522 516 :param model_dict: dictionary containing list of models 517 518 """ 519 self.model_list_box = model_dict 520 self.state.model_list_box = self.model_list_box 523 :param model_list_box: dictionary containing categorized models 524 """ 525 self.model_list_box = model_list_box 521 526 self.initialize_combox() 522 527 523 def set_model_dictionary(self, model_dict ):528 def set_model_dictionary(self, model_dictionary): 524 529 """ 525 530 Store a dictionary linking model name -> model object 526 531 527 :param model_dict : dictionary containing list ofmodels528 """ 529 self.model_dict = model_dict532 :param model_dictionary: dictionary containing all models 533 """ 534 self.model_dictionary = model_dictionary 530 535 531 536 def initialize_combox(self): … … 533 538 put default value in the combo box 534 539 """ 535 if self.model_list_box is not None and len(self.model_list_box) > 0:540 if self.model_list_box: 536 541 self._populate_box(self.structurebox, 537 542 self.model_list_box["Structure Factors"]) … … 632 637 # Get plot image from plotpanel 633 638 images, canvases = self.get_images() 634 # get the report dialog 635 self.state.report(images, canvases) 639 imgRAM, images, refs = self._build_plots_for_report(images, canvases) 640 641 # get the strings for report 642 report_str, text_str = self.state.report(fig_urls=refs) 643 644 # Show the dialog 645 report_list = [report_str, text_str, images] 646 dialog = ReportDialog(report_list, None, wx.ID_ANY, "") 647 dialog.Show() 648 649 def _build_plots_for_report(self, figs, canvases): 650 """ 651 Build image state that wx.html understand 652 by plotting, putting it into wx.FileSystem image object 653 """ 654 images = [] 655 refs = [] 656 657 # For no figures in the list, prepare empty plot 658 if figs is None or len(figs) == 0: 659 figs = [None] 660 661 # Loop over the list of figures 662 # use wx.MemoryFSHandler 663 imgRAM = wx.MemoryFSHandler() 664 for fig in figs: 665 if fig is not None: 666 ind = figs.index(fig) 667 canvas = canvases[ind] 668 669 # store the image in wx.FileSystem Object 670 wx.FileSystem.AddHandler(wx.MemoryFSHandler()) 671 672 # index of the fig 673 ind = figs.index(fig) 674 675 # AddFile, image can be retrieved with 'memory:filename' 676 name = 'img_fit%s.png' % ind 677 refs.append('memory:' + name) 678 imgRAM.AddFile(name, canvas.bitmap, wx.BITMAP_TYPE_PNG) 679 680 # append figs 681 images.append(fig) 682 683 return imgRAM, images, refs 684 636 685 637 686 def on_save(self, event): … … 855 904 self.state.disable_disp = self.disable_disp.GetValue() 856 905 857 self.state.smearer = copy.deepcopy(self.current_smearer)858 906 if hasattr(self, "enable_smearer"): 859 907 self.state.enable_smearer = \ … … 871 919 if len(self._disp_obj_dict) > 0: 872 920 for k, v in self._disp_obj_dict.iteritems(): 873 self.state. _disp_obj_dict[k] = v.type921 self.state.disp_obj_dict[k] = v.type 874 922 875 923 self.state.values = copy.deepcopy(self.values) … … 889 937 self.state.str_parameters) 890 938 self._copy_parameters_state(self.orientation_params, 891 939 self.state.orientation_params) 892 940 self._copy_parameters_state(self.orientation_params_disp, 893 941 self.state.orientation_params_disp) … … 920 968 self.state.disable_disp = self.disable_disp.GetValue() 921 969 922 self.state.smearer = copy.deepcopy(self.current_smearer)923 970 if hasattr(self, "enable_smearer"): 924 971 self.state.enable_smearer = \ … … 944 991 try: 945 992 self.state.disp_cb_dict[k] = v.GetValue() 946 except :993 except Exception: 947 994 self.state.disp_cb_dict[k] = None 948 995 if len(self._disp_obj_dict) > 0: 949 996 for k, v in self._disp_obj_dict.iteritems(): 950 self.state. _disp_obj_dict[k] = v.type997 self.state.disp_obj_dict[k] = v.type 951 998 952 999 self.state.values = copy.deepcopy(self.values) … … 990 1037 # to support older version 991 1038 category_pos = int(state.categorycombobox) 992 except :1039 except Exception: 993 1040 category_pos = 0 994 1041 for ind_cat in range(self.categorybox.GetCount()): … … 1002 1049 # to support older version 1003 1050 formfactor_pos = int(state.formfactorcombobox) 1004 except :1051 except Exception: 1005 1052 formfactor_pos = 0 1006 1053 for ind_form in range(self.formfactorbox.GetCount()): … … 1015 1062 # to support older version 1016 1063 structfactor_pos = int(state.structurecombobox) 1017 except :1064 except Exception: 1018 1065 structfactor_pos = 0 1019 1066 for ind_struct in range(self.structurebox.GetCount()): … … 1182 1229 self.categorybox.Select(category_pos) 1183 1230 self._show_combox(None) 1184 from models import PLUGIN_NAME_BASE 1185 if self.categorybox.GetValue() == CUSTOM_MODEL \ 1186 and PLUGIN_NAME_BASE not in state.formfactorcombobox: 1231 if (self.categorybox.GetValue() == CUSTOM_MODEL 1232 and PLUGIN_NAME_BASE not in state.formfactorcombobox): 1187 1233 state.formfactorcombobox = \ 1188 1234 PLUGIN_NAME_BASE + state.formfactorcombobox 1189 1235 formfactor_pos = 0 1190 1236 for ind_form in range(self.formfactorbox.GetCount()): 1191 if self.formfactorbox.GetString(ind_form) == \1192 (state.formfactorcombobox):1237 if (self.formfactorbox.GetString(ind_form) 1238 == state.formfactorcombobox): 1193 1239 formfactor_pos = int(ind_form) 1194 1240 break … … 1200 1246 state.structurecombobox = unicode(state.structurecombobox) 1201 1247 for ind_struct in range(self.structurebox.GetCount()): 1202 if self.structurebox.GetString(ind_struct) == \1203 (state.structurecombobox):1248 if (self.structurebox.GetString(ind_struct) 1249 == state.structurecombobox): 1204 1250 structfactor_pos = int(ind_struct) 1205 1251 break … … 1252 1298 self.dI_sqrdata.SetValue(state.dI_sqrdata) 1253 1299 self.dI_idata.SetValue(state.dI_idata) 1254 except :1300 except Exception: 1255 1301 # to support older state file formats 1256 1302 self.dI_noweight.SetValue(False) … … 1308 1354 self.weights = copy.deepcopy(state.weights) 1309 1355 1310 for key, disp_type in state. _disp_obj_dict.iteritems():1356 for key, disp_type in state.disp_obj_dict.iteritems(): 1311 1357 # disp_model = disp 1312 1358 disp_model = POLYDISPERSITY_MODELS[disp_type]() … … 1542 1588 try: 1543 1589 self.npts_x = float(self.Npts_total.GetValue()) 1544 except :1590 except Exception: 1545 1591 flag = False 1546 1592 return flag … … 1583 1629 return 1584 1630 1585 for j in range(len(listtorestore)):1631 for item_page in listtorestore: 1586 1632 for param in statelist: 1587 if param[1] == listtorestore[j][1]: 1588 item_page = listtorestore[j] 1633 if param[1] == item_page[1]: 1589 1634 item_page_info = param 1590 1635 if (item_page_info[1] == "theta" or item_page_info[1] == … … 1632 1677 listtorestore = copy.deepcopy(statelist) 1633 1678 1634 for j in range(len(listtorestore)): 1635 item_page = listtorestore[j] 1636 item_page_info = statelist[j] 1679 for item_page, item_page_info in zip(listtorestore, statelist): 1637 1680 # change the state of the check box for simple parameters 1638 1639 1681 if item_page[0] is not None: 1640 1682 item_page[0].SetValue(format_number(item_page_info[0], True)) … … 1741 1783 temp_smear = self.current_smearer 1742 1784 # compute weight for the current data 1743 from sas.sasgui.perspectives.fitting.utils import get_weight1744 1785 flag = self.get_weight_flag() 1745 1786 weight = get_weight(data=self.data, is2d=self._is_2D(), flag=flag) … … 1768 1809 1769 1810 from sas.sasgui.plottools import Data1D as pf_data1d 1770 # from sas.sasgui.perspectives.theory.profile_dialog import SLDPanel1771 1811 from sas.sasgui.guiframe.local_perspectives.plotting.profile_dialog \ 1772 1812 import SLDPanel … … 1829 1869 if mod_cat == CUSTOM_MODEL: 1830 1870 for model in self.model_list_box[mod_cat]: 1831 m_list.append(self.model_dict [model.name])1871 m_list.append(self.model_dictionary[model.name]) 1832 1872 else: 1833 1873 cat_dic = self.master_category_dict[mod_cat] 1834 for (model, enabled)in cat_dic:1874 for model, enabled in cat_dic: 1835 1875 if enabled: 1836 m_list.append(self.model_dict [model])1876 m_list.append(self.model_dictionary[model]) 1837 1877 except Exception: 1838 1878 msg = traceback.format_exc() … … 1906 1946 wx.PostEvent(self.parent, StatusEvent(status=msg)) 1907 1947 return 1908 except :1948 except Exception: 1909 1949 tcrtl.SetBackgroundColour("pink") 1910 1950 msg = "Model Error: wrong value entered: %s" % sys.exc_info()[1] … … 1963 2003 wx.PostEvent(self._manager.parent, StatusEvent(status=msg)) 1964 2004 return 1965 except :2005 except Exception: 1966 2006 tcrtl.SetBackgroundColour("pink") 1967 2007 msg = "Model Error: wrong value entered: %s" % sys.exc_info()[1] … … 2063 2103 2064 2104 if struct_factor is not None: 2065 from sasmodels.sasview_model import MultiplicationModel2066 2105 self.model = MultiplicationModel(form_factor(self.multi_factor), 2067 2106 struct_factor()) … … 2141 2180 # q value from qx and qy 2142 2181 radius = np.sqrt(data.qx_data * data.qx_data + 2143 2182 data.qy_data * data.qy_data) 2144 2183 # get unmasked index 2145 2184 index_data = (float(self.qmin.GetValue()) <= radius) & \ … … 2370 2409 put gaussian dispersity into current model 2371 2410 """ 2372 if len(self.param_toFit) > 0:2411 if self.param_toFit: 2373 2412 for item in self.fittable_param: 2374 2413 if item in self.param_toFit: … … 2385 2424 self.weights = {} 2386 2425 2387 # from sas.models.dispersion_models import GaussianDispersion 2388 from sasmodels.weights import GaussianDispersion 2389 if len(self.disp_cb_dict) == 0: 2390 self.save_current_state() 2426 if not self.disp_cb_dict: 2391 2427 self.sizer4_4.Clear(True) 2392 self.Layout() 2393 return 2394 if (len(self.disp_cb_dict) > 0): 2428 else: 2395 2429 for p in self.disp_cb_dict: 2396 2430 # The parameter was un-selected. … … 2465 2499 self._disp_obj_dict[name1] = disp_model 2466 2500 self.model.set_dispersion(param_name, disp_model) 2467 self.state. _disp_obj_dict[name1] = disp_model.type2501 self.state.disp_obj_dict[name1] = disp_model.type 2468 2502 2469 2503 value1 = str(format_number(self.model.getParam(name1), True)) … … 2580 2614 self._disp_obj_dict[name] = disp 2581 2615 self.model.set_dispersion(name.split('.')[0], disp) 2582 self.state. _disp_obj_dict[name] = disp.type2616 self.state.disp_obj_dict[name] = disp.type 2583 2617 self.values[name] = values 2584 2618 self.weights[name] = weights … … 2938 2972 # go through the parameters 2939 2973 strings = self._get_copy_helper(self.parameters, 2940 self.orientation_params)2974 self.orientation_params) 2941 2975 content += strings 2942 2976 2943 2977 # go through the fittables 2944 2978 strings = self._get_copy_helper(self.fittable_param, 2945 self.orientation_params_disp)2979 self.orientation_params_disp) 2946 2980 content += strings 2947 2981 2948 2982 # go through the fixed params 2949 2983 strings = self._get_copy_helper(self.fixed_param, 2950 self.orientation_params_disp)2984 self.orientation_params_disp) 2951 2985 content += strings 2952 2986 2953 2987 # go through the str params 2954 2988 strings = self._get_copy_helper(self.str_parameters, 2955 self.orientation_params)2989 self.orientation_params) 2956 2990 content += strings 2957 2991 return content … … 2966 3000 the names of parameters that have been fitted 2967 3001 2968 :returns: all_params - A list of all parameters, in the format of 3002 :returns: all_params - A list of all parameters, in the format of 2969 3003 self.parameters 2970 3004 :returns: fitted_par_names - A list of the names of parameters that have … … 3043 3077 # Only print errors for fitted parameters 3044 3078 content += param[4].GetValue() 3045 content += tab 3079 content += tab 3046 3080 3047 3081 return content … … 3063 3097 # Do nothing if self.parameters doesn't exist 3064 3098 return False 3065 3066 content = '\\begin{table}'3067 content += '\\begin{tabular}[h]'3099 3100 content = r'\begin{table}' 3101 content += r'\begin{tabular}[h]' 3068 3102 3069 3103 crlf = chr(13) + chr(10) … … 3075 3109 for param in all_params: 3076 3110 content += 'l|l|' 3077 content += '}\hline'3111 content += r'}\hline' 3078 3112 content += crlf 3079 3113 … … 3081 3115 for index, param in enumerate(all_params): 3082 3116 name = param[1] # Parameter name 3083 content += name.replace('_', '\_') # Escape underscores3117 content += name.replace('_', r'\_') # Escape underscores 3084 3118 if name in fitted_param_names: 3085 3119 # Only print errors for fitted parameters 3086 3120 content += ' & ' 3087 content += name.replace('_', '\_') +"\_err"3121 content += name.replace('_', r'\_') + r"\_err" 3088 3122 if index < len(all_params) - 1: 3089 3123 content += ' & ' 3090 3124 3091 content += '\\\\ \\hline'3125 content += r'\\ \hline' 3092 3126 content += crlf 3093 3127 … … 3108 3142 if index < len(all_params) - 1: 3109 3143 content += ' & ' 3110 3111 content += '\\\\ \\hline'3144 3145 content += r'\\ \hline' 3112 3146 content += crlf 3113 content += '\\end{tabular}'3114 content += '\\end{table}'3147 content += r'\end{tabular}' 3148 content += r'\end{table}' 3115 3149 3116 3150 return content … … 3369 3403 if name.endswith('.npts'): 3370 3404 pd = int(pd) 3371 except :3405 except Exception: 3372 3406 # continue 3373 3407 if not pd and pd != '': … … 3455 3489 self._disp_obj_dict[name] = disp_model 3456 3490 self.model.set_dispersion(param_name, disp_model) 3457 self.state. _disp_obj_dict[name] = disp_model.type3491 self.state.disp_obj_dict[name] = disp_model.type 3458 3492 # TODO: It's not an array, why update values and weights? 3459 3493 self.model._persistency_dict[param_name] = \ … … 3555 3589 self.model_box.Clear() 3556 3590 3557 if category == 'Plugin Models':3591 if category == CUSTOM_MODEL: 3558 3592 for model in self.model_list_box[category]: 3559 3593 str_m = str(model).split(".")[0] … … 3561 3595 3562 3596 else: 3563 for (model, enabled)in sorted(self.master_category_dict[category],3564 3565 if (enabled):3597 for model, enabled in sorted(self.master_category_dict[category], 3598 key=lambda name: name[0]): 3599 if enabled: 3566 3600 self.model_box.Append(model) 3567 3601 … … 3804 3838 self.Bind(wx.EVT_SET_FOCUS, self._on_set_focus) 3805 3839 self.Bind(wx.EVT_KILL_FOCUS, self._silent_kill_focus 3806 if kill_focus_callback is None else kill_focus_callback)3840 if kill_focus_callback is None else kill_focus_callback) 3807 3841 self.Bind(wx.EVT_TEXT_ENTER, parent._onparamEnter 3808 if text_enter_callback is None else text_enter_callback)3842 if text_enter_callback is None else text_enter_callback) 3809 3843 if not ON_MAC: 3810 3844 self.Bind(wx.EVT_LEFT_UP, self._highlight_text 3811 if mouse_up_callback is None else mouse_up_callback)3845 if mouse_up_callback is None else mouse_up_callback) 3812 3846 3813 3847 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
r48154abb r48154abb 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 … … 1726 1733 ind = 0 1727 1734 while(ind < len(list)): 1728 for key, val in list.ite ritems():1729 if (val == ind):1735 for key, val in list.items(): 1736 if val == ind: 1730 1737 fun_box.Append(key, val) 1731 1738 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 r9706d88 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 from sas.sasgui.perspectives.calculator.pyconsole import PyConsole 54 55 from .fitting_widgets import DataDialog 56 from .fit_thread import FitThread 57 from .fitpage import Chi2UpdateEvent 58 from .console import ConsoleUpdate 59 from .fitproblem import FitProblemDictionary 60 from .fitpanel import FitPanel 61 from .model_thread import Calc1D, Calc2D 62 from .resultpanel import ResultPanel, PlotResultEvent 63 from .gpu_options import GpuOptions 52 64 53 65 logger = logging.getLogger(__name__) … … 63 75 ON_MAC = True 64 76 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 77 73 78 class Plugin(PluginBase): … … 240 245 event_id = event.GetId() 241 246 label = self.edit_menu.GetLabel(event_id) 242 from sas.sasgui.perspectives.calculator.pyconsole import PyConsole243 247 filename = os.path.join(models.find_plugins_dir(), label) 244 248 frame = PyConsole(parent=self.parent, manager=self, … … 290 294 break 291 295 except Exception: 292 import traceback;traceback.print_exc()296 traceback.print_exc() 293 297 msg = 'Delete Error: \nCould not delete the file; Check if in use.' 294 298 wx.MessageBox(msg, 'Error') … … 300 304 event_id = event.GetId() 301 305 model_manager = models.ModelManager() 302 model_list = model_manager. get_model_name_list()306 model_list = model_manager.composable_models() 303 307 plug_dir = models.find_plugins_dir() 304 308 textdial = TextDialog(None, self, wx.ID_ANY, 'Easy Sum/Multi(p1, p2) Editor', … … 340 344 self.set_edit_menu_helper(self.parent, self.edit_custom_model) 341 345 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: 346 new_pmodel_list = self.fit_panel.reset_pmodel_list() 347 if not new_pmodel_list: 348 return 349 # Set the new plugin model list for all fit pages 350 for uid, page in self.fit_panel.opened_pages.iteritems(): 351 if hasattr(page, "formfactorbox"): 352 page.model_list_box = new_pmodel_list 353 mod_cat = page.categorybox.GetStringSelection() 354 if mod_cat == custom_model: 355 box = page.formfactorbox 356 model_name = box.GetValue() 357 model = (box.GetClientData(box.GetCurrentSelection()) 358 if model_name else None) 359 page._show_combox_helper() 360 new_index = box.FindString(model_name) 361 new_model = (box.GetClientData(new_index) 362 if new_index >= 0 else None) 363 if new_index >= 0: 364 box.SetStringSelection(model_name) 365 else: 366 box.SetStringSelection('') 367 if model and new_model != model: 368 page._on_select_model(keep_pars=True) 369 if hasattr(page, "structurebox"): 370 selected_name = page.structurebox.GetStringSelection() 371 372 page.structurebox.Clear() 373 page.initialize_combox() 374 375 index = page.structurebox.FindString(selected_name) 376 if index == -1: 377 index = 0 378 page.structurebox.SetSelection(index) 379 page._on_select_model() 380 except Exception: 371 381 logger.error("update_custom_combo: %s", sys.exc_value) 372 382 … … 378 388 #new_model_menu = wx.Menu() 379 389 self.edit_model_menu.Append(wx_id, 'New Plugin Model', 380 'Add a new model function')390 'Add a new model function') 381 391 wx.EVT_MENU(owner, wx_id, self.make_new_model) 382 392 … … 575 585 else: 576 586 if len(data_list) > MAX_NBR_DATA: 577 from fitting_widgets import DataDialog578 587 dlg = DataDialog(data_list=data_list, nb_data=MAX_NBR_DATA) 579 588 if dlg.ShowModal() == wx.ID_OK: … … 620 629 : param datainfo: data 621 630 """ 622 from pagestate import PageState623 from simfitpage import SimFitPageState624 631 if isinstance(state, PageState): 625 632 state = state.clone() 626 633 self.temp_state.append(state) 627 634 elif isinstance(state, SimFitPageState): 628 state.load_from_save_state(self) 635 if self.fit_panel.sim_page is None: 636 self.fit_panel.add_sim_page() 637 self.fit_panel.sim_page.load_from_save_state(state) 629 638 else: 630 639 self.temp_state = [] … … 661 670 self.parent.add_data(data_list={data.id: data}) 662 671 wx.PostEvent(self.parent, NewPlotEvent(plot=data, 663 672 title=data.title)) 664 673 #need to be fix later make sure we are sendind guiframe.data 665 674 #to panel … … 672 681 self.parent.add_data(data_list={data.id: data}) 673 682 wx.PostEvent(self.parent, NewPlotEvent(plot=data, 674 683 title=data.title)) 675 684 page = self.add_fit_page([data]) 676 685 caption = page.window_caption 677 686 self.store_data(uid=page.uid, data_list=page.get_data_list(), 678 caption=caption)687 caption=caption) 679 688 self.mypanels.append(page) 680 689 … … 793 802 """ 794 803 if item.find(".") >= 0: 795 param_names = re.split( "\.", item)804 param_names = re.split(r"\.", item) 796 805 model_name = param_names[0] 797 806 ##Assume max len is 3; eg., M0.radius.width … … 896 905 897 906 self.draw_model(model=model, data=data, page_id=uid, smearer=smear, 898 enable1D=enable1D, enable2D=enable2D,899 qmin=qmin, qmax=qmax, weight=weight)907 enable1D=enable1D, enable2D=enable2D, 908 qmin=qmin, qmax=qmax, weight=weight) 900 909 901 910 def draw_model(self, model, page_id, data=None, smearer=None, … … 940 949 ## draw model 2D with no initial data 941 950 self._draw_model2D(model=model, 942 943 944 945 946 947 948 949 950 951 952 953 951 page_id=page_id, 952 data=data, 953 enable2D=enable2D, 954 smearer=smearer, 955 qmin=qmin, 956 qmax=qmax, 957 fid=fid, 958 weight=weight, 959 state=state, 960 toggle_mode_on=toggle_mode_on, 961 update_chisqr=update_chisqr, 962 source=source) 954 963 955 964 def onFit(self, uid): … … 960 969 :param uid: id related to the panel currently calling this fit function. 961 970 """ 962 if uid is None: raise RuntimeError("no page to fit") # Should never happen 971 if uid is None: 972 raise RuntimeError("no page to fit") # Should never happen 963 973 964 974 sim_page_uid = getattr(self.sim_page, 'uid', None) … … 994 1004 page = self.fit_panel.get_page_by_id(page_id) 995 1005 self.set_fit_weight(uid=page.uid, 996 flag=page.get_weight_flag(),997 is2d=page._is_2D())1006 flag=page.get_weight_flag(), 1007 is2d=page._is_2D()) 998 1008 if not page.param_toFit: 999 1009 msg = "No fitting parameters for %s" % page.window_caption … … 1019 1029 fitter = sim_fitter 1020 1030 self._add_problem_to_fit(fitproblem=fitproblem, 1021 pars=pars,1022 fitter=fitter,1023 fit_id=fit_id)1031 pars=pars, 1032 fitter=fitter, 1033 fit_id=fit_id) 1024 1034 fit_id += 1 1025 1035 list_page_id.append(page_id) … … 1068 1078 ## Perform more than 1 fit at the time 1069 1079 calc_fit = FitThread(handler=handler, 1070 1071 1072 1073 1074 1075 1080 fn=fitter_list, 1081 batch_inputs=batch_inputs, 1082 batch_outputs=batch_outputs, 1083 page_id=list_page_id, 1084 updatefn=handler.update_fit, 1085 completefn=self._fit_completed) 1076 1086 #self.fit_thread_list[current_page_id] = calc_fit 1077 1087 self.fit_thread_list[uid] = calc_fit … … 1134 1144 evt = StatusEvent(status=msg, info="warning") 1135 1145 wx.PostEvent(self.parent, evt) 1136 except :1146 except Exception: 1137 1147 msg = "Creating Fit page: %s" % sys.exc_value 1138 1148 wx.PostEvent(self.parent, StatusEvent(status=msg, info="error")) … … 1158 1168 group_id = str(page.uid) + " Model1D" 1159 1169 wx.PostEvent(self.parent, 1160 NewPlotEvent(group_id=group_id,1161 1170 NewPlotEvent(group_id=group_id, 1171 action="delete")) 1162 1172 self.parent.update_data(prev_data=theory_data, 1163 1173 new_data=data) 1164 1174 else: 1165 1175 if theory_data is not None: … … 1167 1177 data.group_id = theory_data.group_id 1168 1178 wx.PostEvent(self.parent, 1169 NewPlotEvent(group_id=group_id,1170 1179 NewPlotEvent(group_id=group_id, 1180 action="delete")) 1171 1181 self.parent.update_data(prev_data=theory_data, 1172 1182 new_data=data) 1173 1183 self.store_data(uid=page.uid, data_list=page.get_data_list(), 1174 1184 caption=page.window_caption) … … 1479 1489 if "Data" not in batch_outputs.keys(): 1480 1490 batch_outputs["Data"] = [] 1481 from sas.sasgui.guiframe.data_processor import BatchCell1482 1491 cell = BatchCell() 1483 1492 cell.label = data.name … … 1579 1588 except KeyboardInterrupt: 1580 1589 fit_msg += "\nSingular point: Fitting stopped." 1581 except :1590 except Exception: 1582 1591 fit_msg += "\nSingular point: Fitting error occurred." 1583 1592 if fit_msg: 1584 evt = StatusEvent(status=fit_msg, info="warning", type="stop")1585 wx.PostEvent(self.parent, evt)1586 1587 except :1593 evt = StatusEvent(status=fit_msg, info="warning", type="stop") 1594 wx.PostEvent(self.parent, evt) 1595 1596 except Exception: 1588 1597 msg = ("Fit completed but the following error occurred: %s" 1589 1598 % sys.exc_value) 1590 # import traceback;msg = "\n".join((traceback.format_exc(), msg))1599 #msg = "\n".join((traceback.format_exc(), msg)) 1591 1600 evt = StatusEvent(status=msg, info="warning", type="stop") 1592 1601 wx.PostEvent(self.parent, evt) … … 1743 1752 fid=data.id) 1744 1753 self.parent.update_theory(data_id=data.id, theory=new_plot, 1745 1754 state=state) 1746 1755 return new_plot 1747 1756 … … 1767 1776 # Create the new theories 1768 1777 if unsmeared_model is not None: 1769 unsmeared_model_plot = self.create_theory_1D(x, unsmeared_model, 1778 unsmeared_model_plot = self.create_theory_1D(x, unsmeared_model, 1770 1779 page_id, model, data, state, 1771 1780 data_description=model.name + " unsmeared", … … 1774 1783 1775 1784 if unsmeared_data is not None and unsmeared_error is not None: 1776 unsmeared_data_plot = self.create_theory_1D(x, unsmeared_data, 1785 unsmeared_data_plot = self.create_theory_1D(x, unsmeared_data, 1777 1786 page_id, model, data, state, 1778 1787 data_description="Data unsmeared", … … 1792 1801 plots_to_update.append(pq_plot) 1793 1802 # Update the P(Q), S(Q) and unsmeared theory plots if they exist 1794 wx.PostEvent(self.parent, NewPlotEvent(plots=plots_to_update, 1803 wx.PostEvent(self.parent, NewPlotEvent(plots=plots_to_update, 1795 1804 action='update')) 1796 1805 … … 1808 1817 1809 1818 self.page_finder[page_id].set_theory_data(data=new_plot, 1810 1819 fid=data.id) 1811 1820 if toggle_mode_on: 1812 1821 wx.PostEvent(self.parent, 1813 1822 NewPlotEvent(group_id=str(page_id) + " Model2D", 1814 1823 action="Hide")) 1815 1824 else: 1816 1825 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))) 1826 output = self._cal_chisqr(data=data, 1827 fid=fid, 1828 weight=weight, 1829 page_id=page_id, 1830 index=index) 1831 wx.PostEvent(current_pg, Chi2UpdateEvent(output=output)) 1824 1832 else: 1825 1833 self._plot_residuals(page_id=page_id, data=data, fid=fid, … … 1829 1837 logger.error("Using the present parameters the model does not return any finite value. ") 1830 1838 msg = "Computing Error: Model did not return any finite value." 1831 wx.PostEvent(self.parent, StatusEvent(status =msg, info="error"))1839 wx.PostEvent(self.parent, StatusEvent(status=msg, info="error")) 1832 1840 else: 1833 1841 msg = "Computation completed!" … … 1854 1862 1855 1863 def _complete2D(self, image, data, model, page_id, elapsed, index, qmin, 1856 qmax, fid=None, weight=None, toggle_mode_on=False, state=None,1857 1864 qmax, fid=None, weight=None, toggle_mode_on=False, state=None, 1865 update_chisqr=True, source='model', plot_result=True): 1858 1866 """ 1859 1867 Complete get the result of modelthread and create model 2D … … 1896 1904 fid=data.id) 1897 1905 self.parent.update_theory(data_id=data.id, 1898 1899 1906 theory=new_plot, 1907 state=state) 1900 1908 current_pg = self.fit_panel.get_page_by_id(page_id) 1901 1909 title = new_plot.title 1902 1910 if not source == 'fit' and plot_result: 1903 wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot, 1904 title=title)) 1911 wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot, title=title)) 1905 1912 if toggle_mode_on: 1906 1913 wx.PostEvent(self.parent, 1907 1908 1914 NewPlotEvent(group_id=str(page_id) + " Model1D", 1915 action="Hide")) 1909 1916 else: 1910 1917 # Chisqr in fitpage 1911 1918 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)))1919 output = self._cal_chisqr(data=data, 1920 weight=weight, 1921 fid=fid, 1922 page_id=page_id, 1923 index=index) 1924 wx.PostEvent(current_pg, Chi2UpdateEvent(output=output)) 1918 1925 else: 1919 1926 self._plot_residuals(page_id=page_id, data=data, fid=fid, 1920 1927 index=index, weight=weight) 1921 1928 1922 1929 if not number_finite: 1923 1930 logger.error("Using the present parameters the model does not return any finite value. ") 1924 1931 msg = "Computing Error: Model did not return any finite value." 1925 wx.PostEvent(self.parent, StatusEvent(status =msg, info="error"))1932 wx.PostEvent(self.parent, StatusEvent(status=msg, info="error")) 1926 1933 else: 1927 1934 msg = "Computation completed!" … … 1939 1946 weight=None, 1940 1947 toggle_mode_on=False, 1941 1948 update_chisqr=True, source='model'): 1942 1949 """ 1943 1950 draw model in 2D … … 1954 1961 return None 1955 1962 try: 1956 from model_thread import Calc2D1957 1963 ## If a thread is already started, stop it 1958 1964 if (self.calc_2D is not None) and self.calc_2D.isrunning(): … … 1986 1992 def _draw_model1D(self, model, page_id, data, 1987 1993 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): 1994 state=None, weight=None, fid=None, 1995 toggle_mode_on=False, update_chisqr=True, source='model', 1996 enable1D=True): 1993 1997 """ 1994 1998 Draw model 1D from loaded data1D … … 2001 2005 return 2002 2006 try: 2003 from model_thread import Calc1D2004 2007 ## If a thread is already started, stop it 2005 2008 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 r69a6897 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() … … 74 57 75 58 fName = dlg.GetPath() 59 basename = os.path.splitext(fName)[0] 76 60 ext_num = dlg.GetFilterIndex() 61 dlg.Destroy() 62 63 if ext_num == 0 and self.index_offset == 0: # has pdf 64 ext = ".pdf" 65 elif ext_num == 1 - self.index_offset: 66 ext = ".html" 67 elif ext_num == 2 - self.index_offset: 68 ext = ".txt" 69 else: 70 logger.warn("unknown export format in report dialog") 71 return 72 filename = basename + ext 73 74 # save figures 75 pictures = [] 76 for num in range(self.nimages): 77 pic_name = basename + '_img%s.png' % num 78 # save the image for use with pdf writer 79 self.report_list[2][num].savefig(pic_name) 80 pictures.append(pic_name) 81 82 # translate png references int html from in-memory name to on-disk name 83 html = self.report_html.replace("memory:img_fit", basename+'_img') 77 84 78 85 #set file extensions 79 86 img_ext = [] 80 pic_fname = [] 81 #PDF 82 if ext_num == (0 + 2 * self.index_offset): 83 # TODO: Sort this case out 84 ext = '.pdf' 87 if ext == ".pdf": 88 # write pdf as a pdf file 89 pdf = self.HTML2PDF(data=html, filename=filename) 85 90 86 fName = os.path.splitext(fName)[0] + ext 87 dlg.Destroy() 88 #pic (png) file path/name 89 for num in range(self.nimages): 90 im_ext = '_img%s.png' % num 91 #img_ext.append(im_ext) 92 pic_name = os.path.splitext(fName)[0] + im_ext 93 pic_fname.append(pic_name) 94 # save the image for use with pdf writer 95 self.report_list[2][num].savefig(pic_name) 91 # delete images used to create the pdf 92 for pic_name in pictures: 93 os.remove(pic_name) 96 94 97 #put the image path in html string 98 report_frame = self.report_list[0] 99 #put image name strings into the html file 100 #Note:The str for pic_fname shouldn't be removed. 101 if self.nimages == 1: 102 html = report_frame % str(pic_fname[0]) 103 elif self.nimages == 2: 104 html = report_frame % (str(pic_fname[0]), str(pic_fname[1])) 105 elif self.nimages == 3: 106 html = report_frame % (str(pic_fname[0]), str(pic_fname[1]), 107 str(pic_fname[2])) 108 109 # make/open file in case of absence 110 f = open(fName, 'w') 111 f.close() 112 # write pdf as a pdf file 113 pdf = self.HTML2PDF(data=html, filename=fName) 114 115 #open pdf 95 #open pdf viewer 116 96 if pdf: 117 97 try: 118 #Windows 119 os.startfile(str(fName)) 120 except: 121 try: 122 #Mac 98 if os.name == 'nt': # Windows 99 os.startfile(fName) 100 elif sys.platform == "darwin": # Mac 123 101 os.system("open %s" % fName) 124 except: 125 #DO not open 126 pass 127 #delete image file 128 for num in range(self.nimages): 129 os.remove(pic_fname[num]) 130 return 131 #HTML + png(graph) 132 elif ext_num == (1 - self.index_offset): 133 ext = '.html' 134 for num in range(self.nimages): 135 img_ext.append('_img4html%s.png' % num) 136 report_frame = self.report_list[0] 137 #TEXT + pdf(graph) 138 elif ext_num == (2 - self.index_offset): 139 ext = '.txt' 140 # changing the image extension actually changes the image 141 # format on saving 142 for num in range(self.nimages): 143 img_ext.append('_img4txt%s.pdf' % num) 144 report = self.report_list[1] 145 else: 146 return 102 except Exception as exc: 103 # cannot open pdf 104 logging.error(str(exc)) 147 105 148 #file name149 fName = os.path.splitext(fName)[0] + ext150 dlg.Destroy()106 elif ext == ".html": 107 with open(filename, 'w') as f: 108 f.write(html) 151 109 152 #pic (png) file path/name 153 for num in range(self.nimages): 154 pic_name = os.path.splitext(fName)[0] + img_ext[num] 155 pic_fname.append(pic_name) 156 #put the image path in html string 157 if ext_num == (1 - self.index_offset): 158 if self.nimages == 1: 159 report = report_frame % os.path.basename(pic_fname[0]) 160 elif self.nimages == 2: 161 report = report_frame % (os.path.basename(pic_fname[0]), 162 os.path.basename(pic_fname[1])) 163 elif self.nimages == 3: 164 report = report_frame % (os.path.basename(pic_fname[0]), 165 os.path.basename(pic_fname[1]), 166 os.path.basename(pic_fname[2])) 167 f = open(fName, 'w') 168 f.write(report) 169 f.close() 110 elif ext == ".txt": 111 with open(filename, 'w') as f: 112 f.write(self.report_list[1]) 113 170 114 self.Update() 171 #save png file using pic_fname172 for num in range(self.nimages):173 self.report_list[2][num].savefig(pic_fname[num]) -
src/sas/sasgui/perspectives/fitting/simfitpage.py
rf73b47c r24d9e84 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 init_map = {} 166 final_map = {} 167 # Process each model and associate old M# with new M# 168 i = 0 169 for model in self.model_list: 170 model_id = self._format_id(model[1].keys()[0]) 171 for saved_model in sim_state.model_list: 172 save_id = saved_model.pop('name') 173 saved_model['name'] = save_id 174 save_id = self._format_id(save_id) 175 if save_id == model_id: 176 model_map[saved_model.pop('fit_page_source')] = \ 177 model[3].name 178 check = bool(saved_model.pop('checked')) 179 self.model_list[i][0].SetValue(check) 180 inter_id = str(i)*5 181 init_map[saved_model.pop('fit_page_source')] = inter_id 182 final_map[inter_id] = model[3].name 183 check = bool(saved_model.pop('checked')) 184 self.model_list[i][0].SetValue(check) 185 break 186 i += 1 187 188 self.check_model_name(None) 189 190 if len(sim_state.constraints_list) > 0: 191 self.hide_constraint.SetValue(False) 192 self.show_constraint.SetValue(True) 193 self._display_constraint(None) 194 195 for index, item in enumerate(sim_state.constraints_list): 196 model_cbox = item.pop('model_cbox') 197 if model_cbox != "": 198 constraint_value = item.pop('constraint') 199 param = item.pop('param_cbox') 200 equality = item.pop('egal_txt') 201 for key, value in init_map.items(): 202 model_cbox = model_cbox.replace(key, value) 203 constraint_value = constraint_value.replace(key, value) 204 for key, value in final_map.items(): 205 model_cbox = model_cbox.replace(key, value) 206 constraint_value = constraint_value.replace(key, value) 207 208 self.constraints_list[index][0].SetValue(model_cbox) 209 self._on_select_model(None) 210 self.constraints_list[index][1].SetValue(param) 211 self.constraints_list[index][2].SetLabel(equality) 212 self.constraints_list[index][3].SetValue(constraint_value) 213 self._on_add_constraint(None) 214 self._manager.sim_page = self 215 216 def _format_id(self, original_id): 217 original_id = original_id.rstrip('1234567890.') 218 new_id_list = original_id.split() 219 new_id = ' '.join(new_id_list) 220 return new_id 221 222 223 159 224 def draw_page(self): 160 225 """ 161 226 Construct the Simultaneous/Constrained fit page. fills the first 162 region (sizer1) with the list of available fit page pairs of data 227 region (sizer1) with the list of available fit page pairs of data 163 228 and models. Then fills sizer2 with the checkbox for adding 164 229 constraints, and finally fills sizer3 with the fit button and … … 1043 1108 cbox.Append(name, value) 1044 1109 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 init_map = {}1076 final_map = {}1077 if fit.fit_panel.sim_page is None:1078 fit.fit_panel.add_sim_page()1079 sim_page = fit.fit_panel.sim_page1080 1081 # Process each model and associate old M# with new M#1082 i = 01083 for model in sim_page.model_list:1084 model_id = self._format_id(model[1].keys()[0])1085 for saved_model in self.model_list:1086 save_id = saved_model.pop('name')1087 saved_model['name'] = save_id1088 save_id = self._format_id(save_id)1089 if save_id == model_id:1090 inter_id = str(i) + str(i) + str(i) + str(i) + str(i)1091 init_map[saved_model.pop('fit_page_source')] = inter_id1092 final_map[inter_id] = model[3].name1093 check = bool(saved_model.pop('checked'))1094 sim_page.model_list[i][0].SetValue(check)1095 break1096 i += 11097 sim_page.check_model_name(None)1098 1099 if len(self.constraints_list) > 0:1100 sim_page.hide_constraint.SetValue(False)1101 sim_page.show_constraint.SetValue(True)1102 sim_page._display_constraint(None)1103 1104 for index, item in enumerate(self.constraints_list):1105 model_cbox = item.pop('model_cbox')1106 if model_cbox != "":1107 constraint_value = item.pop('constraint')1108 param = item.pop('param_cbox')1109 equality = item.pop('egal_txt')1110 for key, value in init_map.items():1111 model_cbox = model_cbox.replace(key, value)1112 constraint_value = constraint_value.replace(key, value)1113 for key, value in final_map.items():1114 model_cbox = model_cbox.replace(key, value)1115 constraint_value = constraint_value.replace(key, value)1116 1117 sim_page.constraints_list[index][0].SetValue(model_cbox)1118 sim_page._on_select_model(None)1119 sim_page.constraints_list[index][1].SetValue(param)1120 sim_page.constraints_list[index][2].SetLabel(equality)1121 sim_page.constraints_list[index][3].SetValue(constraint_value)1122 sim_page._on_add_constraint(None)1123 sim_page._manager.sim_page = sim_page1124 1125 def _format_id(self, original_id):1126 original_id = original_id.rstrip('1234567890.')1127 new_id_list = original_id.split()1128 new_id = ' '.join(new_id_list)1129 return new_id -
src/sas/sasview/local_config.py
rc6bdb3b rb963b20 145 145 UPDATE_TIMEOUT = 2 146 146 147 #OpenCL option148 SAS_OPENCL = None149 150 147 # Time out for updating sasview 151 148 UPDATE_TIMEOUT = 2 -
src/sas/sasview/sasview.py
r1693141 rb277220 21 21 sys.setdefaultencoding("iso-8859-1") 22 22 23 import sas 24 23 25 APP_NAME = 'SasView' 24 26 PLUGIN_MODEL_DIR = 'plugin_models' … … 43 45 # modules. We load the fitting module here 44 46 # to ensure a complete Windows executable build. 47 48 # Rebuild .sasview/categories.json. This triggers a load of sasmodels 49 # and all the plugins. 50 try: 51 from sas.sascalc.fit.models import ModelManager 52 from sas.sasgui.guiframe.CategoryInstaller import CategoryInstaller 53 model_list = ModelManager().cat_model_list() 54 CategoryInstaller.check_install(model_list=model_list) 55 except Exception: 56 logger.error("%s: could not load SasView models") 57 logger.error(traceback.format_exc()) 45 58 46 59 # Fitting perspective … … 160 173 161 174 162 def setup_mpl(backend='WXAgg'): 163 import sas.sasgui 175 def setup_mpl(backend=None): 164 176 # Always use private .matplotlib setup to avoid conflicts with other 165 mplconfigdir = os.path.join(sas. sasgui.get_user_dir(), '.matplotlib')177 mplconfigdir = os.path.join(sas.get_user_dir(), '.matplotlib') 166 178 if not os.path.exists(mplconfigdir): 167 179 os.mkdir(mplconfigdir) … … 171 183 # we are running may not actually need it; also, putting as little on the 172 184 # path as we can 173 os.environ['MPLBACKEND'] = backend 185 if backend: 186 os.environ['MPLBACKEND'] = backend 174 187 175 188 # TODO: ... so much for not importing matplotlib unless we need it... … … 181 194 Prepare sasmodels for running within sasview. 182 195 """ 183 import sas.sasgui184 196 # Set SAS_MODELPATH so sasmodels can find our custom models 185 plugin_dir = os.path.join(sas. sasgui.get_user_dir(), PLUGIN_MODEL_DIR)197 plugin_dir = os.path.join(sas.get_user_dir(), PLUGIN_MODEL_DIR) 186 198 os.environ['SAS_MODELPATH'] = plugin_dir 187 # TODO: SAS_OPENCL flag belongs in setup_sasmodels 188 # this will require restructuring of the config management so that it 189 # can occur outside of sasgui. 199 #Initiliaze enviromental variable with custom setting but only if variable not set 200 SAS_OPENCL = sas.get_custom_config().SAS_OPENCL 201 if SAS_OPENCL and "SAS_OPENCL" not in os.environ: 202 os.environ["SAS_OPENCL"] = SAS_OPENCL 190 203 191 204 def run_gui(): … … 196 209 freeze_support() 197 210 setup_logging() 198 setup_mpl( )211 setup_mpl(backend='WXAgg') 199 212 setup_sasmodels() 200 213 setup_wx() … … 206 219 freeze_support() 207 220 setup_logging() 208 setup_mpl(backend='Agg') 221 # Use default matplotlib backend on mac/linux, but wx on windows. 222 # The problem on mac is that the wx backend requires pythonw. On windows 223 # we are sure to wx since it is the shipped with the app. 224 setup_mpl(backend='WXAgg' if os.name == 'nt' else None) 209 225 setup_sasmodels() 210 226 if len(sys.argv) == 1: -
src/sas/sasview/welcome_panel.py
rd66dbcc rb963b20 10 10 from wx.lib.scrolledpanel import ScrolledPanel 11 11 12 from sas .sasguiimport get_local_config12 from sas import get_local_config 13 13 from sas.sasgui.guiframe.panel_base import PanelBase 14 14 config = get_local_config()
Note: See TracChangeset
for help on using the changeset viewer.