source: sasview/src/sas/sasgui/perspectives/calculator/gen_scatter_panel.py @ 8dec7e7

ESS_GUIESS_GUI_DocsESS_GUI_batch_fittingESS_GUI_bumps_abstractionESS_GUI_iss1116ESS_GUI_iss879ESS_GUI_iss959ESS_GUI_openclESS_GUI_orderingESS_GUI_sync_sascalccostrafo411magnetic_scattrelease-4.2.2ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249ticket885unittest-saveload
Last change on this file since 8dec7e7 was 7432acb, checked in by andyfaff, 8 years ago

MAINT: search+replace '!= None' by 'is not None'

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