Changeset 02098e3 in sasview
- Timestamp:
- Dec 8, 2015 11:09:13 AM (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, release_4.0.1, ticket-1009, ticket-1094-headless, ticket-1242-2d-resolution, ticket-1243, ticket-1249, ticket885, unittest-saveload
- Children:
- 50a77df
- Parents:
- 12e5cc8 (diff), 1c2bf90 (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. - Files:
-
- 6 deleted
- 27 edited
Legend:
- Unmodified
- Added
- Removed
-
.gitignore
rf0d720b r02098e3 24 24 build 25 25 26 /setup.cfg 27 26 28 /dist 27 29 **/build … … 30 32 **/test/logs 31 33 *.pyc 34 *.so 32 35 default_categories.json 33 36 … … 43 46 /docs/sphinx-docs/source/user/perspectives 44 47 45 default_categories.json 48 # test outputs 49 /test/pr_inversion/test/test_output.txt 50 /test/sasdataloader/test/plugins.zip 51 /test/sasdataloader/test/test_log.txt 52 -
sasview/README.txt
r9533593 r40c69b3 255 255 256 256 2.2- Installing from source 257 - Get the code from GitHub at https://github.com/SasView/sasview.git 258 for this release version use: https://github.com/SasView/sasview/releases 259 - run 'python setup.py install' under the 'sasview-x.x.x' folder 257 - Get the source code 258 - to follow the current development version from source control use 259 git clone https://github.com/SasView/sasview.git 260 git clone https://github.com/bumps/bumps.git 261 - to install a specific version 262 263 - Build, install and run a specific release 264 - make sure the requirements below are already installed 265 - retrieve the source from https://github.com/SasView/sasview/releases 266 - open a command line window in the 'sasview-x.x.x' directory 267 - run 'python setup.py install' 260 268 - run 'python sasview.py' under the 'sasview' folder. 261 269 270 - Build, install and run the current development version 271 - clone the source from git; also clone bumps, which is developed in parallel 272 git clone https://github.com/SasView/sasview.git 273 git clone https://github.com/bumps/bumps.git 274 - open a command line window in the 'sasview' directory 275 - run 'python setup.py build' 276 - run 'python run.py'; this runs from the source directories, so you 277 don't have to rebuild every time you make a change, unless you are 278 changing the C++ model files 279 262 280 - The following modules are required (version numbers are what are used 263 281 in the windows release build): -
sasview/sasview.py
r78f75d02 r85130cb 69 69 70 70 import wx 71 71 72 try: 72 73 logging.info("Wx version: %s" % wx.__version__) 73 74 except: 74 75 logging.error("Wx version: error reading version") 76 77 import wxcruft 78 wxcruft.call_later_fix() 79 #wxcruft.trace_new_id() 75 80 76 81 # The below will make sure that sasview application uses the matplotlib font -
sasview/setup_mac.py
r49cd712 re8e3e38 121 121 VERSION = sasviewver.__version__ 122 122 APPNAME = "SasView "+VERSION 123 DMGNAME = "SasView-"+VERSION 123 DMGNAME = "SasView-"+VERSION+"-MacOSX" 124 124 125 125 APP = ['sasview.py'] -
src/sas/guiframe/gui_toolbar.py
r79492222 r6f16e25 36 36 Implement toolbar for guiframe 37 37 """ 38 ID_BOOKMARK = wx.NewId() 38 39 def __init__(self, parent, *args, **kwds): 39 40 Tbar.__init__(self, parent, *args, **kwds) … … 133 134 Add default items in bookmark menu 134 135 """ 135 id = wx.NewId() 136 self._bookmark_menu.Append(id, 'Bookmark This Page State') 136 self._bookmark_menu.Append(self.ID_BOOKMARK, 'Bookmark This Page State') 137 137 self._bookmark_menu.AppendSeparator() 138 wx.EVT_MENU(self, id, self.on_bookmark)138 wx.EVT_MENU(self, self.ID_BOOKMARK, self.on_bookmark) 139 139 140 140 def on_bind_button(self): -
src/sas/guiframe/local_perspectives/plotting/Plotter1D.py
r098f3d2 r6f16e25 19 19 from sas.guiframe.events import StatusEvent 20 20 from sas.guiframe.events import PanelOnFocusEvent 21 from sas.guiframe.utils import PanelMenu 21 from sas.guiframe.utils import PanelMenu, IdList 22 22 from sas.guiframe.panel_base import PanelBase 23 23 from sas.guiframe.gui_style import GUIFRAME_ICON … … 35 35 """return the key of dictionary dic given the value""" 36 36 return [k for k, v in dic.iteritems() if v == val][0] 37 38 39 37 40 38 class ModelPanel1D(PlotPanel, PanelBase): … … 52 50 ## Group ID 53 51 group_id = None 52 _menu_ids = IdList() 54 53 55 54 def __init__(self, parent, id=-1, color=None, … … 68 67 69 68 self._available_data = [] 70 self._menu_add_ids = []71 69 self._symbol_labels = self.get_symbol_label() 72 70 self._color_labels = self.get_color_label() … … 556 554 self._slicerpop.set_plots(self.plots) 557 555 self._slicerpop.set_graph(self.graph) 556 ids = iter(self._menu_ids) 558 557 if not self.graph.selected_plottable in self.plots: 559 558 # Various plot options 560 wx_id = wx.NewId()559 wx_id = ids.next() 561 560 self._slicerpop.Append(wx_id, '&Save Image', 'Save image as PNG') 562 561 wx.EVT_MENU(self, wx_id, self.onSaveImage) 563 wx_id = wx.NewId()562 wx_id = ids.next() 564 563 self._slicerpop.Append(wx_id, '&Print Image', 'Print image ') 565 564 wx.EVT_MENU(self, wx_id, self.onPrint) 566 565 567 wx_id = wx.NewId()566 wx_id = ids.next() 568 567 self._slicerpop.Append(wx_id, '&Copy to Clipboard', 569 568 'Copy to the clipboard') … … 582 581 continue 583 582 584 wx_id = wx.NewId()583 wx_id = ids.next() 585 584 plot_menu.Append(wx_id, "&DataInfo", name) 586 585 wx.EVT_MENU(self, wx_id, self. _onDataShow) 587 wx_id = wx.NewId()586 wx_id = ids.next() 588 587 plot_menu.Append(wx_id, "&Save Points as a File", name) 589 588 wx.EVT_MENU(self, wx_id, self._onSave) … … 592 591 # add menu of other plugins 593 592 item_list = self.parent.get_current_context_menu(self) 594 595 593 if (not item_list == None) and (not len(item_list) == 0): 596 for item in item_list: 594 # Note: reusing menu ids in submenu. This code works because 595 # IdItems is set up as a lazy iterator returning each id in 596 # sequence, creating new ids as needed so it never runs out. 597 # zip() is set up to stop when any iterator is empty, so it 598 # only asks for the number of ids in item_list. 599 for item, wx_id in zip(item_list, self._menu_ids): 597 600 598 601 try: 599 wx_id = wx.NewId()600 602 plot_menu.Append(wx_id, item[0], name) 601 603 wx.EVT_MENU(self, wx_id, item[2]) … … 607 609 608 610 if self.parent.ClassName.count('wxDialog') == 0: 609 wx_id = wx.NewId()611 wx_id = ids.next() 610 612 plot_menu.Append(wx_id, '&Linear Fit', name) 611 613 wx.EVT_MENU(self, wx_id, self.onFitting) 612 614 plot_menu.AppendSeparator() 613 615 614 wx_id = wx.NewId()616 wx_id = ids.next() 615 617 plot_menu.Append(wx_id, "Remove", name) 616 618 wx.EVT_MENU(self, wx_id, self._onRemove) 617 619 if not plot.is_data: 618 wx_id = wx.NewId()620 wx_id = ids.next() 619 621 plot_menu.Append(wx_id, '&Freeze', name) 620 622 wx.EVT_MENU(self, wx_id, self.onFreeze) … … 622 624 623 625 if plot.is_data: 624 wx_id = wx.NewId()626 wx_id = ids.next() 625 627 self.hide_menu = plot_menu.Append(wx_id, "Hide Error Bar", name) 626 628 … … 636 638 plot_menu.AppendSeparator() 637 639 638 wx_id = wx.NewId()640 wx_id = ids.next() 639 641 plot_menu.Append(wx_id, '&Modify Plot Property', name) 640 642 wx.EVT_MENU(self, wx_id, self.createAppDialog) 641 wx_id = wx.NewId()643 wx_id = ids.next() 642 644 # plot_menu.SetTitle(name) 643 645 self._slicerpop.AppendMenu(wx_id, '&%s' % name, plot_menu) … … 648 650 loc_menu = wx.Menu() 649 651 for label in self._loc_labels: 650 wx_id = wx.NewId()652 wx_id = ids.next() 651 653 loc_menu.Append(wx_id, str(label), str(label)) 652 654 wx.EVT_MENU(self, wx_id, self.onChangeLegendLoc) 653 655 654 wx_id = wx.NewId()656 wx_id = ids.next() 655 657 self._slicerpop.Append(wx_id, '&Modify Graph Appearance', 656 658 'Modify graph appearance') … … 660 662 661 663 if self.position != None: 662 wx_id = wx.NewId()664 wx_id = ids.next() 663 665 self._slicerpop.Append(wx_id, '&Add Text') 664 666 wx.EVT_MENU(self, wx_id, self._on_addtext) 665 wx_id = wx.NewId()667 wx_id = ids.next() 666 668 self._slicerpop.Append(wx_id, '&Remove Text') 667 669 wx.EVT_MENU(self, wx_id, self._on_removetext) 668 670 self._slicerpop.AppendSeparator() 669 wx_id = wx.NewId()671 wx_id = ids.next() 670 672 self._slicerpop.Append(wx_id, '&Change Scale') 671 673 wx.EVT_MENU(self, wx_id, self._onProperties) 672 674 self._slicerpop.AppendSeparator() 673 wx_id = wx.NewId()675 wx_id = ids.next() 674 676 self._slicerpop.Append(wx_id, '&Reset Graph Range') 675 677 wx.EVT_MENU(self, wx_id, self.onResetGraph) … … 677 679 if self.parent.ClassName.count('wxDialog') == 0: 678 680 self._slicerpop.AppendSeparator() 679 wx_id = wx.NewId()681 wx_id = ids.next() 680 682 self._slicerpop.Append(wx_id, '&Window Title') 681 683 wx.EVT_MENU(self, wx_id, self.onChangeCaption) -
src/sas/guiframe/local_perspectives/plotting/Plotter2D.py
r098f3d2 r6f16e25 287 287 288 288 """ 289 ids = iter(self._menu_ids) 289 290 slicerpop = PanelMenu() 290 291 slicerpop.set_plots(self.plots) 291 292 slicerpop.set_graph(self.graph) 292 293 293 wx_id = wx.NewId()294 wx_id = ids.next() 294 295 slicerpop.Append(wx_id, '&Save Image') 295 296 wx.EVT_MENU(self, wx_id, self.onSaveImage) 296 297 297 wx_id = wx.NewId()298 wx_id = ids.next() 298 299 slicerpop.Append(wx_id, '&Print Image', 'Print image') 299 300 wx.EVT_MENU(self, wx_id, self.onPrint) 300 301 301 wx_id = wx.NewId()302 wx_id = ids.next() 302 303 slicerpop.Append(wx_id, '&Copy to Clipboard', 'Copy to the clipboard') 303 304 wx.EVT_MENU(self, wx_id, self.OnCopyFigureMenu) … … 305 306 # saving data 306 307 plot = self.data2D 307 wx_id = wx.NewId()308 wx_id = ids.next() 308 309 slicerpop.Append(wx_id, "&Data Info") 309 310 wx.EVT_MENU(self, wx_id, self._onDataShow) 310 311 311 wx_id = wx.NewId()312 wx_id = ids.next() 312 313 slicerpop.Append(wx_id, "&Save as a File (DAT)") 313 314 self.action_ids[str(wx_id)] = plot … … 320 321 self.data2D.name.split(" ")[0] != 'Residuals': 321 322 # The line above; Not for trunk 322 for item in item_list: 323 # Note: reusing menu ids for the sub-menus. See Plotter1D. 324 for item, wx_id in zip(item_list, self._menu_ids): 323 325 try: 324 wx_id = wx.NewId()325 326 slicerpop.Append(wx_id, item[0], item[1]) 326 327 wx.EVT_MENU(self, wx_id, item[2]) … … 331 332 slicerpop.AppendSeparator() 332 333 333 wx_id = wx.NewId()334 wx_id = ids.next() 334 335 slicerpop.Append(wx_id, '&Perform Circular Average') 335 336 wx.EVT_MENU(self, wx_id, self.onCircular) \ 336 337 # For Masked Data 337 338 if not plot.mask.all(): 338 wx_id = wx.NewId()339 wx_id = ids.next() 339 340 slicerpop.Append(wx_id, '&Masked Circular Average') 340 341 wx.EVT_MENU(self, wx_id, self.onMaskedCircular) 341 wx_id = wx.NewId()342 wx_id = ids.next() 342 343 slicerpop.Append(wx_id, '&Sector [Q View]') 343 344 wx.EVT_MENU(self, wx_id, self.onSectorQ) 344 wx_id = wx.NewId()345 wx_id = ids.next() 345 346 slicerpop.Append(wx_id, '&Annulus [Phi View ]') 346 347 wx.EVT_MENU(self, wx_id, self.onSectorPhi) 347 wx_id = wx.NewId()348 wx_id = ids.next() 348 349 slicerpop.Append(wx_id, '&Box Sum') 349 350 wx.EVT_MENU(self, wx_id, self.onBoxSum) 350 wx_id = wx.NewId()351 wx_id = ids.next() 351 352 slicerpop.Append(wx_id, '&Box Averaging in Qx') 352 353 wx.EVT_MENU(self, wx_id, self.onBoxavgX) 353 wx_id = wx.NewId()354 wx_id = ids.next() 354 355 slicerpop.Append(wx_id, '&Box Averaging in Qy') 355 356 wx.EVT_MENU(self, wx_id, self.onBoxavgY) 356 357 if self.slicer != None: 357 wx_id = wx.NewId()358 wx_id = ids.next() 358 359 slicerpop.Append(wx_id, '&Clear Slicer') 359 360 wx.EVT_MENU(self, wx_id, self.onClearSlicer) 360 361 if self.slicer.__class__.__name__ != "BoxSum": 361 wx_id = wx.NewId()362 wx_id = ids.next() 362 363 slicerpop.Append(wx_id, '&Edit Slicer Parameters') 363 364 wx.EVT_MENU(self, wx_id, self._onEditSlicer) 364 365 slicerpop.AppendSeparator() 365 366 366 wx_id = wx.NewId()367 wx_id = ids.next() 367 368 slicerpop.Append(wx_id, '&Edit Graph Label', 'Edit Graph Label') 368 369 wx.EVT_MENU(self, wx_id, self.onEditLabels) … … 371 372 # ILL mod here 372 373 373 wx_id = wx.NewId()374 wx_id = ids.next() 374 375 slicerpop.Append(wx_id, '&Modify graph appearance', 'Modify graph appearance') 375 376 wx.EVT_MENU(self, wx_id, self.modifyGraphAppearance) 376 377 slicerpop.AppendSeparator() 377 378 378 wx_id = wx.NewId()379 wx_id = ids.next() 379 380 slicerpop.Append(wx_id, '&2D Color Map') 380 381 wx.EVT_MENU(self, wx_id, self._onEditDetector) 381 382 slicerpop.AppendSeparator() 382 383 383 wx_id = wx.NewId()384 wx_id = ids.next() 384 385 slicerpop.Append(wx_id, '&Toggle Linear/Log Scale') 385 386 wx.EVT_MENU(self, wx_id, self._onToggleScale) 386 387 387 388 slicerpop.AppendSeparator() 388 wx_id = wx.NewId()389 wx_id = ids.next() 389 390 slicerpop.Append(wx_id, '&Window Title') 390 391 wx.EVT_MENU(self, wx_id, self.onChangeCaption) -
src/sas/guiframe/utils.py
r79492222 r6f16e25 123 123 return begin_flag, end_flag 124 124 125 class IdList: 126 """ 127 Create a list of wx ids that can be reused. 128 129 Ids for items need to be unique within their context. In a dynamic 130 application where the number of ids needed different each time the 131 form is created, depending for example, on the number of items that 132 need to be shown in the context menu, you cannot preallocate the 133 ids that you are going to use for the form. Instead, you can use 134 an IdList, which will reuse ids from context to context, adding new 135 ones if the new context requires more than a previous context. 136 137 IdList is set up as an iterator, which returns new ids forever 138 or until it runs out. This makes it pretty useful for defining 139 menus:: 140 141 class Form(wx.Dialog): 142 _form_id_pool = IdList() 143 def __init__(self): 144 ... 145 menu = wx.Menu() 146 for item, wx_id in zip(menu_items, self._form_id_pool): 147 name, description, callback = item 148 menu.Append(wx_id, name, description) 149 wx.EVT_MENU(self, wx_id, callback) 150 ... 151 152 It is a little unusual to use an iterator outside of a loop, but it is 153 supported. For example, when defining a form, your class definition 154 might look something like:: 155 156 class Form(wx.Dialog): 157 _form_id_pool = IdList() 158 def __init__(self, pairs, ...): 159 ids = iter(_form_id_pool) 160 ... 161 wx.StaticText(self, ids.next(), "Some key-value pairs") 162 for name, value in pairs: 163 label = wx.StaticText(self, ids.next(), name) 164 input = wx.TextCtrl(self, ids.next(), value=str(value)) 165 ... 166 ... 167 168 If the dialog is really dynamic, and not defined all in one place, then 169 save the id list iterator as *self._ids = iter(_form_id_pool)* in the 170 constructor. 171 172 The wx documentation is not clear on whether ids need to be unique. 173 Clearly different dialogs can use the same ids, as this is done for the 174 standard button ids such as wx.ID_HELP. Presumably each widget on the 175 form needs its own id, but whether these ids can match the ids of menu 176 items is not indicated, or whether different submenus need their own 177 ids. Using different id lists for menu items and widgets is safest, 178 but probably not necessary. And what about notebook tabs. Do the 179 ids need to be unique across all tabs? 180 """ 181 def __init__(self): 182 self._ids = [] 183 def __iter__(self): 184 return _IdListIterator(self) 185 def __getitem__(self, index): 186 while index >= len(self._ids): 187 self._ids.append(wx.NewId()) 188 return self._ids[index] 189 190 class _IdListIterator: 191 def __init__(self, id_list): 192 self.id_list = id_list 193 self.index = -1 194 def next(self): 195 self.index += 1 196 return self.id_list[self.index] 197 -
src/sas/models/PeakGaussModel.py
rac7be54 rd430ee8 3 3 PeakGaussModel function as a BaseComponent model 4 4 """ 5 from __future__ import division 5 6 6 7 from sas.models.BaseComponent import BaseComponent -
src/sas/models/resolution.py
rbe0c318 r80ba1a2 11 11 MINIMUM_RESOLUTION = 1e-8 12 12 13 class Resolution1D(object): 13 14 # When extrapolating to -q, what is the minimum positive q relative to q_min 15 # that we wish to calculate? 16 MIN_Q_SCALE_FOR_NEGATIVE_Q_EXTRAPOLATION = 0.01 17 18 class Resolution(object): 14 19 """ 15 20 Abstract base class defining a 1D resolution function. … … 32 37 33 38 34 class Perfect1D(Resolution 1D):39 class Perfect1D(Resolution): 35 40 """ 36 41 Resolution function to use when there is no actual resolution smearing … … 45 50 46 51 47 class Pinhole1D(Resolution 1D):52 class Pinhole1D(Resolution): 48 53 r""" 49 54 Pinhole aperture with q-dependent gaussian resolution. … … 77 82 78 83 79 class Slit1D(Resolution 1D):84 class Slit1D(Resolution): 80 85 """ 81 86 Slit aperture with a complicated resolution function. … … 92 97 The *weight_matrix* is computed by :func:`slit1d_resolution` 93 98 """ 94 def __init__(self, q, width, height, q_calc=None): 95 # TODO: maybe issue warnings rather than raising errors 96 if not np.isscalar(width): 97 if np.any(np.diff(width) > 0.0): 98 raise ValueError("Slit resolution requires fixed width slits") 99 width = width[0] 100 if not np.isscalar(height): 101 if np.any(np.diff(height) > 0.0): 102 raise ValueError("Slit resolution requires fixed height slits") 103 height = height[0] 104 99 def __init__(self, q, width, height=0., q_calc=None): 105 100 # Remember what width/height was used even though we won't need them 106 101 # after the weight matrix is constructed 107 102 self.width, self.height = width, height 103 104 # Allow independent resolution on each point even though it is not 105 # needed in practice. 106 if np.isscalar(width): 107 width = np.ones(len(q))*width 108 else: 109 width = np.asarray(width) 110 if np.isscalar(height): 111 height = np.ones(len(q))*height 112 else: 113 height = np.asarray(height) 108 114 109 115 self.q = q.flatten() … … 147 153 148 154 149 def slit_resolution(q_calc, q, width, height ):155 def slit_resolution(q_calc, q, width, height, n_height=30): 150 156 r""" 151 157 Build a weight matrix to compute *I_s(q)* from *I(q_calc)*, given 152 $q_v$ = *width* and $q_h$ = *height*. 153 154 *width* and *height* are scalars since current instruments use the 155 same slit settings for all measurement points. 158 $q_\perp$ = *width* and $q_\parallel$ = *height*. *n_height* is 159 is the number of steps to use in the integration over $q_\parallel$ 160 when both $q_\perp$ and $q_\parallel$ are non-zero. 161 162 Each $q$ can have an independent width and height value even though 163 current instruments use the same slit setting for all measured points. 156 164 157 165 If slit height is large relative to width, use: … … 159 167 .. math:: 160 168 161 I_s(q_ o) = \frac{1}{\Delta q_v}162 \int_0^{\Delta q_ v} I(\sqrt{q_o^2 + u^2} du169 I_s(q_i) = \frac{1}{\Delta q_\perp} 170 \int_0^{\Delta q_\perp} I(\sqrt{q_i^2 + q_\perp^2} dq_\perp 163 171 164 172 If slit width is large relative to height, use: … … 166 174 .. math:: 167 175 168 I_s(q_o) = \frac{1}{2 \Delta q_v} 169 \int_{-\Delta q_v}^{\Delta q_v} I(u) du 170 """ 171 if width == 0.0 and height == 0.0: 172 #print "condition zero" 173 return 1 174 176 I_s(q_i) = \frac{1}{2 \Delta q_\parallel} 177 \int_{-\Delta q_\parallel}^{\Delta q_\parallel} 178 I(|q_i + q_\parallel|) dq_\parallel 179 180 For a mixture of slit width and height use: 181 182 .. math:: 183 184 I_s(q_i) = \frac{1}{2 \Delta q_\parallel \Delta q_\perp} 185 \int_{-\Delta q_\parallel)^{\Delta q_parallel} 186 \int_0^[\Delta q_\perp} 187 I(\sqrt{(q_i + q_\parallel)^2 + q_\perp^2}) 188 dq_\perp dq_\parallel 189 190 191 Algorithm 192 --------- 193 194 We are using the mid-point integration rule to assign weights to each 195 element of a weight matrix $W$ so that 196 197 .. math:: 198 199 I_s(q) = W I(q_\text{calc}) 200 201 If *q_calc* is at the mid-point, we can infer the bin edges from the 202 pairwise averages of *q_calc*, adding the missing edges before 203 *q_calc[0]* and after *q_calc[-1]*. 204 205 For $q_\parallel = 0$, the smeared value can be computed numerically 206 using the $u$ substitution 207 208 .. math:: 209 210 u_j = \sqrt{q_j^2 - q^2} 211 212 This gives 213 214 .. math:: 215 216 I_s(q) \approx \sum_j I(u_j) \Delta u_j 217 218 where $I(u_j)$ is the value at the mid-point, and $\Delta u_j$ is the 219 difference between consecutive edges which have been first converted 220 to $u$. Only $u_j \in [0, \Delta q_\perp]$ are used, which corresponds 221 to $q_j \in [q, \sqrt{q^2 + \Delta q_\perp}]$, so 222 223 .. math:: 224 225 W_{ij} = \frac{1}{\Delta q_\perp} \Delta u_j 226 = \frac{1}{\Delta q_\perp} 227 \sqrt{q_{j+1}^2 - q_i^2} - \sqrt{q_j^2 - q_i^2} 228 \text{if} q_j \in [q_i, \sqrt{q_i^2 + q_\perp^2}] 229 230 where $I_s(q_i)$ is the theory function being computed and $q_j$ are the 231 mid-points between the calculated values in *q_calc*. We tweak the 232 edges of the initial and final intervals so that they lie on integration 233 limits. 234 235 (To be precise, the transformed midpoint $u(q_j)$ is not necessarily the 236 midpoint of the edges $u((q_{j-1}+q_j)/2)$ and $u((q_j + q_{j+1})/2)$, 237 but it is at least in the interval, so the approximation is going to be 238 a little better than the left or right Riemann sum, and should be 239 good enough for our purposes.) 240 241 For $q_\perp = 0$, the $u$ substitution is simpler: 242 243 .. math:: 244 245 u_j = |q_j - q| 246 247 so 248 249 .. math:: 250 251 W_ij = \frac{1}{2 \Delta q_\parallel} \Delta u_j 252 = \frac{1}{2 \Delta q_\parallel} (q_{j+1} - q_j) 253 \text{if} q_j \in [q-\Delta q_\parallel, q+\Delta q_\parallel] 254 255 However, we need to support cases were $u_j < 0$, which means using 256 $2 (q_{j+1} - q_j)$ when $q_j \in [0, q_\parallel-q_i]$. This is not 257 an issue for $q_i > q_\parallel$. 258 259 For bot $q_\perp > 0$ and $q_\parallel > 0$ we perform a 2 dimensional 260 integration with 261 262 .. math:: 263 264 u_jk = \sqrt{q_j^2 - (q + (k\Delta q_\parallel/L))^2} 265 \text{for} k = -L \ldots L 266 267 for $L$ = *n_height*. This gives 268 269 .. math:: 270 271 W_{ij} = \frac{1}{2 \Delta q_\perp q_\parallel} 272 \sum_{k=-L}^L \Delta u_jk (\frac{\Delta q_\parallel}{2 L + 1} 273 274 275 """ 276 #np.set_printoptions(precision=6, linewidth=10000) 277 278 # The current algorithm is a midpoint rectangle rule. 175 279 q_edges = bin_edges(q_calc) # Note: requires q > 0 176 280 q_edges[q_edges<0.0] = 0.0 # clip edges below zero 177 178 #np.set_printoptions(linewidth=10000) 179 if width <= 100.0 * height or height == 0: 180 # The current algorithm is a midpoint rectangle rule. In the test case, 181 # neither trapezoid nor Simpson's rule improved the accuracy. 182 #print "condition h", q_edges.shape, q.shape, q_calc.shape 183 weights = np.zeros((len(q), len(q_calc)), 'd') 184 for i, qi in enumerate(q): 185 weights[i, :] = np.diff(q_to_u(q_edges, qi)) 186 weights /= width 187 weights = weights.T 188 else: 189 #print "condition w" 190 # Make q_calc into a row vector, and q into a column vector 191 q, q_calc = q[None,:], q_calc[:,None] 192 in_x = (q_calc >= q-width) * (q_calc <= q+width) 193 weights = np.diff(q_edges)[:,None] * in_x 194 281 weights = np.zeros((len(q), len(q_calc)), 'd') 282 283 #print q_calc 284 for i, (qi, w, h) in enumerate(zip(q, width, height)): 285 if w == 0. and h == 0.: 286 # Perfect resolution, so return the theory value directly. 287 # Note: assumes that q is a subset of q_calc. If qi need not be 288 # in q_calc, then we can do a weighted interpolation by looking 289 # up qi in q_calc, then weighting the result by the relative 290 # distance to the neighbouring points. 291 weights[i, :] = (q_calc == qi) 292 elif h == 0: 293 weights[i, :] = _q_perp_weights(q_edges, qi, w) 294 elif w == 0: 295 in_x = 1.0 * ((q_calc >= qi-h) & (q_calc <= qi+h)) 296 abs_x = 1.0*(q_calc < abs(qi - h)) if qi < h else 0. 297 #print qi - h, qi + h 298 #print in_x + abs_x 299 weights[i,:] = (in_x + abs_x) * np.diff(q_edges) / (2*h) 300 else: 301 L = n_height 302 for k in range(-L, L+1): 303 weights[i,:] += _q_perp_weights(q_edges, qi+k*h/L, w) 304 weights[i,:] /= 2*L + 1 305 306 return weights.T 307 308 309 def _q_perp_weights(q_edges, qi, w): 310 # Convert bin edges from q to u 311 u_limit = np.sqrt(qi**2 + w**2) 312 u_edges = q_edges**2 - qi**2 313 u_edges[q_edges < abs(qi)] = 0. 314 u_edges[q_edges > u_limit] = u_limit**2 - qi**2 315 weights = np.diff(np.sqrt(u_edges))/w 316 #print "i, qi",i,qi,qi+width 317 #print q_calc 318 #print weights 195 319 return weights 196 320 … … 212 336 function. 213 337 """ 214 height # keep lint happy215 q_min, q_max = np.min(q), np.max(np.sqrt(q**2 + width**2)) 338 q_min, q_max = np.min(q-height), np.max(np.sqrt((q+height)**2 + width**2)) 339 216 340 return geometric_extrapolation(q, q_min, q_max) 217 341 … … 233 357 ]) 234 358 return edges 235 236 237 def q_to_u(q, q0):238 """239 Convert *q* values to *u* values for the integral computed at *q0*.240 """241 # array([value])**2 - value**2 is not always zero242 qpsq = q**2 - q0**2243 qpsq[qpsq<0] = 0244 return sqrt(qpsq)245 359 246 360 … … 275 389 q = np.sort(q) 276 390 if q_min < q[0]: 277 if q_min <= 0: q_min = q [0]/10391 if q_min <= 0: q_min = q_min*MIN_Q_SCALE_FOR_NEGATIVE_Q_EXTRAPOLATION 278 392 n_low = np.ceil((q[0]-q_min) / (q[1]-q[0])) if q[1]>q[0] else 15 279 393 q_low = np.linspace(q_min, q[0], n_low+1)[:-1] … … 297 411 *points_per_decade* sets the ratio between consecutive steps such 298 412 that there will be $n$ points used for every factor of 10 increase 299 in $q$.413 in *q*. 300 414 301 415 If *points_per_decade* is not given, it will be estimated as follows. … … 316 430 Substituting: 317 431 318 .. math::319 320 432 n_\text{extend} = (n-1) (\log q_\text{max} - \log q_n) 321 / (\log q_n - \log q_1)433 / (\log q_n - log q_1) 322 434 """ 323 435 q = np.sort(q) … … 327 439 log_delta_q = log(10.) / points_per_decade 328 440 if q_min < q[0]: 329 if q_min < 0: q_min = q[0] /10441 if q_min < 0: q_min = q[0]*MIN_Q_SCALE_FOR_NEGATIVE_Q_EXTRAPOLATION 330 442 n_low = log_delta_q * (log(q[0])-log(q_min)) 331 443 q_low = np.logspace(log10(q_min), log10(q[0]), np.ceil(n_low)+1)[:-1] … … 359 471 360 472 361 def romberg_slit_1d(q, delta_qv, form, pars):473 def romberg_slit_1d(q, width, height, form, pars): 362 474 """ 363 475 Romberg integration for slit resolution. … … 366 478 that make it slow to evaluate but give it good accuracy. 367 479 """ 368 from scipy.integrate import romberg 480 from scipy.integrate import romberg, dblquad 369 481 370 482 if any(k not in form.info['defaults'] for k in pars.keys()): … … 374 486 (", ".join(sorted(extra)), ", ".join(sorted(keys)))) 375 487 376 _fn = lambda u, q0: eval_form(sqrt(q0**2 + u**2), form, pars) 377 r = [romberg(_fn, 0, delta_qv[0], args=(qi,), 378 divmax=100, vec_func=True, tol=0, rtol=1e-8) 379 for qi in q] 488 if np.isscalar(width): 489 width = [width]*len(q) 490 if np.isscalar(height): 491 height = [height]*len(q) 492 _int_w = lambda w, qi: eval_form(sqrt(qi**2 + w**2), form, pars) 493 _int_h = lambda h, qi: eval_form(abs(qi+h), form, pars) 494 # If both width and height are defined, then it is too slow to use dblquad. 495 # Instead use trapz on a fixed grid, interpolated into the I(Q) for 496 # the extended Q range. 497 #_int_wh = lambda w, h, qi: eval_form(sqrt((qi+h)**2 + w**2), form, pars) 498 q_calc = slit_extend_q(q, np.asarray(width), np.asarray(height)) 499 Iq = eval_form(q_calc, form, pars) 500 result = np.empty(len(q)) 501 for i, (qi, w, h) in enumerate(zip(q, width, height)): 502 if h == 0.: 503 r = romberg(_int_w, 0, w, args=(qi,), 504 divmax=100, vec_func=True, tol=0, rtol=1e-8) 505 result[i] = r/w 506 elif w == 0.: 507 r = romberg(_int_h, -h, h, args=(qi,), 508 divmax=100, vec_func=True, tol=0, rtol=1e-8) 509 result[i] = r/(2*h) 510 else: 511 w_grid = np.linspace(0, w, 21)[None,:] 512 h_grid = np.linspace(-h, h, 23)[:,None] 513 u = sqrt((qi+h_grid)**2 + w_grid**2) 514 Iu = np.interp(u, q_calc, Iq) 515 #print np.trapz(Iu, w_grid, axis=1) 516 Is = np.trapz(np.trapz(Iu, w_grid, axis=1), h_grid[:,0]) 517 result[i] = Is / (2*h*w) 518 """ 519 r, err = dblquad(_int_wh, -h, h, lambda h: 0., lambda h: w, 520 args=(qi,)) 521 result[i] = r/(w*2*h) 522 """ 523 380 524 # r should be [float, ...], but it is [array([float]), array([float]),...] 381 return np.asarray(r).flatten()/delta_qv[0]525 return result 382 526 383 527 … … 520 664 521 665 def compare(self, q, output, answer, tolerance): 522 err = (output - answer)/answer523 idx = abs(err) >= tolerance524 problem = zip(q[idx], output[idx], answer[idx], err[idx])525 print "\n".join(str(v) for v in problem)666 #err = (output - answer)/answer 667 #idx = abs(err) >= tolerance 668 #problem = zip(q[idx], output[idx], answer[idx], err[idx]) 669 #print "\n".join(str(v) for v in problem) 526 670 np.testing.assert_allclose(output, answer, rtol=tolerance) 527 671 … … 609 753 data = np.loadtxt(data_string.split('\n')).T 610 754 q, delta_qv, _, answer = data 611 answer = romberg_slit_1d(q, delta_qv, self.model, pars)755 answer = romberg_slit_1d(q, delta_qv, 0., self.model, pars) 612 756 q_calc = slit_extend_q(interpolate(q, 2*np.pi/radius/20), 613 delta_qv[0], delta_qv[0])757 delta_qv[0], 0.) 614 758 resolution = Slit1D(q, width=delta_qv, height=0, q_calc=q_calc) 615 759 output = self.Iq_sphere(pars, resolution) … … 629 773 form = load_model('ellipsoid', dtype='double') 630 774 q = np.logspace(log10(4e-5),log10(2.5e-2), 68) 631 delta_qv = [0.117]632 resolution = Slit1D(q, width= delta_qv, height=0)633 answer = romberg_slit_1d(q, delta_qv, form, pars)775 width, height = 0.117, 0. 776 resolution = Slit1D(q, width=width, height=height) 777 answer = romberg_slit_1d(q, width, height, form, pars) 634 778 output = resolution.apply(eval_form(resolution.q_calc, form, pars)) 635 779 # TODO: 10% is too much error; use better algorithm 780 #print np.max(abs(answer-output)/answer) 636 781 self.compare(q, output, answer, 0.1) 637 782 … … 860 1005 861 1006 def _eval_demo_1d(resolution, title): 1007 import sys 862 1008 from sasmodels import core 863 from sasmodels.models import cylinder 864 ## or alternatively: 865 # cylinder = core.load_model_definition('cylinder') 866 model = core.load_model(cylinder) 1009 name = sys.argv[1] if len(sys.argv) > 1 else 'cylinder' 1010 1011 if name == 'cylinder': 1012 pars = {'length':210, 'radius':500} 1013 elif name == 'teubner_strey': 1014 pars = {'a2':0.003, 'c1':-1e4, 'c2':1e10, 'background':0.312643} 1015 elif name == 'sphere' or name == 'spherepy': 1016 pars = TEST_PARS_SLIT_SPHERE 1017 elif name == 'ellipsoid': 1018 pars = { 1019 'scale':0.05, 1020 'rpolar':500, 'requatorial':15000, 1021 'sld':6, 'solvent_sld': 1, 1022 } 1023 else: 1024 pars = {} 1025 defn = core.load_model_definition(name) 1026 model = core.load_model(defn) 867 1027 868 1028 kernel = core.make_kernel(model, [resolution.q_calc]) 869 theory = core.call_kernel(kernel, {'length':210, 'radius':500})1029 theory = core.call_kernel(kernel, pars) 870 1030 Iq = resolution.apply(theory) 1031 1032 if isinstance(resolution, Slit1D): 1033 width, height = resolution.width, resolution.height 1034 Iq_romb = romberg_slit_1d(resolution.q, width, height, model, pars) 1035 else: 1036 dq = resolution.q_width 1037 Iq_romb = romberg_pinhole_1d(resolution.q, dq, model, pars) 871 1038 872 1039 import matplotlib.pyplot as plt 873 1040 plt.loglog(resolution.q_calc, theory, label='unsmeared') 874 1041 plt.loglog(resolution.q, Iq, label='smeared', hold=True) 1042 plt.loglog(resolution.q, Iq_romb, label='romberg smeared', hold=True) 875 1043 plt.legend() 876 1044 plt.title(title) … … 879 1047 880 1048 def demo_pinhole_1d(): 881 q = np.logspace(- 3, -1, 400)1049 q = np.logspace(-4, np.log10(0.2), 400) 882 1050 q_width = 0.1*q 883 1051 resolution = Pinhole1D(q, q_width) … … 885 1053 886 1054 def demo_slit_1d(): 887 q = np.logspace(-3, -1, 400) 888 qx_width = 0.005 889 qy_width = 0.0 890 resolution = Slit1D(q, qx_width, qy_width) 891 _eval_demo_1d(resolution, title="0.005 Qx Slit Resolution") 1055 q = np.logspace(-4, np.log10(0.2), 100) 1056 w = h = 0. 1057 #w = 0.000000277790 1058 w = 0.0277790 1059 #h = 0.00277790 1060 #h = 0.0277790 1061 resolution = Slit1D(q, w, h) 1062 _eval_demo_1d(resolution, title="(%g,%g) Slit Resolution"%(w,h)) 892 1063 893 1064 def demo(): … … 895 1066 plt.subplot(121) 896 1067 demo_pinhole_1d() 1068 #plt.yscale('linear') 897 1069 plt.subplot(122) 898 1070 demo_slit_1d() 1071 #plt.yscale('linear') 899 1072 plt.show() 900 1073 901 1074 902 1075 if __name__ == "__main__": 903 #demo()904 main()1076 demo() 1077 #main() -
src/sas/perspectives/fitting/basepage.py
rf0d720b r02098e3 15 15 from wx.lib.scrolledpanel import ScrolledPanel 16 16 from sas.guiframe.panel_base import PanelBase 17 from sas.guiframe.utils import format_number, check_float 17 from sas.guiframe.utils import format_number, check_float, IdList 18 18 from sas.guiframe.events import PanelOnFocusEvent 19 19 from sas.guiframe.events import StatusEvent … … 57 57 ## Title to appear on top of the window 58 58 window_caption = "Fit Page " 59 59 60 # These two buttons have specific IDs since they seem to be created more 61 # frequently than they need to. In particular, set_dispers_sizer() is 62 # called by _on_select_model 63 ID_BOOKMARK = wx.NewId() 64 ID_DISPERSER_HELP = wx.NewId() 65 _id_pool = IdList() 66 60 67 def __init__(self, parent, color='blue', **kwargs): 61 68 """ … … 66 73 #Set window's font size 67 74 self.SetWindowVariant(variant=FONT_VARIANT) 68 69 75 self.SetBackgroundColour(color) 76 77 self._ids = iter(self._id_pool) 70 78 ## parent of the page 71 79 self.parent = parent … … 126 134 self.Npts_fit = None 127 135 self.Npts_total = None 128 self.theory_qmin = None 136 self.theory_qmin = None 129 137 self.theory_qmax = None 130 138 self.theory_qmin_x = None … … 135 143 self.sld_axes = None 136 144 self.multi_factor = None 137 145 138 146 self.disp_cb_dict = {} 139 147 140 148 #self.state = PageState(parent=parent) 141 149 ## dictionary containing list of models 142 150 self.model_list_box = {} 143 151 144 152 ## Data member to store the dispersion object created 145 153 self._disp_obj_dict = {} … … 169 177 self.disp_list = [] 170 178 self.disp_name = "" 171 179 172 180 ## list of orientation parameters 173 181 self.orientation_params = [] 174 182 self.orientation_params_disp = [] 175 # Self.model should ALWAYS be None here. It was set to none above in 183 # Self.model should ALWAYS be None here. It was set to none above in 176 184 # this long init setting. no obvious function call in between setting 177 # and this - commenting out on 4/8/2014 by PDB. Remove once clear 185 # and this - commenting out on 4/8/2014 by PDB. Remove once clear 178 186 # it is pointless. 179 187 # if self.model != None: … … 198 206 ## Create context menu for page 199 207 self.popUpMenu = wx.Menu() 200 201 id = wx.NewId()202 self._keep = wx.MenuItem(self.popUpMenu, id, "Add bookmark",208 209 wx_id = self._ids.next() 210 self._keep = wx.MenuItem(self.popUpMenu, wx_id, "Add bookmark", 203 211 " Keep the panel status to recall it later") 204 212 self.popUpMenu.AppendItem(self._keep) … … 206 214 self._set_bookmark_flag(False) 207 215 self._set_save_flag(False) 208 wx.EVT_MENU(self, id, self.on_bookmark)216 wx.EVT_MENU(self, wx_id, self.on_bookmark) 209 217 self.popUpMenu.AppendSeparator() 210 218 211 219 ## Default locations 212 220 self._default_save_location = os.getcwd() … … 214 222 #self.onSave(event=None) 215 223 self.Bind(wx.EVT_CONTEXT_MENU, self.onContextMenu) 216 224 217 225 # bind key event 218 226 self.Bind(wx.EVT_LEFT_DOWN, self.on_left_down) 219 227 220 228 ## create the basic structure of the panel with empty sizer 221 229 self.define_page_structure() 222 230 ## drawing Initial dispersion parameters sizer 223 231 self.set_dispers_sizer() 224 232 225 233 ## layout 226 234 self.set_layout() 227 235 228 236 def set_index_model(self, index): 229 237 """ … … 231 239 """ 232 240 self.index_model = index 233 241 234 242 def create_default_data(self): 235 243 """ … … 248 256 else: 249 257 self._create_default_1d_data() 250 258 251 259 if self.model != None: 252 260 if not self.data.is_data: … … 258 266 self.state.pinhole_smearer = self.pinhole_smearer.GetValue() 259 267 self.state.slit_smearer = self.slit_smearer.GetValue() 260 268 261 269 def _create_default_1d_data(self): 262 270 """ … … 264 272 Only when the page is on theory mode. 265 273 :warning: This data is never plotted. 266 274 267 275 """ 268 276 x = numpy.linspace(start=self.qmin_x, stop=self.qmax_x, … … 274 282 self.data.id = str(self.uid) + " data" 275 283 self.data.group_id = str(self.uid) + " Model1D" 276 284 277 285 def _create_log_1d_data(self): 278 286 """ … … 280 288 Only when the page is on theory mode. 281 289 :warning: This data is never plotted. 282 290 283 291 """ 284 292 if self.qmin_x >= 1.e-10: 285 293 qmin = numpy.log10(self.qmin_x) 286 294 else: 287 qmin = -10. 288 295 qmin = -10. 296 289 297 if self.qmax_x <= 1.e10: 290 298 qmax = numpy.log10(self.qmax_x) 291 299 else: 292 qmax = 10. 293 300 qmax = 10. 301 294 302 x = numpy.logspace(start=qmin, stop=qmax, 295 303 num=self.npts_x, endpoint=True, base=10.0) … … 300 308 self.data.id = str(self.uid) + " data" 301 309 self.data.group_id = str(self.uid) + " Model1D" 302 310 303 311 def _create_default_2d_data(self): 304 312 """ … … 358 366 #xstep = x_size / len(x_bins - 1) 359 367 #ystep = y_size / len(y_bins - 1) 360 368 361 369 self.data.source = Source() 362 370 self.data.data = numpy.ones(len(mask)) … … 381 389 wx.PostEvent(self._manager.parent, PanelOnFocusEvent(panel=self)) 382 390 self.on_tap_focus() 383 391 384 392 def on_tap_focus(self): 385 393 """ … … 397 405 self._manager.menu1.FindItemById(self._manager.id_batchfit) 398 406 batch_menu.Enable(self.batch_on and flag) 399 407 400 408 def set_page_info(self, page_info): 401 409 """ 402 410 set some page important information at once 403 411 """ 404 # THIS METHOD/FUNCTION NO LONGE APPEARS TO BE CALLED. Started up program 412 # THIS METHOD/FUNCTION NO LONGE APPEARS TO BE CALLED. Started up program 405 413 # and started new fit window and PR and Invariant and a fit in fitting 406 414 # but never entered this routine which should be an initialization 407 # routine. Leave for a while but probably something to clean up at 415 # routine. Leave for a while but probably something to clean up at 408 416 # some point? 409 417 # … … 426 434 ## Data member to store the dispersion object created 427 435 self.populate_box(model_dict=self.model_list_box) 428 436 429 437 def onContextMenu(self, event): 430 438 """ … … 433 441 # Skipping the save state functionality for release 0.9.0 434 442 #return 435 443 436 444 pos = event.GetPosition() 437 445 pos = self.ScreenToClient(pos) 438 446 439 447 self.PopupMenu(self.popUpMenu, pos) 440 448 441 449 def onUndo(self, event): 442 450 """ … … 445 453 event = PreviousStateEvent(page=self) 446 454 wx.PostEvent(self.parent, event) 447 455 448 456 def onRedo(self, event): 449 457 """ … … 452 460 event = NextStateEvent(page=self) 453 461 wx.PostEvent(self.parent, event) 454 462 455 463 def define_page_structure(self): 456 464 """ … … 465 473 self.sizer5 = wx.BoxSizer(wx.VERTICAL) 466 474 self.sizer6 = wx.BoxSizer(wx.VERTICAL) 467 475 468 476 self.sizer0.SetMinSize((PANEL_WIDTH, -1)) 469 477 self.sizer1.SetMinSize((PANEL_WIDTH, -1)) … … 473 481 self.sizer5.SetMinSize((PANEL_WIDTH, -1)) 474 482 self.sizer6.SetMinSize((PANEL_WIDTH, -1)) 475 483 476 484 self.vbox.Add(self.sizer0) 477 485 self.vbox.Add(self.sizer1) … … 481 489 self.vbox.Add(self.sizer5) 482 490 self.vbox.Add(self.sizer6) 483 491 484 492 def set_layout(self): 485 493 """ … … 490 498 self.SetSizer(self.vbox) 491 499 self.Centre() 492 500 493 501 def set_owner(self, owner): 494 502 """ 495 503 set owner of fitpage 496 504 497 505 :param owner: the class responsible of plotting 498 506 499 507 """ 500 508 self.event_owner = owner 501 509 self.state.event_owner = owner 502 510 503 511 def get_state(self): 504 512 """ … … 506 514 """ 507 515 return self.state 508 516 509 517 def get_data(self): 510 518 """ … … 512 520 """ 513 521 return self.data 514 522 515 523 def get_data_list(self): 516 524 """ … … 518 526 """ 519 527 return self.data_list 520 528 521 529 def set_manager(self, manager): 522 530 """ 523 531 set panel manager 524 532 525 533 :param manager: instance of plugin fitting 526 534 527 535 """ 528 536 self._manager = manager 529 537 self.state.manager = manager 530 538 531 539 def populate_box(self, model_dict): 532 540 """ 533 541 Store list of model 534 542 535 543 :param model_dict: dictionary containing list of models 536 544 537 545 """ 538 546 self.model_list_box = model_dict 539 547 self.state.model_list_box = self.model_list_box 540 548 self.initialize_combox() 541 549 542 550 def set_model_dictionary(self, model_dict): 543 551 """ … … 551 559 """ 552 560 put default value in the combobox 553 """ 561 """ 554 562 ## fill combox box 555 563 if self.model_list_box is None: … … 560 568 ## These are called for first time by formfactor_combo_init 561 569 ## itself called from fitpanel only. If we find that I'm wrong and 562 ## we DO need to initialize somehow here - do it by a call to 563 ## formfactor_combo_init 570 ## we DO need to initialize somehow here - do it by a call to 571 ## formfactor_combo_init 564 572 ## self.formfator_combo_init() 565 ## BUT NOT HERE -- make it last line of this 573 ## BUT NOT HERE -- make it last line of this 566 574 ## method so that structure box is populated before _show_comboox_helper 567 575 ## is called. Otherwise wx will complain mightily:-) … … 575 583 # self.model_list_box["Shapes"]) 576 584 self._populate_box(self.structurebox, 577 585 self.model_list_box["Structure Factors"]) 578 586 self.structurebox.Insert("None", 0, None) 579 587 self.structurebox.SetSelection(0) … … 582 590 self.structurebox.Disable() 583 591 self.text2.Disable() 584 592 585 593 if self.model.__class__ in self.model_list_box["P(Q)*S(Q)"]: 586 594 self.structurebox.Show() … … 589 597 self.text2.Enable() 590 598 591 599 592 600 def set_dispers_sizer(self): 593 601 """ 594 602 fill sizer containing dispersity info 595 603 """ 604 #print "==== entering set_dispers_sizer ===" 596 605 self.sizer4.Clear(True) 597 606 name = "Polydispersity and Orientational Distribution" 598 box_description = wx.StaticBox(self, -1, name)607 box_description = wx.StaticBox(self, wx.ID_ANY, name) 599 608 box_description.SetForegroundColour(wx.BLUE) 600 609 boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL) 601 610 #---------------------------------------------------- 602 self.disable_disp = wx.RadioButton(self, -1, 'Off', (10, 10),603 604 self.enable_disp = wx.RadioButton(self, -1, 'On', (10, 30))611 self.disable_disp = wx.RadioButton(self, wx.ID_ANY, 'Off', (10, 10), 612 style=wx.RB_GROUP) 613 self.enable_disp = wx.RadioButton(self, wx.ID_ANY, 'On', (10, 30)) 605 614 # best size for MAC and PC 606 615 if ON_MAC: … … 608 617 else: 609 618 size_q = (20, 15) 610 self.disp_help_bt = wx.Button(self, wx.NewId(), '?',619 self.disp_help_bt = wx.Button(self, self.ID_DISPERSER_HELP, '?', 611 620 style=wx.BU_EXACTFIT, 612 621 size=size_q) … … 614 623 id=self.disp_help_bt.GetId()) 615 624 self.disp_help_bt.SetToolTipString("Helps for Polydispersion.") 616 625 617 626 self.Bind(wx.EVT_RADIOBUTTON, self._set_dipers_Param, 618 627 id=self.disable_disp.GetId()) 619 628 self.Bind(wx.EVT_RADIOBUTTON, self._set_dipers_Param, 620 629 id=self.enable_disp.GetId()) 621 630 #MAC needs SetValue 622 631 self.disable_disp.SetValue(True) … … 624 633 sizer_dispersion.Add((20, 20)) 625 634 name = "" # Polydispersity and \nOrientational Distribution " 626 sizer_dispersion.Add(wx.StaticText(self, -1, name))635 sizer_dispersion.Add(wx.StaticText(self, wx.ID_ANY, name)) 627 636 sizer_dispersion.Add(self.enable_disp) 628 637 sizer_dispersion.Add((20, 20)) … … 630 639 sizer_dispersion.Add((25, 20)) 631 640 sizer_dispersion.Add(self.disp_help_bt) 632 641 633 642 ## fill a sizer for dispersion 634 643 boxsizer1.Add(sizer_dispersion, 0, 635 wx.TOP | wx.BOTTOM | wx.LEFT | wx.EXPAND |wx.ADJUST_MINSIZE,636 border=5)644 wx.TOP|wx.BOTTOM|wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 645 border=5) 637 646 self.sizer4_4 = wx.GridBagSizer(6, 5) 638 647 … … 643 652 self.sizer4.Layout() 644 653 self.Layout() 645 654 646 655 self.Refresh() 647 656 ## saving the state of enable dispersity button … … 649 658 self.state.disable_disp = self.disable_disp.GetValue() 650 659 self.SetupScrolling() 651 660 652 661 def onResetModel(self, event): 653 662 """ … … 667 676 previous_state = self.saved_states[name] 668 677 ## reset state of checkbox,textcrtl and regular parameters value 669 678 670 679 self.reset_page(previous_state) 671 680 self.state.m_name = self.m_name 672 681 self.Show(True) 673 682 674 683 def on_preview(self, event): 675 684 """ … … 680 689 # get the report dialog 681 690 self.state.report(images, canvases) 682 691 683 692 def on_save(self, event): 684 693 """ … … 693 702 self._manager.parent._default_save_location 694 703 dlg = wx.FileDialog(self, "Choose a file", self._default_save_location, 695 704 self.window_caption, "*.fitv", wx.SAVE) 696 705 697 706 if dlg.ShowModal() == wx.ID_OK: 698 707 path = dlg.GetPath() 699 708 self._default_save_location = os.path.dirname(path) 700 self._manager.parent._default_save_location = \701 709 self._manager.parent._default_save_location = \ 710 self._default_save_location 702 711 else: 703 712 return None … … 709 718 self._manager.save_fit_state(filepath=fName, fitstate=new_state) 710 719 return new_state 711 720 712 721 def on_copy(self, event): 713 722 """ … … 726 735 wx.CallAfter(self.get_copy) 727 736 728 737 729 738 def on_paste(self, event): 730 739 """ … … 738 747 # messages depending on the flag 739 748 #self._copy_info(True) 740 749 741 750 def _copy_info(self, flag): 742 751 """ 743 752 Send event dpemding on flag 744 753 745 754 : Param flag: flag that distinguish event 746 755 """ … … 758 767 # inform msg to wx 759 768 wx.PostEvent(self._manager.parent, 760 StatusEvent(status=msg, info=infor))761 769 StatusEvent(status=msg, info=infor)) 770 762 771 def _get_time_stamp(self): 763 772 """ … … 769 778 current_date = str(month) + "/" + str(day) + "/" + str(year) 770 779 return current_time, current_date 771 780 772 781 def on_bookmark(self, event): 773 782 """ … … 788 797 name += "bookmarked at %s on %s" % (current_time, current_date) 789 798 self.saved_states[name] = new_state 790 799 791 800 ## Add item in the context menu 792 801 msg = "Model saved at %s on %s" % (current_time, current_date) … … 794 803 msg += " Saved! right click on this page to retrieve this model" 795 804 wx.PostEvent(self._manager.parent, StatusEvent(status=msg)) 796 797 id = wx.NewId() 798 self.popUpMenu.Append(id, name, str(msg)) 799 wx.EVT_MENU(self, id, self.onResetModel) 805 806 self.popUpMenu.Append(self.ID_BOOKMARK, name, str(msg)) 807 wx.EVT_MENU(self, self.ID_BOOKMARK, self.onResetModel) 800 808 wx.PostEvent(self._manager.parent, 801 809 AppendBookmarkEvent(title=name, 802 810 hint=str(msg), 803 811 handler=self._back_to_bookmark)) 804 812 805 813 def _back_to_bookmark(self, event): 806 814 """ … … 810 818 self.onResetModel(event) 811 819 self._draw_model() 812 820 813 821 def onSetFocus(self, evt): 814 822 """ … … 817 825 """ 818 826 return 819 827 820 828 def read_file(self, path): 821 829 """ 822 830 Read two columns file 823 831 824 832 :param path: the path to the file to read 825 833 826 834 """ 827 835 try: … … 856 864 """ 857 865 return self.state.clone() 858 866 859 867 def save_current_state(self): 860 868 """ … … 866 874 self.state.disp_list = copy.deepcopy(self.disp_list) 867 875 self.state.model = self.model.clone() 868 876 869 877 #model combobox: complex code because of mac's silent error 870 878 if self.structurebox != None: … … 885 893 self.state.categorycombobox = self.categorybox.\ 886 894 GetString(cb_select) 887 895 888 896 self.state.enable2D = copy.deepcopy(self.enable2D) 889 897 self.state.values = copy.deepcopy(self.values) … … 902 910 self.state.enable_disp = self.enable_disp.GetValue() 903 911 self.state.disable_disp = self.disable_disp.GetValue() 904 912 905 913 self.state.smearer = copy.deepcopy(self.current_smearer) 906 914 if hasattr(self, "enable_smearer"): … … 917 925 self.state.dxw = copy.deepcopy(self.dxw) 918 926 self.state.slit_smearer = copy.deepcopy(self.slit_smearer.GetValue()) 919 927 920 928 if len(self._disp_obj_dict) > 0: 921 929 for k, v in self._disp_obj_dict.iteritems(): … … 926 934 ## save plotting range 927 935 self._save_plotting_range() 928 936 929 937 self.state.orientation_params = [] 930 938 self.state.orientation_params_disp = [] … … 941 949 self._copy_parameters_state(self.orientation_params_disp, 942 950 self.state.orientation_params_disp) 943 951 944 952 self._copy_parameters_state(self.parameters, self.state.parameters) 945 953 self._copy_parameters_state(self.fittable_param, … … 948 956 #save chisqr 949 957 self.state.tcChi = self.tcChi.GetValue() 950 958 951 959 def save_current_state_fit(self): 952 960 """ … … 958 966 self.state.disp_list = copy.deepcopy(self.disp_list) 959 967 self.state.model = self.model.clone() 960 968 961 969 self.state.enable2D = copy.deepcopy(self.enable2D) 962 970 self.state.values = copy.deepcopy(self.values) … … 964 972 ## save data 965 973 self.state.data = copy.deepcopy(self.data) 966 974 967 975 if hasattr(self, "enable_disp"): 968 976 self.state.enable_disp = self.enable_disp.GetValue() 969 977 self.state.disable_disp = self.disable_disp.GetValue() 970 978 971 979 self.state.smearer = copy.deepcopy(self.current_smearer) 972 980 if hasattr(self, "enable_smearer"): … … 975 983 self.state.disable_smearer = \ 976 984 copy.deepcopy(self.disable_smearer.GetValue()) 977 985 978 986 self.state.pinhole_smearer = \ 979 987 copy.deepcopy(self.pinhole_smearer.GetValue()) … … 998 1006 for k, v in self._disp_obj_dict.iteritems(): 999 1007 self.state._disp_obj_dict[k] = v 1000 1008 1001 1009 self.state.values = copy.deepcopy(self.values) 1002 1010 self.state.weights = copy.deepcopy(self.weights) 1003 1011 1004 1012 ## save plotting range 1005 1013 self._save_plotting_range() 1006 1014 1007 1015 ## save checkbutton state and txtcrtl values 1008 1016 self._copy_parameters_state(self.orientation_params, 1009 1017 self.state.orientation_params) 1010 1018 self._copy_parameters_state(self.orientation_params_disp, 1011 1019 self.state.orientation_params_disp) 1012 1020 self._copy_parameters_state(self.parameters, self.state.parameters) 1013 1021 self._copy_parameters_state(self.fittable_param, 1014 1022 self.state.fittable_param) 1015 1023 self._copy_parameters_state(self.fixed_param, self.state.fixed_param) 1016 1024 1017 1025 def check_invalid_panel(self): 1018 1026 """ … … 1025 1033 wx.MessageBox(msg, 'Info') 1026 1034 return True 1027 1035 1028 1036 def set_model_state(self, state): 1029 1037 """ … … 1032 1040 self.disp_cb_dict = state.disp_cb_dict 1033 1041 self.disp_list = state.disp_list 1034 1042 1035 1043 ## set the state of the radio box 1036 1044 #self.shape_rbutton.SetValue(state.shape_rbutton) … … 1038 1046 #self.struct_rbutton.SetValue(state.struct_rbutton) 1039 1047 #self.plugin_rbutton.SetValue(state.plugin_rbutton) 1040 1048 1041 1049 ## fill model combobox 1042 1050 self._show_combox_helper() … … 1052 1060 category_pos = int(ind_cat) 1053 1061 break 1054 1062 1055 1063 self.categorybox.Select(category_pos) 1056 1064 try: … … 1064 1072 formfactor_pos = int(ind_form) 1065 1073 break 1066 1074 1067 1075 self.formfactorbox.Select(formfactor_pos) 1068 1076 1069 1077 try: 1070 1078 # to support older version … … 1077 1085 structfactor_pos = int(ind_struct) 1078 1086 break 1079 1087 1080 1088 self.structurebox.SetSelection(structfactor_pos) 1081 1089 1082 1090 if state.multi_factor != None: 1083 1091 self.multifactorbox.SetSelection(state.multi_factor) 1084 1092 1085 1093 ## reset state of checkbox,textcrtl and regular parameters value 1086 1094 self._reset_parameters_state(self.orientation_params_disp, … … 1094 1102 self.enable_disp.SetValue(state.enable_disp) 1095 1103 self.disable_disp.SetValue(state.disable_disp) 1096 1104 1097 1105 if hasattr(self, "disp_box") and self.disp_box != None: 1098 1106 self.disp_box.SetSelection(state.disp_box) … … 1102 1110 1103 1111 self._set_dipers_Param(event=None) 1104 1112 1105 1113 if name == "ArrayDispersion": 1106 1114 1107 1115 for item in self.disp_cb_dict.keys(): 1108 1116 1109 1117 if hasattr(self.disp_cb_dict[item], "SetValue"): 1110 1118 self.disp_cb_dict[item].SetValue(\ 1111 1119 state.disp_cb_dict[item]) 1112 1120 # Create the dispersion objects 1113 #from sas.models.dispersion_models import ArrayDispersion 1114 from sasmodels.weights import ArrayDispersion 1121 from sas.models.dispersion_models import ArrayDispersion 1115 1122 disp_model = ArrayDispersion() 1116 1123 if hasattr(state, "values") and \ … … 1123 1130 else: 1124 1131 self._reset_dispersity() 1125 1132 1126 1133 self._disp_obj_dict[item] = disp_model 1127 1134 # Set the new model as the dispersion object 1128 1135 #for the selected parameter 1129 1136 self.model.set_dispersion(item, disp_model) 1130 1137 1131 1138 self.model._persistency_dict[item] = \ 1132 1139 [state.values, state.weights] 1133 1140 1134 1141 else: 1135 1142 keys = self.model.getParamList() … … 1149 1156 self.pinhole_smearer.SetValue(state.pinhole_smearer) 1150 1157 self.slit_smearer.SetValue(state.slit_smearer) 1151 1158 1152 1159 self.dI_noweight.SetValue(state.dI_noweight) 1153 1160 self.dI_didata.SetValue(state.dI_didata) 1154 1161 self.dI_sqrdata.SetValue(state.dI_sqrdata) 1155 1162 self.dI_idata.SetValue(state.dI_idata) 1156 1163 1157 1164 ## we have two more options for smearing 1158 1165 if self.pinhole_smearer.GetValue(): … … 1160 1167 elif self.slit_smearer.GetValue(): 1161 1168 self.onSlitSmear(event=None) 1162 1169 1163 1170 ## reset state of checkbox,textcrtl and dispersity parameters value 1164 1171 self._reset_parameters_state(self.fittable_param, state.fittable_param) 1165 1172 self._reset_parameters_state(self.fixed_param, state.fixed_param) 1166 1173 1167 1174 ## draw the model with previous parameters value 1168 1175 self._onparamEnter_helper() … … 1172 1179 self._lay_out() 1173 1180 self.Refresh() 1174 1181 1175 1182 def reset_page_helper(self, state): 1176 1183 """ 1177 1184 Use page_state and change the state of existing page 1178 1185 1179 1186 :precondition: the page is already drawn or created 1180 1187 1181 1188 :postcondition: the state of the underlying data change as well as the 1182 1189 state of the graphic interface … … 1204 1211 else: 1205 1212 self.set_data(data) 1206 1213 1207 1214 self.enable2D = state.enable2D 1208 1215 try: … … 1214 1221 self.disp_cb_dict = state.disp_cb_dict 1215 1222 self.disp_list = state.disp_list 1216 1223 1217 1224 ## set the state of the radio box 1218 1225 #self.shape_rbutton.SetValue(state.shape_rbutton) … … 1220 1227 #self.struct_rbutton.SetValue(state.struct_rbutton) 1221 1228 #self.plugin_rbutton.SetValue(state.plugin_rbutton) 1222 1229 1223 1230 ## fill model combobox 1224 1231 self._show_combox_helper() … … 1234 1241 category_pos = int(ind_cat) 1235 1242 break 1236 1243 1237 1244 self.categorybox.Select(category_pos) 1238 1245 self._show_combox(None) … … 1247 1254 formfactor_pos = int(ind_form) 1248 1255 break 1249 1256 1250 1257 self.formfactorbox.Select(formfactor_pos) 1251 1258 1252 1259 try: 1253 1260 # to support older version … … 1260 1267 structfactor_pos = int(ind_struct) 1261 1268 break 1262 1269 1263 1270 self.structurebox.SetSelection(structfactor_pos) 1264 1271 … … 1268 1275 #draw the panel according to the new model parameter 1269 1276 self._on_select_model(event=None) 1270 1277 1271 1278 # take care of 2D button 1272 1279 if data == None and self.model_view.IsEnabled(): … … 1275 1282 else: 1276 1283 self.model_view.SetLabel("1D Mode") 1277 1284 1278 1285 ## set the select all check box to the a given state 1279 1286 self.cb1.SetValue(state.cb1) 1280 1287 1281 1288 ## reset state of checkbox,textcrtl and regular parameters value 1282 1289 self._reset_parameters_state(self.orientation_params_disp, … … 1317 1324 self.dI_sqrdata.SetValue(False) 1318 1325 self.dI_idata.SetValue(False) 1319 1326 1320 1327 ## we have two more options for smearing 1321 1328 if self.pinhole_smearer.GetValue(): … … 1333 1340 self.smear_slit_height.SetValue(str(self.dxl)) 1334 1341 if self.dxw != None: 1335 self.smear_slit_width.SetValue(str(self.dxw)) 1342 self.smear_slit_width.SetValue(str(self.dxw)) 1336 1343 else: 1337 self.smear_slit_width.SetValue('') 1344 self.smear_slit_width.SetValue('') 1338 1345 self.onSlitSmear(event=None) 1339 1346 1340 1347 ## reset state of checkbox,textcrtl and dispersity parameters value 1341 1348 self._reset_parameters_state(self.fittable_param, state.fittable_param) 1342 1349 self._reset_parameters_state(self.fixed_param, state.fixed_param) 1343 1350 1344 1351 ## draw the model with previous parameters value 1345 1352 self._onparamEnter_helper() … … 1348 1355 ## reset context menu items 1349 1356 self._reset_context_menu() 1350 1357 1351 1358 ## set the value of the current state to the state given as parameter 1352 1359 self.state = state.clone() 1353 1360 self.state.m_name = self.m_name 1354 1361 1355 1362 def _reset_page_disp_helper(self, state): 1356 1363 """ … … 1367 1374 self.values = copy.deepcopy(state.values) 1368 1375 self.weights = copy.deepcopy(state.weights) 1369 1376 1370 1377 for key, disp in state._disp_obj_dict.iteritems(): 1371 1378 # From saved file, disp_model can not be sent in model obj. … … 1373 1380 if disp.__class__.__name__ == 'str': 1374 1381 disp_model = None 1375 #com_str = "from sas.models.dispersion_models "1376 1382 com_str = "from sasmodels.weights " 1377 1383 com_str += "import %s as disp_func \ndisp_model = disp_func()" … … 1415 1421 except: 1416 1422 logging.error(sys.exc_info()[1]) 1417 1423 1418 1424 # Make sure the check box updated when all checked 1419 1425 if self.cb1.GetValue(): 1420 1426 self.select_all_param(None) 1421 1427 1422 1428 def _selectDlg(self): 1423 1429 """ 1424 open a dialog file to selected the customized dispersity 1430 open a dialog file to selected the customized dispersity 1425 1431 """ 1426 1432 if self.parent != None: … … 1428 1434 self._manager.parent.get_save_location() 1429 1435 dlg = wx.FileDialog(self, "Choose a weight file", 1430 1431 1436 self._default_save_location, "", 1437 "*.*", wx.OPEN) 1432 1438 path = None 1433 1439 if dlg.ShowModal() == wx.ID_OK: … … 1440 1446 reset the context menu 1441 1447 """ 1448 ids = iter(self._id_pool) # Reusing ids for context menu 1442 1449 for name, _ in self.state.saved_states.iteritems(): 1443 1450 self.number_saved_state += 1 1444 1451 ## Add item in the context menu 1445 id = wx.NewId()1452 wx_id = ids.next() 1446 1453 msg = 'Save model and state %g' % self.number_saved_state 1447 self.popUpMenu.Append( id, name, msg)1448 wx.EVT_MENU(self, id, self.onResetModel)1449 1454 self.popUpMenu.Append(wx_id, name, msg) 1455 wx.EVT_MENU(self, wx_id, self.onResetModel) 1456 1450 1457 def _reset_plotting_range(self, state): 1451 1458 """ … … 1466 1473 self.state.formfactorcombobox = self.formfactorbox.GetLabel() 1467 1474 self.state.categorycombobox = self.categorybox.GetLabel() 1468 1475 1469 1476 ## post state to fit panel 1470 1477 event = PageInfoEvent(page=self) 1471 1478 wx.PostEvent(self.parent, event) 1472 1479 1473 1480 def _save_plotting_range(self): 1474 1481 """ … … 1478 1485 self.state.qmax = self.qmax_x 1479 1486 self.state.npts = self.npts_x 1480 1487 1481 1488 def _onparamEnter_helper(self): 1482 1489 """ … … 1495 1502 try: 1496 1503 is_modified = self._check_value_enter(self.fittable_param, 1497 is_modified)1504 is_modified) 1498 1505 is_modified = self._check_value_enter(self.fixed_param, 1499 1506 is_modified) … … 1515 1522 self.qmax_x = tempmax 1516 1523 is_modified = True 1517 1524 1518 1525 if is_2Ddata: 1519 1526 # set mask 1520 1527 is_modified = self._validate_Npts() 1521 1528 1522 1529 else: 1523 1530 self.fitrange = False 1524 1531 1525 1532 if not self.data.is_data: 1526 1533 is_modified = True … … 1542 1549 self.Refresh() 1543 1550 return is_modified 1544 1551 1545 1552 def _update_paramv_on_fit(self): 1546 1553 """ … … 1567 1574 self._check_value_enter(self.parameters, is_modified) 1568 1575 1569 # If qmin and qmax have been modified, update qmin and qmax and 1576 # If qmin and qmax have been modified, update qmin and qmax and 1570 1577 # Here we should check whether the boundaries have been modified. 1571 # If qmin and qmax have been modified, update qmin and qmax and 1578 # If qmin and qmax have been modified, update qmin and qmax and 1572 1579 # set the is_modified flag to True 1573 1580 self.fitrange = self._validate_qrange(self.qmin, self.qmax) … … 1596 1603 qmax=float(self.qmax_x), 1597 1604 enable_smearer=enable_smearer, 1598 1605 draw=False) 1599 1606 elif not self._is_2D(): 1600 1607 enable_smearer = not self.disable_smearer.GetValue() … … 1605 1612 qmax=float(self.qmax_x), 1606 1613 enable_smearer=enable_smearer, 1607 1614 draw=False) 1608 1615 if self.data != None: 1609 1616 index_data = ((self.qmin_x <= self.data.x) & \ … … 1641 1648 msg += " model or Fitting range is not valid!!! " 1642 1649 wx.PostEvent(self._manager.parent, StatusEvent(status=msg)) 1643 1650 1644 1651 try: 1645 1652 self.save_current_state() 1646 1653 except: 1647 1654 logging.error(sys.exc_info()[1]) 1648 1655 1649 1656 return flag 1650 1657 1651 1658 def _is_modified(self, is_modified): 1652 1659 """ … … 1654 1661 """ 1655 1662 return is_modified 1656 1663 1657 1664 def _reset_parameters_state(self, listtorestore, statelist): 1658 1665 """ … … 1693 1700 item_page[5].Show(item_page_info[5][0]) 1694 1701 item_page[5].SetValue(item_page_info[5][1]) 1695 1702 1696 1703 if item_page[6] != None: 1697 1704 ## show of hide the text crtl for fitting error 1698 1705 item_page[6].Show(item_page_info[6][0]) 1699 1706 item_page[6].SetValue(item_page_info[6][1]) 1700 1707 1701 1708 def _reset_strparam_state(self, listtorestore, statelist): 1702 1709 """ … … 1707 1714 1708 1715 listtorestore = copy.deepcopy(statelist) 1709 1716 1710 1717 for j in range(len(listtorestore)): 1711 1718 item_page = listtorestore[j] 1712 1719 item_page_info = statelist[j] 1713 1720 ##change the state of the check box for simple parameters 1714 1721 1715 1722 if item_page[0] != None: 1716 1723 item_page[0].SetValue(format_number(item_page_info[0], True)) … … 1724 1731 item_page[2].SetValue(selection) 1725 1732 self.model.setParam(param_name, selection) 1726 1733 1727 1734 def _copy_parameters_state(self, listtocopy, statelist): 1728 1735 """ 1729 1736 copy the state of button 1730 1737 1731 1738 :param listtocopy: the list of check button to copy 1732 1739 :param statelist: list of state object to store the current state 1733 1740 1734 1741 """ 1735 1742 if len(listtocopy) == 0: 1736 1743 return 1737 1744 1738 1745 for item in listtocopy: 1739 1746 1740 1747 checkbox_state = None 1741 1748 if item[0] != None: … … 1753 1760 error_value = item[4].GetValue() 1754 1761 error_state = item[4].IsShown() 1755 1762 1756 1763 min_value = None 1757 1764 min_state = None … … 1759 1766 min_value = item[5].GetValue() 1760 1767 min_state = item[5].IsShown() 1761 1768 1762 1769 max_value = None 1763 1770 max_state = None … … 1768 1775 if item[7] != None: 1769 1776 unit = item[7].GetLabel() 1770 1777 1771 1778 statelist.append([checkbox_state, parameter_name, parameter_value, 1772 1779 static_text, [error_state, error_value], 1773 1780 [min_state, min_value], 1774 1781 [max_state, max_value], unit]) 1775 1776 1782 1783 1777 1784 def _draw_model(self, update_chisqr=True, source='model'): 1778 1785 """ … … 1780 1787 The method will use the data member from the model page 1781 1788 to build a call to the fitting perspective manager. 1782 1789 1783 1790 :param chisqr: update chisqr value [bool] 1784 1791 """ 1785 1792 wx.CallAfter(self._draw_model_after, update_chisqr, source) 1786 1793 1787 1794 def _draw_model_after(self, update_chisqr=True, source='model'): 1788 1795 """ … … 1790 1797 The method will use the data member from the model page 1791 1798 to build a call to the fitting perspective manager. 1792 1799 1793 1800 :param chisqr: update chisqr value [bool] 1794 1801 """ … … 1818 1825 source='model', 1819 1826 weight=weight) 1820 1827 1821 1828 def _on_show_sld(self, event=None): 1822 1829 """ … … 1833 1840 sld_data.name = 'SLD' 1834 1841 sld_data.axes = self.sld_axes 1835 self.panel = SLDPanel(self, data=sld_data, axes=self.sld_axes, id=-1) 1842 self.panel = SLDPanel(self, data=sld_data, axes=self.sld_axes, 1843 id=wx.ID_ANY) 1836 1844 self.panel.ShowModal() 1837 1845 1838 1846 def _set_multfactor_combobox(self, multiplicity=10): 1839 1847 """ … … 1845 1853 self.multifactorbox.Append(str(idx), int(idx)) 1846 1854 self._hide_multfactor_combobox() 1847 1855 1848 1856 def _show_multfactor_combobox(self): 1849 1857 """ … … 1855 1863 if not self.multifactorbox.IsShown(): 1856 1864 self.multifactorbox.Show(True) 1857 1865 1858 1866 def _hide_multfactor_combobox(self): 1859 1867 """ … … 1865 1873 if self.multifactorbox.IsShown(): 1866 1874 self.multifactorbox.Hide() 1867 1875 1868 1876 def formfactor_combo_init(self): 1869 1877 """ … … 1871 1879 """ 1872 1880 self._show_combox(None) 1873 1881 1874 1882 def _show_combox_helper(self): 1875 1883 """ … … 1904 1912 StatusEvent(status=msg, info="error")) 1905 1913 self._populate_box(self.formfactorbox, m_list) 1906 1907 def _on_modify_cat(self, event=None): 1914 1915 def _on_modify_cat(self, event=None): 1908 1916 """ 1909 1917 Called when category manager is opened 1910 1918 """ 1911 self._manager.parent.on_category_panel(event) 1912 1919 self._manager.parent.on_category_panel(event) 1920 1913 1921 def _show_combox(self, event=None): 1914 1922 """ … … 1924 1932 self.Layout() 1925 1933 self.Refresh() 1926 1934 1927 1935 def _populate_box(self, combobox, list): 1928 1936 """ 1929 1937 fill combox box with dict item 1930 1938 1931 1939 :param list: contains item to fill the combox 1932 1940 item must model class … … 1942 1950 name = model.name 1943 1951 mlist.append((name, models)) 1944 1952 1945 1953 # Sort the models 1946 1954 mlist_sorted = sorted(mlist) … … 1948 1956 combobox.Append(item[0], item[1]) 1949 1957 return 0 1950 1958 1951 1959 def _onQrangeEnter(self, event): 1952 1960 """ 1953 1961 Check validity of value enter in the Q range field 1954 1962 1955 1963 """ 1956 1964 tcrtl = event.GetEventObject() … … 2005 2013 self.create_default_data() 2006 2014 self._draw_model() 2007 2015 2008 2016 def _theory_qrange_enter(self, event): 2009 2017 """ 2010 2018 Check validity of value enter in the Q range field 2011 2019 """ 2012 2020 2013 2021 tcrtl = event.GetEventObject() 2014 2022 #Clear msg if previously shown. … … 2062 2070 self.create_default_data() 2063 2071 self._draw_model() 2064 2072 2065 2073 def _on_select_model_helper(self): 2066 2074 """ … … 2088 2096 self.structurebox.Enable() 2089 2097 self.text2.Enable() 2090 2098 2091 2099 if form_factor != None: 2092 2100 # set multifactor for Mutifunctional models … … 2105 2113 # default value 2106 2114 m_id = 1 2107 2115 2108 2116 self.multi_factor = self.multifactorbox.GetClientData(m_id) 2109 2117 if self.multi_factor == None: … … 2133 2141 self.show_sld_button.Hide() 2134 2142 self.multi_factor = None 2135 2143 2136 2144 s_id = self.structurebox.GetCurrentSelection() 2137 2145 struct_factor = self.structurebox.GetClientData(s_id) 2138 2146 2139 2147 if struct_factor != None: 2140 2148 from sas.models.MultiplicationModel import MultiplicationModel … … 2151 2159 # check if model has magnetic parameters 2152 2160 if len(self.model.magnetic_params) > 0: 2153 self._has_magnetic = True 2161 self._has_magnetic = True 2154 2162 else: 2155 self._has_magnetic = False 2163 self._has_magnetic = False 2156 2164 ## post state to fit panel 2157 2165 self.state.parameters = [] … … 2163 2171 self.on_set_focus(None) 2164 2172 self.Layout() 2165 2173 2166 2174 def _validate_qrange(self, qmin_ctrl, qmax_ctrl): 2167 2175 """ 2168 2176 Verify that the Q range controls have valid values 2169 2177 and that Qmin < Qmax. 2170 2178 2171 2179 :param qmin_ctrl: text control for Qmin 2172 2180 :param qmax_ctrl: text control for Qmax 2173 2181 2174 2182 :return: True is the Q range is value, False otherwise 2175 2183 2176 2184 """ 2177 2185 qmin_validity = check_float(qmin_ctrl) … … 2197 2205 return False 2198 2206 return True 2199 2207 2200 2208 def _validate_Npts(self): 2201 2209 """ … … 2232 2240 self.Npts_fit.SetValue(str(len(index_data[index_data == True]))) 2233 2241 self.fitrange = True 2234 2242 2235 2243 return flag 2236 2244 … … 2267 2275 self.Npts_fit.SetValue(str(len(index_data[index_data == True]))) 2268 2276 self.fitrange = True 2269 2277 2270 2278 return flag 2271 2279 2272 2280 def _check_value_enter(self, list, modified): 2273 2281 """ … … 2291 2299 #try: 2292 2300 name = str(item[1]) 2293 2301 2294 2302 if string.find(name, ".npts") == -1 and \ 2295 2303 string.find(name, ".nsigmas") == -1: … … 2297 2305 param_min = None 2298 2306 param_max = None 2299 2307 2300 2308 ## check minimun value 2301 2309 if item[5] != None and item[5] != "": … … 2306 2314 if numpy.isfinite(param_min): 2307 2315 item[2].SetValue(format_number(param_min)) 2308 2316 2309 2317 item[5].SetBackgroundColour(wx.WHITE) 2310 2318 item[2].SetBackgroundColour(wx.WHITE) 2311 2319 2312 2320 except: 2313 2321 msg = "Wrong fit parameter range entered" … … 2324 2332 if numpy.isfinite(param_max): 2325 2333 item[2].SetValue(format_number(param_max)) 2326 2334 2327 2335 item[6].SetBackgroundColour(wx.WHITE) 2328 2336 item[2].SetBackgroundColour(wx.WHITE) … … 2333 2341 raise ValueError, msg 2334 2342 is_modified = True 2335 2343 2336 2344 if param_min != None and param_max != None: 2337 2345 if not self._validate_qrange(item[5], item[6]): … … 2340 2348 wx.PostEvent(self._manager.parent, 2341 2349 StatusEvent(status=msg)) 2342 2350 2343 2351 if name in self.model.details.keys(): 2344 2352 self.model.details[name][1:3] = param_min, param_max … … 2361 2369 msg = "Wrong Fit parameter value entered " 2362 2370 wx.PostEvent(self._manager.parent, StatusEvent(status=msg)) 2363 2371 2364 2372 return is_modified 2365 2373 2366 2374 def _set_dipers_Param(self, event): 2367 2375 """ … … 2382 2390 2383 2391 self._reset_dispersity() 2384 2392 2385 2393 if self.model == None: 2386 2394 self.model_disp.Hide() … … 2390 2398 if self.enable_disp.GetValue(): 2391 2399 ## layout for model containing no dispersity parameters 2392 2400 2393 2401 self.disp_list = self.model.getDispParamList() 2394 2402 2395 2403 if len(self.disp_list) == 0 and len(self.disp_cb_dict) == 0: 2396 2404 self._layout_sizer_noDipers() … … 2400 2408 else: 2401 2409 self.sizer4_4.Clear(True) 2402 2410 2403 2411 ## post state to fit panel 2404 2412 self.save_current_state() … … 2408 2416 #draw the model with the current dispersity 2409 2417 self._draw_model() 2410 self.sizer4_4.Layout() 2411 self.sizer5.Layout() 2412 self.Layout() 2413 self.Refresh() 2414 2418 ## Need to use FitInside again here to replace the next four lines. 2419 ## Otherwised polydispersity off does not resize the scrollwindow. 2420 ## PDB Nov 28, 2015 2421 self.FitInside() 2422 # self.sizer4_4.Layout() 2423 # self.sizer5.Layout() 2424 # self.Layout() 2425 # self.Refresh() 2426 2415 2427 def _layout_sizer_noDipers(self): 2416 2428 """ … … 2422 2434 self.fixed_param = [] 2423 2435 self.orientation_params_disp = [] 2424 2436 2425 2437 self.sizer4_4.Clear(True) 2426 2438 text = "No polydispersity available for this model" 2427 model_disp = wx.StaticText(self, -1, text)2439 model_disp = wx.StaticText(self, wx.ID_ANY, text) 2428 2440 self.sizer4_4.Add(model_disp, (iy, ix), (1, 1), 2429 2441 wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 10) 2430 2442 self.sizer4_4.Layout() 2431 2443 self.sizer4.Layout() 2432 2444 2433 2445 def _reset_dispersity(self): 2434 2446 """ … … 2443 2455 if item in self.param_toFit: 2444 2456 self.param_toFit.remove(item) 2445 2457 2446 2458 self.fittable_param = [] 2447 2459 self.fixed_param = [] … … 2462 2474 # Go back to Gaussian model (with 0 pts) 2463 2475 disp_model = GaussianDispersion() 2464 2476 2465 2477 self._disp_obj_dict[p] = disp_model 2466 2478 # Set the new model as the dispersion object … … 2475 2487 self.Layout() 2476 2488 self.Refresh() 2477 2489 2478 2490 def _on_select_Disp(self, event): 2479 2491 """ … … 2488 2500 event = PageInfoEvent(page=self) 2489 2501 wx.PostEvent(self.parent, event) 2490 2502 2491 2503 self.sizer4_4.Layout() 2492 2504 self.sizer4.Layout() 2493 2505 self.SetupScrolling() 2494 2506 2495 2507 def _on_disp_func(self, event=None): 2496 2508 """ 2497 2509 Select a distribution function for the polydispersion 2498 2510 2499 2511 :Param event: ComboBox event 2500 2512 """ … … 2512 2524 disp_name = disp_box.GetValue() 2513 2525 dispersity = disp_box.GetClientData(selection) 2514 2526 2515 2527 #disp_model = GaussianDispersion() 2516 2528 disp_model = dispersity() … … 2530 2542 self.model.set_dispersion(param_name, disp_model) 2531 2543 self.state._disp_obj_dict[name1] = disp_model 2532 2544 2533 2545 value1 = str(format_number(self.model.getParam(name1), True)) 2534 2546 value2 = str(format_number(self.model.getParam(name2))) … … 2558 2570 for item in self.fixed_param: 2559 2571 if item[1] == name2: 2560 item[2].SetValue(value2) 2572 item[2].SetValue(value2) 2561 2573 # Disable Npts for array 2562 2574 if disp_name.lower() == "array": … … 2571 2583 else: 2572 2584 item[2].Enable() 2573 2585 2574 2586 # Make sure the check box updated when all checked 2575 2587 if self.cb1.GetValue(): … … 2592 2604 wx.PostEvent(self._manager.parent, 2593 2605 StatusEvent(status=msg, info="error")) 2594 2606 2595 2607 def _set_array_disp(self, name=None, disp=None): 2596 2608 """ 2597 2609 Set array dispersion 2598 2610 2599 2611 :param name: name of the parameter for the dispersion to be set 2600 2612 :param disp: the polydisperion object … … 2613 2625 self._default_save_location = os.path.dirname(path) 2614 2626 if self._manager != None: 2615 self._manager.parent._default_save_location = \2627 self._manager.parent._default_save_location = \ 2616 2628 self._default_save_location 2617 2629 2618 2630 basename = os.path.basename(path) 2619 2631 values, weights = self.read_file(path) 2620 2632 2621 2633 # If any of the two arrays is empty, notify the user that we won't 2622 2634 # proceed … … 2631 2643 values=values, weights=weights) 2632 2644 return basename 2633 2645 2634 2646 def _set_array_disp_model(self, name=None, disp=None, 2635 2647 values=[], weights=[]): 2636 2648 """ 2637 2649 Set array dispersion model 2638 2650 2639 2651 :param name: name of the parameter for the dispersion to be set 2640 2652 :param disp: the polydisperion object … … 2665 2677 self.state.model._persistency_dict[name.split('.')[0]] = \ 2666 2678 [values, weights] 2667 2679 2668 2680 def _del_array_values(self, name=None): 2669 2681 """ 2670 2682 Reset array dispersion 2671 2683 2672 2684 :param name: name of the parameter for the dispersion to be set 2673 2685 """ … … 2683 2695 except: 2684 2696 logging.error(sys.exc_info()[1]) 2685 2697 2686 2698 def _lay_out(self): 2687 2699 """ 2688 2700 returns self.Layout 2689 2701 2690 2702 :Note: Mac seems to like this better when self. 2691 2703 Layout is called after fitting. … … 2694 2706 self.Layout() 2695 2707 return 2696 2708 2697 2709 def _sleep4sec(self): 2698 2710 """ … … 2703 2715 if ON_MAC == True: 2704 2716 time.sleep(1) 2705 2717 2706 2718 def _find_polyfunc_selection(self, disp_func=None): 2707 2719 """ 2708 2720 FInd Comboox selection from disp_func 2709 2721 2710 2722 :param disp_function: dispersion distr. function 2711 2723 """ … … 2721 2733 except: 2722 2734 return 3 2723 2735 2724 2736 def on_reset_clicked(self, event): 2725 2737 """ … … 2733 2745 flag = False 2734 2746 return 2735 2747 2736 2748 elif self.data.__class__.__name__ == "Data2D": 2737 2749 data_min = 0 … … 2739 2751 y = max(math.fabs(self.data.ymin), math.fabs(self.data.ymax)) 2740 2752 self.qmin_x = data_min 2741 self.qmax_x = math.sqrt(x *x + y*y)2753 self.qmax_x = math.sqrt(x * x + y * y) 2742 2754 #self.data.mask = numpy.ones(len(self.data.data),dtype=bool) 2743 2755 # check smearing … … 2749 2761 else: 2750 2762 flag = True 2751 2763 2752 2764 elif self.data == None: 2753 2765 self.qmin_x = _QMIN_DEFAULT … … 2755 2767 self.num_points = _NPTS_DEFAULT 2756 2768 self.state.npts = self.num_points 2757 2769 2758 2770 elif self.data.__class__.__name__ != "Data2D": 2759 2771 self.qmin_x = min(self.data.x) … … 2771 2783 else: 2772 2784 flag = False 2773 2785 2774 2786 if flag == False: 2775 2787 msg = "Cannot Plot :Must enter a number!!! " … … 2788 2800 self.state.qmin = self.qmin_x 2789 2801 self.state.qmax = self.qmax_x 2790 2802 2791 2803 #reset the q range values 2792 2804 self._reset_plotting_range(self.state) 2793 2805 self._draw_model() 2794 2806 2795 2807 def select_log(self, event): 2796 2808 """ … … 2801 2813 """ 2802 2814 Get the images of the plots corresponding this panel for report 2803 2815 2804 2816 : return graphs: list of figures 2805 2817 : Need Move to guiframe … … 2825 2837 # append to the list 2826 2838 graphs.append(item2.figure) 2827 canvases.append(item2.canvas) 2839 canvases.append(item2.canvas) 2828 2840 except: 2829 2841 # Not for control panels … … 2856 2868 name = self.formfactorbox.GetValue() 2857 2869 _PageAnchor = '#' + name.lower() 2858 _doc_viewer = DocumentationWindow(self, -1, _TreeLocation,2870 _doc_viewer = DocumentationWindow(self, wx.ID_ANY, _TreeLocation, 2859 2871 _PageAnchor, name + " Help") 2860 2872 else: 2861 _doc_viewer = DocumentationWindow(self, -1, _TreeLocation, "",2862 2873 _doc_viewer = DocumentationWindow(self, wx.ID_ANY, _TreeLocation, 2874 "", "General Model Help") 2863 2875 2864 2876 … … 2875 2887 :param evt: on Description Button pressed event 2876 2888 """ 2877 2889 2878 2890 if self.model == None: 2879 2891 name = 'index.html' … … 2881 2893 name = self.formfactorbox.GetValue() 2882 2894 2883 2895 msg = 'Model description:\n' 2884 2896 info = "Info" 2885 2897 if self.model != None: 2886 2898 # frame.Destroy() 2887 if str(self.model.description).rstrip().lstrip() == '': 2888 msg += "Sorry, no information is available for this model." 2889 else: 2890 msg += self.model.description + '\n' 2891 wx.MessageBox(msg, info) 2899 if str(self.model.description).rstrip().lstrip() == '': 2900 msg += "Sorry, no information is available for this model." 2892 2901 else: 2902 msg += self.model.description + '\n' 2903 wx.MessageBox(msg, info) 2904 else: 2893 2905 msg += "You must select a model to get information on this" 2894 2906 wx.MessageBox(msg, info) … … 2911 2923 2912 2924 _TreeLocation = "_images/M_angles_pic.bmp" 2913 _doc_viewer = DocumentationWindow(self, -1, _TreeLocation, "",2925 _doc_viewer = DocumentationWindow(self, wx.ID_ANY, _TreeLocation, "", 2914 2926 "Magnetic Angle Defintions") 2915 2927 2916 def _on_mag_help(self, event): 2928 def _on_mag_help(self, event): 2917 2929 """ 2918 2930 Bring up Magnetic Angle definition bmp image whenever the ? button … … 2931 2943 2932 2944 _TreeLocation = "user/perspectives/fitting/mag_help.html" 2933 _doc_viewer = DocumentationWindow(self, -1, _TreeLocation, "",2945 _doc_viewer = DocumentationWindow(self, wx.ID_ANY, _TreeLocation, "", 2934 2946 "Polarized Beam/Magnetc Help") 2935 2947 2936 def _on_mag_on(self, event): 2948 def _on_mag_on(self, event): 2937 2949 """ 2938 2950 Magnetic Parameters ON/OFF … … 2955 2967 #reset mag value to zero fo safety 2956 2968 self.model.setParam(key, 0.0) 2957 2958 self.Show(False) 2969 2970 self.Show(False) 2959 2971 self.set_model_param_sizer(self.model) 2960 2972 #self._set_sizer_dispersion() … … 2962 2974 self.SetupScrolling() 2963 2975 self.Show(True) 2964 2976 2965 2977 def on_pd_help_clicked(self, event): 2966 2978 """ … … 2972 2984 webbrowser does not pass anything past the # to the browser when it is 2973 2985 running "file:///...." 2974 2986 2975 2987 :param evt: Triggers on clicking ? in polydispersity box 2976 2988 """ … … 2978 2990 _TreeLocation = "user/perspectives/fitting/pd_help.html" 2979 2991 _PageAnchor = "" 2980 _doc_viewer = DocumentationWindow(self, -1, _TreeLocation,2992 _doc_viewer = DocumentationWindow(self, wx.ID_ANY, _TreeLocation, 2981 2993 _PageAnchor, "Polydispersity Help") 2982 2994 2983 2995 def on_left_down(self, event): 2984 2996 """ … … 2995 3007 # make event free 2996 3008 event.Skip() 2997 3009 2998 3010 def get_copy(self): 2999 3011 """ … … 3004 3016 self._copy_info(flag) 3005 3017 return flag 3006 3018 3007 3019 def get_copy_params(self): 3008 3020 """ … … 3012 3024 # Do it if params exist 3013 3025 if self.parameters != []: 3014 3026 3015 3027 # go through the parameters 3016 3028 strings = self._get_copy_helper(self.parameters, 3017 3029 self.orientation_params) 3018 3030 content += strings 3019 3031 3020 3032 # go through the fittables 3021 3033 strings = self._get_copy_helper(self.fittable_param, … … 3027 3039 self.orientation_params_disp) 3028 3040 content += strings 3029 3041 3030 3042 # go through the str params 3031 3043 strings = self._get_copy_helper(self.str_parameters, … … 3060 3072 content += param[1] #parameter name 3061 3073 content += tab 3062 content += param[1] +"_err"3074 content += param[1] + "_err" 3063 3075 content += tab 3064 3076 … … 3068 3080 for param in self.parameters: 3069 3081 content += param[2].GetValue() #value 3070 content += tab3082 content += tab 3071 3083 content += param[4].GetValue() #error 3072 content += tab3084 content += tab 3073 3085 3074 3086 return content … … 3106 3118 3107 3119 for index, param in enumerate(self.parameters): 3108 content += param[1].replace('_', '\_') #parameter name3120 content += param[1].replace('_', '\_') #parameter name 3109 3121 content += ' & ' 3110 content += param[1].replace('_', '\_')+"\_err"3111 if index < len(self.parameters) -1:3122 content += param[1].replace('_', '\_') + "\_err" 3123 if index < len(self.parameters) - 1: 3112 3124 content += ' & ' 3113 3125 content += '\\\\ \\hline' … … 3119 3131 content += ' & ' 3120 3132 content += param[4].GetValue() #parameter error 3121 if index < len(self.parameters) -1:3133 if index < len(self.parameters) - 1: 3122 3134 content += ' & ' 3123 3135 content += '\\\\ \\hline' … … 3142 3154 return True 3143 3155 return None 3144 3156 3145 3157 def _get_copy_helper(self, param, orient_param): 3146 3158 """ 3147 3159 Helping get value and name of the params 3148 3160 3149 3161 : param param: parameters 3150 3162 : param orient_param = oritational params … … 3163 3175 except: 3164 3176 logging.error(sys.exc_info()[1]) 3165 3177 3166 3178 # 2D 3167 3179 if self.data.__class__.__name__ == "Data2D": … … 3185 3197 # add to the content 3186 3198 if disfunc != '': 3187 3199 3188 3200 disfunc = ',' + disfunc 3189 3201 # Need to support array func for copy/paste … … 3201 3213 3202 3214 return content 3203 3215 3204 3216 def get_clipboard(self): 3205 3217 """ … … 3221 3233 wx.TheClipboard.Close() 3222 3234 return text 3223 3235 3224 3236 def get_paste(self): 3225 3237 """ … … 3230 3242 self._copy_info(flag) 3231 3243 return flag 3232 3244 3233 3245 def get_paste_params(self, text=''): 3234 3246 """ … … 3259 3271 val = [float(a_val) for a_val in array_values[1:]] 3260 3272 weit = [float(a_weit) for a_weit in array_weights[1:]] 3261 3273 3262 3274 context[name].append(val) 3263 3275 context[name].append(weit) … … 3282 3294 self._get_paste_helper(self.fixed_param, 3283 3295 self.orientation_params_disp, context) 3284 3296 3285 3297 # go through the str params 3286 3298 self._get_paste_helper(self.str_parameters, 3287 3299 self.orientation_params, context) 3288 3300 3289 3301 return True 3290 3302 return None 3291 3303 3292 3304 def _get_paste_helper(self, param, orient_param, content): 3293 3305 """ 3294 3306 Helping set values of the params 3295 3307 3296 3308 : param param: parameters 3297 3309 : param orient_param: oritational params … … 3321 3333 fun_val = self.model.fun_list[content[name][1]] 3322 3334 self.model.setParam(name, fun_val) 3323 3335 3324 3336 value = content[name][1:] 3325 3337 self._paste_poly_help(item, value) … … 3367 3379 if is_true != None: 3368 3380 item[0].SetValue(is_true) 3369 3381 3370 3382 def _paste_poly_help(self, item, value): 3371 3383 """ 3372 3384 Helps get paste for poly function 3373 3385 3374 3386 :param item: Gui param items 3375 3387 :param value: the values for parameter ctrols … … 3411 3423 [self.state.values, 3412 3424 self.state.weights] 3413 3425 3414 3426 except: 3415 3427 logging.error(sys.exc_info()[1]) 3416 3428 print "Error in BasePage._paste_poly_help: %s" % \ 3417 3429 sys.exc_info()[1] 3418 3430 3419 3431 def _set_disp_array_cb(self, item): 3420 3432 """ … … 3430 3442 item[6].SetValue('') 3431 3443 item[6].Enable(False) 3432 3444 3433 3445 def update_pinhole_smear(self): 3434 3446 """ … … 3452 3464 if not os.path.isfile(categorization_file): 3453 3465 categorization_file = CategoryInstaller.get_default_file() 3454 cat_file = open(categorization_file, 'rb') 3466 cat_file = open(categorization_file, 'rb') 3455 3467 self.master_category_dict = json.load(cat_file) 3456 3468 self._regenerate_model_dict() … … 3464 3476 def _regenerate_model_dict(self): 3465 3477 """ 3466 regenerates self.by_model_dict which has each model name as the 3478 regenerates self.by_model_dict which has each model name as the 3467 3479 key and the list of categories belonging to that model 3468 3480 along with the enabled mapping … … 3473 3485 self.by_model_dict[model].append(category) 3474 3486 self.model_enabled_dict[model] = enabled 3475 3487 3476 3488 def _populate_listbox(self): 3477 3489 """ … … 3485 3497 if not uncat_str in cat_list: 3486 3498 cat_list.append(uncat_str) 3487 3499 3488 3500 for category in cat_list: 3489 3501 if category != '': … … 3493 3505 self.categorybox.SetSelection(0) 3494 3506 else: 3495 self.categorybox.SetSelection( 3507 self.categorybox.SetSelection(\ 3496 3508 self.categorybox.GetSelection()) 3497 3509 #self._on_change_cat(None) … … 3513 3525 3514 3526 else: 3515 for (model, enabled) in sorted(self.master_category_dict[category],3516 key =lambda name: name[0]):3527 for (model, enabled) in sorted(self.master_category_dict[category], 3528 key=lambda name: name[0]): 3517 3529 if(enabled): 3518 3530 self.model_box.Append(model) … … 3522 3534 fill sizer containing model info 3523 3535 """ 3536 # This should only be called once per fit tab 3537 #print "==== Entering _fill_model_sizer" 3524 3538 ##Add model function Details button in fitpanel. 3525 3539 ##The following 3 lines are for Mac. Let JHC know before modifying... … … 3527 3541 self.formfactorbox = None 3528 3542 self.multifactorbox = None 3529 self.mbox_description = wx.StaticBox(self, -1, str(title))3543 self.mbox_description = wx.StaticBox(self, wx.ID_ANY, str(title)) 3530 3544 boxsizer1 = wx.StaticBoxSizer(self.mbox_description, wx.VERTICAL) 3531 3545 sizer_cat = wx.BoxSizer(wx.HORIZONTAL) 3532 3546 self.mbox_description.SetForegroundColour(wx.RED) 3533 id = wx.NewId() 3534 self.model_func = wx.Button(self, id, 'Help', size=(80, 23)) 3535 self.model_func.Bind(wx.EVT_BUTTON, self.on_function_help_clicked, id=id) 3547 wx_id = self._ids.next() 3548 self.model_func = wx.Button(self, wx_id, 'Help', size=(80, 23)) 3549 self.model_func.Bind(wx.EVT_BUTTON, self.on_function_help_clicked, 3550 id=wx_id) 3536 3551 self.model_func.SetToolTipString("Full Model Function Help") 3537 id = wx.NewId() 3538 self.model_help = wx.Button(self, id, 'Description', size=(80, 23)) 3539 self.model_help.Bind(wx.EVT_BUTTON, self.on_model_help_clicked, id=id) 3552 wx_id = self._ids.next() 3553 self.model_help = wx.Button(self, wx_id, 'Description', size=(80, 23)) 3554 self.model_help.Bind(wx.EVT_BUTTON, self.on_model_help_clicked, 3555 id=wx_id) 3540 3556 self.model_help.SetToolTipString("Short Model Function Description") 3541 id = wx.NewId()3542 self.model_view = wx.Button(self, id, "Show 2D", size=(80, 23))3543 self.model_view.Bind(wx.EVT_BUTTON, self._onModel2D, id= id)3557 wx_id = self._ids.next() 3558 self.model_view = wx.Button(self, wx_id, "Show 2D", size=(80, 23)) 3559 self.model_view.Bind(wx.EVT_BUTTON, self._onModel2D, id=wx_id) 3544 3560 hint = "toggle view of model from 1D to 2D or 2D to 1D" 3545 3561 self.model_view.SetToolTipString(hint) 3546 3547 cat_set_box = wx.StaticBox(self, -1, 'Category')3562 3563 cat_set_box = wx.StaticBox(self, wx.ID_ANY, 'Category') 3548 3564 sizer_cat_box = wx.StaticBoxSizer(cat_set_box, wx.HORIZONTAL) 3549 3565 sizer_cat_box.SetMinSize((200, 50)) 3550 self.categorybox = wx.ComboBox(self, -1, style=wx.CB_READONLY) 3551 self.categorybox.SetToolTip( wx.ToolTip("Select a Category/Type") ) 3566 self.categorybox = wx.ComboBox(self, wx.ID_ANY, 3567 style=wx.CB_READONLY) 3568 self.categorybox.SetToolTip(wx.ToolTip("Select a Category/Type")) 3552 3569 self._populate_listbox() 3553 wx.EVT_COMBOBOX(self.categorybox, -1, self._show_combox)3554 #self.shape_rbutton = wx.RadioButton(self, -1, 'Shapes',3570 wx.EVT_COMBOBOX(self.categorybox, wx.ID_ANY, self._show_combox) 3571 #self.shape_rbutton = wx.RadioButton(self, wx.ID_ANY, 'Shapes', 3555 3572 # style=wx.RB_GROUP) 3556 #self.shape_indep_rbutton = wx.RadioButton(self, -1,3573 #self.shape_indep_rbutton = wx.RadioButton(self, wx.ID_ANY, 3557 3574 # "Shape-Independent") 3558 #self.struct_rbutton = wx.RadioButton(self, -1, "Structure Factor ") 3559 #self.plugin_rbutton = wx.RadioButton(self, -1, "Uncategorized") 3560 3575 #self.struct_rbutton = wx.RadioButton(self, wx.ID_ANY, 3576 # "Structure Factor ") 3577 #self.plugin_rbutton = wx.RadioButton(self, wx.ID_ANY, 3578 # "Uncategorized") 3579 3561 3580 #self.Bind(wx.EVT_RADIOBUTTON, self._show_combox, 3562 3581 # id=self.shape_rbutton.GetId()) … … 3568 3587 # id=self.plugin_rbutton.GetId()) 3569 3588 #MAC needs SetValue 3570 3571 show_cat_button = wx.Button(self, -1, "Modify")3589 3590 show_cat_button = wx.Button(self, wx.ID_ANY, "Modify") 3572 3591 cat_tip = "Modify model categories \n" 3573 3592 cat_tip += "(also accessible from the menu bar)." … … 3594 3613 sizer_selection = wx.BoxSizer(wx.HORIZONTAL) 3595 3614 mutifactor_selection = wx.BoxSizer(wx.HORIZONTAL) 3596 3597 self.text1 = wx.StaticText(self, -1, "")3598 self.text2 = wx.StaticText(self, -1, "P(Q)*S(Q)")3599 self.mutifactor_text = wx.StaticText(self, -1, "No. of Shells: ")3600 self.mutifactor_text1 = wx.StaticText(self, -1, "")3601 self.show_sld_button = wx.Button(self, -1, "Show SLD Profile")3615 3616 self.text1 = wx.StaticText(self, wx.ID_ANY, "") 3617 self.text2 = wx.StaticText(self, wx.ID_ANY, "P(Q)*S(Q)") 3618 self.mutifactor_text = wx.StaticText(self, wx.ID_ANY, "No. of Shells: ") 3619 self.mutifactor_text1 = wx.StaticText(self, wx.ID_ANY, "") 3620 self.show_sld_button = wx.Button(self, wx.ID_ANY, "Show SLD Profile") 3602 3621 self.show_sld_button.Bind(wx.EVT_BUTTON, self._on_show_sld) 3603 3622 3604 self.formfactorbox = wx.ComboBox(self, -1, style=wx.CB_READONLY)3605 self.formfactorbox.SetToolTip( wx.ToolTip("Select a Model"))3623 self.formfactorbox = wx.ComboBox(self, wx.ID_ANY, style=wx.CB_READONLY) 3624 self.formfactorbox.SetToolTip(wx.ToolTip("Select a Model")) 3606 3625 if self.model != None: 3607 3626 self.formfactorbox.SetValue(self.model.name) 3608 self.structurebox = wx.ComboBox(self, -1, style=wx.CB_READONLY)3609 self.multifactorbox = wx.ComboBox(self, -1, style=wx.CB_READONLY)3627 self.structurebox = wx.ComboBox(self, wx.ID_ANY, style=wx.CB_READONLY) 3628 self.multifactorbox = wx.ComboBox(self, wx.ID_ANY, style=wx.CB_READONLY) 3610 3629 self.initialize_combox() 3611 wx.EVT_COMBOBOX(self.formfactorbox, -1, self._on_select_model)3612 3613 wx.EVT_COMBOBOX(self.structurebox, -1, self._on_select_model)3614 wx.EVT_COMBOBOX(self.multifactorbox, -1, self._on_select_model)3630 wx.EVT_COMBOBOX(self.formfactorbox, wx.ID_ANY, self._on_select_model) 3631 3632 wx.EVT_COMBOBOX(self.structurebox, wx.ID_ANY, self._on_select_model) 3633 wx.EVT_COMBOBOX(self.multifactorbox, wx.ID_ANY, self._on_select_model) 3615 3634 ## check model type to show sizer 3616 3635 if self.model != None: 3617 3636 print "_set_model_sizer_selection: disabled." 3618 3637 #self._set_model_sizer_selection(self.model) 3619 3638 3620 3639 sizer_selection.Add(self.text1) 3621 3640 sizer_selection.Add((10, 5)) … … 3625 3644 sizer_selection.Add((5, 5)) 3626 3645 sizer_selection.Add(self.structurebox) 3627 3646 3628 3647 mutifactor_selection.Add((13, 5)) 3629 3648 mutifactor_selection.Add(self.mutifactor_text) … … 3639 3658 boxsizer1.Add((10, 10)) 3640 3659 boxsizer1.Add(mutifactor_selection) 3641 3660 3642 3661 self._set_multfactor_combobox() 3643 3662 self.multifactorbox.SetSelection(1) … … 3645 3664 sizer.Add(boxsizer1, 0, wx.EXPAND | wx.ALL, 10) 3646 3665 sizer.Layout() 3647 3666 3648 3667 def on_smear_helper(self, update=False): 3649 3668 """ 3650 3669 Help for onSmear if implemented 3651 3670 3652 3671 :param update: force or not to update 3653 3672 """ … … 3658 3677 def onSmear(self, event): 3659 3678 """ 3660 Create a smear object if implemented 3679 Create a smear object if implemented 3661 3680 """ 3662 3681 def onPinholeSmear(self, event): -
src/sas/perspectives/fitting/batchfitpage.py
r373d4ee r6f16e25 38 38 fill sizer 0 with data info 39 39 """ 40 self.data_box_description = wx.StaticBox(self, -1, 'I(q) Data Source')40 self.data_box_description = wx.StaticBox(self, wx.ID_ANY, 'I(q) Data Source') 41 41 if check_data_validity(self.data): 42 42 dname_color = wx.BLUE … … 47 47 #---------------------------------------------------------- 48 48 sizer_data = wx.BoxSizer(wx.VERTICAL) 49 text1 = wx.StaticText(self, -1, ' - Choose a file to set initial fit parameters -')49 text1 = wx.StaticText(self, wx.ID_ANY, ' - Choose a file to set initial fit parameters -') 50 50 text1.SetForegroundColour(wx.RED) 51 51 sizer_data.Add(text1) 52 text2 = wx.StaticText(self, -1, ' - This panel is not designed to view individual fits. - ')52 text2 = wx.StaticText(self, wx.ID_ANY, ' - This panel is not designed to view individual fits. - ') 53 53 text2.SetForegroundColour(wx.RED) 54 54 sizer_data.Add(text2) 55 55 56 56 combo = wx.BoxSizer(wx.HORIZONTAL) 57 self.dataSource = wx.ComboBox(self, -1, style=wx.CB_READONLY)58 wx.EVT_COMBOBOX(self.dataSource, -1, self.on_select_data)57 self.dataSource = wx.ComboBox(self, wx.ID_ANY, style=wx.CB_READONLY) 58 wx.EVT_COMBOBOX(self.dataSource, wx.ID_ANY, self.on_select_data) 59 59 self.dataSource.SetMinSize((_DATA_BOX_WIDTH, -1)) 60 60 61 combo.Add(wx.StaticText(self, -1, 'Name : '))61 combo.Add(wx.StaticText(self, wx.ID_ANY, 'Name : ')) 62 62 combo.Add((0, 5)) 63 63 combo.Add(self.dataSource) … … 86 86 # 87 87 # #Sizers 88 # box_description_range = wx.StaticBox(self, -1, str(title))88 # box_description_range = wx.StaticBox(self, wx.ID_ANY, str(title)) 89 89 # boxsizer_range = wx.StaticBoxSizer(box_description_range, wx.VERTICAL) 90 90 # self.sizer_set_smearer = wx.BoxSizer(wx.VERTICAL) … … 96 96 # sizer_fit = wx.GridSizer(2, 4, 2, 6) 97 97 # #Fit button 98 # self.btFit = wx.Button(self, wx.NewId(), 'Fit', size=(88, 25))98 # self.btFit = wx.Button(self, self._ids.next(), 'Fit', size=(88, 25)) 99 99 # self.default_bt_colour = self.btFit.GetDefaultAttributes() 100 100 # self.btFit.Bind(wx.EVT_BUTTON, self._onFit, id= self.btFit.GetId()) … … 102 102 # 103 103 # # Update and Draw button 104 # self.draw_button = wx.Button(self, wx.NewId(), 'Compute', size=(88, 24))104 # self.draw_button = wx.Button(self, self._ids.next(), 'Compute', size=(88, 24)) 105 105 # self.draw_button.Bind(wx.EVT_BUTTON, \ 106 106 # self._onDraw,id=self.draw_button.GetId()) … … 122 122 # self.sizer5.Clear(True) 123 123 # 124 # self.qmin = ModelTextCtrl(self, -1, size=(_BOX_WIDTH, 20),124 # self.qmin = ModelTextCtrl(self, wx.ID_ANY, size=(_BOX_WIDTH, 20), 125 125 # style=wx.TE_PROCESS_ENTER, 126 126 # text_enter_callback = self._onQrangeEnter) … … 128 128 # self.qmin.SetToolTipString("Minimun value of Q in linear scale.") 129 129 # 130 # self.qmax = ModelTextCtrl(self, -1, size=(_BOX_WIDTH, 20),130 # self.qmax = ModelTextCtrl(self, wx.ID_ANY, size=(_BOX_WIDTH, 20), 131 131 # style=wx.TE_PROCESS_ENTER, 132 132 # text_enter_callback=self._onQrangeEnter) … … 134 134 # self.qmax.SetToolTipString("Maximum value of Q in linear scale.") 135 135 # 136 # id = wx.NewId()136 # id = self._ids.next() 137 137 # self.reset_qrange =wx.Button(self, id, 'Reset', size=(77, 20)) 138 138 # … … 144 144 # sizer = wx.GridSizer(2, 4, 2, 6) 145 145 # 146 # self.btEditMask = wx.Button(self, wx.NewId(),'Editor', size=(88, 23))146 # self.btEditMask = wx.Button(self, self._ids.next(),'Editor', size=(88, 23)) 147 147 # self.btEditMask.Bind(wx.EVT_BUTTON, 148 148 # self._onMask,id=self.btEditMask.GetId()) 149 149 # self.btEditMask.SetToolTipString("Edit Mask.") 150 # self.EditMask_title = wx.StaticText(self, -1, ' Masking(2D)')151 # 152 # sizer.Add(wx.StaticText(self, -1, 'Q range'))153 # sizer.Add(wx.StaticText(self, -1, ' Min[1/A]'))154 # sizer.Add(wx.StaticText(self, -1, ' Max[1/A]'))150 # self.EditMask_title = wx.StaticText(self, wx.ID_ANY, ' Masking(2D)') 151 # 152 # sizer.Add(wx.StaticText(self, wx.ID_ANY, 'Q range')) 153 # sizer.Add(wx.StaticText(self, wx.ID_ANY, ' Min[1/A]')) 154 # sizer.Add(wx.StaticText(self, wx.ID_ANY, ' Max[1/A]')) 155 155 # sizer.Add(self.EditMask_title) 156 156 # -
src/sas/perspectives/fitting/fitpage.py
rcd5e29b r1c2bf90 34 34 FitPanel class contains fields allowing to display results when 35 35 fitting a model and one data 36 36 37 37 :note: For Fit to be performed the user should check at least one parameter 38 38 on fit Panel window. … … 44 44 """ 45 45 BasicPage.__init__(self, parent, color=color) 46 46 47 47 ## draw sizer 48 48 self._fill_data_sizer() … … 71 71 self.create_default_data() 72 72 self._manager.frame.Bind(wx.EVT_SET_FOCUS, self.on_set_focus) 73 73 74 74 def enable_fit_button(self): 75 75 """ … … 93 93 fill sizer 0 with data info 94 94 """ 95 self.data_box_description = wx.StaticBox(self, -1, 'I(q) Data Source') 95 self.data_box_description = wx.StaticBox(self, wx.ID_ANY, 96 'I(q) Data Source') 96 97 if check_data_validity(self.data): 97 98 dname_color = wx.BLUE … … 102 103 #---------------------------------------------------------- 103 104 sizer_data = wx.BoxSizer(wx.HORIZONTAL) 104 self.dataSource = wx.ComboBox(self, -1, style=wx.CB_READONLY)105 wx.EVT_COMBOBOX(self.dataSource, -1, self.on_select_data)105 self.dataSource = wx.ComboBox(self, wx.ID_ANY, style=wx.CB_READONLY) 106 wx.EVT_COMBOBOX(self.dataSource, wx.ID_ANY, self.on_select_data) 106 107 self.dataSource.SetMinSize((_DATA_BOX_WIDTH, -1)) 107 sizer_data.Add(wx.StaticText(self, -1, 'Name : '))108 sizer_data.Add(wx.StaticText(self, wx.ID_ANY, 'Name : ')) 108 109 sizer_data.Add(self.dataSource) 109 110 sizer_data.Add((0, 5)) … … 111 112 self.sizer0.Add(boxsizer1, 0, wx.EXPAND | wx.ALL, 10) 112 113 self.sizer0.Layout() 113 114 114 115 def enable_datasource(self): 115 116 """ … … 120 121 else: 121 122 self.dataSource.Enable() 122 123 123 124 def fill_data_combobox(self, data_list): 124 125 """ … … 155 156 if len(data_list) == 1: 156 157 self.dataSource.Disable() 157 158 158 159 def on_select_data(self, event=None): 159 160 """ … … 167 168 data = self.dataSource.GetClientData(pos) 168 169 self.set_data(data) 169 170 170 171 def _on_fit_complete(self): 171 172 """ … … 174 175 self.fit_started = False 175 176 self.set_fitbutton() 176 177 177 178 def _is_2D(self): 178 179 """ 179 180 Check if data_name is Data2D 180 181 181 182 :return: True or False 182 183 183 184 """ 184 185 if self.data.__class__.__name__ == "Data2D" or \ … … 186 187 return True 187 188 return False 188 189 189 190 def _fill_range_sizer(self): 190 191 """ … … 195 196 """ 196 197 is_2Ddata = False 197 198 198 199 # Check if data is 2D 199 200 if self.data.__class__.__name__ == "Data2D" or \ 200 201 self.enable2D: 201 202 is_2Ddata = True 202 203 203 204 title = "Fitting" 204 205 #smear messages & titles … … 217 218 smear_message_slit_height_title = "Slit height[1/A]:" 218 219 smear_message_slit_width_title = "Slit width[1/A]:" 219 220 220 221 self._get_smear_info() 221 222 222 223 #Sizers 223 box_description_range = wx.StaticBox(self, -1, str(title))224 box_description_range = wx.StaticBox(self, wx.ID_ANY, str(title)) 224 225 box_description_range.SetForegroundColour(wx.BLUE) 225 226 boxsizer_range = wx.StaticBoxSizer(box_description_range, wx.VERTICAL) … … 229 230 self.sizer_set_masking = wx.BoxSizer(wx.HORIZONTAL) 230 231 sizer_chi2 = wx.BoxSizer(wx.VERTICAL) 231 smear_set_box = wx.StaticBox(self, -1, 'Set Instrumental Smearing') 232 smear_set_box = wx.StaticBox(self, wx.ID_ANY, 233 'Set Instrumental Smearing') 232 234 sizer_smearer_box = wx.StaticBoxSizer(smear_set_box, wx.HORIZONTAL) 233 235 sizer_smearer_box.SetMinSize((_DATA_BOX_WIDTH, 60)) 234 235 weighting_set_box = wx.StaticBox(self, -1, \236 237 weighting_set_box = wx.StaticBox(self, wx.ID_ANY, 236 238 'Set Weighting by Selecting dI Source') 237 239 weighting_box = wx.StaticBoxSizer(weighting_set_box, wx.HORIZONTAL) … … 239 241 weighting_box.SetMinSize((_DATA_BOX_WIDTH, 40)) 240 242 #Filling the sizer containing weighting info. 241 self.dI_noweight = wx.RadioButton(self, -1, 'No Weighting',242 style=wx.RB_GROUP)243 self.dI_didata = wx.RadioButton(self, -1, 'Use dI Data')244 self.dI_sqrdata = wx.RadioButton(self, -1, 'Use |sqrt(I Data)|')245 self.dI_idata = wx.RadioButton(self, -1, 'Use |I Data|')243 self.dI_noweight = wx.RadioButton(self, wx.ID_ANY, 244 'No Weighting', style=wx.RB_GROUP) 245 self.dI_didata = wx.RadioButton(self, wx.ID_ANY, 'Use dI Data') 246 self.dI_sqrdata = wx.RadioButton(self, wx.ID_ANY, 'Use |sqrt(I Data)|') 247 self.dI_idata = wx.RadioButton(self, wx.ID_ANY, 'Use |I Data|') 246 248 self.Bind(wx.EVT_RADIOBUTTON, self.onWeighting, 247 249 id=self.dI_noweight.GetId()) … … 267 269 self.dI_idata.Enable(False) 268 270 weighting_box.Add(sizer_weighting) 269 271 270 272 # combobox for smear2d accuracy selection 271 self.smear_accuracy = wx.ComboBox(self, -1, size=(50, -1),272 s tyle=wx.CB_READONLY)273 self.smear_accuracy = wx.ComboBox(self, wx.ID_ANY, 274 size=(50, -1), style=wx.CB_READONLY) 273 275 self._set_accuracy_list() 274 276 self.smear_accuracy.SetValue(self.smear2d_accuracy) 275 277 self.smear_accuracy.SetSelection(0) 276 self.smear_accuracy.SetToolTipString( \278 self.smear_accuracy.SetToolTipString( 277 279 "'Higher' uses more Gaussian points for smearing computation.") 278 279 wx.EVT_COMBOBOX(self.smear_accuracy, -1, self._on_select_accuracy) 280 281 wx.EVT_COMBOBOX(self.smear_accuracy, wx.ID_ANY, 282 self._on_select_accuracy) 280 283 281 284 #Fit button 282 self.btFit = wx.Button(self, wx.NewId(), 'Fit')285 self.btFit = wx.Button(self, self._ids.next(), 'Fit') 283 286 self.default_bt_colour = self.btFit.GetDefaultAttributes() 284 287 self.btFit.Bind(wx.EVT_BUTTON, self._onFit, id=self.btFit.GetId()) 285 288 self.btFit.SetToolTipString("Start fitting.") 286 289 287 290 #General Help button 288 self.btFitHelp = wx.Button(self, -1, 'Help')291 self.btFitHelp = wx.Button(self, wx.ID_ANY, 'Help') 289 292 self.btFitHelp.SetToolTipString("General fitting help.") 290 293 self.btFitHelp.Bind(wx.EVT_BUTTON, self._onFitHelp) … … 299 302 else: 300 303 size_q = (30, 20) #on MAC 301 self.btSmearHelp = wx.Button(self, -1, '?', style=wx.BU_EXACTFIT,\302 s ize=size_q)304 self.btSmearHelp = wx.Button(self, wx.ID_ANY, '?', 305 style=wx.BU_EXACTFIT, size=size_q) 303 306 self.btSmearHelp.SetToolTipString("Resolution smearing help.") 304 307 self.btSmearHelp.Bind(wx.EVT_BUTTON, self._onSmearHelp) 305 308 306 309 #textcntrl for custom resolution 307 self.smear_pinhole_max = ModelTextCtrl(self, -1,310 self.smear_pinhole_max = ModelTextCtrl(self, wx.ID_ANY, 308 311 size=(_BOX_WIDTH - 25, 20), 309 312 style=wx.TE_PROCESS_ENTER, 310 313 text_enter_callback=self.onPinholeSmear) 311 self.smear_pinhole_min = ModelTextCtrl(self, -1,314 self.smear_pinhole_min = ModelTextCtrl(self, wx.ID_ANY, 312 315 size=(_BOX_WIDTH - 25, 20), 313 316 style=wx.TE_PROCESS_ENTER, 314 317 text_enter_callback=self.onPinholeSmear) 315 self.smear_slit_height = ModelTextCtrl(self, -1,318 self.smear_slit_height = ModelTextCtrl(self, wx.ID_ANY, 316 319 size=(_BOX_WIDTH - 25, 20), 317 320 style=wx.TE_PROCESS_ENTER, 318 321 text_enter_callback=self.onSlitSmear) 319 self.smear_slit_width = ModelTextCtrl(self, -1,322 self.smear_slit_width = ModelTextCtrl(self, wx.ID_ANY, 320 323 size=(_BOX_WIDTH - 25, 20), 321 324 style=wx.TE_PROCESS_ENTER, … … 323 326 324 327 ## smear 325 self.smear_data_left = BGTextCtrl(self, -1,326 size=(_BOX_WIDTH - 25, 20), style=0)328 self.smear_data_left = BGTextCtrl(self, wx.ID_ANY, 329 size=(_BOX_WIDTH - 25, 20), style=0) 327 330 self.smear_data_left.SetValue(str(self.dq_l)) 328 self.smear_data_right = BGTextCtrl(self, -1,329 size=(_BOX_WIDTH - 25, 20), style=0)331 self.smear_data_right = BGTextCtrl(self, wx.ID_ANY, 332 size=(_BOX_WIDTH - 25, 20), style=0) 330 333 self.smear_data_right.SetValue(str(self.dq_r)) 331 334 … … 337 340 338 341 #Filling the sizer containing instruments smearing info. 339 self.disable_smearer = wx.RadioButton(self, -1,342 self.disable_smearer = wx.RadioButton(self, wx.ID_ANY, 340 343 'None', style=wx.RB_GROUP) 341 self.enable_smearer = wx.RadioButton(self, -1, 342 'Use dQ Data') 344 self.enable_smearer = wx.RadioButton(self, wx.ID_ANY, 'Use dQ Data') 343 345 #self.enable_smearer.SetToolTipString( 344 346 #"Click to use the loaded dQ data for smearing.") 345 self.pinhole_smearer = wx.RadioButton(self, -1,347 self.pinhole_smearer = wx.RadioButton(self, wx.ID_ANY, 346 348 'Custom Pinhole Smear') 347 349 #self.pinhole_smearer.SetToolTipString 348 350 #("Click to input custom resolution for pinhole smearing.") 349 self.slit_smearer = wx.RadioButton(self, -1, 'Custom Slit Smear')351 self.slit_smearer = wx.RadioButton(self, wx.ID_ANY, 'Custom Slit Smear') 350 352 #self.slit_smearer.SetToolTipString 351 353 #("Click to input custom resolution for slit smearing.") … … 359 361 id=self.slit_smearer.GetId()) 360 362 self.disable_smearer.SetValue(True) 361 363 362 364 sizer_smearer.Add(self.disable_smearer, 0, wx.LEFT, 10) 363 365 sizer_smearer.Add(self.enable_smearer) … … 366 368 sizer_smearer.Add(self.btSmearHelp) 367 369 sizer_smearer.Add((10, 10)) 368 370 369 371 # StaticText for chi2, N(for fitting), Npts + Log/linear spacing 370 self.tcChi = BGTextCtrl(self, -1, "-", size=(75, 20), style=0)372 self.tcChi = BGTextCtrl(self, wx.ID_ANY, "-", size=(75, 20), style=0) 371 373 self.tcChi.SetToolTipString("Chi2/Npts(Fit)") 372 self.Npts_fit = BGTextCtrl(self, -1, "-", size=(75, 20), style=0)373 self.Npts_fit.SetToolTipString( \374 self.Npts_fit = BGTextCtrl(self, wx.ID_ANY, "-", size=(75, 20), style=0) 375 self.Npts_fit.SetToolTipString( 374 376 " Npts : number of points selected for fitting") 375 self.Npts_total = ModelTextCtrl(self, -1, 376 size=(_BOX_WIDTH, 20), 377 style=wx.TE_PROCESS_ENTER, 378 text_enter_callback=self._onQrangeEnter) 377 self.Npts_total = ModelTextCtrl(self, wx.ID_ANY, size=(_BOX_WIDTH, 20), 378 style=wx.TE_PROCESS_ENTER, 379 text_enter_callback=self._onQrangeEnter) 379 380 self.Npts_total.SetValue(format_number(self.npts_x)) 380 381 self.Npts_total.SetToolTipString(\ 381 382 " Total Npts : total number of data points") 382 383 383 384 # Update and Draw button 384 self.draw_button = wx.Button(self, wx.NewId(), 'Compute')385 self.draw_button.Bind(wx.EVT_BUTTON, \385 self.draw_button = wx.Button(self, self._ids.next(), 'Compute') 386 self.draw_button.Bind(wx.EVT_BUTTON, 386 387 self._onDraw, id=self.draw_button.GetId()) 387 388 self.draw_button.SetToolTipString("Compute and Draw.") 388 389 self.points_sizer = wx.BoxSizer(wx.HORIZONTAL) 390 self.pointsbox = wx.CheckBox(self, -1, 'Log?', (10, 10))389 390 self.points_sizer = wx.BoxSizer(wx.HORIZONTAL) 391 self.pointsbox = wx.CheckBox(self, wx.ID_ANY, 'Log?', (10, 10)) 391 392 self.pointsbox.SetValue(False) 392 393 self.pointsbox.SetToolTipString("Check mark to use log spaced points") 393 394 wx.EVT_CHECKBOX(self, self.pointsbox.GetId(), self.select_log) 394 395 self.points_sizer.Add(wx.StaticText(self, -1, 'Npts '))395 396 self.points_sizer.Add(wx.StaticText(self, wx.ID_ANY, 'Npts ')) 396 397 self.points_sizer.Add(self.pointsbox) 397 398 398 box_description_1 = wx.StaticText(self, -1, ' Chi2/Npts')399 box_description_2 = wx.StaticText(self, -1, 'Npts(Fit)')399 box_description_1 = wx.StaticText(self, wx.ID_ANY, ' Chi2/Npts') 400 box_description_2 = wx.StaticText(self, wx.ID_ANY, 'Npts(Fit)') 400 401 401 402 # StaticText for smear 402 self.smear_description_none = wx.StaticText(self, -1,403 self.smear_description_none = wx.StaticText(self, wx.ID_ANY, 403 404 smear_message_none, style=wx.ALIGN_LEFT) 404 self.smear_description_dqdata = wx.StaticText(self, 405 -1,smear_message_dqdata, style=wx.ALIGN_LEFT)406 self.smear_description_type = wx.StaticText(self, 407 -1,"Type:", style=wx.ALIGN_LEFT)408 self.smear_description_accuracy_type = wx.StaticText(self, -1,409 410 self.smear_description_smear_type = BGTextCtrl(self, -1,405 self.smear_description_dqdata = wx.StaticText(self, wx.ID_ANY, 406 smear_message_dqdata, style=wx.ALIGN_LEFT) 407 self.smear_description_type = wx.StaticText(self, wx.ID_ANY, 408 "Type:", style=wx.ALIGN_LEFT) 409 self.smear_description_accuracy_type = wx.StaticText(self, wx.ID_ANY, 410 "Accuracy:", style=wx.ALIGN_LEFT) 411 self.smear_description_smear_type = BGTextCtrl(self, wx.ID_ANY, 411 412 size=(57, 20), style=0) 412 413 self.smear_description_smear_type.SetValue(str(self.dq_l)) 413 414 self.SetBackgroundColour(self.GetParent().GetBackgroundColour()) 414 self.smear_description_2d = wx.StaticText(self, -1,415 self.smear_description_2d = wx.StaticText(self, wx.ID_ANY, 415 416 smear_message_2d, style=wx.ALIGN_LEFT) 416 self.smear_message_new_s = wx.StaticText(self, -1,417 self.smear_message_new_s = wx.StaticText(self, wx.ID_ANY, 417 418 smear_message_new_ssmear, style=wx.ALIGN_LEFT) 418 self.smear_message_new_p = wx.StaticText(self, -1,419 self.smear_message_new_p = wx.StaticText(self, wx.ID_ANY, 419 420 smear_message_new_psmear, style=wx.ALIGN_LEFT) 420 self.smear_description_2d_x = wx.StaticText(self, -1,421 self.smear_description_2d_x = wx.StaticText(self, wx.ID_ANY, 421 422 smear_message_2d_x_title, style=wx.ALIGN_LEFT) 422 self.smear_description_2d_x.SetToolTipString( \423 self.smear_description_2d_x.SetToolTipString( 423 424 " dQp(parallel) in q_r direction.") 424 self.smear_description_2d_y = wx.StaticText(self, -1,425 self.smear_description_2d_y = wx.StaticText(self, wx.ID_ANY, 425 426 smear_message_2d_y_title, style=wx.ALIGN_LEFT) 426 427 self.smear_description_2d_y.SetToolTipString(\ 427 428 " dQs(perpendicular) in q_phi direction.") 428 self.smear_description_pin_min = wx.StaticText(self, -1,429 self.smear_description_pin_min = wx.StaticText(self, wx.ID_ANY, 429 430 smear_message_pinhole_min_title, style=wx.ALIGN_LEFT) 430 self.smear_description_pin_max = wx.StaticText(self, -1,431 self.smear_description_pin_max = wx.StaticText(self, wx.ID_ANY, 431 432 smear_message_pinhole_max_title, style=wx.ALIGN_LEFT) 432 self.smear_description_slit_height = wx.StaticText(self, -1,433 self.smear_description_slit_height = wx.StaticText(self, wx.ID_ANY, 433 434 smear_message_slit_height_title, style=wx.ALIGN_LEFT) 434 self.smear_description_slit_width = wx.StaticText(self, -1,435 self.smear_description_slit_width = wx.StaticText(self, wx.ID_ANY, 435 436 smear_message_slit_width_title, style=wx.ALIGN_LEFT) 436 437 437 438 #arrange sizers 438 439 self.sizer_set_smearer.Add(sizer_smearer) … … 467 468 self.sizer_new_smear.Add((20, -1)) 468 469 self.sizer_new_smear.Add(self.smear_description_2d_y, 469 0, wx.CENTER, 10 470 0, wx.CENTER, 10) 470 471 self.sizer_new_smear.Add(self.smear_description_pin_max, 471 0, wx.CENTER, 10 472 0, wx.CENTER, 10) 472 473 self.sizer_new_smear.Add(self.smear_description_slit_width, 473 0, wx.CENTER, 10 474 0, wx.CENTER, 10) 474 475 475 476 self.sizer_new_smear.Add(self.smear_pinhole_max, 0, wx.CENTER, 10) 476 477 self.sizer_new_smear.Add(self.smear_slit_width, 0, wx.CENTER, 10) 477 478 self.sizer_new_smear.Add(self.smear_data_right, 0, wx.CENTER, 10) 478 479 479 480 self.sizer_set_smearer.Add(self.smear_message_new_s, 0, wx.CENTER, 10) 480 481 self.sizer_set_smearer.Add(self.smear_message_new_p, 0, wx.CENTER, 10) 481 482 self.sizer_set_smearer.Add((5, 2)) 482 483 self.sizer_set_smearer.Add(self.sizer_new_smear, 0, wx.CENTER, 10) 483 484 484 485 # add all to chi2 sizer 485 486 sizer_smearer_box.Add(self.sizer_set_smearer) … … 488 489 sizer_chi2.Add(weighting_box) 489 490 sizer_chi2.Add((-1, 5)) 490 491 491 492 # hide all smear messages and textctrl 492 493 self._hide_all_smear_info() 493 494 494 495 # get smear_selection 495 496 self.current_smearer = smear_selection(self.data, self.model) … … 512 513 #2D data? default 513 514 is_2Ddata = False 514 515 515 516 #check if it is 2D data 516 517 if self.data.__class__.__name__ == "Data2D" or self.enable2D: 517 518 is_2Ddata = True 518 519 519 520 self.sizer5.Clear(True) 520 521 self.qmin = ModelTextCtrl(self, -1, size=(_BOX_WIDTH, 20),522 523 524 525 521 522 self.qmin = ModelTextCtrl(self, wx.ID_ANY, size=(_BOX_WIDTH, 20), 523 style=wx.TE_PROCESS_ENTER, 524 set_focus_callback=self.qrang_set_focus, 525 text_enter_callback=self._onQrangeEnter, 526 name='qmin') 526 527 self.qmin.SetValue(str(self.qmin_x)) 527 528 q_tip = "Click outside of the axes\n to remove the lines." … … 529 530 qmin_tip += q_tip 530 531 self.qmin.SetToolTipString(qmin_tip) 531 532 self.qmax = ModelTextCtrl(self, -1, size=(_BOX_WIDTH, 20),533 534 535 536 532 533 self.qmax = ModelTextCtrl(self, wx.ID_ANY, size=(_BOX_WIDTH, 20), 534 style=wx.TE_PROCESS_ENTER, 535 set_focus_callback=self.qrang_set_focus, 536 text_enter_callback=self._onQrangeEnter, 537 name='qmax') 537 538 self.qmax.SetValue(str(self.qmax_x)) 538 539 qmax_tip = "Maximum value of Q.\n" … … 545 546 self.qmin.Bind(wx.EVT_TEXT, self.on_qrange_text) 546 547 self.qmax.Bind(wx.EVT_TEXT, self.on_qrange_text) 547 wx_id = wx.NewId()548 wx_id = self._ids.next() 548 549 self.reset_qrange = wx.Button(self, wx_id, 'Reset') 549 550 550 551 self.reset_qrange.Bind(wx.EVT_BUTTON, self.on_reset_clicked, id=wx_id) 551 552 self.reset_qrange.SetToolTipString("Reset Q range to the default") 552 553 553 554 sizer = wx.GridSizer(5, 5, 2, 6) 554 555 555 self.btEditMask = wx.Button(self, wx.NewId(), 'Editor')556 self.btEditMask = wx.Button(self, self._ids.next(), 'Editor') 556 557 self.btEditMask.Bind(wx.EVT_BUTTON, self._onMask, 557 558 id=self.btEditMask.GetId()) 558 559 self.btEditMask.SetToolTipString("Edit Mask.") 559 self.EditMask_title = wx.StaticText(self, -1, ' Masking(2D)')560 561 sizer.Add(wx.StaticText(self, -1, ' Q range'))562 sizer.Add(wx.StaticText(self, -1, ' Min[1/A]'))563 sizer.Add(wx.StaticText(self, -1, ' Max[1/A]'))560 self.EditMask_title = wx.StaticText(self, wx.ID_ANY, ' Masking(2D)') 561 562 sizer.Add(wx.StaticText(self, wx.ID_ANY, ' Q range')) 563 sizer.Add(wx.StaticText(self, wx.ID_ANY, ' Min[1/A]')) 564 sizer.Add(wx.StaticText(self, wx.ID_ANY, ' Max[1/A]')) 564 565 sizer.Add(self.EditMask_title) 565 566 sizer.Add((-1,5)) … … 598 599 self.sizer5.Layout() 599 600 600 601 601 602 def _set_sizer_dispersion(self): 602 603 """ … … 614 615 ## the user didn't select dispersity display 615 616 return 616 617 617 618 self._reset_dispersity() 618 619 619 620 ## fill a sizer with the combobox to select dispersion type 620 model_disp = wx.StaticText(self, -1, 'Function')621 model_disp = wx.StaticText(self, wx.ID_ANY, 'Function') 621 622 CHECK_STATE = self.cb1.GetValue() 622 #import sas.models.dispersion_models 623 #self.polydisp = sas.models.dispersion_models.models 624 import sasmodels.weights 625 self.polydisp = sasmodels.weights.models 623 import sas.models.dispersion_models 624 self.polydisp = sas.models.dispersion_models.models 626 625 627 626 ix = 0 628 627 iy = 0 629 disp = wx.StaticText(self, -1, ' ')628 disp = wx.StaticText(self, wx.ID_ANY, ' ') 630 629 self.sizer4_4.Add(disp, (iy, ix), (1, 1), 631 630 wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 15) 632 631 ix += 1 633 values = wx.StaticText(self, -1, 'PD[ratio]')632 values = wx.StaticText(self, wx.ID_ANY, 'PD[ratio]') 634 633 polytext = "Polydispersity (= STD/mean); " 635 634 polytext += "the standard deviation over the mean value." … … 643 642 else: 644 643 err_text = '' 645 self.text_disp_1 = wx.StaticText(self, -1, err_text)644 self.text_disp_1 = wx.StaticText(self, wx.ID_ANY, err_text) 646 645 self.sizer4_4.Add(self.text_disp_1, (iy, ix), (1, 1), \ 647 646 wx.EXPAND | wx.ADJUST_MINSIZE, 0) 648 647 649 648 ix += 1 650 self.text_disp_min = wx.StaticText(self, -1, 'Min')649 self.text_disp_min = wx.StaticText(self, wx.ID_ANY, 'Min') 651 650 self.sizer4_4.Add(self.text_disp_min, (iy, ix), (1, 1), \ 652 651 wx.EXPAND | wx.ADJUST_MINSIZE, 0) 653 652 654 653 ix += 1 655 self.text_disp_max = wx.StaticText(self, -1, 'Max')654 self.text_disp_max = wx.StaticText(self, wx.ID_ANY, 'Max') 656 655 self.sizer4_4.Add(self.text_disp_max, (iy, ix), (1, 1), 657 656 wx.EXPAND | wx.ADJUST_MINSIZE, 0) 658 657 659 658 ix += 1 660 npts = wx.StaticText(self, -1, 'Npts')659 npts = wx.StaticText(self, wx.ID_ANY, 'Npts') 661 660 npts.SetToolTipString("Number of sampling points for the numerical\n\ 662 661 integration over the distribution function.") … … 664 663 wx.EXPAND | wx.ADJUST_MINSIZE, 0) 665 664 ix += 1 666 nsigmas = wx.StaticText(self, -1, 'Nsigs')665 nsigmas = wx.StaticText(self, wx.ID_ANY, 'Nsigs') 667 666 nsigmas.SetToolTipString("Number of sigmas between which the range\n\ 668 667 of the distribution function will be used for weighting. \n\ … … 674 673 self.sizer4_4.Add(model_disp, (iy, ix), (1, 1), 675 674 wx.EXPAND | wx.ADJUST_MINSIZE, 0) 676 675 677 676 self.text_disp_max.Show(True) 678 677 self.text_disp_min.Show(True) … … 694 693 iy += 1 695 694 for p in self.model.dispersion[item].keys(): 696 695 697 696 if p == "width": 698 697 ix = 0 699 cb = wx.CheckBox(self, -1, name0, (10, 10))698 cb = wx.CheckBox(self, wx.ID_ANY, name0, (10, 10)) 700 699 cb.SetValue(CHECK_STATE) 701 700 cb.SetToolTipString("Check mark to fit") … … 705 704 ix = 1 706 705 value = self.model.getParam(name1) 707 ctl1 = ModelTextCtrl(self, -1,708 709 706 ctl1 = ModelTextCtrl(self, wx.ID_ANY, 707 size=(_BOX_WIDTH / 1.3, 20), 708 style=wx.TE_PROCESS_ENTER) 710 709 ctl1.SetLabel('PD[ratio]') 711 710 poly_text = "Polydispersity (STD/mean) of %s\n" % item … … 717 716 ## text to show error sign 718 717 ix = 2 719 text2 = wx.StaticText(self, -1, '+/-')718 text2 = wx.StaticText(self, wx.ID_ANY, '+/-') 720 719 self.sizer4_4.Add(text2, (iy, ix), (1, 1), 721 720 wx.EXPAND | wx.ADJUST_MINSIZE, 0) … … 724 723 725 724 ix = 3 726 ctl2 = wx.TextCtrl(self, -1,725 ctl2 = wx.TextCtrl(self, wx.ID_ANY, 727 726 size=(_BOX_WIDTH / 1.3, 20), 728 727 style=0) 729 728 730 729 self.sizer4_4.Add(ctl2, (iy, ix), (1, 1), 731 730 wx.EXPAND | wx.ADJUST_MINSIZE, 0) … … 734 733 735 734 ix = 4 736 ctl3 = ModelTextCtrl(self, -1,737 738 739 740 735 ctl3 = ModelTextCtrl(self, wx.ID_ANY, 736 size=(_BOX_WIDTH / 2, 20), 737 style=wx.TE_PROCESS_ENTER, 738 text_enter_callback=self._onparamRangeEnter) 739 741 740 self.sizer4_4.Add(ctl3, (iy, ix), (1, 1), 742 741 wx.EXPAND | wx.ADJUST_MINSIZE, 0) 743 742 744 743 ix = 5 745 ctl4 = ModelTextCtrl(self, -1,746 747 744 ctl4 = ModelTextCtrl(self, wx.ID_ANY, 745 size=(_BOX_WIDTH / 2, 20), 746 style=wx.TE_PROCESS_ENTER, 748 747 text_enter_callback=self._onparamRangeEnter) 749 748 750 749 self.sizer4_4.Add(ctl4, (iy, ix), (1, 1), 751 750 wx.EXPAND | wx.ADJUST_MINSIZE, 0) … … 753 752 ctl3.Show(True) 754 753 ctl4.Show(True) 755 754 756 755 elif p == "npts": 757 756 ix = 6 758 757 value = self.model.getParam(name2) 759 Tctl = ModelTextCtrl(self, -1,760 761 762 758 Tctl = ModelTextCtrl(self, wx.ID_ANY, 759 size=(_BOX_WIDTH / 2.2, 20), 760 style=wx.TE_PROCESS_ENTER) 761 763 762 Tctl.SetValue(str(format_number(value))) 764 763 self.sizer4_4.Add(Tctl, (iy, ix), (1, 1), … … 769 768 ix = 7 770 769 value = self.model.getParam(name3) 771 Tct2 = ModelTextCtrl(self, -1,772 773 774 770 Tct2 = ModelTextCtrl(self, wx.ID_ANY, 771 size=(_BOX_WIDTH / 2.2, 20), 772 style=wx.TE_PROCESS_ENTER) 773 775 774 Tct2.SetValue(str(format_number(value))) 776 775 self.sizer4_4.Add(Tct2, (iy, ix), (1, 1), … … 781 780 782 781 ix = 8 783 disp_box = wx.ComboBox(self, -1, size=(65, -1),782 disp_box = wx.ComboBox(self, wx.ID_ANY, size=(65, -1), 784 783 style=wx.CB_READONLY, name='%s' % name1) 785 784 for key, value in self.polydisp.iteritems(): … … 787 786 disp_box.Append(name_disp, value) 788 787 disp_box.SetStringSelection("gaussian") 789 wx.EVT_COMBOBOX(disp_box, -1, self._on_disp_func)788 wx.EVT_COMBOBOX(disp_box, wx.ID_ANY, self._on_disp_func) 790 789 self.sizer4_4.Add(disp_box, (iy, ix), (1, 1), wx.EXPAND) 791 790 self.fittable_param.append([cb, name1, ctl1, text2, 792 791 ctl2, ctl3, ctl4, disp_box]) 793 792 794 793 ix = 0 795 794 iy += 1 … … 808 807 name2 = item + ".npts" 809 808 name3 = item + ".nsigmas" 810 809 811 810 if not name1 in self.model.details: 812 811 self.model.details[name1] = ["", None, None] 813 812 814 813 iy += 1 815 814 for p in self.model.dispersion[item].keys(): 816 815 817 816 if p == "width": 818 817 ix = 0 819 cb = wx.CheckBox(self, -1, name0, (10, 10))818 cb = wx.CheckBox(self, wx.ID_ANY, name0, (10, 10)) 820 819 cb.SetValue(CHECK_STATE) 821 820 cb.SetToolTipString("Check mark to fit") … … 830 829 ix = 1 831 830 value = self.model.getParam(name1) 832 ctl1 = ModelTextCtrl(self, -1,833 834 831 ctl1 = ModelTextCtrl(self, wx.ID_ANY, 832 size=(_BOX_WIDTH / 1.3, 20), 833 style=wx.TE_PROCESS_ENTER) 835 834 poly_tip = "Absolute Sigma for %s." % item 836 835 ctl1.SetToolTipString(poly_tip) … … 846 845 poly_text += "It is the STD (ratio*mean)" 847 846 poly_text += " of the distribution.\n " 848 847 849 848 values.SetToolTipString(poly_text) 850 849 first_orient = False … … 852 851 elif ctl1.IsShown(): 853 852 ctl1.Hide() 854 853 855 854 self.sizer4_4.Add(ctl1, (iy, ix), (1, 1), wx.EXPAND) 856 855 ## text to show error sign 857 856 ix = 2 858 text2 = wx.StaticText(self, -1, '+/-')857 text2 = wx.StaticText(self, wx.ID_ANY, '+/-') 859 858 self.sizer4_4.Add(text2, (iy, ix), (1, 1), 860 859 wx.EXPAND | wx.ADJUST_MINSIZE, 0) … … 863 862 864 863 ix = 3 865 ctl2 = wx.TextCtrl(self, -1,864 ctl2 = wx.TextCtrl(self, wx.ID_ANY, 866 865 size=(_BOX_WIDTH / 1.3, 20), 867 866 style=0) 868 867 869 868 self.sizer4_4.Add(ctl2, (iy, ix), (1, 1), 870 869 wx.EXPAND | wx.ADJUST_MINSIZE, 0) … … 876 875 text2.Show(True) 877 876 ctl2.Show(True) 878 877 879 878 ix = 4 880 ctl3 = ModelTextCtrl(self, -1,881 882 879 ctl3 = ModelTextCtrl(self, wx.ID_ANY, 880 size=(_BOX_WIDTH / 2, 20), 881 style=wx.TE_PROCESS_ENTER, 883 882 text_enter_callback=self._onparamRangeEnter) 884 883 … … 887 886 888 887 ctl3.Hide() 889 888 890 889 ix = 5 891 ctl4 = ModelTextCtrl(self, -1,892 size=(_BOX_WIDTH / 2, 20),893 style=wx.TE_PROCESS_ENTER,890 ctl4 = ModelTextCtrl(self, wx.ID_ANY, 891 size=(_BOX_WIDTH / 2, 20), 892 style=wx.TE_PROCESS_ENTER, 894 893 text_enter_callback=self._onparamRangeEnter) 895 894 self.sizer4_4.Add(ctl4, (iy, ix), (1, 1), 896 895 wx.EXPAND | wx.ADJUST_MINSIZE, 0) 897 896 ctl4.Hide() 898 897 899 898 if self.data.__class__.__name__ == "Data2D" or \ 900 899 self.enable2D: 901 900 ctl3.Show(True) 902 901 ctl4.Show(True) 903 902 904 903 elif p == "npts": 905 904 ix = 6 906 905 value = self.model.getParam(name2) 907 Tctl = ModelTextCtrl(self, -1,908 909 910 906 Tctl = ModelTextCtrl(self, wx.ID_ANY, 907 size=(_BOX_WIDTH / 2.2, 20), 908 style=wx.TE_PROCESS_ENTER) 909 911 910 Tctl.SetValue(str(format_number(value))) 912 911 if self.data.__class__.__name__ == "Data2D" or \ … … 925 924 ix = 7 926 925 value = self.model.getParam(name3) 927 Tct2 = ModelTextCtrl(self, -1,928 929 930 926 Tct2 = ModelTextCtrl(self, wx.ID_ANY, 927 size=(_BOX_WIDTH / 2.2, 20), 928 style=wx.TE_PROCESS_ENTER) 929 931 930 Tct2.SetValue(str(format_number(value))) 932 931 if self.data.__class__.__name__ == "Data2D" or \ … … 940 939 self.fixed_param.append([None, name3, Tct2, 941 940 None, None, None, None, None]) 942 941 943 942 self.orientation_params_disp.append([None, name3, 944 943 Tct2, None, None, None, None, None]) 945 944 946 945 ix = 8 947 disp_box = wx.ComboBox(self, -1, size=(65, -1),946 disp_box = wx.ComboBox(self, wx.ID_ANY, size=(65, -1), 948 947 style=wx.CB_READONLY, name='%s' % name1) 949 948 for key, value in self.polydisp.iteritems(): … … 951 950 disp_box.Append(name_disp, value) 952 951 disp_box.SetStringSelection("gaussian") 953 wx.EVT_COMBOBOX(disp_box, -1, self._on_disp_func)952 wx.EVT_COMBOBOX(disp_box, wx.ID_ANY, self._on_disp_func) 954 953 self.sizer4_4.Add(disp_box, (iy, ix), (1, 1), wx.EXPAND) 955 954 self.fittable_param.append([cb, name1, ctl1, text2, … … 957 956 self.orientation_params_disp.append([cb, name1, ctl1, 958 957 text2, ctl2, ctl3, ctl4, disp_box]) 959 958 960 959 if self.data.__class__.__name__ == "Data2D" or \ 961 960 self.enable2D: … … 963 962 else: 964 963 disp_box.Hide() 965 964 966 965 self.state.disp_cb_dict = copy.deepcopy(self.disp_cb_dict) 967 966 968 967 self.state.model = self.model.clone() 969 968 ## save state into … … 998 997 """ 999 998 flag = self._update_paramv_on_fit() 1000 999 1001 1000 wx.CallAfter(self._onparamEnter_helper) 1002 1001 if not flag: … … 1004 1003 wx.PostEvent(self._manager.parent, StatusEvent(status=msg)) 1005 1004 return 1006 1005 1007 1006 def _onFit(self, event): 1008 1007 """ … … 1029 1028 StatusEvent(status="Fit: %s" % msg, type="stop")) 1030 1029 return 1031 1030 1032 1031 if len(self.param_toFit) <= 0: 1033 1032 msg = "Select at least one parameter to fit" … … 1036 1035 StatusEvent(status=msg, type="stop")) 1037 1036 return 1038 1037 1039 1038 flag = self._update_paramv_on_fit() 1040 1039 1041 1040 if self.batch_on and not self._is_2D(): 1042 1041 if not self._validate_Npts_1D(): 1043 1042 return 1044 1043 1045 1044 if not flag: 1046 1045 msg = "Fitting range or parameters are invalid" … … 1048 1047 StatusEvent(status=msg, type="stop")) 1049 1048 return 1050 1049 1051 1050 self.select_param(event=None) 1052 1051 … … 1064 1063 self.fit_started = self._manager.onFit(uid=self.uid) 1065 1064 wx.CallAfter(self.set_fitbutton) 1066 1065 1067 1066 def _onFitHelp(self, event): 1068 1067 """ … … 1081 1080 1082 1081 _TreeLocation = "user/perspectives/fitting/fitting_help.html" 1083 _doc_viewer = DocumentationWindow(self, -1, _TreeLocation, "",1082 _doc_viewer = DocumentationWindow(self, wx.ID_ANY, _TreeLocation, "", 1084 1083 "General Fitting Help") 1085 1084 … … 1100 1099 1101 1100 _TreeLocation = "user/perspectives/fitting/sm_help.html" 1102 _doc_viewer = DocumentationWindow(self, -1, _TreeLocation, "",1101 _doc_viewer = DocumentationWindow(self, wx.ID_ANY, _TreeLocation, "", 1103 1102 "Instrumental Resolution Smearing \ 1104 1103 Help") … … 1112 1111 if self.is_mac: 1113 1112 return 1114 1113 1115 1114 if self.fit_started: 1116 1115 label = "Stop" … … 1123 1122 self.btFit.SetForegroundColour(color) 1124 1123 self.btFit.Enable(True) 1125 1124 1126 1125 def get_weight_flag(self): 1127 1126 """ … … 1145 1144 break 1146 1145 return flag 1147 1146 1148 1147 def _StopFit(self, event=None): 1149 1148 """ … … 1155 1154 self._manager._reset_schedule_problem(value=0) 1156 1155 self._on_fit_complete() 1157 1156 1158 1157 def rename_model(self): 1159 1158 """ … … 1162 1161 if self.model is not None: 1163 1162 self.model.name = "M" + str(self.index_model) 1164 1163 1165 1164 def _on_select_model(self, event=None): 1166 1165 """ … … 1184 1183 self._keep.Enable(False) 1185 1184 self._set_save_flag(False) 1185 # TODO: why do we have to variables for one flag?? 1186 1186 self.enable_disp.SetValue(False) 1187 1187 self.disable_disp.SetValue(True) 1188 # TODO: should not have an untrapped exception when displaying disperser 1189 # TODO: do we need to create the disperser panel on every model change? 1190 # Note: if we fix this, then remove ID_DISPERSER_HELP from basepage 1188 1191 try: 1189 1192 self.set_dispers_sizer() … … 1194 1197 self.state.pinhole_smearer = self.pinhole_smearer.GetValue() 1195 1198 self.state.slit_smearer = self.slit_smearer.GetValue() 1196 1199 1197 1200 self.state.structurecombobox = self.structurebox.GetLabel() 1198 1201 self.state.formfactorcombobox = self.formfactorbox.GetLabel() … … 1210 1213 self._keep.Enable(not self.batch_on) 1211 1214 self._set_save_flag(True) 1212 1215 1213 1216 # more disables for 2D 1214 1217 self._set_smear_buttons() 1215 1218 1216 1219 try: 1217 1220 # update smearer sizer … … 1227 1230 ## event to post model to fit to fitting plugins 1228 1231 (ModelEventbox, EVT_MODEL_BOX) = wx.lib.newevent.NewEvent() 1229 1232 1230 1233 ## set smearing value whether or not 1231 1234 # the data contain the smearing info … … 1237 1240 caption=self.window_caption, 1238 1241 qmax=float(self.qmax_x)) 1239 1242 1240 1243 self._manager._on_model_panel(evt=evt) 1241 self.mbox_description.SetLabel("Model [ %s ]" % str(self.model.name))1244 self.mbox_description.SetLabel("Model [ %s ]" % str(self.model.name)) 1242 1245 self.mbox_description.SetForegroundColour(wx.BLUE) 1243 1246 self.state.model = self.model.clone() … … 1272 1275 self.get_paste_params(copy_flag) 1273 1276 wx.CallAfter(self._onDraw, None) 1274 1277 1275 1278 else: 1276 1279 self._draw_model() 1277 1280 1278 1281 if self.batch_on: 1279 1282 self.slit_smearer.Enable(False) … … 1281 1284 self.btEditMask.Disable() 1282 1285 self.EditMask_title.Disable() 1283 1286 1284 1287 self.Show(True) 1285 1288 self.SetupScrolling() 1286 1289 1287 1290 def _onparamEnter(self, event): 1288 1291 """ … … 1327 1330 qmax=float(self.qmax_x), 1328 1331 enable_smearer=enable_smearer, 1329 draw=True)1332 draw=True) 1330 1333 if flag: 1331 1334 #self.compute_chisqr(smearer= temp_smearer) 1332 1335 1333 1336 ## new state posted 1334 1337 if self.state_change: … … 1345 1348 msg = "Cannot Plot :Must enter a number!!! " 1346 1349 wx.PostEvent(self._manager.parent, StatusEvent(status=msg)) 1347 1350 1348 1351 self.save_current_state() 1349 1352 return 1350 1353 1351 1354 def _onparamRangeEnter(self, event): 1352 1355 """ … … 1371 1374 else: 1372 1375 tcrtl.SetBackgroundColour(wx.WHITE) 1373 1376 1374 1377 #self._undo.Enable(True) 1375 1378 self.save_current_state() … … 1377 1380 wx.PostEvent(self.parent, event) 1378 1381 self.state_change = False 1379 1380 def qrang_set_focus(self, event=None): 1382 1383 def qrang_set_focus(self, event=None): 1381 1384 """ 1382 1385 ON Qrange focus … … 1386 1389 #tcrtl = event.GetEventObject() 1387 1390 self._validate_qrange(self.qmin, self.qmax) 1388 1391 1389 1392 def qrange_click(self, event): 1390 1393 """ … … 1400 1403 d_group_id = self.data.group_id 1401 1404 act_ctrl = event.GetEventObject() 1402 wx.PostEvent(self._manager.parent, 1403 PlotQrangeEvent(ctrl=[self.qmin, self.qmax], id=d_id, 1405 wx.PostEvent(self._manager.parent, 1406 PlotQrangeEvent(ctrl=[self.qmin, self.qmax], id=d_id, 1404 1407 group_id=d_group_id, leftdown=is_click, 1405 1408 active=act_ctrl)) 1406 1409 1407 1410 def on_qrange_text(self, event): 1408 1411 """ … … 1416 1419 d_id = self.data.id 1417 1420 d_group_id = self.data.group_id 1418 wx.PostEvent(self._manager.parent, 1419 PlotQrangeEvent(ctrl=[self.qmin, self.qmax], id=d_id, 1420 group_id=d_group_id, leftdown=False, 1421 wx.PostEvent(self._manager.parent, 1422 PlotQrangeEvent(ctrl=[self.qmin, self.qmax], id=d_id, 1423 group_id=d_group_id, leftdown=False, 1421 1424 active=act_ctrl)) 1422 1425 self._validate_qrange(self.qmin, self.qmax) 1423 1424 def on_key(self, event): 1426 1427 def on_key(self, event): 1425 1428 """ 1426 1429 On Key down … … 1433 1436 x_data = float(ctrl.GetValue()) 1434 1437 except: 1435 return 1438 return 1436 1439 key = event.GetKeyCode() 1437 1440 length = len(self.data.x) … … 1450 1453 ctrl.SetValue(str(self.data.x[indx])) 1451 1454 self._validate_qrange(self.qmin, self.qmax) 1452 1455 1453 1456 def _onQrangeEnter(self, event): 1454 1457 """ … … 1511 1514 (self.data.x <= self.qmax_x)) 1512 1515 self.Npts_fit.SetValue(str(len(self.data.x[index_data]))) 1513 1516 1514 1517 self.npts_x = self.Npts_total.GetValue() 1515 1518 self.create_default_data() … … 1519 1522 msg = "Model Error:wrong value entered!!!" 1520 1523 wx.PostEvent(self._manager.parent, StatusEvent(status=msg)) 1521 1524 1522 1525 self._draw_model() 1523 1526 self.save_current_state() … … 1526 1529 self.state_change = False 1527 1530 return 1528 1531 1529 1532 def _clear_Err_on_Fit(self): 1530 1533 """ … … 1556 1559 if item[4] != None and item[4].IsShown(): 1557 1560 item[4].Hide() 1558 1561 1559 1562 if len(self.fittable_param) > 0: 1560 1563 for item in self.fittable_param: … … 1576 1579 item[4].Hide() 1577 1580 return 1578 1581 1579 1582 def _get_defult_custom_smear(self): 1580 1583 """ … … 1590 1593 if self.dx_max == None: 1591 1594 self.dx_max = SMEAR_SIZE_H 1592 1595 1593 1596 def _get_smear_info(self): 1594 1597 """ 1595 1598 Get the smear info from data. 1596 1599 1597 1600 :return: self.smear_type, self.dq_l and self.dq_r, 1598 1601 respectively the type of the smear, dq_min and … … 1625 1628 self.dq_l = data.dx[0] 1626 1629 self.dq_r = data.dx[-1] 1627 1630 1628 1631 # check if it is slit smear and get min max if it is. 1629 1632 elif data.dxl != None or data.dxw != None: … … 1634 1637 self.dq_r = data.dxw[0] 1635 1638 #return self.smear_type,self.dq_l,self.dq_r 1636 1639 1637 1640 def _show_smear_sizer(self): 1638 1641 """ … … 1698 1701 self.smear_description_2d_y.Hide() 1699 1702 self.smear_description_2d.Hide() 1700 1703 1701 1704 self.smear_accuracy.Hide() 1702 1705 self.smear_data_left.Hide() … … 1712 1715 self.smear_message_new_p.Hide() 1713 1716 self.smear_message_new_s.Hide() 1714 1717 1715 1718 def _set_accuracy_list(self): 1716 1719 """ … … 1722 1725 for idx in range(len(list)): 1723 1726 self.smear_accuracy.Append(list[idx], idx) 1724 1727 1725 1728 def _set_fun_box_list(self, fun_box): 1726 1729 """