Changeset 13374be in sasview


Ignore:
Timestamp:
Sep 20, 2017 5:55:53 AM (7 years ago)
Author:
Paul Kienzle <pkienzle@…>
Branches:
master, ESS_GUI, ESS_GUI_Docs, ESS_GUI_batch_fitting, ESS_GUI_bumps_abstraction, ESS_GUI_iss1116, ESS_GUI_iss879, ESS_GUI_iss959, ESS_GUI_opencl, ESS_GUI_ordering, ESS_GUI_sync_sascalc, magnetic_scatt, release-4.2.2, ticket-1009, ticket-1094-headless, ticket-1242-2d-resolution, ticket-1243, ticket-1249, ticket885, unittest-saveload
Children:
fca1f50
Parents:
6d62b7f (diff), 2a399ca (diff)
Note: this is a merge changeset, the changes displayed below correspond to the merge itself.
Use the (diff) links above to see all the changes relative to each parent.
Message:

Merge branch 'master' into 4_1_issues

Files:
8 added
3 deleted
31 edited

Legend:

Unmodified
Added
Removed
  • src/sas/sascalc/corfunc/corfunc_calculator.py

    rff11b21 ra859f99  
    3434 
    3535        def __call__(self, x): 
    36             if self._lastx == [] or x.tolist() != self._lastx.tolist(): 
     36            # If input is a single number, evaluate the function at that number 
     37            # and return a single number 
     38            if type(x) == float or type(x) == int: 
     39                return self._smoothed_function(np.array([x]))[0] 
     40            # If input is a list, and is different to the last input, evaluate 
     41            # the function at each point. If the input is the same as last time 
     42            # the function was called, return the result that was calculated 
     43            # last time instead of explicity evaluating the function again. 
     44            elif self._lastx == [] or x.tolist() != self._lastx.tolist(): 
    3745                self._lasty = self._smoothed_function(x) 
    3846                self._lastx = x 
     
    121129        extrapolation = Data1D(qs, iqs) 
    122130 
    123         return params, extrapolation 
     131        return params, extrapolation, s2 
    124132 
    125133    def compute_transform(self, extrapolation, trans_type, background=None, 
     
    131139        :param background: The background value (if not provided, previously 
    132140            calculated value will be used) 
     141        :param extrap_fn: A callable function representing the extraoplated data 
    133142        :param completefn: The function to call when the transform calculation 
    134             is complete` 
     143            is complete 
    135144        :param updatefn: The function to call to update the GUI with the status 
    136145            of the transform calculation 
     
    144153        if trans_type == 'fourier': 
    145154            self._transform_thread = FourierThread(self._data, extrapolation, 
    146             background, completefn=completefn, updatefn=updatefn) 
     155            background, completefn=completefn, 
     156            updatefn=updatefn) 
    147157        elif trans_type == 'hilbert': 
    148158            self._transform_thread = HilbertThread(self._data, extrapolation, 
  • src/sas/sascalc/corfunc/transform_thread.py

    rd03228e ra859f99  
    22from sas.sascalc.dataloader.data_info import Data1D 
    33from scipy.fftpack import dct 
     4from scipy.integrate import trapz, cumtrapz 
    45import numpy as np 
    56from time import sleep 
     
    1314        self.extrapolation = extrapolated_data 
    1415 
     16    def check_if_cancelled(self): 
     17        if self.isquit(): 
     18            self.update("Fourier transform cancelled.") 
     19            self.complete(transforms=None) 
     20            return True 
     21        return False 
     22 
    1523    def compute(self): 
    1624        qs = self.extrapolation.x 
     
    1927        background = self.background 
    2028 
     29        xs = np.pi*np.arange(len(qs),dtype=np.float32)/(q[1]-q[0])/len(qs) 
     30 
    2131        self.ready(delay=0.0) 
    22         self.update(msg="Starting Fourier transform.") 
     32        self.update(msg="Fourier transform in progress.") 
    2333        self.ready(delay=0.0) 
    24         if self.isquit(): 
    25             return 
     34 
     35        if self.check_if_cancelled(): return 
    2636        try: 
    27             gamma = dct((iqs-background)*qs**2) 
    28             gamma = gamma / gamma.max() 
    29         except: 
     37            # ----- 1D Correlation Function ----- 
     38            gamma1 = dct((iqs-background)*qs**2) 
     39            Q = gamma1.max() 
     40            gamma1 /= Q 
     41 
     42            if self.check_if_cancelled(): return 
     43 
     44            # ----- 3D Correlation Function ----- 
     45            # gamma3(R) = 1/R int_{0}^{R} gamma1(x) dx 
     46            # trapz uses the trapezium rule to calculate the integral 
     47            mask = xs <= 200.0 # Only calculate gamma3 up to x=200 (as this is all that's plotted) 
     48            # gamma3 = [trapz(gamma1[:n], xs[:n])/xs[n-1] for n in range(2, len(xs[mask]) + 1)]j 
     49            # gamma3.insert(0, 1.0) # Gamma_3(0) is defined as 1 
     50            n = len(xs[mask]) 
     51            gamma3 = cumtrapz(gamma1[:n], xs[:n])/xs[1:n] 
     52            gamma3 = np.hstack((1.0, gamma3)) # Gamma_3(0) is defined as 1 
     53 
     54            if self.check_if_cancelled(): return 
     55 
     56            # ----- Interface Distribution function ----- 
     57            idf = dct(-qs**4 * (iqs-background)) 
     58 
     59            if self.check_if_cancelled(): return 
     60 
     61            # Manually calculate IDF(0.0), since scipy DCT tends to give us a 
     62            # very large negative value. 
     63            # IDF(x) = int_0^inf q^4 * I(q) * cos(q*x) * dq 
     64            # => IDF(0) = int_0^inf q^4 * I(q) * dq 
     65            idf[0] = trapz(-qs**4 * (iqs-background), qs) 
     66            idf /= Q # Normalise using scattering invariant 
     67 
     68        except Exception as e: 
     69            import logging 
     70            logger = logging.getLogger(__name__) 
     71            logger.error(e) 
     72 
    3073            self.update(msg="Fourier transform failed.") 
    31             self.complete(transform=None) 
     74            self.complete(transforms=None) 
    3275            return 
    3376        if self.isquit(): 
     
    3578        self.update(msg="Fourier transform completed.") 
    3679 
    37         xs = np.pi*np.arange(len(qs),dtype=np.float32)/(q[1]-q[0])/len(qs) 
    38         transform = Data1D(xs, gamma) 
     80        transform1 = Data1D(xs, gamma1) 
     81        transform3 = Data1D(xs[xs <= 200], gamma3) 
     82        idf = Data1D(xs, idf) 
    3983 
    40         self.complete(transform=transform) 
     84        transforms = (transform1, transform3, idf) 
     85 
     86        self.complete(transforms=transforms) 
    4187 
    4288class HilbertThread(CalcThread): 
     
    64110        self.update(msg="Hilbert transform completed.") 
    65111 
    66         self.complete(transform=None) 
     112        self.complete(transforms=None) 
  • src/sas/sasgui/perspectives/calculator/image_viewer.py

    ra1b8fee r412e9e8b  
    5959            _, extension = os.path.splitext(basename) 
    6060            try: 
     61                # Note that matplotlib only reads png natively. 
     62                # Any other formats (tiff, jpeg, etc) are passed 
     63                # to PIL which seems to have a problem in version 
     64                # 1.1.7 that causes a close error which shows up in  
     65                # the log file.  This does not seem to have any adverse 
     66                # effects.  PDB   --- September 17, 2017. 
    6167                img = mpimg.imread(file_path) 
    6268                is_png = extension.lower() == '.png' 
     
    8995        if location is None: 
    9096            location = os.getcwd() 
    91         dlg = wx.FileDialog(self.parent, "Image Viewer: Choose a image file", 
    92                             location, "", "", style=wx.FD_OPEN | wx.FD_MULTIPLE) 
     97        wildcard="Images (*.bmp;*.gif;*jpeg,*jpg;*.png;*tif;*.tiff)|*bmp;\ 
     98            *.gif; *.jpg; *.jpeg;*png;*.png;*.tif;*.tiff|"\ 
     99            "Bitmap (*.bmp)|*.bmp|"\ 
     100            "GIF (*.gif)|*.gif|"\ 
     101            "JPEG (*.jpg;*.jpeg)|*.jpg;*.jpeg|"\ 
     102            "PNG (*.png)|*.png|"\ 
     103            "TIFF (*.tif;*.tiff)|*.tif;*tiff|"\ 
     104            "All Files (*.*)|*.*|" 
     105 
     106        dlg = wx.FileDialog(self.parent, "Image Viewer: Choose an image file", 
     107                            location, "", wildcard, style=wx.FD_OPEN 
     108                            | wx.FD_MULTIPLE) 
    93109        if dlg.ShowModal() == wx.ID_OK: 
    94110            path = dlg.GetPaths() 
  • src/sas/sasgui/perspectives/calculator/media/image_viewer_help.rst

    rda456fb r412e9e8b  
    3434   will be displayed. 
    3535 
    36 .. image:: load_image.bmp 
     36.. image:: load_image.png 
    3737 
    38383) To save, print, or copy the image, or to apply a grid overlay, right-click  
    3939   anywhere in the plot. 
    4040 
    41 .. image:: pic_plot.bmp 
     41.. image:: pic_plot.png 
    4242 
    43434. If the image is taken from a 2D detector, SasView can attempt to convert  
     
    5151   then click the OK. 
    5252 
    53 .. image:: pic_convert.bmp 
     53.. image:: pic_convert.png 
    5454 
    5555.. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 
  • src/sas/sasgui/perspectives/corfunc/corfunc.py

    r463e7ffc r9b90bf8  
    189189            # Show the transformation as a curve instead of points 
    190190            new_plot.symbol = GUIFRAME_ID.CURVE_SYMBOL_NUM 
     191        elif label == IDF_LABEL: 
     192            new_plot.xaxis("{x}", 'A') 
     193            new_plot.yaxis("{g_1}", '') 
     194            # Linear scale 
     195            new_plot.xtransform = 'x' 
     196            new_plot.ytransform = 'y' 
     197            group_id = GROUP_ID_IDF 
     198            # Show IDF as a curve instead of points 
     199            new_plot.symbol = GUIFRAME_ID.CURVE_SYMBOL_NUM 
    191200        new_plot.id = label 
    192201        new_plot.name = label 
  • src/sas/sasgui/perspectives/corfunc/corfunc_panel.py

    r7432acb r2a399ca  
    2020 
    2121OUTPUT_STRINGS = { 
    22     'max': "Long Period (A): ", 
     22    'max': "Long Period / 2 (A): ", 
    2323    'Lc': "Average Hard Block Thickness (A): ", 
    2424    'dtr': "Average Interface Thickness (A): ", 
     
    5555        self._data = data # The data to be analysed (corrected fr background) 
    5656        self._extrapolated_data = None # The extrapolated data set 
     57        # Callable object of class CorfuncCalculator._Interpolator representing 
     58        # the extrapolated and interpolated data 
     59        self._extrapolated_fn = None 
    5760        self._transformed_data = None # Fourier trans. of the extrapolated data 
    5861        self._calculator = CorfuncCalculator() 
     
    218221 
    219222        try: 
    220             params, self._extrapolated_data = self._calculator.compute_extrapolation() 
     223            params, self._extrapolated_data, self._extrapolated_fn = \ 
     224                self._calculator.compute_extrapolation() 
    221225        except Exception as e: 
    222226            msg = "Error extrapolating data:\n" 
     
    257261            StatusEvent(status=msg)) 
    258262 
    259     def transform_complete(self, transform=None): 
     263    def transform_complete(self, transforms=None): 
    260264        """ 
    261265        Called from FourierThread when calculation has completed 
    262266        """ 
    263267        self._transform_btn.SetLabel("Transform") 
    264         if transform is None: 
     268        if transforms is None: 
    265269            msg = "Error calculating Transform." 
    266270            if self.transform_type == 'hilbert': 
     
    270274            self._extract_btn.Disable() 
    271275            return 
    272         self._transformed_data = transform 
    273         import numpy as np 
    274         plot_x = transform.x[np.where(transform.x <= 200)] 
    275         plot_y = transform.y[np.where(transform.x <= 200)] 
     276 
     277        self._transformed_data = transforms 
     278        (transform1, transform3, idf) = transforms 
     279        plot_x = transform1.x[transform1.x <= 200] 
     280        plot_y = transform1.y[transform1.x <= 200] 
    276281        self._manager.show_data(Data1D(plot_x, plot_y), TRANSFORM_LABEL1) 
     282        # No need to shorten gamma3 as it's only calculated up to x=200 
     283        self._manager.show_data(transform3, TRANSFORM_LABEL3) 
     284 
     285        plot_x = idf.x[idf.x <= 200] 
     286        plot_y = idf.y[idf.x <= 200] 
     287        self._manager.show_data(Data1D(plot_x, plot_y), IDF_LABEL) 
     288 
    277289        # Only enable extract params button if a fourier trans. has been done 
    278290        if self.transform_type == 'fourier': 
     
    286298        """ 
    287299        try: 
    288             params = self._calculator.extract_parameters(self._transformed_data) 
     300            params = self._calculator.extract_parameters(self._transformed_data[0]) 
    289301        except: 
    290302            params = None 
  • src/sas/sasgui/perspectives/corfunc/corfunc_state.py

    r7432acb r2a399ca  
    2828# List of output parameters, used by __str__ 
    2929output_list = [ 
    30     ['max', "Long Period (A): "], 
     30    ['max', "Long Period / 2 (A): "], 
    3131    ['Lc', "Average Hard Block Thickness (A): "], 
    3232    ['dtr', "Average Interface Thickness (A): "], 
     
    5959        self.q = None 
    6060        self.iq = None 
    61         # TODO: Add extrapolated data and transformed data (when implemented) 
    6261 
    6362    def __str__(self): 
  • src/sas/sasgui/perspectives/corfunc/media/corfunc_help.rst

    r1404cce rd78b5cb  
    1010 
    1111This performs a correlation function analysis of one-dimensional 
    12 SAXS/SANS data, or generates a model-independent volume fraction  
     12SAXS/SANS data, or generates a model-independent volume fraction 
    1313profile from the SANS from an adsorbed polymer/surfactant layer. 
    1414 
    15 A correlation function may be interpreted in terms of an imaginary rod moving  
    16 through the structure of the material. Γ\ :sub:`1D`\ (R) is the probability that  
    17 a rod of length R moving through the material has equal electron/neutron scattering  
    18 length density at either end. Hence a frequently occurring spacing within a structure  
     15A correlation function may be interpreted in terms of an imaginary rod moving 
     16through the structure of the material. Γ\ :sub:`1D`\ (R) is the probability that 
     17a rod of length R moving through the material has equal electron/neutron scattering 
     18length density at either end. Hence a frequently occurring spacing within a structure 
    1919manifests itself as a peak. 
    2020 
     
    3030*  Fourier / Hilbert Transform of the smoothed data to give the correlation 
    3131   function / volume fraction profile, respectively 
    32 *  (Optional) Interpretation of the 1D correlation function based on an ideal  
     32*  (Optional) Interpretation of the 1D correlation function based on an ideal 
    3333   lamellar morphology 
    3434 
     
    7474   :align: center 
    7575 
    76     
     76 
    7777Smoothing 
    7878--------- 
    7979 
    80 The extrapolated data set consists of the Guinier back-extrapolation from Q~0  
     80The extrapolated data set consists of the Guinier back-extrapolation from Q~0 
    8181up to the lowest Q value in the original data, then the original scattering data, and the Porod tail-fit beyond this. The joins between the original data and the Guinier/Porod fits are smoothed using the algorithm below to avoid the formation of ripples in the transformed data. 
    8282 
     
    9393    h_i = \frac{1}{1 + \frac{(x_i-b)^2}{(x_i-a)^2}} 
    9494 
    95          
     95 
    9696Transform 
    9797--------- 
     
    102102If "Fourier" is selected for the transform type, the analysis will perform a 
    103103discrete cosine transform on the extrapolated data in order to calculate the 
    104 correlation function 
     1041D correlation function: 
    105105 
    106106.. math:: 
     
    115115    \left(n + \frac{1}{2} \right) k \right] } \text{ for } k = 0, 1, \ldots, 
    116116    N-1, N 
     117 
     118The 3D correlation function is also calculated: 
     119 
     120.. math:: 
     121    \Gamma _{3D}(R) = \frac{1}{Q^{*}} \int_{0}^{\infty}I(q) q^{2} 
     122    \frac{sin(qR)}{qR} dq 
    117123 
    118124Hilbert 
     
    165171.. figure:: profile1.png 
    166172   :align: center 
    167   
     173 
    168174.. figure:: profile2.png 
    169175   :align: center 
    170     
     176 
    171177 
    172178References 
     
    191197----- 
    192198Upon sending data for correlation function analysis, it will be plotted (minus 
    193 the background value), along with a *red* bar indicating the *upper end of the  
     199the background value), along with a *red* bar indicating the *upper end of the 
    194200low-Q range* (used for back-extrapolation), and 2 *purple* bars indicating the range to be used for forward-extrapolation. These bars may be moved my clicking and 
    195201dragging, or by entering appropriate values in the Q range input boxes. 
     
    221227    :align: center 
    222228 
    223          
     229 
    224230.. note:: 
    225231    This help document was last changed by Steve King, 08Oct2016 
  • src/sas/sasgui/perspectives/corfunc/plot_labels.py

    r1dc8ec9 r7dda833  
    44 
    55GROUP_ID_TRANSFORM = r"$\Gamma(x)$" 
    6 TRANSFORM_LABEL1 = r"$\Gamma1(x)$" 
    7 TRANSFORM_LABEL3 = r"$\Gamma3(x)$" 
     6TRANSFORM_LABEL1 = r"$\Gamma_1(x)$" 
     7TRANSFORM_LABEL3 = r"$\Gamma_3(x)$" 
     8 
     9GROUP_ID_IDF = r"$g_1(x)$" 
     10IDF_LABEL = r"$g_1(x)$" 
  • src/sas/sasgui/perspectives/fitting/basepage.py

    r914c49d5 r66acafe  
    18411841            if models.name != "NoStructure": 
    18421842                mlist.append((models.name, models)) 
    1843  
    18441843        # Sort the models 
    18451844        mlist_sorted = sorted(mlist) 
     
    29292928            return False 
    29302929 
     2930 
     2931    def _get_copy_params_details(self): 
     2932        """ 
     2933        Combines polydisperse parameters with self.parameters so that they can 
     2934        be written to the clipboard (for Excel or LaTeX). Also returns a list of 
     2935        the names of parameters that have been fitted 
     2936 
     2937        :returns: all_params - A list of all parameters, in the format of  
     2938        self.parameters 
     2939        :returns: fitted_par_names - A list of the names of parameters that have 
     2940        been fitted 
     2941        """ 
     2942        # Names of params that are being fitted 
     2943        fitted_par_names = [param[1] for param in self.param_toFit] 
     2944        # Names of params with associated polydispersity 
     2945        disp_params = [param[1].split('.')[0] for param in self.fittable_param] 
     2946 
     2947        # Create array of all parameters 
     2948        all_params = copy.copy(self.parameters) 
     2949        for param in self.parameters: 
     2950            if param[1] in disp_params: 
     2951                # Polydisperse params aren't in self.parameters, so need adding 
     2952                # to all_params 
     2953                name = param[1] + ".width" 
     2954                index = all_params.index(param) + 1 
     2955                to_insert = [] 
     2956                if name in fitted_par_names: 
     2957                    # Param is fitted, so already has a param list in self.param_toFit 
     2958                    to_insert = self.param_toFit[fitted_par_names.index(name)] 
     2959                else: 
     2960                    # Param isn't fitted, so mockup a param list 
     2961                    to_insert = [None, name, self.model.getParam(name), None, None] 
     2962                all_params.insert(index, to_insert) 
     2963        return all_params, fitted_par_names 
     2964 
    29312965    def get_copy_excel(self): 
    29322966        """ 
     
    29422976        Get the string copies of the param names and values in the tap 
    29432977        """ 
     2978        if not self.parameters: 
     2979            # Do nothing if parameters doesn't exist 
     2980            return False 
     2981 
    29442982        content = '' 
    2945  
    29462983        crlf = chr(13) + chr(10) 
    29472984        tab = chr(9) 
    29482985 
    2949         # Do it if params exist 
    2950         if self.parameters: 
    2951  
    2952             for param in self.parameters: 
    2953                 content += param[1]  # parameter name 
     2986        all_params, fitted_param_names = self._get_copy_params_details() 
     2987 
     2988        # Construct row of parameter names 
     2989        for param in all_params: 
     2990            name = param[1] # Parameter name 
     2991            content += name 
     2992            content += tab 
     2993            if name in fitted_param_names: 
     2994                # Only print errors for fitted parameters 
     2995                content += name + "_err" 
    29542996                content += tab 
    2955                 content += param[1] + "_err" 
    2956                 content += tab 
    2957  
    2958             content += crlf 
    2959  
    2960             # row of values and errors... 
    2961             for param in self.parameters: 
    2962                 content += param[2].GetValue()  # value 
    2963                 content += tab 
    2964                 content += param[4].GetValue()  # error 
    2965                 content += tab 
    2966  
    2967             return content 
    2968         else: 
    2969             return False 
     2997 
     2998        content += crlf 
     2999 
     3000        # Construct row of parameter values and errors 
     3001        for param in all_params: 
     3002            value = param[2] 
     3003            if hasattr(value, 'GetValue'): 
     3004                # param[2] is a text box 
     3005                value = value.GetValue() 
     3006            else: 
     3007                # param[2] is a float (from our self._get_copy_params_details) 
     3008                value = str(value) 
     3009            content += value 
     3010            content += tab 
     3011            if param[1] in fitted_param_names: 
     3012                # Only print errors for fitted parameters 
     3013                content += param[4].GetValue() 
     3014                content += tab  
     3015 
     3016        return content 
    29703017 
    29713018    def get_copy_latex(self): 
     
    29823029        Get the string copies of the param names and values in the tap 
    29833030        """ 
     3031        if not self.parameters: 
     3032            # Do nothing if self.parameters doesn't exist 
     3033            return False 
     3034         
    29843035        content = '\\begin{table}' 
    29853036        content += '\\begin{tabular}[h]' 
     
    29883039        tab = chr(9) 
    29893040 
    2990         # Do it if params exist 
    2991         if self.parameters: 
    2992  
    2993             content += '{|' 
    2994             for param in self.parameters: 
    2995                 content += 'l|l|' 
    2996             content += '}\hline' 
    2997             content += crlf 
    2998  
    2999             for index, param in enumerate(self.parameters): 
    3000                 content += param[1].replace('_', '\_')  # parameter name 
     3041        all_params, fitted_param_names = self._get_copy_params_details() 
     3042 
     3043        content += '{|' 
     3044        for param in all_params: 
     3045            content += 'l|l|' 
     3046        content += '}\hline' 
     3047        content += crlf 
     3048 
     3049        # Construct row of parameter names 
     3050        for index, param in enumerate(all_params): 
     3051            name = param[1] # Parameter name 
     3052            content += name.replace('_', '\_')  # Escape underscores 
     3053            if name in fitted_param_names: 
     3054                # Only print errors for fitted parameters 
    30013055                content += ' & ' 
    3002                 content += param[1].replace('_', '\_') + "\_err" 
    3003                 if index < len(self.parameters) - 1: 
    3004                     content += ' & ' 
    3005             content += '\\\\ \\hline' 
    3006             content += crlf 
    3007  
    3008             # row of values and errors... 
    3009             for index, param in enumerate(self.parameters): 
    3010                 content += param[2].GetValue()  # parameter value 
     3056                content += name.replace('_', '\_') + "\_err" 
     3057            if index < len(all_params) - 1: 
    30113058                content += ' & ' 
    3012                 content += param[4].GetValue()  # parameter error 
    3013                 if index < len(self.parameters) - 1: 
    3014                     content += ' & ' 
    3015             content += '\\\\ \\hline' 
    3016             content += crlf 
    3017  
    3018             content += '\\end{tabular}' 
    3019             content += '\\end{table}' 
    3020             return content 
    3021         else: 
    3022             return False 
     3059 
     3060        content += '\\\\ \\hline' 
     3061        content += crlf 
     3062 
     3063        # Construct row of values and errors 
     3064        for index, param in enumerate(all_params): 
     3065            value = param[2] 
     3066            if hasattr(value, "GetValue"): 
     3067                # value is a text box 
     3068                value = value.GetValue() 
     3069            else: 
     3070                # value is a float (from self._get_copy_params_details) 
     3071                value = str(value) 
     3072            content += value 
     3073            if param[1] in fitted_param_names: 
     3074                # Only print errors for fitted params 
     3075                content += ' & ' 
     3076                content += param[4].GetValue() 
     3077            if index < len(all_params) - 1: 
     3078                content += ' & ' 
     3079         
     3080        content += '\\\\ \\hline' 
     3081        content += crlf 
     3082        content += '\\end{tabular}' 
     3083        content += '\\end{table}' 
     3084 
     3085        return content 
    30233086 
    30243087    def set_clipboard(self, content=None): 
  • src/sas/sasgui/perspectives/fitting/fitpage.py

    r6a455cd3 r13374be  
    289289        self.btFitHelp.SetToolTipString("General fitting help.") 
    290290        self.btFitHelp.Bind(wx.EVT_BUTTON, self._onFitHelp) 
    291          
     291 
    292292        # Resolution Smearing Help button (for now use same technique as 
    293293        # used for dI help to get tiniest possible button that works 
     
    303303        self.btSmearHelp.SetToolTipString("Resolution smearing help.") 
    304304        self.btSmearHelp.Bind(wx.EVT_BUTTON, self._onSmearHelp) 
    305          
     305 
    306306        # textcntrl for custom resolution 
    307307        self.smear_pinhole_percent = ModelTextCtrl(self, wx.ID_ANY, 
     
    564564        sizer.Add(self.draw_button, 0, 0) 
    565565        sizer.Add((-1, 5)) 
    566          
     566 
    567567        sizer.Add(self.tcChi, 0, 0) 
    568568        sizer.Add(self.Npts_fit, 0, 0) 
     
    570570        sizer.Add(self.btFit, 0, 0) 
    571571        sizer.Add(self.btFitHelp, 0, 0) 
    572          
     572 
    573573        boxsizer_range.Add(sizer_chi2) 
    574574        boxsizer_range.Add(sizer) 
     
    11561156                copy_flag = self.get_copy_params() 
    11571157                is_poly_enabled = self.enable_disp.GetValue() 
    1158  
    1159         self._on_select_model_helper() 
     1158        try: 
     1159            self._on_select_model_helper() 
     1160        except Exception as e: 
     1161            evt = StatusEvent(status=e.message, info="error") 
     1162            wx.PostEvent(self._manager.parent, evt) 
     1163            # Set S(Q) to None 
     1164            self.structurebox.SetSelection(0) 
     1165            self._on_select_model() 
     1166            return 
    11601167        self.set_model_param_sizer(self.model) 
    11611168        if self.model is None: 
     
    21852192        self.save_current_state() 
    21862193 
     2194        if not self.is_mac: 
     2195            self.Layout() 
     2196            self.Refresh() 
    21872197        # plot model ( when drawing, do not update chisqr value again) 
    21882198        self._draw_model(update_chisqr=False, source='fit') 
     
    27792789            else: 
    27802790                return cmp(a.lower(), b.lower()) 
    2781          
     2791 
    27822792        # keys obtained now from ordered dict, so commenting alphabetical 
    27832793        # ordering keys.sort(custom_compare) 
  • src/sas/sasgui/perspectives/fitting/fitpanel.py

    rc9ecd1b r13374be  
    503503            if data is None: 
    504504                return None 
     505        focused_page = self.GetPage(self.GetSelection()) 
    505506        for page in self.opened_pages.values(): 
    506507            # check if the selected data existing in the fitpanel 
    507508            pos = self.GetPageIndex(page) 
    508509            if not check_data_validity(page.get_data()) and not page.batch_on: 
     510                if page.model is not None and page != focused_page: 
     511                    # Page has an active theory and is in background - don't 
     512                    # send data here. 
     513                    continue 
    509514                # make sure data get placed in 1D empty tab if data is 1D 
    510515                # else data get place on 2D tab empty tab 
  • src/sas/sasgui/perspectives/fitting/fitting.py

    r2d9526d r66acafe  
    357357                            else: 
    358358                                page.formfactorbox.SetLabel(current_val) 
     359                        if hasattr(page, 'structurebox'): 
     360                            selected_name = page.structurebox.GetStringSelection() 
     361 
     362                            page.structurebox.Clear() 
     363                            page.initialize_combox() 
     364 
     365                            index = page.structurebox.FindString(selected_name) 
     366                            if index == -1: 
     367                                index = 0 
     368                            page.structurebox.SetSelection(index) 
     369                            page._on_select_model() 
    359370        except: 
    360371            logger.error("update_custom_combo: %s", sys.exc_value) 
     
    13261337 
    13271338                is_data2d = issubclass(data.__class__, Data2D) 
    1328                 #check consistency of arrays 
     1339                # Check consistency of arrays 
    13291340                if not is_data2d: 
    13301341                    if len(res.theory) == len(res.index[res.index]) and \ 
     
    13371348                    new_theory[res.index == False] = np.nan 
    13381349                    correct_result = True 
    1339                 #get all fittable parameters of the current model 
     1350                # Get all fittable parameters of the current model 
    13401351                param_list = model.getParamList() 
    13411352                for param in model.getDispParamList(): 
    1342                     if not model.is_fittable(param) and \ 
     1353                    if '.' in param and param in param_list: 
     1354                        # Ensure polydispersity results are displayed 
     1355                        p1, p2 = param.split('.') 
     1356                        if not model.is_fittable(p1) and not (p2 == 'width' and param in res.param_list)\ 
     1357                            and param in param_list: 
     1358                            param_list.remove(param) 
     1359                    elif not model.is_fittable(param) and \ 
    13431360                        param in param_list: 
    13441361                        param_list.remove(param) 
     
    13611378                    batch_outputs["Chi2"].append(ERROR) 
    13621379                    for param in param_list: 
    1363                         # save value of  fixed parameters 
     1380                        # Save value of  fixed parameters 
    13641381                        if param not in res.param_list: 
    13651382                            batch_outputs[str(param)].append(ERROR) 
    13661383                        else: 
    1367                             #save only fitted values 
     1384                            # Save only fitted values 
    13681385                            batch_outputs[param].append(ERROR) 
    13691386                            batch_inputs["error on %s" % str(param)].append(ERROR) 
  • src/sas/sasgui/perspectives/fitting/models.py

    rb682c6a r13374be  
    1414import py_compile 
    1515import shutil 
     16from copy import copy 
    1617# Explicitly import from the pluginmodel module so that py2exe 
    1718# places it in the distribution. The Model1DPlugin class is used 
     
    281282        """ 
    282283 
    283         # regular model names only 
     284        # Regular model names only 
    284285        self.model_name_list = [] 
    285286 
    286         #Build list automagically from sasmodels package 
     287        # Build list automagically from sasmodels package 
    287288        for model in load_standard_models(): 
    288289            self.model_dictionary[model.name] = model 
     
    296297                self.model_name_list.append(model.name) 
    297298 
    298         #Looking for plugins 
     299        # Looking for plugins 
    299300        self.stored_plugins = self.findModels() 
    300301        self.plugins = self.stored_plugins.values() 
    301302        for name, plug in self.stored_plugins.iteritems(): 
    302303            self.model_dictionary[name] = plug 
     304            # TODO: Remove 'hasattr' statements when old style plugin models 
     305            # are no longer supported. All sasmodels models will have 
     306            # the required attributes. 
     307            if hasattr(plug, 'is_structure_factor') and plug.is_structure_factor: 
     308                self.struct_list.append(plug) 
     309                self.plugins.remove(plug) 
     310            elif hasattr(plug, 'is_form_factor') and plug.is_form_factor: 
     311                self.multiplication_factor.append(plug) 
     312            if hasattr(plug, 'is_multiplicity_model') and plug.is_multiplicity_model: 
     313                self.multi_func_list.append(plug) 
    303314 
    304315        self._get_multifunc_models() 
     
    343354        """ 
    344355        self.plugins = [] 
    345         new_plugins = _find_models() 
    346         for name, plug in  new_plugins.iteritems(): 
    347             for stored_name, stored_plug in self.stored_plugins.iteritems(): 
    348                 if name == stored_name: 
    349                     del self.stored_plugins[name] 
    350                     del self.model_dictionary[name] 
    351                     break 
     356        self.stored_plugins = _find_models() 
     357        structure_names = [model.name for model in self.struct_list] 
     358        form_names = [model.name for model in self.multiplication_factor] 
     359 
     360        # Remove all plugin structure factors and form factors 
     361        for name in copy(structure_names): 
     362            if '[plug-in]' in name: 
     363                i = structure_names.index(name) 
     364                del self.struct_list[i] 
     365                structure_names.remove(name) 
     366        for name in copy(form_names): 
     367            if '[plug-in]' in name: 
     368                i = form_names.index(name) 
     369                del self.multiplication_factor[i] 
     370                form_names.remove(name) 
     371 
     372        # Add new plugin structure factors and form factors 
     373        for name, plug in self.stored_plugins.iteritems(): 
     374            if plug.is_structure_factor: 
     375                if name in structure_names: 
     376                    # Delete the old model from self.struct list 
     377                    i = structure_names.index(name) 
     378                    del self.struct_list[i] 
     379                # Add the new model to self.struct_list 
     380                self.struct_list.append(plug) 
     381            elif plug.is_form_factor: 
     382                if name in form_names: 
     383                    # Delete the old model from self.multiplication_factor 
     384                    i = form_names.index(name) 
     385                    del self.multiplication_factor[i] 
     386                # Add the new model to self.multiplication_factor 
     387                self.multiplication_factor.append(plug) 
     388 
     389            # Add references to the updated model 
    352390            self.stored_plugins[name] = plug 
    353             self.plugins.append(plug) 
     391            if not plug.is_structure_factor: 
     392                # Don't show S(Q) models in the 'Plugin Models' dropdown 
     393                self.plugins.append(plug) 
    354394            self.model_dictionary[name] = plug 
    355395 
    356396        self.model_combobox.reset_list("Plugin Models", self.plugins) 
     397        self.model_combobox.reset_list("Structure Factors", self.struct_list) 
     398        self.model_combobox.reset_list("P(Q)*S(Q)", self.multiplication_factor) 
     399 
    357400        return self.model_combobox.get_list() 
    358401 
  • test/corfunc/test/utest_corfunc.py

    r253eb6c6 r86ba9d6  
    22Unit Tests for CorfuncCalculator class 
    33""" 
     4from __future__ import division, print_function 
    45 
    56import unittest 
    67import time 
     8 
    79import numpy as np 
     10 
    811from sas.sascalc.corfunc.corfunc_calculator import CorfuncCalculator 
    912from sas.sascalc.dataloader.data_info import Data1D 
     
    1417    def setUp(self): 
    1518        self.data = load_data() 
     19        # Note: to generate target values from the GUI: 
     20        # * load the data from test/corfunc/test/98929.txt 
     21        # * set qrange to (0, 0.013), (0.15, 0.24) 
     22        # * select fourier transform type 
     23        # * click Calculate Bg 
     24        # * click Extrapolate 
     25        # * click Compute Parameters 
     26        # * copy the Guinier and Porod values to the extrapolate function 
     27        # * for each graph, grab the data from DataInfo and store it in _out.txt 
    1628        self.calculator = CorfuncCalculator(data=self.data, lowerq=0.013, 
    1729            upperq=(0.15, 0.24)) 
     30        self.calculator.background = 0.3 
    1831        self.extrapolation = None 
     32        self.transformation = None 
     33        self.results = [np.loadtxt(filename+"_out.txt").T[2] 
     34                        for filename in ("gamma1", "gamma3", "idf")] 
    1935 
    2036    def extrapolate(self): 
    21         params, extrapolation = self.calculator.compute_extrapolation() 
    22  
     37        params, extrapolation, s2 = self.calculator.compute_extrapolation() 
    2338        # Check the extrapolation parameters 
    24         self.assertAlmostEqual(params['A'], 4.19, places=2) 
    25         self.assertAlmostEqual(params['B'], -25470, places=0) 
    26         self.assertAlmostEqual(params['K'], 4.5e-5, places=2) 
    27         self.assertAlmostEqual(params['sigma'], 2.2e-10, places=2) 
     39        self.assertAlmostEqual(params['A'], 4.18970, places=5) 
     40        self.assertAlmostEqual(params['B'], -25469.9, places=1) 
     41        self.assertAlmostEqual(params['K'], 4.44660e-5, places=10) 
     42        #self.assertAlmostEqual(params['sigma'], 1.70181e-10, places=15) 
    2843 
    2944        # Ensure the extraplation tends to the background value 
     
    5772                break 
    5873 
    59     def transform_callback(self, transform): 
    60         self.assertIsNotNone(transform) 
    61         self.assertAlmostEqual(transform.y[0], 1) 
    62         self.assertAlmostEqual(transform.y[-1], 0, 5) 
    63         self.transformation = transform 
     74    def transform_callback(self, transforms): 
     75        transform1, transform3, idf = transforms 
     76        self.assertIsNotNone(transform1) 
     77        self.assertAlmostEqual(transform1.y[0], 1) 
     78        self.assertAlmostEqual(transform1.y[-1], 0, 5) 
     79        self.transformation = transforms 
    6480 
    6581    def extract_params(self): 
    66         params = self.calculator.extract_parameters(self.transformation) 
     82        params = self.calculator.extract_parameters(self.transformation[0]) 
    6783        self.assertIsNotNone(params) 
    6884        self.assertEqual(len(params), 6) 
    6985        self.assertLess(abs(params['max']-75), 2.5) # L_p ~= 75 
    7086 
     87    def check_transforms(self): 
     88        gamma1, gamma3, idf = self.transformation 
     89        gamma1_out, gamma3_out, idf_out = self.results 
     90        def compare(a, b): 
     91            return max(abs((a-b)/b)) 
     92        #print("gamma1 diff", compare(gamma1.y[gamma1.x<=200.], gamma1_out)) 
     93        #print("gamma3 diff", compare(gamma3.y[gamma3.x<=200.], gamma3_out)) 
     94        #print("idf diff", compare(idf.y[idf.x<=200.], idf_out)) 
     95        #self.assertLess(compare(gamma1.y[gamma1.x<=200.], gamma1_out), 1e-10) 
     96        #self.assertLess(compare(gamma3.y[gamma3.x<=200.], gamma3_out), 1e-10) 
     97        #self.assertLess(compare(idf.y[idf.x<=200.], idf_out), 1e-10) 
     98 
    7199    # Ensure tests are ran in correct order; 
    72100    # Each test depends on the one before it 
    73101    def test_calculator(self): 
    74         steps = [self.extrapolate, self.transform, self.extract_params] 
     102        steps = [self.extrapolate, self.transform, self.extract_params, self.check_transforms] 
    75103        for test in steps: 
    76104            try: 
    77105                test() 
    78106            except Exception as e: 
     107                raise 
    79108                self.fail("{} failed ({}: {})".format(test, type(e), e)) 
    80109 
    81110 
    82111def load_data(filename="98929.txt"): 
    83     data = np.loadtxt(filename, dtype=np.float32) 
     112    data = np.loadtxt(filename, dtype=np.float64) 
    84113    q = data[:,0] 
    85114    iq = data[:,1] 
  • test/utest_sasview.py

    rb54440d rbe51cf6  
    6262                    proc = subprocess.Popen(code, shell=True, stdout=subprocess.PIPE, stderr = subprocess.STDOUT) 
    6363                    std_out, std_err = proc.communicate() 
    64                     #print std_out 
     64                    #print(">>>>>> standard out", file_path, "\n", std_out, "\n>>>>>>>>> end stdout", file_path) 
    6565                    #sys.exit() 
    6666                    m = re.search("Ran ([0-9]+) test", std_out) 
     
    8282                        failed += 1 
    8383                        print("Result for %s (%s): FAILED" % (module_name, module_dir)) 
    84                         print(std_out) 
     84                        #print(std_out) 
    8585                    else: 
    8686                        passed += 1 
  • docs/sphinx-docs/source/conf.py

    r959eb01 rce2819b  
    3939              'sphinx.ext.viewcode'] 
    4040 
     41#set mathjax path 
     42mathjax_path="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.1/MathJax.js?config=TeX-MML-AM_CHTML" 
     43 
    4144# Add any paths that contain templates here, relative to this directory. 
    4245templates_path = ['_templates'] 
     
    6265version = '4.1' 
    6366# The full version, including alpha/beta/rc tags. 
    64 release = '4.1.0' 
     67release = '4.1.2' 
    6568 
    6669# The language for content autogenerated by Sphinx. Refer to documentation 
  • sasview/README.txt

    r9146ed9 r6394851  
    441- Features 
    55=========== 
     6    - New in Version 4.1.2 
     7      -------------------- 
     8      This point release is a bug-fix release addressing: 
     9 
     10       - Fixes #984: PDF Reports Generate Empty PDFs 
     11       - Fixes a path typo 
     12       - 64 bit and 32 bit Windows executables now available 
     13 
     14      It is recommended that all users upgrade to this version 
     15 
     16    - New in Version 4.1.1 
     17      -------------------- 
     18      This point release is a bug-fix release addressing: 
     19 
     20       - Fixes #948: Mathjax CDN is going away 
     21       - Fixes #938: Cannot read canSAS1D file output by SasView 
     22       - Fixes #960: Save project throws error if empty fit page 
     23       - Fixes #929: Problem deleting data in first fit page 
     24       - Fixes #918: Test folders not bundled with release 
     25       - Fixes an issue with the live discovery of plugin models 
     26       - Fixes an issue with the NXcanSAS data loader 
     27       - Updated tutorials for SasView 4.x.y 
     28 
    629    - New in Version 4.1.0 
    730      ------------------ 
  • sasview/__init__.py

    r463e7ffc rce2819b  
    1 __version__ = "4.1" 
     1__version__ = "4.1.2" 
    22__build__ = "GIT_COMMIT" 
    33 
  • sasview/local_config.py

    ra1b8fee rce2819b  
    4747'''This work benefited from the use of the SasView application, originally developed under NSF Award DMR-0520547. SasView also contains code developed with funding from the EU Horizon 2020 programme under the SINE2020 project Grant No 654000.''' 
    4848_acknowledgement_citation = \ 
    49 '''M. Doucet et al. SasView Version 4.1, Zenodo, 10.5281/zenodo.438138''' 
     49'''M. Doucet et al. SasView Version 4.1.2, Zenodo, 10.5281/zenodo.825675''' 
    5050 
    5151_acknowledgement =  \ 
  • sasview/sasview.spec

    re42c8e9d r945f45d  
    138138 'sasmodels.core', 
    139139 'pyopencl', 
    140  'tinycc' 
     140 'tinycc', 
     141 'xhtml2pdf' 
    141142] 
    142143 
  • sasview/setup_exe.py

    r5a8cdbb rcd57c7d4  
    179179test_1d_dir = os.path.join(path, "test\\1d_data") 
    180180test_2d_dir = os.path.join(path, "test\\2d_data") 
     181test_sesans_dir = os.path.join(path, "test\\sesans_data") 
     182test_convertible_dir = os.path.join(path, "test\\convertible_files") 
    181183test_save_dir = os.path.join(path, "test\\save_states") 
    182 test_upcoming_dir = os.path.join(path, "test\\upcoming_formats") 
     184test_coord_dir = os.path.join(path, "test\\coordinate_data") 
     185test_image_dir = os.path.join(path, "test\\image_data") 
     186test_other_dir = os.path.join(path, "test\\other_files") 
    183187 
    184188matplotlibdatadir = matplotlib.get_data_path() 
     
    269273# Copying the images directory to the distribution directory. 
    270274for f in findall(images_dir): 
    271     if not ".svn" in f: 
    272         data_files.append(("images", [f])) 
     275    data_files.append(("images", [f])) 
    273276 
    274277# Copying the HTML help docs 
    275278for f in findall(media_dir): 
    276     if not ".svn" in f: 
    277         data_files.append(("media", [f])) 
     279    data_files.append(("media", [f])) 
    278280 
    279281# Copying the sample data user data 
    280282for f in findall(test_1d_dir): 
    281     if not ".svn" in f: 
    282         data_files.append(("test\\1d_data", [f])) 
    283  
    284 # Copying the sample data user data 
     283    data_files.append(("test\\1d_data", [f])) 
    285284for f in findall(test_2d_dir): 
    286     if not ".svn" in f: 
    287         data_files.append(("test\\2d_data", [f])) 
    288  
    289 # Copying the sample data user data 
     285    data_files.append(("test\\2d_data", [f])) 
    290286for f in findall(test_save_dir): 
    291     if not ".svn" in f: 
    292         data_files.append(("test\\save_states", [f])) 
    293  
    294 # Copying the sample data user data 
    295 for f in findall(test_upcoming_dir): 
    296     if not ".svn" in f: 
    297         data_files.append(("test\\upcoming_formats", [f])) 
     287    data_files.append(("test\\save_states", [f])) 
     288for f in findall(test_sesans_dir): 
     289    data_files.append(("test\\sesans_data", [f])) 
     290for f in findall(test_convertible_dir): 
     291    data_files.append(("test\\convertible_files", [f])) 
     292for f in findall(test_coord_dir): 
     293    data_files.append(("test\\coordinate_data", [f])) 
     294for f in findall(test_image_dir): 
     295    data_files.append(("test\\image_data", [f])) 
     296for f in findall(test_other_dir): 
     297    data_files.append(("test\\other_files", [f])) 
    298298 
    299299# Copying opencl include files 
  • src/sas/sascalc/dataloader/file_reader_base_class.py

    ra78a02f rae69c690  
    115115                data.y = np.asarray([data.y[i] for i in ind]).astype(np.float64) 
    116116                if data.dx is not None: 
     117                    if len(data.dx) == 0: 
     118                        data.dx = None 
     119                        continue 
    117120                    data.dx = np.asarray([data.dx[i] for i in ind]).astype(np.float64) 
    118121                if data.dxl is not None: 
     
    121124                    data.dxw = np.asarray([data.dxw[i] for i in ind]).astype(np.float64) 
    122125                if data.dy is not None: 
     126                    if len(data.dy) == 0: 
     127                        data.dy = None 
     128                        continue 
    123129                    data.dy = np.asarray([data.dy[i] for i in ind]).astype(np.float64) 
    124130                if data.lam is not None: 
     
    185191        self.output = [] 
    186192 
    187     def remove_empty_q_values(self, has_error_dx=False, has_error_dy=False): 
     193    def remove_empty_q_values(self, has_error_dx=False, has_error_dy=False, 
     194                              has_error_dxl=False, has_error_dxw=False): 
    188195        """ 
    189196        Remove any point where Q == 0 
     
    192199        self.current_dataset.x = self.current_dataset.x[x != 0] 
    193200        self.current_dataset.y = self.current_dataset.y[x != 0] 
    194         self.current_dataset.dy = self.current_dataset.dy[x != 0] if \ 
    195             has_error_dy else np.zeros(len(self.current_dataset.y)) 
    196         self.current_dataset.dx = self.current_dataset.dx[x != 0] if \ 
    197             has_error_dx else np.zeros(len(self.current_dataset.x)) 
     201        if has_error_dy: 
     202            self.current_dataset.dy = self.current_dataset.dy[x != 0] 
     203        if has_error_dx: 
     204            self.current_dataset.dx = self.current_dataset.dx[x != 0] 
     205        if has_error_dxl: 
     206            self.current_dataset.dxl = self.current_dataset.dxl[x != 0] 
     207        if has_error_dxw: 
     208            self.current_dataset.dxw = self.current_dataset.dxw[x != 0] 
    198209 
    199210    def reset_data_list(self, no_lines=0): 
     
    204215        x = np.zeros(no_lines) 
    205216        y = np.zeros(no_lines) 
     217        dx = np.zeros(no_lines) 
    206218        dy = np.zeros(no_lines) 
    207         dx = np.zeros(no_lines) 
    208219        self.current_dataset = plottable_1D(x, y, dx, dy) 
    209220 
  • src/sas/sascalc/dataloader/readers/cansas_reader.py

    ra78a02f rae69c690  
    130130                self.current_datainfo.meta_data[PREPROCESS] = self.processing_instructions 
    131131                self._parse_entry(entry) 
    132                 has_error_dx = self.current_dataset.dx is not None 
    133                 has_error_dy = self.current_dataset.dy is not None 
    134                 self.remove_empty_q_values(has_error_dx=has_error_dx, 
    135                     has_error_dy=has_error_dy) 
    136                 self.send_to_output() # Combine datasets with DataInfo 
    137                 self.current_datainfo = DataInfo() # Reset DataInfo 
     132                self.data_cleanup() 
    138133        except FileContentsException as fc_exc: 
    139134            # File doesn't meet schema - try loading with a less strict schema 
     
    154149                    self.load_file_and_schema(xml_file) # Reload strict schema so we can find where error are in file 
    155150                    invalid_xml = self.find_invalid_xml() 
    156                     invalid_xml = INVALID_XML.format(basename + self.extension) + invalid_xml 
    157                     raise DataReaderException(invalid_xml) # Handled by base class 
     151                    if invalid_xml != "": 
     152                        invalid_xml = INVALID_XML.format(basename + self.extension) + invalid_xml 
     153                        raise DataReaderException(invalid_xml) # Handled by base class 
    158154                except FileContentsException as fc_exc: 
    159155                    msg = "CanSAS Reader could not load the file {}".format(xml_file) 
     
    279275                # I and Q points 
    280276                elif tagname == 'I' and isinstance(self.current_dataset, plottable_1D): 
    281                     unit_list = unit.split("|") 
    282                     if len(unit_list) > 1: 
    283                         self.current_dataset.yaxis(unit_list[0].strip(), 
    284                                                    unit_list[1].strip()) 
    285                     else: 
    286                         self.current_dataset.yaxis("Intensity", unit) 
     277                    self.current_dataset.yaxis("Intensity", unit) 
    287278                    self.current_dataset.y = np.append(self.current_dataset.y, data_point) 
    288279                elif tagname == 'Idev' and isinstance(self.current_dataset, plottable_1D): 
    289280                    self.current_dataset.dy = np.append(self.current_dataset.dy, data_point) 
    290281                elif tagname == 'Q': 
    291                     unit_list = unit.split("|") 
    292                     if len(unit_list) > 1: 
    293                         self.current_dataset.xaxis(unit_list[0].strip(), 
    294                                                    unit_list[1].strip()) 
    295                     else: 
    296                         self.current_dataset.xaxis("Q", unit) 
     282                    self.current_dataset.xaxis("Q", unit) 
    297283                    self.current_dataset.x = np.append(self.current_dataset.x, data_point) 
    298284                elif tagname == 'Qdev': 
    299285                    self.current_dataset.dx = np.append(self.current_dataset.dx, data_point) 
    300286                elif tagname == 'dQw': 
    301                     if self.current_dataset.dxw is None: 
    302                         self.current_dataset.dxw = np.empty(0) 
    303                     self.current_dataset.dxw = np.append(self.current_dataset.dxw, data_point) 
     287                   self.current_dataset.dxw = np.append(self.current_dataset.dxw, data_point) 
    304288                elif tagname == 'dQl': 
    305                     if self.current_dataset.dxl is None: 
    306                         self.current_dataset.dxl = np.empty(0) 
    307289                    self.current_dataset.dxl = np.append(self.current_dataset.dxl, data_point) 
    308290                elif tagname == 'Qmean': 
     
    312294                elif tagname == 'Sesans': 
    313295                    self.current_datainfo.isSesans = bool(data_point) 
     296                    self.current_dataset.xaxis(attr.get('x_axis'), 
     297                                                attr.get('x_unit')) 
     298                    self.current_dataset.yaxis(attr.get('y_axis'), 
     299                                                attr.get('y_unit')) 
    314300                elif tagname == 'yacceptance': 
    315301                    self.current_datainfo.sample.yacceptance = (data_point, unit) 
     
    512498            for error in self.errors: 
    513499                self.current_datainfo.errors.add(error) 
    514             self.errors.clear() 
    515             self.send_to_output() 
     500            self.data_cleanup() 
     501            self.sort_one_d_data() 
     502            self.sort_two_d_data() 
     503            self.reset_data_list() 
    516504            empty = None 
    517505            return self.output[0], empty 
     506 
     507    def data_cleanup(self): 
     508        """ 
     509        Clean up the data sets and refresh everything 
     510        :return: None 
     511        """ 
     512        has_error_dx = self.current_dataset.dx is not None 
     513        has_error_dxl = self.current_dataset.dxl is not None 
     514        has_error_dxw = self.current_dataset.dxw is not None 
     515        has_error_dy = self.current_dataset.dy is not None 
     516        self.remove_empty_q_values(has_error_dx=has_error_dx, 
     517                                   has_error_dxl=has_error_dxl, 
     518                                   has_error_dxw=has_error_dxw, 
     519                                   has_error_dy=has_error_dy) 
     520        self.send_to_output()  # Combine datasets with DataInfo 
     521        self.current_datainfo = DataInfo()  # Reset DataInfo 
    518522 
    519523    def _is_call_local(self): 
     
    642646                    value_unit = local_unit 
    643647            except KeyError: 
    644                 err_msg = "CanSAS reader: unexpected " 
    645                 err_msg += "\"{0}\" unit [{1}]; " 
    646                 err_msg = err_msg.format(tagname, local_unit) 
    647                 err_msg += "expecting [{0}]".format(default_unit) 
     648                # Do not throw an error for loading Sesans data in cansas xml 
     649                # This is a temporary fix. 
     650                if local_unit != "A" and local_unit != 'pol': 
     651                    err_msg = "CanSAS reader: unexpected " 
     652                    err_msg += "\"{0}\" unit [{1}]; " 
     653                    err_msg = err_msg.format(tagname, local_unit) 
     654                    err_msg += "expecting [{0}]".format(default_unit) 
    648655                value_unit = local_unit 
    649656            except: 
     
    675682            di_exists = True 
    676683        if dqw_exists and not dql_exists: 
    677             array_size = self.current_dataset.dxw.size - 1 
    678             self.current_dataset.dxl = np.append(self.current_dataset.dxl, 
    679                                                  np.zeros([array_size])) 
     684            array_size = self.current_dataset.dxw.size 
     685            self.current_dataset.dxl = np.zeros(array_size) 
    680686        elif dql_exists and not dqw_exists: 
    681             array_size = self.current_dataset.dxl.size - 1 
    682             self.current_dataset.dxw = np.append(self.current_dataset.dxw, 
    683                                                  np.zeros([array_size])) 
     687            array_size = self.current_dataset.dxl.size 
     688            self.current_dataset.dxw = np.zeros(array_size) 
    684689        elif not dql_exists and not dqw_exists and not dq_exists: 
    685             array_size = self.current_dataset.x.size - 1 
     690            array_size = self.current_dataset.x.size 
    686691            self.current_dataset.dx = np.append(self.current_dataset.dx, 
    687692                                                np.zeros([array_size])) 
    688693        if not di_exists: 
    689             array_size = self.current_dataset.y.size - 1 
     694            array_size = self.current_dataset.y.size 
    690695            self.current_dataset.dy = np.append(self.current_dataset.dy, 
    691696                                                np.zeros([array_size])) 
     
    857862            node.append(point) 
    858863            self.write_node(point, "Q", datainfo.x[i], 
    859                             {'unit': datainfo._xaxis + " | " + datainfo._xunit}) 
     864                            {'unit': datainfo.x_unit}) 
    860865            if len(datainfo.y) >= i: 
    861866                self.write_node(point, "I", datainfo.y[i], 
    862                                 {'unit': datainfo._yaxis + " | " + datainfo._yunit}) 
     867                                {'unit': datainfo.y_unit}) 
    863868            if datainfo.dy is not None and len(datainfo.dy) > i: 
    864869                self.write_node(point, "Idev", datainfo.dy[i], 
    865                                 {'unit': datainfo._yaxis + " | " + datainfo._yunit}) 
     870                                {'unit': datainfo.y_unit}) 
    866871            if datainfo.dx is not None and len(datainfo.dx) > i: 
    867872                self.write_node(point, "Qdev", datainfo.dx[i], 
    868                                 {'unit': datainfo._xaxis + " | " + datainfo._xunit}) 
     873                                {'unit': datainfo.x_unit}) 
    869874            if datainfo.dxw is not None and len(datainfo.dxw) > i: 
    870875                self.write_node(point, "dQw", datainfo.dxw[i], 
    871                                 {'unit': datainfo._xaxis + " | " + datainfo._xunit}) 
     876                                {'unit': datainfo.x_unit}) 
    872877            if datainfo.dxl is not None and len(datainfo.dxl) > i: 
    873878                self.write_node(point, "dQl", datainfo.dxl[i], 
    874                                 {'unit': datainfo._xaxis + " | " + datainfo._xunit}) 
     879                                {'unit': datainfo.x_unit}) 
    875880        if datainfo.isSesans: 
    876             sesans = self.create_element("Sesans") 
     881            sesans_attrib = {'x_axis': datainfo._xaxis, 
     882                             'y_axis': datainfo._yaxis, 
     883                             'x_unit': datainfo.x_unit, 
     884                             'y_unit': datainfo.y_unit} 
     885            sesans = self.create_element("Sesans", attrib=sesans_attrib) 
    877886            sesans.text = str(datainfo.isSesans) 
    878             node.append(sesans) 
    879             self.write_node(node, "yacceptance", datainfo.sample.yacceptance[0], 
     887            entry_node.append(sesans) 
     888            self.write_node(entry_node, "yacceptance", datainfo.sample.yacceptance[0], 
    880889                             {'unit': datainfo.sample.yacceptance[1]}) 
    881             self.write_node(node, "zacceptance", datainfo.sample.zacceptance[0], 
     890            self.write_node(entry_node, "zacceptance", datainfo.sample.zacceptance[0], 
    882891                             {'unit': datainfo.sample.zacceptance[1]}) 
    883892 
  • src/sas/sascalc/dataloader/readers/cansas_reader_HDF5.py

    rdcb91cf rcd57c7d4  
    140140 
    141141            if isinstance(value, h5py.Group): 
     142                # Set parent class before recursion 
    142143                self.parent_class = class_name 
    143144                parent_list.append(key) 
     
    150151                # Recursion step to access data within the group 
    151152                self.read_children(value, parent_list) 
     153                # Reset parent class when returning from recursive method 
     154                self.parent_class = class_name 
    152155                self.add_intermediate() 
    153156                parent_list.remove(key) 
  • src/sas/sascalc/dataloader/readers/xml_reader.py

    rfafe52a rcd57c7d4  
    134134            first_error = schema.assertValid(self.xmldoc) 
    135135        except etree.DocumentInvalid as err: 
     136            # Suppress errors for <'any'> elements 
     137            if "##other" in str(err): 
     138                return first_error 
    136139            first_error = str(err) 
    137140        return first_error 
  • src/sas/sascalc/invariant/invariant.py

    r7432acb rb1f20d1  
    610610        # Data boundaries for fitting 
    611611        qmin = self._data.x[0] 
    612         qmax = self._data.x[self._low_extrapolation_npts - 1] 
     612        qmax = self._data.x[int(self._low_extrapolation_npts - 1)] 
    613613 
    614614        # Extrapolate the low-Q data 
     
    649649        # Data boundaries for fitting 
    650650        x_len = len(self._data.x) - 1 
    651         qmin = self._data.x[x_len - (self._high_extrapolation_npts - 1)] 
    652         qmax = self._data.x[x_len] 
     651        qmin = self._data.x[int(x_len - (self._high_extrapolation_npts - 1))] 
     652        qmax = self._data.x[int(x_len)] 
    653653 
    654654        # fit the data with a model to get the appropriate parameters 
     
    688688        if npts_in is None: 
    689689            npts_in = self._low_extrapolation_npts 
    690         q_end = self._data.x[max(0, npts_in - 1)] 
     690        q_end = self._data.x[max(0, int(npts_in - 1))] 
    691691 
    692692        if q_start >= q_end: 
     
    714714        # Get extrapolation range 
    715715        if npts_in is None: 
    716             npts_in = self._high_extrapolation_npts 
     716            npts_in = int(self._high_extrapolation_npts) 
    717717        _npts = len(self._data.x) 
    718         q_start = self._data.x[min(_npts, _npts - npts_in)] 
     718        q_start = self._data.x[min(_npts, int(_npts - npts_in))] 
    719719 
    720720        if q_start >= q_end: 
  • src/sas/sasgui/guiframe/config.py

    ra1b8fee rce2819b  
    4848'''This work benefited from the use of the SasView application, originally developed under NSF Award DMR-0520547. SasView also contains code developed with funding from the EU Horizon 2020 programme under the SINE2020 project Grant No 654000.''' 
    4949_acknowledgement_citation = \ 
    50 '''M. Doucet et al. SasView Version 4.1, Zenodo, 10.5281/zenodo.438138''' 
     50'''M. Doucet et al. SasView Version 4.1.2, Zenodo, 10.5281/zenodo.825675''' 
    5151 
    5252_acknowledgement =  \ 
  • src/sas/sasgui/guiframe/documentation_window.py

    r959eb01 r6a455cd3  
    7575            logger.error("Could not find Sphinx documentation at %s \ 
    7676            -- has it been built?", file_path) 
    77         elif WX_SUPPORTS_HTML2: 
    78             # Complete HTML/CSS support! 
    79             self.view = html.WebView.New(self) 
    80             self.view.LoadURL(url) 
    81             self.Show() 
     77        #Commenting following 5 lines, so default browser is forced 
     78        #This is due to CDN mathjax discontinuation of service, intenal help 
     79        #browser should be back with qt version 
     80        #Note added by Wojtek Potrzebowski, July 4th 2017 
     81        # elif WX_SUPPORTS_HTML2: 
     82        #     # Complete HTML/CSS support! 
     83        #     self.view = html.WebView.New(self) 
     84        #     self.view.LoadURL(url) 
     85        #     self.Show() 
    8286        else: 
    8387            logger.error("No html2 support, popping up a web browser") 
  • src/sas/sasgui/perspectives/fitting/pagestate.py

    r959eb01 rda9b239  
    617617            value = "" 
    618618            content = line.split(":") 
     619            if line == '' or len(content) == 1: 
     620                continue 
    619621            name = content[0] 
    620622            try: 
  • test/sasdataloader/test/utest_abs_reader.py

    ra78a02f rae69c690  
    333333        self.assertEqual(self.data.x[1], 0.03) 
    334334        self.assertAlmostEquals(self.data.y[1], 1001.0) 
    335         self.assertEqual(self.data.dx[0], 0.0) 
    336335        self.assertEqual(self.data.dxl[1], 0.005) 
    337336        self.assertEqual(self.data.dxw[1], 0.001) 
Note: See TracChangeset for help on using the changeset viewer.