Changes in / [e3f1fed:43345ab] in sasview


Ignore:
Files:
30 added
2 deleted
26 edited

Legend:

Unmodified
Added
Removed
  • check_packages.py

    r235f514 r3e1f417  
    7272    for package_name, test_vals in win_required_package_list.items(): 
    7373        try: 
    74             if package_name == "pywin": 
    75                 import win32api 
    76                 fixed_file_info = win32api.GetFileVersionInfo(win32api.__file__, '\\') 
    77                 print("%s Version Installed: %s"% (package_name, fixed_file_info['FileVersionLS'] >> 16)) 
    78             else: 
    79                 i = __import__(test_vals['import_name'], fromlist=['']) 
    80                 print("%s Version Installed: %s"% (package_name, getattr(i, test_vals['test']))) 
     74            i = __import__(test_vals['import_name'], fromlist=['']) 
     75            print("%s Version Installed: %s"% (package_name, getattr(i, test_vals['test'], "unknown"))) 
    8176        except ImportError: 
    8277            print('%s NOT INSTALLED'% package_name) 
  • docs/sphinx-docs/build_sphinx.py

    r01f1e17 r4abc05d8  
    3838#/sasview-local-trunk/docs/sphinx-docs/build_sphinx.py 
    3939SASMODELS_SOURCE_PROLOG = os.path.join(CURRENT_SCRIPT_DIR, "..", "..", "..", "sasmodels", "doc") 
    40 SASMODELS_SOURCE_GPU = os.path.join(CURRENT_SCRIPT_DIR, "..", "..", "..", "sasmodels", "doc", "ref", "gpu") 
    41 SASMODELS_SOURCE_SESANS = os.path.join(CURRENT_SCRIPT_DIR, "..", "..", "..", "sasmodels", "doc", "ref", "sesans") 
    42 SASMODELS_SOURCE_SESANSIMG = os.path.join(CURRENT_SCRIPT_DIR, "..", "..", "..", "sasmodels", "doc", "ref", "sesans", "sesans_img") 
    43 SASMODELS_SOURCE_MAGNETISM = os.path.join(CURRENT_SCRIPT_DIR, "..", "..", "..", "sasmodels", "doc", "ref", "magnetism") 
    44 SASMODELS_SOURCE_MAGIMG = os.path.join(CURRENT_SCRIPT_DIR, "..", "..", "..", "sasmodels", "doc", "ref", "magnetism", "mag_img") 
    45 SASMODELS_SOURCE_REF_MODELS = os.path.join(CURRENT_SCRIPT_DIR, "..", "..", "..", "sasmodels", "doc", "ref", "models") 
     40SASMODELS_SOURCE_GPU = os.path.join(CURRENT_SCRIPT_DIR, "..", "..", "..", "sasmodels", "doc", "guide", "gpu") 
     41SASMODELS_SOURCE_SESANS = os.path.join(CURRENT_SCRIPT_DIR, "..", "..", "..", "sasmodels", "doc", "guide", "sesans") 
     42SASMODELS_SOURCE_SESANSIMG = os.path.join(CURRENT_SCRIPT_DIR, "..", "..", "..", "sasmodels", "doc", "guide", "sesans", "sesans_img") 
     43SASMODELS_SOURCE_MAGNETISM = os.path.join(CURRENT_SCRIPT_DIR, "..", "..", "..", "sasmodels", "doc", "guide", "magnetism") 
     44SASMODELS_SOURCE_MAGIMG = os.path.join(CURRENT_SCRIPT_DIR, "..", "..", "..", "sasmodels", "doc", "guide", "magnetism", "mag_img") 
     45SASMODELS_SOURCE_REF_MODELS = os.path.join(CURRENT_SCRIPT_DIR, "..", "..", "..", "sasmodels", "doc", "guide", "models") 
    4646SASMODELS_SOURCE_MODELS = os.path.join(CURRENT_SCRIPT_DIR, "..", "..", "..", "sasmodels", "doc", "model") 
    4747SASMODELS_SOURCE_IMG = os.path.join(CURRENT_SCRIPT_DIR, "..", "..", "..", "sasmodels", "doc", "model", "img") 
  • run.py

    rf36e01f rf94a935  
    5151def import_package(modname, path): 
    5252    """Import a package into a particular point in the python namespace""" 
     53    #logger.debug("Dynamicly importing: %s", path) 
    5354    mod = imp.load_source(modname, abspath(joinpath(path, '__init__.py'))) 
    5455    sys.modules[modname] = mod 
  • sasview/test/sesans_data/sphere2micron.ses

    r2a2b43a rd3bce8c  
    1 DataFileTitle   "Polystyrene of Markus Strobl,  Full Sine, ++ only "                                             
    2 Sample  "Polystyrene 2 um in 53% H2O, 47% D2O "                                          
    3 Settings        "D1=D2=20x8 mm,Ds = 16x10 mm (WxH), GF1 =scanning, GF2 = 2.5 A. 2 um polystyrene in 53% H2O, 47% D2O; 8.55% contrast "                                           
    4 Operator        CPD                                              
    5 Date    do 10 jul 2014 16:37:30                                                  
    6 ScanType        sine one element scan                                            
    7 Thickness [cm]  2.00E-01                                                 
    8 Q_zmax [\A^-1]  0.05                                             
    9 Q_ymax [\A^-1]  0.05                                             
    10                                                          
    11 spin echo length [A]     Depolarisation [A-2 cm-1]       error depol [A-2 cm-1]          error SEL [A]   wavelength [A]          error wavelength [A]    polarisation    error pol  
    12 391.56  0.0041929       0.0036894       19.578  2.11    0.1055  1.0037  0.0032974 
    13 1564    -0.0046571      0.0038185       78.2    2.11    0.1055  0.99586 0.003386 
    14 2735.6  -0.017007       0.0038132       136.78  2.11    0.1055  0.98497 0.0033444 
    15 3907.9  -0.033462       0.0035068       195.39  2.11    0.1055  0.97064 0.0030309 
    16 5080.2  -0.047483       0.0038208       254.01  2.11    0.1055  0.9586  0.0032613 
    17 6251.8  -0.070375       0.00376 312.59  2.11    0.1055  0.93926 0.0031446 
    18 7423.2  -0.092217       0.0037927       371.16  2.11    0.1055  0.92117 0.0031108 
    19 8595.5  -0.10238        0.004006        429.77  2.11    0.1055  0.91287 0.0032562 
    20 9767.7  -0.12672        0.0038534       488.39  2.11    0.1055  0.8933  0.0030651 
    21 10940   -0.1374 0.004243        546.98  2.11    0.1055  0.88484 0.003343 
    22 12112   -0.16072        0.0045837       605.58  2.11    0.1055  0.86666 0.0035372 
    23 13284   -0.16623        0.0045613       664.2   2.11    0.1055  0.86242 0.0035027 
    24 14456   -0.18468        0.0044918       722.79  2.11    0.1055  0.84837 0.0033931 
    25 15628   -0.19143        0.0048967       781.38  2.11    0.1055  0.84328 0.0036768 
    26 16800   -0.20029        0.0045421       840.02  2.11    0.1055  0.83666 0.0033837 
    27 17971   -0.19798        0.0046642       898.56  2.11    0.1055  0.83838 0.0034819 
    28 19143   -0.21442        0.0047052       957.17  2.11    0.1055  0.82619 0.0034614 
    29 20316   -0.20885        0.0044931       1015.8  2.11    0.1055  0.8303  0.0033218 
    30 21488   -0.21393        0.0049186       1074.4  2.11    0.1055  0.82655 0.00362 
    31 22660   -0.20685        0.004423        1133    2.11    0.1055  0.83179 0.0032758 
    32 23832   -0.20802        0.0046979       1191.6  2.11    0.1055  0.83092 0.0034758 
    33 25003   -0.19848        0.0045953       1250.2  2.11    0.1055  0.838   0.0034289 
    34 26175   -0.21117        0.0044567       1308.8  2.11    0.1055  0.82859 0.0032881 
    35 27347   -0.21283        0.004137        1367.4  2.11    0.1055  0.82736 0.0030477 
    36 28520   -0.2042 0.0044587       1426    2.11    0.1055  0.83375 0.0033101 
    37 29692   -0.2112 0.0042852       1484.6  2.11    0.1055  0.82857 0.0031615 
    38 30864   -0.20319        0.0043483       1543.2  2.11    0.1055  0.8345  0.003231 
    39 32036   -0.20752        0.0044297       1601.8  2.11    0.1055  0.83129 0.0032788 
    40 33207   -0.20654        0.0043188       1660.4  2.11    0.1055  0.83201 0.0031995 
    41 34380   -0.20126        0.0046375       1719    2.11    0.1055  0.83593 0.0034518 
    42 35551   -0.20924        0.0042871       1777.6  2.11    0.1055  0.83001 0.0031684 
    43 36724   -0.21323        0.0045471       1836.2  2.11    0.1055  0.82707 0.0033487 
    44 37895   -0.21324        0.0045354       1894.7  2.11    0.1055  0.82706 0.00334 
    45 39067   -0.19905        0.0044141       1953.4  2.11    0.1055  0.83758 0.003292 
    46 40239   -0.1991 0.0047441       2012    2.11    0.1055  0.83754 0.003538 
    47 41411   -0.20359        0.0050136       2070.5  2.11    0.1055  0.8342  0.003724 
    48 42583   -0.21032        0.0049474       2129.1  2.11    0.1055  0.82922 0.0036529 
    49 43755   -0.20689        0.0048203       2187.8  2.11    0.1055  0.83176 0.00357 
    50 44927   -0.21075        0.0052337       2246.4  2.11    0.1055  0.8289  0.0038628 
    51 46099   -0.19956        0.0047827       2304.9  2.11    0.1055  0.8372  0.0035653 
     1FileFormatVersion       1.0 
     2DataFileTitle           Polystyrene of Markus Strobl,  Full Sine, ++ only 
     3Sample                  Polystyrene 2 um in 53% H2O, 47% D2O 
     4Settings                D1=D2=20x8 mm,Ds = 16x10 mm (WxH), GF1 =scanning, GF2 = 2.5 A. 2 um polystyrene in 53% H2O, 47% D2O; 8.55% contrast 
     5Operator                CPD 
     6Date                    do 10 jul 2014 16:37:30 
     7ScanType                sine one element scan 
     8Thickness               2.00E-01 
     9Thickness_unit          cm 
     10Theta_zmax              0.0168 
     11Theta_zmax_unit         radians 
     12Theta_ymax              0.0168 
     13Theta_ymax_unit         radians 
     14Orientation             Z 
     15SpinEchoLength_unit     A 
     16Depolarisation_unit     A-2 cm-1 
     17Wavelength_unit         A 
     18 
     19BEGIN_DATA 
     20SpinEchoLength Depolarisation Depolarisation_error SpinEchoLength_error Wavelength Wavelength_error Polarisation  Polarisation_error 
     21391.56 0.0041929 0.0036894 19.578 2.11 0.1055 1.0037 0.0032974 
     221564 -0.0046571 0.0038185 78.2 2.11 0.1055 0.99586 0.003386 
     232735.6 -0.017007 0.0038132 136.78 2.11 0.1055 0.98497 0.0033444 
     243907.9 -0.033462 0.0035068 195.39 2.11 0.1055 0.97064 0.0030309 
     255080.2 -0.047483 0.0038208 254.01 2.11 0.1055 0.9586 0.0032613 
     266251.8 -0.070375 0.00376 312.59 2.11 0.1055 0.93926 0.0031446 
     277423.2 -0.092217 0.0037927 371.16 2.11 0.1055 0.92117 0.0031108 
     288595.5 -0.10238 0.004006 429.77 2.11 0.1055 0.91287 0.0032562 
     299767.7 -0.12672 0.0038534 488.39 2.11 0.1055 0.8933 0.0030651 
     3010940 -0.1374 0.004243 546.98 2.11 0.1055 0.88484 0.003343 
     3112112 -0.16072 0.0045837 605.58 2.11 0.1055 0.86666 0.0035372 
     3213284 -0.16623 0.0045613 664.2 2.11 0.1055 0.86242 0.0035027 
     3314456 -0.18468 0.0044918 722.79 2.11 0.1055 0.84837 0.0033931 
     3415628 -0.19143 0.0048967 781.38 2.11 0.1055 0.84328 0.0036768 
     3516800 -0.20029 0.0045421 840.02 2.11 0.1055 0.83666 0.0033837 
     3617971 -0.19798 0.0046642 898.56 2.11 0.1055 0.83838 0.0034819 
     3719143 -0.21442 0.0047052 957.17 2.11 0.1055 0.82619 0.0034614 
     3820316 -0.20885 0.0044931 1015.8 2.11 0.1055 0.8303 0.0033218 
     3921488 -0.21393 0.0049186 1074.4 2.11 0.1055 0.82655 0.00362 
     4022660 -0.20685 0.004423 1133 2.11 0.1055 0.83179 0.0032758 
     4123832 -0.20802 0.0046979 1191.6 2.11 0.1055 0.83092 0.0034758 
     4225003 -0.19848 0.0045953 1250.2 2.11 0.1055 0.838 0.0034289 
     4326175 -0.21117 0.0044567 1308.8 2.11 0.1055 0.82859 0.0032881 
     4427347 -0.21283 0.004137 1367.4 2.11 0.1055 0.82736 0.0030477 
     4528520 -0.2042 0.0044587 1426 2.11 0.1055 0.83375 0.0033101 
     4629692 -0.2112 0.0042852 1484.6 2.11 0.1055 0.82857 0.0031615 
     4730864 -0.20319 0.0043483 1543.2 2.11 0.1055 0.8345 0.003231 
     4832036 -0.20752 0.0044297 1601.8 2.11 0.1055 0.83129 0.0032788 
     4933207 -0.20654 0.0043188 1660.4 2.11 0.1055 0.83201 0.0031995 
     5034380 -0.20126 0.0046375 1719 2.11 0.1055 0.83593 0.0034518 
     5135551 -0.20924 0.0042871 1777.6 2.11 0.1055 0.83001 0.0031684 
     5236724 -0.21323 0.0045471 1836.2 2.11 0.1055 0.82707 0.0033487 
     5337895 -0.21324 0.0045354 1894.7 2.11 0.1055 0.82706 0.00334 
     5439067 -0.19905 0.0044141 1953.4 2.11 0.1055 0.83758 0.003292 
     5540239 -0.1991 0.0047441 2012 2.11 0.1055 0.83754 0.003538 
     5641411 -0.20359 0.0050136 2070.5 2.11 0.1055 0.8342 0.003724 
     5742583 -0.21032 0.0049474 2129.1 2.11 0.1055 0.82922 0.0036529 
     5843755 -0.20689 0.0048203 2187.8 2.11 0.1055 0.83176 0.00357 
     5944927 -0.21075 0.0052337 2246.4 2.11 0.1055 0.8289 0.0038628 
     6046099 -0.19956 0.0047827 2304.9 2.11 0.1055 0.8372 0.0035653 
  • src/sas/sascalc/data_util/nxsunit.py

    rb699768 r8e9536f  
    136136    sld = { '10^-6 Angstrom^-2': 1e-6, 'Angstrom^-2': 1 } 
    137137    Q = { 'invA': 1, 'invAng': 1, 'invAngstroms': 1, '1/A': 1,  
    138           '10^-3 Angstrom^-1': 1e-3, '1/cm': 1e-8, 
     138          '10^-3 Angstrom^-1': 1e-3, '1/cm': 1e-8, '1/m': 1e-10, 
    139139          'nm^-1': 0.1, '1/nm': 0.1, 'n_m^-1': 0.1 } 
    140140 
     
    195195    _check(1,Converter('n_m^-1')(10,'invA')) # 10 nm^-1 = 1 inv Angstroms 
    196196    _check(2,Converter('mm')(2000,'m')) # 2000 mm -> 2 m 
     197    _check(2.011e10,Converter('1/A')(2.011,"1/m")) # 2.011 1/A -> 2.011 * 10^10 1/m 
    197198    _check(0.003,Converter('microseconds')(3,units='ms')) # 3 us -> 0.003 ms 
    198199    _check(45,Converter('nanokelvin')(45))  # 45 nK -> 45 nK 
  • src/sas/sascalc/data_util/qsmearing.py

    r235f514 r235f514  
    6565            raise ValueError('one or more of your dx values are negative, please check the data file!') 
    6666 
    67     if _found_sesans == True: 
    68         #Pre-compute the Hankel matrix (H) 
    69         qmax, qunits = data.sample.zacceptance 
     67    if _found_sesans: 
     68        # Pre-compute the Hankel matrix (H) 
    7069        SElength = Converter(data._xunit)(data.x, "A") 
    71         zaccept = Converter(qunits)(qmax, "1/A"), 
     70 
     71        theta_max = Converter("radians")(data.sample.zacceptance)[0] 
     72        q_max = 2 * np.pi / np.max(data.source.wavelength) * np.sin(theta_max) 
     73        zaccept = Converter("1/A")(q_max, "1/" + data.source.wavelength_unit), 
     74 
    7275        Rmax = 10000000 
    73         hankel = SesansTransform(data.x, SElength, zaccept, Rmax) 
     76        hankel = SesansTransform(data.x, SElength, 
     77                                 data.source.wavelength, 
     78                                 zaccept, Rmax) 
    7479        # Then return the actual transform, as if it were a smearing function 
    7580        return PySmear(hankel, model, offset=0) 
  • src/sas/sascalc/dataloader/manipulations.py

    r7432acb r324e0bf  
     1from __future__ import division 
    12""" 
    23Data manipulations for 2D data sets. 
    34Using the meta data information, various types of averaging 
    45are performed in Q-space 
     6 
     7To test this module use: 
     8``` 
     9cd test 
     10PYTHONPATH=../src/ python2  -m sasdataloader.test.utest_averaging DataInfoTests.test_sectorphi_quarter 
     11``` 
    512""" 
    613##################################################################### 
    7 #This software was developed by the University of Tennessee as part of the 
    8 #Distributed Data Analysis of Neutron Scattering Experiments (DANSE) 
    9 #project funded by the US National Science Foundation. 
    10 #See the license text in license.txt 
    11 #copyright 2008, University of Tennessee 
     14# This software was developed by the University of Tennessee as part of the 
     15# Distributed Data Analysis of Neutron Scattering Experiments (DANSE) 
     16# project funded by the US National Science Foundation. 
     17# See the license text in license.txt 
     18# copyright 2008, University of Tennessee 
    1219###################################################################### 
    1320 
    14 #TODO: copy the meta data from the 2D object to the resulting 1D object 
     21 
     22# TODO: copy the meta data from the 2D object to the resulting 1D object 
    1523import math 
    16 import numpy 
     24import numpy as np 
     25import sys 
    1726 
    1827#from data_info import plottable_2D 
     
    7079    return phi_out 
    7180 
    72  
    73 def reader2D_converter(data2d=None): 
    74     """ 
    75     convert old 2d format opened by IhorReader or danse_reader 
    76     to new Data2D format 
    77  
    78     :param data2d: 2d array of Data2D object 
    79     :return: 1d arrays of Data2D object 
    80  
    81     """ 
    82     if data2d.data is None or data2d.x_bins is None or data2d.y_bins is None: 
    83         raise ValueError, "Can't convert this data: data=None..." 
    84     new_x = numpy.tile(data2d.x_bins, (len(data2d.y_bins), 1)) 
    85     new_y = numpy.tile(data2d.y_bins, (len(data2d.x_bins), 1)) 
    86     new_y = new_y.swapaxes(0, 1) 
    87  
    88     new_data = data2d.data.flatten() 
    89     qx_data = new_x.flatten() 
    90     qy_data = new_y.flatten() 
    91     q_data = numpy.sqrt(qx_data * qx_data + qy_data * qy_data) 
    92     if data2d.err_data is None or numpy.any(data2d.err_data <= 0): 
    93         new_err_data = numpy.sqrt(numpy.abs(new_data)) 
    94     else: 
    95         new_err_data = data2d.err_data.flatten() 
    96     mask = numpy.ones(len(new_data), dtype=bool) 
    97  
    98     #TODO: make sense of the following two lines... 
    99     #from sas.sascalc.dataloader.data_info import Data2D 
    100     #output = Data2D() 
    101     output = data2d 
    102     output.data = new_data 
    103     output.err_data = new_err_data 
    104     output.qx_data = qx_data 
    105     output.qy_data = qy_data 
    106     output.q_data = q_data 
    107     output.mask = mask 
    108  
    109     return output 
    110  
    111  
    112 class _Slab(object): 
    113     """ 
    114     Compute average I(Q) for a region of interest 
    115     """ 
    116     def __init__(self, x_min=0.0, x_max=0.0, y_min=0.0, 
    117                  y_max=0.0, bin_width=0.001): 
    118         # Minimum Qx value [A-1] 
    119         self.x_min = x_min 
    120         # Maximum Qx value [A-1] 
    121         self.x_max = x_max 
    122         # Minimum Qy value [A-1] 
    123         self.y_min = y_min 
    124         # Maximum Qy value [A-1] 
    125         self.y_max = y_max 
    126         # Bin width (step size) [A-1] 
    127         self.bin_width = bin_width 
    128         # If True, I(|Q|) will be return, otherwise, 
    129         # negative q-values are allowed 
    130         self.fold = False 
    131  
    132     def __call__(self, data2D): 
    133         return NotImplemented 
    134  
    135     def _avg(self, data2D, maj): 
    136         """ 
    137         Compute average I(Q_maj) for a region of interest. 
    138         The major axis is defined as the axis of Q_maj. 
    139         The minor axis is the axis that we average over. 
    140  
    141         :param data2D: Data2D object 
    142         :param maj_min: min value on the major axis 
    143         :return: Data1D object 
    144         """ 
    145         if len(data2D.detector) > 1: 
    146             msg = "_Slab._avg: invalid number of " 
    147             msg += " detectors: %g" % len(data2D.detector) 
    148             raise RuntimeError, msg 
    149  
    150         # Get data 
    151         data = data2D.data[numpy.isfinite(data2D.data)] 
    152         err_data = data2D.err_data[numpy.isfinite(data2D.data)] 
    153         qx_data = data2D.qx_data[numpy.isfinite(data2D.data)] 
    154         qy_data = data2D.qy_data[numpy.isfinite(data2D.data)] 
    155  
    156         # Build array of Q intervals 
    157         if maj == 'x': 
    158             if self.fold: 
    159                 x_min = 0 
    160             else: 
    161                 x_min = self.x_min 
    162             nbins = int(math.ceil((self.x_max - x_min) / self.bin_width)) 
    163         elif maj == 'y': 
    164             if self.fold: 
    165                 y_min = 0 
    166             else: 
    167                 y_min = self.y_min 
    168             nbins = int(math.ceil((self.y_max - y_min) / self.bin_width)) 
    169         else: 
    170             raise RuntimeError, "_Slab._avg: unrecognized axis %s" % str(maj) 
    171  
    172         x = numpy.zeros(nbins) 
    173         y = numpy.zeros(nbins) 
    174         err_y = numpy.zeros(nbins) 
    175         y_counts = numpy.zeros(nbins) 
    176  
    177         # Average pixelsize in q space 
    178         for npts in range(len(data)): 
    179             # default frac 
    180             frac_x = 0 
    181             frac_y = 0 
    182             # get ROI 
    183             if self.x_min <= qx_data[npts] and self.x_max > qx_data[npts]: 
    184                 frac_x = 1 
    185             if self.y_min <= qy_data[npts] and self.y_max > qy_data[npts]: 
    186                 frac_y = 1 
    187             frac = frac_x * frac_y 
    188  
    189             if frac == 0: 
    190                 continue 
    191             # binning: find axis of q 
    192             if maj == 'x': 
    193                 q_value = qx_data[npts] 
    194                 min_value = x_min 
    195             if maj == 'y': 
    196                 q_value = qy_data[npts] 
    197                 min_value = y_min 
    198             if self.fold and q_value < 0: 
    199                 q_value = -q_value 
    200             # bin 
    201             i_q = int(math.ceil((q_value - min_value) / self.bin_width)) - 1 
    202  
    203             # skip outside of max bins 
    204             if i_q < 0 or i_q >= nbins: 
    205                 continue 
    206  
    207             #TODO: find better definition of x[i_q] based on q_data 
    208             # min_value + (i_q + 1) * self.bin_width / 2.0 
    209             x[i_q] += frac * q_value 
    210             y[i_q] += frac * data[npts] 
    211  
    212             if err_data is None or err_data[npts] == 0.0: 
    213                 if data[npts] < 0: 
    214                     data[npts] = -data[npts] 
    215                 err_y[i_q] += frac * frac * data[npts] 
    216             else: 
    217                 err_y[i_q] += frac * frac * err_data[npts] * err_data[npts] 
    218             y_counts[i_q] += frac 
    219  
    220         # Average the sums 
    221         for n in range(nbins): 
    222             err_y[n] = math.sqrt(err_y[n]) 
    223  
    224         err_y = err_y / y_counts 
    225         y = y / y_counts 
    226         x = x / y_counts 
    227         idx = (numpy.isfinite(y) & numpy.isfinite(x)) 
    228  
    229         if not idx.any(): 
    230             msg = "Average Error: No points inside ROI to average..." 
    231             raise ValueError, msg 
    232         return Data1D(x=x[idx], y=y[idx], dy=err_y[idx]) 
    233  
    234  
    235 class SlabY(_Slab): 
    236     """ 
    237     Compute average I(Qy) for a region of interest 
    238     """ 
    239     def __call__(self, data2D): 
    240         """ 
    241         Compute average I(Qy) for a region of interest 
    242  
    243         :param data2D: Data2D object 
    244         :return: Data1D object 
    245         """ 
    246         return self._avg(data2D, 'y') 
    247  
    248  
    249 class SlabX(_Slab): 
    250     """ 
    251     Compute average I(Qx) for a region of interest 
    252     """ 
    253     def __call__(self, data2D): 
    254         """ 
    255         Compute average I(Qx) for a region of interest 
    256         :param data2D: Data2D object 
    257         :return: Data1D object 
    258         """ 
    259         return self._avg(data2D, 'x') 
    260  
    261  
    262 class Boxsum(object): 
    263     """ 
    264     Perform the sum of counts in a 2D region of interest. 
    265     """ 
    266     def __init__(self, x_min=0.0, x_max=0.0, y_min=0.0, y_max=0.0): 
    267         # Minimum Qx value [A-1] 
    268         self.x_min = x_min 
    269         # Maximum Qx value [A-1] 
    270         self.x_max = x_max 
    271         # Minimum Qy value [A-1] 
    272         self.y_min = y_min 
    273         # Maximum Qy value [A-1] 
    274         self.y_max = y_max 
    275  
    276     def __call__(self, data2D): 
    277         """ 
    278         Perform the sum in the region of interest 
    279  
    280         :param data2D: Data2D object 
    281         :return: number of counts, error on number of counts, 
    282             number of points summed 
    283         """ 
    284         y, err_y, y_counts = self._sum(data2D) 
    285  
    286         # Average the sums 
    287         counts = 0 if y_counts == 0 else y 
    288         error = 0 if y_counts == 0 else math.sqrt(err_y) 
    289  
    290         # Added y_counts to return, SMK & PDB, 04/03/2013 
    291         return counts, error, y_counts 
    292  
    293     def _sum(self, data2D): 
    294         """ 
    295         Perform the sum in the region of interest 
    296  
    297         :param data2D: Data2D object 
    298         :return: number of counts, 
    299             error on number of counts, number of entries summed 
    300         """ 
    301         if len(data2D.detector) > 1: 
    302             msg = "Circular averaging: invalid number " 
    303             msg += "of detectors: %g" % len(data2D.detector) 
    304             raise RuntimeError, msg 
    305         # Get data 
    306         data = data2D.data[numpy.isfinite(data2D.data)] 
    307         err_data = data2D.err_data[numpy.isfinite(data2D.data)] 
    308         qx_data = data2D.qx_data[numpy.isfinite(data2D.data)] 
    309         qy_data = data2D.qy_data[numpy.isfinite(data2D.data)] 
    310  
    311         y = 0.0 
    312         err_y = 0.0 
    313         y_counts = 0.0 
    314  
    315         # Average pixelsize in q space 
    316         for npts in range(len(data)): 
    317             # default frac 
    318             frac_x = 0 
    319             frac_y = 0 
    320  
    321             # get min and max at each points 
    322             qx = qx_data[npts] 
    323             qy = qy_data[npts] 
    324  
    325             # get the ROI 
    326             if self.x_min <= qx and self.x_max > qx: 
    327                 frac_x = 1 
    328             if self.y_min <= qy and self.y_max > qy: 
    329                 frac_y = 1 
    330             #Find the fraction along each directions 
    331             frac = frac_x * frac_y 
    332             if frac == 0: 
    333                 continue 
    334             y += frac * data[npts] 
    335             if err_data is None or err_data[npts] == 0.0: 
    336                 if data[npts] < 0: 
    337                     data[npts] = -data[npts] 
    338                 err_y += frac * frac * data[npts] 
    339             else: 
    340                 err_y += frac * frac * err_data[npts] * err_data[npts] 
    341             y_counts += frac 
    342         return y, err_y, y_counts 
    343  
    344  
    345 class Boxavg(Boxsum): 
    346     """ 
    347     Perform the average of counts in a 2D region of interest. 
    348     """ 
    349     def __init__(self, x_min=0.0, x_max=0.0, y_min=0.0, y_max=0.0): 
    350         super(Boxavg, self).__init__(x_min=x_min, x_max=x_max, 
    351                                      y_min=y_min, y_max=y_max) 
    352  
    353     def __call__(self, data2D): 
    354         """ 
    355         Perform the sum in the region of interest 
    356  
    357         :param data2D: Data2D object 
    358         :return: average counts, error on average counts 
    359  
    360         """ 
    361         y, err_y, y_counts = self._sum(data2D) 
    362  
    363         # Average the sums 
    364         counts = 0 if y_counts == 0 else y / y_counts 
    365         error = 0 if y_counts == 0 else math.sqrt(err_y) / y_counts 
    366  
    367         return counts, error 
    368  
    369  
    37081def get_pixel_fraction_square(x, xmin, xmax): 
    37182    """ 
     
    390101        return 1.0 
    391102 
    392  
    393 class CircularAverage(object): 
    394     """ 
    395     Perform circular averaging on 2D data 
    396  
    397     The data returned is the distribution of counts 
    398     as a function of Q 
    399     """ 
    400     def __init__(self, r_min=0.0, r_max=0.0, bin_width=0.0005): 
    401         # Minimum radius included in the average [A-1] 
    402         self.r_min = r_min 
    403         # Maximum radius included in the average [A-1] 
    404         self.r_max = r_max 
    405         # Bin width (step size) [A-1] 
    406         self.bin_width = bin_width 
    407  
    408     def __call__(self, data2D, ismask=False): 
    409         """ 
    410         Perform circular averaging on the data 
    411  
    412         :param data2D: Data2D object 
    413         :return: Data1D object 
    414         """ 
    415         # Get data W/ finite values 
    416         data = data2D.data[numpy.isfinite(data2D.data)] 
    417         q_data = data2D.q_data[numpy.isfinite(data2D.data)] 
    418         err_data = data2D.err_data[numpy.isfinite(data2D.data)] 
    419         mask_data = data2D.mask[numpy.isfinite(data2D.data)] 
    420  
    421         dq_data = None 
    422  
    423         # Get the dq for resolution averaging 
    424         if data2D.dqx_data is not None and data2D.dqy_data is not None: 
    425             # The pinholes and det. pix contribution present 
    426             # in both direction of the 2D which must be subtracted when 
    427             # converting to 1D: dq_overlap should calculated ideally at 
    428             # q = 0. Note This method works on only pinhole geometry. 
    429             # Extrapolate dqx(r) and dqy(phi) at q = 0, and take an average. 
    430             z_max = max(data2D.q_data) 
    431             z_min = min(data2D.q_data) 
    432             x_max = data2D.dqx_data[data2D.q_data[z_max]] 
    433             x_min = data2D.dqx_data[data2D.q_data[z_min]] 
    434             y_max = data2D.dqy_data[data2D.q_data[z_max]] 
    435             y_min = data2D.dqy_data[data2D.q_data[z_min]] 
    436             # Find qdx at q = 0 
    437             dq_overlap_x = (x_min * z_max - x_max * z_min) / (z_max - z_min) 
    438             # when extrapolation goes wrong 
    439             if dq_overlap_x > min(data2D.dqx_data): 
    440                 dq_overlap_x = min(data2D.dqx_data) 
    441             dq_overlap_x *= dq_overlap_x 
    442             # Find qdx at q = 0 
    443             dq_overlap_y = (y_min * z_max - y_max * z_min) / (z_max - z_min) 
    444             # when extrapolation goes wrong 
    445             if dq_overlap_y > min(data2D.dqy_data): 
    446                 dq_overlap_y = min(data2D.dqy_data) 
    447             # get dq at q=0. 
    448             dq_overlap_y *= dq_overlap_y 
    449  
    450             dq_overlap = numpy.sqrt((dq_overlap_x + dq_overlap_y) / 2.0) 
    451             # Final protection of dq 
    452             if dq_overlap < 0: 
    453                 dq_overlap = y_min 
    454             dqx_data = data2D.dqx_data[numpy.isfinite(data2D.data)] 
    455             dqy_data = data2D.dqy_data[numpy.isfinite(data2D.data)] - dq_overlap 
    456             # def; dqx_data = dq_r dqy_data = dq_phi 
    457             # Convert dq 2D to 1D here 
    458             dqx = dqx_data * dqx_data 
    459             dqy = dqy_data * dqy_data 
    460             dq_data = numpy.add(dqx, dqy) 
    461             dq_data = numpy.sqrt(dq_data) 
    462  
    463         #q_data_max = numpy.max(q_data) 
    464         if len(data2D.q_data) is None: 
    465             msg = "Circular averaging: invalid q_data: %g" % data2D.q_data 
    466             raise RuntimeError, msg 
    467  
    468         # Build array of Q intervals 
    469         nbins = int(math.ceil((self.r_max - self.r_min) / self.bin_width)) 
    470  
    471         x = numpy.zeros(nbins) 
    472         y = numpy.zeros(nbins) 
    473         err_y = numpy.zeros(nbins) 
    474         err_x = numpy.zeros(nbins) 
    475         y_counts = numpy.zeros(nbins) 
    476  
    477         for npt in range(len(data)): 
    478  
    479             if ismask and not mask_data[npt]: 
    480                 continue 
    481  
    482             frac = 0 
    483  
    484             # q-value at the pixel (j,i) 
    485             q_value = q_data[npt] 
    486             data_n = data[npt] 
    487  
    488             ## No need to calculate the frac when all data are within range 
    489             if self.r_min >= self.r_max: 
    490                 raise ValueError, "Limit Error: min > max" 
    491  
    492             if self.r_min <= q_value and q_value <= self.r_max: 
    493                 frac = 1 
    494             if frac == 0: 
    495                 continue 
    496             i_q = int(math.floor((q_value - self.r_min) / self.bin_width)) 
    497  
    498             # Take care of the edge case at phi = 2pi. 
    499             if i_q == nbins: 
    500                 i_q = nbins - 1 
    501             y[i_q] += frac * data_n 
    502             # Take dqs from data to get the q_average 
    503             x[i_q] += frac * q_value 
    504             if err_data is None or err_data[npt] == 0.0: 
    505                 if data_n < 0: 
    506                     data_n = -data_n 
    507                 err_y[i_q] += frac * frac * data_n 
    508             else: 
    509                 err_y[i_q] += frac * frac * err_data[npt] * err_data[npt] 
    510             if dq_data is not None: 
    511                 # To be consistent with dq calculation in 1d reduction, 
    512                 # we need just the averages (not quadratures) because 
    513                 # it should not depend on the number of the q points 
    514                 # in the qr bins. 
    515                 err_x[i_q] += frac * dq_data[npt] 
    516             else: 
    517                 err_x = None 
    518             y_counts[i_q] += frac 
    519  
    520         # Average the sums 
    521         for n in range(nbins): 
    522             if err_y[n] < 0: 
    523                 err_y[n] = -err_y[n] 
    524             err_y[n] = math.sqrt(err_y[n]) 
    525             #if err_x is not None: 
    526             #    err_x[n] = math.sqrt(err_x[n]) 
    527  
    528         err_y = err_y / y_counts 
    529         err_y[err_y == 0] = numpy.average(err_y) 
    530         y = y / y_counts 
    531         x = x / y_counts 
    532         idx = (numpy.isfinite(y)) & (numpy.isfinite(x)) 
    533  
    534         if err_x is not None: 
    535             d_x = err_x[idx] / y_counts[idx] 
    536         else: 
    537             d_x = None 
    538  
    539         if not idx.any(): 
    540             msg = "Average Error: No points inside ROI to average..." 
    541             raise ValueError, msg 
    542  
    543         return Data1D(x=x[idx], y=y[idx], dy=err_y[idx], dx=d_x) 
    544  
    545  
    546 class Ring(object): 
    547     """ 
    548     Defines a ring on a 2D data set. 
    549     The ring is defined by r_min, r_max, and 
    550     the position of the center of the ring. 
    551  
    552     The data returned is the distribution of counts 
    553     around the ring as a function of phi. 
    554  
    555     Phi_min and phi_max should be defined between 0 and 2*pi 
    556     in anti-clockwise starting from the x- axis on the left-hand side 
    557     """ 
    558     #Todo: remove center. 
    559     def __init__(self, r_min=0, r_max=0, center_x=0, center_y=0, nbins=36): 
    560         # Minimum radius 
    561         self.r_min = r_min 
    562         # Maximum radius 
    563         self.r_max = r_max 
    564         # Center of the ring in x 
    565         self.center_x = center_x 
    566         # Center of the ring in y 
    567         self.center_y = center_y 
    568         # Number of angular bins 
    569         self.nbins_phi = nbins 
    570  
    571  
    572     def __call__(self, data2D): 
    573         """ 
    574         Apply the ring to the data set. 
    575         Returns the angular distribution for a given q range 
    576  
    577         :param data2D: Data2D object 
    578  
    579         :return: Data1D object 
    580         """ 
    581         if data2D.__class__.__name__ not in ["Data2D", "plottable_2D"]: 
    582             raise RuntimeError, "Ring averaging only take plottable_2D objects" 
    583  
    584         Pi = math.pi 
    585  
    586         # Get data 
    587         data = data2D.data[numpy.isfinite(data2D.data)] 
    588         q_data = data2D.q_data[numpy.isfinite(data2D.data)] 
    589         err_data = data2D.err_data[numpy.isfinite(data2D.data)] 
    590         qx_data = data2D.qx_data[numpy.isfinite(data2D.data)] 
    591         qy_data = data2D.qy_data[numpy.isfinite(data2D.data)] 
    592  
    593         # Set space for 1d outputs 
    594         phi_bins = numpy.zeros(self.nbins_phi) 
    595         phi_counts = numpy.zeros(self.nbins_phi) 
    596         phi_values = numpy.zeros(self.nbins_phi) 
    597         phi_err = numpy.zeros(self.nbins_phi) 
    598  
    599         # Shift to apply to calculated phi values in order 
    600         # to center first bin at zero 
    601         phi_shift = Pi / self.nbins_phi 
    602  
    603         for npt in range(len(data)): 
    604             frac = 0 
    605             # q-value at the point (npt) 
    606             q_value = q_data[npt] 
    607             data_n = data[npt] 
    608  
    609             # phi-value at the point (npt) 
    610             phi_value = math.atan2(qy_data[npt], qx_data[npt]) + Pi 
    611  
    612             if self.r_min <= q_value and q_value <= self.r_max: 
    613                 frac = 1 
    614             if frac == 0: 
    615                 continue 
    616             # binning 
    617             i_phi = int(math.floor((self.nbins_phi) * \ 
    618                                    (phi_value + phi_shift) / (2 * Pi))) 
    619  
    620             # Take care of the edge case at phi = 2pi. 
    621             if i_phi >= self.nbins_phi: 
    622                 i_phi = 0 
    623             phi_bins[i_phi] += frac * data[npt] 
    624  
    625             if err_data is None or err_data[npt] == 0.0: 
    626                 if data_n < 0: 
    627                     data_n = -data_n 
    628                 phi_err[i_phi] += frac * frac * math.fabs(data_n) 
    629             else: 
    630                 phi_err[i_phi] += frac * frac * err_data[npt] * err_data[npt] 
    631             phi_counts[i_phi] += frac 
    632  
    633         for i in range(self.nbins_phi): 
    634             phi_bins[i] = phi_bins[i] / phi_counts[i] 
    635             phi_err[i] = math.sqrt(phi_err[i]) / phi_counts[i] 
    636             phi_values[i] = 2.0 * math.pi / self.nbins_phi * (1.0 * i) 
    637  
    638         idx = (numpy.isfinite(phi_bins)) 
    639  
    640         if not idx.any(): 
    641             msg = "Average Error: No points inside ROI to average..." 
    642             raise ValueError, msg 
    643         #elif len(phi_bins[idx])!= self.nbins_phi: 
    644         #    print "resulted",self.nbins_phi- len(phi_bins[idx]) 
    645         #,"empty bin(s) due to tight binning..." 
    646         return Data1D(x=phi_values[idx], y=phi_bins[idx], dy=phi_err[idx]) 
    647  
     103def get_intercept(q, q_0, q_1): 
     104    """ 
     105    Returns the fraction of the side at which the 
     106    q-value intercept the pixel, None otherwise. 
     107    The values returned is the fraction ON THE SIDE 
     108    OF THE LOWEST Q. :: 
     109 
     110            A           B 
     111        +-----------+--------+    <--- pixel size 
     112        0                    1 
     113        Q_0 -------- Q ----- Q_1   <--- equivalent Q range 
     114        if Q_1 > Q_0, A is returned 
     115        if Q_1 < Q_0, B is returned 
     116        if Q is outside the range of [Q_0, Q_1], None is returned 
     117 
     118    """ 
     119    if q_1 > q_0: 
     120        if q > q_0 and q <= q_1: 
     121            return (q - q_0) / (q_1 - q_0) 
     122    else: 
     123        if q > q_1 and q <= q_0: 
     124            return (q - q_1) / (q_0 - q_1) 
     125    return None 
    648126 
    649127def get_pixel_fraction(qmax, q_00, q_01, q_10, q_11): 
     
    710188    return frac_max 
    711189 
    712  
    713 def get_intercept(q, q_0, q_1): 
    714     """ 
    715     Returns the fraction of the side at which the 
    716     q-value intercept the pixel, None otherwise. 
    717     The values returned is the fraction ON THE SIDE 
    718     OF THE LOWEST Q. :: 
    719  
    720             A           B 
    721         +-----------+--------+    <--- pixel size 
    722         0                    1 
    723         Q_0 -------- Q ----- Q_1   <--- equivalent Q range 
    724         if Q_1 > Q_0, A is returned 
    725         if Q_1 < Q_0, B is returned 
    726         if Q is outside the range of [Q_0, Q_1], None is returned 
    727  
    728     """ 
    729     if q_1 > q_0: 
    730         if q > q_0 and q <= q_1: 
    731             return (q - q_0) / (q_1 - q_0) 
     190def get_dq_data(data2D): 
     191    ''' 
     192    Get the dq for resolution averaging 
     193    The pinholes and det. pix contribution present 
     194    in both direction of the 2D which must be subtracted when 
     195    converting to 1D: dq_overlap should calculated ideally at 
     196    q = 0. Note This method works on only pinhole geometry. 
     197    Extrapolate dqx(r) and dqy(phi) at q = 0, and take an average. 
     198    ''' 
     199    z_max = max(data2D.q_data) 
     200    z_min = min(data2D.q_data) 
     201    dqx_at_z_max = data2D.dqx_data[np.argmax(data2D.q_data)] 
     202    dqx_at_z_min = data2D.dqx_data[np.argmin(data2D.q_data)] 
     203    dqy_at_z_max = data2D.dqy_data[np.argmax(data2D.q_data)] 
     204    dqy_at_z_min = data2D.dqy_data[np.argmin(data2D.q_data)] 
     205    # Find qdx at q = 0 
     206    dq_overlap_x = (dqx_at_z_min * z_max - dqx_at_z_max * z_min) / (z_max - z_min) 
     207    # when extrapolation goes wrong 
     208    if dq_overlap_x > min(data2D.dqx_data): 
     209        dq_overlap_x = min(data2D.dqx_data) 
     210    dq_overlap_x *= dq_overlap_x 
     211    # Find qdx at q = 0 
     212    dq_overlap_y = (dqy_at_z_min * z_max - dqy_at_z_max * z_min) / (z_max - z_min) 
     213    # when extrapolation goes wrong 
     214    if dq_overlap_y > min(data2D.dqy_data): 
     215        dq_overlap_y = min(data2D.dqy_data) 
     216    # get dq at q=0. 
     217    dq_overlap_y *= dq_overlap_y 
     218 
     219    dq_overlap = np.sqrt((dq_overlap_x + dq_overlap_y) / 2.0) 
     220    # Final protection of dq 
     221    if dq_overlap < 0: 
     222        dq_overlap = dqy_at_z_min 
     223    dqx_data = data2D.dqx_data[np.isfinite(data2D.data)] 
     224    dqy_data = data2D.dqy_data[np.isfinite( 
     225        data2D.data)] - dq_overlap 
     226    # def; dqx_data = dq_r dqy_data = dq_phi 
     227    # Convert dq 2D to 1D here 
     228    dq_data = np.sqrt(dqx_data**2 + dqx_data**2) 
     229    return dq_data 
     230 
     231################################################################################ 
     232 
     233def reader2D_converter(data2d=None): 
     234    """ 
     235    convert old 2d format opened by IhorReader or danse_reader 
     236    to new Data2D format 
     237    This is mainly used by the Readers 
     238 
     239    :param data2d: 2d array of Data2D object 
     240    :return: 1d arrays of Data2D object 
     241 
     242    """ 
     243    if data2d.data is None or data2d.x_bins is None or data2d.y_bins is None: 
     244        raise ValueError("Can't convert this data: data=None...") 
     245    new_x = np.tile(data2d.x_bins, (len(data2d.y_bins), 1)) 
     246    new_y = np.tile(data2d.y_bins, (len(data2d.x_bins), 1)) 
     247    new_y = new_y.swapaxes(0, 1) 
     248 
     249    new_data = data2d.data.flatten() 
     250    qx_data = new_x.flatten() 
     251    qy_data = new_y.flatten() 
     252    q_data = np.sqrt(qx_data * qx_data + qy_data * qy_data) 
     253    if data2d.err_data is None or np.any(data2d.err_data <= 0): 
     254        new_err_data = np.sqrt(np.abs(new_data)) 
    732255    else: 
    733         if q > q_1 and q <= q_0: 
    734             return (q - q_1) / (q_0 - q_1) 
    735     return None 
     256        new_err_data = data2d.err_data.flatten() 
     257    mask = np.ones(len(new_data), dtype=bool) 
     258 
     259    # TODO: make sense of the following two lines... 
     260    #from sas.sascalc.dataloader.data_info import Data2D 
     261    #output = Data2D() 
     262    output = data2d 
     263    output.data = new_data 
     264    output.err_data = new_err_data 
     265    output.qx_data = qx_data 
     266    output.qy_data = qy_data 
     267    output.q_data = q_data 
     268    output.mask = mask 
     269 
     270    return output 
     271 
     272################################################################################ 
     273 
     274class Binning(object): 
     275    ''' 
     276    This class just creates a binning object 
     277    either linear or log 
     278    ''' 
     279 
     280    def __init__(self, min_value, max_value, n_bins, base=None): 
     281        ''' 
     282        if base is None: Linear binning 
     283        ''' 
     284        self.min = min_value if min_value > 0 else 0.0001 
     285        self.max = max_value 
     286        self.n_bins = n_bins 
     287        self.base = base 
     288 
     289    def get_bin_index(self, value): 
     290        ''' 
     291        The general formula logarithm binning is: 
     292        bin = floor(N * (log(x) - log(min)) / (log(max) - log(min))) 
     293        ''' 
     294        if self.base: 
     295            temp_x = self.n_bins * (math.log(value, self.base) - math.log(self.min, self.base)) 
     296            temp_y = math.log(self.max, self.base) - math.log(self.min, self.base) 
     297        else: 
     298            temp_x = self.n_bins * (value - self.min) 
     299            temp_y = self.max - self.min 
     300        # Bin index calulation 
     301        return int(math.floor(temp_x / temp_y)) 
     302 
     303 
     304################################################################################ 
     305 
     306class _Slab(object): 
     307    """ 
     308    Compute average I(Q) for a region of interest 
     309    """ 
     310 
     311    def __init__(self, x_min=0.0, x_max=0.0, y_min=0.0, 
     312                 y_max=0.0, bin_width=0.001): 
     313        # Minimum Qx value [A-1] 
     314        self.x_min = x_min 
     315        # Maximum Qx value [A-1] 
     316        self.x_max = x_max 
     317        # Minimum Qy value [A-1] 
     318        self.y_min = y_min 
     319        # Maximum Qy value [A-1] 
     320        self.y_max = y_max 
     321        # Bin width (step size) [A-1] 
     322        self.bin_width = bin_width 
     323        # If True, I(|Q|) will be return, otherwise, 
     324        # negative q-values are allowed 
     325        self.fold = False 
     326 
     327    def __call__(self, data2D): 
     328        return NotImplemented 
     329 
     330    def _avg(self, data2D, maj): 
     331        """ 
     332        Compute average I(Q_maj) for a region of interest. 
     333        The major axis is defined as the axis of Q_maj. 
     334        The minor axis is the axis that we average over. 
     335 
     336        :param data2D: Data2D object 
     337        :param maj_min: min value on the major axis 
     338        :return: Data1D object 
     339        """ 
     340        if len(data2D.detector) > 1: 
     341            msg = "_Slab._avg: invalid number of " 
     342            msg += " detectors: %g" % len(data2D.detector) 
     343            raise RuntimeError(msg) 
     344 
     345        # Get data 
     346        data = data2D.data[np.isfinite(data2D.data)] 
     347        err_data = data2D.err_data[np.isfinite(data2D.data)] 
     348        qx_data = data2D.qx_data[np.isfinite(data2D.data)] 
     349        qy_data = data2D.qy_data[np.isfinite(data2D.data)] 
     350 
     351        # Build array of Q intervals 
     352        if maj == 'x': 
     353            if self.fold: 
     354                x_min = 0 
     355            else: 
     356                x_min = self.x_min 
     357            nbins = int(math.ceil((self.x_max - x_min) / self.bin_width)) 
     358        elif maj == 'y': 
     359            if self.fold: 
     360                y_min = 0 
     361            else: 
     362                y_min = self.y_min 
     363            nbins = int(math.ceil((self.y_max - y_min) / self.bin_width)) 
     364        else: 
     365            raise RuntimeError("_Slab._avg: unrecognized axis %s" % str(maj)) 
     366 
     367        x = np.zeros(nbins) 
     368        y = np.zeros(nbins) 
     369        err_y = np.zeros(nbins) 
     370        y_counts = np.zeros(nbins) 
     371 
     372        # Average pixelsize in q space 
     373        for npts in range(len(data)): 
     374            # default frac 
     375            frac_x = 0 
     376            frac_y = 0 
     377            # get ROI 
     378            if self.x_min <= qx_data[npts] and self.x_max > qx_data[npts]: 
     379                frac_x = 1 
     380            if self.y_min <= qy_data[npts] and self.y_max > qy_data[npts]: 
     381                frac_y = 1 
     382            frac = frac_x * frac_y 
     383 
     384            if frac == 0: 
     385                continue 
     386            # binning: find axis of q 
     387            if maj == 'x': 
     388                q_value = qx_data[npts] 
     389                min_value = x_min 
     390            if maj == 'y': 
     391                q_value = qy_data[npts] 
     392                min_value = y_min 
     393            if self.fold and q_value < 0: 
     394                q_value = -q_value 
     395            # bin 
     396            i_q = int(math.ceil((q_value - min_value) / self.bin_width)) - 1 
     397 
     398            # skip outside of max bins 
     399            if i_q < 0 or i_q >= nbins: 
     400                continue 
     401 
     402            # TODO: find better definition of x[i_q] based on q_data 
     403            # min_value + (i_q + 1) * self.bin_width / 2.0 
     404            x[i_q] += frac * q_value 
     405            y[i_q] += frac * data[npts] 
     406 
     407            if err_data is None or err_data[npts] == 0.0: 
     408                if data[npts] < 0: 
     409                    data[npts] = -data[npts] 
     410                err_y[i_q] += frac * frac * data[npts] 
     411            else: 
     412                err_y[i_q] += frac * frac * err_data[npts] * err_data[npts] 
     413            y_counts[i_q] += frac 
     414 
     415        # Average the sums 
     416        for n in range(nbins): 
     417            err_y[n] = math.sqrt(err_y[n]) 
     418 
     419        err_y = err_y / y_counts 
     420        y = y / y_counts 
     421        x = x / y_counts 
     422        idx = (np.isfinite(y) & np.isfinite(x)) 
     423 
     424        if not idx.any(): 
     425            msg = "Average Error: No points inside ROI to average..." 
     426            raise ValueError(msg) 
     427        return Data1D(x=x[idx], y=y[idx], dy=err_y[idx]) 
     428 
     429 
     430class SlabY(_Slab): 
     431    """ 
     432    Compute average I(Qy) for a region of interest 
     433    """ 
     434 
     435    def __call__(self, data2D): 
     436        """ 
     437        Compute average I(Qy) for a region of interest 
     438 
     439        :param data2D: Data2D object 
     440        :return: Data1D object 
     441        """ 
     442        return self._avg(data2D, 'y') 
     443 
     444 
     445class SlabX(_Slab): 
     446    """ 
     447    Compute average I(Qx) for a region of interest 
     448    """ 
     449 
     450    def __call__(self, data2D): 
     451        """ 
     452        Compute average I(Qx) for a region of interest 
     453        :param data2D: Data2D object 
     454        :return: Data1D object 
     455        """ 
     456        return self._avg(data2D, 'x') 
     457 
     458################################################################################ 
     459 
     460class Boxsum(object): 
     461    """ 
     462    Perform the sum of counts in a 2D region of interest. 
     463    """ 
     464 
     465    def __init__(self, x_min=0.0, x_max=0.0, y_min=0.0, y_max=0.0): 
     466        # Minimum Qx value [A-1] 
     467        self.x_min = x_min 
     468        # Maximum Qx value [A-1] 
     469        self.x_max = x_max 
     470        # Minimum Qy value [A-1] 
     471        self.y_min = y_min 
     472        # Maximum Qy value [A-1] 
     473        self.y_max = y_max 
     474 
     475    def __call__(self, data2D): 
     476        """ 
     477        Perform the sum in the region of interest 
     478 
     479        :param data2D: Data2D object 
     480        :return: number of counts, error on number of counts, 
     481            number of points summed 
     482        """ 
     483        y, err_y, y_counts = self._sum(data2D) 
     484 
     485        # Average the sums 
     486        counts = 0 if y_counts == 0 else y 
     487        error = 0 if y_counts == 0 else math.sqrt(err_y) 
     488 
     489        # Added y_counts to return, SMK & PDB, 04/03/2013 
     490        return counts, error, y_counts 
     491 
     492    def _sum(self, data2D): 
     493        """ 
     494        Perform the sum in the region of interest 
     495 
     496        :param data2D: Data2D object 
     497        :return: number of counts, 
     498            error on number of counts, number of entries summed 
     499        """ 
     500        if len(data2D.detector) > 1: 
     501            msg = "Circular averaging: invalid number " 
     502            msg += "of detectors: %g" % len(data2D.detector) 
     503            raise RuntimeError(msg) 
     504        # Get data 
     505        data = data2D.data[np.isfinite(data2D.data)] 
     506        err_data = data2D.err_data[np.isfinite(data2D.data)] 
     507        qx_data = data2D.qx_data[np.isfinite(data2D.data)] 
     508        qy_data = data2D.qy_data[np.isfinite(data2D.data)] 
     509 
     510        y = 0.0 
     511        err_y = 0.0 
     512        y_counts = 0.0 
     513 
     514        # Average pixelsize in q space 
     515        for npts in range(len(data)): 
     516            # default frac 
     517            frac_x = 0 
     518            frac_y = 0 
     519 
     520            # get min and max at each points 
     521            qx = qx_data[npts] 
     522            qy = qy_data[npts] 
     523 
     524            # get the ROI 
     525            if self.x_min <= qx and self.x_max > qx: 
     526                frac_x = 1 
     527            if self.y_min <= qy and self.y_max > qy: 
     528                frac_y = 1 
     529            # Find the fraction along each directions 
     530            frac = frac_x * frac_y 
     531            if frac == 0: 
     532                continue 
     533            y += frac * data[npts] 
     534            if err_data is None or err_data[npts] == 0.0: 
     535                if data[npts] < 0: 
     536                    data[npts] = -data[npts] 
     537                err_y += frac * frac * data[npts] 
     538            else: 
     539                err_y += frac * frac * err_data[npts] * err_data[npts] 
     540            y_counts += frac 
     541        return y, err_y, y_counts 
     542 
     543 
     544class Boxavg(Boxsum): 
     545    """ 
     546    Perform the average of counts in a 2D region of interest. 
     547    """ 
     548 
     549    def __init__(self, x_min=0.0, x_max=0.0, y_min=0.0, y_max=0.0): 
     550        super(Boxavg, self).__init__(x_min=x_min, x_max=x_max, 
     551                                     y_min=y_min, y_max=y_max) 
     552 
     553    def __call__(self, data2D): 
     554        """ 
     555        Perform the sum in the region of interest 
     556 
     557        :param data2D: Data2D object 
     558        :return: average counts, error on average counts 
     559 
     560        """ 
     561        y, err_y, y_counts = self._sum(data2D) 
     562 
     563        # Average the sums 
     564        counts = 0 if y_counts == 0 else y / y_counts 
     565        error = 0 if y_counts == 0 else math.sqrt(err_y) / y_counts 
     566 
     567        return counts, error 
     568 
     569################################################################################ 
     570 
     571class CircularAverage(object): 
     572    """ 
     573    Perform circular averaging on 2D data 
     574 
     575    The data returned is the distribution of counts 
     576    as a function of Q 
     577    """ 
     578 
     579    def __init__(self, r_min=0.0, r_max=0.0, bin_width=0.0005): 
     580        # Minimum radius included in the average [A-1] 
     581        self.r_min = r_min 
     582        # Maximum radius included in the average [A-1] 
     583        self.r_max = r_max 
     584        # Bin width (step size) [A-1] 
     585        self.bin_width = bin_width 
     586 
     587    def __call__(self, data2D, ismask=False): 
     588        """ 
     589        Perform circular averaging on the data 
     590 
     591        :param data2D: Data2D object 
     592        :return: Data1D object 
     593        """ 
     594        # Get data W/ finite values 
     595        data = data2D.data[np.isfinite(data2D.data)] 
     596        q_data = data2D.q_data[np.isfinite(data2D.data)] 
     597        err_data = data2D.err_data[np.isfinite(data2D.data)] 
     598        mask_data = data2D.mask[np.isfinite(data2D.data)] 
     599 
     600        dq_data = None 
     601        if data2D.dqx_data is not None and data2D.dqy_data is not None: 
     602            dq_data = get_dq_data(data2D) 
     603 
     604        if len(q_data) == 0: 
     605            msg = "Circular averaging: invalid q_data: %g" % data2D.q_data 
     606            raise RuntimeError(msg) 
     607 
     608        # Build array of Q intervals 
     609        nbins = int(math.ceil((self.r_max - self.r_min) / self.bin_width)) 
     610 
     611        x = np.zeros(nbins) 
     612        y = np.zeros(nbins) 
     613        err_y = np.zeros(nbins) 
     614        err_x = np.zeros(nbins) 
     615        y_counts = np.zeros(nbins) 
     616 
     617        for npt in range(len(data)): 
     618 
     619            if ismask and not mask_data[npt]: 
     620                continue 
     621 
     622            frac = 0 
     623 
     624            # q-value at the pixel (j,i) 
     625            q_value = q_data[npt] 
     626            data_n = data[npt] 
     627 
     628            # No need to calculate the frac when all data are within range 
     629            if self.r_min >= self.r_max: 
     630                raise ValueError("Limit Error: min > max") 
     631 
     632            if self.r_min <= q_value and q_value <= self.r_max: 
     633                frac = 1 
     634            if frac == 0: 
     635                continue 
     636            i_q = int(math.floor((q_value - self.r_min) / self.bin_width)) 
     637 
     638            # Take care of the edge case at phi = 2pi. 
     639            if i_q == nbins: 
     640                i_q = nbins - 1 
     641            y[i_q] += frac * data_n 
     642            # Take dqs from data to get the q_average 
     643            x[i_q] += frac * q_value 
     644            if err_data is None or err_data[npt] == 0.0: 
     645                if data_n < 0: 
     646                    data_n = -data_n 
     647                err_y[i_q] += frac * frac * data_n 
     648            else: 
     649                err_y[i_q] += frac * frac * err_data[npt] * err_data[npt] 
     650            if dq_data is not None: 
     651                # To be consistent with dq calculation in 1d reduction, 
     652                # we need just the averages (not quadratures) because 
     653                # it should not depend on the number of the q points 
     654                # in the qr bins. 
     655                err_x[i_q] += frac * dq_data[npt] 
     656            else: 
     657                err_x = None 
     658            y_counts[i_q] += frac 
     659 
     660        # Average the sums 
     661        for n in range(nbins): 
     662            if err_y[n] < 0: 
     663                err_y[n] = -err_y[n] 
     664            err_y[n] = math.sqrt(err_y[n]) 
     665            # if err_x is not None: 
     666            #    err_x[n] = math.sqrt(err_x[n]) 
     667 
     668        err_y = err_y / y_counts 
     669        err_y[err_y == 0] = np.average(err_y) 
     670        y = y / y_counts 
     671        x = x / y_counts 
     672        idx = (np.isfinite(y)) & (np.isfinite(x)) 
     673 
     674        if err_x is not None: 
     675            d_x = err_x[idx] / y_counts[idx] 
     676        else: 
     677            d_x = None 
     678 
     679        if not idx.any(): 
     680            msg = "Average Error: No points inside ROI to average..." 
     681            raise ValueError(msg) 
     682 
     683        return Data1D(x=x[idx], y=y[idx], dy=err_y[idx], dx=d_x) 
     684 
     685################################################################################ 
     686 
     687class Ring(object): 
     688    """ 
     689    Defines a ring on a 2D data set. 
     690    The ring is defined by r_min, r_max, and 
     691    the position of the center of the ring. 
     692 
     693    The data returned is the distribution of counts 
     694    around the ring as a function of phi. 
     695 
     696    Phi_min and phi_max should be defined between 0 and 2*pi 
     697    in anti-clockwise starting from the x- axis on the left-hand side 
     698    """ 
     699    # Todo: remove center. 
     700 
     701    def __init__(self, r_min=0, r_max=0, center_x=0, center_y=0, nbins=36): 
     702        # Minimum radius 
     703        self.r_min = r_min 
     704        # Maximum radius 
     705        self.r_max = r_max 
     706        # Center of the ring in x 
     707        self.center_x = center_x 
     708        # Center of the ring in y 
     709        self.center_y = center_y 
     710        # Number of angular bins 
     711        self.nbins_phi = nbins 
     712 
     713    def __call__(self, data2D): 
     714        """ 
     715        Apply the ring to the data set. 
     716        Returns the angular distribution for a given q range 
     717 
     718        :param data2D: Data2D object 
     719 
     720        :return: Data1D object 
     721        """ 
     722        if data2D.__class__.__name__ not in ["Data2D", "plottable_2D"]: 
     723            raise RuntimeError("Ring averaging only take plottable_2D objects") 
     724 
     725        Pi = math.pi 
     726 
     727        # Get data 
     728        data = data2D.data[np.isfinite(data2D.data)] 
     729        q_data = data2D.q_data[np.isfinite(data2D.data)] 
     730        err_data = data2D.err_data[np.isfinite(data2D.data)] 
     731        qx_data = data2D.qx_data[np.isfinite(data2D.data)] 
     732        qy_data = data2D.qy_data[np.isfinite(data2D.data)] 
     733 
     734        # Set space for 1d outputs 
     735        phi_bins = np.zeros(self.nbins_phi) 
     736        phi_counts = np.zeros(self.nbins_phi) 
     737        phi_values = np.zeros(self.nbins_phi) 
     738        phi_err = np.zeros(self.nbins_phi) 
     739 
     740        # Shift to apply to calculated phi values in order 
     741        # to center first bin at zero 
     742        phi_shift = Pi / self.nbins_phi 
     743 
     744        for npt in range(len(data)): 
     745            frac = 0 
     746            # q-value at the point (npt) 
     747            q_value = q_data[npt] 
     748            data_n = data[npt] 
     749 
     750            # phi-value at the point (npt) 
     751            phi_value = math.atan2(qy_data[npt], qx_data[npt]) + Pi 
     752 
     753            if self.r_min <= q_value and q_value <= self.r_max: 
     754                frac = 1 
     755            if frac == 0: 
     756                continue 
     757            # binning 
     758            i_phi = int(math.floor((self.nbins_phi) * 
     759                                   (phi_value + phi_shift) / (2 * Pi))) 
     760 
     761            # Take care of the edge case at phi = 2pi. 
     762            if i_phi >= self.nbins_phi: 
     763                i_phi = 0 
     764            phi_bins[i_phi] += frac * data[npt] 
     765 
     766            if err_data is None or err_data[npt] == 0.0: 
     767                if data_n < 0: 
     768                    data_n = -data_n 
     769                phi_err[i_phi] += frac * frac * math.fabs(data_n) 
     770            else: 
     771                phi_err[i_phi] += frac * frac * err_data[npt] * err_data[npt] 
     772            phi_counts[i_phi] += frac 
     773 
     774        for i in range(self.nbins_phi): 
     775            phi_bins[i] = phi_bins[i] / phi_counts[i] 
     776            phi_err[i] = math.sqrt(phi_err[i]) / phi_counts[i] 
     777            phi_values[i] = 2.0 * math.pi / self.nbins_phi * (1.0 * i) 
     778 
     779        idx = (np.isfinite(phi_bins)) 
     780 
     781        if not idx.any(): 
     782            msg = "Average Error: No points inside ROI to average..." 
     783            raise ValueError(msg) 
     784        # elif len(phi_bins[idx])!= self.nbins_phi: 
     785        #    print "resulted",self.nbins_phi- len(phi_bins[idx]) 
     786        #,"empty bin(s) due to tight binning..." 
     787        return Data1D(x=phi_values[idx], y=phi_bins[idx], dy=phi_err[idx]) 
    736788 
    737789 
     
    748800    starting from the x- axis on the left-hand side 
    749801    """ 
    750     def __init__(self, r_min, r_max, phi_min=0, phi_max=2 * math.pi, nbins=20): 
     802 
     803    def __init__(self, r_min, r_max, phi_min=0, phi_max=2 * math.pi, nbins=20, 
     804                 base=None): 
     805        ''' 
     806        :param base: must be a valid base for an algorithm, i.e., 
     807        a positive number 
     808        ''' 
    751809        self.r_min = r_min 
    752810        self.r_max = r_max 
     
    754812        self.phi_max = phi_max 
    755813        self.nbins = nbins 
     814        self.base = base 
    756815 
    757816    def _agv(self, data2D, run='phi'): 
     
    765824        """ 
    766825        if data2D.__class__.__name__ not in ["Data2D", "plottable_2D"]: 
    767             raise RuntimeError, "Ring averaging only take plottable_2D objects" 
    768         Pi = math.pi 
     826            raise RuntimeError("Ring averaging only take plottable_2D objects") 
    769827 
    770828        # Get the all data & info 
    771         data = data2D.data[numpy.isfinite(data2D.data)] 
    772         q_data = data2D.q_data[numpy.isfinite(data2D.data)] 
    773         err_data = data2D.err_data[numpy.isfinite(data2D.data)] 
    774         qx_data = data2D.qx_data[numpy.isfinite(data2D.data)] 
    775         qy_data = data2D.qy_data[numpy.isfinite(data2D.data)] 
     829        data = data2D.data[np.isfinite(data2D.data)] 
     830        q_data = data2D.q_data[np.isfinite(data2D.data)] 
     831        err_data = data2D.err_data[np.isfinite(data2D.data)] 
     832        qx_data = data2D.qx_data[np.isfinite(data2D.data)] 
     833        qy_data = data2D.qy_data[np.isfinite(data2D.data)] 
     834 
    776835        dq_data = None 
    777  
    778         # Get the dq for resolution averaging 
    779836        if data2D.dqx_data is not None and data2D.dqy_data is not None: 
    780             # The pinholes and det. pix contribution present 
    781             # in both direction of the 2D which must be subtracted when 
    782             # converting to 1D: dq_overlap should calculated ideally at 
    783             # q = 0. 
    784             # Extrapolate dqy(perp) at q = 0 
    785             z_max = max(data2D.q_data) 
    786             z_min = min(data2D.q_data) 
    787             x_max = data2D.dqx_data[data2D.q_data[z_max]] 
    788             x_min = data2D.dqx_data[data2D.q_data[z_min]] 
    789             y_max = data2D.dqy_data[data2D.q_data[z_max]] 
    790             y_min = data2D.dqy_data[data2D.q_data[z_min]] 
    791             # Find qdx at q = 0 
    792             dq_overlap_x = (x_min * z_max - x_max * z_min) / (z_max - z_min) 
    793             # when extrapolation goes wrong 
    794             if dq_overlap_x > min(data2D.dqx_data): 
    795                 dq_overlap_x = min(data2D.dqx_data) 
    796             dq_overlap_x *= dq_overlap_x 
    797             # Find qdx at q = 0 
    798             dq_overlap_y = (y_min * z_max - y_max * z_min) / (z_max - z_min) 
    799             # when extrapolation goes wrong 
    800             if dq_overlap_y > min(data2D.dqy_data): 
    801                 dq_overlap_y = min(data2D.dqy_data) 
    802             # get dq at q=0. 
    803             dq_overlap_y *= dq_overlap_y 
    804  
    805             dq_overlap = numpy.sqrt((dq_overlap_x + dq_overlap_y) / 2.0) 
    806             if dq_overlap < 0: 
    807                 dq_overlap = y_min 
    808             dqx_data = data2D.dqx_data[numpy.isfinite(data2D.data)] 
    809             dqy_data = data2D.dqy_data[numpy.isfinite(data2D.data)] - dq_overlap 
    810             # def; dqx_data = dq_r dqy_data = dq_phi 
    811             # Convert dq 2D to 1D here 
    812             dqx = dqx_data * dqx_data 
    813             dqy = dqy_data * dqy_data 
    814             dq_data = numpy.add(dqx, dqy) 
    815             dq_data = numpy.sqrt(dq_data) 
    816  
    817         #set space for 1d outputs 
    818         x = numpy.zeros(self.nbins) 
    819         y = numpy.zeros(self.nbins) 
    820         y_err = numpy.zeros(self.nbins) 
    821         x_err = numpy.zeros(self.nbins) 
    822         y_counts = numpy.zeros(self.nbins) 
     837            dq_data = get_dq_data(data2D) 
     838 
     839        # set space for 1d outputs 
     840        x = np.zeros(self.nbins) 
     841        y = np.zeros(self.nbins) 
     842        y_err = np.zeros(self.nbins) 
     843        x_err = np.zeros(self.nbins) 
     844        y_counts = np.zeros(self.nbins)  # Cycle counts (for the mean) 
    823845 
    824846        # Get the min and max into the region: 0 <= phi < 2Pi 
     
    826848        phi_max = flip_phi(self.phi_max) 
    827849 
     850        #  binning object 
     851        if run.lower() == 'phi': 
     852            binning = Binning(self.phi_min, self.phi_max, self.nbins, self.base) 
     853        else: 
     854            binning = Binning(self.r_min, self.r_max, self.nbins, self.base) 
     855 
    828856        for n in range(len(data)): 
    829             frac = 0 
    830857 
    831858            # q-value at the pixel (j,i) 
     
    837864 
    838865            # phi-value of the pixel (j,i) 
    839             phi_value = math.atan2(qy_data[n], qx_data[n]) + Pi 
    840  
    841             ## No need to calculate the frac when all data are within range 
    842             if self.r_min <= q_value and q_value <= self.r_max: 
    843                 frac = 1 
    844             if frac == 0: 
     866            phi_value = math.atan2(qy_data[n], qx_data[n]) + math.pi 
     867 
     868            # No need to calculate: data outside of the radius 
     869            if self.r_min > q_value or q_value > self.r_max: 
    845870                continue 
    846             #In case of two ROIs (symmetric major and minor regions)(for 'q2') 
     871 
     872            # In case of two ROIs (symmetric major and minor regions)(for 'q2') 
    847873            if run.lower() == 'q2': 
    848                 ## For minor sector wing 
     874                # For minor sector wing 
    849875                # Calculate the minor wing phis 
    850                 phi_min_minor = flip_phi(phi_min - Pi) 
    851                 phi_max_minor = flip_phi(phi_max - Pi) 
     876                phi_min_minor = flip_phi(phi_min - math.pi) 
     877                phi_max_minor = flip_phi(phi_max - math.pi) 
    852878                # Check if phis of the minor ring is within 0 to 2pi 
    853879                if phi_min_minor > phi_max_minor: 
    854                     is_in = (phi_value > phi_min_minor or \ 
    855                               phi_value < phi_max_minor) 
     880                    is_in = (phi_value > phi_min_minor or 
     881                             phi_value < phi_max_minor) 
    856882                else: 
    857                     is_in = (phi_value > phi_min_minor and \ 
    858                               phi_value < phi_max_minor) 
    859  
    860             #For all cases(i.e.,for 'q', 'q2', and 'phi') 
    861             #Find pixels within ROI 
     883                    is_in = (phi_value > phi_min_minor and 
     884                             phi_value < phi_max_minor) 
     885 
     886            # For all cases(i.e.,for 'q', 'q2', and 'phi') 
     887            # Find pixels within ROI 
    862888            if phi_min > phi_max: 
    863                 is_in = is_in or (phi_value > phi_min or \ 
    864                                    phi_value < phi_max) 
     889                is_in = is_in or (phi_value > phi_min or 
     890                                  phi_value < phi_max) 
    865891            else: 
    866                 is_in = is_in or (phi_value >= phi_min  and \ 
    867                                     phi_value < phi_max) 
    868  
     892                is_in = is_in or (phi_value >= phi_min and 
     893                                  phi_value < phi_max) 
     894 
     895            # data oustide of the phi range 
    869896            if not is_in: 
    870                 frac = 0 
    871             if frac == 0: 
    872897                continue 
    873             # Check which type of averaging we need 
     898 
     899            # Get the binning index 
    874900            if run.lower() == 'phi': 
    875                 temp_x = (self.nbins) * (phi_value - self.phi_min) 
    876                 temp_y = (self.phi_max - self.phi_min) 
    877                 i_bin = int(math.floor(temp_x / temp_y)) 
     901                i_bin = binning.get_bin_index(phi_value) 
    878902            else: 
    879                 temp_x = (self.nbins) * (q_value - self.r_min) 
    880                 temp_y = (self.r_max - self.r_min) 
    881                 i_bin = int(math.floor(temp_x / temp_y)) 
     903                i_bin = binning.get_bin_index(q_value) 
    882904 
    883905            # Take care of the edge case at phi = 2pi. 
     
    885907                i_bin = self.nbins - 1 
    886908 
    887             ## Get the total y 
    888             y[i_bin] += frac * data_n 
    889             x[i_bin] += frac * q_value 
     909            # Get the total y 
     910            y[i_bin] += data_n 
     911            x[i_bin] += q_value 
    890912            if err_data[n] is None or err_data[n] == 0.0: 
    891913                if data_n < 0: 
    892914                    data_n = -data_n 
    893                 y_err[i_bin] += frac * frac * data_n 
     915                y_err[i_bin] += data_n 
    894916            else: 
    895                 y_err[i_bin] += frac * frac * err_data[n] * err_data[n] 
     917                y_err[i_bin] += err_data[n]**2 
    896918 
    897919            if dq_data is not None: 
     
    900922                # it should not depend on the number of the q points 
    901923                # in the qr bins. 
    902                 x_err[i_bin] += frac * dq_data[n] 
     924                x_err[i_bin] += dq_data[n] 
    903925            else: 
    904926                x_err = None 
    905             y_counts[i_bin] += frac 
     927            y_counts[i_bin] += 1 
    906928 
    907929        # Organize the results 
     
    918940                # We take the center of ring area, not radius. 
    919941                # This is more accurate than taking the radial center of ring. 
    920                 #delta_r = (self.r_max - self.r_min) / self.nbins 
    921                 #r_inner = self.r_min + delta_r * i 
    922                 #r_outer = r_inner + delta_r 
    923                 #x[i] = math.sqrt((r_inner * r_inner + r_outer * r_outer) / 2) 
     942                # delta_r = (self.r_max - self.r_min) / self.nbins 
     943                # r_inner = self.r_min + delta_r * i 
     944                # r_outer = r_inner + delta_r 
     945                # x[i] = math.sqrt((r_inner * r_inner + r_outer * r_outer) / 2) 
    924946                x[i] = x[i] / y_counts[i] 
    925         y_err[y_err == 0] = numpy.average(y_err) 
    926         idx = (numpy.isfinite(y) & numpy.isfinite(y_err)) 
     947        y_err[y_err == 0] = np.average(y_err) 
     948        idx = (np.isfinite(y) & np.isfinite(y_err)) 
    927949        if x_err is not None: 
    928950            d_x = x_err[idx] / y_counts[idx] 
     
    931953        if not idx.any(): 
    932954            msg = "Average Error: No points inside sector of ROI to average..." 
    933             raise ValueError, msg 
    934         #elif len(y[idx])!= self.nbins: 
     955            raise ValueError(msg) 
     956        # elif len(y[idx])!= self.nbins: 
    935957        #    print "resulted",self.nbins- len(y[idx]), 
    936         #"empty bin(s) due to tight binning..." 
     958        # "empty bin(s) due to tight binning..." 
    937959        return Data1D(x=x[idx], y=y[idx], dy=y_err[idx], dx=d_x) 
    938960 
     
    946968    The number of bin in phi also has to be defined. 
    947969    """ 
     970 
    948971    def __call__(self, data2D): 
    949972        """ 
     
    965988    The number of bin in Q also has to be defined. 
    966989    """ 
     990 
    967991    def __call__(self, data2D): 
    968992        """ 
     
    975999        return self._agv(data2D, 'q2') 
    9761000 
     1001################################################################################ 
    9771002 
    9781003class Ringcut(object): 
     
    9871012    in anti-clockwise starting from the x- axis on the left-hand side 
    9881013    """ 
     1014 
    9891015    def __init__(self, r_min=0, r_max=0, center_x=0, center_y=0): 
    9901016        # Minimum radius 
     
    10071033        """ 
    10081034        if data2D.__class__.__name__ not in ["Data2D", "plottable_2D"]: 
    1009             raise RuntimeError, "Ring cut only take plottable_2D objects" 
     1035            raise RuntimeError("Ring cut only take plottable_2D objects") 
    10101036 
    10111037        # Get data 
    10121038        qx_data = data2D.qx_data 
    10131039        qy_data = data2D.qy_data 
    1014         q_data = numpy.sqrt(qx_data * qx_data + qy_data * qy_data) 
     1040        q_data = np.sqrt(qx_data * qx_data + qy_data * qy_data) 
    10151041 
    10161042        # check whether or not the data point is inside ROI 
     
    10181044        return out 
    10191045 
     1046################################################################################ 
    10201047 
    10211048class Boxcut(object): 
     
    10231050    Find a rectangular 2D region of interest. 
    10241051    """ 
     1052 
    10251053    def __init__(self, x_min=0.0, x_max=0.0, y_min=0.0, y_max=0.0): 
    10261054        # Minimum Qx value [A-1] 
     
    10551083        """ 
    10561084        if data2D.__class__.__name__ not in ["Data2D", "plottable_2D"]: 
    1057             raise RuntimeError, "Boxcut take only plottable_2D objects" 
     1085            raise RuntimeError("Boxcut take only plottable_2D objects") 
    10581086        # Get qx_ and qy_data 
    10591087        qx_data = data2D.qx_data 
     
    10661094        return outx & outy 
    10671095 
     1096################################################################################ 
    10681097 
    10691098class Sectorcut(object): 
     
    10771106    and (phi_max-phi_min) should not be larger than pi 
    10781107    """ 
     1108 
    10791109    def __init__(self, phi_min=0, phi_max=math.pi): 
    10801110        self.phi_min = phi_min 
     
    11061136        """ 
    11071137        if data2D.__class__.__name__ not in ["Data2D", "plottable_2D"]: 
    1108             raise RuntimeError, "Sectorcut take only plottable_2D objects" 
     1138            raise RuntimeError("Sectorcut take only plottable_2D objects") 
    11091139        Pi = math.pi 
    11101140        # Get data 
     
    11131143 
    11141144        # get phi from data 
    1115         phi_data = numpy.arctan2(qy_data, qx_data) 
     1145        phi_data = np.arctan2(qy_data, qx_data) 
    11161146 
    11171147        # Get the min and max into the region: -pi <= phi < Pi 
     
    11201150        # check for major sector 
    11211151        if phi_min_major > phi_max_major: 
    1122             out_major = (phi_min_major <= phi_data) + (phi_max_major > phi_data) 
     1152            out_major = (phi_min_major <= phi_data) + \ 
     1153                (phi_max_major > phi_data) 
    11231154        else: 
    1124             out_major = (phi_min_major <= phi_data) & (phi_max_major > phi_data) 
     1155            out_major = (phi_min_major <= phi_data) & ( 
     1156                phi_max_major > phi_data) 
    11251157 
    11261158        # minor sector 
     
    11321164        if phi_min_minor > phi_max_minor: 
    11331165            out_minor = (phi_min_minor <= phi_data) + \ 
    1134                             (phi_max_minor >= phi_data) 
     1166                (phi_max_minor >= phi_data) 
    11351167        else: 
    11361168            out_minor = (phi_min_minor <= phi_data) & \ 
    1137                             (phi_max_minor >= phi_data) 
     1169                (phi_max_minor >= phi_data) 
    11381170        out = out_major + out_minor 
    11391171 
  • src/sas/sascalc/dataloader/readers/sesans_reader.py

    r9a5097c r149b8f6  
    11""" 
    22    SESANS reader (based on ASCII reader) 
    3      
     3 
    44    Reader for .ses or .sesans file format 
    5      
    6     Jurrian Bakker  
     5 
     6    Jurrian Bakker 
    77""" 
    88import numpy as np 
     
    1818_ZERO = 1e-16 
    1919 
     20 
    2021class Reader: 
    2122    """ 
    2223    Class to load sesans files (6 columns). 
    2324    """ 
    24     ## File type 
     25    # File type 
    2526    type_name = "SESANS" 
    26      
    27     ## Wildcards 
     27 
     28    # Wildcards 
    2829    type = ["SESANS files (*.ses)|*.ses", 
    2930            "SESANS files (*..sesans)|*.sesans"] 
    30     ## List of allowed extensions 
     31    # List of allowed extensions 
    3132    ext = ['.ses', '.SES', '.sesans', '.SESANS'] 
    32      
    33     ## Flag to bypass extension check 
     33 
     34    # Flag to bypass extension check 
    3435    allow_all = True 
    35      
     36 
    3637    def read(self, path): 
    37          
    38 #        print "reader triggered" 
    39          
    4038        """ 
    4139        Load data file 
    42          
     40 
    4341        :param path: file path 
    44          
     42 
    4543        :return: SESANSData1D object, or None 
    46          
     44 
    4745        :raise RuntimeError: when the file can't be opened 
    4846        :raise ValueError: when the length of the data vectors are inconsistent 
     
    5149            basename = os.path.basename(path) 
    5250            _, extension = os.path.splitext(basename) 
    53             if self.allow_all or extension.lower() in self.ext: 
    54                 try: 
    55                     # Read in binary mode since GRASP frequently has no-ascii 
    56                     # characters that brakes the open operation 
    57                     input_f = open(path,'rb') 
    58                 except: 
    59                     raise  RuntimeError, "sesans_reader: cannot open %s" % path 
    60                 buff = input_f.read() 
    61                 lines = buff.splitlines() 
    62                 x  = np.zeros(0) 
    63                 y  = np.zeros(0) 
    64                 dy = np.zeros(0) 
    65                 lam  = np.zeros(0) 
    66                 dlam = np.zeros(0) 
    67                 dx = np.zeros(0) 
    68                  
    69                #temp. space to sort data 
    70                 tx  = np.zeros(0) 
    71                 ty  = np.zeros(0) 
    72                 tdy = np.zeros(0) 
    73                 tlam  = np.zeros(0) 
    74                 tdlam = np.zeros(0) 
    75                 tdx = np.zeros(0) 
    76                 output = Data1D(x=x, y=y, lam=lam, dy=dy, dx=dx, dlam=dlam, isSesans=True) 
    77                 self.filename = output.filename = basename 
     51            if not (self.allow_all or extension.lower() in self.ext): 
     52                raise RuntimeError( 
     53                    "{} has an unrecognized file extension".format(path)) 
     54        else: 
     55            raise RuntimeError("{} is not a file".format(path)) 
     56        with open(path, 'r') as input_f: 
     57            line = input_f.readline() 
     58            params = {} 
     59            while not line.startswith("BEGIN_DATA"): 
     60                terms = line.split() 
     61                if len(terms) >= 2: 
     62                    params[terms[0]] = " ".join(terms[1:]) 
     63                line = input_f.readline() 
     64            self.params = params 
    7865 
    79                 paramnames=[] 
    80                 paramvals=[] 
    81                 zvals=[] 
    82                 dzvals=[] 
    83                 lamvals=[] 
    84                 dlamvals=[] 
    85                 Pvals=[] 
    86                 dPvals=[] 
     66            if "FileFormatVersion" not in self.params: 
     67                raise RuntimeError("SES file missing FileFormatVersion") 
     68            if float(self.params["FileFormatVersion"]) >= 2.0: 
     69                raise RuntimeError("SASView only supports SES version 1") 
    8770 
    88                 for line in lines: 
    89                     # Initial try for CSV (split on ,) 
    90                     line=line.strip() 
    91                     toks = line.split('\t') 
    92                     if len(toks)==2: 
    93                         paramnames.append(toks[0]) 
    94                         paramvals.append(toks[1]) 
    95                     if len(toks)>5: 
    96                         zvals.append(toks[0]) 
    97                         dzvals.append(toks[3]) 
    98                         lamvals.append(toks[4]) 
    99                         dlamvals.append(toks[5]) 
    100                         Pvals.append(toks[1]) 
    101                         dPvals.append(toks[2]) 
    102                     else: 
    103                         continue 
     71            if "SpinEchoLength_unit" not in self.params: 
     72                raise RuntimeError("SpinEchoLength has no units") 
     73            if "Wavelength_unit" not in self.params: 
     74                raise RuntimeError("Wavelength has no units") 
     75            if params["SpinEchoLength_unit"] != params["Wavelength_unit"]: 
     76                raise RuntimeError("The spin echo data has rudely used " 
     77                                   "different units for the spin echo length " 
     78                                   "and the wavelength.  While sasview could " 
     79                                   "handle this instance, it is a violation " 
     80                                   "of the file format and will not be " 
     81                                   "handled by other software.") 
    10482 
    105                 x=[] 
    106                 y=[] 
    107                 lam=[] 
    108                 dx=[] 
    109                 dy=[] 
    110                 dlam=[] 
    111                 lam_header = lamvals[0].split() 
    112                 data_conv_z = None 
    113                 default_z_unit = "A" 
    114                 data_conv_P = None 
    115                 default_p_unit = " " # Adjust unit for axis (L^-3) 
    116                 lam_unit = lam_header[1].replace("[","").replace("]","") 
    117                 if lam_unit == 'AA': 
    118                     lam_unit = 'A' 
    119                 varheader=[zvals[0],dzvals[0],lamvals[0],dlamvals[0],Pvals[0],dPvals[0]] 
    120                 valrange=range(1, len(zvals)) 
    121                 for i in valrange: 
    122                     x.append(float(zvals[i])) 
    123                     y.append(float(Pvals[i])) 
    124                     lam.append(float(lamvals[i])) 
    125                     dy.append(float(dPvals[i])) 
    126                     dx.append(float(dzvals[i])) 
    127                     dlam.append(float(dlamvals[i])) 
     83            headers = input_f.readline().split() 
    12884 
    129                 x,y,lam,dy,dx,dlam = [ 
    130                     np.asarray(v, 'double') 
    131                    for v in (x,y,lam,dy,dx,dlam) 
    132                 ] 
     85            self._insist_header(headers, "SpinEchoLength") 
     86            self._insist_header(headers, "Depolarisation") 
     87            self._insist_header(headers, "Depolarisation_error") 
     88            self._insist_header(headers, "Wavelength") 
    13389 
    134                 input_f.close() 
     90            data = np.loadtxt(input_f) 
    13591 
    136                 output.x, output.x_unit = self._unit_conversion(x, lam_unit, default_z_unit) 
    137                 output.y = y 
    138                 output.y_unit = r'\AA^{-2} cm^{-1}'  # output y_unit added 
    139                 output.dx, output.dx_unit = self._unit_conversion(dx, lam_unit, default_z_unit) 
    140                 output.dy = dy 
    141                 output.lam, output.lam_unit = self._unit_conversion(lam, lam_unit, default_z_unit) 
    142                 output.dlam, output.dlam_unit = self._unit_conversion(dlam, lam_unit, default_z_unit) 
    143                  
    144                 output.xaxis(r"\rm{z}", output.x_unit) 
    145                 output.yaxis(r"\rm{ln(P)/(t \lambda^2)}", output.y_unit)  # Adjust label to ln P/(lam^2 t), remove lam column refs 
     92            if data.shape[1] != len(headers): 
     93                raise RuntimeError( 
     94                    "File has {} headers, but {} columns".format( 
     95                        len(headers), 
     96                        data.shape[1])) 
    14697 
    147                 # Store loading process information 
    148                 output.meta_data['loader'] = self.type_name 
    149                 #output.sample.thickness = float(paramvals[6]) 
    150                 output.sample.name = paramvals[1] 
    151                 output.sample.ID = paramvals[0] 
    152                 zaccept_unit_split = paramnames[7].split("[") 
    153                 zaccept_unit = zaccept_unit_split[1].replace("]","") 
    154                 if zaccept_unit.strip() == r'\AA^-1' or zaccept_unit.strip() == r'\A^-1': 
    155                     zaccept_unit = "1/A" 
    156                 output.sample.zacceptance=(float(paramvals[7]),zaccept_unit) 
    157                 output.vars = varheader 
     98            if not data.size: 
     99                raise RuntimeError("{} is empty".format(path)) 
     100            x = data[:, headers.index("SpinEchoLength")] 
     101            if "SpinEchoLength_error" in headers: 
     102                dx = data[:, headers.index("SpinEchoLength_error")] 
     103            else: 
     104                dx = x * 0.05 
     105            lam = data[:, headers.index("Wavelength")] 
     106            if "Wavelength_error" in headers: 
     107                dlam = data[:, headers.index("Wavelength_error")] 
     108            else: 
     109                dlam = lam * 0.05 
     110            y = data[:, headers.index("Depolarisation")] 
     111            dy = data[:, headers.index("Depolarisation_error")] 
    158112 
    159                 if len(output.x) < 1: 
    160                     raise RuntimeError, "%s is empty" % path 
    161                 return output 
     113            lam_unit = self._unit_fetch("Wavelength") 
     114            x, x_unit = self._unit_conversion(x, "A", 
     115                                              self._unit_fetch( 
     116                                                  "SpinEchoLength")) 
     117            dx, dx_unit = self._unit_conversion( 
     118                dx, lam_unit, 
     119                self._unit_fetch("SpinEchoLength")) 
     120            dlam, dlam_unit = self._unit_conversion( 
     121                dlam, lam_unit, 
     122                self._unit_fetch("Wavelength")) 
     123            y_unit = self._unit_fetch("Depolarisation") 
    162124 
    163         else: 
    164             raise RuntimeError, "%s is not a file" % path 
    165         return None 
     125            output = Data1D(x=x, y=y, lam=lam, dy=dy, dx=dx, dlam=dlam, 
     126                            isSesans=True) 
    166127 
    167     def _unit_conversion(self, value, value_unit, default_unit): 
    168         if has_converter == True and value_unit != default_unit: 
    169             data_conv_q = Converter(value_unit) 
    170             value = data_conv_q(value, units=default_unit) 
     128            output.y_unit = y_unit 
     129            output.x_unit = x_unit 
     130            output.source.wavelength_unit = lam_unit 
     131            output.source.wavelength = lam 
     132            self.filename = output.filename = basename 
     133            output.xaxis(r"\rm{z}", x_unit) 
     134            # Adjust label to ln P/(lam^2 t), remove lam column refs 
     135            output.yaxis(r"\rm{ln(P)/(t \lambda^2)}", y_unit) 
     136            # Store loading process information 
     137            output.meta_data['loader'] = self.type_name 
     138            output.sample.name = params["Sample"] 
     139            output.sample.ID = params["DataFileTitle"] 
     140            output.sample.thickness = self._unit_conversion( 
     141                float(params["Thickness"]), "cm", 
     142                self._unit_fetch("Thickness"))[0] 
     143 
     144            output.sample.zacceptance = ( 
     145                float(params["Theta_zmax"]), 
     146                self._unit_fetch("Theta_zmax")) 
     147 
     148            output.sample.yacceptance = ( 
     149                float(params["Theta_ymax"]), 
     150                self._unit_fetch("Theta_ymax")) 
     151            return output 
     152 
     153    @staticmethod 
     154    def _insist_header(headers, name): 
     155        if name not in headers: 
     156            raise RuntimeError( 
     157                "Missing {} column in spin echo data".format(name)) 
     158 
     159    @staticmethod 
     160    def _unit_conversion(value, value_unit, default_unit): 
     161        """ 
     162        Performs unit conversion on a measurement. 
     163 
     164        :param value: The magnitude of the measurement 
     165        :param value_unit: a string containing the final desired unit 
     166        :param default_unit: string with the units of the original measurement 
     167        :return: The magnitude of the measurement in the new units 
     168        """ 
     169        # (float, string, string) -> float 
     170        if has_converter and value_unit != default_unit: 
     171            data_conv_q = Converter(default_unit) 
     172            value = data_conv_q(value, units=value_unit) 
    171173            new_unit = default_unit 
    172174        else: 
    173175            new_unit = value_unit 
    174176        return value, new_unit 
     177 
     178    def _unit_fetch(self, unit): 
     179        return self.params[unit+"_unit"] 
  • src/sas/sascalc/pr/c_extensions/Cinvertor.c

    r959eb01 rcb62bd5  
    294294} 
    295295 
    296 const char set_has_bck_doc[] = 
     296const char set_est_bck_doc[] = 
    297297        "Sets background flag\n"; 
    298298 
     
    300300 * Sets the maximum distance 
    301301 */ 
    302 static PyObject * set_has_bck(Cinvertor *self, PyObject *args) { 
    303         int has_bck; 
    304  
    305         if (!PyArg_ParseTuple(args, "i", &has_bck)) return NULL; 
    306         self->params.has_bck = has_bck; 
    307         return Py_BuildValue("i", self->params.has_bck); 
    308 } 
    309  
    310 const char get_has_bck_doc[] = 
     302static PyObject * set_est_bck(Cinvertor *self, PyObject *args) { 
     303        int est_bck; 
     304 
     305        if (!PyArg_ParseTuple(args, "i", &est_bck)) return NULL; 
     306        self->params.est_bck = est_bck; 
     307        return Py_BuildValue("i", self->params.est_bck); 
     308} 
     309 
     310const char get_est_bck_doc[] = 
    311311        "Gets background flag\n"; 
    312312 
     
    314314 * Gets the maximum distance 
    315315 */ 
    316 static PyObject * get_has_bck(Cinvertor *self, PyObject *args) { 
    317         return Py_BuildValue("i", self->params.has_bck); 
     316static PyObject * get_est_bck(Cinvertor *self, PyObject *args) { 
     317        return Py_BuildValue("i", self->params.est_bck); 
    318318} 
    319319 
     
    882882        sqrt_alpha = sqrt(self->params.alpha); 
    883883        pi = acos(-1.0); 
    884         offset = (self->params.has_bck==1) ? 0 : 1; 
     884        offset = (self->params.est_bck==1) ? 0 : 1; 
    885885 
    886886    for (j=0; j<nfunc; j++) { 
     
    892892            } 
    893893            if (accept_q(self, self->params.x[i])){ 
    894                 if (self->params.has_bck==1 && j==0) { 
     894                if (self->params.est_bck==1 && j==0) { 
    895895                    a[i*nfunc+j] = 1.0/self->params.err[i]; 
    896896                } else { 
     
    906906        } 
    907907        for (i_r=0; i_r<nr; i_r++){ 
    908             if (self->params.has_bck==1 && j==0) { 
     908            if (self->params.est_bck==1 && j==0) { 
    909909                a[(i_r+self->params.npoints)*nfunc+j] = 0.0; 
    910910            } else { 
     
    10291029                   {"set_slit_height", (PyCFunction)set_slit_height, METH_VARARGS, set_slit_height_doc}, 
    10301030                   {"get_slit_height", (PyCFunction)get_slit_height, METH_VARARGS, get_slit_height_doc}, 
    1031                    {"set_has_bck", (PyCFunction)set_has_bck, METH_VARARGS, set_has_bck_doc}, 
    1032                    {"get_has_bck", (PyCFunction)get_has_bck, METH_VARARGS, get_has_bck_doc}, 
     1031                   {"set_est_bck", (PyCFunction)set_est_bck, METH_VARARGS, set_est_bck_doc}, 
     1032                   {"get_est_bck", (PyCFunction)get_est_bck, METH_VARARGS, get_est_bck_doc}, 
    10331033                   {"get_nx", (PyCFunction)get_nx, METH_VARARGS, get_nx_doc}, 
    10341034                   {"get_ny", (PyCFunction)get_ny, METH_VARARGS, get_ny_doc}, 
  • src/sas/sascalc/pr/c_extensions/invertor.c

    r959eb01 rcb62bd5  
    2020        pars->q_min = -1.0; 
    2121        pars->q_max = -1.0; 
    22         pars->has_bck = 0; 
     22        pars->est_bck = 0; 
    2323} 
    2424 
     
    313313    return sqrt(sum_r2/(2.0*sum)); 
    314314} 
    315  
  • src/sas/sascalc/pr/c_extensions/invertor.h

    r959eb01 rcb62bd5  
    2727    double q_max; 
    2828    /// Flag for whether or not to evalute a constant background while inverting 
    29     int has_bck; 
     29    int est_bck; 
    3030    /// Slit height in units of q [A-1] 
    3131    double slit_height; 
  • src/sas/sascalc/pr/invertor.py

    r45dffa69 rcb62bd5  
    121121         self.q_min, self.q_max, 
    122122         self.x, self.y, 
    123          self.err, self.has_bck, 
     123         self.err, self.est_bck, 
    124124         self.slit_height, self.slit_width) = state 
    125125 
     
    133133                 self.q_min, self.q_max, 
    134134                 self.x, self.y, 
    135                  self.err, self.has_bck, 
     135                 self.err, self.est_bck, 
    136136                 self.slit_height, self.slit_width, 
    137137                ) 
     
    175175        elif name == 'slit_width': 
    176176            return self.set_slit_width(value) 
    177         elif name == 'has_bck': 
     177        elif name == 'est_bck': 
    178178            if value == True: 
    179                 return self.set_has_bck(1) 
     179                return self.set_est_bck(1) 
    180180            elif value == False: 
    181                 return self.set_has_bck(0) 
     181                return self.set_est_bck(0) 
    182182            else: 
    183                 raise ValueError, "Invertor: has_bck can only be True or False" 
     183                raise ValueError, "Invertor: est_bck can only be True or False" 
    184184 
    185185        return Cinvertor.__setattr__(self, name, value) 
     
    220220        elif name == 'slit_width': 
    221221            return self.get_slit_width() 
    222         elif name == 'has_bck': 
    223             value = self.get_has_bck() 
     222        elif name == 'est_bck': 
     223            value = self.get_est_bck() 
    224224            if value == 1: 
    225225                return True 
     
    248248        invertor.y = self.y 
    249249        invertor.err = self.err 
    250         invertor.has_bck = self.has_bck 
     250        invertor.est_bck = self.est_bck 
     251        invertor.background = self.background 
    251252        invertor.slit_height = self.slit_height 
    252253        invertor.slit_width = self.slit_width 
     
    290291        """ 
    291292        # Reset the background value before proceeding 
    292         self.background = 0.0 
    293         return self.lstsq(nfunc, nr=nr) 
     293        # self.background = 0.0 
     294        if not self.est_bck: 
     295            self.y -= self.background 
     296        out, cov = self.lstsq(nfunc, nr=nr) 
     297        if not self.est_bck: 
     298            self.y += self.background 
     299        return out, cov 
    294300 
    295301    def iq(self, out, q): 
     
    454460 
    455461        # If we need to fit the background, add a term 
    456         if self.has_bck == True: 
     462        if self.est_bck == True: 
    457463            nfunc_0 = nfunc 
    458464            nfunc += 1 
     
    500506 
    501507        # Keep a copy of the last output 
    502         if self.has_bck == False: 
    503             self.background = 0 
     508        if self.est_bck == False: 
    504509            self.out = c 
    505510            self.cov = err 
     
    653658        file.write("#slit_width=%g\n" % self.slit_width) 
    654659        file.write("#background=%g\n" % self.background) 
    655         if self.has_bck == True: 
     660        if self.est_bck == True: 
    656661            file.write("#has_bck=1\n") 
    657662        else: 
     
    734739                        toks = line.split('=') 
    735740                        if int(toks[1]) == 1: 
    736                             self.has_bck = True 
     741                            self.est_bck = True 
    737742                        else: 
    738                             self.has_bck = False 
     743                            self.est_bck = False 
    739744 
    740745                    # Now read in the parameters 
  • src/sas/sasgui/guiframe/local_perspectives/plotting/Plotter2D.py

    r7432acb r3e5648b  
    361361                if self.slicer.__class__.__name__ != "BoxSum": 
    362362                    wx_id = ids.next() 
    363                     slicerpop.Append(wx_id, '&Edit Slicer Parameters') 
     363                    name = '&Edit Slicer Parameters and Batch Slicing' 
     364                    slicerpop.Append(wx_id, name) 
    364365                    wx.EVT_MENU(self, wx_id, self._onEditSlicer) 
    365366            slicerpop.AppendSeparator() 
     
    532533 
    533534        """ 
    534         ## Clear current slicer 
     535        # Clear current slicer 
    535536        if self.slicer is not None: 
    536537            self.slicer.clear() 
    537         ## Create a new slicer 
     538        # Create a new slicer 
    538539        self.slicer_z += 1 
    539540        self.slicer = slicer(self, self.subplot, zorder=self.slicer_z) 
    540541        self.subplot.set_ylim(self.data2D.ymin, self.data2D.ymax) 
    541542        self.subplot.set_xlim(self.data2D.xmin, self.data2D.xmax) 
    542         ## Draw slicer 
     543        # Draw slicer 
    543544        self.update() 
    544545        self.slicer.update() 
     
    572573        npt = math.floor(npt) 
    573574        from sas.sascalc.dataloader.manipulations import CircularAverage 
    574         ## compute the maximum radius of data2D 
     575        # compute the maximum radius of data2D 
    575576        self.qmax = max(math.fabs(self.data2D.xmax), 
    576577                        math.fabs(self.data2D.xmin)) 
     
    578579                        math.fabs(self.data2D.ymin)) 
    579580        self.radius = math.sqrt(math.pow(self.qmax, 2) + math.pow(self.ymax, 2)) 
    580         ##Compute beam width 
     581        # Compute beam width 
    581582        bin_width = (self.qmax + self.qmax) / npt 
    582         ## Create data1D circular average of data2D 
     583        # Create data1D circular average of data2D 
    583584        Circle = CircularAverage(r_min=0, r_max=self.radius, 
    584585                                 bin_width=bin_width) 
     
    599600        new_plot.name = "Circ avg " + self.data2D.name 
    600601        new_plot.source = self.data2D.source 
    601         #new_plot.info = self.data2D.info 
     602        # new_plot.info = self.data2D.info 
    602603        new_plot.interactive = True 
    603604        new_plot.detector = self.data2D.detector 
    604605 
    605         ## If the data file does not tell us what the axes are, just assume... 
     606        # If the data file does not tell us what the axes are, just assume... 
    606607        new_plot.xaxis("\\rm{Q}", "A^{-1}") 
    607608        if hasattr(self.data2D, "scale") and \ 
     
    615616        new_plot.id = "Circ avg " + self.data2D.name 
    616617        new_plot.is_data = True 
    617         self.parent.update_theory(data_id=self.data2D.id, \ 
    618                                        theory=new_plot) 
     618        self.parent.update_theory(data_id=self.data2D.id, theory=new_plot) 
    619619        wx.PostEvent(self.parent, 
    620620                     NewPlotEvent(plot=new_plot, title=new_plot.name)) 
     
    630630        """ 
    631631        if self.slicer is not None: 
    632             from SlicerParameters import SlicerParameterPanel 
     632            from parameters_panel_slicer import SlicerParameterPanel 
    633633            dialog = SlicerParameterPanel(self, -1, "Slicer Parameters") 
    634634            dialog.set_slicer(self.slicer.__class__.__name__, 
     
    668668        params = self.slicer.get_params() 
    669669        ## Create a new panel to display results of summation of Data2D 
    670         from slicerpanel import SlicerPanel 
     670        from parameters_panel_boxsum import SlicerPanel 
    671671        win = MDIFrame(self.parent, None, 'None', (100, 200)) 
    672672        new_panel = SlicerPanel(parent=win, id=-1, 
     
    758758        if default_name.count('.') > 0: 
    759759            default_name = default_name.split('.')[0] 
    760         #default_name += "_out" 
    761760        if self.parent is not None: 
    762761            self.parent.show_data2d(data, default_name) 
    763762 
    764763    def modifyGraphAppearance(self, e): 
    765         self.graphApp = graphAppearance(self, 'Modify graph appearance', legend=False) 
     764        self.graphApp = graphAppearance(self, 'Modify graph appearance', 
     765                                        legend=False) 
    766766        self.graphApp.setDefaults(self.grid_on, self.legend_on, 
    767767                                  self.xaxis_label, self.yaxis_label, 
  • src/sas/sasgui/guiframe/local_perspectives/plotting/SectorSlicer.py

    r7432acb r8de66b6  
    3737        ## Absolute value of the Angle between the middle line and any side line 
    3838        self.phi = math.pi / 12 
     39        # Binning base for log/lin binning 
     40        self.bin_base = 0 
    3941        ## Middle line 
    4042        self.main_line = LineInteractor(self, self.base.subplot, color='blue', 
     
    151153        phimin = -self.left_line.phi + self.main_line.theta 
    152154        phimax = self.left_line.phi + self.main_line.theta 
     155        bin_base = self.bin_base 
    153156        if nbins is None: 
    154157            nbins = 20 
    155158        sect = SectorQ(r_min=0.0, r_max=radius, 
    156159                       phi_min=phimin + math.pi, 
    157                        phi_max=phimax + math.pi, nbins=nbins) 
     160                       phi_max=phimax + math.pi, nbins=nbins, base=bin_base) 
    158161 
    159162        sector = sect(self.base.data2D) 
     
    239242        params["Delta_Phi [deg]"] = math.fabs(self.left_line.phi * 180 / math.pi) 
    240243        params["nbins"] = self.nbins 
     244        params["binning base"] = self.bin_base 
    241245        return params 
    242246 
     
    252256        phi = math.fabs(params["Delta_Phi [deg]"] * math.pi / 180) 
    253257        self.nbins = int(params["nbins"]) 
     258        self.bin_base = params["binning base"] 
    254259        self.main_line.theta = main 
    255260        ## Reset the slicer parameters 
  • src/sas/sasgui/perspectives/calculator/model_editor.py

    ra1b8fee r07ec714  
    643643        self.name_hsizer = None 
    644644        self.name_tcl = None 
     645        self.overwrite_cb = None 
    645646        self.desc_sizer = None 
    646647        self.desc_tcl = None 
     
    657658        self.warning = "" 
    658659        #This does not seem to be used anywhere so commenting out for now 
    659         #    -- PDB 2/26/17  
     660        #    -- PDB 2/26/17 
    660661        #self._description = "New Plugin Model" 
    661662        self.function_tcl = None 
     
    689690        #title name [string] 
    690691        name_txt = wx.StaticText(self, -1, 'Function Name : ') 
    691         overwrite_cb = wx.CheckBox(self, -1, "Overwrite existing plugin model of this name?", (10, 10)) 
    692         overwrite_cb.SetValue(False) 
    693         overwrite_cb.SetToolTipString("Overwrite it if already exists?") 
    694         wx.EVT_CHECKBOX(self, overwrite_cb.GetId(), self.on_over_cb) 
     692        self.overwrite_cb = wx.CheckBox(self, -1, "Overwrite existing plugin model of this name?", (10, 10)) 
     693        self.overwrite_cb.SetValue(False) 
     694        self.overwrite_cb.SetToolTipString("Overwrite it if already exists?") 
     695        wx.EVT_CHECKBOX(self, self.overwrite_cb.GetId(), self.on_over_cb) 
    695696        self.name_tcl = wx.TextCtrl(self, -1, size=(PANEL_WIDTH * 3 / 5, -1)) 
    696697        self.name_tcl.Bind(wx.EVT_TEXT_ENTER, self.on_change_name) 
     
    700701        self.name_tcl.SetToolTipString(hint_name) 
    701702        self.name_hsizer.AddMany([(self.name_tcl, 0, wx.LEFT | wx.TOP, 0), 
    702                                   (overwrite_cb, 0, wx.LEFT, 20)]) 
     703                                  (self.overwrite_cb, 0, wx.LEFT, 20)]) 
    703704        self.name_sizer.AddMany([(name_txt, 0, wx.LEFT | wx.TOP, 10), 
    704705                                 (self.name_hsizer, 0, 
     
    740741        self.param_sizer.AddMany([(param_txt, 0, wx.LEFT, 10), 
    741742                                  (self.param_tcl, 1, wx.EXPAND | wx.ALL, 10)]) 
    742          
     743 
    743744        # Parameters with polydispersity 
    744745        pd_param_txt = wx.StaticText(self, -1, 'Fit Parameters requiring ' + \ 
     
    755756        self.pd_param_tcl.setDisplayLineNumbers(True) 
    756757        self.pd_param_tcl.SetToolTipString(pd_param_tip) 
    757          
     758 
    758759        self.param_sizer.AddMany([(pd_param_txt, 0, wx.LEFT, 10), 
    759760                                  (self.pd_param_tcl, 1, wx.EXPAND | wx.ALL, 10)]) 
     
    995996            info = 'Error' 
    996997            color = 'red' 
     998            self.overwrite_cb.SetValue(True) 
     999            self.overwrite_name = True 
    9971000        else: 
    9981001            self._notes = result 
     
    10301033        if has_scipy: 
    10311034            lines.insert(0, 'import scipy') 
    1032          
    1033         # Think about 2D later         
     1035 
     1036        # Think about 2D later 
    10341037        #self.is_2d = func_str.count("#self.ndim = 2") 
    10351038        #line_2d = '' 
    10361039        #if self.is_2d: 
    10371040        #    line_2d = CUSTOM_2D_TEMP.split('\n') 
    1038          
    1039         # Also think about test later         
     1041 
     1042        # Also think about test later 
    10401043        #line_test = TEST_TEMPLATE.split('\n') 
    10411044        #local_params = '' 
     
    10431046        spaces4  = ' '*4 
    10441047        spaces13 = ' '*13 
    1045         spaces16 = ' '*16      
     1048        spaces16 = ' '*16 
    10461049        param_names = []    # to store parameter names 
    10471050        has_scipy = func_str.count("scipy.") 
     
    10551058            out_f.write(line + '\n') 
    10561059            if line.count('#name'): 
    1057                 out_f.write('name = "%s" \n' % name)                
     1060                out_f.write('name = "%s" \n' % name) 
    10581061            elif line.count('#title'): 
    1059                 out_f.write('title = "User model for %s"\n' % name)                
     1062                out_f.write('title = "User model for %s"\n' % name) 
    10601063            elif line.count('#description'): 
    1061                 out_f.write('description = "%s"\n' % desc_str)                
     1064                out_f.write('description = "%s"\n' % desc_str) 
    10621065            elif line.count('#parameters'): 
    10631066                out_f.write('parameters = [ \n') 
     
    10651068                    p_line = param_line.lstrip().rstrip() 
    10661069                    if p_line: 
    1067                         pname, pvalue = self.get_param_helper(p_line) 
     1070                        pname, pvalue, desc = self.get_param_helper(p_line) 
    10681071                        param_names.append(pname) 
    1069                         out_f.write("%s['%s', '', %s, [-numpy.inf, numpy.inf], '', ''],\n" % (spaces16, pname, pvalue)) 
     1072                        out_f.write("%s['%s', '', %s, [-numpy.inf, numpy.inf], '', '%s'],\n" % (spaces16, pname, pvalue, desc)) 
    10701073                for param_line in pd_param_str.split('\n'): 
    10711074                    p_line = param_line.lstrip().rstrip() 
    10721075                    if p_line: 
    1073                         pname, pvalue = self.get_param_helper(p_line) 
     1076                        pname, pvalue, desc = self.get_param_helper(p_line) 
    10741077                        param_names.append(pname) 
    1075                         out_f.write("%s['%s', '', %s, [-numpy.inf, numpy.inf], 'volume', ''],\n" % (spaces16, pname, pvalue)) 
     1078                        out_f.write("%s['%s', '', %s, [-numpy.inf, numpy.inf], 'volume', '%s'],\n" % (spaces16, pname, pvalue, desc)) 
    10761079                out_f.write('%s]\n' % spaces13) 
    1077              
     1080 
    10781081        # No form_volume or ER available in simple model editor 
    10791082        out_f.write('def form_volume(*arg): \n') 
     
    10821085        out_f.write('def ER(*arg): \n') 
    10831086        out_f.write('    return 1.0 \n') 
    1084          
     1087 
    10851088        # function to compute 
    10861089        out_f.write('\n') 
     
    10911094        for func_line in func_str.split('\n'): 
    10921095            out_f.write('%s%s\n' % (spaces4, func_line)) 
    1093          
     1096 
    10941097        Iqxy_string = 'return Iq(numpy.sqrt(x**2+y**2) ' 
    1095              
     1098 
    10961099        out_f.write('\n') 
    10971100        out_f.write('def Iqxy(x, y ') 
     
    11131116        items = line.split(";") 
    11141117        for item in items: 
    1115             name = item.split("=")[0].lstrip().rstrip() 
     1118            name = item.split("=")[0].strip() 
     1119            description = "" 
    11161120            try: 
    1117                 value = item.split("=")[1].lstrip().rstrip() 
     1121                value = item.split("=")[1].strip() 
     1122                if value.count("#"): 
     1123                    # If line ends in a comment, remove it before parsing float 
     1124                    index = value.index("#") 
     1125                    description = value[(index + 1):].strip() 
     1126                    value = value[:value.index("#")].strip() 
    11181127                float(value) 
    1119             except: 
     1128            except ValueError: 
    11201129                value = 1.0 # default 
    11211130 
    1122         return name, value 
     1131        return name, value, description 
    11231132 
    11241133    def set_function_helper(self, line): 
     
    12041213import numpy 
    12051214 
    1206 #name  
     1215#name 
    12071216 
    12081217#title 
     
    12101219#description 
    12111220 
    1212 #parameters  
     1221#parameters 
    12131222 
    12141223""" 
  • src/sas/sasgui/perspectives/calculator/pyconsole.py

    r7432acb r4627657  
    3737    Iqxy = model.evalDistribution([qx, qy]) 
    3838 
    39     result = """ 
    40     Iq(%s) = %s 
    41     Iqxy(%s, %s) = %s 
    42     """%(q, Iq, qx, qy, Iqxy) 
     39    # check the model's unit tests run 
     40    from sasmodels.model_test import run_one 
     41    result = run_one(path) 
    4342 
    4443    return result 
     
    8988        ok = wx.Button(self, wx.ID_OK, "OK") 
    9089 
    91         # Mysterious constraint layouts from  
     90        # Mysterious constraint layouts from 
    9291        # https://www.wxpython.org/docs/api/wx.lib.layoutf.Layoutf-class.html 
    9392        lc = layoutf.Layoutf('t=t5#1;b=t5#2;l=l5#1;r=r5#1', (self,ok)) 
  • src/sas/sasgui/perspectives/fitting/basepage.py

    ra1b8fee ra1b8fee  
    254254        if not hasattr(self, "model_view"): 
    255255            return 
    256         toggle_mode_on = self.model_view.IsEnabled() 
     256        toggle_mode_on = self.model_view.IsEnabled() or self.data is None 
    257257        if toggle_mode_on: 
    258258            if self.enable2D and not check_data_validity(self.data): 
  • src/sas/sasgui/perspectives/fitting/fitting.py

    ra1b8fee r489f53a  
    257257        toks = os.path.splitext(label) 
    258258        path = os.path.join(models.find_plugins_dir(), toks[0]) 
     259        message = "Are you sure you want to delete the file {}?".format(path) 
     260        dlg = wx.MessageDialog(self.frame, message, '', wx.YES_NO | wx.ICON_QUESTION) 
     261        if not dlg.ShowModal() == wx.ID_YES: 
     262            return 
    259263        try: 
    260264            for ext in ['.py', '.pyc']: 
    261265                p_path = path + ext 
     266                if ext == '.pyc' and not os.path.isfile(path + ext): 
     267                    # If model is invalid, .pyc file may not exist as model has 
     268                    # never been compiled. Don't try and delete it 
     269                    continue 
    262270                os.remove(p_path) 
    263271            self.update_custom_combo() 
     
    383391          '(Re)Load all models present in user plugin_models folder') 
    384392        wx.EVT_MENU(owner, wx_id, self.load_plugin_models) 
    385     
     393 
    386394    def set_edit_menu_helper(self, owner=None, menu=None): 
    387395        """ 
     
    17341742            @param unsmeared_error: data error, rescaled to unsmeared model 
    17351743        """ 
    1736         try: 
    1737             np.nan_to_num(y) 
    1738             new_plot = self.create_theory_1D(x, y, page_id, model, data, state, 
    1739                                              data_description=model.name, 
    1740                                              data_id=str(page_id) + " " + data.name) 
    1741             if unsmeared_model is not None: 
    1742                 self.create_theory_1D(x, unsmeared_model, page_id, model, data, state, 
    1743                                       data_description=model.name + " unsmeared", 
    1744                                       data_id=str(page_id) + " " + data.name + " unsmeared") 
    1745  
    1746                 if unsmeared_data is not None and unsmeared_error is not None: 
    1747                     self.create_theory_1D(x, unsmeared_data, page_id, model, data, state, 
    1748                                           data_description="Data unsmeared", 
    1749                                           data_id="Data  " + data.name + " unsmeared", 
    1750                                           dy=unsmeared_error) 
    1751             if sq_model is not None and pq_model is not None: 
    1752                 self.create_theory_1D(x, sq_model, page_id, model, data, state, 
    1753                                       data_description=model.name + " S(q)", 
    1754                                       data_id=str(page_id) + " " + data.name + " S(q)") 
    1755                 self.create_theory_1D(x, pq_model, page_id, model, data, state, 
    1756                                       data_description=model.name + " P(q)", 
    1757                                       data_id=str(page_id) + " " + data.name + " P(q)") 
    1758  
    1759             current_pg = self.fit_panel.get_page_by_id(page_id) 
    1760             title = new_plot.title 
    1761             batch_on = self.fit_panel.get_page_by_id(page_id).batch_on 
    1762             if not batch_on: 
    1763                 wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot, 
    1764                                             title=str(title))) 
    1765             elif plot_result: 
    1766                 top_data_id = self.fit_panel.get_page_by_id(page_id).data.id 
    1767                 if data.id == top_data_id: 
    1768                     wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot, 
    1769                                             title=str(title))) 
    1770             caption = current_pg.window_caption 
    1771             self.page_finder[page_id].set_fit_tab_caption(caption=caption) 
    1772  
    1773             self.page_finder[page_id].set_theory_data(data=new_plot, 
     1744        number_finite = np.count_nonzero(np.isfinite(y)) 
     1745        np.nan_to_num(y) 
     1746        new_plot = self.create_theory_1D(x, y, page_id, model, data, state, 
     1747                                         data_description=model.name, 
     1748                                         data_id=str(page_id) + " " + data.name) 
     1749        if unsmeared_model is not None: 
     1750            self.create_theory_1D(x, unsmeared_model, page_id, model, data, state, 
     1751                                  data_description=model.name + " unsmeared", 
     1752                                  data_id=str(page_id) + " " + data.name + " unsmeared") 
     1753 
     1754            if unsmeared_data is not None and unsmeared_error is not None: 
     1755                self.create_theory_1D(x, unsmeared_data, page_id, model, data, state, 
     1756                                      data_description="Data unsmeared", 
     1757                                      data_id="Data  " + data.name + " unsmeared", 
     1758                                      dy=unsmeared_error) 
     1759        # Comment this out until we can get P*S models with correctly populated parameters 
     1760        if sq_model is not None and pq_model is not None: 
     1761            self.create_theory_1D(x, sq_model, page_id, model, data, state, 
     1762                                  data_description=model.name + " S(q)", 
     1763                                  data_id=str(page_id) + " " + data.name + " S(q)") 
     1764            self.create_theory_1D(x, pq_model, page_id, model, data, state, 
     1765                                  data_description=model.name + " P(q)", 
     1766                                  data_id=str(page_id) + " " + data.name + " P(q)") 
     1767 
     1768        current_pg = self.fit_panel.get_page_by_id(page_id) 
     1769        title = new_plot.title 
     1770        batch_on = self.fit_panel.get_page_by_id(page_id).batch_on 
     1771        if not batch_on: 
     1772            wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot, title=str(title))) 
     1773        elif plot_result: 
     1774            top_data_id = self.fit_panel.get_page_by_id(page_id).data.id 
     1775            if data.id == top_data_id: 
     1776                wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot, title=str(title))) 
     1777        caption = current_pg.window_caption 
     1778        self.page_finder[page_id].set_fit_tab_caption(caption=caption) 
     1779 
     1780        self.page_finder[page_id].set_theory_data(data=new_plot, 
    17741781                                                      fid=data.id) 
    1775             if toggle_mode_on: 
    1776                 wx.PostEvent(self.parent, 
    1777                              NewPlotEvent(group_id=str(page_id) + " Model2D", 
     1782        if toggle_mode_on: 
     1783            wx.PostEvent(self.parent, 
     1784                         NewPlotEvent(group_id=str(page_id) + " Model2D", 
    17781785                                          action="Hide")) 
    1779             else: 
    1780                 if update_chisqr: 
    1781                     wx.PostEvent(current_pg, 
    1782                                  Chi2UpdateEvent(output=self._cal_chisqr( 
     1786        else: 
     1787            if update_chisqr: 
     1788                wx.PostEvent(current_pg, 
     1789                             Chi2UpdateEvent(output=self._cal_chisqr( 
    17831790                                                                data=data, 
    17841791                                                                fid=fid, 
    17851792                                                                weight=weight, 
    1786                                                             page_id=page_id, 
    1787                                                             index=index))) 
    1788                 else: 
    1789                     self._plot_residuals(page_id=page_id, data=data, fid=fid, 
    1790                                          index=index, weight=weight) 
    1791  
     1793                                                                page_id=page_id, 
     1794                                                                index=index))) 
     1795            else: 
     1796                self._plot_residuals(page_id=page_id, data=data, fid=fid, 
     1797                                     index=index, weight=weight) 
     1798 
     1799        if not number_finite: 
     1800            logger.error("Using the present parameters the model does not return any finite value. ") 
     1801            msg = "Computing Error: Model did not return any finite value." 
     1802            wx.PostEvent(self.parent, StatusEvent(status = msg, info="error")) 
     1803        else: 
    17921804            msg = "Computation  completed!" 
     1805            if number_finite != y.size: 
     1806                msg += ' PROBLEM: For some Q values the model returns non finite intensities!' 
     1807                logger.error("For some Q values the model returns non finite intensities.") 
    17931808            wx.PostEvent(self.parent, StatusEvent(status=msg, type="stop")) 
    1794         except: 
    1795             raise 
    17961809 
    17971810    def _calc_exception(self, etype, value, tb): 
     
    18181831        that can be plot. 
    18191832        """ 
     1833        number_finite = np.count_nonzero(np.isfinite(image)) 
    18201834        np.nan_to_num(image) 
    18211835        new_plot = Data2D(image=image, err_image=data.err_data) 
     
    18761890                self._plot_residuals(page_id=page_id, data=data, fid=fid, 
    18771891                                      index=index, weight=weight) 
    1878         msg = "Computation  completed!" 
    1879         wx.PostEvent(self.parent, StatusEvent(status=msg, type="stop")) 
     1892 
     1893        if not number_finite: 
     1894            logger.error("Using the present parameters the model does not return any finite value. ") 
     1895            msg = "Computing Error: Model did not return any finite value." 
     1896            wx.PostEvent(self.parent, StatusEvent(status = msg, info="error")) 
     1897        else: 
     1898            msg = "Computation  completed!" 
     1899            if number_finite != image.size: 
     1900                msg += ' PROBLEM: For some Qx,Qy values the model returns non finite intensities!' 
     1901                logger.error("For some Qx,Qy values the model returns non finite intensities.") 
     1902            wx.PostEvent(self.parent, StatusEvent(status=msg, type="stop")) 
    18801903 
    18811904    def _draw_model2D(self, model, page_id, qmin, 
  • src/sas/sasgui/perspectives/fitting/models.py

    ra1b8fee rb1c2011  
    156156    try: 
    157157        import compileall 
    158         compileall.compile_dir(dir=dir, ddir=dir, force=1, 
     158        compileall.compile_dir(dir=dir, ddir=dir, force=0, 
    159159                               quiet=report_problem) 
    160160    except: 
     
    163163 
    164164 
    165 def _findModels(dir): 
     165def _find_models(): 
    166166    """ 
    167167    Find custom models 
    168168    """ 
    169169    # List of plugin objects 
    170     dir = find_plugins_dir() 
     170    directory = find_plugins_dir() 
    171171    # Go through files in plug-in directory 
    172     if not os.path.isdir(dir): 
    173         msg = "SasView couldn't locate Model plugin folder %r." % dir 
     172    if not os.path.isdir(directory): 
     173        msg = "SasView couldn't locate Model plugin folder %r." % directory 
    174174        logger.warning(msg) 
    175175        return {} 
    176176 
    177     plugin_log("looking for models in: %s" % str(dir)) 
    178     #compile_file(dir)  #always recompile the folder plugin 
    179     logger.info("plugin model dir: %s" % str(dir)) 
     177    plugin_log("looking for models in: %s" % str(directory)) 
     178    # compile_file(directory)  #always recompile the folder plugin 
     179    logger.info("plugin model dir: %s" % str(directory)) 
    180180 
    181181    plugins = {} 
    182     for filename in os.listdir(dir): 
     182    for filename in os.listdir(directory): 
    183183        name, ext = os.path.splitext(filename) 
    184184        if ext == '.py' and not name == '__init__': 
    185             path = os.path.abspath(os.path.join(dir, filename)) 
     185            path = os.path.abspath(os.path.join(directory, filename)) 
    186186            try: 
    187187                model = load_custom_model(path) 
    188                 model.name = PLUGIN_NAME_BASE + model.name 
     188                if not model.name.count(PLUGIN_NAME_BASE): 
     189                    model.name = PLUGIN_NAME_BASE + model.name 
    189190                plugins[model.name] = model 
    190191            except Exception: 
     
    193194                plugin_log(msg) 
    194195                logger.warning("Failed to load plugin %r. See %s for details" 
    195                                 % (path, PLUGIN_LOG)) 
    196              
     196                               % (path, PLUGIN_LOG)) 
     197 
    197198    return plugins 
    198199 
     
    264265        temp = {} 
    265266        if self.is_changed(): 
    266             return  _findModels(dir) 
     267            return  _find_models() 
    267268        logger.info("plugin model : %s" % str(temp)) 
    268269        return temp 
     
    297298        for name, plug in self.stored_plugins.iteritems(): 
    298299            self.model_dictionary[name] = plug 
    299          
     300 
    300301        self._get_multifunc_models() 
    301302 
     
    339340        """ 
    340341        self.plugins = [] 
    341         new_plugins = _findModels(dir) 
     342        new_plugins = _find_models() 
    342343        for name, plug in  new_plugins.iteritems(): 
    343344            for stored_name, stored_plug in self.stored_plugins.iteritems(): 
  • src/sas/sasgui/perspectives/pr/inversion_panel.py

    r7432acb rcb62bd5  
    7070        self.rg_ctl = None 
    7171        self.iq0_ctl = None 
    72         self.bck_chk = None 
     72        self.bck_value = None 
     73        self.bck_est_ctl = None 
     74        self.bck_man_ctl = None 
     75        self.est_bck = True 
     76        self.bck_input = None 
    7377        self.bck_ctl = None 
    7478 
     
    312316        # Read the panel's parameters 
    313317        flag, alpha, dmax, nfunc, qmin, \ 
    314         qmax, height, width = self._read_pars() 
     318        qmax, height, width, bck = self._read_pars() 
    315319 
    316320        state.nfunc = nfunc 
     
    326330 
    327331        # Background evaluation checkbox 
    328         state.estimate_bck = self.bck_chk.IsChecked() 
     332        state.estimate_bck = self.est_bck 
     333        state.bck_value = bck 
    329334 
    330335        # Estimates 
     
    371376        self.plot_data.SetValue(str(state.file)) 
    372377 
    373         # Background evaluation checkbox 
    374         self.bck_chk.SetValue(state.estimate_bck) 
     378        # Background value 
     379        self.bck_est_ctl.SetValue(state.estimate_bck) 
     380        self.bck_man_ctl.SetValue(not state.estimate_bck) 
     381        if not state.estimate_bck: 
     382            self.bck_input.Enable() 
     383            self.bck_input.SetValue(str(state.bck_value)) 
     384        self.est_bck = state.estimate_bck 
     385        self.bck_value = state.bck_value 
    375386 
    376387        # Estimates 
     
    431442                       wx.EXPAND | wx.LEFT | wx.RIGHT | wx.ADJUST_MINSIZE, 15) 
    432443 
    433         self.bck_chk = wx.CheckBox(self, -1, "Estimate background level") 
    434         hint_msg = "Check box to let the fit estimate " 
    435         hint_msg += "the constant background level." 
    436         self.bck_chk.SetToolTipString(hint_msg) 
    437         self.bck_chk.Bind(wx.EVT_CHECKBOX, self._on_pars_changed) 
     444        radio_sizer = wx.GridBagSizer(5, 5) 
     445 
     446        self.bck_est_ctl = wx.RadioButton(self, -1, "Estimate background level", 
     447            name="estimate_bck", style=wx.RB_GROUP) 
     448        self.bck_man_ctl = wx.RadioButton(self, -1, "Input manual background level", 
     449            name="manual_bck") 
     450 
     451        self.bck_est_ctl.Bind(wx.EVT_RADIOBUTTON, self._on_bck_changed) 
     452        self.bck_man_ctl.Bind(wx.EVT_RADIOBUTTON, self._on_bck_changed) 
     453 
     454        radio_sizer.Add(self.bck_est_ctl, (0,0), (1,1), wx.LEFT | wx.EXPAND) 
     455        radio_sizer.Add(self.bck_man_ctl, (0,1), (1,1), wx.RIGHT | wx.EXPAND) 
     456 
    438457        iy += 1 
    439         pars_sizer.Add(self.bck_chk, (iy, 0), (1, 2), 
     458        pars_sizer.Add(radio_sizer, (iy, 0), (1, 2), 
    440459                       wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 15) 
     460 
     461        background_label = wx.StaticText(self, -1, "Background: ") 
     462        self.bck_input = PrTextCtrl(self, -1, style=wx.TE_PROCESS_ENTER, 
     463            size=(60, 20), value="0.0") 
     464        self.bck_input.Disable() 
     465        self.bck_input.Bind(wx.EVT_TEXT, self._read_pars) 
     466        background_units = wx.StaticText(self, -1, "[A^(-1)]", size=(55, 20)) 
     467        iy += 1 
     468 
     469        background_sizer = wx.GridBagSizer(5, 5) 
     470 
     471        background_sizer.Add(background_label, (0, 0), (1,1), 
     472            wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 23) 
     473        background_sizer.Add(self.bck_input, (0, 1), (1,1), 
     474            wx.LEFT | wx.ADJUST_MINSIZE, 5) 
     475        background_sizer.Add(background_units, (0, 2), (1,1), 
     476            wx.LEFT | wx.ADJUST_MINSIZE, 5) 
     477        pars_sizer.Add(background_sizer, (iy, 0), (1, 2), 
     478            wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 15) 
     479 
    441480        boxsizer1.Add(pars_sizer, 0, wx.EXPAND) 
    442481        vbox.Add(boxsizer1, (iy_vb, 0), (1, 1), 
     
    764803        self._on_pars_changed() 
    765804 
     805    def _on_bck_changed(self, evt=None): 
     806        self.est_bck = self.bck_est_ctl.GetValue() 
     807        if self.est_bck: 
     808            self.bck_input.Disable() 
     809        else: 
     810            self.bck_input.Enable() 
     811 
    766812    def _on_pars_changed(self, evt=None): 
    767813        """ 
     
    770816        scenes. 
    771817        """ 
    772         flag, alpha, dmax, nfunc, qmin, qmax, height, width = self._read_pars() 
    773         has_bck = self.bck_chk.IsChecked() 
     818        flag, alpha, dmax, nfunc, qmin, qmax, height, width, bck = self._read_pars() 
    774819 
    775820        # If the pars are valid, estimate alpha 
     
    783828                                                      d_max=dmax, 
    784829                                                      q_min=qmin, q_max=qmax, 
    785                                                       bck=has_bck, 
     830                                                      est_bck=self.est_bck, 
     831                                                      bck_val=bck, 
    786832                                                      height=height, 
    787833                                                      width=width) 
     
    797843        height = 0 
    798844        width = 0 
     845        background = 0 
    799846        flag = True 
    800847        # Read slit height 
     
    890937            self.qmax_ctl.Refresh() 
    891938 
    892         return flag, alpha, dmax, nfunc, qmin, qmax, height, width 
     939        # Read background 
     940        if not self.est_bck: 
     941            try: 
     942                bck_str = self.bck_input.GetValue() 
     943                if len(bck_str.strip()) == 0: 
     944                    background = 0.0 
     945                else: 
     946                    background = float(bck_str) 
     947                    self.bck_input.SetBackgroundColour(wx.WHITE) 
     948            except ValueError: 
     949                background = 0.0 
     950                self.bck_input.SetBackgroundColour("pink") 
     951            self.bck_input.Refresh() 
     952 
     953        return flag, alpha, dmax, nfunc, qmin, qmax, height, width, background 
    893954 
    894955    def _on_explore(self, evt): 
     
    915976        # Push it to the manager 
    916977 
    917         flag, alpha, dmax, nfunc, qmin, qmax, height, width = self._read_pars() 
    918         has_bck = self.bck_chk.IsChecked() 
     978        flag, alpha, dmax, nfunc, qmin, qmax, height, width, bck = self._read_pars() 
    919979 
    920980        if flag: 
     
    928988                                                   d_max=dmax, 
    929989                                                   q_min=qmin, q_max=qmax, 
    930                                                    bck=has_bck, 
     990                                                   est_bck=self.est_bck, 
     991                                                   bck_val = bck, 
    931992                                                   height=height, 
    932993                                                   width=width) 
  • src/sas/sasgui/perspectives/pr/inversion_state.py

    r7432acb ra0e6b1b  
    3636           ["qmin", "qmin"], 
    3737           ["qmax", "qmax"], 
    38            ["estimate_bck", "estimate_bck"]] 
     38           ["estimate_bck", "estimate_bck"], 
     39           ["bck_value", "bck_value"]] 
    3940 
    4041## List of P(r) inversion outputs 
     
    6263        self.estimate_bck = False 
    6364        self.timestamp = time.time() 
     65        self.bck_value = 0.0 
    6466 
    6567        # Inversion parameters 
     
    109111        state += "Timestamp:    %s\n" % self.timestamp 
    110112        state += "Estimate bck: %s\n" % str(self.estimate_bck) 
     113        state += "Bck Value:    %s\n" % str(self.bck_value) 
    111114        state += "No. terms:    %s\n" % str(self.nfunc) 
    112115        state += "D_max:        %s\n" % str(self.d_max) 
     
    296299                            self.coefficients.append(float(c)) 
    297300                        except: 
    298                             # Bad data, skip. We will count the number of  
    299                             # coefficients at the very end and deal with  
     301                            # Bad data, skip. We will count the number of 
     302                            # coefficients at the very end and deal with 
    300303                            # inconsistencies then. 
    301304                            pass 
     
    329332                                cov_row.append(float(c)) 
    330333                            except: 
    331                                 # Bad data, skip. We will count the number of  
    332                                 # coefficients at the very end and deal with  
     334                                # Bad data, skip. We will count the number of 
     335                                # coefficients at the very end and deal with 
    333336                                # inconsistencies then. 
    334337                                pass 
     
    461464                tree = etree.parse(path, parser=etree.ETCompatXMLParser()) 
    462465                # Check the format version number 
    463                 # Specifying the namespace will take care of the file  
    464                 #format version  
     466                # Specifying the namespace will take care of the file 
     467                #format version 
    465468                root = tree.getroot() 
    466469 
  • src/sas/sasgui/perspectives/pr/media/pr_help.rst

    r1221196 r1abd19c  
    4949P(r) inversion requires that the background be perfectly subtracted.  This is 
    5050often difficult to do well and thus many data sets will include a background. 
    51 For those cases, the user should check the "estimate background" box and the 
    52 module will do its best to estimate it. 
     51For those cases, the user should check the "Estimate background level" option 
     52and the module will do its best to estimate it. If you know the background value 
     53for your data, select the "Input manual background level" option. Note that 
     54this value will be treated as having 0 error. 
    5355 
    5456The P(r) module is constantly computing in the background what the optimum 
  • src/sas/sasgui/perspectives/pr/pr.py

    ra1b8fee rcb62bd5  
    6868        self.q_min = None 
    6969        self.q_max = None 
    70         self.has_bck = False 
     70        self.est_bck = False 
     71        self.bck_val = 0 
    7172        self.slit_height = 0 
    7273        self.slit_width = 0 
     
    828829        self.control_panel.iq0 = pr.iq0(out) 
    829830        self.control_panel.bck = pr.background 
     831        self.control_panel.bck_input.SetValue("{:.2g}".format(pr.background)) 
    830832 
    831833        # Show I(q) fit 
     
    907909 
    908910    def setup_plot_inversion(self, alpha, nfunc, d_max, q_min=None, q_max=None, 
    909                              bck=False, height=0, width=0): 
     911                             est_bck=False, bck_val=0, height=0, width=0): 
    910912        """ 
    911913            Set up inversion from plotted data 
     
    916918        self.q_min = q_min 
    917919        self.q_max = q_max 
    918         self.has_bck = bck 
     920        self.est_bck = est_bck 
     921        self.bck_val = bck_val 
    919922        self.slit_height = height 
    920923        self.slit_width = width 
     
    930933    def estimate_plot_inversion(self, alpha, nfunc, d_max, 
    931934                                q_min=None, q_max=None, 
    932                                 bck=False, height=0, width=0): 
     935                                est_bck=False, bck_val=0, height=0, width=0): 
    933936        """ 
    934937            Estimate parameters from plotted data 
     
    939942        self.q_min = q_min 
    940943        self.q_max = q_max 
    941         self.has_bck = bck 
     944        self.est_bck = est_bck 
     945        self.bck_val = bck_val 
    942946        self.slit_height = height 
    943947        self.slit_width = width 
     
    973977        pr.x = self.current_plottable.x 
    974978        pr.y = self.current_plottable.y 
    975         pr.has_bck = self.has_bck 
     979        pr.est_bck = self.est_bck 
    976980        pr.slit_height = self.slit_height 
    977981        pr.slit_width = self.slit_width 
     982        pr.background = self.bck_val 
    978983 
    979984        # Keep track of the plot window title to ensure that 
     
    10191024        self.q_min = q_min 
    10201025        self.q_max = q_max 
    1021         self.has_bck = bck 
     1026        self.est_bck = bck 
    10221027        self.slit_height = height 
    10231028        self.slit_width = width 
     
    10421047        self.q_min = q_min 
    10431048        self.q_max = q_max 
    1044         self.has_bck = bck 
     1049        self.est_bck = bck 
    10451050        self.slit_height = height 
    10461051        self.slit_width = width 
     
    11151120            pr.y = y 
    11161121            pr.err = err 
    1117             pr.has_bck = self.has_bck 
     1122            pr.est_bck = self.est_bck 
    11181123            pr.slit_height = self.slit_height 
    11191124            pr.slit_width = self.slit_width 
  • test/pr_inversion/test/utest_invertor.py

    raaf5e49 rcb62bd5  
    6868            self.x_in[i] = 1.0*(i+1) 
    6969 
    70     def test_has_bck_flag(self): 
    71         """ 
    72             Tests the has_bck flag operations 
    73         """ 
    74         self.assertEqual(self.invertor.has_bck, False) 
    75         self.invertor.has_bck=True 
    76         self.assertEqual(self.invertor.has_bck, True) 
     70    def test_est_bck_flag(self): 
     71        """ 
     72            Tests the est_bck flag operations 
     73        """ 
     74        self.assertEqual(self.invertor.est_bck, False) 
     75        self.invertor.est_bck=True 
     76        self.assertEqual(self.invertor.est_bck, True) 
    7777        def doit_float(): 
    78             self.invertor.has_bck  = 2.0 
     78            self.invertor.est_bck  = 2.0 
    7979        def doit_str(): 
    80             self.invertor.has_bck  = 'a' 
     80            self.invertor.est_bck  = 'a' 
    8181 
    8282        self.assertRaises(ValueError, doit_float) 
  • test/sasdataloader/test/utest_averaging.py

    r9a5097c re123eb9  
    11 
     2import math 
     3import os 
    24import unittest 
    3 import math 
    4  
    5 from sas.sascalc.dataloader.loader import  Loader 
    6 from sas.sascalc.dataloader.manipulations import Ring, CircularAverage, SectorPhi, get_q,reader2D_converter 
    7  
     5from scipy.stats import binned_statistic_2d 
    86import numpy as np 
     7 
    98import sas.sascalc.dataloader.data_info as data_info 
     9from sas.sascalc.dataloader.loader import Loader 
     10from sas.sascalc.dataloader.manipulations import (Boxavg, Boxsum, 
     11                                                  CircularAverage, Ring, 
     12                                                  SectorPhi, SectorQ, SlabX, 
     13                                                  SlabY, get_q, 
     14                                                  reader2D_converter) 
     15 
    1016 
    1117class Averaging(unittest.TestCase): 
     
    1319        Test averaging manipulations on a flat distribution 
    1420    """ 
     21 
    1522    def setUp(self): 
    1623        """ 
     
    1825            should return the predefined height of the distribution (1.0). 
    1926        """ 
    20         x_0  = np.ones([100,100]) 
    21         dx_0 = np.ones([100,100]) 
    22          
     27        x_0 = np.ones([100, 100]) 
     28        dx_0 = np.ones([100, 100]) 
     29 
    2330        self.data = data_info.Data2D(data=x_0, err_data=dx_0) 
    2431        detector = data_info.Detector() 
    25         detector.distance = 1000.0  #mm 
    26         detector.pixel_size.x = 1.0 #mm 
    27         detector.pixel_size.y = 1.0 #mm 
    28          
     32        detector.distance = 1000.0  # mm 
     33        detector.pixel_size.x = 1.0  # mm 
     34        detector.pixel_size.y = 1.0  # mm 
     35 
    2936        # center in pixel position = (len(x_0)-1)/2 
    30         detector.beam_center.x = (len(x_0)-1)/2 #pixel number 
    31         detector.beam_center.y = (len(x_0)-1)/2 #pixel number 
     37        detector.beam_center.x = (len(x_0) - 1) / 2  # pixel number 
     38        detector.beam_center.y = (len(x_0) - 1) / 2  # pixel number 
    3239        self.data.detector.append(detector) 
    33          
     40 
    3441        source = data_info.Source() 
    35         source.wavelength = 10.0 #A 
     42        source.wavelength = 10.0  # A 
    3643        self.data.source = source 
    37          
    38         # get_q(dx, dy, det_dist, wavelength) where units are mm,mm,mm,and A respectively. 
     44 
     45        # get_q(dx, dy, det_dist, wavelength) where units are mm,mm,mm,and A 
     46        # respectively. 
    3947        self.qmin = get_q(1.0, 1.0, detector.distance, source.wavelength) 
    4048 
    4149        self.qmax = get_q(49.5, 49.5, detector.distance, source.wavelength) 
    42          
     50 
    4351        self.qstep = len(x_0) 
    44         x=  np.linspace(start= -1*self.qmax, 
    45                                stop= self.qmax, 
    46                                num= self.qstep, 
    47                                endpoint=True )   
    48         y = np.linspace(start= -1*self.qmax, 
    49                                stop= self.qmax, 
    50                                num= self.qstep, 
    51                                endpoint=True ) 
    52         self.data.x_bins=x 
    53         self.data.y_bins=y 
     52        x = np.linspace(start=-1 * self.qmax, 
     53                        stop=self.qmax, 
     54                        num=self.qstep, 
     55                        endpoint=True) 
     56        y = np.linspace(start=-1 * self.qmax, 
     57                        stop=self.qmax, 
     58                        num=self.qstep, 
     59                        endpoint=True) 
     60        self.data.x_bins = x 
     61        self.data.y_bins = y 
    5462        self.data = reader2D_converter(self.data) 
    55              
     63 
    5664    def test_ring_flat_distribution(self): 
    5765        """ 
    5866            Test ring averaging 
    5967        """ 
    60         r = Ring(r_min=2*self.qmin, r_max=5*self.qmin,  
    61                  center_x=self.data.detector[0].beam_center.x,  
     68        r = Ring(r_min=2 * self.qmin, r_max=5 * self.qmin, 
     69                 center_x=self.data.detector[0].beam_center.x, 
    6270                 center_y=self.data.detector[0].beam_center.y) 
    6371        r.nbins_phi = 20 
    64          
     72 
    6573        o = r(self.data) 
    6674        for i in range(20): 
    6775            self.assertEqual(o.y[i], 1.0) 
    68              
     76 
    6977    def test_sectorphi_full(self): 
    7078        """ 
    7179            Test sector averaging 
    7280        """ 
    73         r = SectorPhi(r_min=self.qmin, r_max=3*self.qmin,  
    74                       phi_min=0, phi_max=math.pi*2.0) 
     81        r = SectorPhi(r_min=self.qmin, r_max=3 * self.qmin, 
     82                      phi_min=0, phi_max=math.pi * 2.0) 
    7583        r.nbins_phi = 20 
    7684        o = r(self.data) 
    7785        for i in range(7): 
    7886            self.assertEqual(o.y[i], 1.0) 
    79              
    80              
     87 
    8188    def test_sectorphi_partial(self): 
    8289        """ 
    8390        """ 
    8491        phi_max = math.pi * 1.5 
    85         r = SectorPhi(r_min=self.qmin, r_max=3*self.qmin,  
     92        r = SectorPhi(r_min=self.qmin, r_max=3 * self.qmin, 
    8693                      phi_min=0, phi_max=phi_max) 
    8794        self.assertEqual(r.phi_max, phi_max) 
     
    9198        for i in range(17): 
    9299            self.assertEqual(o.y[i], 1.0) 
    93              
    94              
    95  
    96 class data_info_tests(unittest.TestCase): 
    97      
     100 
     101 
     102class DataInfoTests(unittest.TestCase): 
     103 
    98104    def setUp(self): 
    99         self.data = Loader().load('MAR07232_rest.ASC') 
    100          
     105        filepath = os.path.join(os.path.dirname( 
     106            os.path.realpath(__file__)), 'MAR07232_rest.ASC') 
     107        self.data = Loader().load(filepath) 
     108 
    101109    def test_ring(self): 
    102110        """ 
    103111            Test ring averaging 
    104112        """ 
    105         r = Ring(r_min=.005, r_max=.01,  
    106                  center_x=self.data.detector[0].beam_center.x,  
     113        r = Ring(r_min=.005, r_max=.01, 
     114                 center_x=self.data.detector[0].beam_center.x, 
    107115                 center_y=self.data.detector[0].beam_center.y, 
    108                  nbins = 20) 
     116                 nbins=20) 
    109117        ##r.nbins_phi = 20 
    110          
    111         o = r(self.data) 
    112         answer = Loader().load('ring_testdata.txt') 
    113          
     118 
     119        o = r(self.data) 
     120        filepath = os.path.join(os.path.dirname( 
     121            os.path.realpath(__file__)), 'ring_testdata.txt') 
     122        answer = Loader().load(filepath) 
     123 
    114124        for i in range(r.nbins_phi - 1): 
    115125            self.assertAlmostEqual(o.x[i + 1], answer.x[i], 4) 
    116126            self.assertAlmostEqual(o.y[i + 1], answer.y[i], 4) 
    117127            self.assertAlmostEqual(o.dy[i + 1], answer.dy[i], 4) 
    118              
     128 
    119129    def test_circularavg(self): 
    120130        """ 
     131        Test circular averaging 
     132        The test data was not generated by IGOR. 
     133        """ 
     134        r = CircularAverage(r_min=.00, r_max=.025, 
     135                            bin_width=0.0003) 
     136        r.nbins_phi = 20 
     137 
     138        o = r(self.data) 
     139 
     140        filepath = os.path.join(os.path.dirname( 
     141            os.path.realpath(__file__)), 'avg_testdata.txt') 
     142        answer = Loader().load(filepath) 
     143        for i in range(r.nbins_phi): 
     144            self.assertAlmostEqual(o.x[i], answer.x[i], 4) 
     145            self.assertAlmostEqual(o.y[i], answer.y[i], 4) 
     146            self.assertAlmostEqual(o.dy[i], answer.dy[i], 4) 
     147 
     148    def test_box(self): 
     149        """ 
    121150            Test circular averaging 
    122151            The test data was not generated by IGOR. 
    123152        """ 
    124         r = CircularAverage(r_min=.00, r_max=.025,  
    125                  bin_width=0.0003) 
    126         r.nbins_phi = 20 
    127          
    128         o = r(self.data) 
    129  
    130         answer = Loader().load('avg_testdata.txt') 
    131         for i in range(r.nbins_phi): 
    132             self.assertAlmostEqual(o.x[i], answer.x[i], 4) 
    133             self.assertAlmostEqual(o.y[i], answer.y[i], 4) 
    134             self.assertAlmostEqual(o.dy[i], answer.dy[i], 4) 
    135              
    136     def test_box(self): 
    137         """ 
    138             Test circular averaging 
    139             The test data was not generated by IGOR. 
    140         """ 
    141         from sas.sascalc.dataloader.manipulations import Boxsum, Boxavg 
    142          
     153 
    143154        r = Boxsum(x_min=.01, x_max=.015, y_min=0.01, y_max=0.015) 
    144155        s, ds, npoints = r(self.data) 
    145156        self.assertAlmostEqual(s, 34.278990899999997, 4) 
    146157        self.assertAlmostEqual(ds, 7.8007981835194293, 4) 
    147         self.assertAlmostEqual(npoints, 324.0000, 4)         
    148      
     158        self.assertAlmostEqual(npoints, 324.0000, 4) 
     159 
    149160        r = Boxavg(x_min=.01, x_max=.015, y_min=0.01, y_max=0.015) 
    150161        s, ds = r(self.data) 
    151162        self.assertAlmostEqual(s, 0.10579935462962962, 4) 
    152163        self.assertAlmostEqual(ds, 0.024076537603455028, 4) 
    153              
     164 
    154165    def test_slabX(self): 
    155166        """ 
     
    157168            The test data was not generated by IGOR. 
    158169        """ 
    159         from sas.sascalc.dataloader.manipulations import SlabX 
    160          
    161         r = SlabX(x_min=-.01, x_max=.01, y_min=-0.0002, y_max=0.0002, bin_width=0.0004) 
     170 
     171        r = SlabX(x_min=-.01, x_max=.01, y_min=-0.0002, 
     172                  y_max=0.0002, bin_width=0.0004) 
    162173        r.fold = False 
    163174        o = r(self.data) 
    164175 
    165         answer = Loader().load('slabx_testdata.txt') 
    166         for i in range(len(o.x)): 
    167             self.assertAlmostEqual(o.x[i], answer.x[i], 4) 
    168             self.assertAlmostEqual(o.y[i], answer.y[i], 4) 
    169             self.assertAlmostEqual(o.dy[i], answer.dy[i], 4) 
    170              
     176        filepath = os.path.join(os.path.dirname( 
     177            os.path.realpath(__file__)), 'slabx_testdata.txt') 
     178        answer = Loader().load(filepath) 
     179        for i in range(len(o.x)): 
     180            self.assertAlmostEqual(o.x[i], answer.x[i], 4) 
     181            self.assertAlmostEqual(o.y[i], answer.y[i], 4) 
     182            self.assertAlmostEqual(o.dy[i], answer.dy[i], 4) 
     183 
    171184    def test_slabY(self): 
    172185        """ 
     
    174187            The test data was not generated by IGOR. 
    175188        """ 
    176         from sas.sascalc.dataloader.manipulations import SlabY 
    177          
    178         r = SlabY(x_min=.005, x_max=.01, y_min=-0.01, y_max=0.01, bin_width=0.0004) 
     189 
     190        r = SlabY(x_min=.005, x_max=.01, y_min=- 
     191                  0.01, y_max=0.01, bin_width=0.0004) 
    179192        r.fold = False 
    180193        o = r(self.data) 
    181194 
    182         answer = Loader().load('slaby_testdata.txt') 
    183         for i in range(len(o.x)): 
    184             self.assertAlmostEqual(o.x[i], answer.x[i], 4) 
    185             self.assertAlmostEqual(o.y[i], answer.y[i], 4) 
    186             self.assertAlmostEqual(o.dy[i], answer.dy[i], 4) 
    187              
     195        filepath = os.path.join(os.path.dirname( 
     196            os.path.realpath(__file__)), 'slaby_testdata.txt') 
     197        answer = Loader().load(filepath) 
     198        for i in range(len(o.x)): 
     199            self.assertAlmostEqual(o.x[i], answer.x[i], 4) 
     200            self.assertAlmostEqual(o.y[i], answer.y[i], 4) 
     201            self.assertAlmostEqual(o.dy[i], answer.dy[i], 4) 
     202 
    188203    def test_sectorphi_full(self): 
    189204        """ 
     
    193208            The test data was not generated by IGOR. 
    194209        """ 
    195         from sas.sascalc.dataloader.manipulations import SectorPhi 
    196         import math 
    197          
     210 
    198211        nbins = 19 
    199212        phi_min = math.pi / (nbins + 1) 
    200213        phi_max = math.pi * 2 - phi_min 
    201          
     214 
    202215        r = SectorPhi(r_min=.005, 
    203216                      r_max=.01, 
     
    207220        o = r(self.data) 
    208221 
    209         answer = Loader().load('ring_testdata.txt') 
    210         for i in range(len(o.x)): 
    211             self.assertAlmostEqual(o.x[i], answer.x[i], 4) 
    212             self.assertAlmostEqual(o.y[i], answer.y[i], 4) 
    213             self.assertAlmostEqual(o.dy[i], answer.dy[i], 4) 
    214              
     222        filepath = os.path.join(os.path.dirname( 
     223            os.path.realpath(__file__)), 'ring_testdata.txt') 
     224        answer = Loader().load(filepath) 
     225        for i in range(len(o.x)): 
     226            self.assertAlmostEqual(o.x[i], answer.x[i], 4) 
     227            self.assertAlmostEqual(o.y[i], answer.y[i], 4) 
     228            self.assertAlmostEqual(o.dy[i], answer.dy[i], 4) 
     229 
    215230    def test_sectorphi_quarter(self): 
    216231        """ 
     
    218233            The test data was not generated by IGOR. 
    219234        """ 
    220         from sas.sascalc.dataloader.manipulations import SectorPhi 
    221         import math 
    222          
    223         r = SectorPhi(r_min=.005, r_max=.01, phi_min=0, phi_max=math.pi/2.0) 
    224         r.nbins_phi = 20 
    225         o = r(self.data) 
    226  
    227         answer = Loader().load('sectorphi_testdata.txt') 
    228         for i in range(len(o.x)): 
    229             self.assertAlmostEqual(o.x[i], answer.x[i], 4) 
    230             self.assertAlmostEqual(o.y[i], answer.y[i], 4) 
    231             self.assertAlmostEqual(o.dy[i], answer.dy[i], 4) 
    232              
     235 
     236        r = SectorPhi(r_min=.005, r_max=.01, phi_min=0, phi_max=math.pi / 2.0) 
     237        r.nbins_phi = 20 
     238        o = r(self.data) 
     239 
     240        filepath = os.path.join(os.path.dirname( 
     241            os.path.realpath(__file__)), 'sectorphi_testdata.txt') 
     242        answer = Loader().load(filepath) 
     243        for i in range(len(o.x)): 
     244            self.assertAlmostEqual(o.x[i], answer.x[i], 4) 
     245            self.assertAlmostEqual(o.y[i], answer.y[i], 4) 
     246            self.assertAlmostEqual(o.dy[i], answer.dy[i], 4) 
     247 
    233248    def test_sectorq_full(self): 
    234249        """ 
     
    236251            The test data was not generated by IGOR. 
    237252        """ 
    238         from sas.sascalc.dataloader.manipulations import SectorQ 
    239         import math 
    240          
    241         r = SectorQ(r_min=.005, r_max=.01, phi_min=0, phi_max=math.pi/2.0) 
    242         r.nbins_phi = 20 
    243         o = r(self.data) 
    244  
    245         answer = Loader().load('sectorq_testdata.txt') 
    246         for i in range(len(o.x)): 
    247             self.assertAlmostEqual(o.x[i], answer.x[i], 4) 
    248             self.assertAlmostEqual(o.y[i], answer.y[i], 4) 
    249             self.assertAlmostEqual(o.dy[i], answer.dy[i], 4) 
    250              
     253 
     254        r = SectorQ(r_min=.005, r_max=.01, phi_min=0, phi_max=math.pi / 2.0) 
     255        r.nbins_phi = 20 
     256        o = r(self.data) 
     257 
     258        filepath = os.path.join(os.path.dirname( 
     259            os.path.realpath(__file__)), 'sectorq_testdata.txt') 
     260        answer = Loader().load(filepath) 
     261        for i in range(len(o.x)): 
     262            self.assertAlmostEqual(o.x[i], answer.x[i], 4) 
     263            self.assertAlmostEqual(o.y[i], answer.y[i], 4) 
     264            self.assertAlmostEqual(o.dy[i], answer.dy[i], 4) 
     265 
     266    def test_sectorq_log(self): 
     267        """ 
     268            Test sector averaging I(q) 
     269            The test data was not generated by IGOR. 
     270        """ 
     271 
     272        r = SectorQ(r_min=.005, r_max=.01, phi_min=0, phi_max=math.pi / 2.0, base=10) 
     273        r.nbins_phi = 20 
     274        o = r(self.data) 
     275 
     276        expected_binning = np.logspace(np.log10(0.005), np.log10(0.01), 20, base=10) 
     277        for i in range(len(o.x)): 
     278            self.assertAlmostEqual(o.x[i], expected_binning[i], 3) 
     279         
     280        # TODO: Test for Y values (o.y) 
     281        # print len(self.data.x_bins) 
     282        # print len(self.data.y_bins) 
     283        # print self.data.q_data.shape 
     284        # data_to_bin = np.array(self.data.q_data) 
     285        # data_to_bin = data_to_bin.reshape(len(self.data.x_bins), len(self.data.y_bins)) 
     286        # H, xedges, yedges, binnumber = binned_statistic_2d(self.data.x_bins, self.data.y_bins, data_to_bin, 
     287        #     bins=[[0, math.pi / 2.0], expected_binning], statistic='mean') 
     288        # xedges_width = (xedges[1] - xedges[0]) 
     289        # xedges_center = xedges[1:] - xedges_width / 2 
     290         
     291        # yedges_width = (yedges[1] - yedges[0]) 
     292        # yedges_center = yedges[1:] - yedges_width / 2 
     293         
     294        # print H.flatten().shape 
     295        # print o.y.shape 
     296         
    251297 
    252298if __name__ == '__main__': 
  • test/sasguiframe/test/utest_manipulations.py

    r959eb01 r959eb01  
    22    Unit tests for data manipulations 
    33""" 
    4 #TODO: what happens if you add a Data1D to a Data2D? 
    5  
     4# TODO: what happens if you add a Data1D to a Data2D? 
     5 
     6import math 
     7import os.path 
    68import unittest 
    7 import math 
     9 
    810import numpy as np 
    9 from sas.sascalc.dataloader.loader import  Loader 
    10 from sas.sasgui.guiframe.dataFitting import Data1D, Data2D 
    11 from sas.sasgui.guiframe.dataFitting import Data1D as Theory1D 
    12   
    13 import os.path 
    14  
    15 class data_info_tests(unittest.TestCase): 
    16      
     11 
     12from sas.sascalc.dataloader.loader import Loader 
     13from sas.sasgui.guiframe.dataFitting import Data1D 
     14from sas.sasgui.guiframe.dataFitting import Data2D 
     15 
     16 
     17class DataInfoTests(unittest.TestCase): 
     18 
    1719    def setUp(self): 
    1820        data = Loader().load("cansas1d.xml") 
    1921        self.data = data[0] 
    20          
     22 
    2123    def test_clone1D(self): 
    2224        """ 
     
    2426        """ 
    2527        clone = self.data.clone_without_data() 
    26          
     28 
    2729        for i in range(len(self.data.detector)): 
    28             self.assertEqual(self.data.detector[i].distance, clone.detector[i].distance) 
    29              
    30 class theory1d_tests(unittest.TestCase): 
    31      
     30            self.assertEqual( 
     31                self.data.detector[i].distance, clone.detector[i].distance) 
     32 
     33 
     34class Theory1DTests(unittest.TestCase): 
     35 
    3236    def setUp(self): 
    3337        data = Loader().load("cansas1d.xml") 
    3438        self.data = data[0] 
    35          
     39 
    3640    def test_clone_theory1D(self): 
    3741        """ 
    3842            Test basic cloning 
    3943        """ 
    40         theory = Theory1D(x=[], y=[], dy=None) 
     44        theory = Data1D(x=[], y=[], dy=None) 
    4145        theory.clone_without_data(clone=self.data) 
    4246        theory.copy_from_datainfo(data1d=self.data) 
    4347        for i in range(len(self.data.detector)): 
    44             self.assertEqual(self.data.detector[i].distance, theory.detector[i].distance) 
    45              
     48            self.assertEqual( 
     49                self.data.detector[i].distance, theory.detector[i].distance) 
     50 
    4651        for i in range(len(self.data.x)): 
    4752            self.assertEqual(self.data.x[i], theory.x[i]) 
     
    4954            self.assertEqual(self.data.dy[i], theory.dy[i]) 
    5055 
    51 class manip_tests(unittest.TestCase): 
    52      
     56 
     57class ManipTests(unittest.TestCase): 
     58 
    5359    def setUp(self): 
    5460        # Create two data sets to play with 
    5561        x_0 = np.ones(5) 
    5662        for i in range(5): 
    57             x_0[i] = x_0[i]*(i+1.0) 
    58              
    59         y_0 = 2.0*np.ones(5) 
    60         dy_0 = 0.5*np.ones(5) 
     63            x_0[i] = x_0[i] * (i + 1.0) 
     64 
     65        y_0 = 2.0 * np.ones(5) 
     66        dy_0 = 0.5 * np.ones(5) 
    6167        self.data = Data1D(x_0, y_0, dy=dy_0) 
    62          
     68 
    6369        x = self.data.x 
    6470        y = np.ones(5) 
    6571        dy = np.ones(5) 
    6672        self.data2 = Data1D(x, y, dy=dy) 
    67          
    68          
     73 
    6974    def test_load(self): 
    7075        """ 
     
    7378        # There should be 5 entries in the file 
    7479        self.assertEqual(len(self.data.x), 5) 
    75          
     80 
    7681        for i in range(5): 
    7782            # The x values should be from 1 to 5 
    78             self.assertEqual(self.data.x[i], float(i+1)) 
    79          
     83            self.assertEqual(self.data.x[i], float(i + 1)) 
     84 
    8085            # All y-error values should be 0.5 
    81             self.assertEqual(self.data.dy[i], 0.5)     
    82              
     86            self.assertEqual(self.data.dy[i], 0.5) 
     87 
    8388            # All y values should be 2.0 
    84             self.assertEqual(self.data.y[i], 2.0)     
    85          
     89            self.assertEqual(self.data.y[i], 2.0) 
     90 
    8691    def test_add(self): 
    87         result = self.data2+self.data 
     92        result = self.data2 + self.data 
    8893        for i in range(5): 
    8994            self.assertEqual(result.y[i], 3.0) 
    90             self.assertEqual(result.dy[i], math.sqrt(0.5**2+1.0)) 
    91          
     95            self.assertEqual(result.dy[i], math.sqrt(0.5**2 + 1.0)) 
     96 
    9297    def test_sub(self): 
    93         result = self.data2-self.data 
     98        result = self.data2 - self.data 
    9499        for i in range(5): 
    95100            self.assertEqual(result.y[i], -1.0) 
    96             self.assertEqual(result.dy[i], math.sqrt(0.5**2+1.0)) 
    97          
     101            self.assertEqual(result.dy[i], math.sqrt(0.5**2 + 1.0)) 
     102 
    98103    def test_mul(self): 
    99         result = self.data2*self.data 
     104        result = self.data2 * self.data 
    100105        for i in range(5): 
    101106            self.assertEqual(result.y[i], 2.0) 
    102             self.assertEqual(result.dy[i], math.sqrt((0.5*1.0)**2+(1.0*2.0)**2)) 
    103          
     107            self.assertEqual(result.dy[i], math.sqrt( 
     108                (0.5 * 1.0)**2 + (1.0 * 2.0)**2)) 
     109 
    104110    def test_div(self): 
    105         result = self.data2/self.data 
     111        result = self.data2 / self.data 
    106112        for i in range(5): 
    107113            self.assertEqual(result.y[i], 0.5) 
    108             self.assertEqual(result.dy[i], math.sqrt((1.0/2.0)**2+(0.5*1.0/4.0)**2)) 
    109          
     114            self.assertEqual(result.dy[i], math.sqrt( 
     115                (1.0 / 2.0)**2 + (0.5 * 1.0 / 4.0)**2)) 
     116 
    110117    def test_radd(self): 
    111         result = self.data+3.0 
     118        result = self.data + 3.0 
    112119        for i in range(5): 
    113120            self.assertEqual(result.y[i], 5.0) 
    114121            self.assertEqual(result.dy[i], 0.5) 
    115              
    116         result = 3.0+self.data 
     122 
     123        result = 3.0 + self.data 
    117124        for i in range(5): 
    118125            self.assertEqual(result.y[i], 5.0) 
    119126            self.assertEqual(result.dy[i], 0.5) 
    120              
     127 
    121128    def test_rsub(self): 
    122         result = self.data-3.0 
     129        result = self.data - 3.0 
    123130        for i in range(5): 
    124131            self.assertEqual(result.y[i], -1.0) 
    125132            self.assertEqual(result.dy[i], 0.5) 
    126              
    127         result = 3.0-self.data 
     133 
     134        result = 3.0 - self.data 
    128135        for i in range(5): 
    129136            self.assertEqual(result.y[i], 1.0) 
    130137            self.assertEqual(result.dy[i], 0.5) 
    131              
     138 
    132139    def test_rmul(self): 
    133         result = self.data*3.0 
     140        result = self.data * 3.0 
    134141        for i in range(5): 
    135142            self.assertEqual(result.y[i], 6.0) 
    136143            self.assertEqual(result.dy[i], 1.5) 
    137              
    138         result = 3.0*self.data 
     144 
     145        result = 3.0 * self.data 
    139146        for i in range(5): 
    140147            self.assertEqual(result.y[i], 6.0) 
    141148            self.assertEqual(result.dy[i], 1.5) 
    142              
     149 
    143150    def test_rdiv(self): 
    144         result = self.data/4.0 
     151        result = self.data / 4.0 
    145152        for i in range(5): 
    146153            self.assertEqual(result.y[i], 0.5) 
    147154            self.assertEqual(result.dy[i], 0.125) 
    148              
    149         result = 6.0/self.data 
     155 
     156        result = 6.0 / self.data 
    150157        for i in range(5): 
    151158            self.assertEqual(result.y[i], 3.0) 
    152             self.assertEqual(result.dy[i], 6.0*0.5/4.0) 
    153              
    154 class manip_2D(unittest.TestCase): 
    155      
     159            self.assertEqual(result.dy[i], 6.0 * 0.5 / 4.0) 
     160 
     161 
     162class Manin2DTests(unittest.TestCase): 
     163 
    156164    def setUp(self): 
    157165        # Create two data sets to play with 
    158         x_0 = 2.0*np.ones(25) 
    159         dx_0 = 0.5*np.ones(25) 
     166        x_0 = 2.0 * np.ones(25) 
     167        dx_0 = 0.5 * np.ones(25) 
    160168        qx_0 = np.arange(25) 
    161169        qy_0 = np.arange(25) 
    162170        mask_0 = np.zeros(25) 
    163         dqx_0 = np.arange(25)/100 
    164         dqy_0 = np.arange(25)/100 
     171        dqx_0 = np.arange(25) / 100 
     172        dqy_0 = np.arange(25) / 100 
    165173        q_0 = np.sqrt(qx_0 * qx_0 + qy_0 * qy_0) 
    166         self.data = Data2D(image=x_0, err_image=dx_0, qx_data=qx_0,  
    167                            qy_data=qy_0, q_data=q_0, mask=mask_0,  
     174        self.data = Data2D(image=x_0, err_image=dx_0, qx_data=qx_0, 
     175                           qy_data=qy_0, q_data=q_0, mask=mask_0, 
    168176                           dqx_data=dqx_0, dqy_data=dqy_0) 
    169          
     177 
    170178        y = np.ones(25) 
    171179        dy = np.ones(25) 
     
    174182        mask = np.zeros(25) 
    175183        q = np.sqrt(qx * qx + qy * qy) 
    176         self.data2 = Data2D(image=y, err_image=dy, qx_data=qx, qy_data=qy,  
     184        self.data2 = Data2D(image=y, err_image=dy, qx_data=qx, qy_data=qy, 
    177185                            q_data=q, mask=mask) 
    178          
    179          
     186 
    180187    def test_load(self): 
    181188        """ 
     
    184191        # There should be 5 entries in the file 
    185192        self.assertEqual(np.size(self.data.data), 25) 
    186          
     193 
    187194        for i in range(25): 
    188195            # All y-error values should be 0.5 
    189             self.assertEqual(self.data.err_data[i], 0.5)     
    190              
     196            self.assertEqual(self.data.err_data[i], 0.5) 
     197 
    191198            # All y values should be 2.0 
    192             self.assertEqual(self.data.data[i], 2.0)     
    193          
     199            self.assertEqual(self.data.data[i], 2.0) 
     200 
    194201    def test_add(self): 
    195         result = self.data2+self.data 
     202        result = self.data2 + self.data 
    196203        for i in range(25): 
    197204            self.assertEqual(result.data[i], 3.0) 
    198             self.assertEqual(result.err_data[i], math.sqrt(0.5**2+1.0)) 
    199          
     205            self.assertEqual(result.err_data[i], math.sqrt(0.5**2 + 1.0)) 
     206 
    200207    def test_sub(self): 
    201         result = self.data2-self.data 
    202         for i in range(25): 
    203                 self.assertEqual(result.data[i], -1.0) 
    204                 self.assertEqual(result.err_data[i], math.sqrt(0.5**2+1.0)) 
    205          
     208        result = self.data2 - self.data 
     209        for i in range(25): 
     210            self.assertEqual(result.data[i], -1.0) 
     211            self.assertEqual(result.err_data[i], math.sqrt(0.5**2 + 1.0)) 
     212 
    206213    def test_mul(self): 
    207         result = self.data2*self.data 
     214        result = self.data2 * self.data 
    208215        for i in range(25): 
    209216            self.assertEqual(result.data[i], 2.0) 
    210             self.assertEqual(result.err_data[i], math.sqrt((0.5*1.0)**2+(1.0*2.0)**2)) 
    211          
     217            self.assertEqual(result.err_data[i], math.sqrt( 
     218                (0.5 * 1.0)**2 + (1.0 * 2.0)**2)) 
     219 
    212220    def test_div(self): 
    213         result = self.data2/self.data 
     221        result = self.data2 / self.data 
    214222        for i in range(25): 
    215223            self.assertEqual(result.data[i], 0.5) 
    216             self.assertEqual(result.err_data[i], math.sqrt((1.0/2.0)**2+(0.5*1.0/4.0)**2)) 
    217          
     224            self.assertEqual(result.err_data[i], math.sqrt( 
     225                (1.0 / 2.0)**2 + (0.5 * 1.0 / 4.0)**2)) 
     226 
    218227    def test_radd(self): 
    219         result = self.data+3.0 
     228        result = self.data + 3.0 
    220229        for i in range(25): 
    221230            self.assertEqual(result.data[i], 5.0) 
    222231            self.assertEqual(result.err_data[i], 0.5) 
    223     
    224         result = 3.0+self.data 
     232 
     233        result = 3.0 + self.data 
    225234        for i in range(25): 
    226235            self.assertEqual(result.data[i], 5.0) 
    227236            self.assertEqual(result.err_data[i], 0.5) 
    228              
     237 
    229238    def test_rsub(self): 
    230         result = self.data-3.0 
     239        result = self.data - 3.0 
    231240        for i in range(25): 
    232241            self.assertEqual(result.data[i], -1.0) 
    233242            self.assertEqual(result.err_data[i], 0.5) 
    234      
    235         result = 3.0-self.data 
     243 
     244        result = 3.0 - self.data 
    236245        for i in range(25): 
    237246            self.assertEqual(result.data[i], 1.0) 
    238247            self.assertEqual(result.err_data[i], 0.5) 
    239              
     248 
    240249    def test_rmul(self): 
    241         result = self.data*3.0 
     250        result = self.data * 3.0 
    242251        for i in range(25): 
    243252            self.assertEqual(result.data[i], 6.0) 
    244253            self.assertEqual(result.err_data[i], 1.5) 
    245   
    246         result = 3.0*self.data 
     254 
     255        result = 3.0 * self.data 
    247256        for i in range(25): 
    248257            self.assertEqual(result.data[i], 6.0) 
    249258            self.assertEqual(result.err_data[i], 1.5) 
    250              
     259 
    251260    def test_rdiv(self): 
    252         result = self.data/4.0 
     261        result = self.data / 4.0 
    253262        for i in range(25): 
    254263            self.assertEqual(result.data[i], 0.5) 
    255264            self.assertEqual(result.err_data[i], 0.125) 
    256265 
    257         result = 6.0/self.data 
     266        result = 6.0 / self.data 
    258267        for i in range(25): 
    259268            self.assertEqual(result.data[i], 3.0) 
    260             self.assertEqual(result.err_data[i], 6.0*0.5/4.0) 
    261      
    262 class extra_manip_2D(unittest.TestCase): 
    263      
     269            self.assertEqual(result.err_data[i], 6.0 * 0.5 / 4.0) 
     270 
     271 
     272class ExtraManip2DTests(unittest.TestCase): 
     273 
    264274    def setUp(self): 
    265275        # Create two data sets to play with 
    266         x_0 = 2.0*np.ones(25) 
    267         dx_0 = 0.5*np.ones(25) 
     276        x_0 = 2.0 * np.ones(25) 
     277        dx_0 = 0.5 * np.ones(25) 
    268278        qx_0 = np.arange(25) 
    269279        qy_0 = np.arange(25) 
    270280        mask_0 = np.zeros(25) 
    271         dqx_0 = np.arange(25)/100 
    272         dqy_0 = np.arange(25)/100 
     281        dqx_0 = np.arange(25) / 100 
     282        dqy_0 = np.arange(25) / 100 
    273283        q_0 = np.sqrt(qx_0 * qx_0 + qy_0 * qy_0) 
    274         self.data = Data2D(image=x_0, err_image=dx_0, qx_data=qx_0,  
    275                            qy_data=qy_0, q_data=q_0, mask=mask_0,  
     284        self.data = Data2D(image=x_0, err_image=dx_0, qx_data=qx_0, 
     285                           qy_data=qy_0, q_data=q_0, mask=mask_0, 
    276286                           dqx_data=dqx_0, dqy_data=dqy_0) 
    277          
     287 
    278288        y = np.ones(25) 
    279289        dy = np.ones(25) 
     
    282292        mask = np.zeros(25) 
    283293        q = np.sqrt(qx * qx + qy * qy) 
    284         self.data2 = Data2D(image=y, err_image=dy, qx_data=qx, qy_data=qy,  
     294        self.data2 = Data2D(image=y, err_image=dy, qx_data=qx, qy_data=qy, 
    285295                            q_data=q, mask=mask) 
    286          
    287          
     296 
    288297    def test_load(self): 
    289298        """ 
     
    292301        # There should be 5 entries in the file 
    293302        self.assertEqual(np.size(self.data.data), 25) 
    294          
     303 
    295304        for i in range(25): 
    296305            # All y-error values should be 0.5 
    297             self.assertEqual(self.data.err_data[i], 0.5)     
    298              
     306            self.assertEqual(self.data.err_data[i], 0.5) 
     307 
    299308            # All y values should be 2.0 
    300             self.assertEqual(self.data.data[i], 2.0)     
    301          
     309            self.assertEqual(self.data.data[i], 2.0) 
     310 
    302311    def test_add(self): 
    303         result = self.data2+self.data 
     312        result = self.data2 + self.data 
    304313        for i in range(25): 
    305314            self.assertEqual(result.data[i], 3.0) 
    306             self.assertEqual(result.err_data[i], math.sqrt(0.5**2+1.0)) 
    307          
     315            self.assertEqual(result.err_data[i], math.sqrt(0.5**2 + 1.0)) 
     316 
    308317    def test_sub(self): 
    309         result = self.data2-self.data 
    310         for i in range(25): 
    311                 self.assertEqual(result.data[i], -1.0) 
    312                 self.assertEqual(result.err_data[i], math.sqrt(0.5**2+1.0)) 
    313          
     318        result = self.data2 - self.data 
     319        for i in range(25): 
     320            self.assertEqual(result.data[i], -1.0) 
     321            self.assertEqual(result.err_data[i], math.sqrt(0.5**2 + 1.0)) 
     322 
    314323    def test_mul(self): 
    315         result = self.data2*self.data 
     324        result = self.data2 * self.data 
    316325        for i in range(25): 
    317326            self.assertEqual(result.data[i], 2.0) 
    318             self.assertEqual(result.err_data[i], math.sqrt((0.5*1.0)**2+(1.0*2.0)**2)) 
    319          
     327            self.assertEqual(result.err_data[i], math.sqrt( 
     328                (0.5 * 1.0)**2 + (1.0 * 2.0)**2)) 
     329 
    320330    def test_div(self): 
    321         result = self.data2/self.data 
     331        result = self.data2 / self.data 
    322332        for i in range(25): 
    323333            self.assertEqual(result.data[i], 0.5) 
    324             self.assertEqual(result.err_data[i], math.sqrt((1.0/2.0)**2+(0.5*1.0/4.0)**2)) 
    325          
     334            self.assertEqual(result.err_data[i], math.sqrt( 
     335                (1.0 / 2.0)**2 + (0.5 * 1.0 / 4.0)**2)) 
     336 
    326337    def test_radd(self): 
    327         result = self.data+3.0 
     338        result = self.data + 3.0 
    328339        for i in range(25): 
    329340            self.assertEqual(result.data[i], 5.0) 
    330341            self.assertEqual(result.err_data[i], 0.5) 
    331     
    332         result = 3.0+self.data 
     342 
     343        result = 3.0 + self.data 
    333344        for i in range(25): 
    334345            self.assertEqual(result.data[i], 5.0) 
    335346            self.assertEqual(result.err_data[i], 0.5) 
    336              
     347 
    337348    def test_rsub(self): 
    338         result = self.data-3.0 
     349        result = self.data - 3.0 
    339350        for i in range(25): 
    340351            self.assertEqual(result.data[i], -1.0) 
    341352            self.assertEqual(result.err_data[i], 0.5) 
    342      
    343         result = 3.0-self.data 
     353 
     354        result = 3.0 - self.data 
    344355        for i in range(25): 
    345356            self.assertEqual(result.data[i], 1.0) 
    346357            self.assertEqual(result.err_data[i], 0.5) 
    347              
     358 
    348359    def test_rmul(self): 
    349         result = self.data*3.0 
     360        result = self.data * 3.0 
    350361        for i in range(25): 
    351362            self.assertEqual(result.data[i], 6.0) 
    352363            self.assertEqual(result.err_data[i], 1.5) 
    353   
    354         result = 3.0*self.data 
     364 
     365        result = 3.0 * self.data 
    355366        for i in range(25): 
    356367            self.assertEqual(result.data[i], 6.0) 
    357368            self.assertEqual(result.err_data[i], 1.5) 
    358              
     369 
    359370    def test_rdiv(self): 
    360         result = self.data/4.0 
     371        result = self.data / 4.0 
    361372        for i in range(25): 
    362373            self.assertEqual(result.data[i], 0.5) 
    363374            self.assertEqual(result.err_data[i], 0.125) 
    364375 
    365         result = 6.0/self.data 
     376        result = 6.0 / self.data 
    366377        for i in range(25): 
    367378            self.assertEqual(result.data[i], 3.0) 
    368             self.assertEqual(result.err_data[i], 6.0*0.5/4.0) 
     379            self.assertEqual(result.err_data[i], 6.0 * 0.5 / 4.0) 
     380 
    369381 
    370382if __name__ == '__main__': 
    371383    unittest.main() 
    372     
Note: See TracChangeset for help on using the changeset viewer.