source: sasview/src/sas/perspectives/calculator/gen_scatter_panel.py @ 26500ec

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalccostrafo411magnetic_scattrelease-4.1.1release-4.1.2release-4.2.2release_4.0.1ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249ticket885unittest-saveload
Last change on this file since 26500ec was 3f5d75b, checked in by butler, 10 years ago

Fixed General Scattering Panel

  • Removed abandoned menu bar code
  • Removed toolbar code - It is not consistent with rest of tools.

Furthermore, it had nothing useful except help.

  • Added a Help button to bottom of panel
  • Cleaned up help code (i.e. removed all the old code and replaced with

simple call to Sphinx documentation)

  • Fixed sizing of panel (1 + ½.5 = 1.4 not 1.3 for total width)

—- still seems to be an odd vertical line to left of right hand pane
when trying to resize said pane.

  • Property mode set to 100644
File size: 74.6 KB
RevLine 
[318b5bbb]1"""
2Generic Scattering panel.
3This module relies on guiframe manager.
4"""
5
6import wx
7import sys
8import os
9import numpy
10#import math
11import wx.aui as aui
12#import wx.lib.agw.aui as aui
13import logging
14import time
15
16import matplotlib
17matplotlib.interactive(False)
18#Use the WxAgg back end. The Wx one takes too long to render
19matplotlib.use('WXAgg')
20
[79492222]21#from sas.guiframe.gui_manager import MDIFrame
22from sas.data_util.calcthread import CalcThread
23from sas.guiframe.local_perspectives.plotting.SimplePlot import PlotFrame
24from sas.guiframe.dataFitting import Data2D
25from sas.guiframe.dataFitting import Data1D
26from sas.dataloader.data_info import Detector
27from sas.dataloader.data_info import Source
28from sas.guiframe.panel_base import PanelBase
29from sas.guiframe.utils import format_number
30from sas.guiframe.events import StatusEvent 
[b9a5f0e]31from sas.calculator import sas_gen
[79492222]32from sas.perspectives.calculator.calculator_widgets import OutputTextCtrl
33from sas.perspectives.calculator.calculator_widgets import InputTextCtrl
[318b5bbb]34from wx.lib.scrolledpanel import ScrolledPanel
[79492222]35from sas.perspectives.calculator.load_thread import GenReader
36from sas.plottools.arrow3d import Arrow3D
37from sas.perspectives.calculator import calculator_widgets as widget
38from sas.guiframe.events import NewPlotEvent   
[3f5d75b]39from sas.guiframe.documentation_window import DocumentationWindow
[077207b]40
[318b5bbb]41_BOX_WIDTH = 76
42#Slit length panel size
43if sys.platform.count("win32") > 0:
44    PANEL_WIDTH = 570
45    PANEL_HEIGHT = 370
46    FONT_VARIANT = 0
47else:
[aaaf9b4]48    PANEL_WIDTH = 620
49    PANEL_HEIGHT = 370
[318b5bbb]50    FONT_VARIANT = 1
[077207b]51_QMAX_DEFAULT = 0.3
[318b5bbb]52_NPTS_DEFAULT = 50 
[9624cda]53_Q1D_MIN = 0.001
[318b5bbb]54
55def add_icon(parent, frame):
56    """
57    Add icon in the frame
58    """
59    if parent != None:
60        if hasattr(frame, "IsIconized"):
61            if not frame.IsIconized():
62                try:
63                    icon = parent.GetIcon()
64                    frame.SetIcon(icon)
65                except:
66                    pass 
67
68def _set_error(panel, item, show_msg=False):
69    """
70    Set_error dialog
71    """
72    if item != None:
73        item.SetBackgroundColour("pink")
74        item.Refresh()
75    if show_msg:
[46be5e6]76        msg = "Error: wrong (or out of range) value entered."
[318b5bbb]77        if panel.parent.parent != None:
78            wx.PostEvent(panel.parent.parent, 
79                     StatusEvent(status=msg, info='Error' )) 
80            panel.SetFocus()
81    return False
82
[3f5d75b]83
84
[318b5bbb]85class CalcGen(CalcThread):
86    """
87    Computation
88    """
89    def __init__(self,
90                 id=-1,
91                 input = None,
92                 completefn = None,
93                 updatefn   = None,
[9624cda]94                 #elapsed = 0,
95                 yieldtime  = 0.01,
[318b5bbb]96                 worktime   = 0.01):
97        """
98        """
[cd89c6f]99        CalcThread.__init__(self, completefn,
[318b5bbb]100                 updatefn,
101                 yieldtime,
102                 worktime)
103        self.starttime = 0
104        self.id = id 
105        self.input = input 
[9624cda]106        self.update_fn = updatefn
[318b5bbb]107       
108    def compute(self):
109        """
110        excuting computation
111        """
[9624cda]112        #elapsed = time.time() - self.starttime
113        self.starttime = time.time()
114        self.complete(input=self.input, update=self.update_fn)
[318b5bbb]115           
116class SasGenPanel(ScrolledPanel, PanelBase):
117    """
118        Provides the sas gen calculator GUI.
119    """
120    ## Internal nickname for the window, used by the AUI manager
[b9a5f0e]121    window_name = "Generic SAS Calculator"
[318b5bbb]122    ## Name to appear on the window title bar
[b9a5f0e]123    window_caption = "Generic SAS "
[318b5bbb]124   
125    def __init__(self, parent, *args, **kwds):
126        ScrolledPanel.__init__(self, parent, style=wx.RAISED_BORDER, 
127                               *args, **kwds)
128        #kwds['style'] = wx.SUNKEN_BORDER
129        PanelBase.__init__(self)
130        #Font size
131        self.SetWindowVariant(variant=FONT_VARIANT)
132        self.SetupScrolling()
133        #thread to read data
134        self.reader = None
135        self.ext = None
[b9a5f0e]136        self.id = 'GenSAS'
[318b5bbb]137        self.file_name = ''
138        self.time_text = None
[3657667]139        self.orient_combo = None
[b9a5f0e]140        self.omfreader = sas_gen.OMFReader()
141        self.sldreader = sas_gen.SLDReader()
142        self.pdbreader = sas_gen.PDBReader()
143        self.model = sas_gen.GenSAS()
[318b5bbb]144        self.param_dic = self.model.params
145        self.parameters = []
146        self.data = None
147        self.scale2d = None
[9624cda]148        self.is_avg = False
[318b5bbb]149        self.plot_frame = None
150        self.qmax_x = _QMAX_DEFAULT
151        self.npts_x = _NPTS_DEFAULT
152        self.sld_data = None
153        self.graph_num = 1
154        self.default_shape = 'rectangular'
155        # Object that receive status event
156        self.parent = parent
157        self._do_layout()
158        self._create_default_sld_data()
159        self._create_default_2d_data()
160        wx.CallAfter(self._set_sld_data_helper)
161       
162    def _define_structure(self):
163        """
164            Define the main sizers building to build this application.
165        """
166        self.main_sizer = wx.BoxSizer(wx.VERTICAL)
167        self.box_source = wx.StaticBox(self, -1, str("SLD Data File"))
168        self.box_parameters = wx.StaticBox(self, -1, str("Input Parameters"))
169        self.box_qrange = wx.StaticBox(self, -1, str("Q Range"))
170        self.boxsizer_source = wx.StaticBoxSizer(self.box_source,
171                                                    wx.VERTICAL)
172        self.boxsizer_parameters = wx.StaticBoxSizer(self.box_parameters,
173                                                    wx.VERTICAL)
174        self.boxsizer_qrange = wx.StaticBoxSizer(self.box_qrange,
175                                                    wx.VERTICAL)
176        self.data_name_sizer = wx.BoxSizer(wx.HORIZONTAL)
177        self.param_sizer = wx.BoxSizer(wx.HORIZONTAL)
178        self.shape_sizer = wx.BoxSizer(wx.HORIZONTAL)
179        self.hint_sizer = wx.BoxSizer(wx.HORIZONTAL)
180        self.qrange_sizer = wx.BoxSizer(wx.HORIZONTAL)
181        self.button_sizer = wx.BoxSizer(wx.HORIZONTAL)
182       
183    def _layout_data_name(self):
184        """
185            Fill the sizer containing data's name
186        """
187        data_name_txt = wx.StaticText(self, -1, 'Data: ')
188        self.data_name_tcl = OutputTextCtrl(self, -1, 
189                                            size=(_BOX_WIDTH * 4, -1))
190        data_hint = "Loaded data"
191        self.data_name_tcl.SetToolTipString(data_hint)
192        #control that triggers importing data
193        id = wx.NewId()
194        self.browse_button = wx.Button(self, id, "Load")
[3f5d75b]195        hint_on_browse = "Click to load data into this panel."
196        self.browse_button.SetToolTipString(hint_on_browse)
[318b5bbb]197        self.Bind(wx.EVT_BUTTON, self.on_load_data, id=id)
198        self.data_name_sizer.AddMany([(data_name_txt, 0, wx.LEFT, 15),
199                                      (self.data_name_tcl, 0, wx.LEFT, 10),
200                                      (self.browse_button, 0, wx.LEFT, 10)])
201    def _layout_param_size(self):
202        """
203            Fill the sizer containing slit size information
204        """
205        self.parameters = []
206        sizer = wx.GridBagSizer(3, 6)
207        model = self.model
208        details = self.model.details
209        params = self.model.params
210        ix = 0
211        iy = 0
212        param_title = wx.StaticText(self, -1, 'Parameter')
213        sizer.Add(param_title, (iy, ix), (1, 1), \
214                            wx.EXPAND | wx.ADJUST_MINSIZE, 0)
215        ix += 1
216        value_title = wx.StaticText(self, -1, 'Value')
217        sizer.Add(value_title, (iy, ix), (1, 1), \
218                            wx.EXPAND | wx.ADJUST_MINSIZE, 0)
219        ix += 1
220        unit_title = wx.StaticText(self, -1, 'Unit')
221        sizer.Add(unit_title, (iy, ix), (1, 1), \
222                            wx.EXPAND | wx.ADJUST_MINSIZE, 0)
223        key_list = params.keys()
224        key_list.sort()
225        for param in key_list:
226            iy += 1
227            ix = 0
228            p_name = wx.StaticText(self, -1, param)
229            sizer.Add(p_name, (iy, ix), (1, 1), \
230                            wx.EXPAND | wx.ADJUST_MINSIZE, 0)
231            ## add parameter value
232            ix += 1
233            value = model.getParam(param)
234            ctl = InputTextCtrl(self, -1, size=(_BOX_WIDTH * 2, 20),
235                                style=wx.TE_PROCESS_ENTER)
236            #ctl.SetToolTipString(\
237            #            "Hit 'Enter' after typing to update the plot.")
238            ctl.SetValue(format_number(value, True))
239            sizer.Add(ctl, (iy, ix), (1, 1), wx.EXPAND)
240            ## add unit
241            ix += 1
242            unit = wx.StaticText(self, -1, details[param][0])
243            sizer.Add(unit, (iy, ix), (1, 1), \
244                            wx.EXPAND | wx.ADJUST_MINSIZE, 0)
245            self.parameters.append([p_name, ctl, unit])
246                                 
247        self.param_sizer.Add(sizer, 0, wx.LEFT, 10)
248   
249    def _layout_hint(self):
250        """
251            Fill the sizer containing hint
252        """
[78807b1]253        hint_msg = "We support omf, sld or pdb data files only."
[aaaf9b4]254        hint_msg +=  "         "
255        if FONT_VARIANT < 1:
256            hint_msg +=  "Very "
257        hint_msg += "SLOW drawing -->"
[318b5bbb]258        hint_txt = wx.StaticText(self, -1, hint_msg)
259       
260        id = wx.NewId()
261        self.draw_button = wx.Button(self, id, "Arrow Draw")
262        hint_on_draw = "Draw with arrows. Caution: it is a very slow drawing."
263        self.draw_button.SetToolTipString(hint_on_draw)
264        self.draw_button.Bind(wx.EVT_BUTTON, self.sld_draw, id=id)
265       
266        self.draw_button.Enable(False)
267        self.hint_sizer.AddMany([(hint_txt, 0, wx.LEFT, 15),
[78807b1]268                                 (self.draw_button, 0, wx.LEFT, 7)])
[318b5bbb]269   
270    def _layout_shape(self):
271        """
272        Fill the shape sizer
273        """
274        label_txt = wx.StaticText(self, -1, "Shape:")
275        self.shape_combo = self._fill_shape_combo()
276        self.shape_sizer.AddMany([(label_txt, 0, wx.LEFT, 15),
277                                (self.shape_combo, 0, wx.LEFT, 5)])
278   
279    def _fill_shape_combo(self):
280        """
281        Fill up the shape combo box
282        """
283        shape_combo = wx.ComboBox(self, -1, size=(150, -1), 
284                                      style=wx.CB_READONLY) 
285        shape_combo.Append('Rectangular')
286        shape_combo.Append('Ellipsoid')
287        shape_combo.Bind(wx.EVT_COMBOBOX, self._on_shape_select)
288        shape_combo.SetSelection(0)
289        return shape_combo
290   
291    def _on_shape_select(self, event):
292        """
293        On selecting a shape
294        """
295        event.Skip()
[aaaf9b4]296        label = event.GetEventObject().GetValue().lower() 
[318b5bbb]297        self.default_shape = label
298        self.parent.set_omfpanel_default_shap(self.default_shape)
299        self.parent.set_omfpanel_npts()
[3657667]300       
301    def _fill_orient_combo(self):
302        """
303        Fill up the orientation combo box: used only for atomic structure
304        """
305        orient_combo = wx.ComboBox(self, -1, size=(150, -1), 
306                                      style=wx.CB_READONLY) 
307        orient_combo.Append('Fixed orientation')
[9624cda]308        orient_combo.Append('Debye full avg.')
309        #orient_combo.Append('Debye sph. sym.')
[3657667]310       
311        orient_combo.Bind(wx.EVT_COMBOBOX, self._on_orient_select)
312        orient_combo.SetSelection(0)
313        return orient_combo
314   
315    def _on_orient_select(self, event):
316        """
317        On selecting a orientation
318        """
319        event.Skip()
320        cb = event.GetEventObject()
[9624cda]321        if cb.GetCurrentSelection() == 2:
322            self.is_avg = None
323        else:
324            is_avg = cb.GetCurrentSelection() == 1
325            self.is_avg = is_avg
326        self.model.set_is_avg(self.is_avg)
327        self.set_est_time()   
[318b5bbb]328           
329    def _layout_qrange(self):
330        """
331        Fill the sizer containing qrange
332        """
333        sizer = wx.GridBagSizer(2, 3)
334        ix = 0
335        iy = 0
336        #key_list.sort()
337        name = wx.StaticText(self, -1, 'No. of Qx (Qy) bins: ')
338        sizer.Add(name, (iy, ix), (1, 1), \
339                        wx.EXPAND | wx.ADJUST_MINSIZE, 0)
340        ## add parameter value
341        ix += 1
342        self.npt_ctl = InputTextCtrl(self, -1, size=(_BOX_WIDTH * 1.5, 20),
343                            style=wx.TE_PROCESS_ENTER)
344        self.npt_ctl.Bind(wx.EVT_TEXT, self._onparamEnter)
345        self.npt_ctl.SetValue(format_number(self.npts_x, True))
346        sizer.Add(self.npt_ctl, (iy, ix), (1, 1), wx.EXPAND)
347        ## add unit
348        ix += 1
349        unit = wx.StaticText(self, -1, '')
350        sizer.Add(unit, (iy, ix), (1, 1), \
351                        wx.EXPAND | wx.ADJUST_MINSIZE, 0)
352        iy += 1
353        ix = 0
354        name = wx.StaticText(self, -1, 'Qx (Qy) Max: ')
355        sizer.Add(name, (iy, ix), (1, 1), \
356                        wx.EXPAND | wx.ADJUST_MINSIZE, 0)
357        ## add parameter value
358        ix += 1
359        self.qmax_ctl = InputTextCtrl(self, -1, size=(_BOX_WIDTH * 1.5, 20),
360                            style=wx.TE_PROCESS_ENTER)
361        self.qmax_ctl.Bind(wx.EVT_TEXT, self._onparamEnter )
362        self.qmax_ctl.SetValue(format_number(self.qmax_x, True))
363        sizer.Add(self.qmax_ctl, (iy, ix), (1, 1), wx.EXPAND)
364        ## add unit
365        ix += 1
366        unit = wx.StaticText(self, -1, '[1/A]')
367        sizer.Add(unit, (iy, ix), (1, 1), \
368                        wx.EXPAND | wx.ADJUST_MINSIZE, 0)
369        self.qrange_sizer.Add(sizer, 0, wx.LEFT, 10)
370   
371    def _layout_button(self): 
372        """
373            Do the layout for the button widgets
374        """ 
[2d8018f]375        self.est_time = '*Estimated Computation time :\n  %s'
[9624cda]376        self.time_text = wx.StaticText(self, -1, self.est_time% str('2 sec') )
[3657667]377        self.orient_combo = self._fill_orient_combo()
378        self.orient_combo.Show(False)
[318b5bbb]379        self.bt_compute = wx.Button(self, wx.NewId(),'Compute')
380        self.bt_compute.Bind(wx.EVT_BUTTON, self.on_compute)
381        self.bt_compute.SetToolTipString("Compute 2D Scattering Pattern.")
[3f5d75b]382        self.bt_help = wx.Button(self, wx.NewId(),'HELP')
383        self.bt_help.Bind(wx.EVT_BUTTON, self.on_help)
384        self.bt_help.SetToolTipString("Help on Scatter Calculator")
[318b5bbb]385        self.button_sizer.AddMany([(self.time_text , 0, wx.LEFT, 20),
[3f5d75b]386                                   (self.orient_combo , 0, wx.LEFT, 20),
387                                   (self.bt_compute, 0, wx.LEFT, 20),
388                                   (self.bt_help, 0, wx.LEFT, 5)])
[318b5bbb]389       
390    def estimate_ctime(self):
391        """
[3657667]392        Calculation time estimation
[318b5bbb]393        """
[2d8018f]394        # magic equation: not very accurate
395        factor = 1
[318b5bbb]396        n_qbins = float(self.npt_ctl.GetValue())
397        n_qbins *= n_qbins
398        n_pixs = float(self.parent.get_npix())
[9624cda]399        if self.is_avg:
[2d8018f]400            factor = 6
[9624cda]401            n_pixs *= (n_pixs / 200)
[318b5bbb]402        x_in = n_qbins * n_pixs / 100000
[2d8018f]403        etime = factor + 0.085973 * x_in
[318b5bbb]404        return int(etime)
405       
406    def set_est_time(self):
407        """
408        Set text for est. computation time
409        """
[9624cda]410        unit = 'sec'
[318b5bbb]411        if self.time_text != None:
[9624cda]412            self.time_text.SetForegroundColour('black')
[318b5bbb]413            etime = self.estimate_ctime()
[9624cda]414            if etime > 60:
415                etime /= 60
416                unit = 'min'
417                self.time_text.SetForegroundColour('red')
418            time_str = str(etime) + ' ' + unit
419            self.time_text.SetLabel(self.est_time% time_str)
[318b5bbb]420       
421    def _do_layout(self):
422        """
[3657667]423        Draw window content
[318b5bbb]424        """
425        self._define_structure()
426        self._layout_data_name()
427        self._layout_param_size()
428        self._layout_qrange()
429        self._layout_hint()
430        self._layout_shape()
431        self._layout_button()
432        self.boxsizer_source.AddMany([(self.data_name_sizer, 0,
433                                        wx.EXPAND|wx.TOP|wx.BOTTOM, 5),
434                                      (self.hint_sizer, 0,
435                                        wx.EXPAND|wx.TOP|wx.BOTTOM, 5),
436                                      (self.shape_sizer, 0, 
437                                        wx.EXPAND|wx.TOP|wx.BOTTOM, 5)])
438        self.boxsizer_parameters.AddMany([(self.param_sizer, 0,
439                                     wx.EXPAND|wx.TOP|wx.BOTTOM, 5),])
440        self.boxsizer_qrange.AddMany([(self.qrange_sizer, 0,
441                                     wx.EXPAND|wx.TOP|wx.BOTTOM, 5),])
442        self.main_sizer.AddMany([(self.boxsizer_source, 0, 
443                                  wx.EXPAND|wx.ALL, 10),
444                                 (self.boxsizer_parameters, 0, 
445                                  wx.EXPAND|wx.ALL, 10),
446                                 (self.boxsizer_qrange, 0, 
447                                  wx.EXPAND|wx.ALL, 10),
448                                 (self.button_sizer, 0,
449                                  wx.EXPAND|wx.TOP|wx.BOTTOM, 5)])
450        self.SetSizer(self.main_sizer)
451        self.SetAutoLayout(True)
452   
453    def _create_default_sld_data(self):
454        """
455        Making default sld-data
456        """
457        sld_n_default = 6.97e-06
[b9a5f0e]458        omfdata = sas_gen.OMFData()
459        omf2sld = sas_gen.OMF2SLD()
[318b5bbb]460        omf2sld.set_data(omfdata, self.default_shape)
461        self.sld_data = omf2sld.output
462        self.sld_data.is_data = False
463        self.sld_data.filename = "Default SLD Profile"
464        self.sld_data.set_sldn(sld_n_default)
465        self.data_name_tcl.SetValue(self.sld_data.filename)       
466               
467    def choose_data_file(self, location=None):
468        """
469        Choosing a dtata file
470        """
471        path = None
472        filename = ''
473        if location == None:
474            location = os.getcwd()
[968f72d]475
476        exts = "*" + self.omfreader.ext[0]
477        exts += ", *" + self.sldreader.ext[0]
478        exts += ", *" + self.pdbreader.ext[0]
479        all_type = "All GEN files (%s, %s) | %s"% (exts.upper(), exts.lower(), 
480                                               exts.lower().replace(',', ';'))       
481        wildcard = [all_type]
[318b5bbb]482        omf_type = self.omfreader.type
483        sld_type = self.sldreader.type
[dbc5dc9b]484        pdb_type = self.pdbreader.type
[968f72d]485
[318b5bbb]486        for type in sld_type:
487            wildcard.append(type)
488        for type in omf_type:
489            wildcard.append(type)
[077207b]490        for type in pdb_type:
491            wildcard.append(type)
[318b5bbb]492        wildcard = '|'.join(wildcard)
493        dlg = wx.FileDialog(self, "Choose a file", location,
494                            "", wildcard, wx.OPEN)
495        if dlg.ShowModal() == wx.ID_OK:
496            path = dlg.GetPath()
497            filename = os.path.basename(path)
498        dlg.Destroy() 
499        return path
500       
501    def on_load_data(self, event):
502        """
503        Open a file dialog to allow the user to select a given file.
504        The user is only allow to load file with extension .omf, .txt, .sld.
505        Display the slit size corresponding to the loaded data.
506        """
507        location = self.parent.get_path()
508        path = self.choose_data_file(location=location)
509        if path is None:
510            return 
511       
512        self.shape_sizer.ShowItems(False)
513        self.default_shape = 'rectangular'
514        self.parent.set_omfpanel_default_shap(self.default_shape)
515       
516        self.parent.set_file_location(os.path.dirname(path))
517        try:
518            #Load data
519            self.ext = os.path.splitext(path)[-1]
520            if self.ext in self.omfreader.ext:
521                loader = self.omfreader
522            elif self.ext in self.sldreader.ext:
523                loader = self.sldreader
[dbc5dc9b]524            elif self.ext in self.pdbreader.ext:
525                loader = self.pdbreader
[318b5bbb]526            else:
527                loader = None
528            if self.reader is not None and self.reader.isrunning():
529                self.reader.stop()
[077207b]530            self.browse_button.Enable(False)
531            self.browse_button.SetLabel("Loading...")
[318b5bbb]532            if self.parent.parent is not None:
533                wx.PostEvent(self.parent.parent, 
534                                StatusEvent(status="Loading...",
535                                type="progress"))
536            self.reader = GenReader(path=path, loader=loader,
537                                    completefn=self.complete_loading,
538                                    updatefn=self.load_update)
539            self.reader.queue()
[077207b]540            #self.load_update()
[318b5bbb]541        except:
542            self.ext = None
543            if self.parent.parent is None:
544                return 
[b9a5f0e]545            msg = "Generic SAS Calculator: %s" % (sys.exc_value)
[318b5bbb]546            wx.PostEvent(self.parent.parent,
547                          StatusEvent(status=msg, type='stop'))
548            self.SetFocus()
549            return 
550       
551    def load_update(self):
552        """
553        print update on the status bar
[077207b]554        """       
[318b5bbb]555        if self.parent.parent is None:
556                return 
557        if self.reader.isrunning():
558            type = "progress"
559        else:
560            type = "stop"
561        wx.PostEvent(self.parent.parent, StatusEvent(status="",
562                                                  type=type))
563           
564    def complete_loading(self, data=None, filename=''):
565        """
566        Complete the loading
567        """
568        #compute the slit size
[077207b]569        self.browse_button.Enable(True)
570        self.browse_button.SetLabel('Load')
[318b5bbb]571        try:
[3cfa760]572            is_pdbdata = False
[318b5bbb]573            filename = data.filename
574            self.data_name_tcl.SetValue(str(filename))
575            self.file_name = filename.split('.')[0]
[3657667]576            self.orient_combo.SetSelection(0)
[9624cda]577            self.is_avg = False
[318b5bbb]578            if self.ext in self.omfreader.ext:
[b9a5f0e]579                gen = sas_gen.OMF2SLD()
[318b5bbb]580                gen.set_data(data)
581                #omf_data = data
582                self.sld_data = gen.get_magsld()
583            elif self.ext in self.sldreader.ext:
584                self.sld_data = data
[dbc5dc9b]585            elif self.ext in self.pdbreader.ext:
586                self.sld_data = data
[3cfa760]587                is_pdbdata = True
[318b5bbb]588                #omf_data = None
589            else:
590                raise
[3657667]591            self.orient_combo.Show(is_pdbdata)
592            self.button_sizer.Layout()
[318b5bbb]593            self._set_sld_data_helper(True)
594        except:
595            if self.parent.parent is None:
[077207b]596                raise
[318b5bbb]597            msg = "Loading Error: This file format is not supported "
[b9a5f0e]598            msg += "for GenSAS." 
[318b5bbb]599            wx.PostEvent(self.parent.parent,
600                          StatusEvent(status=msg, type='stop', info='Error'))
601            self.SetFocus()
602            return 
603        if self.parent.parent is None:
604            return 
[077207b]605       
[318b5bbb]606        msg = "Load Complete"
607        wx.PostEvent(self.parent.parent, StatusEvent(status=msg, type='stop'))
608        self.SetFocus()
609       
610    def _set_sld_data_helper(self, is_draw=False):
611        """
612        Set sld data helper
613        """
[9624cda]614        #is_avg = self.orient_combo.GetCurrentSelection() == 1
615        self.model.set_is_avg(self.is_avg)
[318b5bbb]616        self.model.set_sld_data(self.sld_data)
[afd45674]617       
[318b5bbb]618        self.draw_button.Enable(self.sld_data!=None)
619        wx.CallAfter(self.parent.set_sld_data, self.sld_data)
[afd45674]620        self._update_model_params()
[318b5bbb]621        if is_draw:
[1de85f4]622            wx.CallAfter(self.sld_draw, None, False)
[afd45674]623   
624    def _update_model_params(self):
625        """
626        Update the model parameter values
627        """
628        for list in self.parameters:
629            param_name = list[0].GetLabelText()
630            val = str(self.model.params[param_name])
631            list[1].SetValue(val)
632   
633    def set_volume_ctl_val(self, val):
634        """
635        Set volume txtctrl value
636        """
637        for list in self.parameters:
638            param_name = list[0].GetLabelText()
639            if param_name.lower() == 'total_volume':
640                list[1].SetValue(val)
641                list[1].Refresh()
642                break
643                           
[318b5bbb]644    def _onparamEnter(self, event):
645        """
646        On param enter
647        """
648        try:
649            item = event.GetEventObject()
650            self._check_value()
651            item.Refresh()
652        except:
653            pass
654   
[1de85f4]655    def sld_draw(self, event=None, has_arrow=True):
[318b5bbb]656        """
657        Draw 3D sld profile
658        """
659        flag = self.parent.check_omfpanel_inputs()
660        if not flag:
661            infor = 'Error'
662            msg = 'Error: Wrong inputs in the SLD info panel.'
663            # inform msg to wx
664            wx.PostEvent(self.parent.parent,
665                    StatusEvent(status=msg, info=infor))
666            self.SetFocus()
667            return
668
669        self.sld_data = self.parent.get_sld_from_omf()
670        output = self.sld_data 
671        #frame_size = wx.Size(470, 470)   
[d4895dd]672        self.plot_frame = PlotFrame(self, -1, 'testView')
[318b5bbb]673        frame = self.plot_frame
674        frame.Show(False)
675        add_icon(self.parent, frame)
[fdb134b9]676        panel = frame.plotpanel   
[318b5bbb]677        try:
678            # mpl >= 1.0.0
679            ax = panel.figure.gca(projection='3d')
680        except:
681            # mpl < 1.0.0
682            try:
683                from mpl_toolkits.mplot3d import Axes3D
684                ax = Axes3D(panel.figure)
685            except:
686                logging.error("PlotPanel could not import Axes3D")
687                raise
[fad6056]688        panel.dimension = 3   
[1de85f4]689        graph_title = self._sld_plot_helper(ax, output, has_arrow)
[fdb134b9]690        # Use y, z axes (in mpl 3d) as z, y axes
[b9a5f0e]691        # that consistent with our SAS detector coords.
[fdb134b9]692        ax.set_xlabel('x ($\A%s$)'% output.pos_unit)
693        ax.set_ylabel('z ($\A%s$)'% output.pos_unit)
694        ax.set_zlabel('y ($\A%s$)'% output.pos_unit)
695        panel.subplot.figure.subplots_adjust(left=0.05, right=0.95, 
696                                             bottom=0.05, top=0.96)
697        if output.pix_type == 'atom':
698            ax.legend(loc='upper left', prop={'size':10})
699        num_graph = str(self.graph_num)
700        frame.SetTitle('Graph %s: %s'% (num_graph, graph_title))       
701        wx.CallAfter(frame.Show, True)
702        self.graph_num += 1
703
704    def _sld_plot_helper(self, ax, output, has_arrow=False):
705        """
706        Actual plot definition happens here
707        :Param ax: axis3d
708        :Param output: sld_data [MagSLD]
709        :Param has_arrow: whether or not draws M vector [bool]
710        """
711        # Set the locals
712        color_dic = {'H':'blue', 'D':'purple', 'N': 'orange', 
713                     'O':'red', 'C':'green', 'P':'cyan', 'Other':'k'}
[dbc5dc9b]714        marker = ','
715        m_size = 2
[1de85f4]716        graph_title = self.file_name
717        graph_title += "   3D SLD Profile "
[318b5bbb]718        pos_x = output.pos_x
719        pos_y = output.pos_y
720        pos_z = output.pos_z
721        sld_mx = output.sld_mx
722        sld_my = output.sld_my
[3657667]723        sld_mz = output.sld_mz
724        pix_symbol = output.pix_symbol
[fdb134b9]725        if output.pix_type == 'atom':
726            marker = 'o'
727            m_size = 3.5
728        sld_tot = (numpy.fabs(sld_mx) + numpy.fabs(sld_my) + \
[318b5bbb]729                   numpy.fabs(sld_mz) + numpy.fabs(output.sld_n))
730        is_nonzero = sld_tot > 0.0 
[fdb134b9]731        is_zero = sld_tot == 0.0   
732        # I. Plot null points
[318b5bbb]733        if is_zero.any():
[077207b]734            ax.plot(pos_x[is_zero], pos_z[is_zero], pos_y[is_zero], marker, 
[fdb134b9]735                    c="y", alpha=0.5, markeredgecolor='y', markersize=m_size) 
[318b5bbb]736            pos_x = pos_x[is_nonzero]
737            pos_y = pos_y[is_nonzero]
738            pos_z = pos_z[is_nonzero]
739            sld_mx = sld_mx[is_nonzero]
740            sld_my = sld_my[is_nonzero]
741            sld_mz = sld_mz[is_nonzero]
[3657667]742            pix_symbol = output.pix_symbol[is_nonzero]
[fdb134b9]743        # II. Plot selective points in color
[3657667]744        other_color = numpy.ones(len(pix_symbol), dtype='bool')
[dbc01f2]745        for key in color_dic.keys():
[3657667]746            chosen_color = pix_symbol == key
[440006a]747            if numpy.any(chosen_color):
[dbc01f2]748                other_color = other_color  & (chosen_color != True)
749                color = color_dic[key]
750                ax.plot(pos_x[chosen_color], pos_z[chosen_color], 
751                        pos_y[chosen_color], marker, c=color, alpha=0.5, 
752                        markeredgecolor=color, markersize=m_size, label=key) 
[fdb134b9]753        # III. Plot All others       
[440006a]754        if numpy.any(other_color):
[fdb134b9]755            a_name = ''
756            if output.pix_type == 'atom':
757                # Get atom names not in the list
758                a_names = [symb  for symb in pix_symbol \
759                           if symb not in color_dic.keys()]
760                a_name = a_names[0]
761                for name in a_names:
762                    new_name = ", " + name
[644f95b]763                    if a_name.count(name) == 0:
[fdb134b9]764                        a_name += new_name
765            # plot in black
[dbc01f2]766            ax.plot(pos_x[other_color], pos_z[other_color], pos_y[other_color], 
767                    marker, c="k", alpha=0.5, markeredgecolor="k", 
[fdb134b9]768                    markersize=m_size, label=a_name) 
769        # IV. Draws atomic bond with grey lines if any
770        if output.has_conect:
[11363ee]771            for ind in range(len(output.line_x)):
772                ax.plot(output.line_x[ind], output.line_z[ind], 
773                        output.line_y[ind], '-', lw=0.6, c="grey", alpha=0.3) 
[fdb134b9]774        # V. Draws magnetic vectors
[318b5bbb]775        if has_arrow and len(pos_x) > 0:     
[1de85f4]776            graph_title += " - Magnetic Vector as Arrow -" 
777            panel = self.plot_frame.plotpanel
[9624cda]778            def _draw_arrow(input=None, update=None):
[318b5bbb]779                """
[fdb134b9]780                draw magnetic vectors w/arrow
[318b5bbb]781                """
782                max_mx = max(numpy.fabs(sld_mx))
783                max_my = max(numpy.fabs(sld_my))
784                max_mz = max(numpy.fabs(sld_mz))
785                max_m = max(max_mx, max_my, max_mz)
786                try:
787                    max_step = max(output.xstepsize, output.ystepsize, 
788                                   output.zstepsize)
789                except:
790                    max_step = 0
791                if max_step <= 0:
792                    max_step = 5
793                try:
794                    if max_m != 0:
795                        unit_x2 = sld_mx / max_m
796                        unit_y2 = sld_my / max_m
797                        unit_z2 = sld_mz / max_m
798                        # 0.8 is for avoiding the color becomes white=(1,1,1))
799                        color_x = numpy.fabs(unit_x2 * 0.8)
800                        color_y = numpy.fabs(unit_y2 * 0.8)
801                        color_z = numpy.fabs(unit_z2 * 0.8)
802                        x2 = pos_x + unit_x2 * max_step
803                        y2 = pos_y + unit_y2 * max_step
804                        z2 = pos_z + unit_z2 * max_step
805                        x_arrow = numpy.column_stack((pos_x, x2))
806                        y_arrow = numpy.column_stack((pos_y, y2))
807                        z_arrow = numpy.column_stack((pos_z, z2))
[fdb134b9]808                        colors = numpy.column_stack((color_x, color_y, color_z))
[077207b]809                        arrows = Arrow3D(panel, x_arrow, z_arrow, y_arrow, 
[fdb134b9]810                                        colors, mutation_scale=10, lw=1, 
811                                        arrowstyle="->", alpha = 0.5)
[dbc01f2]812                        ax.add_artist(arrows) 
[318b5bbb]813                except:
814                    pass 
815                msg = "Arrow Drawing completed.\n"
816                status_type = 'stop'
817                self._status_info(msg, status_type) 
[1de85f4]818            msg = "Arrow Drawing is in progress..."
819            status_type = 'progress'
820            self._status_info(msg, status_type) 
821            draw_out = CalcGen(input=ax,
822                             completefn=_draw_arrow, updatefn=self._update)
823            draw_out.queue()
824        return graph_title
[fdb134b9]825 
[318b5bbb]826    def set_input_params(self):
827        """
828        Set model parameters
829        """
830        for list in self.parameters:
831            param_name = list[0].GetLabelText()
832            param_value = float(list[1].GetValue())
833            self.model.setParam(param_name, param_value)
834           
835    def on_compute(self, event):
836        """
837        Compute I(qx, qy)
838        """
839        flag = self.parent.check_omfpanel_inputs()
840        if not flag and self.parent.parent != None:
841            infor = 'Error'
842            msg = 'Error: Wrong inputs in the SLD info panel.'
843            # inform msg to wx
844            wx.PostEvent(self.parent.parent,
845                    StatusEvent(status=msg, info=infor))
846            self.SetFocus()
847            return
848        self.sld_data = self.parent.get_sld_from_omf()
849        if self.sld_data == None:
850            if self.parent.parent != None:
851                infor = 'Error'
852                msg = 'Error: No data has been selected.'
853                # inform msg to wx
854                wx.PostEvent(self.parent.parent,
855                        StatusEvent(status=msg, info=infor))
856                self.SetFocus()
857            return
858        flag = self._check_value()
859        if not flag:
860            _set_error(self, None, True)
861            return
862        try:
863            self.model.set_sld_data(self.sld_data)
864            self.set_input_params()
[9624cda]865            if self.is_avg or self.is_avg == None:
866                self._create_default_1d_data()
867                i_out = numpy.zeros(len(self.data.y))
868                inputs = [self.data.x, [], i_out]
869            else:
870                self._create_default_2d_data()
871                i_out = numpy.zeros(len(self.data.data))
872                inputs=[self.data.qx_data, self.data.qy_data, i_out]
873               
[318b5bbb]874            msg = "Computation is in progress..."
875            status_type = 'progress'
876            self._status_info(msg, status_type)
[9624cda]877            cal_out = CalcGen(input=inputs, 
[9714ff5]878                              completefn=self.complete, 
879                              updatefn=self._update)
[9624cda]880            cal_out.queue()             
[318b5bbb]881           
882        except:
883            msg = "%s."% sys.exc_value
884            status_type = 'stop'
885            self._status_info(msg, status_type)
886            wx.PostEvent(self.parent.parent,
887                        StatusEvent(status=msg, info='Error'))
888            self.SetFocus()
889
[3f5d75b]890    def on_help(self, event):   
891        """
892        Bring up the General scattering Calculator Documentation whenever
893        the HELP button is clicked.
894       
895        Calls DocumentationWindow with the path of the location within the
896        documentation tree (after /doc/ ....".  Note that when using old
897        versions of Wx (before 2.9) and thus not the release version of
898        installers, the help comes up at the top level of the file as
899        webbrowser does not pass anything past the # to the browser when it is
900        running "file:///...."
901   
902    :param evt: Triggers on clicking the help button
903    """
904               
905        _TreeLocation = "user/perspectives/calculator/sas_calculator_help.html"
906        _doc_viewer = DocumentationWindow(self, -1, \
907             _TreeLocation,"General Scattering Calculator Help")
908
[318b5bbb]909    def _check_value(self):
910        """
911        Check input values if float
912        """
913        flag = True
914        self.npt_ctl.SetBackgroundColour("white")
915        self.qmax_ctl.SetBackgroundColour("white")
916        try:
917            npt_val = float(self.npt_ctl.GetValue()) 
[46be5e6]918            if npt_val < 2 or npt_val > 1000:
[318b5bbb]919                raise
920            self.npt_ctl.SetValue(str(int(npt_val)))
921            self.set_est_time()
922        except:
[dbc5dc9b]923            flag =  _set_error(self, self.npt_ctl)
[318b5bbb]924        try:
[46be5e6]925            qmax_val = float(self.qmax_ctl.GetValue()) 
926            if qmax_val <= 0 or qmax_val > 1000:
[318b5bbb]927                raise
928        except:
929            flag = _set_error(self, self.qmax_ctl)       
930        for list in self.parameters:
931            list[1].SetBackgroundColour("white")
932            param_name = list[0].GetLabelText()
933            try: 
934                param_val = float(list[1].GetValue())
935                if param_name.count('frac') > 0:
936                    if param_val < 0 or param_val > 1:
937                       raise
938            except:
939                flag = _set_error(self, list[1])
940        return flag
941                   
942    def _status_info(self, msg = '', type = "update"):
943        """
944        Status msg
945        """
946        if type == "stop":
947            label = "Compute"
948            able = True
949        else:   
950            label = "Wait..."
951            able = False
952        self.bt_compute.Enable(able)
953        self.bt_compute.SetLabel(label)
954        self.bt_compute.SetToolTipString(label)
955        if self.parent.parent != None:
956            wx.PostEvent(self.parent.parent, 
957                             StatusEvent(status = msg, type = type )) 
958
959    def _update(self, time=None):
960        """
[9624cda]961        Update the progress bar
[318b5bbb]962        """
[9624cda]963        if self.parent.parent == None:
964            return
965        type = "progress"
966        msg = "Please wait. Computing... (Note: Window may look frozen.)"
967        wx.PostEvent(self.parent.parent, StatusEvent(status=msg,
968                                                  type=type))
[318b5bbb]969                               
[9624cda]970    def complete(self, input, update=None):   
[318b5bbb]971        """
972        Gen compute complete function
973        :Param input: input list [qx_data, qy_data, i_out]
974        """
[9624cda]975        out = numpy.empty(0)
[2d8018f]976        #s = time.time()
[9624cda]977        for ind in range(len(input[0])):
978            if self.is_avg:
979                if ind % 1 == 0 and update != None:
980                    update()
981                    time.sleep(0.1)
982                inputi = [input[0][ind:ind+1], [], input[2][ind:ind+1]]
983                outi = self.model.run(inputi)
984                out = numpy.append(out, outi)
985            else:
986                if ind % 50 == 0  and update != None:
987                    update()
988                    time.sleep(0.001)
989                inputi = [input[0][ind:ind+1], input[1][ind:ind+1], 
990                          input[2][ind:ind+1]]
991                outi = self.model.runXY(inputi)
992                out = numpy.append(out, outi)
[2d8018f]993        #print time.time() - s
[9624cda]994        if self.is_avg or self.is_avg == None:
995            self._draw1D(out)
996        else:
997            #out = self.model.runXY(input)
998            self._draw2D(out)
999           
[318b5bbb]1000        msg = "Gen computation completed.\n"
1001        status_type = 'stop'
1002        self._status_info(msg, status_type)
[9624cda]1003               
[318b5bbb]1004    def _create_default_2d_data(self):
1005        """
1006        Create 2D data by default
1007        Only when the page is on theory mode.
1008        :warning: This data is never plotted.
1009        """
1010        self.qmax_x = float(self.qmax_ctl.GetValue())
1011        self.npts_x = int(float(self.npt_ctl.GetValue()))
1012        self.data = Data2D()
1013        qmax = self.qmax_x #/ numpy.sqrt(2)
1014        self.data.xaxis('\\rm{Q_{x}}', '\AA^{-1}')
1015        self.data.yaxis('\\rm{Q_{y}}', '\AA^{-1}')
1016        self.data.is_data = False
1017        self.data.id = str(self.uid) + " GenData"
1018        self.data.group_id = str(self.uid) + " Model2D"
1019        ## Default values
1020        self.data.detector.append(Detector())
1021        index = len(self.data.detector) - 1
1022        self.data.detector[index].distance = 8000   # mm
1023        self.data.source.wavelength = 6             # A
1024        self.data.detector[index].pixel_size.x = 5  # mm
1025        self.data.detector[index].pixel_size.y = 5  # mm
1026        self.data.detector[index].beam_center.x = qmax
1027        self.data.detector[index].beam_center.y = qmax
1028        xmax = qmax
1029        xmin = -qmax
1030        ymax = qmax
1031        ymin = -qmax
1032        qstep = self.npts_x
1033
1034        x = numpy.linspace(start=xmin, stop=xmax, num=qstep, endpoint=True)
1035        y = numpy.linspace(start=ymin, stop=ymax, num=qstep, endpoint=True)
1036        ## use data info instead
1037        new_x = numpy.tile(x, (len(y), 1))
1038        new_y = numpy.tile(y, (len(x), 1))
1039        new_y = new_y.swapaxes(0, 1)
1040        # all data reuire now in 1d array
1041        qx_data = new_x.flatten()
1042        qy_data = new_y.flatten()
1043        q_data = numpy.sqrt(qx_data * qx_data + qy_data * qy_data)
1044        # set all True (standing for unmasked) as default
1045        mask = numpy.ones(len(qx_data), dtype=bool)
1046        # store x and y bin centers in q space
1047        x_bins = x
1048        y_bins = y
1049        self.data.source = Source()
1050        self.data.data = numpy.ones(len(mask))
1051        self.data.err_data = numpy.ones(len(mask))
1052        self.data.qx_data = qx_data
1053        self.data.qy_data = qy_data
1054        self.data.q_data = q_data
1055        self.data.mask = mask
1056        self.data.x_bins = x_bins
1057        self.data.y_bins = y_bins
1058        # max and min taking account of the bin sizes
1059        self.data.xmin = xmin
1060        self.data.xmax = xmax
1061        self.data.ymin = ymin
1062        self.data.ymax = ymax
[9624cda]1063
1064    def _create_default_1d_data(self):
1065        """
1066        Create 2D data by default
1067        Only when the page is on theory mode.
1068        :warning: This data is never plotted.
1069                    residuals.x = data_copy.x[index]
1070            residuals.dy = numpy.ones(len(residuals.y))
1071            residuals.dx = None
1072            residuals.dxl = None
1073            residuals.dxw = None
1074        """
1075        self.qmax_x = float(self.qmax_ctl.GetValue())
1076        self.npts_x = int(float(self.npt_ctl.GetValue()))
1077        qmax = self.qmax_x #/ numpy.sqrt(2)
1078        ## Default values
1079        xmax = qmax
1080        xmin = qmax * _Q1D_MIN
1081        qstep = self.npts_x
1082        x = numpy.linspace(start=xmin, stop=xmax, num=qstep, endpoint=True)
1083        # store x and y bin centers in q space
1084        #self.data.source = Source()
1085        y = numpy.ones(len(x))
1086        dy = numpy.zeros(len(x))
1087        dx = numpy.zeros(len(x))
1088        self.data = Data1D(x=x, y=y)
1089        self.data.dx = dx
1090        self.data.dy = dy
1091
1092    def _draw1D(self, y_out):
1093        """
1094        Complete get the result of modelthread and create model 2D
1095        that can be plot.
1096        """
1097        page_id = self.id
1098        data = self.data
1099       
1100        model = self.model
1101        state = None
[318b5bbb]1102       
[9624cda]1103        new_plot = Data1D(x=data.x, y=y_out)
1104        new_plot.dx = data.dx
1105        new_plot.dy = data.dy
1106        new_plot.xaxis('\\rm{Q_{x}}', '\AA^{-1}')
1107        new_plot.yaxis('\\rm{Intensity}', 'cm^{-1}')
1108        new_plot.is_data = False
1109        new_plot.id = str(self.uid) + " GenData1D"
1110        new_plot.group_id = str(self.uid) + " Model1D"
1111        new_plot.name = model.name + '1d'
1112        new_plot.title = "Generic model1D "
1113        new_plot.id = str(page_id) + ': ' + self.file_name \
1114                        + ' #%s'% str(self.graph_num) + "_1D"
1115        new_plot.group_id = str(page_id) + " Model1D"  +\
1116                             ' #%s'% str(self.graph_num) + "_1D"
1117        new_plot.is_data = False
1118
1119        title = new_plot.title
1120        _yaxis, _yunit = new_plot.get_yaxis()
1121        _xaxis, _xunit = new_plot.get_xaxis()
1122        new_plot.xaxis(str(_xaxis), str(_xunit))
1123        new_plot.yaxis(str(_yaxis), str(_yunit))
1124       
1125        if new_plot.is_data:
1126            data_name = str(new_plot.name)
1127        else:
1128            data_name = str(model.__class__.__name__) + '1d'
1129
1130        if len(title) > 1:
1131            new_plot.title = "Gen Theory for %s "% model.name + data_name
1132        new_plot.name = new_plot.id
1133        new_plot.label = new_plot.id
1134        #theory_data = deepcopy(new_plot)
1135        if self.parent.parent != None:
1136            self.parent.parent.update_theory(data_id=new_plot.id,
1137                                           theory=new_plot,
1138                                           state=state)
1139        title = new_plot.title
1140        num_graph = str(self.graph_num)
1141        wx.CallAfter(self.parent.draw_graph, new_plot, 
[ae84427]1142                     title="GEN Graph %s: "% num_graph + new_plot.id )
[9624cda]1143        self.graph_num += 1
1144               
[318b5bbb]1145    def _draw2D(self, image):
1146        """
1147        Complete get the result of modelthread and create model 2D
1148        that can be plot.
1149        """
1150        page_id = self.id
1151        data = self.data
1152       
1153        model = self.model
1154        qmin = 0.0
1155        state = None
1156       
1157        numpy.nan_to_num(image)
1158        new_plot = Data2D(image=image, err_image=data.err_data)
1159        new_plot.name = model.name + '2d'
1160        new_plot.title = "Generic model 2D "
1161        new_plot.id = str(page_id) + ': ' + self.file_name \
[9624cda]1162                        + ' #%s'% str(self.graph_num) + "_2D"
1163        new_plot.group_id = str(page_id) + " Model2D" \
1164                        + ' #%s'% str(self.graph_num) + "_2D"
[318b5bbb]1165        new_plot.detector = data.detector
1166        new_plot.source = data.source
1167        new_plot.is_data = False
1168        new_plot.qx_data = data.qx_data
1169        new_plot.qy_data = data.qy_data
1170        new_plot.q_data = data.q_data
1171        new_plot.mask = data.mask
1172        ## plot boundaries
1173        new_plot.ymin = data.ymin
1174        new_plot.ymax = data.ymax
1175        new_plot.xmin = data.xmin
1176        new_plot.xmax = data.xmax
1177        title = data.title
1178        _yaxis, _yunit = data.get_yaxis()
1179        _xaxis, _xunit = data.get_xaxis()
1180        new_plot.xaxis(str(_xaxis), str(_xunit))
1181        new_plot.yaxis(str(_yaxis), str(_yunit))
1182       
1183        new_plot.is_data = False
1184        if data.is_data:
1185            data_name = str(data.name)
1186        else:
1187            data_name = str(model.__class__.__name__) + '2d'
1188
1189        if len(title) > 1:
1190            new_plot.title = "Gen Theory for %s "% model.name + data_name
1191        new_plot.name = new_plot.id
1192        new_plot.label = new_plot.id
1193        #theory_data = deepcopy(new_plot)
1194        if self.parent.parent != None:
1195            self.parent.parent.update_theory(data_id=data.id,
1196                                           theory=new_plot,
1197                                           state=state)
1198        title = new_plot.title
1199        num_graph = str(self.graph_num)
1200        wx.CallAfter(self.parent.draw_graph, new_plot, 
[ae84427]1201                     title="GEN Graph %s: "% num_graph + new_plot.id )
[318b5bbb]1202        self.graph_num += 1
[ae84427]1203         
[318b5bbb]1204    def set_scale2d(self, scale):
1205        """
1206        Set SLD plot scale
1207        """
1208        self.scale2d = None
1209       
1210    def on_panel_close(self, event):
1211        """
1212        On Close SLD panel
1213        """
1214        #Not implemented   
1215                 
1216class OmfPanel(ScrolledPanel, PanelBase):
1217    """
1218        Provides the sas gen calculator GUI.
1219    """
1220    ## Internal nickname for the window, used by the AUI manager
1221    window_name = "SLD Pixel Info"
1222    ## Name to appear on the window title bar
1223    window_caption = "SLD Pixel Info "
1224   
1225    def __init__(self, parent, *args, **kwds):
1226        ScrolledPanel.__init__(self, parent, style=wx.RAISED_BORDER, 
1227                               *args, **kwds)
1228        PanelBase.__init__(self)
1229        #Font size
1230        self.SetWindowVariant(variant=FONT_VARIANT)
1231        self.SetupScrolling() 
1232        # Object that receive status event
1233        self.parent = parent
[b9a5f0e]1234        self.sld_data = sas_gen.MagSLD([0], [0], [0]) 
[318b5bbb]1235        self.sld_ctl = None
1236        self.default_shape = 'rectangular'
1237        self._do_layout()
1238       
1239    def set_slddata(self, slddata):
1240        """
1241        Set sld data related items
1242        """
1243        self.sld_data = slddata
1244        self._set_slddata_ctr_val(slddata)
1245        # Make sure that self._set_slddata_ctr_val() is finished
1246        wx.CallAfter(self._set_omfdata_ctr, slddata)
1247   
1248    def get_sld_val(self):
1249        """
1250        Set sld_n of slddata on sld input
1251        """
1252        sld_sets = {}
1253        if not self.sld_data.is_data:
1254            self._get_other_val()
1255        for list in self.slds:
1256            if list[1].IsEnabled():
1257                list[1].SetBackgroundColour("white")
1258                list[1].Refresh()
1259                try:
1260                    val = float(list[1].GetValue())
1261                    sld_sets[list[0]] = val
1262                except:
1263                    flag = _set_error(self, list[1])
1264                    if not flag:
1265                        return self.sld_data
1266            else:
[cd89c6f]1267               sld_sets[list[0]] = None
[318b5bbb]1268        for key in sld_sets.keys():
1269            key_low = key.lower()
1270            if key_low.count('mx') > 0:
1271                if sld_sets[key] == None:
1272                    sld_sets[key] = self.sld_data.sld_mx
1273                mx = sld_sets[key]
1274            elif key_low.count('my') > 0:
1275                if sld_sets[key] == None:
1276                    sld_sets[key] = self.sld_data.sld_my
1277                my = sld_sets[key]
1278            elif key_low.count('mz') > 0:
1279                if sld_sets[key] == None:
1280                    sld_sets[key] = self.sld_data.sld_mz
1281                mz = sld_sets[key]
1282            else:
1283                if sld_sets[key] != None:
1284                    self.sld_data.set_sldn(sld_sets[key])
1285        self.sld_data.set_sldms(mx, my, mz)
1286        self._set_slddata_ctr_val(self.sld_data)
1287       
1288        return self.sld_data
1289   
[dbc01f2]1290    def get_pix_volumes(self):
[318b5bbb]1291        """
1292        Get the pixel volume
1293        """
[dbc01f2]1294        vol = self.sld_data.vol_pix
[318b5bbb]1295       
[dbc01f2]1296        return vol
[318b5bbb]1297               
1298    def _get_other_val(self): 
1299        """
1300        """
[b9a5f0e]1301        omfdata = sas_gen.OMFData()
[318b5bbb]1302        sets = {}
1303        try:
1304            for lst in self.stepsize:
1305                if lst[1].IsEnabled():
1306                    val = float(lst[1].GetValue())
1307                    sets[lst[0]] = val
1308                else:
1309                    sets[lst[0]] = None
1310                    return
1311            for lst in self.nodes:
1312                if lst[1].IsEnabled():
1313                    val = float(lst[1].GetValue())
1314                    sets[lst[0]] = val
1315                else:
1316                    sets[lst[0]] = None
1317                    return
1318                   
1319            for key in sets.keys():
1320                exec "omfdata.%s = sets['%s']"% (key, key)           
1321
[b9a5f0e]1322            omf2sld = sas_gen.OMF2SLD()
[318b5bbb]1323            omf2sld.set_data(omfdata, self.default_shape)
1324            self.sld_data = omf2sld.output
1325            self.sld_data.is_data = False
1326            self.sld_data.filename = "Default SLD Profile"
1327        except:
1328            msg = "OMF Panel: %s"% sys.exc_value
1329            infor = 'Error'
1330            #logging.error(msg)
1331            if self.parent.parent != None:
1332                # inform msg to wx
1333                wx.PostEvent(self.parent.parent,
1334                        StatusEvent(status=msg, info=infor))
1335                self.SetFocus()
1336               
1337    def _set_slddata_ctr_val(self, slddata):
1338        """
1339        Set slddata crl
1340        """
1341        try:
1342            val = str(len(slddata.sld_n))
1343        except:
1344            val = 'Unknown'
1345        self.npix_ctl.SetValue(val)
1346       
1347    def _set_omfdata_ctr(self, omfdata):   
1348        """
1349        Set the textctr box values
1350        """
1351       
1352        if omfdata == None:
1353            self._set_none_text()
1354            return
1355        nodes_list = self._get_nodes_key_list(omfdata)
1356        step_list = self._get_step_key_list(omfdata)
1357        for ctr_list in self.nodes:
1358            for key in nodes_list.keys():
1359                if ctr_list[0] == key:
1360                    ctr_list[1].SetValue(format_number(nodes_list[key], True))
1361                    ctr_list[1].Enable(not omfdata.is_data)
1362                    break
1363        for ctr_list in self.stepsize:
1364            for key in step_list.keys():
1365                if ctr_list[0] == key:
1366                    ctr_list[1].SetValue(format_number(step_list[key], True))
1367                    ctr_list[1].Enable(not omfdata.is_data)
1368                    break   
1369               
1370    def _set_none_text(self):
1371        """
1372        Set Unknown in textctrls
1373        """
1374        val = 'Unknown'
1375        for ctr_list in self.nodes:
1376            ctr_list[1].SetValue(val)
1377        for ctr_list in self.stepsize:
1378            ctr_list[1].SetValue(val)
1379               
1380    def _define_structure(self):
1381        """
1382        Define the main sizers building to build this application.
1383        """
1384        self.main_sizer = wx.BoxSizer(wx.VERTICAL)
1385       
1386        self.npixels_sizer = wx.BoxSizer(wx.HORIZONTAL)
[077207b]1387        self.box_sld = wx.StaticBox(self, -1, 
[be0fe41]1388                                    str("Mean SLD"))
[318b5bbb]1389        self.box_node = wx.StaticBox(self, -1, str("Nodes"))
1390        self.boxsizer_sld = wx.StaticBoxSizer(self.box_sld, wx.VERTICAL)
1391        self.box_stepsize = wx.StaticBox(self, -1, str("Step Size"))
1392        self.boxsizer_node = wx.StaticBoxSizer(self.box_node, wx.VERTICAL)
1393        self.boxsizer_stepsize = wx.StaticBoxSizer(self.box_stepsize,
1394                                                    wx.VERTICAL)
1395        self.sld_sizer = wx.BoxSizer(wx.HORIZONTAL)
1396        self.node_sizer = wx.BoxSizer(wx.HORIZONTAL)
1397        self.step_sizer = wx.BoxSizer(wx.HORIZONTAL)
1398        self.hint_sizer = wx.BoxSizer(wx.HORIZONTAL)
1399        self.button_sizer = wx.BoxSizer(wx.HORIZONTAL)
1400               
1401    def _layout_npix(self):
1402        """
1403        Build No of pixels sizer
1404        """
1405        num_pix_text = wx.StaticText(self, -1, "No. of Pixels: ") 
1406        self.npix_ctl = OutputTextCtrl(self, -1, size=(_BOX_WIDTH, 20),
1407                                style=wx.TE_PROCESS_ENTER)
1408        self._set_slddata_ctr_val(self.sld_data)
1409        self._set_omfdata_ctr(self.sld_data) 
1410        self.npixels_sizer.AddMany([(num_pix_text, 0,
1411                                          wx.EXPAND|wx.LEFT|wx.TOP, 5),
1412                                     (self.npix_ctl, 0,
1413                                     wx.EXPAND|wx.TOP, 5)])
1414
1415    def _layout_slds(self):
1416        """
1417        Build nuclear sld sizer
1418        """
1419        self.slds = []
1420        omfdata = self.sld_data
1421        if omfdata == None:
1422            raise
1423        sld_key_list = self._get_slds_key_list(omfdata)
1424        # Dic is not sorted
1425        key_list = [key for key in sld_key_list.keys()]
1426        # Sort here
1427        key_list.sort()
1428        is_data = self.sld_data.is_data
1429        sizer = wx.GridBagSizer(2, 3)
1430        ix = 0
1431        iy = -1
1432        for key in key_list:
1433            value = sld_key_list[key]
1434            iy += 1
1435            ix = 0
1436            name = wx.StaticText(self, -1, key)
1437            sizer.Add(name, (iy, ix), (1, 1), \
1438                            wx.EXPAND | wx.ADJUST_MINSIZE, 0)
1439            ## add parameter value
1440            ix += 1
1441            ctl = InputTextCtrl(self, -1, size=(_BOX_WIDTH, 20),
1442                                style=wx.TE_PROCESS_ENTER)
1443            ctl.SetValue(format_number(value, True))
1444            ctl.Enable(not is_data)
1445            sizer.Add(ctl, (iy, ix), (1, 1), wx.EXPAND)
1446            ## add unit
1447            ix += 1
1448            s_unit = '[' + omfdata.sld_unit + ']'
1449            unit = wx.StaticText(self, -1, s_unit)
1450            sizer.Add(unit, (iy, ix), (1, 1), \
1451                            wx.EXPAND | wx.ADJUST_MINSIZE, 0)
1452            self.slds.append([key, ctl, unit])
1453        self.sld_sizer.Add(sizer, 0, wx.LEFT, 10) 
1454               
1455    def _layout_nodes(self):
1456        """
1457        Fill the sizer containing data's name
1458        """
1459        self.nodes = []
1460        omfdata = self.sld_data
1461        if omfdata == None:
1462            raise
1463        key_list = self._get_nodes_key_list(omfdata)
1464        is_data = self.sld_data.is_data
1465        sizer = wx.GridBagSizer(2, 3)
1466        ix = 0
1467        iy = -1
1468        for key, value in key_list.iteritems():
1469            iy += 1
1470            ix = 0
1471            name = wx.StaticText(self, -1, key)
1472            sizer.Add(name, (iy, ix), (1, 1), \
1473                            wx.EXPAND | wx.ADJUST_MINSIZE, 0)
1474            ## add parameter value
1475            ix += 1
1476            ctl = InputTextCtrl(self, -1, size=(_BOX_WIDTH, 20),
1477                                style=wx.TE_PROCESS_ENTER)
1478            ctl.Bind(wx.EVT_TEXT, self._onparamEnter )
1479            ctl.SetValue(format_number(value, True))
1480            ctl.Enable(not is_data)
1481            sizer.Add(ctl, (iy, ix), (1, 1), wx.EXPAND)
1482            ## add unit
1483            ix += 1
1484            unit = wx.StaticText(self, -1, '')
1485            sizer.Add(unit, (iy, ix), (1, 1), \
1486                            wx.EXPAND | wx.ADJUST_MINSIZE, 0)
1487            self.nodes.append([key, ctl, unit])
1488        self.node_sizer.Add(sizer, 0, wx.LEFT, 10)
1489           
1490    def _layout_stepsize(self):
1491        """
1492        Fill the sizer containing slit size information
1493        """
1494        self.stepsize = []
1495        omfdata = self.sld_data
1496        if omfdata == None:
1497            raise
1498        key_list = self._get_step_key_list(omfdata)
1499        is_data = self.sld_data.is_data
1500        sizer = wx.GridBagSizer(2, 3)
1501        ix = 0
1502        iy = -1
1503        #key_list.sort()
1504        for key, value in key_list.iteritems():
1505            iy += 1
1506            ix = 0
1507            name = wx.StaticText(self, -1, key)
1508            sizer.Add(name, (iy, ix), (1, 1), \
1509                            wx.EXPAND | wx.ADJUST_MINSIZE, 0)
1510            ## add parameter value
1511            ix += 1
1512            ctl = InputTextCtrl(self, -1, size=(_BOX_WIDTH, 20),
1513                                style=wx.TE_PROCESS_ENTER)
[dbc01f2]1514            ctl.Bind(wx.EVT_TEXT, self._onstepsize )
[318b5bbb]1515            ctl.SetValue(format_number(value, True))
1516            ctl.Enable(not is_data)
1517            sizer.Add(ctl, (iy, ix), (1, 1), wx.EXPAND)
1518            ## add unit
1519            ix += 1
1520            p_unit = '[' + omfdata.pos_unit + ']'
1521            unit = wx.StaticText(self, -1, p_unit)
1522            sizer.Add(unit, (iy, ix), (1, 1), \
1523                            wx.EXPAND | wx.ADJUST_MINSIZE, 0)
1524            self.stepsize.append([key, ctl, unit])
1525        self.step_sizer.Add(sizer, 0, wx.LEFT, 10)
1526   
1527    def _layout_hint(self):
1528        """
1529        Fill the sizer containing hint
1530        """
1531        hint_msg = "Load an omf or 3d sld profile data file."
1532        self.hint_txt = wx.StaticText(self, -1, hint_msg)
1533        self.hint_sizer.AddMany([(self.hint_txt, 0, wx.LEFT, 15)])
1534   
1535    def _layout_button(self): 
1536        """
1537        Do the layout for the button widgets
1538        """ 
1539        self.bt_draw = wx.Button(self, wx.NewId(),'Draw Points')
1540        self.bt_draw.Bind(wx.EVT_BUTTON, self.on_sld_draw)
1541        self.bt_draw.SetToolTipString("Draw a scatter plot for sld profile.")
1542        self.bt_save = wx.Button(self, wx.NewId(),'Save SLD Data')
1543        self.bt_save.Bind(wx.EVT_BUTTON, self.on_save)
1544        self.bt_save.Enable(False)
1545        self.bt_save.SetToolTipString("Save SLD data.")
1546        self.button_sizer.AddMany([(self.bt_draw, 0, wx.LEFT, 10),
1547                                   (self.bt_save, 0, wx.LEFT, 10)])
1548       
1549    def _do_layout(self):
1550        """
[3f5d75b]1551        Draw omf panel content, used to define sld s.
1552       
[318b5bbb]1553        """
1554        self._define_structure()
1555        self._layout_nodes()
1556        self._layout_stepsize()
1557        self._layout_npix()
1558        self._layout_slds()
1559        #self._layout_hint()
1560        self._layout_button()
1561        self.boxsizer_node.AddMany([(self.node_sizer, 0,
1562                                    wx.EXPAND|wx.TOP, 5),
1563                                     (self.hint_sizer, 0,
1564                                     wx.EXPAND|wx.TOP|wx.BOTTOM, 5)])
1565        self.boxsizer_stepsize.AddMany([(self.step_sizer, 0,
1566                                     wx.EXPAND|wx.TOP|wx.BOTTOM, 5),])
1567        self.boxsizer_sld.AddMany([(self.sld_sizer, 0,
1568                                     wx.EXPAND|wx.BOTTOM, 5),])
1569        self.main_sizer.AddMany([(self.npixels_sizer, 0, wx.EXPAND|wx.ALL, 10),
1570                        (self.boxsizer_sld, 0, wx.EXPAND|wx.ALL, 10),
1571                        (self.boxsizer_node, 0, wx.EXPAND|wx.ALL, 10),
1572                        (self.boxsizer_stepsize, 0, wx.EXPAND|wx.ALL, 10),
1573                        (self.button_sizer, 0, wx.EXPAND|wx.TOP|wx.BOTTOM, 5)])
1574        self.SetSizer(self.main_sizer)
1575        self.SetAutoLayout(True)
1576       
1577    def _get_nodes_key_list(self, data):
1578        """
1579        Return nodes key list
1580       
1581        :Param data: OMFData
1582        """
1583        key_list = {'xnodes' : data.xnodes, 
1584                    'ynodes' : data.ynodes,
1585                    'znodes' : data.znodes}
1586        return key_list
1587       
1588    def _get_slds_key_list(self, data):
1589        """
1590        Return nodes key list
1591       
1592        :Param data: OMFData
1593        """
1594        key_list = {'Nucl.' : data.sld_n, 
1595                    'Mx' : data.sld_mx,
1596                    'My' : data.sld_my,
1597                    'Mz' : data.sld_mz}
1598        return key_list
1599
1600    def _get_step_key_list(self, data):
1601        """
1602        Return step key list
1603       
1604        :Param data: OMFData
1605        """
1606        key_list = {'xstepsize' : data.xstepsize, 
1607                    'ystepsize' : data.ystepsize,
1608                    'zstepsize' : data.zstepsize}
1609        return key_list       
1610   
1611    def set_sld_ctr(self, sld_data):
1612        """
[077207b]1613        Set sld textctrls
[318b5bbb]1614        """
1615        if sld_data == None:
1616            for ctr_list in self.slds:
1617                ctr_list[1].Enable(False)
1618                #break   
1619            return
1620       
1621        self.sld_data = sld_data
1622        sld_list = self._get_slds_key_list(sld_data)
1623        for ctr_list in self.slds:
1624            for key in sld_list.keys():
1625                if ctr_list[0] == key:
1626                    min_val = numpy.min(sld_list[key])
1627                    max_val = numpy.max(sld_list[key])
1628                    mean_val = numpy.mean(sld_list[key])
[077207b]1629                    enable = (min_val == max_val) and \
1630                             sld_data.pix_type == 'pixel'
[318b5bbb]1631                    ctr_list[1].SetValue(format_number(mean_val, True))
1632                    ctr_list[1].Enable(enable)
[dbc01f2]1633                    #ctr_list[2].SetLabel("[" + sld_data.sld_unit + "]")
[318b5bbb]1634                    break   
1635
1636    def on_sld_draw(self, event):
1637        """
1638        Draw sld profile as scattered plot
1639        """
1640        self.parent.sld_draw()
1641         
1642    def on_save(self, event):
1643        """
1644        Close the window containing this panel
1645        """
1646        flag = True
1647        flag = self.check_inputs()
1648        if not flag:
1649            return
1650        self.sld_data = self.get_sld_val()
1651        self.parent.set_main_panel_sld_data(self.sld_data)
1652       
[b9a5f0e]1653        reader = sas_gen.SLDReader() 
[318b5bbb]1654        extension = '*.sld'
1655        path = None
1656        data= None
1657        location = self.parent.get_path()
1658        dlg = wx.FileDialog(self, "Save sld file",
1659                            location, "sld_file",
1660                             extension, 
1661                             wx.SAVE)
1662        if dlg.ShowModal() == wx.ID_OK:
1663            path = dlg.GetPath()
1664            self.parent.set_file_location(os.path.dirname(path))
1665        else:
1666            return None
1667        dlg.Destroy()
1668        try:
1669            if path is None:
1670                return
1671           
1672            data = self.parent.get_sld_data()
1673            fName = os.path.splitext(path)[0] + '.' + extension.split('.')[-1]
1674            if data != None:
1675                try:
1676                    reader.write(fName, data)
1677                except:
1678                    raise
1679            else:
1680                msg = "%s cannot write %s\n" % ('Generic Scattering', str(path))
1681                infor = 'Error'
1682                #logging.error(msg)
1683                if self.parent.parent != None:
1684                    # inform msg to wx
1685                    wx.PostEvent(self.parent.parent,
1686                            StatusEvent(status=msg, info=infor))
1687                    self.SetFocus()
1688            return
1689        except:
1690            msg = "Error occurred while saving. "
1691            infor = 'Error'
1692            if self.parent.parent != None:
1693                # inform msg to wx
1694                wx.PostEvent(self.parent.parent,
1695                        StatusEvent(status=msg, info=infor)) 
1696                self.SetFocus()   
1697
1698    def _onparamEnter(self, event):
1699        """
1700        """
1701        flag = True
1702        if event != None:
1703            event.Skip()
1704            ctl = event.GetEventObject()
1705            ctl.SetBackgroundColour("white")
1706            #_set_error(self, ctl)
1707        try:
1708            float(ctl.GetValue())
1709        except:
1710            flag = _set_error(self, ctl)
1711        if flag:
1712            npts = 1
1713            for item in self.nodes:
1714                n_val = float(item[1].GetValue())
1715                if n_val <= 0:
1716                    item[1].SetBackgroundColour("pink")
1717                    npts = -1
1718                    break
[dbc5dc9b]1719                if numpy.isfinite(n_val):
1720                    npts *= int(n_val)
[318b5bbb]1721            if npts > 0:
1722                nop = self.set_npts_from_slddata()
1723                if nop == None:
1724                    nop = npts
1725                self.display_npts(nop)
[afd45674]1726               
[318b5bbb]1727        ctl.Refresh()
1728        return flag
1729   
[afd45674]1730    def _set_volume_ctr_val(self, npts):
1731        """
1732        Set total volume
1733        """
1734        total_volume = npts * self.sld_data.vol_pix[0]
1735        self.parent.set_volume_ctr_val(total_volume)
1736                   
[dbc01f2]1737    def _onstepsize(self, event):
1738        """
1739        On stepsize event
1740        """
1741        flag = True
1742        if event != None:
1743            event.Skip()
1744            ctl = event.GetEventObject()
1745            ctl.SetBackgroundColour("white")
1746
1747        if flag and not self.sld_data.is_data:#ctl.IsEnabled():
1748            s_size = 1.0
1749            try:
1750                for item in self.stepsize:
1751                    s_val = float(item[1].GetValue())
1752                    if s_val <= 0:
1753                        item[1].SetBackgroundColour("pink")
1754                        ctl.Refresh()
1755                        return
1756                    if numpy.isfinite(s_val):
1757                        s_size *= s_val
1758                self.sld_data.set_pixel_volumes(s_size)
[afd45674]1759                if ctl.IsEnabled():
1760                    total_volume = sum(self.sld_data.vol_pix)
1761                    self.parent.set_volume_ctr_val(total_volume)
[dbc01f2]1762            except:
1763                pass
1764        ctl.Refresh()
1765 
1766         
[318b5bbb]1767    def set_npts_from_slddata(self):
1768        """
1769        Set total n. of points form the sld data
1770        """
1771        try:
1772            sld_data = self.parent.get_sld_from_omf()
1773            #nop = (nop * numpy.pi) / 6
1774            nop = len(sld_data.sld_n)
1775        except:
1776            nop = None
1777        return nop
1778   
1779    def display_npts(self, nop):
1780        """
1781        Displays Npts ctrl
1782        """
1783        try:
1784            self.npix_ctl.SetValue(str(nop))
1785            self.npix_ctl.Refresh()
1786            self.parent.set_etime()
[afd45674]1787            wx.CallAfter(self._set_volume_ctr_val, nop)
[318b5bbb]1788        except:
1789            # On Init
1790            pass
1791   
1792    def check_inputs(self):
1793        """
1794        check if the inputs are valid
1795        """
1796        flag = self._check_input_helper(self.slds)
1797        if flag:
1798            flag = self._check_input_helper(self.nodes)
1799        if flag:
1800            flag = self._check_input_helper(self.stepsize)
1801        return flag
1802   
1803    def _check_input_helper(self, list):
1804        """
1805        Check list values
1806        """
1807        flag = True
1808        for item in list:
1809            item[1].SetBackgroundColour("white")
1810            item[1].Refresh()
1811            try:
1812                float(item[1].GetValue())
1813            except:
1814                flag = _set_error(self, item[1])
1815                break
1816        return flag
1817
[d0923a3]1818class SasGenWindow(widget.CHILD_FRAME):
[318b5bbb]1819    """
1820    GEN SAS main window
1821    """
[ae84427]1822    def __init__(self, parent=None, manager= None, title="Generic Scattering Calculator",
[3f5d75b]1823                size=(PANEL_WIDTH * 1.4, PANEL_HEIGHT * 1.65), *args, **kwds):
[318b5bbb]1824        """
1825        Init
1826        """
[cd89c6f]1827        kwds['size'] = size
1828        kwds['title'] = title
[d0923a3]1829        widget.CHILD_FRAME.__init__(self, parent, *args, **kwds)
[318b5bbb]1830        self.parent = parent
[ae84427]1831        self.base = manager
[318b5bbb]1832        self.omfpanel = OmfPanel(parent=self)
1833        self.panel = SasGenPanel(parent=self)
1834        self.data = None
[b9a5f0e]1835        self.omfdata = sas_gen.OMFData()
[318b5bbb]1836        self.sld_data = None
1837        self._default_save_location = os.getcwd() 
[9714ff5]1838       
[318b5bbb]1839        self._mgr = aui.AuiManager(self)
1840        self._mgr.SetDockSizeConstraint(0.5, 0.5)
1841        self._plot_title = ''
1842        self.scale2d = 'log_{10}'
[ae84427]1843        self.Bind(wx.EVT_CLOSE, self.on_close)
[318b5bbb]1844       
1845       
1846        self.build_panels()
[3f5d75b]1847        self.SetPosition((20, 5))
[318b5bbb]1848        self.Show(True)
1849       
1850    def build_panels(self):
1851        """
1852        """
1853       
1854        self.set_sld_data(self.sld_data)
1855        self._mgr.AddPane(self.panel, aui.AuiPaneInfo().
1856                              Name(self.panel.window_name).
1857                              CenterPane().
1858                              # This is where we set the size of
1859                              # the application window
1860                              BestSize(wx.Size(PANEL_WIDTH, 
1861                                               PANEL_HEIGHT)).
1862                              Show()) 
1863        self._mgr.AddPane(self.omfpanel, aui.AuiPaneInfo().
1864                              Name(self.omfpanel.window_name).
1865                              Caption(self.omfpanel.window_caption).
1866                              CloseButton(False).
1867                              Right().
1868                              Floatable(False).
1869                              BestSize(wx.Size(PANEL_WIDTH/2.5, PANEL_HEIGHT)).
1870                              Show()) 
1871        self._mgr.Update()
1872
1873    def get_sld_data(self):
1874        """
1875        Return slddata
1876        """
1877        return self.sld_data
1878   
1879    def get_sld_from_omf(self):
1880        """
1881        """
1882        self.sld_data = self.omfpanel.get_sld_val()
1883        return self.sld_data
1884   
1885    def set_sld_n(self, sld):
1886        """
1887        """
1888        self.panel.sld_data = sld
1889        self.panel.model.set_sld_data(sld)
1890       
1891    def set_sld_data(self, data):
1892        """
1893        Set omfdata
1894        """
1895        if data == None:
1896            return
1897        self.sld_data = data
1898        enable = (not data==None)
1899        self._set_omfpanel_sld_data(self.sld_data)
1900        self.omfpanel.bt_save.Enable(enable)
1901        self.set_etime()
1902   
1903    def set_omfpanel_npts(self):
1904        """
1905        Set Npts in omf panel
1906        """
1907        nop = self.omfpanel.set_npts_from_slddata()
1908        self.omfpanel.display_npts(nop)
1909       
1910    def _set_omfpanel_sld_data(self, data):
1911        """
1912        Set sld_data in omf panel
1913        """
1914        self.omfpanel.set_slddata(data) 
1915        self.omfpanel.set_sld_ctr(data)
1916   
1917    def check_omfpanel_inputs(self):
1918        """
1919        Check OMF panel inputs
1920        """
1921        return self.omfpanel.check_inputs() 
1922       
1923    def set_main_panel_sld_data(self, sld_data):
1924        """
1925        """
1926        self.sld_data = sld_data
1927       
1928    def set_file_location(self, path):
1929        """
1930        File location
1931        """
1932        self._default_save_location = path
1933   
1934    def get_path(self):
1935        """
1936        File location
1937        """
1938        return self._default_save_location
1939   
1940    def draw_graph(self, plot, title=''):
1941        """
1942        """
[62af27a9]1943        try: 
1944            wx.PostEvent(self.parent, NewPlotEvent(plot=plot, title=title))
1945        except:
1946            # standalone
1947            frame = PlotFrame(self, -1, 'testView', self.scale2d)
1948            #add_icon(self.parent, frame)
1949            frame.add_plot(plot)
1950            frame.SetTitle(title)
1951            frame.Show(True)
1952            frame.SetFocus()
1953
[ae84427]1954    def set_schedule_full_draw(self, panel=None, func='del'): 
1955        """
1956        Send full draw to gui frame
1957        """
[62af27a9]1958        if self.parent != None:
1959            self.parent.set_schedule_full_draw(panel, func)
[ae84427]1960       
[318b5bbb]1961    def get_npix(self):
1962        """
1963        Get no. of pixels from omf panel
1964        """
1965        n_pix = self.omfpanel.npix_ctl.GetValue()
1966        return n_pix
1967   
[dbc01f2]1968    def get_pix_volumes(self):
[318b5bbb]1969        """
1970        Get a pixel volume
1971        """
[dbc01f2]1972        vol = self.omfpanel.get_pix_volumes()
[318b5bbb]1973        return vol
1974   
[afd45674]1975    def set_volume_ctr_val(self, val):
1976        """
1977        Set volume txtctl value
1978        """
1979        try:
1980            self.panel.set_volume_ctl_val(str(val))
1981        except:
1982            print "self.panel is not initialized yet"
1983           
[318b5bbb]1984    def set_omfpanel_default_shap(self, shape):
1985        """
1986        Set default_shape in omfpanel
1987        """
1988        self.omfpanel.default_shape = shape
1989   
1990    def set_etime(self):
1991        """
1992        Sets est. computation time on panel
1993        """
1994        self.panel.set_est_time()
1995   
1996    def get_sld_data_from_omf(self):
1997        """
1998        """
1999        data = self.omfpanel.get_sld_val() 
2000        return data
2001       
2002    def set_scale2d(self, scale):
2003        """
2004        """
2005        self.scale2d = scale
2006           
2007    def on_panel_close(self, event):
2008        """
2009        """
2010        #Not implemented
2011         
2012    def on_open_file(self, event):
2013        """
2014        On Open
2015        """
2016        self.panel.on_load_data(event)
2017   
2018    def sld_draw(self):
2019        """
2020        sld draw
2021        """
[1de85f4]2022        self.panel.sld_draw(event=None, has_arrow=False)
[318b5bbb]2023       
2024    def on_save_file(self, event):
2025        """
2026        On Close
2027        """
2028        self.omfpanel.on_save(event)
2029       
2030    def on_close(self, event):
2031        """
2032        Close
2033        """
[ae84427]2034        if self.base != None:
2035            self.base.gen_frame = None
[318b5bbb]2036        self.Destroy()
2037       
[3f5d75b]2038#    def on_help(self, event):   
2039#        """
2040#       Gen scatter angle help panel
2041#        """
2042#        from sas.perspectives.calculator.help_panel import  HelpWindow
2043#        # Get models help model_function path
2044#        import sas.perspectives.calculator as calmedia
2045#
2046#        media = calmedia.get_data_path(media='media')
2047#        path = os.path.join(media,"gen_sas_help.html")
2048#        name = "Generic Scattering Calculator"
2049#        frame = HelpWindow(self, -1,
2050#                           title=' Help: GenSAS', 
2051#                           pageToOpen=path, size=(865, 450))   
2052#        try:
2053#            frame.splitter.DetachWindow(frame.lpanel)
2054#            # Display only the right side one
2055#            frame.lpanel.Hide()
2056#            frame.Show(True)
2057#            add_icon(self.parent, frame)
2058#        except:
2059#            frame.Destroy()
2060#            msg = 'Display Error\n'
2061#            info = "Info"
2062#            wx.MessageBox(msg, info)
[318b5bbb]2063           
2064if __name__ == "__main__": 
2065    app = wx.PySimpleApp()
[62af27a9]2066    widget.CHILD_FRAME = wx.Frame
[cd89c6f]2067    SGframe = SasGenWindow()   
2068    SGframe.Show(True)
[318b5bbb]2069    app.MainLoop()     
Note: See TracBrowser for help on using the repository browser.