source: sasview/src/sans/perspectives/calculator/gen_scatter_panel.py @ 18c8c3d

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 18c8c3d was e6d9703, checked in by Mathieu Doucet <doucetm@…>, 11 years ago

Re #212 Fix another tool bar

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