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

magnetic_scattrelease-4.2.2ticket-1009ticket-1094-headlessticket-1242-2d-resolutionticket-1243ticket-1249unittest-saveload
Last change on this file since fa412df was 20fa5fe, checked in by Stuart Prescott <stuart@…>, 7 years ago

Fix lots more typos in comments and docs

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