Changeset 1f9f3c8a in sasview
- Timestamp:
- Apr 27, 2012 8:58:21 AM (13 years ago)
- Branches:
- master, ESS_GUI, ESS_GUI_Docs, ESS_GUI_batch_fitting, ESS_GUI_bumps_abstraction, ESS_GUI_iss1116, ESS_GUI_iss879, ESS_GUI_iss959, ESS_GUI_opencl, ESS_GUI_ordering, ESS_GUI_sync_sascalc, costrafo411, magnetic_scatt, release-4.1.1, release-4.1.2, release-4.2.2, release_4.0.1, ticket-1009, ticket-1094-headless, ticket-1242-2d-resolution, ticket-1243, ticket-1249, ticket885, unittest-saveload
- Children:
- 34f3ad0
- Parents:
- e1bc51d
- Location:
- park_integration/src/sans/fit
- Files:
-
- 2 deleted
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
park_integration/src/sans/fit/AbstractFitEngine.py
r06e7c26 r1f9f3c8a 8 8 from sans.dataloader.data_info import Data1D 9 9 from sans.dataloader.data_info import Data2D 10 import time11 10 _SMALLVALUE = 1.0e-10 12 11 … … 19 18 def __init__(self, name, model, data): 20 19 """ 21 :param name: the name of the model parameter 22 :param model: the sans model to wrap as a park model 23 20 :param name: the name of the model parameter 21 :param model: the sans model to wrap as a park model 24 22 """ 25 23 park.Parameter.__init__(self, name) … … 59 57 if lo is None: lo = -numpy.inf 60 58 if hi is None: hi = numpy.inf 61 #else:62 #lo,hi = self._model.details[self.name][1:]63 #if lo is None: lo = -numpy.inf64 #if hi is None: hi = numpy.inf65 59 if lo > hi: 66 raise ValueError, "wrong fit range for parameters"60 raise ValueError, "wrong fit range for parameters" 67 61 68 62 return lo, hi … … 82 76 self._model.details[self.name][1:3] = r 83 77 range = property(_getrange, _setrange) 78 84 79 85 80 class Model(park.Model): … … 100 95 #list of park parameter 101 96 self.parkp = [SansParameter(p, sans_model, sans_data) for p in self.sansp] 102 #list of parameter set97 #list of parameter set 103 98 self.parameterset = park.ParameterSet(sans_model.name, pars=self.parkp) 104 99 self.pars = [] … … 124 119 Set value for parameters to fit 125 120 126 :param params: list of value for parameters to fit 121 :param params: list of value for parameters to fit 127 122 128 123 """ … … 138 133 def eval(self, x): 139 134 """ 140 override eval method of park model. 141 142 :param x: the x value used to compute a function 143 135 Override eval method of park model. 136 137 :param x: the x value used to compute a function 144 138 """ 145 139 try: … … 162 156 return [] 163 157 164 165 158 166 159 class FitData1D(Data1D): 167 """ 168 Wrapper class for SANS data169 FitData1D inherits from DataLoader.data_info.Data1D. Implements170 a way to get residuals from data.160 """ 161 Wrapper class for SANS data 162 FitData1D inherits from DataLoader.data_info.Data1D. Implements 163 a way to get residuals from data. 171 164 """ 172 165 def __init__(self, x, y, dx=None, dy=None, smearer=None, data=None): 173 166 """ 174 :param smearer: is an object of class QSmearer or SlitSmearer 175 that will smear the theory data (slit smearing or resolution 176 smearing) when set. 177 178 The proper way to set the smearing object would be to 179 do the following: :: 180 181 from DataLoader.qsmearing import smear_selection 182 smearer = smear_selection(some_data) 183 fitdata1d = FitData1D( x= [1,3,..,], 184 y= [3,4,..,8], 185 dx=None, 186 dy=[1,2...], smearer= smearer) 187 188 :Note: that some_data _HAS_ to be of class DataLoader.data_info.Data1D 189 Setting it back to None will turn smearing off. 190 167 :param smearer: is an object of class QSmearer or SlitSmearer 168 that will smear the theory data (slit smearing or resolution 169 smearing) when set. 170 171 The proper way to set the smearing object would be to 172 do the following: :: 173 174 from DataLoader.qsmearing import smear_selection 175 smearer = smear_selection(some_data) 176 fitdata1d = FitData1D( x= [1,3,..,], 177 y= [3,4,..,8], 178 dx=None, 179 dy=[1,2...], smearer= smearer) 180 181 :Note: that some_data _HAS_ to be of 182 class DataLoader.data_info.Data1D 183 Setting it back to None will turn smearing off. 184 191 185 """ 192 186 Data1D.__init__(self, x=x, y=y, dx=dx, dy=dy) … … 199 193 # constant, or dy data 200 194 if dy == None or dy == [] or dy.all() == 0: 201 self.dy = numpy.ones(len(y)) 195 self.dy = numpy.ones(len(y)) 202 196 else: 203 197 self.dy = numpy.asarray(dy).copy() … … 205 199 ## Min Q-value 206 200 #Skip the Q=0 point, especially when y(q=0)=None at x[0]. 207 if min 201 if min(self.x) == 0.0 and self.x[0] == 0 and\ 208 202 not numpy.isfinite(self.y[0]): 209 self.qmin = min(self.x[self.x !=0])210 else: 203 self.qmin = min(self.x[self.x != 0]) 204 else: 211 205 self.qmin = min(self.x) 212 206 ## Max Q-value … … 227 221 if qmin == 0.0 and not numpy.isfinite(self.y[qmin]): 228 222 self.qmin = min(self.x[self.x != 0]) 229 elif qmin != None: 230 self.qmin = qmin 223 elif qmin != None: 224 self.qmin = qmin 231 225 if qmax != None: 232 226 self.qmax = qmax … … 234 228 # the smeared Q range 235 229 self._qmin_unsmeared = self.qmin 236 self._qmax_unsmeared = self.qmax 230 self._qmax_unsmeared = self.qmax 237 231 238 232 self._first_unsmeared_bin = 0 239 self._last_unsmeared_bin 233 self._last_unsmeared_bin = len(self.x) - 1 240 234 241 235 if self.smearer != None: … … 248 242 self.idx = (self.x >= self.qmin) & (self.x <= self.qmax) 249 243 ## zero error can not participate for fitting 250 self.idx = self.idx & (self.dy != 0) 244 self.idx = self.idx & (self.dy != 0) 251 245 self.idx_unsmeared = (self.x >= self._qmin_unsmeared) \ 252 246 & (self.x <= self._qmax_unsmeared) … … 254 248 def get_fit_range(self): 255 249 """ 256 return the range of data.x to fit250 Return the range of data.x to fit 257 251 """ 258 252 return self.qmin, self.qmax 259 253 260 254 def residuals(self, fn): 261 """ 262 Compute residuals. 263 264 If self.smearer has been set, use if to smear 265 the data before computing chi squared. 266 267 :param fn: function that return model value 268 269 :return: residuals 270 255 """ 256 Compute residuals. 257 258 If self.smearer has been set, use if to smear 259 the data before computing chi squared. 260 261 :param fn: function that return model value 262 263 :return: residuals 271 264 """ 272 265 # Compute theory data f(x) … … 276 269 ## Smear theory data 277 270 if self.smearer is not None: 278 fx = self.smearer(fx, self._first_unsmeared_bin, 271 fx = self.smearer(fx, self._first_unsmeared_bin, 279 272 self._last_unsmeared_bin) 280 273 ## Sanity check 281 274 if numpy.size(self.dy) != numpy.size(fx): 282 275 msg = "FitData1D: invalid error array " 283 msg += "%d <> %d" % (numpy.shape(self.dy), numpy.size(fx)) 284 raise RuntimeError, msg 276 msg += "%d <> %d" % (numpy.shape(self.dy), numpy.size(fx)) 277 raise RuntimeError, msg 285 278 return (self.y[self.idx] - fx[self.idx]) / self.dy[self.idx], fx[self.idx] 286 279 287 288 280 def residuals_deriv(self, model, pars=[]): 289 """ 290 :return: residuals derivatives . 291 292 :note: in this case just return empty array 293 281 """ 282 :return: residuals derivatives . 283 284 :note: in this case just return empty array 294 285 """ 295 286 return [] 296 287 288 297 289 class FitData2D(Data2D): 298 """ Wrapper class for SANS data """ 290 """ 291 Wrapper class for SANS data 292 """ 299 293 def __init__(self, sans_data2d, data=None, err_data=None): 300 294 Data2D.__init__(self, data=data, err_data=err_data) 301 295 """ 302 Data can be initital with a data (sans plottable)303 or with vectors.296 Data can be initital with a data (sans plottable) 297 or with vectors. 304 298 """ 305 299 self.res_err_image = [] … … 315 309 def set_data(self, sans_data2d, qmin=None, qmax=None): 316 310 """ 317 Determine the correct qx_data and qy_data within range to fit311 Determine the correct qx_data and qy_data within range to fit 318 312 """ 319 313 self.data = sans_data2d.data … … 341 335 342 336 # Note: mask = True: for MASK while mask = False for NOT to mask 343 self.idx = ((self.qmin <= self.radius) &\337 self.idx = ((self.qmin <= self.radius) &\ 344 338 (self.radius <= self.qmax)) 345 339 self.idx = (self.idx) & (self.mask) 346 340 self.idx = (self.idx) & (numpy.isfinite(self.data)) 347 341 348 def set_smearer(self, smearer): 349 """ 350 Set smearer342 def set_smearer(self, smearer): 343 """ 344 Set smearer 351 345 """ 352 346 if smearer == None: … … 357 351 358 352 def set_fit_range(self, qmin=None, qmax=None): 359 """ to set the fit range""" 353 """ 354 To set the fit range 355 """ 360 356 if qmin == 0.0: 361 357 self.qmin = 1e-16 362 elif qmin != None: 363 self.qmin = qmin 358 elif qmin != None: 359 self.qmin = qmin 364 360 if qmax != None: 365 self.qmax = qmax 361 self.qmax = qmax 366 362 self.radius = numpy.sqrt(self.qx_data**2 + self.qy_data**2) 367 self.idx = ((self.qmin <= self.radius) &\363 self.idx = ((self.qmin <= self.radius) &\ 368 364 (self.radius <= self.qmax)) 369 self.idx = (self.idx) & (self.mask)365 self.idx = (self.idx) & (self.mask) 370 366 self.idx = (self.idx) & (numpy.isfinite(self.data)) 371 367 self.idx = (self.idx) & (self.res_err_data != 0) … … 377 373 return self.qmin, self.qmax 378 374 379 def residuals(self, fn): 375 def residuals(self, fn): 380 376 """ 381 377 return the residuals 382 """ 378 """ 383 379 if self.smearer != None: 384 380 fn.set_index(self.idx) … … 386 382 fn.get_data() 387 383 388 gn = fn.get_value() 384 gn = fn.get_value() 389 385 else: 390 386 gn = fn([self.qx_data[self.idx], 391 387 self.qy_data[self.idx]]) 392 388 # use only the data point within ROI range 393 res = (self.data[self.idx] - gn) /self.res_err_data[self.idx]394 395 return res, gn 389 res = (self.data[self.idx] - gn) / self.res_err_data[self.idx] 390 391 return res, gn 396 392 397 393 def residuals_deriv(self, model, pars=[]): 398 """ 394 """ 399 395 :return: residuals derivatives . 400 396 … … 403 399 """ 404 400 return [] 401 405 402 406 403 class FitAbort(Exception): … … 416 413 Sans Assembly class a class wrapper to be call in optimizer.leastsq method 417 414 """ 418 def __init__(self, paramlist, model=None 415 def __init__(self, paramlist, model=None, data=None, fitresult=None, 419 416 handler=None, curr_thread=None, msg_q=None): 420 417 """ … … 424 421 """ 425 422 self.model = model 426 self.data 423 self.data = data 427 424 self.paramlist = paramlist 428 425 self.msg_q = msg_q … … 435 432 self.theory = None 436 433 437 #def chisq(self, params):438 434 def chisq(self): 439 435 """ … … 445 441 446 442 """ 447 sum= 0443 total = 0 448 444 for item in self.true_res: 449 sum+= item * item445 total += item * item 450 446 if len(self.true_res) == 0: 451 447 return None 452 return sum/ len(self.true_res)448 return total / len(self.true_res) 453 449 454 450 def __call__(self, params): 455 451 """ 456 Compute residuals 457 458 :param params: value of parameters to fit 459 460 """ 452 Compute residuals 453 :param params: value of parameters to fit 454 """ 461 455 #import thread 462 456 self.model.set_params(self.paramlist, params) … … 469 463 # just silent return res = inf 470 464 return self.res 471 self.res = self.true_res 465 self.res = self.true_res 472 466 473 467 if self.fitresult is not None: … … 488 482 self.handler.update_fit() 489 483 490 if self.curr_thread != None 484 if self.curr_thread != None: 491 485 try: 492 486 self.curr_thread.isquit() 493 487 except: 494 msg = "Fitting: Terminated... Note: Forcing to stop " 488 msg = "Fitting: Terminated... Note: Forcing to stop " 495 489 msg += "fitting may cause a 'Functor error message' " 496 490 msg += "being recorded in the log file....." 497 491 self.handler.error(msg) 498 492 raise 499 #return500 493 501 494 return self.res … … 521 514 # This value works on Scipy 522 515 # Do not change numbers below 523 value = _SMALLVALUE 516 value = _SMALLVALUE 524 517 else: 525 518 value = p.value 526 519 # For leastsq, it needs a bit step back from the boundary 527 val = p.range[0] - value * _SMALLVALUE 528 if p.value < val: 520 val = p.range[0] - value * _SMALLVALUE 521 if p.value < val: 529 522 self.res *= 1e+6 530 523 … … 535 528 # Do not change numbers below 536 529 if p.value == 0: 537 value = _SMALLVALUE 530 value = _SMALLVALUE 538 531 else: 539 532 value = p.value 540 533 # For leastsq, it needs a bit step back from the boundary 541 val = p.range[1] + value * _SMALLVALUE 534 val = p.range[1] + value * _SMALLVALUE 542 535 if p.value > val: 543 536 self.res *= 1e+6 … … 559 552 self.fitter_id = None 560 553 561 def set_model(self, model, id,pars=[], constraints=[], data=None):554 def set_model(self, model, id, pars=[], constraints=[], data=None): 562 555 """ 563 556 set a model on a given in the fit engine. … … 629 622 630 623 def set_data(self, data, id, smearer=None, qmin=None, qmax=None): 631 """ 624 """ 632 625 Receives plottable, creates a list of data to fit,set data 633 in a FitArrange object and adds that object in a dictionary 626 in a FitArrange object and adds that object in a dictionary 634 627 with key id. 635 628 636 629 :param data: data added 637 630 :param id: unique key corresponding to a fitArrange object with data 638 639 631 """ 640 632 if data.__class__.__name__ == 'Data2D': … … 642 634 err_data=data.err_data) 643 635 else: 644 fitdata = FitData1D(x=data.x, y=data.y 636 fitdata = FitData1D(x=data.x, y=data.y, 645 637 dx=data.dx, dy=data.dy, smearer=smearer) 646 638 fitdata.sans_data = data … … 648 640 fitdata.set_fit_range(qmin=qmin, qmax=qmax) 649 641 #A fitArrange is already created but contains model only at id 650 if self.fit_arrange_dict.has_key(id):642 if id in self.fit_arrange_dict: 651 643 self.fit_arrange_dict[id].add_data(fitdata) 652 644 else: … … 654 646 fitproblem = FitArrange() 655 647 fitproblem.add_data(fitdata) 656 self.fit_arrange_dict[id] = fitproblem 648 self.fit_arrange_dict[id] = fitproblem 657 649 658 650 def get_model(self, id): 659 """ 660 651 """ 661 652 :param id: id is key in the dictionary containing the model to return 662 653 663 :return: a model at this id or None if no FitArrange element was 654 :return: a model at this id or None if no FitArrange element was 664 655 created with this id 665 666 """ 667 if self.fit_arrange_dict.has_key(id): 656 """ 657 if id in self.fit_arrange_dict: 668 658 return self.fit_arrange_dict[id].get_model() 669 659 else: … … 672 662 def remove_fit_problem(self, id): 673 663 """remove fitarrange in id""" 674 if self.fit_arrange_dict.has_key(id):664 if id in self.fit_arrange_dict: 675 665 del self.fit_arrange_dict[id] 676 666 … … 680 670 and set in self.selected value to value 681 671 682 :param value: the value to allow fitting. 672 :param value: the value to allow fitting. 683 673 can only have the value one or zero 684 685 """ 686 if self.fit_arrange_dict.has_key(id): 674 """ 675 if id in self.fit_arrange_dict: 687 676 self.fit_arrange_dict[id].set_to_fit(value) 688 677 … … 692 681 693 682 :param id: the id of the problem 694 695 """ 696 if self.fit_arrange_dict.has_key(id): 683 """ 684 if id in self.fit_arrange_dict: 697 685 self.fit_arrange_dict[id].get_to_fit() 686 698 687 699 688 class FitArrange: … … 712 701 self.pars = [] 713 702 self.vals = [] 714 #self.selected is zero when this fit problem is not schedule to fit715 #self.selected is 1 when schedule to fit716 703 self.selected = 0 717 704 718 705 def set_model(self, model): 719 """ 706 """ 720 707 set_model save a copy of the model 721 708 722 709 :param model: the model being set 723 724 710 """ 725 711 self.model = model 726 712 727 713 def add_data(self, data): 728 """ 714 """ 729 715 add_data fill a self.data_list with data to fit 730 716 731 :param data: Data to add in the list 732 717 :param data: Data to add in the list 733 718 """ 734 719 if not data in self.data_list: … … 736 721 737 722 def get_model(self): 738 """ 739 740 :return: saved model 741 742 """ 743 return self.model 723 """ 724 :return: saved model 725 """ 726 return self.model 744 727 745 728 def get_data(self): 746 """ 747 729 """ 748 730 :return: list of data data_list 749 750 """ 751 #return self.data_list 752 return self.data_list[0] 731 """ 732 return self.data_list[0] 753 733 754 734 def remove_data(self, data): … … 757 737 758 738 :param data: Data to remove from data_list 759 760 739 """ 761 740 if data in self.data_list: 762 741 self.data_list.remove(data) 763 742 764 def set_to_fit 743 def set_to_fit(self, value=0): 765 744 """ 766 745 set self.selected to 0 or 1 for other values raise an exception 767 746 768 747 :param value: integer between 0 or 1 769 770 748 """ 771 749 self.selected = value … … 781 759 if sys.platform.count("win32") > 0: 782 760 IS_MAC = False 783 761 762 784 763 class FResult(object): 785 764 """ … … 835 814 (p[0], p[1], p[1].value)\ 836 815 for p in result_param if p[1].name in self.param_list] 837 msg = 816 msg = msg1 + msg3 + msg2 838 817 else: 839 818 msg = msg1 + msg3 … … 844 823 """ 845 824 """ 846 print self 825 print self
Note: See TracChangeset
for help on using the changeset viewer.