Changeset 95eef00 in sasview for src/sas/sasgui
- Timestamp:
- Oct 7, 2016 2:05:57 PM (8 years ago)
- 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. - Location:
- src/sas/sasgui
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
src/sas/sasgui/guiframe/gui_manager.py
re6de6b8 r95eef00 1334 1334 self._applications_menu_name = name 1335 1335 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 1336 1343 def _add_help_menu(self): 1337 1344 """ … … 1339 1346 tutorial PDF and documentation pages. 1340 1347 """ 1341 # Help menu1342 1348 self._help_menu = wx.Menu() 1343 style = self.__gui_style & GUIFRAME.WELCOME_PANEL_ON1344 1349 1345 1350 wx_id = wx.NewId() 1346 1351 self._help_menu.Append(wx_id, '&Documentation', '') 1347 1352 wx.EVT_MENU(self, wx_id, self._onSphinxDocs) 1348 self._help_menu.AppendSeparator()1349 1353 1350 1354 if config._do_tutorial and (IS_WIN or sys.platform == 'darwin'): … … 1352 1356 self._help_menu.Append(wx_id, '&Tutorial', 'Software tutorial') 1353 1357 wx.EVT_MENU(self, wx_id, self._onTutorial) 1354 self._help_menu.AppendSeparator()1355 1356 1358 1357 1359 if config._do_acknowledge: … … 1359 1361 self._help_menu.Append(wx_id, '&Acknowledge', 'Acknowledging SasView') 1360 1362 wx.EVT_MENU(self, wx_id, self._onAcknowledge) 1361 self._help_menu.AppendSeparator()1362 1363 1363 1364 1364 if config._do_aboutbox: … … 1367 1367 self._help_menu.Append(wx_id, '&About', 'Software information') 1368 1368 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) 1371 1374 1372 1375 # Checking for updates -
src/sas/sasgui/guiframe/media/data_formats_help.rst
r280f929 r48b8f6d 10 10 ============ 11 11 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. 12 SasView 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. 16 13 17 1D Formats SANS18 -------------- -14 1D SAS Formats 15 -------------- 19 16 20 SasView will read files with 2 to 4 columns of numbers in the following order:17 SasView will read ASCII ('text') files with 2 to 4 columns of numbers in the following order: 21 18 22 Q, I(Q), (dI(Q), dQ(Q))19 *Q, I(Q), ( dI(Q), dQ(Q) )* 23 20 24 where dQ(Q) is the instrumental resolution in Qand assumed to have originated21 where *dQ(Q)* is the instrumental resolution in *Q* and assumed to have originated 25 22 from pinhole geometry. 26 23 27 24 Numbers can be separated by spaces or commas. 28 25 29 SasView recognises the following file extensions :26 SasView recognises the following file extensions which are not case-sensitive: 30 27 31 28 * .TXT … … 34 31 * .XML (in canSAS format v1.0 and 1.1) 35 32 36 If using CSV output from, for example, a spreadsheet, ensure that it is not 37 using commas as delimiters for thousands. 33 If using CSV output from, for example, a spreadsheet, ensure that it is not using commas as delimiters for thousands. 34 35 The 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. 38 36 39 37 For a description of the CanSAS/SASXML format see: 40 38 http://www.cansas.org/formats/canSAS1d/1.1/doc/ 41 39 40 For a description of the ISIS 1D format see: 41 http://www.isis.stfc.ac.uk/instruments/loq/software/colette-ascii-file-format-descriptions9808.pdf 42 43 For a description of the NXcanSAS format see: 44 http://cansas-org.github.io/NXcanSAS/classes/contributed_definitions/NXcanSAS.html 45 46 All the above formats are written by the `Mantid Framework <http://www.mantidproject.org/>`_. 47 42 48 For a description of the NIST 1D format see: 43 49 http://danse.chem.utk.edu/trac/wiki/NCNROutput1D_IQ 44 50 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.pdf51 For a description of the BSL/OTOKO format see: 52 http://www.diamond.ac.uk/Beamlines/Soft-Condensed-Matter/small-angle/SAXS-Software/CCP13/BSL.html 47 53 48 54 .. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 49 55 50 2D Formats SANS51 -------------- -56 2D SAS Formats 57 -------------- 52 58 53 SasView will only read files in the NIST 2D format with the extensions 54 .ASC or .DAT 59 SasView 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/>`_. 55 60 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. 61 Most 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 63 The 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. 58 64 59 65 For a description of the NIST 2D format see: 60 66 http://danse.chem.utk.edu/trac/wiki/NCNROutput1D_2DQxQy 61 67 62 .. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 68 For a description of the NXcanSAS format see: 69 http://cansas-org.github.io/NXcanSAS/classes/contributed_definitions/NXcanSAS.html 63 70 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) 71 For a description of the BSL/OTOKO format see: For a description of the BSL/OTOKO format see: 72 http://www.diamond.ac.uk/Beamlines/Soft-Condensed-Matter/small-angle/SAXS-Software/CCP13/BSL.html 79 73 80 74 81 75 .. ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ 82 76 83 .. note:: This help document was last changed by Wim Bouwman, 05Oct2016 77 1D SESANS Format 78 ---------------- 79 80 SasView 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 82 The 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 84 Following 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 890 890 891 891 892 def on_remove(self, event ):892 def on_remove(self, event, msg=""): 893 893 """ 894 894 Get a list of item checked and remove them from the treectrl 895 895 Ask the parent to remove reference to this item 896 896 """ 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." 899 900 msg_box = wx.MessageDialog(None, msg, 'Warning', wx.OK|wx.CANCEL) 900 901 if msg_box.ShowModal() != wx.ID_OK: 901 return 902 return True 902 903 903 904 data_to_remove, theory_to_remove, _ = self.set_data_helper() -
src/sas/sasgui/perspectives/fitting/fitpanel.py
r05228b0 re6de6b8 10 10 11 11 from sas.sasgui.guiframe.panel_base import PanelBase 12 from sas.sasgui.guiframe.events import PanelOnFocusEvent 13 from sas.sasgui.guiframe.events import StatusEvent 12 from sas.sasgui.guiframe.events import PanelOnFocusEvent, StatusEvent 14 13 from sas.sasgui.guiframe.dataFitting import check_data_validity 14 from sas.sasgui.perspectives.fitting.simfitpage import SimultaneousFitPage 15 15 16 16 import basepage … … 18 18 _BOX_WIDTH = 80 19 19 20 20 21 class FitPanel(nb, PanelBase): 21 22 """ … … 26 27 27 28 """ 28 # #Internal name for the AUI manager29 # Internal name for the AUI manager 29 30 window_name = "Fit panel" 30 # #Title to appear on top of the window31 # Title to appear on top of the window 31 32 window_caption = "Fit Panel " 32 33 CENTER_PANE = True … … 40 41 wx.CLIP_CHILDREN) 41 42 PanelBase.__init__(self, parent) 42 # self.SetWindowStyleFlag(style=nb.FNB_FANCY_TABS)43 # self.SetWindowStyleFlag(style=nb.FNB_FANCY_TABS) 43 44 self._manager = manager 44 45 self.parent = parent 45 46 self.event_owner = None 46 # dictionary of miodel {model class name, model class}47 # dictionary of miodel {model class name, model class} 47 48 self.menu_mng = models.ModelManager() 48 49 self.model_list_box = self.menu_mng.get_model_list() 49 # pageClosedEvent = nb.EVT_FLATNOTEBOOK_PAGE_CLOSING50 # pageClosedEvent = nb.EVT_FLATNOTEBOOK_PAGE_CLOSING 50 51 self.model_dictionary = self.menu_mng.get_model_dictionary() 51 52 self.pageClosedEvent = wx.aui.EVT_AUINOTEBOOK_PAGE_CLOSE 52 53 53 54 self.Bind(self.pageClosedEvent, self.on_close_page) 54 # #save the title of the last page tab added55 # save the title of the last page tab added 55 56 self.fit_page_name = {} 56 # #list of existing fit page57 # list of existing fit page 57 58 self.opened_pages = {} 58 # index of fit page59 # index of fit page 59 60 self.fit_page_index = 0 60 # index of batch page61 # index of batch page 61 62 self.batch_page_index = 0 62 # page of simultaneous fit63 # page of simultaneous fit 63 64 self.sim_page = None 64 65 self.batch_page = None 65 # #get the state of a page66 # get the state of a page 66 67 self.Bind(basepage.EVT_PAGE_INFO, self._onGetstate) 67 68 self.Bind(basepage.EVT_PREVIOUS_STATE, self._onUndo) … … 80 81 """ 81 82 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 85 90 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 108 104 return doc 109 105 … … 179 175 def get_state(self): 180 176 """ 181 177 return the state of the current selected page 182 178 """ 183 179 pos = self.GetSelection() … … 191 187 """ 192 188 193 # get number of pages189 # get number of pages 194 190 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. 196 192 while (nop > 0): 197 # delete the first page until no page exists193 # delete the first page until no page exists 198 194 page = self.GetPage(0) 199 195 if self._manager.parent.panel_on_focus == page: … … 201 197 self._close_helper(selected_page=page) 202 198 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 206 201 self.fit_page_name = {} 207 # # list of existing fit page202 # Clear list of opened pages 208 203 self.opened_pages = {} 204 self.fit_page_index = 0 205 self.batch_page_index = 0 209 206 210 207 def set_state(self, state): … … 215 212 if state is not None: 216 213 for uid, panel in self.opened_pages.iteritems(): 217 # Don't return any panel is the exact same page is created214 # Don't return any panel is the exact same page is created 218 215 if uid == panel.uid and panel.data == state.data: 219 216 # the page is still opened … … 223 220 if not page_is_opened: 224 221 if state.data.__class__.__name__ != 'list': 225 # To support older state file format222 # To support older state file format 226 223 list_data = [state.data] 227 224 else: 228 # Todo: need new file format for the list225 # Todo: need new file format for the list 229 226 list_data = state.data 230 227 panel = self._manager.add_fit_page(data=list_data) … … 241 238 Clear and close all panels, used by guimanager 242 239 """ 243 244 #close all panels only when svs file opened 240 # close all panels only when svs file opened 245 241 self.close_all() 246 242 self._manager.mypanels = [] 243 self.sim_page = None 244 self.batch_page = None 247 245 248 246 def on_close_page(self, event=None): … … 253 251 selected_page = self.GetPage(self.GetSelection()) 254 252 if nbr_page == 1: 255 if selected_page.get_data() ==None:253 if selected_page.get_data() is not None: 256 254 if event is not None: 257 255 event.Veto() … … 271 269 272 270 if data is None: 273 # the fitpanel exists and only the initial fit page is open274 # with no selected data271 # the fitpanel exists and only the initial fit page is open 272 # with no selected data 275 273 return 276 274 if data.id == deleted_data.id: … … 284 282 285 283 :param manager: instance of plugin fitting 286 287 284 """ 288 285 self._manager = manager … … 333 330 else: 334 331 self.batch_page = SimultaneousFitPage(self, batch_on=True, 335 332 page_finder=page_finder) 336 333 self.batch_page.window_caption = caption 337 334 self.batch_page.window_name = caption … … 346 343 add an empty page 347 344 """ 348 """349 345 if self.batch_on: 350 346 from batchfitpage import BatchFitPage 351 panel = BatchFitPage(parent=self)352 #Increment index of batch page353 self.batch_page_index += 1354 index = self.batch_page_index355 else:356 """357 from fitpage import FitPage358 from batchfitpage import BatchFitPage359 if self.batch_on:360 347 panel = BatchFitPage(parent=self) 361 348 self.batch_page_index += 1 … … 363 350 panel.set_index_model(self.batch_page_index) 364 351 else: 365 #Increment index of fit page 352 # Increment index of fit page 353 from fitpage import FitPage 366 354 panel = FitPage(parent=self) 367 355 self.fit_page_index += 1 … … 441 429 page = None 442 430 for p in self.opened_pages.values(): 443 # check if there is an empty page to fill up431 # check if there is an empty page to fill up 444 432 if not check_data_validity(p.get_data()) and p.batch_on: 445 433 446 # make sure data get placed in 1D empty tab if data is 1D447 # else data get place on 2D tab empty tab434 # make sure data get placed in 1D empty tab if data is 1D 435 # else data get place on 2D tab empty tab 448 436 enable2D = p.get_view_mode() 449 437 if (data.__class__.__name__ == "Data2D" and enable2D)\ … … 458 446 data_type = dlg.get_data() 459 447 dlg.Destroy() 460 if page 448 if page is None: 461 449 page = self.add_empty_page() 462 450 if data_type == 1: 463 # user has selected only data1D451 # user has selected only data1D 464 452 page.fill_data_combobox(data_1d_list) 465 453 elif data_type == 2: 466 454 page.fill_data_combobox(data_2d_list) 467 455 else: 468 # the batch analysis is canceled456 # the batch analysis is canceled 469 457 dlg.Destroy() 470 458 return None … … 503 491 try: 504 492 data = data_list[0] 505 except :493 except Exception: 506 494 # for 'fitv' files 507 495 data_list = [data] … … 511 499 return None 512 500 for page in self.opened_pages.values(): 513 # check if the selected data existing in the fitpanel501 # check if the selected data existing in the fitpanel 514 502 pos = self.GetPageIndex(page) 515 503 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 1D517 # else data get place on 2D tab empty tab504 # make sure data get placed in 1D empty tab if data is 1D 505 # else data get place on 2D tab empty tab 518 506 enable2D = page.get_view_mode() 519 507 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): 521 509 page.batch_on = self.batch_on 522 510 page._set_save_flag(not page.batch_on) 523 511 page.fill_data_combobox(data_list) 524 # caption = "FitPage" + str(self.fit_page_index)512 # caption = "FitPage" + str(self.fit_page_index) 525 513 self.SetPageText(pos, page.window_caption) 526 514 self.SetSelection(pos) 527 515 return page 528 # create new page and add data516 # create new page and add data 529 517 page = self.add_empty_page() 530 518 pos = self.GetPageIndex(page) … … 574 562 Delete the given page from the notebook 575 563 """ 576 # remove hint page577 # if selected_page == self.hint_page:564 # remove hint page 565 # if selected_page == self.hint_page: 578 566 # return 579 # #removing sim_page567 # removing sim_page 580 568 if selected_page == self.sim_page: 581 569 self._manager.sim_page = None … … 584 572 self._manager.batch_page = None 585 573 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 594 575 state = selected_page.createMemento() 595 576 page_finder = self._manager.get_page_finder() 596 # #removing fit page577 # removing fit page 597 578 data = selected_page.get_data() 598 # Don' t remove plot for 2D579 # Don' t remove plot for 2D 599 580 flag = True 600 581 if data.__class__.__name__ == 'Data2D': 601 582 flag = False 602 583 if selected_page in page_finder: 603 # Delete the name of the page into the list of open page584 # Delete the name of the page into the list of open page 604 585 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 607 587 if flag and selected_page.uid == uid: 608 588 self._manager.remove_plot(uid, theory=False) … … 610 590 del page_finder[selected_page] 611 591 612 # Delete the name of the page into the list of open page592 # Delete the name of the page into the list of open page 613 593 for uid, list in self.opened_pages.iteritems(): 614 # Don't return any panel is the exact same page is created594 # Don't return any panel is the exact same page is created 615 595 if selected_page.uid == uid: 616 596 del self.opened_pages[selected_page.uid] 617 597 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 619 599 try: 620 600 self.sim_page.draw_page() 621 601 except: 622 # #that page is already deleted no need to remove check box on623 # #non existing page602 # that page is already deleted no need to remove check box on 603 # non existing page 624 604 pass 625 605 try: 626 606 self.batch_page.draw_page() 627 607 except: 628 # #that page is already deleted no need to remove check box on629 # #non existing page608 # that page is already deleted no need to remove check box on 609 # non existing page 630 610 pass -
src/sas/sasgui/perspectives/fitting/fitting.py
r286c757 rff3f5821 593 593 : param datainfo: data 594 594 """ 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): 597 598 state = state.clone() 598 # store fitting state in temp_state599 599 self.temp_state.append(state) 600 elif isinstance(state, SimFitPageState): 601 state.load_from_save_state(self) 600 602 else: 601 603 self.temp_state = [] -
src/sas/sasgui/perspectives/fitting/pagestate.py
r6c382da re6de6b8 2 2 Class that holds a fit page state 3 3 """ 4 # TODO: Refactor code so we don't need to use getattr/setattr4 # TODO: Refactor code so we don't need to use getattr/setattr 5 5 ################################################################################ 6 # This software was developed by the University of Tennessee as part of the7 # 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. 9 9 # 10 # See the license text in license.txt10 # See the license text in license.txt 11 11 # 12 # copyright 2009, University of Tennessee12 # copyright 2009, University of Tennessee 13 13 ################################################################################ 14 14 import time … … 30 30 from sas.sascalc.dataloader.readers.cansas_reader import Reader as CansasReader 31 31 from 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 32 from sas.sascalc.dataloader.data_info import Data2D, Collimation, Detector 33 from sas.sascalc.dataloader.data_info import Process, Aperture 34 # Information to read/write state as xml 38 35 FITTING_NODE_NAME = 'fitting_plug_in' 39 36 CANSAS_NS = "cansas1d/1.0" … … 123 120 try: 124 121 return node.get(item[0]).strip() == "True" 125 126 122 except: 127 123 return None … … 146 142 """ 147 143 self.file = None 148 # Time of state creation144 # Time of state creation 149 145 self.timestamp = time.time() 150 # #Data member to store the dispersion object created146 # Data member to store the dispersion object created 151 147 self._disp_obj_dict = {} 152 # ------------------------153 # Data used for fitting148 # ------------------------ 149 # Data used for fitting 154 150 self.data = data 155 151 # model data 156 152 self.theory_data = None 157 # Is 2D153 # Is 2D 158 154 self.is_2D = False 159 155 self.images = None 160 156 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 162 159 self.is_data = None 163 160 self.data_name = "" … … 172 169 self.data_group_id = self.data.group_id 173 170 174 # # reset True change the state of exsiting button171 # reset True change the state of existing button 175 172 self.reset = False 176 173 … … 180 177 self.model = model 181 178 self.m_name = None 182 # list of process done to model179 # list of process done to model 183 180 self.process = [] 184 # fit page manager181 # fit page manager 185 182 self.manager = None 186 # Store the parent of this panel parent183 # Store the parent of this panel parent 187 184 # For this application fitpanel is the parent 188 185 self.parent = parent 189 186 # Event_owner is the owner of model event 190 187 self.event_owner = None 191 # #page name188 # page name 192 189 self.page_name = "" 193 190 # Contains link between model, all its parameters, and panel organization … … 196 193 self.str_parameters = [] 197 194 # Contains list of parameters that cannot be fitted and reference to 198 # panel objects195 # panel objects 199 196 self.fixed_param = [] 200 197 # Contains list of parameters with dispersity and reference to 201 # panel objects198 # panel objects 202 199 self.fittable_param = [] 203 # #orientation parameters200 # orientation parameters 204 201 self.orientation_params = [] 205 # #orientation parameters for gaussian dispersity202 # orientation parameters for gaussian dispersity 206 203 self.orientation_params_disp = [] 207 # #smearer info204 # smearer info 208 205 self.smearer = None 209 206 self.smear_type = None … … 214 211 self.dxl = None 215 212 self.dxw = None 216 # list of dispersion parameters213 # list of dispersion parameters 217 214 self.disp_list = [] 218 215 if self.model is not None: … … 223 220 self.weights = {} 224 221 225 # contains link between a model and selected parameters to fit222 # contains link between a model and selected parameters to fit 226 223 self.param_toFit = [] 227 # #dictionary of model type and model class224 # dictionary of model type and model class 228 225 self.model_list_box = None 229 # #save the state of the context menu226 # save the state of the context menu 230 227 self.saved_states = {} 231 # #save selection of combobox228 # save selection of combobox 232 229 self.formfactorcombobox = None 233 230 self.categorycombobox = None 234 231 self.structurecombobox = None 235 232 236 # #radio box to select type of model237 # self.shape_rbutton = False238 # self.shape_indep_rbutton = False239 # self.struct_rbutton = False240 # self.plugin_rbutton = False241 # #the indice of the current selection233 # 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 242 239 self.disp_box = 0 243 # #Qrange244 # #Q range240 # Qrange 241 # Q range 245 242 self.qmin = 0.001 246 243 self.qmax = 0.1 247 # reset data range244 # reset data range 248 245 self.qmax_x = None 249 246 self.qmin_x = None … … 253 250 self.multi_factor = None 254 251 self.magnetic_on = False 255 # #enable smearering state252 # enable smearering state 256 253 self.enable_smearer = False 257 254 self.disable_smearer = True … … 263 260 self.dI_sqrdata = False 264 261 self.dI_idata = False 265 # #disperity selection262 # disperity selection 266 263 self.enable_disp = False 267 264 self.disable_disp = True 268 265 269 # #state of selected all check button266 # state of selected all check button 270 267 self.cb1 = False 271 # #store value of chisqr268 # store value of chisqr 272 269 self.tcChi = None 273 270 … … 293 290 obj.structurecombobox = self.structurecombobox 294 291 295 # obj.shape_rbutton = self.shape_rbutton296 # obj.shape_indep_rbutton = self.shape_indep_rbutton297 # obj.struct_rbutton = self.struct_rbutton298 # obj.plugin_rbutton = self.plugin_rbutton292 # 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 299 296 300 297 obj.manager = self.manager … … 381 378 382 379 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 385 384 rep += "is data : %s\n" % self.is_data 386 385 rep += "data's name : %s\n" % self.data_name 387 386 rep += "data's id : %s\n" % self.data_id 388 if self.model !=None:387 if self.model is not None: 389 388 m_name = self.model.__class__.__name__ 390 389 if m_name == 'Model': … … 397 396 rep += "model type (Category) selected: %s\n" % self.categorycombobox 398 397 rep += "data : %s\n" % str(self.data) 399 rep += "Plotting Range: min: %s, max: %s, steps: %s\n" % (str(self.qmin),400 398 rep += "Plotting Range: min: %s, max: %s, steps: %s\n" % \ 399 (str(self.qmin),str(self.qmax), str(self.npts)) 401 400 rep += "Dispersion selection : %s\n" % str(self.disp_box) 402 401 rep += "Smearing enable : %s\n" % str(self.enable_smearer) … … 414 413 415 414 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) 417 416 rep += "Value of Chisqr : %s\n" % str(self.tcChi) 418 417 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) 420 419 rep += "dq_l : %s\n" % self.dq_l 421 420 rep += "dq_r : %s\n" % self.dq_r … … 434 433 if not self.is_2D: 435 434 for item in self.parameters: 436 if not itemin self.orientation_params:435 if item not in self.orientation_params: 437 436 temp_parameters.append(item) 438 437 for item in self.fittable_param: 439 if not itemin self.orientation_params_disp:438 if item not in self.orientation_params_disp: 440 439 temp_fittable_param.append(item) 441 440 else: … … 443 442 temp_fittable_param = self.fittable_param 444 443 445 rep += "number parameters(self.parameters): %s\n" % len(temp_parameters) 444 rep += "number parameters(self.parameters): %s\n" % \ 445 len(temp_parameters) 446 446 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) 448 449 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) 450 452 rep = self._repr_helper(list=temp_fittable_param, rep=rep) 451 453 return rep … … 551 553 paramval_string += CENTRE % param + "\n" 552 554 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) 554 557 555 558 title_name = self._check_html_format(title_name) … … 632 635 element.appendChild(sub_element) 633 636 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. 637 641 638 642 Compatible with standalone writing, or appending to an 639 already existing XML document. In that case, the XML document 640 isrequired. 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. 641 645 642 646 :param file: file to write to 643 647 :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] 646 650 """ 647 651 from xml.dom.minidom import getDOMImplementation … … 691 695 element.setAttributeNode(attr) 692 696 top_element.appendChild(element) 697 693 698 # Inputs 694 699 inputs = newdoc.createElement("Attributes") … … 741 746 for item in LIST_OF_STATE_PARAMETERS: 742 747 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) 744 750 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) 745 800 746 801 # Save the file … … 809 864 :param file: .fitv file 810 865 :param node: node of a XML document to read from 811 812 866 """ 813 867 if file is not None: … … 816 870 raise RuntimeError, msg 817 871 818 if node.get('version') and node.get('version') == '1.0':872 if node.get('version') and node.get('version') == '1.0': 819 873 820 874 # Get file name … … 862 916 value = cls.type 863 917 except Exception: 864 logging.error("unable to load distribution %r for %s"865 918 base = "unable to load distribution %r for %s" 919 logging.error(base % (value, parameter)) 866 920 continue 867 921 _disp_obj_dict = getattr(self, varname) … … 960 1014 self.cansas = cansas 961 1015 self.state = None 1016 # batch fitting params for saving 1017 self.batchfit_params = [] 962 1018 963 1019 def get_state(self): … … 984 1040 raise RuntimeError, "The cansas writer expects a Data2D instance" 985 1041 1042 title = "cansas1d/%s" % self.version 1043 title += "http://svn.smallangles.net/svn/canSAS/1dwg/trunk/cansas1d.xsd" 986 1044 doc = xml.dom.minidom.Document() 987 1045 main_node = doc.createElement("SASroot") 988 1046 main_node.setAttribute("version", self.version) 989 1047 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) 993 1051 994 1052 doc.appendChild(main_node) … … 999 1057 write_node(doc, entry_node, "Title", datainfo.title) 1000 1058 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__) 1002 1061 for item in datainfo.run: 1003 1062 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: 1005 1065 runname = {'name': datainfo.run_name[item]} 1006 1066 write_node(doc, entry_node, "Run", item, runname) … … 1219 1279 1220 1280 :param entry: XML node to read from 1221 1222 1281 :return: PageState object 1223 1282 """ … … 1228 1287 nodes = entry.xpath('ns:%s' % FITTING_NODE_NAME, 1229 1288 namespaces={'ns': CANSAS_NS}) 1230 if nodes != []:1289 if nodes: 1231 1290 # Create an empty state 1232 1291 state = PageState() … … 1238 1297 1239 1298 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 1240 1339 1241 1340 def _parse_save_state_entry(self, dom): … … 1298 1397 data_info.notes.append(note_value) 1299 1398 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 1301 1401 self.errors.append(err_mess) 1302 1402 logging.error(err_mess) … … 1308 1408 1309 1409 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}) 1315 1419 for item in nodes: 1316 1420 try: … … 1320 1424 data_info.sample.details.append(detail_value) 1321 1425 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 1323 1428 self.errors.append(err_mess) 1324 1429 logging.error(err_mess) 1325 1430 1326 1431 # 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) 1330 1438 1331 1439 # Orientation (as a vector) … … 1461 1569 process.term.append(term_attr) 1462 1570 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 1464 1573 self.errors.append(err_mess) 1465 1574 logging.error(err_mess) … … 1476 1585 nodes = dom.xpath('ns:SASdata', namespaces={'ns': CANSAS_NS}) 1477 1586 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" 1479 1589 1480 1590 for entry in nodes: … … 1488 1598 value_list = [] 1489 1599 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] 1491 1602 if len(value_list) < 2: 1492 1603 setattr(data_info, item[0], None) … … 1498 1609 def _read_cansas(self, path): 1499 1610 """ 1500 Load data and P(r)information from a CanSAS XML file.1611 Load data and fitting information from a CanSAS XML file. 1501 1612 1502 1613 :param path: file path 1503 1504 1614 :return: Data1D object if a single SASentry was found, 1505 1615 or a list of Data1D objects if multiple entries were found, 1506 1616 or None of nothing was found 1507 1508 1617 :raise RuntimeError: when the file can't be opened 1509 1618 :raise ValueError: when the length of the data vectors are inconsistent 1510 1511 1619 """ 1512 1620 output = [] 1621 simfitstate = None 1513 1622 basename = os.path.basename(path) 1514 1623 root, extension = os.path.splitext(basename) … … 1516 1625 try: 1517 1626 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': 1524 1628 tree = etree.parse(path, parser=etree.ETCompatXMLParser()) 1525 1629 # 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 1527 1632 root = tree.getroot() 1528 1633 entry_list = root.xpath('ns:SASentry', 1529 1634 namespaces={'ns': CANSAS_NS}) 1635 name_map = {} 1530 1636 for entry in entry_list: 1531 1637 try: … … 1535 1641 fitstate = self._parse_state(entry) 1536 1642 1537 # state could be None when .svs file is loaded1538 # in this case, skip appending to output1539 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: 1540 1646 sas_entry.meta_data['fitstate'] = fitstate 1541 1647 sas_entry.filename = fitstate.file 1542 1648 output.append(sas_entry) 1649 1543 1650 else: 1544 1651 self.call_back(format=ext) … … 1580 1687 name = original_fname 1581 1688 state.data.group_id = name 1582 # store state in fitting1689 # store state in fitting 1583 1690 self.call_back(state=state, 1584 1691 datainfo=output[ind], format=ext) 1585 1692 self.state = state 1693 simfitstate = self._parse_simfit_state(entry) 1694 if simfitstate is not None: 1695 self.call_back(state=simfitstate) 1696 1586 1697 return output 1587 1698 except: … … 1599 1710 """ 1600 1711 # Sanity check 1601 if self.cansas == True:1712 if self.cansas: 1602 1713 # Add fitting information to the XML document 1603 1714 doc = self.write_toXML(datainfo, fitstate) … … 1611 1722 fd.close() 1612 1723 1613 def write_toXML(self, datainfo=None, state=None ):1724 def write_toXML(self, datainfo=None, state=None, batchfit=None): 1614 1725 """ 1615 1726 Write toXML, a helper for write(), … … 1619 1730 """ 1620 1731 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: 1623 1734 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) 1626 1746 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) 1641 1749 1642 1750 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) 1644 1753 1645 1754 return doc 1646 1647 # Simple html report templet1648 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> </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> </p>1666 <br>1667 <p class=MsoNormal><b><span ><center> <font size='4' > Graph1668 </font></span></center></b></p>1669 <p class=MsoNormal> </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> </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_state1701 new_state= pickle.load(file)1702 print "new state", new_state1703 #print "state", state1704 """1705 import bsddb1706 import pickle1707 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 9 9 from wx.lib.scrolledpanel import ScrolledPanel 10 10 11 from sas.sasgui.guiframe.events import StatusEvent 11 from sas.sasgui.guiframe.events import StatusEvent, PanelOnFocusEvent 12 12 from sas.sasgui.guiframe.panel_base import PanelBase 13 from sas.sasgui.guiframe.events import PanelOnFocusEvent14 13 from sas.sasgui.guiframe.utils import IdList 15 14 from sas.sasgui.guiframe.documentation_window import DocumentationWindow 16 15 17 # Control panel width16 # Control panel width 18 17 if sys.platform.count("darwin") == 0: 19 18 PANEL_WID = 420 … … 29 28 'model_cbox param_cbox egal_txt constraint btRemove sizer') 30 29 30 31 31 def get_fittableParam(model): 32 32 """ … … 47 47 return fittable_param 48 48 49 49 50 class SimultaneousFitPage(ScrolledPanel, PanelBase): 50 51 """ … … 53 54 two data members window_name and window_caption 54 55 """ 55 # #Internal name for the AUI manager56 window_name = " simultaneous Fit page"57 # #Title to appear on top of the window56 # Internal name for the AUI manager 57 window_name = "Simultaneous Fit Page" 58 # Title to appear on top of the window 58 59 window_caption = "Simultaneous Fit Page" 59 60 ID_DOC = wx.NewId() … … 74 75 self._ids = iter(self._id_pool) 75 76 self.SetupScrolling() 76 # #Font size77 # Font size 77 78 self.SetWindowVariant(variant=FONT_VARIANT) 78 79 self.uid = wx.NewId() 79 80 self.parent = parent 80 81 self.batch_on = batch_on 81 # #store page_finder82 # store page_finder 82 83 self.page_finder = page_finder 83 # #list containing info to set constraint84 # #look like self.constraint_dict[page_id]= page84 # list containing info to set constraint 85 # look like self.constraint_dict[page_id]= page 85 86 self.constraint_dict = {} 86 # #item list87 # #self.constraints_list=[combobox1, combobox2,=,textcrtl, button ]87 # item list 88 # self.constraints_list=[combobox1, combobox2,=,textcrtl, button ] 88 89 self.constraints_list = [] 89 # #list of current model90 # list of current model 90 91 self.model_list = [] 91 # # selected mdoel to fit92 self.model_to Fit = []93 # #Control the fit state92 # selected model to fit 93 self.model_to_fit = [] 94 # Control the fit state 94 95 self.fit_started = False 95 # #number of constraint96 # number of constraint 96 97 self.nb_constraint = 0 98 self.state = SimFitPageState() 97 99 self.model_cbox_left = None 98 100 self.model_cbox_right = None 99 # #draw page101 # draw page 100 102 self.define_page_structure() 101 103 self.draw_page() … … 107 109 """ 108 110 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) 119 121 self.SetSizer(self.vbox) 120 122 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 121 144 122 145 def draw_page(self): … … 131 154 # create blank list of constraints 132 155 self.model_list = [] 133 self.model_to Fit = []156 self.model_to_fit = [] 134 157 self.constraints_list = [] 135 158 self.constraint_dict = {} … … 144 167 145 168 #------------------------------------------------------- 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) 148 171 box_description = wx.StaticBox(self, wx.ID_ANY, "Fit Combinations") 149 172 boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL) … … 151 174 sizer_couples = wx.GridBagSizer(5, 5) 152 175 153 # This if statement should be obsolete and can be removed in version 4154 # Leave it here for now as no time to thoroughly test. However if no155 # fit page is found the menu item that calls this page is inactive156 # Nov. 22 2015 --PDB176 # 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 157 180 if len(self.page_finder) == 0: 158 181 msg = " No fit combinations are found! \n\n" … … 161 184 sizer_title.Add(wx.StaticText(self, wx.ID_ANY, msg)) 162 185 else: 163 # #store model186 # store model 164 187 self._store_model() 165 188 … … 171 194 wx.TOP | wx.BOTTOM | wx.EXPAND | wx.ADJUST_MINSIZE, border=5) 172 195 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 176 200 self._fill_sizer_model_list(sizer_couples) 177 201 178 202 boxsizer1.Add(sizer_title, flag=wx.TOP | wx.BOTTOM, border=5) 179 203 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() 182 206 183 207 #-------------------------------------------------------- 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 189 216 if len(self.page_finder) > 0: 190 # #draw the sizer containing constraint info217 # draw the sizer containing constraint info 191 218 if not self.batch_on: 192 219 self._fill_sizer_constraint() 193 # #draw fit button sizer220 # draw fit button sizer 194 221 self._fill_sizer_fit() 195 196 222 197 223 def _fill_sizer_model_list(self, sizer): … … 201 227 ix = 0 202 228 iy = 0 203 list = []204 229 sizer.Clear(True) 205 230 … … 209 234 new_name.SetForegroundColour(wx.WHITE) 210 235 sizer.Add(new_name, (iy, ix), (1, 1), 211 236 wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 15) 212 237 ix += 2 213 238 model_type = wx.StaticText(self, wx.ID_ANY, ' Model ') … … 215 240 model_type.SetForegroundColour(wx.WHITE) 216 241 sizer.Add(model_type, (iy, ix), (1, 1), 217 242 wx.EXPAND | wx.ADJUST_MINSIZE, 0) 218 243 ix += 1 219 244 data_used = wx.StaticText(self, wx.ID_ANY, ' Data ') … … 221 246 data_used.SetForegroundColour(wx.WHITE) 222 247 sizer.Add(data_used, (iy, ix), (1, 1), 223 248 wx.EXPAND | wx.ADJUST_MINSIZE, 0) 224 249 ix += 1 225 250 tab_used = wx.StaticText(self, wx.ID_ANY, ' FitPage ') … … 302 327 wx.PostEvent(self.parent.parent, StatusEvent(status=msg)) 303 328 304 self. sizer2.Clear(True)329 self.constraints_sizer.Clear(True) 305 330 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) 308 333 return 309 334 box_description = wx.StaticBox(self, wx.ID_ANY, "Fit Constraints") 310 box sizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL)335 box_sizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL) 311 336 sizer_title = wx.BoxSizer(wx.HORIZONTAL) 312 337 self.sizer_all_constraints = wx.BoxSizer(wx.HORIZONTAL) … … 338 363 339 364 self.btAdd = wx.Button(self, self.ID_ADD, 'Add') 340 self.btAdd.Bind(wx.EVT_BUTTON, self._on Add_constraint,365 self.btAdd.Bind(wx.EVT_BUTTON, self._on_add_constraint, 341 366 id=self.btAdd.GetId()) 342 367 self.btAdd.SetToolTipString("Add another constraint?") … … 344 369 345 370 text_hint = wx.StaticText(self, wx.ID_ANY, 346 "Example: [M0][param ter] = M1.parameter")371 "Example: [M0][parameter] = M1.parameter") 347 372 sizer_button.Add(text_hint, 0, 348 373 wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 10) … … 350 375 wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 10) 351 376 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) 361 385 362 386 def _fill_sizer_fit(self): … … 364 388 Draw fit button 365 389 """ 366 self. sizer3.Clear(True)390 self.run_fit_sizer.Clear(True) 367 391 box_description = wx.StaticBox(self, wx.ID_ANY, "Fit ") 368 392 boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL) 369 393 sizer_button = wx.BoxSizer(wx.HORIZONTAL) 370 394 371 # Fit button395 # Fit button 372 396 self.btFit = wx.Button(self, self.ID_FIT, 'Fit', size=wx.DefaultSize) 373 self.btFit.Bind(wx.EVT_BUTTON, self.on Fit, id=self.btFit.GetId())397 self.btFit.Bind(wx.EVT_BUTTON, self.on_fit, id=self.btFit.GetId()) 374 398 self.btFit.SetToolTipString("Perform fit.") 375 399 376 # General Help button400 # General Help button 377 401 self.btHelp = wx.Button(self, wx.ID_HELP, 'HELP') 378 402 self.btHelp.SetToolTipString("Simultaneous/Constrained Fitting help.") 379 self.btHelp.Bind(wx.EVT_BUTTON, self._on Help)380 381 # hint text on button line403 self.btHelp.Bind(wx.EVT_BUTTON, self._on_help) 404 405 # hint text on button line 382 406 if self.batch_on: 383 407 text = " Fit in Parallel all Data sets\n" … … 393 417 394 418 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 on Remove(self, event):419 self.run_fit_sizer.Add(boxsizer1, 0, wx.EXPAND | wx.ALL, 10) 420 421 def on_remove(self, event): 398 422 """ 399 423 Remove constraint fields … … 406 430 return 407 431 wx.CallAfter(self._remove_after, event.GetId()) 408 # self._onAdd_constraint(None)432 # self._onAdd_constraint(None) 409 433 410 434 def _remove_after(self, id): … … 416 440 self.constraints_list.remove(item) 417 441 self.nb_constraint -= 1 418 self. sizer2.Layout()442 self.constraints_sizer.Layout() 419 443 self.FitInside() 420 444 break 421 445 422 def on Fit(self, event):446 def on_fit(self, event): 423 447 """ 424 448 signal for fitting … … 435 459 flag = (self._manager.sim_page.uid == self.uid) 436 460 437 # #making sure all parameters content a constraint461 # making sure all parameters content a constraint 438 462 if not self.batch_on and self.show_constraint.GetValue(): 439 463 if not self._set_constraint(): 440 464 return 441 # #model was actually selected from this page to be fit442 if len(self.model_to Fit) >= 1:465 # model was actually selected from this page to be fit 466 if len(self.model_to_fit) >= 1: 443 467 self.manager._reset_schedule_problem(value=0) 444 468 for item in self.model_list: … … 456 480 msg = "Select at least one model check box to fit " 457 481 wx.PostEvent(self.parent.parent, StatusEvent(status=msg)) 482 self.set_state() 458 483 459 484 def _on_fit_complete(self): … … 467 492 """ 468 493 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: 471 498 event.Skip() 472 499 self.manager.stop_fit(self.uid) … … 485 512 self.btFit.Enable(True) 486 513 487 def _on Help(self, event):514 def _on_help(self, event): 488 515 """ 489 516 Bring up the simultaneous Fitting Documentation whenever the HELP … … 494 521 versions of Wx (before 2.9) and thus not the release version of 495 522 installers, the help comes up at the top level of the file as 496 web browser does not pass anything past the # to the browser when it is523 web browser does not pass anything past the # to the browser when it is 497 524 running "file:///...." 498 525 499 :param ev t: Triggers on clicking the help button526 :param event: Triggers on clicking the help button 500 527 """ 501 528 _TreeLocation = "user/sasgui/perspectives/fitting/fitting_help.html" … … 510 537 511 538 :param manager: instance of plugin fitting 512 513 539 """ 514 540 self.manager = manager … … 518 544 check all models names 519 545 """ 520 self.model_to Fit = []521 if self.cb1.GetValue() == True:546 self.model_to_fit = [] 547 if self.cb1.GetValue(): 522 548 for item in self.model_list: 523 549 if item[0].IsEnabled(): 524 550 item[0].SetValue(True) 525 self.model_to Fit.append(item)526 527 # #constraint info551 self.model_to_fit.append(item) 552 553 # constraint info 528 554 self._store_model() 529 555 if not self.batch_on: 530 # #display constraint fields556 # display constraint fields 531 557 if (self.show_constraint.GetValue() and 532 558 len(self.constraints_list) == 0): … … 538 564 539 565 if not self.batch_on: 540 # #constraint info566 # constraint info 541 567 self._hide_constraint() 542 568 … … 544 570 self.FitInside() 545 571 546 547 572 def check_model_name(self, event): 548 573 """ 549 574 Save information related to checkbox and their states 550 575 """ 551 self.model_toFit = [] 552 cbox = event.GetEventObject() 576 self.model_to_fit = [] 553 577 for item in self.model_list: 554 if item[0].GetValue() == True:555 self.model_to Fit.append(item)578 if item[0].GetValue(): 579 self.model_to_fit.append(item) 556 580 else: 557 if item in self.model_to Fit:558 self.model_to Fit.remove(item)581 if item in self.model_to_fit: 582 self.model_to_fit.remove(item) 559 583 self.cb1.SetValue(False) 560 584 561 # #display constraint fields562 if len(self.model_to Fit) >= 1:585 # display constraint fields 586 if len(self.model_to_fit) >= 1: 563 587 self._store_model() 564 588 if not self.batch_on and self.show_constraint.GetValue() and\ … … 567 591 self._show_constraint() 568 592 569 elif len(self.model_to Fit) < 1:570 # #constraint info593 elif len(self.model_to_fit) < 1: 594 # constraint info 571 595 self._hide_constraint() 572 596 573 597 self._update_easy_setup_cb() 574 # #set the value of the main check button575 if len(self.model_list) == len(self.model_to Fit):598 # set the value of the main check button 599 if len(self.model_list) == len(self.model_to_fit): 576 600 self.cb1.SetValue(True) 577 601 self.FitInside() … … 585 609 Update easy setup combobox on selecting a model 586 610 """ 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_to Fit]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] 591 615 setComboBoxItems(self.model_cbox_left, models) 592 616 setComboBoxItems(self.model_cbox_right, models) … … 595 619 if self.model_cbox_left.GetSelection() == wx.NOT_FOUND: 596 620 self.model_cbox_left.SetSelection(0) 597 self. sizer2.Layout()621 self.constraints_sizer.Layout() 598 622 599 623 def _store_model(self): … … 601 625 Store selected model 602 626 """ 603 if len(self.model_to Fit) < 1:604 return 605 for item in self.model_to Fit:627 if len(self.model_to_fit) < 1: 628 return 629 for item in self.model_to_fit: 606 630 model = item[3] 607 631 page_id = item[2] … … 612 636 Show fields to add constraint 613 637 """ 614 if len(self.model_to Fit) < 1:638 if len(self.model_to_fit) < 1: 615 639 msg = "Select at least 1 model to add constraint " 616 640 wx.PostEvent(self.parent.parent, StatusEvent(status=msg)) 617 # #hide button641 # hide button 618 642 self._hide_constraint() 619 643 return … … 632 656 """ 633 657 box_description = wx.StaticBox(self, wx.ID_ANY, "Easy Setup ") 634 box sizer = wx.StaticBoxSizer(box_description, wx.HORIZONTAL)658 box_sizer = wx.StaticBoxSizer(box_description, wx.HORIZONTAL) 635 659 sizer_constraint = wx.BoxSizer(wx.HORIZONTAL) 636 660 self.model_cbox_left = wx.ComboBox(self, wx.ID_ANY, style=wx.CB_READONLY) … … 650 674 651 675 for id, model in self.constraint_dict.iteritems(): 652 # #check if all parameters have been selected for constraint653 # #then do not allow add constraint on parameters676 # check if all parameters have been selected for constraint 677 # then do not allow add constraint on parameters 654 678 self.model_cbox_left.Append(str(model.name), model) 655 679 self.model_cbox_left.Select(0) 656 680 for id, model in self.constraint_dict.iteritems(): 657 # #check if all parameters have been selected for constraint658 # #then do not allow add constraint on parameters681 # check if all parameters have been selected for constraint 682 # then do not allow add constraint on parameters 659 683 self.model_cbox_right.Append(str(model.name), model) 660 box sizer.Add(self.model_cbox_left,684 box_sizer.Add(self.model_cbox_left, 661 685 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"), 663 687 # flag=wx.RIGHT | wx.EXPAND, border=5) 664 box sizer.Add(egal_txt, flag=wx.RIGHT | wx.EXPAND, border=5)665 box sizer.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, 666 690 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"), 668 692 # flag=wx.RIGHT | wx.EXPAND, border=5) 669 box sizer.Add((20, -1))670 box sizer.Add(self.set_button, flag=wx.RIGHT | wx.EXPAND, border=5)671 sizer_constraint.Add(box sizer, 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) 672 696 self.sizer_all_constraints.Insert(before=0, 673 697 item=sizer_constraint, … … 699 723 return 700 724 param_list = [] 701 param_list B= []725 param_list_b = [] 702 726 selection = self.model_cbox_left.GetCurrentSelection() 703 727 model_left = self.model_cbox_left.GetValue() 704 728 model = self.model_cbox_left.GetClientData(selection) 705 selection B= self.model_cbox_right.GetCurrentSelection()729 selection_b = self.model_cbox_right.GetCurrentSelection() 706 730 model_right = self.model_cbox_right.GetValue() 707 model B = self.model_cbox_right.GetClientData(selectionB)731 model_b = self.model_cbox_right.GetClientData(selection_b) 708 732 for id, dic_model in self.constraint_dict.iteritems(): 709 733 if model == dic_model: 710 734 param_list = self.page_finder[id].get_param2fit() 711 if model B== dic_model:712 param_list B= self.page_finder[id].get_param2fit()713 if len(param_list) > 0 and len(param_list B) > 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: 714 738 break 715 739 num_cbox = 0 … … 717 741 for param in param_list: 718 742 num_cbox += 1 719 if param in param_list B:743 if param in param_list_b: 720 744 item = self.constraints_list[-1] 721 745 item.model_cbox.SetStringSelection(model_left) … … 744 768 """ 745 769 Show constraint fields 770 :param dict: dictionary mapping constraint values 746 771 """ 747 772 self.btAdd.Show(True) … … 750 775 for id, model in self.constraint_dict.iteritems(): 751 776 nb_fit_param += len(self.page_finder[id].get_param2fit()) 752 # #Don't add anymore777 # Don't add anymore 753 778 if len(self.constraints_list) == nb_fit_param: 754 779 msg = "Cannot add another constraint. Maximum of number " … … 756 781 wx.PostEvent(self.parent.parent, StatusEvent(status=msg)) 757 782 self.sizer_constraints.Layout() 758 self. sizer2.Layout()783 self.constraints_sizer.Layout() 759 784 return 760 if len(self.model_to Fit) < 1:785 if len(self.model_to_fit) < 1: 761 786 msg = "Select at least 1 model to add constraint " 762 787 wx.PostEvent(self.parent.parent, StatusEvent(status=msg)) 763 788 self.sizer_constraints.Layout() 764 self. sizer2.Layout()789 self.constraints_sizer.Layout() 765 790 return 766 791 … … 771 796 model_cbox.Clear() 772 797 for id, model in self.constraint_dict.iteritems(): 773 # #check if all parameters have been selected for constraint774 # #then do not allow add constraint on parameters798 # check if all parameters have been selected for constraint 799 # then do not allow add constraint on parameters 775 800 model_cbox.Append(str(model.name), model) 776 801 wx.EVT_COMBOBOX(model_cbox, wx.ID_ANY, self._on_select_model) … … 789 814 # Remove button 790 815 #btRemove = wx.Button(self, self.ID_REMOVE, 'Remove') 791 bt Remove = wx.Button(self, self._ids.next(), 'Remove')792 bt Remove.Bind(wx.EVT_BUTTON, self.onRemove,793 id=bt Remove.GetId())794 bt Remove.SetToolTipString("Remove constraint.")795 bt Remove.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() 796 821 797 822 # Hid the add button, if it exists … … 804 829 sizer_constraint.Add(egal_txt, flag=wx.RIGHT | wx.EXPAND, border=5) 805 830 sizer_constraint.Add(constraint, flag=wx.RIGHT | wx.EXPAND, border=10) 806 sizer_constraint.Add(bt Remove, flag=wx.RIGHT | wx.EXPAND, border=10)831 sizer_constraint.Add(bt_remove, flag=wx.RIGHT | wx.EXPAND, border=10) 807 832 808 833 self.sizer_constraints.Insert(before=self.nb_constraint, … … 810 835 border=5) 811 836 c = ConstraintLine(model_cbox, param_cbox, egal_txt, 812 constraint, bt Remove, sizer_constraint)837 constraint, bt_remove, sizer_constraint) 813 838 self.constraints_list.append(c) 814 839 815 840 self.nb_constraint += 1 816 841 self.sizer_constraints.Layout() 817 self. sizer2.Layout()818 self.Layout 842 self.constraints_sizer.Layout() 843 self.Layout() 819 844 820 845 def _hide_constraint(self): … … 841 866 self.sizer_constraints.Clear(True) 842 867 self.sizer_constraints.Layout() 843 self. sizer2.Layout()844 self.Layout 868 self.constraints_sizer.Layout() 869 self.Layout() 845 870 self.FitInside() 846 871 847 872 def _on_select_model(self, event): 848 873 """ 849 fill combo xbox with list of parameters874 fill combo box with list of parameters 850 875 """ 851 876 if not self.constraints_list: 852 877 return 853 878 854 # #This way PC/MAC both work, instead of using event.GetClientData().879 # This way PC/MAC both work, instead of using event.GetClientData(). 855 880 model_cbox = self.constraints_list[-1].model_cbox 856 881 n = model_cbox.GetCurrentSelection() … … 867 892 param_cbox = self.constraints_list[-1].param_cbox 868 893 param_cbox.Clear() 869 # #insert only fittable paramaters894 # insert only fittable paramaters 870 895 for param in param_list: 871 896 param_cbox.Append(str(param), model) 872 897 param_cbox.Show(True) 873 898 874 bt Remove = self.constraints_list[-1].btRemove875 bt Remove.Show(True)899 bt_remove = self.constraints_list[-1].btRemove 900 bt_remove.Show(True) 876 901 self.btAdd.Show(True) 877 902 # self.Layout() … … 882 907 Store the appropriate constraint in the page_finder 883 908 """ 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() 888 913 889 914 if self.constraints_list: … … 891 916 self.constraints_list[-1].constraint.Show(True) 892 917 893 def _on Add_constraint(self, event):918 def _on_add_constraint(self, event): 894 919 """ 895 920 Add another line for constraint … … 899 924 wx.PostEvent(self.parent.parent, StatusEvent(status=msg)) 900 925 return 901 # #check that a constraint is added926 # check that a constraint is added 902 927 # before allow to add another constraint 903 928 for item in self.constraints_list: … … 913 938 model = item.param_cbox.GetClientData( 914 939 item.param_cbox.GetCurrentSelection()) 915 if model !=None:940 if model is not None: 916 941 msg = " Enter a constraint for %s.%s! " % (model.name, 917 942 item.param_cbox.GetString(0)) … … 920 945 wx.PostEvent(self.parent.parent, StatusEvent(status=msg)) 921 946 return 922 # #some model or parameters can be constrained947 # some model or parameters can be constrained 923 948 self._show_constraint() 924 949 self.FitInside() … … 980 1005 def on_set_focus(self, event=None): 981 1006 """ 982 The 1007 The derivative class is on focus if implemented 983 1008 """ 984 1009 if self.parent is not None: … … 995 1020 cbox.Append(name, value) 996 1021 cbox.SetStringSelection(selected) 1022 1023 1024 class 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.