source: sasview/calculatorview/src/sans/perspectives/calculator/gen_scatter_panel.py @ 3e001f9

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 3e001f9 was 3e001f9, checked in by Jae Cho <jhjcho@…>, 11 years ago

Added tools, imageviwer and qrange cursors

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