Changeset e56f335 in sasview for src/sas/sasgui


Ignore:
Timestamp:
Sep 14, 2017 2:28:11 PM (7 years ago)
Author:
krzywon
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:
590b5c2
Parents:
4660990 (diff), 7b3f154 (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

Location:
src/sas/sasgui
Files:
3 added
11 edited

Legend:

Unmodified
Added
Removed
  • src/sas/sasgui/guiframe/local_perspectives/plotting/plotting.py

    r235f514 r2d9526d  
    1414import wx 
    1515import sys 
     16from copy import deepcopy 
    1617from sas.sasgui.guiframe.events import EVT_NEW_PLOT 
    1718from sas.sasgui.guiframe.events import EVT_PLOT_QRANGE 
     
    275276                action_check = True 
    276277            else: 
     278                if action_string == 'update': 
     279                    # Update all existing plots of data with this ID 
     280                    for data in event.plots: 
     281                        for panel in self.plot_panels.values(): 
     282                            if data.id in panel.plots.keys(): 
     283                                plot_exists = True 
     284                                # Pass each panel it's own copy of the data 
     285                                # that's being updated, otherwise things like 
     286                                # colour and line thickness are unintentionally 
     287                                # synced across panels 
     288                                self.update_panel(deepcopy(data), panel) 
     289                    return 
     290                     
    277291                group_id = event.group_id 
    278                 if group_id in self.plot_panels.keys(): 
     292                if group_id in self.plot_panels: 
    279293                    #remove data from panel 
    280294                    if action_string == 'remove': 
  • src/sas/sasgui/perspectives/fitting/fitting.py

    r489f53a r2d9526d  
    17421742            @param unsmeared_error: data error, rescaled to unsmeared model 
    17431743        """ 
    1744  
    17451744        number_finite = np.count_nonzero(np.isfinite(y)) 
    17461745        np.nan_to_num(y) 
     
    17481747                                         data_description=model.name, 
    17491748                                         data_id=str(page_id) + " " + data.name) 
     1749        plots_to_update = [] # List of plottables that have changed since last calculation 
     1750        # Create the new theories 
    17501751        if unsmeared_model is not None: 
    1751             self.create_theory_1D(x, unsmeared_model, page_id, model, data, state, 
     1752            unsmeared_model_plot = self.create_theory_1D(x, unsmeared_model,  
     1753                                  page_id, model, data, state, 
    17521754                                  data_description=model.name + " unsmeared", 
    17531755                                  data_id=str(page_id) + " " + data.name + " unsmeared") 
     1756            plots_to_update.append(unsmeared_model_plot) 
    17541757 
    17551758            if unsmeared_data is not None and unsmeared_error is not None: 
    1756                 self.create_theory_1D(x, unsmeared_data, page_id, model, data, state, 
     1759                unsmeared_data_plot = self.create_theory_1D(x, unsmeared_data,  
     1760                                      page_id, model, data, state, 
    17571761                                      data_description="Data unsmeared", 
    17581762                                      data_id="Data  " + data.name + " unsmeared", 
    17591763                                      dy=unsmeared_error) 
    1760         # Comment this out until we can get P*S models with correctly populated parameters 
    1761         #if sq_model is not None and pq_model is not None: 
    1762         #    self.create_theory_1D(x, sq_model, page_id, model, data, state, 
    1763         #                          data_description=model.name + " S(q)", 
    1764         #                          data_id=str(page_id) + " " + data.name + " S(q)") 
    1765         #    self.create_theory_1D(x, pq_model, page_id, model, data, state, 
    1766         #                          data_description=model.name + " P(q)", 
    1767         #                          data_id=str(page_id) + " " + data.name + " P(q)") 
     1764                plots_to_update.append(unsmeared_data_plot) 
     1765        if sq_model is not None and pq_model is not None: 
     1766            sq_id = str(page_id) + " " + data.name + " S(q)" 
     1767            sq_plot = self.create_theory_1D(x, sq_model, page_id, model, data, state, 
     1768                                  data_description=model.name + " S(q)", 
     1769                                  data_id=sq_id) 
     1770            plots_to_update.append(sq_plot) 
     1771            pq_id = str(page_id) + " " + data.name + " P(q)" 
     1772            pq_plot = self.create_theory_1D(x, pq_model, page_id, model, data, state, 
     1773                                  data_description=model.name + " P(q)", 
     1774                                  data_id=pq_id) 
     1775            plots_to_update.append(pq_plot) 
     1776        # Update the P(Q), S(Q) and unsmeared theory plots if they exist 
     1777        wx.PostEvent(self.parent, NewPlotEvent(plots=plots_to_update,  
     1778                                              action='update')) 
    17681779 
    17691780        current_pg = self.fit_panel.get_page_by_id(page_id) 
  • src/sas/sasgui/perspectives/fitting/media/fitting_help.rst

    r5295cf5 r05b0bf6  
    484484.. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 
    485485 
     486.. _Batch_Fit_Mode: 
     487 
    486488Batch Fit Mode 
    487489-------------- 
     
    636638 
    637639     Example: radius [2 : 5] , radius [10 : 25] 
    638  
    639 .. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 
    640  
    641 .. note::  This help document was last changed by Steve King, 10Oct2016 
     640      
     641.. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 
     642 
     643Combined Batch Fit Mode 
     644----------------------- 
     645 
     646The purpose of the Combined Batch Fit is to allow running two or more batch 
     647fits in sequence without overwriting the output table of results.  This may be 
     648of interest for example if one is fitting a series of data sets where there is 
     649a shape change occurring in the series that requires changing the model part 
     650way through the series; for example a sphere to rod transition.  Indeed the 
     651regular batch mode does not allow for multiple models and requires all the 
     652files in the series to be fit with single model and set of parameters.  While 
     653it is of course possible to just run part of the series as a batch fit using 
     654model one followed by running another batch fit on the rest of the series with 
     655model two (and/or model three etc), doing so will overwrite the table of 
     656outputs from the previous batch fit(s).  This may not be desirable if one is 
     657interested in comparing the parameters: for example the sphere radius of set 
     658one and the cylinder radius of set two. 
     659 
     660Method 
     661^^^^^^ 
     662 
     663In order to use the *Combined Batch Fit*, first load all the data needed as 
     664described in :ref:`Loading_data`. Next start up two or more *BatchPage* fits 
     665following the instructions in :ref:`Batch_Fit_Mode` but **DO NOT PRESS FIT**. 
     666At this point the *Combine Batch Fit* menu item under the *Fitting menu* should 
     667be active (if there is one or no *BatchPage* the menu item will be greyed out 
     668and inactive).  Clicking on *Combine Batch Fit* will bring up a new panel, 
     669similar to the *Const & Simult Fit* panel. In this case there will be a 
     670checkbox for each *BatchPage* instead of each *FitPage* that should be included 
     671in the fit.  Once all are selected, click the Fit button on 
     672the *BatchPage* to run each batch fit in *sequence* 
     673 
     674.. image:: combine_batch_page.png 
     675 
     676The batch table will then pop up at the end as for the case of the simple Batch 
     677Fitting with the following caveats: 
     678 
     679.. note:: 
     680   The order matters.  The parameters in the table will be taken from the model 
     681   used in the first *BatchPage* of the list.  Any parameters from the 
     682   second and later *BatchPage* s that have the same name as a parameter in the 
     683   first will show up allowing for plotting of that parameter across the 
     684   models. The other parameters will not be available in the grid. 
     685.. note:: 
     686   a corralary of the above is that currently models created as a sum|multiply 
     687   model will not work as desired because the generated model parameters have a 
     688   p#_ appended to the beginning and thus radius and p1_radius will not be 
     689   recognized as the same parameter. 
     690    
     691.. image:: combine_batch_grid.png 
     692 
     693In the example shown above the data is a time series with a shifting peak. 
     694The first part of the series was fitted using the *broad_peak* model, while 
     695the rest of the data were fit using the *gaussian_peak* model. Unfortunately the 
     696time is not listed in the file but the file name contains the information. As 
     697described in :ref:`Grid_Window`, a column can be added manually, in this case 
     698called time, and the peak position plotted against time.  
     699 
     700.. image:: combine_batch_plot.png 
     701 
     702Note the discontinuity in the peak position.  This reflects the fact that the 
     703Gaussian fit is a rather poor model for the data and is not actually 
     704finding the peak. 
     705 
     706.. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 
     707 
     708.. note::  This help document was last changed by Paul Butler, 10 September 
     709   2017 
  • src/sas/sasgui/perspectives/fitting/model_thread.py

    r7432acb r0f9ea1c  
    7171                    (self.data.qy_data * self.data.qy_data)) 
    7272 
    73         # For theory, qmax is based on 1d qmax  
     73        # For theory, qmax is based on 1d qmax 
    7474        # so that must be mulitified by sqrt(2) to get actual max for 2d 
    7575        index_model = (self.qmin <= radius) & (radius <= self.qmax) 
     
    9191                self.data.qy_data[index_model] 
    9292            ]) 
    93         output = np.zeros(len(self.data.qx_data)) 
     93        # Initialize output to NaN so masked elements do not get plotted. 
     94        output = np.empty_like(self.data.qx_data) 
    9495        # output default is None 
    9596        # This method is to distinguish between masked 
    9697        #point(nan) and data point = 0. 
    97         output = output / output 
     98        output[:] = np.NaN 
    9899        # set value for self.mask==True, else still None to Plottools 
    99100        output[index_model] = value 
     
    198199            output[index] = self.model.evalDistribution(self.data.x[index]) 
    199200 
     201        x=self.data.x[index] 
     202        y=output[index] 
    200203        sq_values = None 
    201204        pq_values = None 
    202         s_model = None 
    203         p_model = None 
    204205        if isinstance(self.model, MultiplicationModel): 
    205206            s_model = self.model.s_model 
    206207            p_model = self.model.p_model 
    207         elif hasattr(self.model, "get_composition_models"): 
    208             p_model, s_model = self.model.get_composition_models() 
    209  
    210         if p_model is not None and s_model is not None: 
    211             sq_values = np.zeros((len(self.data.x))) 
    212             pq_values = np.zeros((len(self.data.x))) 
    213             sq_values[index] = s_model.evalDistribution(self.data.x[index]) 
    214             pq_values[index] = p_model.evalDistribution(self.data.x[index]) 
     208            sq_values = s_model.evalDistribution(x) 
     209            pq_values = p_model.evalDistribution(x) 
     210        elif hasattr(self.model, "calc_composition_models"): 
     211            results = self.model.calc_composition_models(x) 
     212            if results is not None: 
     213                pq_values, sq_values = results 
     214 
    215215 
    216216        elapsed = time.time() - self.starttime 
    217217 
    218         self.complete(x=self.data.x[index], y=output[index], 
     218        self.complete(x=x, y=y, 
    219219                      page_id=self.page_id, 
    220220                      state=self.state, 
  • src/sas/sasgui/perspectives/fitting/simfitpage.py

    r959eb01 ra9f9ca4  
    11""" 
    2     Simultaneous fit page 
     2    Simultaneous or Batch fit page 
    33""" 
     4# Note that this is used for both Simultaneous/Constrained fit AND for  
     5# combined batch fit.  This is done through setting of the batch_on parameter. 
     6# There are the a half dozen or so places where an if statement is used as in  
     7# if not batch_on: 
     8#     xxxx 
     9# else: 
     10#     xxxx 
     11# This is just wrong but dont have time to fix this go. Proper approach would be 
     12# to strip all parts of the code that depend on batch_on and create the top 
     13# level class from which a contrained/simultaneous fit page and a combined  
     14# batch page inherit. 
     15# 
     16#            04/09/2017   --PDB 
     17 
    418import sys 
    519from collections import namedtuple 
     
    400414        # General Help button 
    401415        self.btHelp = wx.Button(self, wx.ID_HELP, 'HELP') 
    402         self.btHelp.SetToolTipString("Simultaneous/Constrained Fitting help.") 
     416        if self.batch_on: 
     417            self.btHelp.SetToolTipString("Combined Batch Fitting help.") 
     418        else: 
     419            self.btHelp.SetToolTipString("Simultaneous/Constrained Fitting help.") 
    403420        self.btHelp.Bind(wx.EVT_BUTTON, self._on_help) 
    404421 
     
    527544    """ 
    528545        _TreeLocation = "user/sasgui/perspectives/fitting/fitting_help.html" 
    529         _PageAnchor = "#simultaneous-fit-mode" 
    530         _doc_viewer = DocumentationWindow(self, self.ID_DOC, _TreeLocation, 
     546        if not self.batch_on: 
     547            _PageAnchor = "#simultaneous-fit-mode" 
     548            _doc_viewer = DocumentationWindow(self, self.ID_DOC, _TreeLocation, 
    531549                                          _PageAnchor, 
    532550                                          "Simultaneous/Constrained Fitting Help") 
     551        else: 
     552            _PageAnchor = "#combined-batch-fit-mode" 
     553            _doc_viewer = DocumentationWindow(self, self.ID_DOC, _TreeLocation, 
     554                                          _PageAnchor, 
     555                                          "Combined Batch Fit Help") 
    533556 
    534557    def set_manager(self, manager): 
  • src/sas/sasgui/plottools/plottables.py

    r45dffa69 r2d9526d  
    239239    def replace(self, plottable): 
    240240        """Replace an existing plottable from the graph""" 
    241         selected_color = None 
     241        # If the user has set a custom color, ensure the new plot is the same color 
     242        selected_color = plottable.custom_color 
    242243        selected_plottable = None 
    243244        for p in self.plottables.keys(): 
    244245            if plottable.id == p.id: 
    245246                selected_plottable = p 
    246                 selected_color = self.plottables[p] 
     247                if selected_color is None: 
     248                    selected_color = self.plottables[p] 
    247249                break 
    248         if  selected_plottable is not None and selected_color is not None: 
     250        if selected_plottable is not None and selected_color is not None: 
    249251            del self.plottables[selected_plottable] 
     252            plottable.custom_color = selected_color 
    250253            self.plottables[plottable] = selected_color 
    251254 
  • 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/fitpage.py

    red2276f r6a455cd3  
    12361236            wx.PostEvent(self.parent, new_event) 
    12371237            # update list of plugins if new plugin is available 
    1238             custom_model = CUSTOM_MODEL 
    12391238            mod_cat = self.categorybox.GetStringSelection() 
    1240             if mod_cat == custom_model: 
     1239            if mod_cat == CUSTOM_MODEL: 
     1240                temp_id = self.model.id 
    12411241                temp = self.parent.update_model_list() 
     1242                for v in self.parent.model_dictionary.values(): 
     1243                    if v.id == temp_id: 
     1244                        self.model = v() 
     1245                        break 
    12421246                if temp: 
    12431247                    self.model_list_box = temp 
  • src/sas/sasgui/perspectives/fitting/fitpanel.py

    r67b0a99 rc9ecd1b  
    9292            # state must be cloned 
    9393            state = page.get_state().clone() 
    94             if data is not None or page.model is not None: 
     94            # data_list only populated with real data 
     95            # Fake object in data from page.get_data() if model is selected 
     96            if len(page.data_list) is not 0 and page.model is not None: 
    9597                new_doc = self._manager.state_reader.write_toXML(data, 
    9698                                                                 state, 
    9799                                                                 batch_state) 
     100                # Fit #2 through #n are append to first fit 
    98101                if doc is not None and hasattr(doc, "firstChild"): 
    99                     child = new_doc.firstChild.firstChild 
    100                     doc.firstChild.appendChild(child) 
     102                    # Only append if properly formed new_doc 
     103                    if new_doc is not None and hasattr(new_doc, "firstChild"): 
     104                        child = new_doc.firstChild.firstChild 
     105                        doc.firstChild.appendChild(child) 
     106                # First fit defines the main document 
    101107                else: 
    102108                    doc = new_doc 
     
    395401                temp_data = page.get_data() 
    396402                if temp_data is not None and temp_data.id in data: 
    397                     self.SetSelection(pos) 
    398                     self.on_close_page(event=None) 
    399                     temp = self.GetSelection() 
    400                     self.DeletePage(temp) 
     403                    self.close_page_with_data(temp_data) 
    401404            if self.sim_page is not None: 
    402405                if len(self.sim_page.model_list) == 0: 
     
    404407                    self.SetSelection(pos) 
    405408                    self.on_close_page(event=None) 
    406                     temp = self.GetSelection() 
    407                     self.DeletePage(temp) 
     409                    self.DeletePage(pos) 
    408410                    self.sim_page = None 
    409411                    self.batch_on = False 
  • src/sas/sasgui/perspectives/fitting/models.py

    rb1c2011 rb682c6a  
    2020from sas.sasgui.guiframe.CategoryInstaller import CategoryInstaller 
    2121from sasmodels.sasview_model import load_custom_model, load_standard_models 
     22from sas.sasgui.perspectives.fitting.fitpage import CUSTOM_MODEL 
    2223 
    2324logger = logging.getLogger(__name__) 
     
    265266        temp = {} 
    266267        if self.is_changed(): 
    267             return  _find_models() 
     268            temp =  _find_models() 
     269            self.last_time_dir_modified = time.time() 
     270            return temp 
    268271        logger.info("plugin model : %s" % str(temp)) 
    269272        return temp 
     
    312315        if os.path.isdir(plugin_dir): 
    313316            temp = os.path.getmtime(plugin_dir) 
    314             if  self.last_time_dir_modified != temp: 
     317            if  self.last_time_dir_modified < temp: 
    315318                is_modified = True 
    316319                self.last_time_dir_modified = temp 
     
    323326        new models were added else return empty dictionary 
    324327        """ 
     328        self.plugins = [] 
    325329        new_plugins = self.findModels() 
    326         if len(new_plugins) > 0: 
    327             for name, plug in  new_plugins.iteritems(): 
    328                 if name not in self.stored_plugins.keys(): 
    329                     self.stored_plugins[name] = plug 
    330                     self.plugins.append(plug) 
    331                     self.model_dictionary[name] = plug 
    332             self.model_combobox.set_list("Plugin Models", self.plugins) 
     330        if new_plugins: 
     331            for name, plug in  new_plugins.items(): 
     332                self.stored_plugins[name] = plug 
     333                self.plugins.append(plug) 
     334                self.model_dictionary[name] = plug 
     335            self.model_combobox.set_list(CUSTOM_MODEL, self.plugins) 
    333336            return self.model_combobox.get_list() 
    334337        else: 
Note: See TracChangeset for help on using the changeset viewer.