Changeset 932519a in sasview for src/sas


Ignore:
Timestamp:
Sep 19, 2017 2:07:00 PM (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:
86ba9d6
Parents:
1f21a43 (diff), b22e23e (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 corfunc3d

Location:
src/sas
Files:
3 added
3 deleted
14 edited

Legend:

Unmodified
Added
Removed
  • 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/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

    red2276f r66acafe  
    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: 
     
    21812188        self.save_current_state() 
    21822189 
     2190        if not self.is_mac: 
     2191            self.Layout() 
     2192            self.Refresh() 
    21832193        # plot model ( when drawing, do not update chisqr value again) 
    21842194        self._draw_model(update_chisqr=False, source='fit') 
     
    27752785            else: 
    27762786                return cmp(a.lower(), b.lower()) 
    2777          
     2787 
    27782788        # keys obtained now from ordered dict, so commenting alphabetical 
    27792789        # ordering keys.sort(custom_compare) 
  • src/sas/sasgui/perspectives/fitting/fitpanel.py

    r67b0a99 r6f9abd3  
    501501            if data is None: 
    502502                return None 
     503        focused_page = self.GetPage(self.GetSelection()) 
    503504        for page in self.opened_pages.values(): 
    504505            # check if the selected data existing in the fitpanel 
    505506            pos = self.GetPageIndex(page) 
    506507            if not check_data_validity(page.get_data()) and not page.batch_on: 
     508                if page.model is not None and page != focused_page: 
     509                    # Page has an active theory and is in background - don't 
     510                    # send data here. 
     511                    continue 
    507512                # make sure data get placed in 1D empty tab if data is 1D 
    508513                # 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

    rb1c2011 r632fda9  
    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 
     
    278279        """ 
    279280 
    280         # regular model names only 
     281        # Regular model names only 
    281282        self.model_name_list = [] 
    282283 
    283         #Build list automagically from sasmodels package 
     284        # Build list automagically from sasmodels package 
    284285        for model in load_standard_models(): 
    285286            self.model_dictionary[model.name] = model 
     
    293294                self.model_name_list.append(model.name) 
    294295 
    295         #Looking for plugins 
     296        # Looking for plugins 
    296297        self.stored_plugins = self.findModels() 
    297298        self.plugins = self.stored_plugins.values() 
    298299        for name, plug in self.stored_plugins.iteritems(): 
    299300            self.model_dictionary[name] = plug 
     301            # TODO: Remove 'hasattr' statements when old style plugin models 
     302            # are no longer supported. All sasmodels models will have 
     303            # the required attributes. 
     304            if hasattr(plug, 'is_structure_factor') and plug.is_structure_factor: 
     305                self.struct_list.append(plug) 
     306                self.plugins.remove(plug) 
     307            elif hasattr(plug, 'is_form_factor') and plug.is_form_factor: 
     308                self.multiplication_factor.append(plug) 
     309            if hasattr(plug, 'is_multiplicity_model') and plug.is_multiplicity_model: 
     310                self.multi_func_list.append(plug) 
    300311 
    301312        self._get_multifunc_models() 
     
    340351        """ 
    341352        self.plugins = [] 
    342         new_plugins = _find_models() 
    343         for name, plug in  new_plugins.iteritems(): 
    344             for stored_name, stored_plug in self.stored_plugins.iteritems(): 
    345                 if name == stored_name: 
    346                     del self.stored_plugins[name] 
    347                     del self.model_dictionary[name] 
    348                     break 
     353        self.stored_plugins = _find_models() 
     354        structure_names = [model.name for model in self.struct_list] 
     355        form_names = [model.name for model in self.multiplication_factor] 
     356 
     357        # Remove all plugin structure factors and form factors 
     358        for name in copy(structure_names): 
     359            if '[plug-in]' in name: 
     360                i = structure_names.index(name) 
     361                del self.struct_list[i] 
     362                structure_names.remove(name) 
     363        for name in copy(form_names): 
     364            if '[plug-in]' in name: 
     365                i = form_names.index(name) 
     366                del self.multiplication_factor[i] 
     367                form_names.remove(name) 
     368 
     369        # Add new plugin structure factors and form factors 
     370        for name, plug in self.stored_plugins.iteritems(): 
     371            if plug.is_structure_factor: 
     372                if name in structure_names: 
     373                    # Delete the old model from self.struct list 
     374                    i = structure_names.index(name) 
     375                    del self.struct_list[i] 
     376                # Add the new model to self.struct_list 
     377                self.struct_list.append(plug) 
     378            elif plug.is_form_factor: 
     379                if name in form_names: 
     380                    # Delete the old model from self.multiplication_factor 
     381                    i = form_names.index(name) 
     382                    del self.multiplication_factor[i] 
     383                # Add the new model to self.multiplication_factor 
     384                self.multiplication_factor.append(plug) 
     385 
     386            # Add references to the updated model 
    349387            self.stored_plugins[name] = plug 
    350             self.plugins.append(plug) 
     388            if not plug.is_structure_factor: 
     389                # Don't show S(Q) models in the 'Plugin Models' dropdown 
     390                self.plugins.append(plug) 
    351391            self.model_dictionary[name] = plug 
    352392 
    353393        self.model_combobox.reset_list("Plugin Models", self.plugins) 
     394        self.model_combobox.reset_list("Structure Factors", self.struct_list) 
     395        self.model_combobox.reset_list("P(Q)*S(Q)", self.multiplication_factor) 
     396 
    354397        return self.model_combobox.get_list() 
    355398 
  • 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/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 r9b90bf8  
    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 r457f735  
    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)$" 
Note: See TracChangeset for help on using the changeset viewer.