Changeset a45622a in sasview
- Timestamp:
- Jun 1, 2010 3:52:47 PM (14 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:
- 74755ff
- Parents:
- 0997158f
- Location:
- Invariant
- Files:
-
- 35 added
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
Invariant/invariant.py
r6d55d81 ra45622a 1 ##################################################################### 2 #This software was developed by the University of Tennessee as part of the 3 #Distributed Data Analysis of Neutron Scattering Experiments (DANSE) 4 #project funded by the US National Science Foundation. 5 #See the license text in license.txt 6 #copyright 2010, University of Tennessee 7 ###################################################################### 8 1 9 """ 2 This software was developed by the University of Tennessee as part of the 3 Distributed Data Analysis of Neutron Scattering Experiments (DANSE) 4 project funded by the US National Science Foundation. 5 6 See the license text in license.txt 7 8 copyright 2010, University of Tennessee 9 """ 10 11 """ 12 This module implements invariant and its related computations. 13 @author: Gervaise B. Alina/UTK 14 15 16 TODO: 17 - intro / documentation 10 This module implements invariant and its related computations. 11 12 :author: Gervaise B. Alina/UTK 13 :author: Mathieu Doucet/UTK 14 :author: Jae Cho/UTK 18 15 19 16 """ … … 34 31 class Transform(object): 35 32 """ 36 37 33 Define interface that need to compute a function or an inverse 34 function given some x, y 38 35 """ 39 36 40 37 def linearize_data(self, data): 41 38 """ 42 Linearize data so that a linear fit can be performed. 43 Filter out the data that can't be transformed. 44 @param data : LoadData1D instance 39 Linearize data so that a linear fit can be performed. 40 Filter out the data that can't be transformed. 41 42 :param data: LoadData1D instance 43 45 44 """ 46 45 # Check that the vector lengths are equal … … 71 70 def get_allowed_bins(self, data): 72 71 """ 73 74 75 76 @param data: Data1D object72 Goes through the data points and returns a list of boolean values 73 to indicate whether each points is allowed by the model or not. 74 75 :param data: Data1D object 77 76 """ 78 77 return [p[0]>0 and p[1]>0 and p[2]>0 for p in zip(data.x, data.y, data.dy)] … … 80 79 def linearize_q_value(self, value): 81 80 """ 82 81 Transform the input q-value for linearization 83 82 """ 84 83 return NotImplemented … … 86 85 def extract_model_parameters(self, constant, slope, dconstant=0, dslope=0): 87 86 """ 88 87 set private member 89 88 """ 90 89 return NotImplemented … … 92 91 def evaluate_model(self, x): 93 92 """ 94 93 Returns an array f(x) values where f is the Transform function. 95 94 """ 96 95 return NotImplemented … … 98 97 def evaluate_model_errors(self, x): 99 98 """ 100 99 Returns an array of I(q) errors 101 100 """ 102 101 return NotImplemented … … 104 103 class Guinier(Transform): 105 104 """ 106 107 105 class of type Transform that performs operations related to guinier 106 function 108 107 """ 109 108 def __init__(self, scale=1, radius=60): … … 118 117 def linearize_q_value(self, value): 119 118 """ 120 Transform the input q-value for linearization 121 @param value: q-value 122 @return: q*q 119 Transform the input q-value for linearization 120 121 :param value: q-value 122 123 :return: q*q 123 124 """ 124 125 return value * value 125 126 126 127 def extract_model_parameters(self, constant, slope, dconstant=0, dslope=0): 127 128 128 """ 129 assign new value to the scale and the radius 129 130 """ 130 131 self.scale = math.exp(constant) … … 139 140 def evaluate_model(self, x): 140 141 """ 141 142 return F(x)= scale* e-((radius*x)**2/3) 142 143 """ 143 144 return self._guinier(x) … … 145 146 def evaluate_model_errors(self, x): 146 147 """ 147 Returns the error on I(q) for the given array of q-values 148 @param x: array of q-values 148 Returns the error on I(q) for the given array of q-values 149 150 :param x: array of q-values 149 151 """ 150 152 p1 = numpy.array([self.dscale * math.exp(-((self.radius * q)**2/3)) for q in x]) … … 155 157 def _guinier(self, x): 156 158 """ 157 Retrive the guinier function after apply an inverse guinier function 158 to x 159 Compute a F(x) = scale* e-((radius*x)**2/3). 160 @param x: a vector of q values 161 @param scale: the scale value 162 @param radius: the guinier radius value 163 @return F(x) 159 Retrive the guinier function after apply an inverse guinier function 160 to x 161 Compute a F(x) = scale* e-((radius*x)**2/3). 162 163 :param x: a vector of q values 164 :param scale: the scale value 165 :param radius: the guinier radius value 166 167 :return: F(x) 164 168 """ 165 169 # transform the radius of coming from the inverse guinier function to a … … 172 176 class PowerLaw(Transform): 173 177 """ 174 175 178 class of type transform that perform operation related to power_law 179 function 176 180 """ 177 181 def __init__(self, scale=1, power=4): … … 182 186 def linearize_q_value(self, value): 183 187 """ 184 Transform the input q-value for linearization 185 @param value: q-value 186 @return: log(q) 188 Transform the input q-value for linearization 189 190 :param value: q-value 191 192 :return: log(q) 187 193 """ 188 194 return math.log(value) … … 190 196 def extract_model_parameters(self, constant, slope, dconstant=0, dslope=0): 191 197 """ 192 198 Assign new value to the scale and the power 193 199 """ 194 200 self.power = -slope … … 203 209 def evaluate_model(self, x): 204 210 """ 205 206 211 given a scale and a radius transform x, y using a power_law 212 function 207 213 """ 208 214 return self._power_law(x) … … 210 216 def evaluate_model_errors(self, x): 211 217 """ 212 213 @param x: array of q-values218 Returns the error on I(q) for the given array of q-values 219 :param x: array of q-values 214 220 """ 215 221 p1 = numpy.array([self.dscale * math.pow(q, -self.power) for q in x]) … … 220 226 def _power_law(self, x): 221 227 """ 222 F(x) = scale* (x)^(-power) 223 when power= 4. the model is porod 224 else power_law 225 The model has three parameters: 226 @param x: a vector of q values 227 @param power: power of the function 228 @param scale : scale factor value 229 @param F(x) 228 F(x) = scale* (x)^(-power) 229 when power= 4. the model is porod 230 else power_law 231 The model has three parameters: :: 232 1. x: a vector of q values 233 2. power: power of the function 234 3. scale : scale factor value 235 236 :param x: array 237 :return: F(x) 230 238 """ 231 239 if self.power <= 0: … … 239 247 class Extrapolator: 240 248 """ 241 249 Extrapolate I(q) distribution using a given model 242 250 """ 243 251 def __init__(self, data, model=None): 244 252 """ 245 246 247 248 249 250 @param data: data containing x and y such as y = ax + b251 @param model: optional Transform object253 Determine a and b given a linear equation y = ax + b 254 255 If a model is given, it will be used to linearize the data before 256 the extrapolation is performed. If None, a simple linear fit will be done. 257 258 :param data: data containing x and y such as y = ax + b 259 :param model: optional Transform object 252 260 """ 253 261 self.data = data … … 264 272 def fit(self, power=None, qmin=None, qmax=None): 265 273 """ 266 Fit data for y = ax + b return a and b 267 @param power: a fixed, otherwise None 268 @param qmin: Minimum Q-value 269 @param qmax: Maximum Q-value 274 Fit data for y = ax + b return a and b 275 276 :param power: a fixed, otherwise None 277 :param qmin: Minimum Q-value 278 :param qmax: Maximum Q-value 270 279 """ 271 280 if qmin is None: … … 331 340 class InvariantCalculator(object): 332 341 """ 333 Compute invariant if data is given. 334 Can provide volume fraction and surface area if the user provides 335 Porod constant and contrast values. 336 @precondition: the user must send a data of type DataLoader.Data1D 337 the user provide background and scale values. 338 339 @note: Some computations depends on each others. 342 Compute invariant if data is given. 343 Can provide volume fraction and surface area if the user provides 344 Porod constant and contrast values. 345 346 :precondition: the user must send a data of type DataLoader.Data1D 347 the user provide background and scale values. 348 349 :note: Some computations depends on each others. 340 350 """ 341 351 def __init__(self, data, background=0, scale=1 ): 342 352 """ 343 Initialize variables 344 @param data: data must be of type DataLoader.Data1D 345 @param background: Background value. The data will be corrected before processing 346 @param scale: Scaling factor for I(q). The data will be corrected before processing 353 Initialize variables. 354 355 :param data: data must be of type DataLoader.Data1D 356 :param background: Background value. The data will be corrected before processing 357 :param scale: Scaling factor for I(q). The data will be corrected before processing 347 358 """ 348 359 # Background and scale should be private data member if the only way to … … 378 389 def _get_data(self, data): 379 390 """ 380 @note this function must be call before computing any type 381 of invariant 382 @return data= self._scale *data - self._background 391 :note: this function must be call before computing any type 392 of invariant 393 394 :return: new data = self._scale *data - self._background 383 395 """ 384 396 if not issubclass(data.__class__, LoaderData1D): … … 400 412 def _fit(self, model, qmin=Q_MINIMUM, qmax=Q_MAXIMUM, power=None): 401 413 """ 402 fit data with function using 403 data= self._get_data() 404 fx= Functor(data , function) 405 y = data.y 406 slope, constant = linalg.lstsq(y,fx) 407 @param qmin: data first q value to consider during the fit 408 @param qmax: data last q value to consider during the fit 409 @param power : power value to consider for power-law 410 @param function: the function to use during the fit 411 @return a: the scale of the function 412 @return b: the other parameter of the function for guinier will be radius 413 for power_law will be the power value 414 fit data with function using 415 data = self._get_data() 416 fx = Functor(data , function) 417 y = data.y 418 slope, constant = linalg.lstsq(y,fx) 419 420 :param qmin: data first q value to consider during the fit 421 :param qmax: data last q value to consider during the fit 422 :param power : power value to consider for power-law 423 :param function: the function to use during the fit 424 425 :return a: the scale of the function 426 :return b: the other parameter of the function for guinier will be radius 427 for power_law will be the power value 414 428 """ 415 429 extrapolator = Extrapolator(data=self._data, model=model) … … 420 434 def _get_qstar(self, data): 421 435 """ 422 423 This invariant is given by:424 425 426 427 436 Compute invariant for pinhole data. 437 This invariant is given by: :: 438 439 q_star = x0**2 *y0 *dx0 +x1**2 *y1 *dx1 440 + ..+ xn**2 *yn *dxn 441 428 442 where n >= len(data.x)-1 429 443 dxi = 1/2*(xi+1 - xi) + (xi - xi-1) 430 444 dx0 = (x1 - x0)/2 431 445 dxn = (xn - xn-1)/2 432 @param data: the data to use to compute invariant. 433 @return q_star: invariant value for pinhole data. q_star > 0 446 447 :param data: the data to use to compute invariant. 448 449 :return q_star: invariant value for pinhole data. q_star > 0 434 450 """ 435 451 if len(data.x) <= 1 or len(data.y) <= 1 or len(data.x)!= len(data.y): … … 458 474 def _get_qstar_uncertainty(self, data): 459 475 """ 460 Compute invariant uncertainty with with pinhole data. 461 This uncertainty is given as follow: 462 dq_star = math.sqrt[(x0**2*(dy0)*dx0)**2 + 463 (x1**2 *(dy1)*dx1)**2 + ..+ (xn**2 *(dyn)*dxn)**2 ] 464 where n >= len(data.x)-1 465 dxi = 1/2*(xi+1 - xi) + (xi - xi-1) 466 dx0 = (x1 - x0)/2 467 dxn = (xn - xn-1)/2 468 dyn: error on dy 469 470 @param data: 471 note: if data doesn't contain dy assume dy= math.sqrt(data.y) 476 Compute invariant uncertainty with with pinhole data. 477 This uncertainty is given as follow: :: 478 479 dq_star = math.sqrt[(x0**2*(dy0)*dx0)**2 + 480 (x1**2 *(dy1)*dx1)**2 + ..+ (xn**2 *(dyn)*dxn)**2 ] 481 where n >= len(data.x)-1 482 dxi = 1/2*(xi+1 - xi) + (xi - xi-1) 483 dx0 = (x1 - x0)/2 484 dxn = (xn - xn-1)/2 485 dyn: error on dy 486 487 :param data: 488 :note: if data doesn't contain dy assume dy= math.sqrt(data.y) 472 489 """ 473 490 if len(data.x) <= 1 or len(data.y) <= 1 or \ … … 505 522 q_start=Q_MINIMUM, q_end=Q_MAXIMUM): 506 523 """ 507 @returnextrapolate data create from data524 :return: extrapolate data create from data 508 525 """ 509 526 #create new Data1D to compute the invariant … … 520 537 def get_data(self): 521 538 """ 522 @returnself._data539 :return: self._data 523 540 """ 524 541 return self._data … … 526 543 def get_extrapolation_power(self, range='high'): 527 544 """ 528 returnthe fitted power for power law function for a given extrapolation range545 :return: the fitted power for power law function for a given extrapolation range 529 546 """ 530 547 if range == 'low': … … 534 551 def get_qstar_low(self): 535 552 """ 536 537 538 539 540 541 542 @return q_star: the invariant for data extrapolated at low q.553 Compute the invariant for extrapolated data at low q range. 554 555 Implementation: 556 data = self._get_extra_data_low() 557 return self._get_qstar() 558 559 :return q_star: the invariant for data extrapolated at low q. 543 560 """ 544 561 # Data boundaries for fitting … … 571 588 def get_qstar_high(self): 572 589 """ 573 574 575 576 577 578 579 @return q_star: the invariant for data extrapolated at high q.590 Compute the invariant for extrapolated data at high q range. 591 592 Implementation: 593 data = self._get_extra_data_high() 594 return self._get_qstar() 595 596 :return q_star: the invariant for data extrapolated at high q. 580 597 """ 581 598 # Data boundaries for fitting … … 600 617 def get_extra_data_low(self, npts_in=None, q_start=None, npts=20): 601 618 """ 602 603 604 605 606 607 608 609 @param npts_in: number of data points for which the extrapolated data overlap610 @param q_start: is the minimum value to uses for extrapolated data611 @param npts: the number of points in the extrapolated distribution619 Returns the extrapolated data used for the loew-Q invariant calculation. 620 By default, the distribution will cover the data points used for the 621 extrapolation. The number of overlap points is a parameter (npts_in). 622 By default, the maximum q-value of the distribution will be 623 the minimum q-value used when extrapolating for the purpose of the 624 invariant calculation. 625 626 :param npts_in: number of data points for which the extrapolated data overlap 627 :param q_start: is the minimum value to uses for extrapolated data 628 :param npts: the number of points in the extrapolated distribution 612 629 613 630 """ … … 629 646 def get_extra_data_high(self, npts_in=None, q_end=Q_MAXIMUM, npts=20): 630 647 """ 631 632 633 634 635 636 637 638 @param npts_in: number of data points for which the extrapolated data overlap639 @param q_end: is the maximum value to uses for extrapolated data640 @param npts: the number of points in the extrapolated distribution648 Returns the extrapolated data used for the high-Q invariant calculation. 649 By default, the distribution will cover the data points used for the 650 extrapolation. The number of overlap points is a parameter (npts_in). 651 By default, the maximum q-value of the distribution will be Q_MAXIMUM, 652 the maximum q-value used when extrapolating for the purpose of the 653 invariant calculation. 654 655 :param npts_in: number of data points for which the extrapolated data overlap 656 :param q_end: is the maximum value to uses for extrapolated data 657 :param npts: the number of points in the extrapolated distribution 641 658 """ 642 659 # Get extrapolation range … … 655 672 def set_extrapolation(self, range, npts=4, function=None, power=None): 656 673 """ 657 Set the extrapolation parameters for the high or low Q-range. 658 Note that this does not turn extrapolation on or off. 659 @param range: a keyword set the type of extrapolation . type string 660 @param npts: the numbers of q points of data to consider for extrapolation 661 @param function: a keyword to select the function to use for extrapolation. 662 of type string. 663 @param power: an power to apply power_low function 674 Set the extrapolation parameters for the high or low Q-range. 675 Note that this does not turn extrapolation on or off. 676 677 :param range: a keyword set the type of extrapolation . type string 678 :param npts: the numbers of q points of data to consider for extrapolation 679 :param function: a keyword to select the function to use for extrapolation. 680 of type string. 681 :param power: an power to apply power_low function 664 682 665 683 """ … … 688 706 def get_qstar(self, extrapolation=None): 689 707 """ 690 Compute the invariant of the local copy of data. 708 Compute the invariant of the local copy of data. 709 710 :param extrapolation: string to apply optional extrapolation 691 711 692 @param extrapolation: string to apply optional extrapolation 693 @return q_star: invariant of the data within data's q range 694 695 @warning: When using setting data to Data1D , the user is responsible of 712 :return q_star: invariant of the data within data's q range 713 714 :warning: When using setting data to Data1D , the user is responsible of 696 715 checking that the scale and the background are properly apply to the data 716 697 717 """ 698 718 self._qstar = self._get_qstar(self._data) … … 724 744 def get_surface(self, contrast, porod_const, extrapolation=None): 725 745 """ 726 Compute the specific surface from the data. 727 728 Implementation: 729 V= self.get_volume_fraction(contrast, extrapolation) 730 731 Compute the surface given by: 732 surface = (2*pi *V(1- V)*porod_const)/ q_star 733 734 @param contrast: contrast value to compute the volume 735 @param porod_const: Porod constant to compute the surface 736 @param extrapolation: string to apply optional extrapolation 737 @return: specific surface 746 Compute the specific surface from the data. 747 748 Implementation:: 749 750 V = self.get_volume_fraction(contrast, extrapolation) 751 752 Compute the surface given by: 753 surface = (2*pi *V(1- V)*porod_const)/ q_star 754 755 :param contrast: contrast value to compute the volume 756 :param porod_const: Porod constant to compute the surface 757 :param extrapolation: string to apply optional extrapolation 758 759 :return: specific surface 738 760 """ 739 761 # Compute the volume … … 743 765 def get_volume_fraction(self, contrast, extrapolation=None): 744 766 """ 745 Compute volume fraction is deduced as follow:746 767 Compute volume fraction is deduced as follow: :: 768 747 769 q_star = 2*(pi*contrast)**2* volume( 1- volume) 748 770 for k = 10^(-8)*q_star/(2*(pi*|contrast|)**2) … … 757 779 758 780 the result returned will be 0 <= volume <= 1 759 760 @param contrast: contrast value provides by the user of type float. 761 contrast unit is 1/A^(2)= 10^(16)cm^(2) 762 @param extrapolation: string to apply optional extrapolation 763 @return: volume fraction 764 @note: volume fraction must have no unit 781 782 :param contrast: contrast value provides by the user of type float. 783 contrast unit is 1/A^(2)= 10^(16)cm^(2) 784 :param extrapolation: string to apply optional extrapolation 785 786 :return: volume fraction 787 788 :note: volume fraction must have no unit 765 789 """ 766 790 if contrast <= 0: … … 795 819 def get_qstar_with_error(self, extrapolation=None): 796 820 """ 797 Compute the invariant uncertainty. 798 This uncertainty computation depends on whether or not the data is 799 smeared. 800 801 @param extrapolation: string to apply optional extrapolation 802 @return: invariant, the invariant uncertainty 821 Compute the invariant uncertainty. 822 This uncertainty computation depends on whether or not the data is 823 smeared. 824 825 :param extrapolation: string to apply optional extrapolation 826 827 :return: invariant, the invariant uncertainty 803 828 """ 804 829 self.get_qstar(extrapolation) … … 807 832 def get_volume_fraction_with_error(self, contrast, extrapolation=None): 808 833 """ 809 Compute uncertainty on volume value as well as the volume fraction 810 This uncertainty is given by the following equation: 834 Compute uncertainty on volume value as well as the volume fraction 835 This uncertainty is given by the following equation: :: 836 811 837 dV = 0.5 * (4*k* dq_star) /(2* math.sqrt(1-k* q_star)) 812 838 … … 816 842 dq_star: the invariant uncertainty 817 843 dV: the volume uncertainty 818 819 The uncertainty will be set to -1 if it can't be computed. 820 821 @param contrast: contrast value 822 @param extrapolation: string to apply optional extrapolation 823 @return: V, dV = volume fraction, error on volume fraction 844 845 The uncertainty will be set to -1 if it can't be computed. 846 847 :param contrast: contrast value 848 :param extrapolation: string to apply optional extrapolation 849 850 :return: V, dV = volume fraction, error on volume fraction 824 851 """ 825 852 volume = self.get_volume_fraction(contrast, extrapolation) … … 838 865 def get_surface_with_error(self, contrast, porod_const, extrapolation=None): 839 866 """ 840 841 The uncertainty is given as follow:842 867 Compute uncertainty of the surface value as well as the surface value. 868 The uncertainty is given as follow: :: 869 843 870 dS = porod_const *2*pi[( dV -2*V*dV)/q_star 844 871 + dq_star(v-v**2) … … 848 875 V: the volume fraction value 849 876 dV: the volume uncertainty 850 851 @param contrast: contrast value 852 @param porod_const: porod constant value 853 @param extrapolation: string to apply optional extrapolation 854 @return S, dS: the surface, with its uncertainty 877 878 :param contrast: contrast value 879 :param porod_const: porod constant value 880 :param extrapolation: string to apply optional extrapolation 881 882 :return S, dS: the surface, with its uncertainty 855 883 """ 856 884 # We get the volume fraction, with error
Note: See TracChangeset
for help on using the changeset viewer.