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

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 ba152f1 was ae84427, checked in by Jae Cho <jhjcho@…>, 12 years ago

mdi frames for main applications

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