source: sasview/src/sas/sasgui/perspectives/calculator/gen_scatter_panel.py @ 5251ec6

magnetic_scattrelease-4.2.2ticket-1009ticket-1249
Last change on this file since 5251ec6 was 5251ec6, checked in by Paul Kienzle <pkienzle@…>, 8 months ago

improved support for py37 in sasgui

  • Property mode set to 100644
File size: 71.0 KB
Line 
1"""
2Generic Scattering panel.
3This module relies on guiframe manager.
4"""
5from __future__ import print_function
6
7import wx
8import sys
9import os
10import numpy as np
11#import math
12import wx.aui as aui
13#import wx.lib.agw.aui as aui
14import logging
15import time
16
17import matplotlib
18matplotlib.interactive(False)
19#Use the WxAgg back end. The Wx one takes too long to render
20matplotlib.use('WXAgg')
21
22#from sas.sasgui.guiframe.gui_manager import MDIFrame
23from sas.sascalc.data_util.calcthread import CalcThread
24from sas.sasgui.guiframe.local_perspectives.plotting.SimplePlot import PlotFrame
25from sas.sasgui.guiframe.dataFitting import Data2D
26from sas.sasgui.guiframe.dataFitting import Data1D
27from sas.sascalc.dataloader.data_info import Detector
28from sas.sascalc.dataloader.data_info import Source
29from sas.sasgui.guiframe.panel_base import PanelBase
30from sas.sasgui.guiframe.utils import format_number
31from sas.sasgui.guiframe.events import StatusEvent
32from sas.sascalc.calculator import sas_gen
33from sas.sasgui.perspectives.calculator.calculator_widgets import OutputTextCtrl
34from sas.sasgui.perspectives.calculator.calculator_widgets import InputTextCtrl
35from wx.lib.scrolledpanel import ScrolledPanel
36from sas.sasgui.perspectives.calculator.load_thread import GenReader
37from sas.sasgui.plottools.arrow3d import Arrow3D
38from sas.sasgui.perspectives.calculator import calculator_widgets as widget
39from sas.sasgui.guiframe.events import NewPlotEvent
40from sas.sasgui.guiframe.documentation_window import DocumentationWindow
41
42logger = logging.getLogger(__name__)
43
44_BOX_WIDTH = 76
45#Slit length panel size
46if sys.platform.count("win32") > 0:
47    PANEL_TOP = 0
48    PANEL_WIDTH = 570
49    PANEL_HEIGHT = 370
50    FONT_VARIANT = 0
51else:
52    PANEL_TOP = 60
53    PANEL_WIDTH = 620
54    PANEL_HEIGHT = 370
55    FONT_VARIANT = 1
56_QMAX_DEFAULT = 0.3
57_NPTS_DEFAULT = 50
58_Q1D_MIN = 0.001
59
60def add_icon(parent, frame):
61    """
62    Add icon in the frame
63    """
64    if parent is not None:
65        if hasattr(frame, "IsIconized"):
66            if not frame.IsIconized():
67                try:
68                    icon = parent.GetIcon()
69                    frame.SetIcon(icon)
70                except:
71                    pass
72
73def _set_error(panel, item, show_msg=False):
74    """
75    Set_error dialog
76    """
77    if item is not None:
78        item.SetBackgroundColour("pink")
79        item.Refresh()
80    if show_msg:
81        msg = "Error: wrong (or out of range) value entered."
82        if panel.parent.parent is not None:
83            wx.PostEvent(panel.parent.parent,
84                     StatusEvent(status=msg, info='Error'))
85            panel.SetFocus()
86    return False
87
88
89
90class CalcGen(CalcThread):
91    """
92    Computation
93    """
94    def __init__(self,
95                 id= -1,
96                 input=None,
97                 completefn=None,
98                 updatefn=None,
99                 #elapsed = 0,
100                 yieldtime=0.01,
101                 worktime=0.01):
102        """
103        """
104        CalcThread.__init__(self, completefn,
105                 updatefn,
106                 yieldtime,
107                 worktime)
108        self.starttime = 0
109        self.id = id
110        self.input = input
111        self.update_fn = updatefn
112
113    def compute(self):
114        """
115        executing computation
116        """
117        #elapsed = time.time() - self.starttime
118        self.starttime = time.time()
119        self.complete(input=self.input, update=self.update_fn)
120
121class SasGenPanel(ScrolledPanel, PanelBase):
122    """
123        Provides the sas gen calculator GUI.
124    """
125    ## Internal nickname for the window, used by the AUI manager
126    window_name = "Generic SAS Calculator"
127    ## Name to appear on the window title bar
128    window_caption = "Generic SAS "
129
130    def __init__(self, parent, *args, **kwds):
131        ScrolledPanel.__init__(self, parent, style=wx.RAISED_BORDER,
132                               *args, **kwds)
133        #kwds['style'] = wx.SUNKEN_BORDER
134        PanelBase.__init__(self)
135        #Font size
136        self.SetWindowVariant(variant=FONT_VARIANT)
137        self.SetupScrolling()
138        #thread to read data
139        self.reader = None
140        self.ext = None
141        self.id = 'GenSAS'
142        self.file_name = ''
143        self.time_text = None
144        self.orient_combo = None
145        self.omfreader = sas_gen.OMFReader()
146        self.sldreader = sas_gen.SLDReader()
147        self.pdbreader = sas_gen.PDBReader()
148        self.model = sas_gen.GenSAS()
149        self.param_dic = self.model.params
150        self.parameters = []
151        self.data = None
152        self.scale2d = None
153        self.is_avg = False
154        self.plot_frame = None
155        self.qmax_x = _QMAX_DEFAULT
156        self.npts_x = _NPTS_DEFAULT
157        self.sld_data = None
158        self.graph_num = 1
159        self.default_shape = 'rectangular'
160        # Object that receive status event
161        self.parent = parent
162        self._do_layout()
163        self._create_default_sld_data()
164        self._create_default_2d_data()
165        wx.CallAfter(self._set_sld_data_helper)
166
167    def _define_structure(self):
168        """
169            Define the main sizers building to build this application.
170        """
171        self.main_sizer = wx.BoxSizer(wx.VERTICAL)
172        self.box_source = wx.StaticBox(self, -1, str("SLD Data File"))
173        self.box_parameters = wx.StaticBox(self, -1, str("Input Parameters"))
174        self.box_qrange = wx.StaticBox(self, -1, str("Q Range"))
175        self.boxsizer_source = wx.StaticBoxSizer(self.box_source,
176                                                    wx.VERTICAL)
177        self.boxsizer_parameters = wx.StaticBoxSizer(self.box_parameters,
178                                                    wx.VERTICAL)
179        self.boxsizer_qrange = wx.StaticBoxSizer(self.box_qrange,
180                                                    wx.VERTICAL)
181        self.data_name_sizer = wx.BoxSizer(wx.HORIZONTAL)
182        self.param_sizer = wx.BoxSizer(wx.HORIZONTAL)
183        self.shape_sizer = wx.BoxSizer(wx.HORIZONTAL)
184        self.hint_sizer = wx.BoxSizer(wx.HORIZONTAL)
185        self.qrange_sizer = wx.BoxSizer(wx.HORIZONTAL)
186        self.button_sizer = wx.BoxSizer(wx.VERTICAL)
187        self.button_sizer1 = wx.BoxSizer(wx.HORIZONTAL)
188        self.button_sizer2 = wx.BoxSizer(wx.HORIZONTAL)
189
190    def _layout_data_name(self):
191        """
192            Fill the sizer containing data's name
193        """
194        data_name_txt = wx.StaticText(self, -1, 'Data: ')
195        self.data_name_tcl = OutputTextCtrl(self, -1,
196                                            size=(_BOX_WIDTH * 4, -1))
197        data_hint = "Loaded data"
198        self.data_name_tcl.SetToolTipString(data_hint)
199        #control that triggers importing data
200        id = wx.NewId()
201        self.browse_button = wx.Button(self, id, "Load")
202        hint_on_browse = "Click to load data into this panel."
203        self.browse_button.SetToolTipString(hint_on_browse)
204        self.Bind(wx.EVT_BUTTON, self.on_load_data, id=id)
205        self.data_name_sizer.AddMany([(data_name_txt, 0, wx.LEFT, 15),
206                                      (self.data_name_tcl, 0, wx.LEFT, 10),
207                                      (self.browse_button, 0, wx.LEFT, 10)])
208    def _layout_param_size(self):
209        """
210            Fill the sizer containing slit size information
211        """
212        self.parameters = []
213        sizer = wx.GridBagSizer(3, 6)
214        model = self.model
215        details = self.model.details
216        params = self.model.params
217        ix = 0
218        iy = 0
219        param_title = wx.StaticText(self, -1, 'Parameter')
220        sizer.Add(param_title, (iy, ix), (1, 1), \
221                            wx.EXPAND | wx.ADJUST_MINSIZE, 0)
222        ix += 1
223        value_title = wx.StaticText(self, -1, 'Value')
224        sizer.Add(value_title, (iy, ix), (1, 1), \
225                            wx.EXPAND | wx.ADJUST_MINSIZE, 0)
226        ix += 1
227        unit_title = wx.StaticText(self, -1, 'Unit')
228        sizer.Add(unit_title, (iy, ix), (1, 1), \
229                            wx.EXPAND | wx.ADJUST_MINSIZE, 0)
230        for param in sorted(params.keys()):
231            iy += 1
232            ix = 0
233            p_name = wx.StaticText(self, -1, param)
234            sizer.Add(p_name, (iy, ix), (1, 1), \
235                            wx.EXPAND | wx.ADJUST_MINSIZE, 0)
236            ## add parameter value
237            ix += 1
238            value = model.getParam(param)
239            ctl = InputTextCtrl(self, -1, size=(_BOX_WIDTH * 2, 20),
240                                style=wx.TE_PROCESS_ENTER)
241            #ctl.SetToolTipString(\
242            #            "Hit 'Enter' after typing to update the plot.")
243            ctl.SetValue(format_number(value, True))
244            sizer.Add(ctl, (iy, ix), (1, 1), wx.EXPAND)
245            ## add unit
246            ix += 1
247            unit = wx.StaticText(self, -1, details[param][0])
248            sizer.Add(unit, (iy, ix), (1, 1), \
249                            wx.EXPAND | wx.ADJUST_MINSIZE, 0)
250            self.parameters.append([p_name, ctl, unit])
251
252        self.param_sizer.Add(sizer, 0, wx.LEFT, 10)
253
254    def _layout_hint(self):
255        """
256            Fill the sizer containing hint
257        """
258        hint_msg = "We support omf, sld or pdb data files only."
259        hint_msg += "         "
260        if FONT_VARIANT < 1:
261            hint_msg += "Very "
262        hint_msg += "SLOW drawing -->"
263        hint_txt = wx.StaticText(self, -1, hint_msg)
264
265        id = wx.NewId()
266        self.draw_button = wx.Button(self, id, "Arrow Draw")
267        hint_on_draw = "Draw with arrows. Caution: it is a very slow drawing."
268        self.draw_button.SetToolTipString(hint_on_draw)
269        self.draw_button.Bind(wx.EVT_BUTTON, self.sld_draw, id=id)
270
271        self.draw_button.Enable(False)
272        self.hint_sizer.AddMany([(hint_txt, 0, wx.LEFT, 15),
273                                 (self.draw_button, 0, wx.LEFT, 7)])
274
275    def _layout_shape(self):
276        """
277        Fill the shape sizer
278        """
279        label_txt = wx.StaticText(self, -1, "Shape:")
280        self.shape_combo = self._fill_shape_combo()
281        self.shape_sizer.AddMany([(label_txt, 0, wx.LEFT, 15),
282                                (self.shape_combo, 0, wx.LEFT, 5)])
283
284    def _fill_shape_combo(self):
285        """
286        Fill up the shape combo box
287        """
288        shape_combo = wx.ComboBox(self, -1, size=(150, -1),
289                                      style=wx.CB_READONLY)
290        shape_combo.Append('Rectangular')
291        shape_combo.Append('Ellipsoid')
292        shape_combo.Bind(wx.EVT_COMBOBOX, self._on_shape_select)
293        shape_combo.SetSelection(0)
294        return shape_combo
295
296    def _on_shape_select(self, event):
297        """
298        On selecting a shape
299        """
300        event.Skip()
301        label = event.GetEventObject().GetValue().lower()
302        self.default_shape = label
303        self.parent.set_omfpanel_default_shap(self.default_shape)
304        self.parent.set_omfpanel_npts()
305
306    def _fill_orient_combo(self):
307        """
308        Fill up the orientation combo box: used only for atomic structure
309        """
310        orient_combo = wx.ComboBox(self, -1, size=(150, -1),
311                                      style=wx.CB_READONLY)
312        orient_combo.Append('Fixed orientation')
313        orient_combo.Append('Debye full avg.')
314        #orient_combo.Append('Debye sph. sym.')
315
316        orient_combo.Bind(wx.EVT_COMBOBOX, self._on_orient_select)
317        orient_combo.SetSelection(0)
318        return orient_combo
319
320    def _on_orient_select(self, event):
321        """
322        On selecting a orientation
323        """
324        event.Skip()
325        cb = event.GetEventObject()
326        if cb.GetCurrentSelection() == 2:
327            self.is_avg = None
328        else:
329            is_avg = cb.GetCurrentSelection() == 1
330            self.is_avg = is_avg
331        self.model.set_is_avg(self.is_avg)
332        self.set_est_time()
333
334    def _layout_qrange(self):
335        """
336        Fill the sizer containing qrange
337        """
338        sizer = wx.GridBagSizer(2, 3)
339        ix = 0
340        iy = 0
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 is not 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 is 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.FD_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 Exception as exc:
556            self.ext = None
557            if self.parent.parent is None:
558                return
559            msg = "Generic SAS Calculator: %s" % exc
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 is not 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                logger.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 = (np.fabs(sld_mx) + np.fabs(sld_my) + \
744                   np.fabs(sld_mz) + np.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 = np.ones(len(pix_symbol), dtype='bool')
760        for key in color_dic.keys():
761            chosen_color = pix_symbol == key
762            if np.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 np.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]
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(np.fabs(sld_mx))
798                max_my = max(np.fabs(sld_my))
799                max_mz = max(np.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 = np.fabs(unit_x2 * 0.8)
815                        color_y = np.fabs(unit_y2 * 0.8)
816                        color_z = np.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 = np.column_stack((pos_x, x2))
821                        y_arrow = np.column_stack((pos_y, y2))
822                        z_arrow = np.column_stack((pos_z, z2))
823                        colors = np.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 is not 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 is None:
865            if self.parent.parent is not 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 is None:
881                self._create_default_1d_data()
882                i_out = np.zeros(len(self.data.y))
883                inputs = [self.data.x, [], i_out]
884            else:
885                self._create_default_2d_data()
886                i_out = np.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 Exception as exc:
898            msg = "%s." % exc
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 is not 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 is 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 = np.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 is not 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 = np.append(out, outi)
1001            else:
1002                if ind % 50 == 0  and update is not 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 = np.append(out, outi)
1009        #print time.time() - s
1010        if self.is_avg or self.is_avg is 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 #/ np.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 = np.linspace(start=xmin, stop=xmax, num=qstep, endpoint=True)
1051        y = np.linspace(start=ymin, stop=ymax, num=qstep, endpoint=True)
1052        ## use data info instead
1053        new_x = np.tile(x, (len(y), 1))
1054        new_y = np.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 = np.sqrt(qx_data * qx_data + qy_data * qy_data)
1060        # set all True (standing for unmasked) as default
1061        mask = np.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 = np.ones(len(mask))
1067        self.data.err_data = np.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 = np.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 #/ np.sqrt(2)
1094        ## Default values
1095        xmax = qmax
1096        xmin = qmax * _Q1D_MIN
1097        qstep = self.npts_x
1098        x = np.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 = np.ones(len(x))
1102        dy = np.zeros(len(x))
1103        dx = np.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 is not 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        np.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 is not 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] is 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] is 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] is None:
1296                    sld_sets[key] = self.sld_data.sld_mz
1297                mz = sld_sets[key]
1298            else:
1299                if sld_sets[key] is not 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 Exception as exc:
1344            msg = "OMF Panel: %s" % exc
1345            infor = 'Error'
1346            #logger.error(msg)
1347            if self.parent.parent is not 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 is 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 is None:
1438            raise
1439        sld_key_list = self._get_slds_key_list(omfdata)
1440        is_data = self.sld_data.is_data
1441        sizer = wx.GridBagSizer(2, 3)
1442        ix = 0
1443        iy = -1
1444        for key, value in sorted(sld_key_list.items()):
1445            iy += 1
1446            ix = 0
1447            name = wx.StaticText(self, -1, key)
1448            sizer.Add(name, (iy, ix), (1, 1), \
1449                            wx.EXPAND | wx.ADJUST_MINSIZE, 0)
1450            ## add parameter value
1451            ix += 1
1452            ctl = InputTextCtrl(self, -1, size=(_BOX_WIDTH, 20),
1453                                style=wx.TE_PROCESS_ENTER)
1454            ctl.SetValue(format_number(value, True))
1455            ctl.Enable(not is_data)
1456            sizer.Add(ctl, (iy, ix), (1, 1), wx.EXPAND)
1457            ## add unit
1458            ix += 1
1459            s_unit = '[' + omfdata.sld_unit + ']'
1460            unit = wx.StaticText(self, -1, s_unit)
1461            sizer.Add(unit, (iy, ix), (1, 1), \
1462                            wx.EXPAND | wx.ADJUST_MINSIZE, 0)
1463            self.slds.append([key, ctl, unit])
1464        self.sld_sizer.Add(sizer, 0, wx.LEFT, 10)
1465
1466    def _layout_nodes(self):
1467        """
1468        Fill the sizer containing data's name
1469        """
1470        self.nodes = []
1471        omfdata = self.sld_data
1472        if omfdata is None:
1473            raise
1474        key_list = self._get_nodes_key_list(omfdata)
1475        is_data = self.sld_data.is_data
1476        sizer = wx.GridBagSizer(2, 3)
1477        ix = 0
1478        iy = -1
1479        for key, value in sorted(key_list.items()):
1480            iy += 1
1481            ix = 0
1482            name = wx.StaticText(self, -1, key)
1483            sizer.Add(name, (iy, ix), (1, 1), \
1484                            wx.EXPAND | wx.ADJUST_MINSIZE, 0)
1485            ## add parameter value
1486            ix += 1
1487            ctl = InputTextCtrl(self, -1, size=(_BOX_WIDTH, 20),
1488                                style=wx.TE_PROCESS_ENTER)
1489            ctl.Bind(wx.EVT_TEXT, self._onparamEnter)
1490            ctl.SetValue(format_number(value, True))
1491            ctl.Enable(not is_data)
1492            sizer.Add(ctl, (iy, ix), (1, 1), wx.EXPAND)
1493            ## add unit
1494            ix += 1
1495            unit = wx.StaticText(self, -1, '')
1496            sizer.Add(unit, (iy, ix), (1, 1), \
1497                            wx.EXPAND | wx.ADJUST_MINSIZE, 0)
1498            self.nodes.append([key, ctl, unit])
1499        self.node_sizer.Add(sizer, 0, wx.LEFT, 10)
1500
1501    def _layout_stepsize(self):
1502        """
1503        Fill the sizer containing slit size information
1504        """
1505        self.stepsize = []
1506        omfdata = self.sld_data
1507        if omfdata is None:
1508            raise
1509        key_list = self._get_step_key_list(omfdata)
1510        is_data = self.sld_data.is_data
1511        sizer = wx.GridBagSizer(2, 3)
1512        ix = 0
1513        iy = -1
1514        for key, value in sorted(key_list.items()):
1515            iy += 1
1516            ix = 0
1517            name = wx.StaticText(self, -1, key)
1518            sizer.Add(name, (iy, ix), (1, 1), \
1519                            wx.EXPAND | wx.ADJUST_MINSIZE, 0)
1520            ## add parameter value
1521            ix += 1
1522            ctl = InputTextCtrl(self, -1, size=(_BOX_WIDTH, 20),
1523                                style=wx.TE_PROCESS_ENTER)
1524            ctl.Bind(wx.EVT_TEXT, self._onstepsize)
1525            ctl.SetValue(format_number(value, True))
1526            ctl.Enable(not is_data)
1527            sizer.Add(ctl, (iy, ix), (1, 1), wx.EXPAND)
1528            ## add unit
1529            ix += 1
1530            p_unit = '[' + omfdata.pos_unit + ']'
1531            unit = wx.StaticText(self, -1, p_unit)
1532            sizer.Add(unit, (iy, ix), (1, 1), \
1533                            wx.EXPAND | wx.ADJUST_MINSIZE, 0)
1534            self.stepsize.append([key, ctl, unit])
1535        self.step_sizer.Add(sizer, 0, wx.LEFT, 10)
1536
1537    def _layout_hint(self):
1538        """
1539        Fill the sizer containing hint
1540        """
1541        hint_msg = "Load an omf or 3d sld profile data file."
1542        self.hint_txt = wx.StaticText(self, -1, hint_msg)
1543        self.hint_sizer.AddMany([(self.hint_txt, 0, wx.LEFT, 15)])
1544
1545    def _layout_button(self):
1546        """
1547        Do the layout for the button widgets
1548        """
1549        self.bt_draw = wx.Button(self, wx.NewId(), 'Draw Points')
1550        self.bt_draw.Bind(wx.EVT_BUTTON, self.on_sld_draw)
1551        self.bt_draw.SetToolTipString("Draw a scatter plot for sld profile.")
1552        self.bt_save = wx.Button(self, wx.NewId(), 'Save SLD Data')
1553        self.bt_save.Bind(wx.EVT_BUTTON, self.on_save)
1554        self.bt_save.Enable(False)
1555        self.bt_save.SetToolTipString("Save SLD data.")
1556        self.button_sizer.AddMany([(self.bt_draw, 0, wx.LEFT, 10),
1557                                   (self.bt_save, 0, wx.LEFT, 10)])
1558
1559    def _do_layout(self):
1560        """
1561        Draw omf panel content, used to define sld s.
1562
1563        """
1564        self._define_structure()
1565        self._layout_nodes()
1566        self._layout_stepsize()
1567        self._layout_npix()
1568        self._layout_slds()
1569        #self._layout_hint()
1570        self._layout_button()
1571        self.boxsizer_node.AddMany([(self.node_sizer, 0,
1572                                    wx.EXPAND | wx.TOP, 5),
1573                                     (self.hint_sizer, 0,
1574                                     wx.EXPAND | wx.TOP | wx.BOTTOM, 5)])
1575        self.boxsizer_stepsize.AddMany([(self.step_sizer, 0,
1576                                     wx.EXPAND | wx.TOP | wx.BOTTOM, 5), ])
1577        self.boxsizer_sld.AddMany([(self.sld_sizer, 0,
1578                                     wx.EXPAND | wx.BOTTOM, 5), ])
1579        self.main_sizer.AddMany([(self.npixels_sizer, 0, wx.EXPAND | wx.ALL, 10),
1580                        (self.boxsizer_sld, 0, wx.EXPAND | wx.ALL, 10),
1581                        (self.boxsizer_node, 0, wx.EXPAND | wx.ALL, 10),
1582                        (self.boxsizer_stepsize, 0, wx.EXPAND | wx.ALL, 10),
1583                        (self.button_sizer, 0, wx.EXPAND | wx.TOP | wx.BOTTOM, 5)])
1584        self.SetSizer(self.main_sizer)
1585        self.SetAutoLayout(True)
1586
1587    def _get_nodes_key_list(self, data):
1588        """
1589        Return nodes key list
1590
1591        :Param data: OMFData
1592        """
1593        key_list = {'xnodes' : data.xnodes,
1594                    'ynodes' : data.ynodes,
1595                    'znodes' : data.znodes}
1596        return key_list
1597
1598    def _get_slds_key_list(self, data):
1599        """
1600        Return nodes key list
1601
1602        :Param data: OMFData
1603        """
1604        key_list = {'Nucl.' : data.sld_n,
1605                    'Mx' : data.sld_mx,
1606                    'My' : data.sld_my,
1607                    'Mz' : data.sld_mz}
1608        return key_list
1609
1610    def _get_step_key_list(self, data):
1611        """
1612        Return step key list
1613
1614        :Param data: OMFData
1615        """
1616        key_list = {'xstepsize' : data.xstepsize,
1617                    'ystepsize' : data.ystepsize,
1618                    'zstepsize' : data.zstepsize}
1619        return key_list
1620
1621    def set_sld_ctr(self, sld_data):
1622        """
1623        Set sld textctrls
1624        """
1625        if sld_data is None:
1626            for ctr_list in self.slds:
1627                ctr_list[1].Enable(False)
1628                #break   
1629            return
1630
1631        self.sld_data = sld_data
1632        sld_list = self._get_slds_key_list(sld_data)
1633        for ctr_list in self.slds:
1634            for key in sld_list.keys():
1635                if ctr_list[0] == key:
1636                    min_val = np.min(sld_list[key])
1637                    max_val = np.max(sld_list[key])
1638                    mean_val = np.mean(sld_list[key])
1639                    enable = (min_val == max_val) and \
1640                             sld_data.pix_type == 'pixel'
1641                    ctr_list[1].SetValue(format_number(mean_val, True))
1642                    ctr_list[1].Enable(enable)
1643                    #ctr_list[2].SetLabel("[" + sld_data.sld_unit + "]")
1644                    break
1645
1646    def on_sld_draw(self, event):
1647        """
1648        Draw sld profile as scattered plot
1649        """
1650        self.parent.sld_draw()
1651
1652    def on_save(self, event):
1653        """
1654        Close the window containing this panel
1655        """
1656        flag = True
1657        flag = self.check_inputs()
1658        if not flag:
1659            return
1660        self.sld_data = self.get_sld_val()
1661        self.parent.set_main_panel_sld_data(self.sld_data)
1662
1663        reader = sas_gen.SLDReader()
1664        extension = '*.sld'
1665        path = None
1666        data = None
1667        location = self.parent.get_path()
1668        dlg = wx.FileDialog(self, "Save sld file",
1669                            location, "sld_file",
1670                             extension,
1671                             wx.SAVE)
1672        if dlg.ShowModal() == wx.ID_OK:
1673            path = dlg.GetPath()
1674            self.parent.set_file_location(os.path.dirname(path))
1675        else:
1676            return None
1677        dlg.Destroy()
1678        try:
1679            if path is None:
1680                return
1681
1682            data = self.parent.get_sld_data()
1683            fName = os.path.splitext(path)[0] + '.' + extension.split('.')[-1]
1684            if data is not None:
1685                try:
1686                    reader.write(fName, data)
1687                except:
1688                    raise
1689            else:
1690                msg = "%s cannot write %s\n" % ('Generic Scattering', str(path))
1691                infor = 'Error'
1692                #logger.error(msg)
1693                if self.parent.parent is not None:
1694                    # inform msg to wx
1695                    wx.PostEvent(self.parent.parent,
1696                            StatusEvent(status=msg, info=infor))
1697                    self.SetFocus()
1698            return
1699        except:
1700            msg = "Error occurred while saving. "
1701            infor = 'Error'
1702            if self.parent.parent is not None:
1703                # inform msg to wx
1704                wx.PostEvent(self.parent.parent,
1705                        StatusEvent(status=msg, info=infor))
1706                self.SetFocus()
1707
1708    def _onparamEnter(self, event):
1709        """
1710        """
1711        flag = True
1712        if event is not None:
1713            event.Skip()
1714            ctl = event.GetEventObject()
1715            ctl.SetBackgroundColour("white")
1716            #_set_error(self, ctl)
1717        try:
1718            float(ctl.GetValue())
1719        except:
1720            flag = _set_error(self, ctl)
1721        if flag:
1722            npts = 1
1723            for item in self.nodes:
1724                n_val = float(item[1].GetValue())
1725                if n_val <= 0:
1726                    item[1].SetBackgroundColour("pink")
1727                    npts = -1
1728                    break
1729                if np.isfinite(n_val):
1730                    npts *= int(n_val)
1731            if npts > 0:
1732                nop = self.set_npts_from_slddata()
1733                if nop is None:
1734                    nop = npts
1735                self.display_npts(nop)
1736
1737        ctl.Refresh()
1738        return flag
1739
1740    def _set_volume_ctr_val(self, npts):
1741        """
1742        Set total volume
1743        """
1744        total_volume = npts * self.sld_data.vol_pix[0]
1745        self.parent.set_volume_ctr_val(total_volume)
1746
1747    def _onstepsize(self, event):
1748        """
1749        On stepsize event
1750        """
1751        flag = True
1752        if event is not None:
1753            event.Skip()
1754            ctl = event.GetEventObject()
1755            ctl.SetBackgroundColour("white")
1756
1757        if flag and not self.sld_data.is_data:#ctl.IsEnabled():
1758            s_size = 1.0
1759            try:
1760                for item in self.stepsize:
1761                    s_val = float(item[1].GetValue())
1762                    if s_val <= 0:
1763                        item[1].SetBackgroundColour("pink")
1764                        ctl.Refresh()
1765                        return
1766                    if np.isfinite(s_val):
1767                        s_size *= s_val
1768                self.sld_data.set_pixel_volumes(s_size)
1769                if ctl.IsEnabled():
1770                    total_volume = sum(self.sld_data.vol_pix)
1771                    self.parent.set_volume_ctr_val(total_volume)
1772            except:
1773                pass
1774        ctl.Refresh()
1775
1776
1777    def set_npts_from_slddata(self):
1778        """
1779        Set total n. of points form the sld data
1780        """
1781        try:
1782            sld_data = self.parent.get_sld_from_omf()
1783            #nop = (nop * np.pi) / 6
1784            nop = len(sld_data.sld_n)
1785        except:
1786            nop = None
1787        return nop
1788
1789    def display_npts(self, nop):
1790        """
1791        Displays Npts ctrl
1792        """
1793        try:
1794            self.npix_ctl.SetValue(str(nop))
1795            self.npix_ctl.Refresh()
1796            self.parent.set_etime()
1797            wx.CallAfter(self._set_volume_ctr_val, nop)
1798        except:
1799            # On Init
1800            pass
1801
1802    def check_inputs(self):
1803        """
1804        check if the inputs are valid
1805        """
1806        flag = self._check_input_helper(self.slds)
1807        if flag:
1808            flag = self._check_input_helper(self.nodes)
1809        if flag:
1810            flag = self._check_input_helper(self.stepsize)
1811        return flag
1812
1813    def _check_input_helper(self, list):
1814        """
1815        Check list values
1816        """
1817        flag = True
1818        for item in list:
1819            item[1].SetBackgroundColour("white")
1820            item[1].Refresh()
1821            try:
1822                float(item[1].GetValue())
1823            except:
1824                flag = _set_error(self, item[1])
1825                break
1826        return flag
1827
1828class SasGenWindow(widget.CHILD_FRAME):
1829    """
1830    GEN SAS main window
1831    """
1832    def __init__(self, parent=None, manager=None, title="Generic Scattering Calculator",
1833                size=(PANEL_WIDTH * 1.4, PANEL_HEIGHT * 1.65), *args, **kwds):
1834        """
1835        Init
1836        """
1837        kwds['size'] = size
1838        kwds['title'] = title
1839        widget.CHILD_FRAME.__init__(self, parent, *args, **kwds)
1840        self.parent = parent
1841        self.base = manager
1842        self.omfpanel = OmfPanel(parent=self)
1843        self.panel = SasGenPanel(parent=self)
1844        self.data = None
1845        self.omfdata = sas_gen.OMFData()
1846        self.sld_data = None
1847        self._default_save_location = os.getcwd()
1848
1849        self._mgr = aui.AuiManager(self)
1850        self._mgr.SetDockSizeConstraint(0.5, 0.5)
1851        self._plot_title = ''
1852        self.scale2d = 'log_{10}'
1853        self.Bind(wx.EVT_CLOSE, self.on_close)
1854
1855
1856        self.build_panels()
1857        self.SetPosition((wx.LEFT, PANEL_TOP))
1858        self.Show(True)
1859
1860    def build_panels(self):
1861        """
1862        """
1863
1864        self.set_sld_data(self.sld_data)
1865        self._mgr.AddPane(self.panel, aui.AuiPaneInfo().
1866                              Name(self.panel.window_name).
1867                              CenterPane().
1868                              # This is where we set the size of
1869                              # the application window
1870                              BestSize(wx.Size(PANEL_WIDTH,
1871                                               PANEL_HEIGHT)).
1872                              Show())
1873        self._mgr.AddPane(self.omfpanel, aui.AuiPaneInfo().
1874                              Name(self.omfpanel.window_name).
1875                              Caption(self.omfpanel.window_caption).
1876                              CloseButton(False).
1877                              Right().
1878                              Floatable(False).
1879                              BestSize(wx.Size(PANEL_WIDTH / 2.5, PANEL_HEIGHT)).
1880                              Show())
1881        self._mgr.Update()
1882
1883    def get_sld_data(self):
1884        """
1885        Return slddata
1886        """
1887        return self.sld_data
1888
1889    def get_sld_from_omf(self):
1890        """
1891        """
1892        self.sld_data = self.omfpanel.get_sld_val()
1893        return self.sld_data
1894
1895    def set_sld_n(self, sld):
1896        """
1897        """
1898        self.panel.sld_data = sld
1899        self.panel.model.set_sld_data(sld)
1900
1901    def set_sld_data(self, data):
1902        """
1903        Set omfdata
1904        """
1905        if data is None:
1906            return
1907        self.sld_data = data
1908        enable = (data is not None)
1909        self._set_omfpanel_sld_data(self.sld_data)
1910        self.omfpanel.bt_save.Enable(enable)
1911        self.set_etime()
1912
1913    def set_omfpanel_npts(self):
1914        """
1915        Set Npts in omf panel
1916        """
1917        nop = self.omfpanel.set_npts_from_slddata()
1918        self.omfpanel.display_npts(nop)
1919
1920    def _set_omfpanel_sld_data(self, data):
1921        """
1922        Set sld_data in omf panel
1923        """
1924        self.omfpanel.set_slddata(data)
1925        self.omfpanel.set_sld_ctr(data)
1926
1927    def check_omfpanel_inputs(self):
1928        """
1929        Check OMF panel inputs
1930        """
1931        return self.omfpanel.check_inputs()
1932
1933    def set_main_panel_sld_data(self, sld_data):
1934        """
1935        """
1936        self.sld_data = sld_data
1937
1938    def set_file_location(self, path):
1939        """
1940        File location
1941        """
1942        self._default_save_location = path
1943
1944    def get_path(self):
1945        """
1946        File location
1947        """
1948        return self._default_save_location
1949
1950    def draw_graph(self, plot, title=''):
1951        """
1952        """
1953        try:
1954            wx.PostEvent(self.parent, NewPlotEvent(plot=plot, title=title))
1955        except:
1956            # standalone
1957            frame = PlotFrame(self, -1, 'testView', self.scale2d)
1958            #add_icon(self.parent, frame)
1959            frame.add_plot(plot)
1960            frame.SetTitle(title)
1961            frame.Show(True)
1962            frame.SetFocus()
1963
1964    def set_schedule_full_draw(self, panel=None, func='del'):
1965        """
1966        Send full draw to gui frame
1967        """
1968        if self.parent is not None:
1969            self.parent.set_schedule_full_draw(panel, func)
1970
1971    def get_npix(self):
1972        """
1973        Get no. of pixels from omf panel
1974        """
1975        n_pix = self.omfpanel.npix_ctl.GetValue()
1976        return n_pix
1977
1978    def get_pix_volumes(self):
1979        """
1980        Get a pixel volume
1981        """
1982        vol = self.omfpanel.get_pix_volumes()
1983        return vol
1984
1985    def set_volume_ctr_val(self, val):
1986        """
1987        Set volume txtctl value
1988        """
1989        try:
1990            self.panel.set_volume_ctl_val(str(val))
1991        except:
1992            print("self.panel is not initialized yet")
1993
1994    def set_omfpanel_default_shap(self, shape):
1995        """
1996        Set default_shape in omfpanel
1997        """
1998        self.omfpanel.default_shape = shape
1999
2000    def set_etime(self):
2001        """
2002        Sets est. computation time on panel
2003        """
2004        self.panel.set_est_time()
2005
2006    def get_sld_data_from_omf(self):
2007        """
2008        """
2009        data = self.omfpanel.get_sld_val()
2010        return data
2011
2012    def set_scale2d(self, scale):
2013        """
2014        """
2015        self.scale2d = scale
2016
2017    def on_panel_close(self, event):
2018        """
2019        """
2020        #Not implemented
2021
2022    def on_open_file(self, event):
2023        """
2024        On Open
2025        """
2026        self.panel.on_load_data(event)
2027
2028    def sld_draw(self):
2029        """
2030        sld draw
2031        """
2032        self.panel.sld_draw(event=None, has_arrow=False)
2033
2034    def on_save_file(self, event):
2035        """
2036        On Close
2037        """
2038        self.omfpanel.on_save(event)
2039
2040    def on_close(self, event):
2041        """
2042        Close
2043        """
2044        if self.base is not None:
2045            self.base.gen_frame = None
2046        self.Destroy()
2047
2048if __name__ == "__main__":
2049    app = wx.PySimpleApp()
2050    widget.CHILD_FRAME = wx.Frame
2051    SGframe = SasGenWindow()
2052    SGframe.Show(True)
2053    app.MainLoop()
Note: See TracBrowser for help on using the repository browser.