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

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 d16339c was 7a04dbb, checked in by krzywon, 10 years ago

Removed the last vestiges of the SANS references and ran run.py. Tested
loading multiple file types and ran fits, p(r) and inversion. Help
windows loaded properly. Saving and loading projects and analyses acted
the same as before the conversion.

All unit tests run by utest_sasview.py passed.

  • Property mode set to 100644
File size: 77.0 KB
Line 
1"""
2Generic Scattering panel.
3This module relies on guiframe manager.
4"""
5
6import wx
7import sys
8import os
9import numpy
10#import math
11import wx.aui as aui
12#import wx.lib.agw.aui as aui
13import logging
14import time
15
16import matplotlib
17matplotlib.interactive(False)
18#Use the WxAgg back end. The Wx one takes too long to render
19matplotlib.use('WXAgg')
20
21#from sas.guiframe.gui_manager import MDIFrame
22from sas.data_util.calcthread import CalcThread
23from sas.guiframe.local_perspectives.plotting.SimplePlot import PlotFrame
24from sas.guiframe.dataFitting import Data2D
25from sas.guiframe.dataFitting import Data1D
26from sas.dataloader.data_info import Detector
27from sas.dataloader.data_info import Source
28from sas.guiframe.panel_base import PanelBase
29from sas.guiframe.utils import format_number
30from sas.guiframe.events import StatusEvent 
31from sas.calculator import sas_gen
32from sas.perspectives.calculator.calculator_widgets import OutputTextCtrl
33from sas.perspectives.calculator.calculator_widgets import InputTextCtrl
34from wx.lib.scrolledpanel import ScrolledPanel
35from sas.perspectives.calculator.load_thread import GenReader
36from sas.plottools.arrow3d import Arrow3D
37from sas.perspectives.calculator import calculator_widgets as widget
38from sas.guiframe.events import NewPlotEvent   
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 SAS Calculator"
119    ## Name to appear on the window title bar
120    window_caption = "Generic SAS "
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 = 'GenSAS'
136        self.file_name = ''
137        self.time_text = None
138        self.orient_combo = None
139        self.omfreader = sas_gen.OMFReader()
140        self.sldreader = sas_gen.SLDReader()
141        self.pdbreader = sas_gen.PDBReader()
142        self.model = sas_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 = sas_gen.OMFData()
454        omf2sld = sas_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 SAS 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 = sas_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 GenSAS." 
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 SAS 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 = sas_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 = sas_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 = sas_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 = sas_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 = sas_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 sas.perspectives.calculator.help_panel import  HelpWindow
2115        # Get models help model_function path
2116        import sas.perspectives.calculator as calmedia
2117
2118        media = calmedia.get_data_path(media='media')
2119        path = os.path.join(media,"gen_sas_help.html") 
2120        name = "Generic Scattering Calculator"
2121        frame = HelpWindow(self, -1, 
2122                           title=' Help: GenSAS', 
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.