source: sasview/src/sas/sasgui/perspectives/calculator/gen_scatter_panel.py @ 1b061a31

Last change on this file since 1b061a31 was 0f7c930, checked in by butler, 8 years ago

force resize of panel (self.FitInside?()) when the button sizer expands
due to user action. Also puts buttons in two rows so not usually a
problem anyway now. Fixes #616

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