Changeset 95eef00 in sasview for src/sas/sasgui


Ignore:
Timestamp:
Oct 7, 2016 4:05:57 PM (8 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, costrafo411, magnetic_scatt, release-4.1.1, release-4.1.2, release-4.2.2, ticket-1009, ticket-1094-headless, ticket-1242-2d-resolution, ticket-1243, ticket-1249, ticket885, unittest-saveload
Children:
b61bd57
Parents:
e6de6b8 (diff), 48b8f6d (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 wx_save_simfit

Location:
src/sas/sasgui
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • src/sas/sasgui/guiframe/gui_manager.py

    re6de6b8 r95eef00  
    13341334                    self._applications_menu_name = name 
    13351335 
     1336    def _on_marketplace_click(self, event): 
     1337        """ 
     1338            Click event for the help menu item linking to the Marketplace. 
     1339        """ 
     1340        import webbrowser 
     1341        webbrowser.open_new(config.marketplace_url) 
     1342 
    13361343    def _add_help_menu(self): 
    13371344        """ 
     
    13391346        tutorial PDF and documentation pages. 
    13401347        """ 
    1341         # Help menu 
    13421348        self._help_menu = wx.Menu() 
    1343         style = self.__gui_style & GUIFRAME.WELCOME_PANEL_ON 
    13441349 
    13451350        wx_id = wx.NewId() 
    13461351        self._help_menu.Append(wx_id, '&Documentation', '') 
    13471352        wx.EVT_MENU(self, wx_id, self._onSphinxDocs) 
    1348         self._help_menu.AppendSeparator() 
    13491353 
    13501354        if config._do_tutorial and (IS_WIN or sys.platform == 'darwin'): 
     
    13521356            self._help_menu.Append(wx_id, '&Tutorial', 'Software tutorial') 
    13531357            wx.EVT_MENU(self, wx_id, self._onTutorial) 
    1354             self._help_menu.AppendSeparator() 
    1355  
    13561358 
    13571359        if config._do_acknowledge: 
     
    13591361            self._help_menu.Append(wx_id, '&Acknowledge', 'Acknowledging SasView') 
    13601362            wx.EVT_MENU(self, wx_id, self._onAcknowledge) 
    1361             self._help_menu.AppendSeparator() 
    1362  
    13631363 
    13641364        if config._do_aboutbox: 
     
    13671367            self._help_menu.Append(wx_id, '&About', 'Software information') 
    13681368            wx.EVT_MENU(self, wx_id, self._onAbout) 
    1369             self._help_menu.AppendSeparator() 
    1370  
     1369 
     1370        if config.marketplace_url: 
     1371            wx_id = wx.NewId() 
     1372            self._help_menu.Append(wx_id, '&Model marketplace', '') 
     1373            wx.EVT_MENU(self, wx_id, self._on_marketplace_click) 
    13711374 
    13721375        # Checking for updates 
  • src/sas/sasgui/guiframe/media/data_formats_help.rst

    r280f929 r48b8f6d  
    1010============ 
    1111 
    12 SasView reads several different 1D (I(Q) vs Q), 2D SANS(I(Qx,Qy) vs (Qx,Qy)) 
    13 and SESANS (P(z) vs z) 
    14 data files. But please note that SasView does not at present load data where 
    15 the Q and I(Q) data are in separate files. 
     12SasView reads several different 1D SAS (*I(Q) vs Q*), 2D SAS(*I(Qx,Qy) vs (Qx,Qy)*) and 1D SESANS (*P(z) vs z*) data files. From SasView 4.1 onwards, a :ref:`File_Converter_Tool` allows some legacy formats to be converted into modern formats that SasView will read. 
    1613 
    17 1D Formats SANS 
    18 --------------- 
     141D SAS Formats 
     15-------------- 
    1916 
    20 SasView will read files with 2 to 4 columns of numbers in the following order:  
     17SasView will read ASCII ('text') files with 2 to 4 columns of numbers in the following order:  
    2118 
    22     Q, I(Q), (dI(Q), dQ(Q)) 
     19    *Q, I(Q), ( dI(Q), dQ(Q) )* 
    2320     
    24 where dQ(Q) is the instrumental resolution in Q and assumed to have originated  
     21where *dQ(Q)* is the instrumental resolution in *Q* and assumed to have originated  
    2522from pinhole geometry. 
    2623 
    2724Numbers can be separated by spaces or commas. 
    2825 
    29 SasView recognises the following file extensions: 
     26SasView recognises the following file extensions which are not case-sensitive: 
    3027 
    3128*  .TXT 
     
    3431*  .XML (in canSAS format v1.0 and 1.1) 
    3532 
    36 If using CSV output from, for example, a spreadsheet, ensure that it is not  
    37 using commas as delimiters for thousands. 
     33If using CSV output from, for example, a spreadsheet, ensure that it is not using commas as delimiters for thousands. 
     34 
     35The SasView :ref:`File_Converter_Tool` available in SasView 4.1 onwards can be used to convert data sets with separated *I(Q)* and *Q* files (for example, BSL/OTOKO, and some output from FIT2D and other SAXS-oriented software) into either the canSAS SASXML (XML) format or the NeXus NXcanSAS (HDF5) format. 
    3836 
    3937For a description of the CanSAS/SASXML format see: 
    4038http://www.cansas.org/formats/canSAS1d/1.1/doc/ 
    4139 
     40For a description of the ISIS 1D format see: 
     41http://www.isis.stfc.ac.uk/instruments/loq/software/colette-ascii-file-format-descriptions9808.pdf 
     42 
     43For a description of the NXcanSAS format see: 
     44http://cansas-org.github.io/NXcanSAS/classes/contributed_definitions/NXcanSAS.html 
     45 
     46All the above formats are written by the `Mantid Framework <http://www.mantidproject.org/>`_. 
     47 
    4248For a description of the NIST 1D format see: 
    4349http://danse.chem.utk.edu/trac/wiki/NCNROutput1D_IQ 
    4450 
    45 For a description of the ISIS 1D format see: 
    46 http://www.isis.stfc.ac.uk/instruments/loq/software/colette-ascii-file-format-descriptions9808.pdf 
     51For a description of the BSL/OTOKO format see:  
     52http://www.diamond.ac.uk/Beamlines/Soft-Condensed-Matter/small-angle/SAXS-Software/CCP13/BSL.html 
    4753 
    4854.. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 
    4955 
    50 2D Formats SANS 
    51 --------------- 
     562D SAS Formats 
     57-------------- 
    5258 
    53 SasView will only read files in the NIST 2D format with the extensions  
    54 .ASC or .DAT 
     59SasView will read ASCII ('text') files in the NIST 2D format (with the extensions .ASC or .DAT) or files in the NeXus NXcanSAS (HDF5) format (with the extension .H5). File extensions are not case-sensitive. Both of these formats are written by the `Mantid Framework <http://www.mantidproject.org/>`_. 
    5560 
    56 Most of the header lines can be removed except the last line, and only the  
    57 first three columns (Qx, Qy, and I(Qx,Qy)) are actually required. 
     61Most of the header lines in the NIST 2D format can actually be removed except the last line, and only the first three columns (*Qx, Qy,* and *I(Qx,Qy)*) are actually required. 
     62 
     63The SasView :ref:`File_Converter_Tool` available in SasView 4.1 onwards can be used to convert data sets in the 2D BSL/OTOKO format into the NeXus NXcanSAS (HDF5) format. 
    5864 
    5965For a description of the NIST 2D format see: 
    6066http://danse.chem.utk.edu/trac/wiki/NCNROutput1D_2DQxQy  
    6167 
    62 .. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 
     68For a description of the NXcanSAS format see:  
     69http://cansas-org.github.io/NXcanSAS/classes/contributed_definitions/NXcanSAS.html 
    6370 
    64 SESANS Format 
    65 ------------- 
    66  
    67 The current file extension is .ses or .sesans (not case sensitive). 
    68  
    69 The file format is to have a list of name-value pairs as a header at the top of the file, detailing general experimental parameters necessary for fitting and analyzing data. This list should contain all information necessary for the file to be 'portable' between users. 
    70  
    71 Following that is a 6 column list of instrument experimental variables: 
    72  
    73 - Spin echo length (z, in Angstroms) 
    74 - Spin echo length error (:math:`\Delta` z, in Angstroms) (experimental resolution) 
    75 - neutron wavelength (:math:`\lambda`, in Angstroms) (essential for ToF instruments) 
    76 - neutron wavelength error (:math:`\Delta \lambda`, in Angstroms) 
    77 - Normalized polarization (:math:`P/P_0`, unitless) 
    78 - Normalized polarization error (:math:`\Delta(P/P_0)`, unitless) (measurement error) 
     71For a description of the BSL/OTOKO format see: For a description of the BSL/OTOKO format see:  
     72http://www.diamond.ac.uk/Beamlines/Soft-Condensed-Matter/small-angle/SAXS-Software/CCP13/BSL.html 
    7973 
    8074 
    8175.. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 
    8276 
    83 .. note::  This help document was last changed by Wim Bouwman, 05Oct2016 
     771D SESANS Format 
     78---------------- 
     79 
     80SasView version 4.1 onwards will read ASCII ('text') files in a prototype SESANS standard format (with the extensions .SES or .SESANS). The file extensions are not case-sensitive. 
     81 
     82The file format has a list of name-value pairs at the top of the file which detail the general experimental parameters necessary for fitting and analyzing data. This list should contain all the information necessary for the file to be 'portable' between users. 
     83 
     84Following the header is a 6 column list of instrument experimental variables: 
     85 
     86- Spin echo length (z, in Angstroms) 
     87- Spin echo length error (:math:`\Delta`\ z, in Angstroms) (experimental resolution) 
     88- Neutron wavelength (:math:`\lambda`, in Angstroms) (essential for ToF instruments) 
     89- Neutron wavelength error (:math:`\Delta \lambda`, in Angstroms) 
     90- Normalized polarization (:math:`P/P_0`, unitless) 
     91- Normalized polarization error (:math:`\Delta(P/P_0)`, unitless) (measurement error) 
     92 
     93.. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 
     94 
     95.. note::  This help document was last changed by Steve King, 07Oct2016 
  • src/sas/sasgui/guiframe/data_panel.py

    re767897 r998ca90  
    890890 
    891891 
    892     def on_remove(self, event): 
     892    def on_remove(self, event, msg=""): 
    893893        """ 
    894894        Get a list of item checked and remove them from the treectrl 
    895895        Ask the parent to remove reference to this item 
    896896        """ 
    897         msg = "This operation will delete the data sets checked " 
    898         msg += "and all the dependents." 
     897        if msg == "": 
     898            msg = "This operation will delete the data sets checked " 
     899            msg += "and all the dependents." 
    899900        msg_box = wx.MessageDialog(None, msg, 'Warning', wx.OK|wx.CANCEL) 
    900901        if msg_box.ShowModal() != wx.ID_OK: 
    901             return 
     902            return True 
    902903 
    903904        data_to_remove, theory_to_remove, _ = self.set_data_helper() 
  • src/sas/sasgui/perspectives/fitting/fitpanel.py

    r05228b0 re6de6b8  
    1010 
    1111from sas.sasgui.guiframe.panel_base import PanelBase 
    12 from sas.sasgui.guiframe.events import PanelOnFocusEvent 
    13 from sas.sasgui.guiframe.events import StatusEvent 
     12from sas.sasgui.guiframe.events import PanelOnFocusEvent, StatusEvent 
    1413from sas.sasgui.guiframe.dataFitting import check_data_validity 
     14from sas.sasgui.perspectives.fitting.simfitpage import SimultaneousFitPage 
    1515 
    1616import basepage 
     
    1818_BOX_WIDTH = 80 
    1919 
     20 
    2021class FitPanel(nb, PanelBase): 
    2122    """ 
     
    2627 
    2728    """ 
    28     ## Internal name for the AUI manager 
     29    # Internal name for the AUI manager 
    2930    window_name = "Fit panel" 
    30     ## Title to appear on top of the window 
     31    # Title to appear on top of the window 
    3132    window_caption = "Fit Panel " 
    3233    CENTER_PANE = True 
     
    4041                    wx.CLIP_CHILDREN) 
    4142        PanelBase.__init__(self, parent) 
    42         #self.SetWindowStyleFlag(style=nb.FNB_FANCY_TABS) 
     43        # self.SetWindowStyleFlag(style=nb.FNB_FANCY_TABS) 
    4344        self._manager = manager 
    4445        self.parent = parent 
    4546        self.event_owner = None 
    46         #dictionary of miodel {model class name, model class} 
     47        # dictionary of miodel {model class name, model class} 
    4748        self.menu_mng = models.ModelManager() 
    4849        self.model_list_box = self.menu_mng.get_model_list() 
    49         #pageClosedEvent = nb.EVT_FLATNOTEBOOK_PAGE_CLOSING 
     50        # pageClosedEvent = nb.EVT_FLATNOTEBOOK_PAGE_CLOSING 
    5051        self.model_dictionary = self.menu_mng.get_model_dictionary() 
    5152        self.pageClosedEvent = wx.aui.EVT_AUINOTEBOOK_PAGE_CLOSE 
    5253 
    5354        self.Bind(self.pageClosedEvent, self.on_close_page) 
    54         ## save the title of the last page tab added 
     55        # save the title of the last page tab added 
    5556        self.fit_page_name = {} 
    56         ## list of existing fit page 
     57        # list of existing fit page 
    5758        self.opened_pages = {} 
    58         #index of fit page 
     59        # index of fit page 
    5960        self.fit_page_index = 0 
    60         #index of batch page 
     61        # index of batch page 
    6162        self.batch_page_index = 0 
    62         #page of simultaneous fit 
     63        # page of simultaneous fit 
    6364        self.sim_page = None 
    6465        self.batch_page = None 
    65         ## get the state of a page 
     66        # get the state of a page 
    6667        self.Bind(basepage.EVT_PAGE_INFO, self._onGetstate) 
    6768        self.Bind(basepage.EVT_PREVIOUS_STATE, self._onUndo) 
     
    8081        """ 
    8182        return an xml node containing state of the panel 
    82          that guiframe can write to file 
    83         """ 
    84         msg = "" 
     83        that guiframe can write to file 
     84        """ 
     85        # Iterate through all pages and check for batch fitting 
     86        batch_state = None 
     87        if self.sim_page is not None: 
     88            batch_state = self.sim_page.set_state() 
     89 
    8590        for uid, page in self.opened_pages.iteritems(): 
    86             if page.batch_on: 
    87                 pos = self.GetPageIndex(page) 
    88                 if pos != -1 and page not in [self.sim_page, self.batch_page]: 
    89                     msg += "%s .\n" % str(self.GetPageText(pos)) 
    90             else: 
    91                 data = page.get_data() 
    92                 # state must be cloned 
    93                 state = page.get_state().clone() 
    94                 if data is not None and page.model is not None: 
    95                     new_doc = self._manager.state_reader.write_toXML(data, 
    96                                                                      state) 
    97                     if doc != None and hasattr(doc, "firstChild"): 
    98                         child = new_doc.firstChild.firstChild 
    99                         doc.firstChild.appendChild(child) 
    100                     else: 
    101                         doc = new_doc 
    102         if msg.strip() != "": 
    103             temp = "Save Project is not supported for Batch page.\n" 
    104             temp += "The following pages will not be save:\n" 
    105             message = temp + msg 
    106             wx.PostEvent(self._manager.parent, StatusEvent(status=message, 
    107                                                             info="warning")) 
     91            data = page.get_data() 
     92            # state must be cloned 
     93            state = page.get_state().clone() 
     94            if data is not None or page.model is not None: 
     95                new_doc = self._manager.state_reader.write_toXML(data, 
     96                                                                 state, 
     97                                                                 batch_state) 
     98                if doc is not None and hasattr(doc, "firstChild"): 
     99                    child = new_doc.firstChild.firstChild 
     100                    doc.firstChild.appendChild(child) 
     101                else: 
     102                    doc = new_doc 
     103 
    108104        return doc 
    109105 
     
    179175    def get_state(self): 
    180176        """ 
    181          return the state of the current selected page 
     177        return the state of the current selected page 
    182178        """ 
    183179        pos = self.GetSelection() 
     
    191187        """ 
    192188 
    193         #get number of pages 
     189        # get number of pages 
    194190        nop = self.GetPageCount() 
    195         #use while-loop, for-loop will not do the job well. 
     191        # use while-loop, for-loop will not do the job well. 
    196192        while (nop > 0): 
    197             #delete the first page until no page exists 
     193            # delete the first page until no page exists 
    198194            page = self.GetPage(0) 
    199195            if self._manager.parent.panel_on_focus == page: 
     
    201197            self._close_helper(selected_page=page) 
    202198            self.DeletePage(0) 
    203             nop = nop - 1 
    204  
    205         ## save the title of the last page tab added 
     199            nop = self.GetPageCount() 
     200        # Clear list of names 
    206201        self.fit_page_name = {} 
    207         ## list of existing fit page 
     202        # Clear list of opened pages 
    208203        self.opened_pages = {} 
     204        self.fit_page_index = 0 
     205        self.batch_page_index = 0 
    209206 
    210207    def set_state(self, state): 
     
    215212        if state is not None: 
    216213            for uid, panel in self.opened_pages.iteritems(): 
    217                 #Don't return any panel is the exact same page is created 
     214                # Don't return any panel is the exact same page is created 
    218215                if uid == panel.uid and panel.data == state.data: 
    219216                    # the page is still opened 
     
    223220            if not page_is_opened: 
    224221                if state.data.__class__.__name__ != 'list': 
    225                     #To support older state file format 
     222                    # To support older state file format 
    226223                    list_data = [state.data] 
    227224                else: 
    228                     #Todo: need new file format for the list 
     225                    # Todo: need new file format for the list 
    229226                    list_data = state.data 
    230227                panel = self._manager.add_fit_page(data=list_data) 
     
    241238        Clear and close all panels, used by guimanager 
    242239        """ 
    243  
    244         #close all panels only when svs file opened 
     240        # close all panels only when svs file opened 
    245241        self.close_all() 
    246242        self._manager.mypanels = [] 
     243        self.sim_page = None 
     244        self.batch_page = None 
    247245 
    248246    def on_close_page(self, event=None): 
     
    253251        selected_page = self.GetPage(self.GetSelection()) 
    254252        if nbr_page == 1: 
    255             if selected_page.get_data() == None: 
     253            if selected_page.get_data() is not None: 
    256254                if event is not None: 
    257255                    event.Veto() 
     
    271269 
    272270                if data is None: 
    273                     #the fitpanel exists and only the initial fit page is open 
    274                     #with no selected data 
     271                    # the fitpanel exists and only the initial fit page is open 
     272                    # with no selected data 
    275273                    return 
    276274                if data.id == deleted_data.id: 
     
    284282 
    285283        :param manager: instance of plugin fitting 
    286  
    287284        """ 
    288285        self._manager = manager 
     
    333330        else: 
    334331            self.batch_page = SimultaneousFitPage(self, batch_on=True, 
    335                                                    page_finder=page_finder) 
     332                                                  page_finder=page_finder) 
    336333            self.batch_page.window_caption = caption 
    337334            self.batch_page.window_name = caption 
     
    346343        add an empty page 
    347344        """ 
    348         """ 
    349345        if self.batch_on: 
    350346            from batchfitpage import BatchFitPage 
    351             panel = BatchFitPage(parent=self) 
    352             #Increment index of batch page 
    353             self.batch_page_index += 1 
    354             index = self.batch_page_index 
    355         else: 
    356         """ 
    357         from fitpage import FitPage 
    358         from batchfitpage import BatchFitPage 
    359         if self.batch_on: 
    360347            panel = BatchFitPage(parent=self) 
    361348            self.batch_page_index += 1 
     
    363350            panel.set_index_model(self.batch_page_index) 
    364351        else: 
    365             #Increment index of fit page 
     352            # Increment index of fit page 
     353            from fitpage import FitPage 
    366354            panel = FitPage(parent=self) 
    367355            self.fit_page_index += 1 
     
    441429        page = None 
    442430        for p in self.opened_pages.values(): 
    443             #check if there is an empty page to fill up 
     431            # check if there is an empty page to fill up 
    444432            if not check_data_validity(p.get_data()) and p.batch_on: 
    445433 
    446                 #make sure data get placed in 1D empty tab if data is 1D 
    447                 #else data get place on 2D tab empty tab 
     434                # make sure data get placed in 1D empty tab if data is 1D 
     435                # else data get place on 2D tab empty tab 
    448436                enable2D = p.get_view_mode() 
    449437                if (data.__class__.__name__ == "Data2D" and enable2D)\ 
     
    458446                data_type = dlg.get_data() 
    459447                dlg.Destroy() 
    460                 if page  is None: 
     448                if page is None: 
    461449                    page = self.add_empty_page() 
    462450                if data_type == 1: 
    463                     #user has selected only data1D 
     451                    # user has selected only data1D 
    464452                    page.fill_data_combobox(data_1d_list) 
    465453                elif data_type == 2: 
    466454                    page.fill_data_combobox(data_2d_list) 
    467455            else: 
    468                 #the batch analysis is canceled 
     456                # the batch analysis is canceled 
    469457                dlg.Destroy() 
    470458                return None 
     
    503491            try: 
    504492                data = data_list[0] 
    505             except: 
     493            except Exception: 
    506494                # for 'fitv' files 
    507495                data_list = [data] 
     
    511499                return None 
    512500        for page in self.opened_pages.values(): 
    513             #check if the selected data existing in the fitpanel 
     501            # check if the selected data existing in the fitpanel 
    514502            pos = self.GetPageIndex(page) 
    515503            if not check_data_validity(page.get_data()) and not page.batch_on: 
    516                 #make sure data get placed in 1D empty tab if data is 1D 
    517                 #else data get place on 2D tab empty tab 
     504                # make sure data get placed in 1D empty tab if data is 1D 
     505                # else data get place on 2D tab empty tab 
    518506                enable2D = page.get_view_mode() 
    519507                if (data.__class__.__name__ == "Data2D" and enable2D)\ 
    520                 or (data.__class__.__name__ == "Data1D" and not enable2D): 
     508                   or (data.__class__.__name__ == "Data1D" and not enable2D): 
    521509                    page.batch_on = self.batch_on 
    522510                    page._set_save_flag(not page.batch_on) 
    523511                    page.fill_data_combobox(data_list) 
    524                     #caption = "FitPage" + str(self.fit_page_index) 
     512                    # caption = "FitPage" + str(self.fit_page_index) 
    525513                    self.SetPageText(pos, page.window_caption) 
    526514                    self.SetSelection(pos) 
    527515                    return page 
    528         #create new page and add data 
     516        # create new page and add data 
    529517        page = self.add_empty_page() 
    530518        pos = self.GetPageIndex(page) 
     
    574562        Delete the given page from the notebook 
    575563        """ 
    576         #remove hint page 
    577         #if selected_page == self.hint_page: 
     564        # remove hint page 
     565        # if selected_page == self.hint_page: 
    578566        #    return 
    579         ## removing sim_page 
     567        # removing sim_page 
    580568        if selected_page == self.sim_page: 
    581569            self._manager.sim_page = None 
     
    584572            self._manager.batch_page = None 
    585573            return 
    586         """ 
    587         # The below is not working when delete #5 and still have #6. 
    588         if selected_page.__class__.__name__ == "FitPage": 
    589             self.fit_page_index -= 1 
    590         else: 
    591             self.batch_page_index -= 1 
    592         """ 
    593         ## closing other pages 
     574        # closing other pages 
    594575        state = selected_page.createMemento() 
    595576        page_finder = self._manager.get_page_finder() 
    596         ## removing fit page 
     577        # removing fit page 
    597578        data = selected_page.get_data() 
    598         #Don' t remove plot for 2D 
     579        # Don' t remove plot for 2D 
    599580        flag = True 
    600581        if data.__class__.__name__ == 'Data2D': 
    601582            flag = False 
    602583        if selected_page in page_finder: 
    603             #Delete the name of the page into the list of open page 
     584            # Delete the name of the page into the list of open page 
    604585            for uid, list in self.opened_pages.iteritems(): 
    605                 #Don't return any panel is the exact same page is created 
    606  
     586                # Don't return any panel is the exact same page is created 
    607587                if flag and selected_page.uid == uid: 
    608588                    self._manager.remove_plot(uid, theory=False) 
     
    610590            del page_finder[selected_page] 
    611591 
    612         #Delete the name of the page into the list of open page 
     592        # Delete the name of the page into the list of open page 
    613593        for uid, list in self.opened_pages.iteritems(): 
    614             #Don't return any panel is the exact same page is created 
     594            # Don't return any panel is the exact same page is created 
    615595            if selected_page.uid == uid: 
    616596                del self.opened_pages[selected_page.uid] 
    617597                break 
    618         ##remove the check box link to the model name of this page (selected_page) 
     598        # remove the check box link to the model name of the selected_page 
    619599        try: 
    620600            self.sim_page.draw_page() 
    621601        except: 
    622             ## that page is already deleted no need to remove check box on 
    623             ##non existing page 
     602            # that page is already deleted no need to remove check box on 
     603            # non existing page 
    624604            pass 
    625605        try: 
    626606            self.batch_page.draw_page() 
    627607        except: 
    628             ## that page is already deleted no need to remove check box on 
    629             ##non existing page 
     608            # that page is already deleted no need to remove check box on 
     609            # non existing page 
    630610            pass 
  • src/sas/sasgui/perspectives/fitting/fitting.py

    r286c757 rff3f5821  
    593593        : param datainfo: data 
    594594        """ 
    595         #state = self.state_reader.get_state() 
    596         if state != None: 
     595        from pagestate import PageState 
     596        from simfitpage import SimFitPageState 
     597        if isinstance(state, PageState): 
    597598            state = state.clone() 
    598             # store fitting state in temp_state 
    599599            self.temp_state.append(state) 
     600        elif isinstance(state, SimFitPageState): 
     601            state.load_from_save_state(self) 
    600602        else: 
    601603            self.temp_state = [] 
  • src/sas/sasgui/perspectives/fitting/pagestate.py

    r6c382da re6de6b8  
    22    Class that holds a fit page state 
    33""" 
    4 #TODO: Refactor code so we don't need to use getattr/setattr 
     4# TODO: Refactor code so we don't need to use getattr/setattr 
    55################################################################################ 
    6 #This software was developed by the University of Tennessee as part of the 
    7 #Distributed Data Analysis of Neutron Scattering Experiments (DANSE) 
    8 #project funded by the US National Science Foundation. 
     6# This software was developed by the University of Tennessee as part of the 
     7# Distributed Data Analysis of Neutron Scattering Experiments (DANSE) 
     8# project funded by the US National Science Foundation. 
    99# 
    10 #See the license text in license.txt 
     10# See the license text in license.txt 
    1111# 
    12 #copyright 2009, University of Tennessee 
     12# copyright 2009, University of Tennessee 
    1313################################################################################ 
    1414import time 
     
    3030from sas.sascalc.dataloader.readers.cansas_reader import Reader as CansasReader 
    3131from sas.sascalc.dataloader.readers.cansas_reader import get_content, write_node 
    32 from sas.sascalc.dataloader.data_info import Data2D 
    33 from sas.sascalc.dataloader.data_info import Collimation 
    34 from sas.sascalc.dataloader.data_info import Detector 
    35 from sas.sascalc.dataloader.data_info import Process 
    36 from sas.sascalc.dataloader.data_info import Aperture 
    37 #Information to read/write state as xml 
     32from sas.sascalc.dataloader.data_info import Data2D, Collimation, Detector 
     33from sas.sascalc.dataloader.data_info import Process, Aperture 
     34# Information to read/write state as xml 
    3835FITTING_NODE_NAME = 'fitting_plug_in' 
    3936CANSAS_NS = "cansas1d/1.0" 
     
    123120            try: 
    124121                return node.get(item[0]).strip() == "True" 
    125  
    126122            except: 
    127123                return None 
     
    146142        """ 
    147143        self.file = None 
    148         #Time of state creation 
     144        # Time of state creation 
    149145        self.timestamp = time.time() 
    150         ## Data member to store the dispersion object created 
     146        # Data member to store the dispersion object created 
    151147        self._disp_obj_dict = {} 
    152         #------------------------ 
    153         #Data used for fitting 
     148        # ------------------------ 
     149        # Data used for fitting 
    154150        self.data = data 
    155151        # model data 
    156152        self.theory_data = None 
    157         #Is 2D 
     153        # Is 2D 
    158154        self.is_2D = False 
    159155        self.images = None 
    160156 
    161         #save additional information on data that dataloader.reader does not read 
     157        # save additional information on data that dataloader.reader 
     158        # does not read 
    162159        self.is_data = None 
    163160        self.data_name = "" 
     
    172169            self.data_group_id = self.data.group_id 
    173170 
    174         ## reset True change the state of exsiting button 
     171        # reset True change the state of existing button 
    175172        self.reset = False 
    176173 
     
    180177        self.model = model 
    181178        self.m_name = None 
    182         #list of process done to model 
     179        # list of process done to model 
    183180        self.process = [] 
    184         #fit page manager 
     181        # fit page manager 
    185182        self.manager = None 
    186         #Store the parent of this panel parent 
     183        # Store the parent of this panel parent 
    187184        # For this application fitpanel is the parent 
    188185        self.parent = parent 
    189186        # Event_owner is the owner of model event 
    190187        self.event_owner = None 
    191         ##page name 
     188        # page name 
    192189        self.page_name = "" 
    193190        # Contains link between model, all its parameters, and panel organization 
     
    196193        self.str_parameters = [] 
    197194        # Contains list of parameters that cannot be fitted and reference to 
    198         #panel objects 
     195        # panel objects 
    199196        self.fixed_param = [] 
    200197        # Contains list of parameters with dispersity and reference to 
    201         #panel objects 
     198        # panel objects 
    202199        self.fittable_param = [] 
    203         ## orientation parameters 
     200        # orientation parameters 
    204201        self.orientation_params = [] 
    205         ## orientation parameters for gaussian dispersity 
     202        # orientation parameters for gaussian dispersity 
    206203        self.orientation_params_disp = [] 
    207         ## smearer info 
     204        # smearer info 
    208205        self.smearer = None 
    209206        self.smear_type = None 
     
    214211        self.dxl = None 
    215212        self.dxw = None 
    216         #list of dispersion parameters 
     213        # list of dispersion parameters 
    217214        self.disp_list = [] 
    218215        if self.model is not None: 
     
    223220        self.weights = {} 
    224221 
    225         #contains link between a model and selected parameters to fit 
     222        # contains link between a model and selected parameters to fit 
    226223        self.param_toFit = [] 
    227         ##dictionary of model type and model class 
     224        # dictionary of model type and model class 
    228225        self.model_list_box = None 
    229         ## save the state of the context menu 
     226        # save the state of the context menu 
    230227        self.saved_states = {} 
    231         ## save selection of combobox 
     228        # save selection of combobox 
    232229        self.formfactorcombobox = None 
    233230        self.categorycombobox = None 
    234231        self.structurecombobox = None 
    235232 
    236         ## radio box to select type of model 
    237         #self.shape_rbutton = False 
    238         #self.shape_indep_rbutton = False 
    239         #self.struct_rbutton = False 
    240         #self.plugin_rbutton = False 
    241         ## the indice of the current selection 
     233        # radio box to select type of model 
     234        # self.shape_rbutton = False 
     235        # self.shape_indep_rbutton = False 
     236        # self.struct_rbutton = False 
     237        # self.plugin_rbutton = False 
     238        # the indice of the current selection 
    242239        self.disp_box = 0 
    243         ## Qrange 
    244         ## Q range 
     240        # Qrange 
     241        # Q range 
    245242        self.qmin = 0.001 
    246243        self.qmax = 0.1 
    247         #reset data range 
     244        # reset data range 
    248245        self.qmax_x = None 
    249246        self.qmin_x = None 
     
    253250        self.multi_factor = None 
    254251        self.magnetic_on = False 
    255         ## enable smearering state 
     252        # enable smearering state 
    256253        self.enable_smearer = False 
    257254        self.disable_smearer = True 
     
    263260        self.dI_sqrdata = False 
    264261        self.dI_idata = False 
    265         ## disperity selection 
     262        # disperity selection 
    266263        self.enable_disp = False 
    267264        self.disable_disp = True 
    268265 
    269         ## state of selected all check button 
     266        # state of selected all check button 
    270267        self.cb1 = False 
    271         ## store value of chisqr 
     268        # store value of chisqr 
    272269        self.tcChi = None 
    273270 
     
    293290        obj.structurecombobox = self.structurecombobox 
    294291 
    295         #obj.shape_rbutton = self.shape_rbutton 
    296         #obj.shape_indep_rbutton = self.shape_indep_rbutton 
    297         #obj.struct_rbutton = self.struct_rbutton 
    298         #obj.plugin_rbutton = self.plugin_rbutton 
     292        # obj.shape_rbutton = self.shape_rbutton 
     293        # obj.shape_indep_rbutton = self.shape_indep_rbutton 
     294        # obj.struct_rbutton = self.struct_rbutton 
     295        # obj.plugin_rbutton = self.plugin_rbutton 
    299296 
    300297        obj.manager = self.manager 
     
    381378 
    382379        rep += "State created: %s\n" % time_str 
    383         rep += "State form factor combobox selection: %s\n" % self.formfactorcombobox 
    384         rep += "State structure factor combobox selection: %s\n" % self.structurecombobox 
     380        rep += "State form factor combobox selection: %s\n" % \ 
     381               self.formfactorcombobox 
     382        rep += "State structure factor combobox selection: %s\n" % \ 
     383               self.structurecombobox 
    385384        rep += "is data : %s\n" % self.is_data 
    386385        rep += "data's name : %s\n" % self.data_name 
    387386        rep += "data's id : %s\n" % self.data_id 
    388         if self.model != None: 
     387        if self.model is not None: 
    389388            m_name = self.model.__class__.__name__ 
    390389            if m_name == 'Model': 
     
    397396        rep += "model type (Category) selected: %s\n" % self.categorycombobox 
    398397        rep += "data : %s\n" % str(self.data) 
    399         rep += "Plotting Range: min: %s, max: %s, steps: %s\n" % (str(self.qmin), 
    400                                                                   str(self.qmax), str(self.npts)) 
     398        rep += "Plotting Range: min: %s, max: %s, steps: %s\n" % \ 
     399               (str(self.qmin),str(self.qmax), str(self.npts)) 
    401400        rep += "Dispersion selection : %s\n" % str(self.disp_box) 
    402401        rep += "Smearing enable : %s\n" % str(self.enable_smearer) 
     
    414413 
    415414        rep += "2D enable : %s\n" % str(self.enable2D) 
    416         rep += "All parameters checkbox selected: %s\n" % (self.cb1) 
     415        rep += "All parameters checkbox selected: %s\n" % str(self.cb1) 
    417416        rep += "Value of Chisqr : %s\n" % str(self.tcChi) 
    418417        rep += "Smear object : %s\n" % str(self.smearer) 
    419         rep += "Smear type : %s\n" % (self.smear_type) 
     418        rep += "Smear type : %s\n" % str(self.smear_type) 
    420419        rep += "dq_l  : %s\n" % self.dq_l 
    421420        rep += "dq_r  : %s\n" % self.dq_r 
     
    434433            if not self.is_2D: 
    435434                for item in self.parameters: 
    436                     if not item in self.orientation_params: 
     435                    if item not in self.orientation_params: 
    437436                        temp_parameters.append(item) 
    438437                for item in self.fittable_param: 
    439                     if not item in self.orientation_params_disp: 
     438                    if item not in self.orientation_params_disp: 
    440439                        temp_fittable_param.append(item) 
    441440            else: 
     
    443442                temp_fittable_param = self.fittable_param 
    444443 
    445             rep += "number parameters(self.parameters): %s\n" % len(temp_parameters) 
     444            rep += "number parameters(self.parameters): %s\n" % \ 
     445                   len(temp_parameters) 
    446446            rep = self._repr_helper(list=temp_parameters, rep=rep) 
    447             rep += "number str_parameters(self.str_parameters): %s\n" % len(self.str_parameters) 
     447            rep += "number str_parameters(self.str_parameters): %s\n" % \ 
     448                   len(self.str_parameters) 
    448449            rep = self._repr_helper(list=self.str_parameters, rep=rep) 
    449             rep += "number fittable_param(self.fittable_param): %s\n" % len(temp_fittable_param) 
     450            rep += "number fittable_param(self.fittable_param): %s\n" % \ 
     451                   len(temp_fittable_param) 
    450452            rep = self._repr_helper(list=temp_fittable_param, rep=rep) 
    451453        return rep 
     
    551553                    paramval_string += CENTRE % param + "\n" 
    552554 
    553         text_string = "\n\n\n%s\n\n%s\n%s\n%s\n\n%s" % (title, file, q_name, chi2, paramval) 
     555        text_string = "\n\n\n%s\n\n%s\n%s\n%s\n\n%s" % \ 
     556                      (title, file, q_name, chi2, paramval) 
    554557 
    555558        title_name = self._check_html_format(title_name) 
     
    632635            element.appendChild(sub_element) 
    633636 
    634     def toXML(self, file="fitting_state.fitv", doc=None, entry_node=None): 
    635         """ 
    636         Writes the state of the InversionControl panel to file, as XML. 
     637    def toXML(self, file="fitting_state.fitv", doc=None, 
     638              entry_node=None, batch_fit_state=None): 
     639        """ 
     640        Writes the state of the fit panel to file, as XML. 
    637641 
    638642        Compatible with standalone writing, or appending to an 
    639         already existing XML document. In that case, the XML document 
    640         is required. An optional entry node in the XML document may also be given. 
     643        already existing XML document. In that case, the XML document is 
     644        required. An optional entry node in the XML document may also be given. 
    641645 
    642646        :param file: file to write to 
    643647        :param doc: XML document object [optional] 
    644         :param entry_node: XML node within the XML document at which we will append the data [optional] 
    645  
     648        :param entry_node: XML node within the XML document at which we 
     649                           will append the data [optional] 
    646650        """ 
    647651        from xml.dom.minidom import getDOMImplementation 
     
    691695        element.setAttributeNode(attr) 
    692696        top_element.appendChild(element) 
     697 
    693698        # Inputs 
    694699        inputs = newdoc.createElement("Attributes") 
     
    741746        for item in LIST_OF_STATE_PARAMETERS: 
    742747            element = newdoc.createElement(item[0]) 
    743             self._toXML_helper(thelist=getattr(self, item[1]), element=element, newdoc=newdoc) 
     748            self._toXML_helper(thelist=getattr(self, item[1]), 
     749                               element=element, newdoc=newdoc) 
    744750            inputs.appendChild(element) 
     751 
     752        # Combined and Simultaneous Fit Parameters 
     753        if batch_fit_state is not None: 
     754            batch_combo = newdoc.createElement('simultaneous_fit') 
     755            top_element.appendChild(batch_combo) 
     756 
     757            # Simultaneous Fit Number For Linking Later 
     758            element = newdoc.createElement('sim_fit_number') 
     759            element.setAttribute('fit_number', str(batch_fit_state.fit_page_no)) 
     760            batch_combo.appendChild(element) 
     761 
     762            # Save constraints 
     763            constraints = newdoc.createElement('constraints') 
     764            batch_combo.appendChild(constraints) 
     765            for constraint in batch_fit_state.constraints_list: 
     766                if constraint.model_cbox.GetValue() != "": 
     767                    # model_cbox, param_cbox, egal_txt, constraint, btRemove, sizer 
     768                    doc_cons = newdoc.createElement('constraint') 
     769                    doc_cons.setAttribute('model_cbox', 
     770                                          str(constraint.model_cbox.GetValue())) 
     771                    doc_cons.setAttribute('param_cbox', 
     772                                          str(constraint.param_cbox.GetValue())) 
     773                    doc_cons.setAttribute('egal_txt', 
     774                                          str(constraint.egal_txt.GetLabel())) 
     775                    doc_cons.setAttribute('constraint', 
     776                                          str(constraint.constraint.GetValue())) 
     777                    constraints.appendChild(doc_cons) 
     778 
     779            # Save all models 
     780            models = newdoc.createElement('model_list') 
     781            batch_combo.appendChild(models) 
     782            for model in batch_fit_state.model_list: 
     783                doc_model = newdoc.createElement('model_list_item') 
     784                doc_model.setAttribute('checked', str(model[0].GetValue())) 
     785                keys = model[1].keys() 
     786                doc_model.setAttribute('name', str(keys[0])) 
     787                values = model[1].get(keys[0]) 
     788                doc_model.setAttribute('fit_number', str(model[2])) 
     789                doc_model.setAttribute('fit_page_source', str(model[3])) 
     790                doc_model.setAttribute('model_name', str(values.model.id)) 
     791                models.appendChild(doc_model) 
     792 
     793            # Select All Checkbox 
     794            element = newdoc.createElement('select_all') 
     795            if batch_fit_state.select_all: 
     796                element.setAttribute('checked', 'True') 
     797            else: 
     798                element.setAttribute('checked', 'False') 
     799            batch_combo.appendChild(element) 
    745800 
    746801        # Save the file 
     
    809864        :param file: .fitv file 
    810865        :param node: node of a XML document to read from 
    811  
    812866        """ 
    813867        if file is not None: 
     
    816870            raise RuntimeError, msg 
    817871 
    818         if node.get('version')and node.get('version') == '1.0': 
     872        if node.get('version') and node.get('version') == '1.0': 
    819873 
    820874            # Get file name 
     
    862916                                value = cls.type 
    863917                            except Exception: 
    864                                 logging.error("unable to load distribution %r for %s" 
    865                                               % (value, parameter)) 
     918                                base = "unable to load distribution %r for %s" 
     919                                logging.error(base % (value, parameter)) 
    866920                                continue 
    867921                        _disp_obj_dict = getattr(self, varname) 
     
    9601014        self.cansas = cansas 
    9611015        self.state = None 
     1016        # batch fitting params for saving 
     1017        self.batchfit_params = [] 
    9621018 
    9631019    def get_state(self): 
     
    9841040            raise RuntimeError, "The cansas writer expects a Data2D instance" 
    9851041 
     1042        title = "cansas1d/%s" % self.version 
     1043        title += "http://svn.smallangles.net/svn/canSAS/1dwg/trunk/cansas1d.xsd" 
    9861044        doc = xml.dom.minidom.Document() 
    9871045        main_node = doc.createElement("SASroot") 
    9881046        main_node.setAttribute("version", self.version) 
    9891047        main_node.setAttribute("xmlns", "cansas1d/%s" % self.version) 
    990         main_node.setAttribute("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance") 
    991         main_node.setAttribute("xsi:schemaLocation", 
    992                                "cansas1d/%s http://svn.smallangles.net/svn/canSAS/1dwg/trunk/cansas1d.xsd" % self.version) 
     1048        main_node.setAttribute("xmlns:xsi", 
     1049                               "http://www.w3.org/2001/XMLSchema-instance") 
     1050        main_node.setAttribute("xsi:schemaLocation", title) 
    9931051 
    9941052        doc.appendChild(main_node) 
     
    9991057        write_node(doc, entry_node, "Title", datainfo.title) 
    10001058        if datainfo is not None: 
    1001             write_node(doc, entry_node, "data_class", datainfo.__class__.__name__) 
     1059            write_node(doc, entry_node, "data_class", 
     1060                       datainfo.__class__.__name__) 
    10021061        for item in datainfo.run: 
    10031062            runname = {} 
    1004             if datainfo.run_name.has_key(item) and len(str(datainfo.run_name[item])) > 1: 
     1063            if datainfo.run_name.has_key(item) and \ 
     1064                            len(str(datainfo.run_name[item])) > 1: 
    10051065                runname = {'name': datainfo.run_name[item]} 
    10061066            write_node(doc, entry_node, "Run", item, runname) 
     
    12191279 
    12201280        :param entry: XML node to read from 
    1221  
    12221281        :return: PageState object 
    12231282        """ 
     
    12281287            nodes = entry.xpath('ns:%s' % FITTING_NODE_NAME, 
    12291288                                namespaces={'ns': CANSAS_NS}) 
    1230             if nodes != []: 
     1289            if nodes: 
    12311290                # Create an empty state 
    12321291                state = PageState() 
     
    12381297 
    12391298        return state 
     1299 
     1300    def _parse_simfit_state(self, entry): 
     1301        """ 
     1302        Parses the saved data for a simultaneous fit 
     1303        :param entry: XML object to read from 
     1304        :return: XML object for a simultaneous fit or None 
     1305        """ 
     1306        nodes = entry.xpath('ns:%s' % FITTING_NODE_NAME, 
     1307                            namespaces={'ns': CANSAS_NS}) 
     1308        if nodes: 
     1309            simfitstate = nodes[0].xpath('ns:simultaneous_fit', 
     1310                                         namespaces={'ns': CANSAS_NS}) 
     1311            if simfitstate: 
     1312                from simfitpage import SimFitPageState 
     1313                sim_fit_state = SimFitPageState() 
     1314                simfitstate_0 = simfitstate[0] 
     1315                all = simfitstate_0.xpath('ns:select_all', 
     1316                                        namespaces={'ns': CANSAS_NS}) 
     1317                atts = all[0].attrib 
     1318                checked = atts.get('checked') 
     1319                sim_fit_state.select_all = bool(checked) 
     1320                model_list = simfitstate_0.xpath('ns:model_list', 
     1321                                               namespaces={'ns': CANSAS_NS}) 
     1322                model_list_items = model_list[0].xpath('ns:model_list_item', 
     1323                                                   namespaces={'ns': CANSAS_NS}) 
     1324                for model in model_list_items: 
     1325                    attrs = model.attrib 
     1326                    sim_fit_state.model_list.append(attrs) 
     1327 
     1328                constraints = simfitstate_0.xpath('ns:constraints', 
     1329                                                namespaces={'ns': CANSAS_NS}) 
     1330                constraint_list = constraints[0].xpath('ns:constraint', 
     1331                                               namespaces={'ns': CANSAS_NS}) 
     1332                for constraint in constraint_list: 
     1333                    attrs = constraint.attrib 
     1334                    sim_fit_state.constraints_list.append(attrs) 
     1335 
     1336                return sim_fit_state 
     1337            else: 
     1338                return None 
    12401339 
    12411340    def _parse_save_state_entry(self, dom): 
     
    12981397                        data_info.notes.append(note_value) 
    12991398            except Exception: 
    1300                 err_mess = "cansas_reader.read: error processing entry notes\n  %s" % sys.exc_value 
     1399                err_mess = "cansas_reader.read: error processing entry notes\n" 
     1400                err_mess += "  %s" % sys.exc_value 
    13011401                self.errors.append(err_mess) 
    13021402                logging.error(err_mess) 
     
    13081408 
    13091409        self._store_content('ns:SASsample/ns:ID', dom, 'ID', data_info.sample) 
    1310         self._store_float('ns:SASsample/ns:thickness', dom, 'thickness', data_info.sample) 
    1311         self._store_float('ns:SASsample/ns:transmission', dom, 'transmission', data_info.sample) 
    1312         self._store_float('ns:SASsample/ns:temperature', dom, 'temperature', data_info.sample) 
    1313  
    1314         nodes = dom.xpath('ns:SASsample/ns:details', namespaces={'ns': CANSAS_NS}) 
     1410        self._store_float('ns:SASsample/ns:thickness', dom, 'thickness', 
     1411                          data_info.sample) 
     1412        self._store_float('ns:SASsample/ns:transmission', dom, 'transmission', 
     1413                          data_info.sample) 
     1414        self._store_float('ns:SASsample/ns:temperature', dom, 'temperature', 
     1415                          data_info.sample) 
     1416 
     1417        nodes = dom.xpath('ns:SASsample/ns:details', 
     1418                          namespaces={'ns': CANSAS_NS}) 
    13151419        for item in nodes: 
    13161420            try: 
     
    13201424                        data_info.sample.details.append(detail_value) 
    13211425            except Exception: 
    1322                 err_mess = "cansas_reader.read: error processing sample details\n  %s" % sys.exc_value 
     1426                err_mess = "cansas_reader.read: error processing entry notes\n" 
     1427                err_mess += "  %s" % sys.exc_value 
    13231428                self.errors.append(err_mess) 
    13241429                logging.error(err_mess) 
    13251430 
    13261431        # Position (as a vector) 
    1327         self._store_float('ns:SASsample/ns:position/ns:x', dom, 'position.x', data_info.sample) 
    1328         self._store_float('ns:SASsample/ns:position/ns:y', dom, 'position.y', data_info.sample) 
    1329         self._store_float('ns:SASsample/ns:position/ns:z', dom, 'position.z', data_info.sample) 
     1432        self._store_float('ns:SASsample/ns:position/ns:x', dom, 'position.x', 
     1433                          data_info.sample) 
     1434        self._store_float('ns:SASsample/ns:position/ns:y', dom, 'position.y', 
     1435                          data_info.sample) 
     1436        self._store_float('ns:SASsample/ns:position/ns:z', dom, 'position.z', 
     1437                          data_info.sample) 
    13301438 
    13311439        # Orientation (as a vector) 
     
    14611569                        process.term.append(term_attr) 
    14621570                except: 
    1463                     err_mess = "cansas_reader.read: error processing process term\n  %s" % sys.exc_value 
     1571                    err_mess = "cansas_reader.read: error processing " 
     1572                    err_mess += "entry notes\n  %s" % sys.exc_value 
    14641573                    self.errors.append(err_mess) 
    14651574                    logging.error(err_mess) 
     
    14761585        nodes = dom.xpath('ns:SASdata', namespaces={'ns': CANSAS_NS}) 
    14771586        if len(nodes) > 1: 
    1478             raise RuntimeError, "CanSAS reader is not compatible with multiple SASdata entries" 
     1587            raise RuntimeError, "CanSAS reader is not compatible with" + \ 
     1588                                " multiple SASdata entries" 
    14791589 
    14801590        for entry in nodes: 
     
    14881598                value_list = [] 
    14891599                if field is not None: 
    1490                     value_list = [parse_entry_helper(node, item) for node in field] 
     1600                    value_list = \ 
     1601                        [parse_entry_helper(node, item) for node in field] 
    14911602                if len(value_list) < 2: 
    14921603                    setattr(data_info, item[0], None) 
     
    14981609    def _read_cansas(self, path): 
    14991610        """ 
    1500         Load data and P(r) information from a CanSAS XML file. 
     1611        Load data and fitting information from a CanSAS XML file. 
    15011612 
    15021613        :param path: file path 
    1503  
    15041614        :return: Data1D object if a single SASentry was found, 
    15051615                    or a list of Data1D objects if multiple entries were found, 
    15061616                    or None of nothing was found 
    1507  
    15081617        :raise RuntimeError: when the file can't be opened 
    15091618        :raise ValueError: when the length of the data vectors are inconsistent 
    1510  
    15111619        """ 
    15121620        output = [] 
     1621        simfitstate = None 
    15131622        basename = os.path.basename(path) 
    15141623        root, extension = os.path.splitext(basename) 
     
    15161625        try: 
    15171626            if os.path.isfile(path): 
    1518  
    1519                 #TODO: eventually remove the check for .xml once 
    1520                 # the P(r) writer/reader is truly complete. 
    1521                 if  ext in self.ext or \ 
    1522                     ext == '.xml': 
    1523  
     1627                if ext in self.ext or ext == '.xml': 
    15241628                    tree = etree.parse(path, parser=etree.ETCompatXMLParser()) 
    15251629                    # Check the format version number 
    1526                     # Specifying the namespace will take care of the file format version 
     1630                    # Specifying the namespace will take care of the file 
     1631                    # format version 
    15271632                    root = tree.getroot() 
    15281633                    entry_list = root.xpath('ns:SASentry', 
    15291634                                            namespaces={'ns': CANSAS_NS}) 
     1635                    name_map = {} 
    15301636                    for entry in entry_list: 
    15311637                        try: 
     
    15351641                        fitstate = self._parse_state(entry) 
    15361642 
    1537                         #state could be None when .svs file is loaded 
    1538                         #in this case, skip appending to output 
    1539                         if fitstate != None: 
     1643                        # state could be None when .svs file is loaded 
     1644                        # in this case, skip appending to output 
     1645                        if fitstate is not None: 
    15401646                            sas_entry.meta_data['fitstate'] = fitstate 
    15411647                            sas_entry.filename = fitstate.file 
    15421648                            output.append(sas_entry) 
     1649 
    15431650            else: 
    15441651                self.call_back(format=ext) 
     
    15801687                        name = original_fname 
    15811688                    state.data.group_id = name 
    1582                     #store state in fitting 
     1689                    # store state in fitting 
    15831690                    self.call_back(state=state, 
    15841691                                   datainfo=output[ind], format=ext) 
    15851692                    self.state = state 
     1693                simfitstate = self._parse_simfit_state(entry) 
     1694                if simfitstate is not None: 
     1695                    self.call_back(state=simfitstate) 
     1696 
    15861697                return output 
    15871698        except: 
     
    15991710        """ 
    16001711        # Sanity check 
    1601         if self.cansas == True: 
     1712        if self.cansas: 
    16021713            # Add fitting information to the XML document 
    16031714            doc = self.write_toXML(datainfo, fitstate) 
     
    16111722        fd.close() 
    16121723 
    1613     def write_toXML(self, datainfo=None, state=None): 
     1724    def write_toXML(self, datainfo=None, state=None, batchfit=None): 
    16141725        """ 
    16151726        Write toXML, a helper for write(), 
     
    16191730        """ 
    16201731 
    1621         if state.data is None: 
    1622             data = sas.sascalc.dataloader.data_info.Data1D(x=[], y=[]) 
     1732        self.batchfit_params = batchfit 
     1733        if state.data is None or not state.data.is_data: 
    16231734            return None 
    1624         elif not state.data.is_data: 
    1625             return None 
     1735        # make sure title and data run are filled. 
     1736        if state.data.title is None or state.data.title == '': 
     1737            state.data.title = state.data.name 
     1738        if state.data.run_name is None or state.data.run_name == {}: 
     1739            state.data.run = [str(state.data.name)] 
     1740            state.data.run_name[0] = state.data.name 
     1741 
     1742        if issubclass(state.data.__class__, 
     1743                      sas.sascalc.dataloader.data_info.Data1D): 
     1744            data = state.data 
     1745            doc, sasentry = self._to_xml_doc(data) 
    16261746        else: 
    1627             #make sure title and data run is filled up. 
    1628             if state.data.title == None or state.data.title == '': 
    1629                 state.data.title = state.data.name 
    1630             if state.data.run_name == None or state.data.run_name == {}: 
    1631                 state.data.run = [str(state.data.name)] 
    1632                 state.data.run_name[0] = state.data.name 
    1633  
    1634             if issubclass(state.data.__class__, 
    1635                           sas.sascalc.dataloader.data_info.Data1D): 
    1636                 data = state.data 
    1637                 doc, sasentry = self._to_xml_doc(data) 
    1638             else: 
    1639                 data = state.data 
    1640                 doc, sasentry = self._data2d_to_xml_doc(data) 
     1747            data = state.data 
     1748            doc, sasentry = self._data2d_to_xml_doc(data) 
    16411749 
    16421750        if state is not None: 
    1643             doc = state.toXML(doc=doc, file=data.filename, entry_node=sasentry) 
     1751            doc = state.toXML(doc=doc, file=data.filename, entry_node=sasentry, 
     1752                              batch_fit_state=self.batchfit_params) 
    16441753 
    16451754        return doc 
    1646  
    1647 # Simple html report templet 
    1648 HEADER = "<html>\n" 
    1649 HEADER += "<head>\n" 
    1650 HEADER += "<meta http-equiv=Content-Type content='text/html; " 
    1651 HEADER += "charset=windows-1252'> \n" 
    1652 HEADER += "<meta name=Generator >\n" 
    1653 HEADER += "</head>\n" 
    1654 HEADER += "<body lang=EN-US>\n" 
    1655 HEADER += "<div class=WordSection1>\n" 
    1656 HEADER += "<p class=MsoNormal><b><span ><center><font size='4' >" 
    1657 HEADER += "%s</font></center></span></center></b></p>" 
    1658 HEADER += "<p class=MsoNormal>&nbsp;</p>" 
    1659 PARA = "<p class=MsoNormal><font size='4' > %s \n" 
    1660 PARA += "</font></p>" 
    1661 CENTRE = "<p class=MsoNormal><center><font size='4' > %s \n" 
    1662 CENTRE += "</font></center></p>" 
    1663 FEET_1 = \ 
    1664 """ 
    1665 <p class=MsoNormal>&nbsp;</p> 
    1666 <br> 
    1667 <p class=MsoNormal><b><span ><center> <font size='4' > Graph 
    1668 </font></span></center></b></p> 
    1669 <p class=MsoNormal>&nbsp;</p> 
    1670 <center> 
    1671 <br><font size='4' >Model Computation</font> 
    1672 <br><font size='4' >Data: "%s"</font><br> 
    1673 """ 
    1674 FEET_2 = \ 
    1675 """ 
    1676 <img src="%s" > 
    1677 </img> 
    1678 """ 
    1679 FEET_3 = \ 
    1680 """ 
    1681 </center> 
    1682 </div> 
    1683 </body> 
    1684 </html> 
    1685 """ 
    1686 ELINE = "<p class=MsoNormal>&nbsp;</p>" 
    1687  
    1688 if __name__ == "__main__": 
    1689     state = PageState(parent=None) 
    1690     #state.toXML() 
    1691     """ 
    1692  
    1693     file = open("test_state", "w") 
    1694     pickle.dump(state, file) 
    1695     print pickle.dumps(state) 
    1696     state.data_name = "hello---->" 
    1697     pickle.dump(state, file) 
    1698     file = open("test_state", "r") 
    1699     new_state= pickle.load(file) 
    1700     print "new state", new_state 
    1701     new_state= pickle.load(file) 
    1702     print "new state", new_state 
    1703     #print "state", state 
    1704     """ 
    1705     import bsddb 
    1706     import pickle 
    1707     db = bsddb.btopen('file_state.db', 'c') 
    1708     val = (pickle.dumps(state), "hello", "hi") 
    1709     db['state1'] = pickle.dumps(val) 
    1710     print pickle.loads(db['state1']) 
    1711     state.data_name = "hello---->22" 
    1712     db['state2'] = pickle.dumps(state) 
    1713     state.data_name = "hello---->2" 
    1714     db['state3'] = pickle.dumps(state) 
    1715     del db['state3'] 
    1716     state.data_name = "hello---->3" 
    1717     db['state4'] = pickle.dumps(state) 
    1718     new_state = pickle.loads(db['state1']) 
    1719     #print db.last() 
    1720     db.set_location('state2') 
    1721     state.data_name = "hello---->5" 
    1722     db['aastate5'] = pickle.dumps(state) 
    1723     db.keys().sort() 
    1724     print pickle.loads(db['state2']) 
    1725  
    1726     db.close() 
  • src/sas/sasgui/perspectives/fitting/simfitpage.py

    r4cafdff r998ca90  
    99from wx.lib.scrolledpanel import ScrolledPanel 
    1010 
    11 from sas.sasgui.guiframe.events import StatusEvent 
     11from sas.sasgui.guiframe.events import StatusEvent, PanelOnFocusEvent 
    1212from sas.sasgui.guiframe.panel_base import PanelBase 
    13 from sas.sasgui.guiframe.events import PanelOnFocusEvent 
    1413from sas.sasgui.guiframe.utils import IdList 
    1514from sas.sasgui.guiframe.documentation_window import DocumentationWindow 
    1615 
    17 #Control panel width  
     16# Control panel width 
    1817if sys.platform.count("darwin") == 0: 
    1918    PANEL_WID = 420 
     
    2928        'model_cbox param_cbox egal_txt constraint btRemove sizer') 
    3029 
     30 
    3131def get_fittableParam(model): 
    3232    """ 
     
    4747    return fittable_param 
    4848 
     49 
    4950class SimultaneousFitPage(ScrolledPanel, PanelBase): 
    5051    """ 
     
    5354    two data members window_name and window_caption 
    5455    """ 
    55     ## Internal name for the AUI manager 
    56     window_name = "simultaneous Fit page" 
    57     ## Title to appear on top of the window 
     56    # Internal name for the AUI manager 
     57    window_name = "Simultaneous Fit Page" 
     58    # Title to appear on top of the window 
    5859    window_caption = "Simultaneous Fit Page" 
    5960    ID_DOC = wx.NewId() 
     
    7475        self._ids = iter(self._id_pool) 
    7576        self.SetupScrolling() 
    76         ##Font size 
     77        # Font size 
    7778        self.SetWindowVariant(variant=FONT_VARIANT) 
    7879        self.uid = wx.NewId() 
    7980        self.parent = parent 
    8081        self.batch_on = batch_on 
    81         ## store page_finder 
     82        # store page_finder 
    8283        self.page_finder = page_finder 
    83         ## list containing info to set constraint 
    84         ## look like self.constraint_dict[page_id]= page 
     84        # list containing info to set constraint 
     85        # look like self.constraint_dict[page_id]= page 
    8586        self.constraint_dict = {} 
    86         ## item list 
    87         ## self.constraints_list=[combobox1, combobox2,=,textcrtl, button ] 
     87        # item list 
     88        # self.constraints_list=[combobox1, combobox2,=,textcrtl, button ] 
    8889        self.constraints_list = [] 
    89         ## list of current model 
     90        # list of current model 
    9091        self.model_list = [] 
    91         ## selected mdoel to fit 
    92         self.model_toFit = [] 
    93         ## Control the fit state 
     92        # selected model to fit 
     93        self.model_to_fit = [] 
     94        # Control the fit state 
    9495        self.fit_started = False 
    95         ## number of constraint 
     96        # number of constraint 
    9697        self.nb_constraint = 0 
     98        self.state = SimFitPageState() 
    9799        self.model_cbox_left = None 
    98100        self.model_cbox_right = None 
    99         ## draw page 
     101        # draw page 
    100102        self.define_page_structure() 
    101103        self.draw_page() 
     
    107109        """ 
    108110        self.vbox = wx.BoxSizer(wx.VERTICAL) 
    109         self.sizer1 = wx.BoxSizer(wx.VERTICAL) 
    110         self.sizer2 = wx.BoxSizer(wx.VERTICAL) 
    111         self.sizer3 = wx.BoxSizer(wx.VERTICAL) 
    112  
    113         self.sizer1.SetMinSize((PANEL_WID, -1)) 
    114         self.sizer2.SetMinSize((PANEL_WID, -1)) 
    115         self.sizer3.SetMinSize((PANEL_WID, -1)) 
    116         self.vbox.Add(self.sizer1) 
    117         self.vbox.Add(self.sizer2) 
    118         self.vbox.Add(self.sizer3) 
     111        self.data_selection_sizer = wx.BoxSizer(wx.VERTICAL) 
     112        self.constraints_sizer = wx.BoxSizer(wx.VERTICAL) 
     113        self.run_fit_sizer = wx.BoxSizer(wx.VERTICAL) 
     114 
     115        self.data_selection_sizer.SetMinSize((PANEL_WID, -1)) 
     116        self.constraints_sizer.SetMinSize((PANEL_WID, -1)) 
     117        self.run_fit_sizer.SetMinSize((PANEL_WID, -1)) 
     118        self.vbox.Add(self.data_selection_sizer) 
     119        self.vbox.Add(self.constraints_sizer) 
     120        self.vbox.Add(self.run_fit_sizer) 
    119121        self.SetSizer(self.vbox) 
    120122        self.Centre() 
     123 
     124    def set_state(self): 
     125        """ 
     126        Define a set of state parameters for saving simultaneous fits. 
     127        """ 
     128        self._set_constraint() 
     129        self.state.fit_page_no = self.uid 
     130        self.state.select_all = self.cb1.GetValue() 
     131        self.state.model_list = self.model_list 
     132        self.state.model_to_fit = self.model_to_fit 
     133        self.state.no_constraint = self.nb_constraint 
     134        self.state.constraint_dict = self.constraint_dict 
     135        self.state.constraints_list = self.constraints_list 
     136        return self.get_state() 
     137 
     138    def get_state(self): 
     139        """ 
     140        Return the state of the current page 
     141        :return: self.state 
     142        """ 
     143        return self.state 
    121144 
    122145    def draw_page(self): 
     
    131154        # create blank list of constraints 
    132155        self.model_list = [] 
    133         self.model_toFit = [] 
     156        self.model_to_fit = [] 
    134157        self.constraints_list = [] 
    135158        self.constraint_dict = {} 
     
    144167 
    145168        #------------------------------------------------------- 
    146         ## setup sizer1 (which fitpages to include) 
    147         self.sizer1.Clear(True) 
     169        # setup sizer1 (which fitpages to include) 
     170        self.data_selection_sizer.Clear(True) 
    148171        box_description = wx.StaticBox(self, wx.ID_ANY, "Fit Combinations") 
    149172        boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL) 
     
    151174        sizer_couples = wx.GridBagSizer(5, 5) 
    152175 
    153         #This if statement should be obsolete and can be removed in version 4 
    154         #Leave it here for now as no time to thoroughly test.  However if no 
    155         #fit page is found the menu item that calls this page is inactive  
    156         # Nov. 22 2015  --PDB 
     176        # The wx GUI has a flag to enable a menu item, but can still be 
     177        # reached via scripting. There is no guearantee future GUI 
     178        # implementations force this check, either. 
     179        # IMHO, this if statement should stay -- JRK 2016-OCT-05 
    157180        if len(self.page_finder) == 0: 
    158181            msg = " No fit combinations are found! \n\n" 
     
    161184            sizer_title.Add(wx.StaticText(self, wx.ID_ANY, msg)) 
    162185        else: 
    163             ## store model 
     186            # store model 
    164187            self._store_model() 
    165188 
     
    171194                wx.TOP | wx.BOTTOM | wx.EXPAND | wx.ADJUST_MINSIZE, border=5) 
    172195            sizer_title.Add(self.cb1, 0, 
    173                 wx.TOP | wx.BOTTOM | wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, border=5) 
    174  
    175             ## draw list of model and data names 
     196                wx.TOP | wx.BOTTOM | wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 
     197                border=5) 
     198 
     199            # draw list of model and data names 
    176200            self._fill_sizer_model_list(sizer_couples) 
    177201 
    178202        boxsizer1.Add(sizer_title, flag=wx.TOP | wx.BOTTOM, border=5) 
    179203        boxsizer1.Add(sizer_couples, 1, flag=wx.TOP | wx.BOTTOM, border=5) 
    180         self.sizer1.Add(boxsizer1, 1, wx.EXPAND | wx.ALL, 10) 
    181 #        self.sizer1.Layout() 
     204        self.data_selection_sizer.Add(boxsizer1, 1, wx.EXPAND | wx.ALL, 10) 
     205        # self.sizer1.Layout() 
    182206 
    183207        #-------------------------------------------------------- 
    184         ## set up the other 2 sizers: the constraints list and the 
    185         ## buttons (fit, help etc) sizer at the bottom of the page. 
    186         ## Note: the if statement should be removed along with the above 
    187         ## if statement as soon as it can be properly tested. 
    188         ## Nov. 22 2015  --PDB 
     208        # set up the other 2 sizers: the constraints list and the 
     209        # buttons (fit, help etc) sizer at the bottom of the page. 
     210        # Note: the if statement should be removed along with the above 
     211        # if statement as soon as it can be properly tested. 
     212        # Nov. 22 2015  --PDB 
     213        # As above, this page can be accessed through other means than the 
     214        # base SasView GUI. 
     215        # Oct. 5, 2016 --JRK 
    189216        if len(self.page_finder) > 0: 
    190             ## draw the sizer containing constraint info 
     217            # draw the sizer containing constraint info 
    191218            if not self.batch_on: 
    192219                self._fill_sizer_constraint() 
    193             ## draw fit button sizer 
     220            # draw fit button sizer 
    194221            self._fill_sizer_fit() 
    195  
    196222 
    197223    def _fill_sizer_model_list(self, sizer): 
     
    201227        ix = 0 
    202228        iy = 0 
    203         list = [] 
    204229        sizer.Clear(True) 
    205230 
     
    209234        new_name.SetForegroundColour(wx.WHITE) 
    210235        sizer.Add(new_name, (iy, ix), (1, 1), 
    211                             wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 15) 
     236                  wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 15) 
    212237        ix += 2 
    213238        model_type = wx.StaticText(self, wx.ID_ANY, '  Model ') 
     
    215240        model_type.SetForegroundColour(wx.WHITE) 
    216241        sizer.Add(model_type, (iy, ix), (1, 1), 
    217                             wx.EXPAND | wx.ADJUST_MINSIZE, 0) 
     242                  wx.EXPAND | wx.ADJUST_MINSIZE, 0) 
    218243        ix += 1 
    219244        data_used = wx.StaticText(self, wx.ID_ANY, '  Data ') 
     
    221246        data_used.SetForegroundColour(wx.WHITE) 
    222247        sizer.Add(data_used, (iy, ix), (1, 1), 
    223                             wx.EXPAND | wx.ADJUST_MINSIZE, 0) 
     248                  wx.EXPAND | wx.ADJUST_MINSIZE, 0) 
    224249        ix += 1 
    225250        tab_used = wx.StaticText(self, wx.ID_ANY, '  FitPage ') 
     
    302327        wx.PostEvent(self.parent.parent, StatusEvent(status=msg)) 
    303328 
    304         self.sizer2.Clear(True) 
     329        self.constraints_sizer.Clear(True) 
    305330        if self.batch_on: 
    306             if self.sizer2.IsShown(): 
    307                 self.sizer2.Show(False) 
     331            if self.constraints_sizer.IsShown(): 
     332                self.constraints_sizer.Show(False) 
    308333            return 
    309334        box_description = wx.StaticBox(self, wx.ID_ANY, "Fit Constraints") 
    310         boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL) 
     335        box_sizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL) 
    311336        sizer_title = wx.BoxSizer(wx.HORIZONTAL) 
    312337        self.sizer_all_constraints = wx.BoxSizer(wx.HORIZONTAL) 
     
    338363 
    339364        self.btAdd = wx.Button(self, self.ID_ADD, 'Add') 
    340         self.btAdd.Bind(wx.EVT_BUTTON, self._onAdd_constraint, 
     365        self.btAdd.Bind(wx.EVT_BUTTON, self._on_add_constraint, 
    341366                        id=self.btAdd.GetId()) 
    342367        self.btAdd.SetToolTipString("Add another constraint?") 
     
    344369 
    345370        text_hint = wx.StaticText(self, wx.ID_ANY, 
    346                                   "Example: [M0][paramter] = M1.parameter") 
     371                                  "Example: [M0][parameter] = M1.parameter") 
    347372        sizer_button.Add(text_hint, 0, 
    348373                         wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 10) 
     
    350375                         wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 10) 
    351376 
    352         boxsizer1.Add(sizer_title, flag=wx.TOP | wx.BOTTOM, border=10) 
    353         boxsizer1.Add(self.sizer_all_constraints, flag=wx.TOP | wx.BOTTOM, 
    354                       border=10) 
    355         boxsizer1.Add(self.sizer_constraints, flag=wx.TOP | wx.BOTTOM, 
    356                       border=10) 
    357         boxsizer1.Add(sizer_button, flag=wx.TOP | wx.BOTTOM, border=10) 
    358  
    359         self.sizer2.Add(boxsizer1, 0, wx.EXPAND | wx.ALL, 10) 
    360  
     377        box_sizer1.Add(sizer_title, flag=wx.TOP | wx.BOTTOM, border=10) 
     378        box_sizer1.Add(self.sizer_all_constraints, flag=wx.TOP | wx.BOTTOM, 
     379                       border=10) 
     380        box_sizer1.Add(self.sizer_constraints, flag=wx.TOP | wx.BOTTOM, 
     381                       border=10) 
     382        box_sizer1.Add(sizer_button, flag=wx.TOP | wx.BOTTOM, border=10) 
     383 
     384        self.constraints_sizer.Add(box_sizer1, 0, wx.EXPAND | wx.ALL, 10) 
    361385 
    362386    def _fill_sizer_fit(self): 
     
    364388        Draw fit button 
    365389        """ 
    366         self.sizer3.Clear(True) 
     390        self.run_fit_sizer.Clear(True) 
    367391        box_description = wx.StaticBox(self, wx.ID_ANY, "Fit ") 
    368392        boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL) 
    369393        sizer_button = wx.BoxSizer(wx.HORIZONTAL) 
    370394 
    371         #Fit button 
     395        # Fit button 
    372396        self.btFit = wx.Button(self, self.ID_FIT, 'Fit', size=wx.DefaultSize) 
    373         self.btFit.Bind(wx.EVT_BUTTON, self.onFit, id=self.btFit.GetId()) 
     397        self.btFit.Bind(wx.EVT_BUTTON, self.on_fit, id=self.btFit.GetId()) 
    374398        self.btFit.SetToolTipString("Perform fit.") 
    375399 
    376         #General Help button 
     400        # General Help button 
    377401        self.btHelp = wx.Button(self, wx.ID_HELP, 'HELP') 
    378402        self.btHelp.SetToolTipString("Simultaneous/Constrained Fitting help.") 
    379         self.btHelp.Bind(wx.EVT_BUTTON, self._onHelp) 
    380  
    381         #hint text on button line 
     403        self.btHelp.Bind(wx.EVT_BUTTON, self._on_help) 
     404 
     405        # hint text on button line 
    382406        if self.batch_on: 
    383407            text = " Fit in Parallel all Data sets\n" 
     
    393417 
    394418        boxsizer1.Add(sizer_button, flag=wx.TOP | wx.BOTTOM, border=10) 
    395         self.sizer3.Add(boxsizer1, 0, wx.EXPAND | wx.ALL, 10) 
    396  
    397     def onRemove(self, event): 
     419        self.run_fit_sizer.Add(boxsizer1, 0, wx.EXPAND | wx.ALL, 10) 
     420 
     421    def on_remove(self, event): 
    398422        """ 
    399423        Remove constraint fields 
     
    406430            return 
    407431        wx.CallAfter(self._remove_after, event.GetId()) 
    408         #self._onAdd_constraint(None) 
     432        # self._onAdd_constraint(None) 
    409433 
    410434    def _remove_after(self, id): 
     
    416440                self.constraints_list.remove(item) 
    417441                self.nb_constraint -= 1 
    418                 self.sizer2.Layout() 
     442                self.constraints_sizer.Layout() 
    419443                self.FitInside() 
    420444                break 
    421445 
    422     def onFit(self, event): 
     446    def on_fit(self, event): 
    423447        """ 
    424448        signal for fitting 
     
    435459            flag = (self._manager.sim_page.uid == self.uid) 
    436460 
    437         ## making sure all parameters content a constraint 
     461        # making sure all parameters content a constraint 
    438462        if not self.batch_on and self.show_constraint.GetValue(): 
    439463            if not self._set_constraint(): 
    440464                return 
    441         ## model was actually selected from this page to be fit 
    442         if len(self.model_toFit) >= 1: 
     465        # model was actually selected from this page to be fit 
     466        if len(self.model_to_fit) >= 1: 
    443467            self.manager._reset_schedule_problem(value=0) 
    444468            for item in self.model_list: 
     
    456480            msg = "Select at least one model check box to fit " 
    457481            wx.PostEvent(self.parent.parent, StatusEvent(status=msg)) 
     482        self.set_state() 
    458483 
    459484    def _on_fit_complete(self): 
     
    467492        """ 
    468493        Attempt to stop the fitting thread 
    469         """ 
    470         if event != None: 
     494 
     495        :param event: Event handler when stop fit is clicked 
     496        """ 
     497        if event is not None: 
    471498            event.Skip() 
    472499        self.manager.stop_fit(self.uid) 
     
    485512        self.btFit.Enable(True) 
    486513 
    487     def _onHelp(self, event): 
     514    def _on_help(self, event): 
    488515        """ 
    489516        Bring up the simultaneous Fitting Documentation whenever the HELP 
     
    494521        versions of Wx (before 2.9) and thus not the release version of 
    495522        installers, the help comes up at the top level of the file as 
    496         webbrowser does not pass anything past the # to the browser when it is 
     523        web browser does not pass anything past the # to the browser when it is 
    497524        running "file:///...." 
    498525 
    499     :param evt: Triggers on clicking the help button 
     526    :param event: Triggers on clicking the help button 
    500527    """ 
    501528        _TreeLocation = "user/sasgui/perspectives/fitting/fitting_help.html" 
     
    510537 
    511538        :param manager: instance of plugin fitting 
    512  
    513539        """ 
    514540        self.manager = manager 
     
    518544        check all models names 
    519545        """ 
    520         self.model_toFit = [] 
    521         if self.cb1.GetValue() == True: 
     546        self.model_to_fit = [] 
     547        if self.cb1.GetValue(): 
    522548            for item in self.model_list: 
    523549                if item[0].IsEnabled(): 
    524550                    item[0].SetValue(True) 
    525                     self.model_toFit.append(item) 
    526  
    527             ## constraint info 
     551                    self.model_to_fit.append(item) 
     552 
     553            # constraint info 
    528554            self._store_model() 
    529555            if not self.batch_on: 
    530                 ## display constraint fields 
     556                # display constraint fields 
    531557                if (self.show_constraint.GetValue() and 
    532558                                 len(self.constraints_list) == 0): 
     
    538564 
    539565            if not self.batch_on: 
    540                 ##constraint info 
     566                # constraint info 
    541567                self._hide_constraint() 
    542568 
     
    544570        self.FitInside() 
    545571 
    546  
    547572    def check_model_name(self, event): 
    548573        """ 
    549574        Save information related to checkbox and their states 
    550575        """ 
    551         self.model_toFit = [] 
    552         cbox = event.GetEventObject() 
     576        self.model_to_fit = [] 
    553577        for item in self.model_list: 
    554             if item[0].GetValue() == True: 
    555                 self.model_toFit.append(item) 
     578            if item[0].GetValue(): 
     579                self.model_to_fit.append(item) 
    556580            else: 
    557                 if item in self.model_toFit: 
    558                     self.model_toFit.remove(item) 
     581                if item in self.model_to_fit: 
     582                    self.model_to_fit.remove(item) 
    559583                    self.cb1.SetValue(False) 
    560584 
    561         ## display constraint fields 
    562         if len(self.model_toFit) >= 1: 
     585        # display constraint fields 
     586        if len(self.model_to_fit) >= 1: 
    563587            self._store_model() 
    564588            if not self.batch_on and self.show_constraint.GetValue() and\ 
     
    567591                self._show_constraint() 
    568592 
    569         elif len(self.model_toFit) < 1: 
    570             ##constraint info 
     593        elif len(self.model_to_fit) < 1: 
     594            # constraint info 
    571595            self._hide_constraint() 
    572596 
    573597        self._update_easy_setup_cb() 
    574         ## set the value of the main check button 
    575         if len(self.model_list) == len(self.model_toFit): 
     598        # set the value of the main check button 
     599        if len(self.model_list) == len(self.model_to_fit): 
    576600            self.cb1.SetValue(True) 
    577601            self.FitInside() 
     
    585609        Update easy setup combobox on selecting a model 
    586610        """ 
    587         if self.model_cbox_left == None or self.model_cbox_right == None: 
    588             return 
    589  
    590         models = [(item[3].name, item[3]) for item in self.model_toFit] 
     611        if self.model_cbox_left is None or self.model_cbox_right is None: 
     612            return 
     613 
     614        models = [(item[3].name, item[3]) for item in self.model_to_fit] 
    591615        setComboBoxItems(self.model_cbox_left, models) 
    592616        setComboBoxItems(self.model_cbox_right, models) 
     
    595619        if self.model_cbox_left.GetSelection() == wx.NOT_FOUND: 
    596620            self.model_cbox_left.SetSelection(0) 
    597         self.sizer2.Layout() 
     621        self.constraints_sizer.Layout() 
    598622 
    599623    def _store_model(self): 
     
    601625         Store selected model 
    602626        """ 
    603         if len(self.model_toFit) < 1: 
    604             return 
    605         for item in self.model_toFit: 
     627        if len(self.model_to_fit) < 1: 
     628            return 
     629        for item in self.model_to_fit: 
    606630            model = item[3] 
    607631            page_id = item[2] 
     
    612636        Show fields to add constraint 
    613637        """ 
    614         if len(self.model_toFit) < 1: 
     638        if len(self.model_to_fit) < 1: 
    615639            msg = "Select at least 1 model to add constraint " 
    616640            wx.PostEvent(self.parent.parent, StatusEvent(status=msg)) 
    617             ## hide button 
     641            # hide button 
    618642            self._hide_constraint() 
    619643            return 
     
    632656        """ 
    633657        box_description = wx.StaticBox(self, wx.ID_ANY, "Easy Setup ") 
    634         boxsizer = wx.StaticBoxSizer(box_description, wx.HORIZONTAL) 
     658        box_sizer = wx.StaticBoxSizer(box_description, wx.HORIZONTAL) 
    635659        sizer_constraint = wx.BoxSizer(wx.HORIZONTAL) 
    636660        self.model_cbox_left = wx.ComboBox(self, wx.ID_ANY, style=wx.CB_READONLY) 
     
    650674 
    651675        for id, model in self.constraint_dict.iteritems(): 
    652             ## check if all parameters have been selected for constraint 
    653             ## then do not allow add constraint on parameters 
     676            # check if all parameters have been selected for constraint 
     677            # then do not allow add constraint on parameters 
    654678            self.model_cbox_left.Append(str(model.name), model) 
    655679        self.model_cbox_left.Select(0) 
    656680        for id, model in self.constraint_dict.iteritems(): 
    657             ## check if all parameters have been selected for constraint 
    658             ## then do not allow add constraint on parameters 
     681            # check if all parameters have been selected for constraint 
     682            # then do not allow add constraint on parameters 
    659683            self.model_cbox_right.Append(str(model.name), model) 
    660         boxsizer.Add(self.model_cbox_left, 
     684        box_sizer.Add(self.model_cbox_left, 
    661685                             flag=wx.RIGHT | wx.EXPAND, border=10) 
    662         #boxsizer.Add(wx.StaticText(self, wx.ID_ANY, ".parameters"), 
     686        # box_sizer.Add(wx.StaticText(self, wx.ID_ANY, ".parameters"), 
    663687        #                     flag=wx.RIGHT | wx.EXPAND, border=5) 
    664         boxsizer.Add(egal_txt, flag=wx.RIGHT | wx.EXPAND, border=5) 
    665         boxsizer.Add(self.model_cbox_right, 
     688        box_sizer.Add(egal_txt, flag=wx.RIGHT | wx.EXPAND, border=5) 
     689        box_sizer.Add(self.model_cbox_right, 
    666690                             flag=wx.RIGHT | wx.EXPAND, border=10) 
    667         #boxsizer.Add(wx.StaticText(self, wx.ID_ANY, ".parameters"), 
     691        # box_sizer.Add(wx.StaticText(self, wx.ID_ANY, ".parameters"), 
    668692        #                     flag=wx.RIGHT | wx.EXPAND, border=5) 
    669         boxsizer.Add((20, -1)) 
    670         boxsizer.Add(self.set_button, flag=wx.RIGHT | wx.EXPAND, border=5) 
    671         sizer_constraint.Add(boxsizer, flag=wx.RIGHT | wx.EXPAND, border=5) 
     693        box_sizer.Add((20, -1)) 
     694        box_sizer.Add(self.set_button, flag=wx.RIGHT | wx.EXPAND, border=5) 
     695        sizer_constraint.Add(box_sizer, flag=wx.RIGHT | wx.EXPAND, border=5) 
    672696        self.sizer_all_constraints.Insert(before=0, 
    673697                             item=sizer_constraint, 
     
    699723            return 
    700724        param_list = [] 
    701         param_listB = [] 
     725        param_list_b = [] 
    702726        selection = self.model_cbox_left.GetCurrentSelection() 
    703727        model_left = self.model_cbox_left.GetValue() 
    704728        model = self.model_cbox_left.GetClientData(selection) 
    705         selectionB = self.model_cbox_right.GetCurrentSelection() 
     729        selection_b = self.model_cbox_right.GetCurrentSelection() 
    706730        model_right = self.model_cbox_right.GetValue() 
    707         modelB = self.model_cbox_right.GetClientData(selectionB) 
     731        model_b = self.model_cbox_right.GetClientData(selection_b) 
    708732        for id, dic_model in self.constraint_dict.iteritems(): 
    709733            if model == dic_model: 
    710734                param_list = self.page_finder[id].get_param2fit() 
    711             if modelB == dic_model: 
    712                 param_listB = self.page_finder[id].get_param2fit() 
    713             if len(param_list) > 0 and len(param_listB) > 0: 
     735            if model_b == dic_model: 
     736                param_list_b = self.page_finder[id].get_param2fit() 
     737            if len(param_list) > 0 and len(param_list_b) > 0: 
    714738                break 
    715739        num_cbox = 0 
     
    717741        for param in param_list: 
    718742            num_cbox += 1 
    719             if param in param_listB: 
     743            if param in param_list_b: 
    720744                item = self.constraints_list[-1] 
    721745                item.model_cbox.SetStringSelection(model_left) 
     
    744768        """ 
    745769        Show constraint fields 
     770        :param dict: dictionary mapping constraint values 
    746771        """ 
    747772        self.btAdd.Show(True) 
     
    750775            for id, model in self.constraint_dict.iteritems(): 
    751776                nb_fit_param += len(self.page_finder[id].get_param2fit()) 
    752             ##Don't add anymore 
     777            # Don't add anymore 
    753778            if len(self.constraints_list) == nb_fit_param: 
    754779                msg = "Cannot add another constraint. Maximum of number " 
     
    756781                wx.PostEvent(self.parent.parent, StatusEvent(status=msg)) 
    757782                self.sizer_constraints.Layout() 
    758                 self.sizer2.Layout() 
     783                self.constraints_sizer.Layout() 
    759784                return 
    760         if len(self.model_toFit) < 1: 
     785        if len(self.model_to_fit) < 1: 
    761786            msg = "Select at least 1 model to add constraint " 
    762787            wx.PostEvent(self.parent.parent, StatusEvent(status=msg)) 
    763788            self.sizer_constraints.Layout() 
    764             self.sizer2.Layout() 
     789            self.constraints_sizer.Layout() 
    765790            return 
    766791 
     
    771796        model_cbox.Clear() 
    772797        for id, model in self.constraint_dict.iteritems(): 
    773             ## check if all parameters have been selected for constraint 
    774             ## then do not allow add constraint on parameters 
     798            # check if all parameters have been selected for constraint 
     799            # then do not allow add constraint on parameters 
    775800            model_cbox.Append(str(model.name), model) 
    776801        wx.EVT_COMBOBOX(model_cbox, wx.ID_ANY, self._on_select_model) 
     
    789814        # Remove button 
    790815        #btRemove = wx.Button(self, self.ID_REMOVE, 'Remove') 
    791         btRemove = wx.Button(self, self._ids.next(), 'Remove') 
    792         btRemove.Bind(wx.EVT_BUTTON, self.onRemove, 
    793                       id=btRemove.GetId()) 
    794         btRemove.SetToolTipString("Remove constraint.") 
    795         btRemove.Hide() 
     816        bt_remove = wx.Button(self, self._ids.next(), 'Remove') 
     817        bt_remove.Bind(wx.EVT_BUTTON, self.on_remove, 
     818                      id=bt_remove.GetId()) 
     819        bt_remove.SetToolTipString("Remove constraint.") 
     820        bt_remove.Hide() 
    796821 
    797822        # Hid the add button, if it exists 
     
    804829        sizer_constraint.Add(egal_txt, flag=wx.RIGHT | wx.EXPAND, border=5) 
    805830        sizer_constraint.Add(constraint, flag=wx.RIGHT | wx.EXPAND, border=10) 
    806         sizer_constraint.Add(btRemove, flag=wx.RIGHT | wx.EXPAND, border=10) 
     831        sizer_constraint.Add(bt_remove, flag=wx.RIGHT | wx.EXPAND, border=10) 
    807832 
    808833        self.sizer_constraints.Insert(before=self.nb_constraint, 
     
    810835                border=5) 
    811836        c = ConstraintLine(model_cbox, param_cbox, egal_txt, 
    812                            constraint, btRemove, sizer_constraint) 
     837                           constraint, bt_remove, sizer_constraint) 
    813838        self.constraints_list.append(c) 
    814839 
    815840        self.nb_constraint += 1 
    816841        self.sizer_constraints.Layout() 
    817         self.sizer2.Layout() 
    818         self.Layout 
     842        self.constraints_sizer.Layout() 
     843        self.Layout() 
    819844 
    820845    def _hide_constraint(self): 
     
    841866        self.sizer_constraints.Clear(True) 
    842867        self.sizer_constraints.Layout() 
    843         self.sizer2.Layout() 
    844         self.Layout 
     868        self.constraints_sizer.Layout() 
     869        self.Layout() 
    845870        self.FitInside() 
    846871 
    847872    def _on_select_model(self, event): 
    848873        """ 
    849         fill combox box with list of parameters 
     874        fill combo box with list of parameters 
    850875        """ 
    851876        if not self.constraints_list: 
    852877            return 
    853878 
    854         ##This way PC/MAC both work, instead of using event.GetClientData(). 
     879        # This way PC/MAC both work, instead of using event.GetClientData(). 
    855880        model_cbox = self.constraints_list[-1].model_cbox 
    856881        n = model_cbox.GetCurrentSelection() 
     
    867892        param_cbox = self.constraints_list[-1].param_cbox 
    868893        param_cbox.Clear() 
    869         ## insert only fittable paramaters 
     894        # insert only fittable paramaters 
    870895        for param in param_list: 
    871896            param_cbox.Append(str(param), model) 
    872897        param_cbox.Show(True) 
    873898 
    874         btRemove = self.constraints_list[-1].btRemove 
    875         btRemove.Show(True) 
     899        bt_remove = self.constraints_list[-1].btRemove 
     900        bt_remove.Show(True) 
    876901        self.btAdd.Show(True) 
    877902#        self.Layout() 
     
    882907        Store the appropriate constraint in the page_finder 
    883908        """ 
    884         ##This way PC/MAC both work, instead of using event.GetClientData(). 
    885         #n = self.param_cbox.GetCurrentSelection() 
    886         #model = self.param_cbox.GetClientData(n) 
    887         #param = event.GetString() 
     909        # This way PC/MAC both work, instead of using event.GetClientData(). 
     910        # n = self.param_cbox.GetCurrentSelection() 
     911        # model = self.param_cbox.GetClientData(n) 
     912        # param = event.GetString() 
    888913 
    889914        if self.constraints_list: 
     
    891916            self.constraints_list[-1].constraint.Show(True) 
    892917 
    893     def _onAdd_constraint(self, event): 
     918    def _on_add_constraint(self, event): 
    894919        """ 
    895920        Add another line for constraint 
     
    899924            wx.PostEvent(self.parent.parent, StatusEvent(status=msg)) 
    900925            return 
    901         ## check that a constraint is added 
     926        # check that a constraint is added 
    902927        # before allow to add another constraint 
    903928        for item in self.constraints_list: 
     
    913938                model = item.param_cbox.GetClientData( 
    914939                                        item.param_cbox.GetCurrentSelection()) 
    915                 if model != None: 
     940                if model is not None: 
    916941                    msg = " Enter a constraint for %s.%s! " % (model.name, 
    917942                                        item.param_cbox.GetString(0)) 
     
    920945                wx.PostEvent(self.parent.parent, StatusEvent(status=msg)) 
    921946                return 
    922         ## some model or parameters can be constrained 
     947        # some model or parameters can be constrained 
    923948        self._show_constraint() 
    924949        self.FitInside() 
     
    9801005    def on_set_focus(self, event=None): 
    9811006        """ 
    982         The  derivative class is on focus if implemented 
     1007        The derivative class is on focus if implemented 
    9831008        """ 
    9841009        if self.parent is not None: 
     
    9951020        cbox.Append(name, value) 
    9961021    cbox.SetStringSelection(selected) 
     1022 
     1023 
     1024class SimFitPageState: 
     1025    """ 
     1026    State of the simultaneous fit page for saving purposes 
     1027    """ 
     1028 
     1029    def __init__(self): 
     1030        # Sim Fit Page Number 
     1031        self.fit_page_no = None 
     1032        # Select all data 
     1033        self.select_all = False 
     1034        # Data sets sent to fit page 
     1035        self.model_list = [] 
     1036        # Data sets to be fit 
     1037        self.model_to_fit = [] 
     1038        # Number of constraints 
     1039        self.no_constraint = 0 
     1040        # Dictionary of constraints 
     1041        self.constraint_dict = {} 
     1042        # List of constraints 
     1043        self.constraints_list = [] 
     1044 
     1045    def load_from_save_state(self, fit): 
     1046        """ 
     1047        Load in a simultaneous/constrained fit from a save state 
     1048        :param fit: Fitpanel object 
     1049        :return: None 
     1050        """ 
     1051 
     1052        model_map = {} 
     1053        if fit.fit_panel.sim_page is None: 
     1054            fit.fit_panel.add_sim_page() 
     1055        sim_page = fit.fit_panel.sim_page 
     1056 
     1057        # Process each model and associate old M# with new M# 
     1058        i = 0 
     1059        for model in sim_page.model_list: 
     1060            model_id = self._format_id(model[1].keys()[0]) 
     1061            for saved_model in self.model_list: 
     1062                save_id = saved_model.pop('name') 
     1063                saved_model['name'] = save_id 
     1064                save_id = self._format_id(save_id) 
     1065                if save_id == model_id: 
     1066                    model_map[saved_model.pop('fit_page_source')] = \ 
     1067                        model[3].name 
     1068                    check = bool(saved_model.pop('checked')) 
     1069                    sim_page.model_list[i][0].SetValue(check) 
     1070                    break 
     1071            i += 1 
     1072        sim_page.check_model_name(None) 
     1073 
     1074        if len(self.constraints_list) > 0: 
     1075            sim_page.hide_constraint.SetValue(False) 
     1076            sim_page.show_constraint.SetValue(True) 
     1077            sim_page._display_constraint(None) 
     1078 
     1079        for index, item in enumerate(self.constraints_list): 
     1080            model_cbox = item.pop('model_cbox') 
     1081            if model_cbox != "": 
     1082                constraint_value = item.pop('constraint') 
     1083                param = item.pop('param_cbox') 
     1084                equality = item.pop('egal_txt') 
     1085                for key, value in model_map.iteritems(): 
     1086                    model_cbox.replace(key, value) 
     1087                    constraint_value.replace(key, value) 
     1088 
     1089                sim_page.constraints_list[index][0].SetValue(model_cbox) 
     1090                sim_page._on_select_model(None) 
     1091                sim_page.constraints_list[index][1].SetValue(param) 
     1092                sim_page.constraints_list[index][2].SetLabel(equality) 
     1093                sim_page.constraints_list[index][3].SetValue(constraint_value) 
     1094                sim_page._on_add_constraint(None) 
     1095 
     1096    def _format_id(self, original_id): 
     1097        original_id = original_id.rstrip('1234567890.') 
     1098        new_id_list = original_id.split() 
     1099        new_id = ' '.join(new_id_list) 
     1100        return new_id 
Note: See TracChangeset for help on using the changeset viewer.