""" FitPanel class contains fields allowing to display results when fitting a model and one data """ import sys import wx import wx.lib.newevent import numpy import copy import math import time from sans.guiframe.events import StatusEvent from sans.guiframe.events import NewPlotEvent from sans.guiframe.dataFitting import check_data_validity from sans.guiframe.utils import format_number from sans.guiframe.utils import check_float (Chi2UpdateEvent, EVT_CHI2_UPDATE) = wx.lib.newevent.NewEvent() _BOX_WIDTH = 76 _DATA_BOX_WIDTH = 300 SMEAR_SIZE_L = 0.00 SMEAR_SIZE_H = 0.00 from basepage import BasicPage from basepage import PageInfoEvent from sans.models.qsmearing import smear_selection class FitPage(BasicPage): """ FitPanel class contains fields allowing to display results when fitting a model and one data :note: For Fit to be performed the user should check at least one parameter on fit Panel window. """ def __init__(self, parent, color='rand'): """ Initialization of the Panel """ BasicPage.__init__(self, parent, color=color) ## draw sizer self._fill_data_sizer() self.is_2D = None self.fit_started = False self.weightbt_string = None self.m_name = None # get smear info from data self._get_smear_info() self._fill_model_sizer( self.sizer1) self._get_defult_custom_smear() self._fill_range_sizer() self._set_smear(self.data) self.Bind(EVT_CHI2_UPDATE, self.on_complete_chisqr) # bind key event self.Bind(wx.EVT_RIGHT_DOWN, self.on_right_down) self._set_bookmark_flag(False) self._set_save_flag(False) self._set_preview_flag(False) self._set_copy_flag(False) self._set_paste_flag(False) self.btFit.SetFocus() self.enable_fit_button() self.fill_data_combobox(data_list=self.data_list) #create a default data for an empty panel self.create_default_data() def enable_fit_button(self): """ Enable fit button if data is valid and model is valid """ flag = check_data_validity(self.data) & (self.model is not None) self.btFit.Enable(flag) def _fill_data_sizer(self): """ fill sizer 0 with data info """ self.data_box_description = wx.StaticBox(self, -1, 'I(q) Data Source') if check_data_validity(self.data): dname_color = wx.BLUE else: dname_color = wx.RED self.data_box_description.SetForegroundColour(dname_color) boxsizer1 = wx.StaticBoxSizer(self.data_box_description, wx.VERTICAL) #---------------------------------------------------------- sizer_data = wx.BoxSizer(wx.HORIZONTAL) self.dataSource = wx.ComboBox(self, -1, style=wx.CB_READONLY) wx.EVT_COMBOBOX(self.dataSource, -1, self.on_select_data) self.dataSource.SetMinSize((_DATA_BOX_WIDTH, -1)) sizer_data.Add(wx.StaticText(self, -1, 'Name : ')) sizer_data.Add(self.dataSource) sizer_data.Add( (0, 5) ) boxsizer1.Add(sizer_data, 0, wx.ALL, 10) self.sizer0.Add(boxsizer1, 0, wx.EXPAND | wx.ALL, 10) self.sizer0.Layout() def enable_datasource(self): """ Enable or disable data source control depending on existing data """ if not self.data_list: self.dataSource.Disable() else: self.dataSource.Enable() def fill_data_combobox(self, data_list): """ Get a list of data and fill the corresponding combobox """ self.dataSource.Clear() self.data_list = data_list self.enable_datasource() if len(data_list) > 0: #find the maximum range covering all data qmin, qmax, npts = self.compute_data_set_range(data_list) self.qmin_data_set = qmin self.qmax_data_set = qmax self.npts_data_set = npts self.qmin.SetValue(str(self.qmin_data_set)) self.qmax.SetValue(str(self.qmax_data_set)) self.qmin.SetBackgroundColour("white") self.qmax.SetBackgroundColour("white") self.qmin_x = self.qmin_data_set self.qmax_x = self.qmax_data_set self.state.qmin = self.qmin_x self.state.qmax = self.qmax_x is_data = False for data in self.data_list: if data is not None: self.dataSource.Append(str(data.name), clientData=data) if not is_data: is_data = check_data_validity(data) self.dataSource.SetSelection(0) self.on_select_data(event=None) def on_select_data(self, event=None): """ """ if event is None and self.dataSource.GetCount() > 0: data = self.dataSource.GetClientData(0) self.set_data(data) elif self.dataSource.GetCount() > 0: pos = self.dataSource.GetSelection() data = self.dataSource.GetClientData(pos) self.set_data(data) def _on_fit_complete(self): """ When fit is complete ,reset the fit button label. """ self.btFit.SetLabel("Fit") def _is_2D(self): """ Check if data_name is Data2D :return: True or False """ if self.data.__class__.__name__ == "Data2D" or \ self.enable2D: return True return False def _on_engine_change(self, name): """ get the current name of the fit engine type and update the panel accordingly """ self.engine_type = str(name) self.state.engine_type = self.engine_type if not self.is_mac: if len(self.parameters) == 0: self.Layout() return self.Layout() self.Refresh() def _fill_range_sizer(self): """ Fill the sizer containing the plotting range add access to npts """ is_2Ddata = False # Check if data is 2D if self.data.__class__.__name__ == "Data2D" or \ self.enable2D: is_2Ddata = True title = "Fitting" #smear messages & titles smear_message_none = "No smearing is selected..." smear_message_dqdata = "The dQ data is being used for smearing..." smear_message_2d = \ "Higher accuracy is very time-expensive. Use it with care..." smear_message_new_ssmear = \ "Please enter only the value of interest to customize smearing..." smear_message_new_psmear = \ "Please enter both; the dQ will be generated by interpolation..." smear_message_2d_x_title = "[1/A]:" smear_message_2d_y_title = "[1/A]:" smear_message_pinhole_min_title = "dQ_low[1/A]:" smear_message_pinhole_max_title = "dQ_high[1/A]:" smear_message_slit_height_title = "Slit height[1/A]:" smear_message_slit_width_title = "Slit width[1/A]:" self._get_smear_info() #Sizers box_description_range = wx.StaticBox(self, -1, str(title)) box_description_range.SetForegroundColour(wx.BLUE) boxsizer_range = wx.StaticBoxSizer(box_description_range, wx.VERTICAL) self.sizer_set_smearer = wx.BoxSizer(wx.VERTICAL) sizer_smearer = wx.BoxSizer(wx.HORIZONTAL) self.sizer_new_smear= wx.BoxSizer(wx.HORIZONTAL) self.sizer_set_masking = wx.BoxSizer(wx.HORIZONTAL) sizer_chi2 = wx.BoxSizer(wx.VERTICAL) smear_set_box= wx.StaticBox(self, -1,'Set Instrumental Smearing') sizer_smearer_box = wx.StaticBoxSizer(smear_set_box, wx.HORIZONTAL) sizer_smearer_box.SetMinSize((_DATA_BOX_WIDTH, 60)) weighting_set_box= wx.StaticBox(self, -1,\ 'Set Weighting by Selecting dI Source') weighting_box = wx.StaticBoxSizer(weighting_set_box, wx.HORIZONTAL) sizer_weighting = wx.BoxSizer(wx.HORIZONTAL) weighting_box.SetMinSize((_DATA_BOX_WIDTH, 40)) #Filling the sizer containing weighting info. self.dI_noweight = wx.RadioButton(self, -1, 'No Weighting', style=wx.RB_GROUP) self.dI_didata = wx.RadioButton(self, -1, 'Use dI Data') self.dI_sqrdata = wx.RadioButton(self, -1, 'Use |sqrt(I Data)|') self.dI_idata = wx.RadioButton(self, -1, 'Use |I Data|') self.Bind(wx.EVT_RADIOBUTTON, self.onWeighting, id=self.dI_noweight.GetId()) self.Bind(wx.EVT_RADIOBUTTON, self.onWeighting, id=self.dI_didata.GetId()) self.Bind(wx.EVT_RADIOBUTTON, self.onWeighting, id=self.dI_sqrdata.GetId()) self.Bind(wx.EVT_RADIOBUTTON, self.onWeighting, id=self.dI_idata.GetId()) self.dI_didata.SetValue(True) # add 4 types of weighting to the sizer sizer_weighting.Add( self.dI_noweight, 0, wx.LEFT, 10) sizer_weighting.Add((14, 10)) sizer_weighting.Add( self.dI_didata) sizer_weighting.Add((14, 10)) sizer_weighting.Add( self.dI_sqrdata) sizer_weighting.Add((14, 10)) sizer_weighting.Add( self.dI_idata) sizer_weighting.Add((10, 10)) self.dI_noweight.Enable(False) self.dI_didata.Enable(False) self.dI_sqrdata.Enable(False) self.dI_idata.Enable(False) weighting_box.Add(sizer_weighting) sizer_fit = wx.GridSizer(2, 4, 2, 6) # combobox for smear2d accuracy selection self.smear_accuracy = wx.ComboBox(self, -1, size=(50, -1), style=wx.CB_READONLY) self._set_accuracy_list() self.smear_accuracy.SetValue(self.smear2d_accuracy) self.smear_accuracy.SetSelection(0) self.smear_accuracy.SetToolTipString(\ "'Higher' uses more Gaussian points for smearing computation.") wx.EVT_COMBOBOX(self.smear_accuracy,-1, self._on_select_accuracy) #Fit button self.btFit = wx.Button(self, wx.NewId(),'Fit', size=(88, 25)) self.default_bt_colour = self.btFit.GetDefaultAttributes() self.btFit.Bind(wx.EVT_BUTTON, self._onFit, id= self.btFit.GetId()) self.btFit.SetToolTipString("Start fitting.") #textcntrl for custom resolution self.smear_pinhole_max = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH-25,20),style=wx.TE_PROCESS_ENTER, text_enter_callback = self.onPinholeSmear) self.smear_pinhole_min = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH-25,20),style=wx.TE_PROCESS_ENTER, text_enter_callback = self.onPinholeSmear) self.smear_slit_height= self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH-25,20),style=wx.TE_PROCESS_ENTER, text_enter_callback = self.onSlitSmear) self.smear_slit_width = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH-25,20),style=wx.TE_PROCESS_ENTER, text_enter_callback = self.onSlitSmear) ## smear self.smear_data_left= BGTextCtrl(self, -1, size=(_BOX_WIDTH-25, 20), style=0) self.smear_data_left.SetValue(str(self.dq_l)) self.smear_data_right = BGTextCtrl(self, -1, size=(_BOX_WIDTH-25, 20), style=0) self.smear_data_right.SetValue(str(self.dq_r)) #set default values for smear self.smear_pinhole_max.SetValue(str(self.dx_max)) self.smear_pinhole_min.SetValue(str(self.dx_min)) self.smear_slit_height.SetValue(str(self.dxl)) self.smear_slit_width.SetValue(str(self.dxw)) #Filling the sizer containing instruments smearing info. self.disable_smearer = wx.RadioButton(self, -1, 'None', style=wx.RB_GROUP) self.enable_smearer = wx.RadioButton(self, -1, 'Use dQ Data') #self.enable_smearer.SetToolTipString( #"Click to use the loaded dQ data for smearing.") self.pinhole_smearer = wx.RadioButton(self, -1, 'Custom Pinhole Smear') #self.pinhole_smearer.SetToolTipString #("Click to input custom resolution for pinhole smearing.") self.slit_smearer = wx.RadioButton(self, -1, 'Custom Slit Smear') #self.slit_smearer.SetToolTipString #("Click to input custom resolution for slit smearing.") self.Bind(wx.EVT_RADIOBUTTON, self.onSmear, id=self.disable_smearer.GetId()) self.Bind(wx.EVT_RADIOBUTTON, self.onSmear, id=self.enable_smearer.GetId()) self.Bind(wx.EVT_RADIOBUTTON, self.onPinholeSmear, id=self.pinhole_smearer.GetId()) self.Bind(wx.EVT_RADIOBUTTON, self.onSlitSmear, id=self.slit_smearer.GetId()) self.disable_smearer.SetValue(True) # add 4 types of smearing to the sizer sizer_smearer.Add( self.disable_smearer, 0, wx.LEFT, 10) sizer_smearer.Add((10, 10)) sizer_smearer.Add( self.enable_smearer) sizer_smearer.Add((10, 10)) sizer_smearer.Add( self.pinhole_smearer ) sizer_smearer.Add((10, 10)) sizer_smearer.Add( self.slit_smearer ) sizer_smearer.Add((10, 10)) # StaticText for chi2, N(for fitting), Npts self.tcChi = BGTextCtrl(self, -1, "-", size=(75, 20), style=0) self.tcChi.SetToolTipString("Chi2/Npts(Fit)") self.Npts_fit = BGTextCtrl(self, -1, "-", size=(75, 20), style=0) self.Npts_fit.SetToolTipString(\ " Npts : number of points selected for fitting") self.Npts_total = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH, 20), style=wx.TE_PROCESS_ENTER, text_enter_callback=self._onQrangeEnter) self.Npts_total.SetValue(format_number(self.npts_x)) self.Npts_total.SetToolTipString(\ " Total Npts : total number of data points") # Update and Draw button self.draw_button = wx.Button(self,wx.NewId(), 'Compute', size=(88,24)) self.draw_button.Bind(wx.EVT_BUTTON, \ self._onDraw,id = self.draw_button.GetId()) self.draw_button.SetToolTipString("Compute and Draw.") box_description_1= wx.StaticText(self, -1, ' Chi2/Npts') box_description_2= wx.StaticText(self, -1, 'Npts(Fit)') box_description_3= wx.StaticText(self, -1, 'Total Npts') box_description_3.SetToolTipString( \ " Total Npts : total number of data points") #box_description_4= wx.StaticText(self, -1,' ') sizer_fit.Add(box_description_1, 0, 0) sizer_fit.Add(box_description_2, 0, 0) sizer_fit.Add(box_description_3, 0, 0) sizer_fit.Add(self.draw_button, 0, 0) sizer_fit.Add(self.tcChi, 0, 0) sizer_fit.Add(self.Npts_fit, 0, 0) sizer_fit.Add(self.Npts_total, 0, 0) sizer_fit.Add(self.btFit, 0, 0) # StaticText for smear #self.tcChi = wx.StaticText(self, -1, "-", style=wx.ALIGN_LEFT) self.smear_description_none = wx.StaticText(self, -1, smear_message_none , style=wx.ALIGN_LEFT) self.smear_description_dqdata = wx.StaticText(self, -1, smear_message_dqdata , style=wx.ALIGN_LEFT) self.smear_description_type = wx.StaticText(self, -1, "Type:" , style=wx.ALIGN_LEFT) self.smear_description_accuracy_type = wx.StaticText(self, -1, "Accuracy:" , style=wx.ALIGN_LEFT) self.smear_description_smear_type = BGTextCtrl(self, -1, size=(57,20), style=0) self.smear_description_smear_type.SetValue(str(self.dq_l)) self.SetBackgroundColour(self.GetParent().GetBackgroundColour()) self.smear_description_2d = wx.StaticText(self, -1, smear_message_2d , style=wx.ALIGN_LEFT) self.smear_message_new_s = wx.StaticText(self, -1, smear_message_new_ssmear, style=wx.ALIGN_LEFT) self.smear_message_new_p = wx.StaticText(self, -1, smear_message_new_psmear , style=wx.ALIGN_LEFT) self.smear_description_2d_x = wx.StaticText(self, -1, smear_message_2d_x_title , style=wx.ALIGN_LEFT) self.smear_description_2d_x.SetToolTipString(\ " dQp(parallel) in q_r direction.") self.smear_description_2d_y = wx.StaticText(self, -1, smear_message_2d_y_title , style=wx.ALIGN_LEFT) self.smear_description_2d_y.SetToolTipString(\ " dQs(perpendicular) in q_phi direction.") self.smear_description_pin_min = wx.StaticText(self, -1, smear_message_pinhole_min_title , style=wx.ALIGN_LEFT) self.smear_description_pin_max = wx.StaticText(self, -1, smear_message_pinhole_max_title , style=wx.ALIGN_LEFT) self.smear_description_slit_height = wx.StaticText(self, -1, smear_message_slit_height_title , style=wx.ALIGN_LEFT) self.smear_description_slit_width = wx.StaticText(self, -1, smear_message_slit_width_title , style=wx.ALIGN_LEFT) #arrange sizers #boxsizer1.Add( self.tcChi ) self.sizer_set_smearer.Add(sizer_smearer ) self.sizer_set_smearer.Add((10,10)) self.sizer_set_smearer.Add( self.smear_description_none, 0, wx.CENTER, 10 ) self.sizer_set_smearer.Add( self.smear_description_dqdata, 0, wx.CENTER, 10 ) self.sizer_set_smearer.Add( self.smear_description_2d, 0, wx.CENTER, 10 ) self.sizer_new_smear.Add( self.smear_description_type, 0, wx.CENTER, 10 ) self.sizer_new_smear.Add( self.smear_description_accuracy_type, 0, wx.CENTER, 10 ) self.sizer_new_smear.Add( self.smear_accuracy ) self.sizer_new_smear.Add( self.smear_description_smear_type, 0, wx.CENTER, 10 ) self.sizer_new_smear.Add((15,-1)) self.sizer_new_smear.Add( self.smear_description_2d_x, 0, wx.CENTER, 10 ) self.sizer_new_smear.Add( self.smear_description_pin_min, 0, wx.CENTER, 10 ) self.sizer_new_smear.Add( self.smear_description_slit_height, 0, wx.CENTER, 10 ) self.sizer_new_smear.Add( self.smear_pinhole_min, 0, wx.CENTER, 10 ) self.sizer_new_smear.Add( self.smear_slit_height, 0, wx.CENTER, 10 ) self.sizer_new_smear.Add( self.smear_data_left, 0, wx.CENTER, 10 ) self.sizer_new_smear.Add((20,-1)) self.sizer_new_smear.Add( self.smear_description_2d_y, 0, wx.CENTER, 10 ) self.sizer_new_smear.Add( self.smear_description_pin_max, 0, wx.CENTER, 10 ) self.sizer_new_smear.Add( self.smear_description_slit_width, 0, wx.CENTER, 10 ) self.sizer_new_smear.Add( self.smear_pinhole_max,0, wx.CENTER, 10 ) self.sizer_new_smear.Add( self.smear_slit_width,0, wx.CENTER, 10 ) self.sizer_new_smear.Add( self.smear_data_right,0, wx.CENTER, 10 ) self.sizer_set_smearer.Add( self.smear_message_new_s,0, wx.CENTER, 10) self.sizer_set_smearer.Add( self.smear_message_new_p,0, wx.CENTER, 10) self.sizer_set_smearer.Add((5,2)) self.sizer_set_smearer.Add( self.sizer_new_smear,0, wx.CENTER, 10 ) # add all to chi2 sizer sizer_smearer_box.Add(self.sizer_set_smearer) sizer_chi2.Add(sizer_smearer_box) sizer_chi2.Add((-1,5)) sizer_chi2.Add(weighting_box) sizer_chi2.Add((-1,5)) # hide all smear messages and textctrl self._hide_all_smear_info() # get smear_selection self.current_smearer= smear_selection( self.data, self.model ) # Show only the relevant smear messages, etc if self.current_smearer == None: if not is_2Ddata: self.smear_description_none.Show(True) self.enable_smearer.Disable() else: self.smear_description_none.Show(True) #self.smear_description_2d.Show(True) #self.pinhole_smearer.Disable() self.slit_smearer.Disable() #self.enable_smearer.Disable() if self.data == None: self.slit_smearer.Disable() self.pinhole_smearer.Disable() self.enable_smearer.Disable() else: self._show_smear_sizer() boxsizer_range.Add(self.sizer_set_masking) #2D data? default is_2Ddata = False #check if it is 2D data if self.data.__class__.__name__ == "Data2D" or \ self.enable2D: is_2Ddata = True self.sizer5.Clear(True) self.qmin = self.ModelTextCtrl(self, -1,size=(_BOX_WIDTH,20), style=wx.TE_PROCESS_ENTER, text_enter_callback = self._onQrangeEnter) self.qmin.SetValue(str(self.qmin_x)) self.qmin.SetToolTipString("Minimun value of Q in linear scale.") self.qmax = self.ModelTextCtrl(self, -1,size=(_BOX_WIDTH,20), style=wx.TE_PROCESS_ENTER, text_enter_callback=self._onQrangeEnter) self.qmax.SetValue(str(self.qmax_x)) self.qmax.SetToolTipString("Maximum value of Q in linear scale.") """ self.theory_npts_tcrtl = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH, 20), style=wx.TE_PROCESS_ENTER, text_enter_callback=self._onQrangeEnter) self.theory_npts_tcrtl.SetValue(format_number(self.npts_x)) self.theory_npts_tcrtl.SetToolTipString("Number of point to plot.") """ id = wx.NewId() self.reset_qrange =wx.Button(self,id,'Reset',size=(77,20)) self.reset_qrange.Bind(wx.EVT_BUTTON, self.on_reset_clicked,id=id) self.reset_qrange.SetToolTipString("Reset Q range to the default values") sizer_horizontal=wx.BoxSizer(wx.HORIZONTAL) sizer= wx.GridSizer(2, 4, 2, 6) self.btEditMask = wx.Button(self,wx.NewId(),'Editor', size=(88,23)) self.btEditMask.Bind(wx.EVT_BUTTON, self._onMask,id= self.btEditMask.GetId()) self.btEditMask.SetToolTipString("Edit Mask.") self.EditMask_title = wx.StaticText(self, -1, ' Masking(2D)') sizer.Add(wx.StaticText(self, -1, ' Q range')) sizer.Add(wx.StaticText(self, -1, ' Min[1/A]')) sizer.Add(wx.StaticText(self, -1, ' Max[1/A]')) sizer.Add(self.EditMask_title) #sizer.Add(wx.StaticText(self, -1, '')) sizer.Add(self.reset_qrange) sizer.Add(self.qmin) sizer.Add(self.qmax) #sizer.Add(self.theory_npts_tcrtl) sizer.Add(self.btEditMask) boxsizer_range.Add(sizer_chi2) boxsizer_range.Add((10,10)) boxsizer_range.Add(sizer) boxsizer_range.Add((10,15)) boxsizer_range.Add(sizer_fit) if is_2Ddata: self.btEditMask.Enable() self.EditMask_title.Enable() else: self.btEditMask.Disable() self.EditMask_title.Disable() ## save state self.save_current_state() self.sizer5.Add(boxsizer_range,0, wx.EXPAND | wx.ALL, 10) self.sizer5.Layout() def _fill_model_sizer(self, sizer): """ fill sizer containing model info """ ##Add model function Details button in fitpanel. ##The following 3 lines are for Mac. Let JHC know before modifying... title = "Model" self.formfactorbox = None self.multifactorbox = None self.mbox_description= wx.StaticBox(self, -1,str(title)) boxsizer1 = wx.StaticBoxSizer(self.mbox_description, wx.VERTICAL) self.mbox_description.SetForegroundColour(wx.RED) id = wx.NewId() self.model_help =wx.Button(self,id,'Details', size=(80,23)) self.model_help.Bind(wx.EVT_BUTTON, self.on_model_help_clicked,id=id) self.model_help.SetToolTipString("Model Function Help") id = wx.NewId() self.model_view = wx.Button(self, id,"Show 2D", size=(80, 23)) self.model_view.Bind(wx.EVT_BUTTON, self._onModel2D, id=id) hint = "toggle view of model from 1D to 2D or 2D to 1D" self.model_view.SetToolTipString(hint) self.shape_rbutton = wx.RadioButton(self, -1, 'Shapes', style=wx.RB_GROUP) self.shape_indep_rbutton = wx.RadioButton(self, -1, "Shape-Independent") self.struct_rbutton = wx.RadioButton(self, -1, "Structure Factor ") self.plugin_rbutton = wx.RadioButton(self, -1, "Customized Models") self.Bind(wx.EVT_RADIOBUTTON, self._show_combox, id= self.shape_rbutton.GetId()) self.Bind(wx.EVT_RADIOBUTTON, self._show_combox, id= self.shape_indep_rbutton.GetId()) self.Bind(wx.EVT_RADIOBUTTON, self._show_combox, id= self.struct_rbutton.GetId()) self.Bind(wx.EVT_RADIOBUTTON, self._show_combox, id= self.plugin_rbutton.GetId()) #MAC needs SetValue self.shape_rbutton.SetValue(True) sizer_radiobutton = wx.GridSizer(2, 3, 5, 5) sizer_radiobutton.Add(self.shape_rbutton) sizer_radiobutton.Add(self.shape_indep_rbutton) #sizer_radiobutton.Add((5, 5)) sizer_radiobutton.Add(self.model_view,1, wx.LEFT, 20) sizer_radiobutton.Add(self.plugin_rbutton) sizer_radiobutton.Add(self.struct_rbutton) #sizer_radiobutton.Add((5, 5)) sizer_radiobutton.Add(self.model_help,1, wx.LEFT, 20) sizer_selection = wx.BoxSizer(wx.HORIZONTAL) mutifactor_selection = wx.BoxSizer(wx.HORIZONTAL) self.text1 = wx.StaticText(self,-1,"" ) self.text2 = wx.StaticText(self,-1,"P(Q)*S(Q)" ) self.mutifactor_text = wx.StaticText( self,-1,"No. of Shells: ") self.mutifactor_text1 = wx.StaticText( self,-1,"" ) self.show_sld_button = wx.Button( self,-1,"Show SLD Profile" ) self.show_sld_button.Bind(wx.EVT_BUTTON,self._on_show_sld) self.formfactorbox = wx.ComboBox(self, -1,style=wx.CB_READONLY) if self.model!= None: self.formfactorbox.SetValue(self.model.name) self.structurebox = wx.ComboBox(self, -1, style=wx.CB_READONLY) self.multifactorbox = wx.ComboBox(self, -1, style=wx.CB_READONLY) self.initialize_combox() wx.EVT_COMBOBOX(self.formfactorbox, -1, self._on_select_model) wx.EVT_COMBOBOX(self.structurebox, -1, self._on_select_model) wx.EVT_COMBOBOX(self.multifactorbox, -1, self._on_select_model) ## check model type to show sizer if self.model !=None: self._set_model_sizer_selection(self.model) sizer_selection.Add(self.text1) sizer_selection.Add((5, 5)) sizer_selection.Add(self.formfactorbox) sizer_selection.Add((5, 5)) sizer_selection.Add(self.text2) sizer_selection.Add((5, 5)) sizer_selection.Add(self.structurebox) mutifactor_selection.Add((10,5)) mutifactor_selection.Add(self.mutifactor_text) mutifactor_selection.Add(self.multifactorbox) mutifactor_selection.Add((5, 5)) mutifactor_selection.Add(self.mutifactor_text1) mutifactor_selection.Add((10, 5)) mutifactor_selection.Add(self.show_sld_button) boxsizer1.Add(sizer_radiobutton) boxsizer1.Add((10, 10)) boxsizer1.Add(sizer_selection) boxsizer1.Add((10, 10)) boxsizer1.Add(mutifactor_selection) self._set_multfactor_combobox() self.multifactorbox.SetSelection(1) self.show_sld_button.Hide() sizer.Add(boxsizer1,0, wx.EXPAND | wx.ALL, 10) sizer.Layout() def _set_sizer_dispersion(self): """ draw sizer with gaussian dispersity parameters """ self.fittable_param=[] self.fixed_param=[] self.orientation_params_disp=[] self.sizer4_4.Clear(True) if self.model==None: ##no model is selected return if not self.enable_disp.GetValue(): ## the user didn't select dispersity display return self._reset_dispersity() ## fill a sizer with the combobox to select dispersion type #sizer_select_dispers = wx.BoxSizer(wx.HORIZONTAL) model_disp = wx.StaticText(self, -1, 'Function') CHECK_STATE = self.cb1.GetValue() import sans.models.dispersion_models self.polydisp= sans.models.dispersion_models.models ix = 0 iy = 0 disp = wx.StaticText(self, -1, ' ') self.sizer4_4.Add(disp,( iy, ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15) ix += 1 values = wx.StaticText(self, -1, 'PD[ratio]') polytext = "Polydispersity (= STD/mean); " polytext += "the standard deviation over the mean value." values.SetToolTipString(polytext) self.sizer4_4.Add(values,( iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0) ix +=2 if self.is_mac: err_text = 'Error' else: err_text = '' self.text_disp_1 = wx.StaticText(self, -1, err_text) self.sizer4_4.Add( self.text_disp_1,(iy, ix),(1,1),\ wx.EXPAND|wx.ADJUST_MINSIZE, 0) ix +=1 self.text_disp_min = wx.StaticText(self, -1, 'Min') self.sizer4_4.Add(self.text_disp_min,(iy, ix),(1,1),\ wx.EXPAND|wx.ADJUST_MINSIZE, 0) ix +=1 self.text_disp_max = wx.StaticText(self, -1, 'Max') self.sizer4_4.Add(self.text_disp_max,(iy, ix),(1,1),\ wx.EXPAND|wx.ADJUST_MINSIZE, 0) ix += 1 npts = wx.StaticText(self, -1, 'Npts') npts.SetToolTipString("Number of sampling points for the numerical\n\ integration over the distribution function.") self.sizer4_4.Add(npts,( iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0) ix += 1 nsigmas = wx.StaticText(self, -1, 'Nsigs') nsigmas.SetToolTipString(" Number of sigmas between which the range\n\ of the distribution function will be used for weighting. \n\ The value '3' covers 99.5% for Gaussian distribution \n\ function. Note: Not recommended to change this value.") self.sizer4_4.Add(nsigmas,( iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0) ix +=1 self.sizer4_4.Add(model_disp,(iy, ix),(1,1),\ wx.EXPAND|wx.ADJUST_MINSIZE, 0) if self.engine_type=="park": self.text_disp_max.Show(True) self.text_disp_min.Show(True) for item in self.model.dispersion.keys(): if not item in self.model.orientation_params: if not self.disp_cb_dict.has_key(item): self.disp_cb_dict[item]= None name0="Distribution of " + item name1=item+".width" name2=item+".npts" name3=item+".nsigmas" if not self.model.details.has_key(name1): self.model.details [name1] = ["",None,None] iy += 1 for p in self.model.dispersion[item].keys(): if p=="width": ix = 0 cb = wx.CheckBox(self, -1, name0, (10, 10)) cb.SetValue(CHECK_STATE) cb.SetToolTipString("Check mark to fit") wx.EVT_CHECKBOX(self, cb.GetId(), self.select_param) self.sizer4_4.Add( cb,( iy, ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 5) ix = 1 value= self.model.getParam(name1) ctl1 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH/1.3,20) ,style=wx.TE_PROCESS_ENTER) ctl1.SetLabel('PD[ratio]') poly_text = "Polydispersity (STD/mean) of %s\n" % item poly_text += "STD: the standard deviation" poly_text += " from the mean value." ctl1.SetToolTipString(poly_text) ctl1.SetValue(str (format_number(value, True))) self.sizer4_4.Add(ctl1, (iy,ix),(1,1),wx.EXPAND) ## text to show error sign ix = 2 text2=wx.StaticText(self, -1, '+/-') self.sizer4_4.Add(text2,(iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0) if not self.is_mac: text2.Hide() ix = 3 ctl2 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH/1.3,20), style=0) self.sizer4_4.Add(ctl2, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0) if not self.is_mac: ctl2.Hide() ix = 4 ctl3 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH/2, 20), style=wx.TE_PROCESS_ENTER, text_enter_callback = self._onparamRangeEnter) self.sizer4_4.Add(ctl3, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0) ix = 5 ctl4 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH/2, 20), style=wx.TE_PROCESS_ENTER, text_enter_callback = self._onparamRangeEnter) self.sizer4_4.Add(ctl4, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0) if self.engine_type=="park": ctl3.Show(True) ctl4.Show(True) elif p=="npts": ix = 6 value= self.model.getParam(name2) Tctl = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH/2.2,20), style=wx.TE_PROCESS_ENTER) Tctl.SetValue(str (format_number(value))) self.sizer4_4.Add(Tctl, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0) self.fixed_param.append([None,name2, Tctl,None,None, None, None,None]) elif p=="nsigmas": ix = 7 value= self.model.getParam(name3) Tct2 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH/2.2,20), style=wx.TE_PROCESS_ENTER) Tct2.SetValue(str (format_number(value))) self.sizer4_4.Add(Tct2, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0) #ix +=1 #self.sizer4_4.Add((20,20), (iy,ix),(1,1), # wx.EXPAND|wx.ADJUST_MINSIZE, 0) self.fixed_param.append([None, name3, Tct2, None, None, None, None, None]) ix = 8 disp_box = wx.ComboBox(self, -1,size=(65,-1), style=wx.CB_READONLY, name = '%s'% name1) for key, value in self.polydisp.iteritems(): name_disp = str(key) disp_box.Append(name_disp,value) disp_box.SetStringSelection("gaussian") wx.EVT_COMBOBOX(disp_box,-1, self._on_disp_func) self.sizer4_4.Add(disp_box,(iy,ix),(1,1), wx.EXPAND) self.fittable_param.append([cb,name1,ctl1,text2, ctl2, ctl3, ctl4, disp_box]) ix =0 iy +=1 self.sizer4_4.Add((20,20),(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15) first_orient = True for item in self.model.dispersion.keys(): if item in self.model.orientation_params: if not self.disp_cb_dict.has_key(item): self.disp_cb_dict[item]= None name0="Distribution of " + item name1=item+".width" name2=item+".npts" name3=item+".nsigmas" if not self.model.details.has_key(name1): self.model.details [name1] = ["",None,None] iy += 1 for p in self.model.dispersion[item].keys(): if p=="width": ix = 0 cb = wx.CheckBox(self, -1, name0, (10, 10)) cb.SetValue(CHECK_STATE) cb.SetToolTipString("Check mark to fit") wx.EVT_CHECKBOX(self, cb.GetId(), self.select_param) self.sizer4_4.Add( cb,( iy, ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 5) if self.data.__class__.__name__ == "Data2D" or \ self.enable2D: cb.Show(True) elif cb.IsShown(): cb.Hide() ix = 1 value= self.model.getParam(name1) ctl1 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH/1.3, 20),style=wx.TE_PROCESS_ENTER) poly_tip = "Absolute Sigma for %s." % item ctl1.SetToolTipString(poly_tip) ctl1.SetValue(str (format_number(value, True))) if self.data.__class__.__name__ == "Data2D" or \ self.enable2D: if first_orient: values.SetLabel('PD[ratio], Sig[deg]') poly_text = "PD(polydispersity for lengths):\n" poly_text += "It should be a value between" poly_text += "0 and 1\n" poly_text += "Sigma for angles: \n" poly_text += "It is the STD (ratio*mean)" poly_text += " of the distribution.\n " values.SetToolTipString(poly_text) first_orient = False ctl1.Show(True) elif ctl1.IsShown(): ctl1.Hide() self.sizer4_4.Add(ctl1, (iy,ix),(1,1),wx.EXPAND) ## text to show error sign ix = 2 text2=wx.StaticText(self, -1, '+/-') self.sizer4_4.Add(text2,(iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0) text2.Hide() ix = 3 ctl2 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH/1.3,20), style=0) self.sizer4_4.Add(ctl2, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0) ctl2.Hide() if self.data.__class__.__name__ == "Data2D" or \ self.enable2D: if self.is_mac: text2.Show(True) ctl2.Show(True) ix = 4 ctl3 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH/2,20), style=wx.TE_PROCESS_ENTER, text_enter_callback = self._onparamRangeEnter) self.sizer4_4.Add(ctl3, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0) ctl3.Hide() ix = 5 ctl4 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH/2,20), style=wx.TE_PROCESS_ENTER, text_enter_callback = self._onparamRangeEnter) self.sizer4_4.Add(ctl4, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0) ctl4.Hide() if self.data.__class__.__name__ == "Data2D" or \ self.enable2D: ctl3.Show(True) ctl4.Show(True) elif p=="npts": ix = 6 value= self.model.getParam(name2) Tctl = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH/2.2, 20), style=wx.TE_PROCESS_ENTER) Tctl.SetValue(str (format_number(value))) if self.data.__class__.__name__ == "Data2D" or \ self.enable2D: Tctl.Show(True) else: Tctl.Hide() self.sizer4_4.Add(Tctl, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0) self.fixed_param.append([None,name2, Tctl,None,None, None, None,None]) self.orientation_params_disp.append([None,name2, Tctl,None,None, None, None,None]) elif p=="nsigmas": ix = 7 value= self.model.getParam(name3) Tct2 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH/2.2,20), style=wx.TE_PROCESS_ENTER) Tct2.SetValue(str (format_number(value))) if self.data.__class__.__name__ == "Data2D" or \ self.enable2D: Tct2.Show(True) else: Tct2.Hide() self.sizer4_4.Add(Tct2, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0) self.fixed_param.append([None,name3, Tct2 ,None,None, None, None,None]) self.orientation_params_disp.append([None,name3, Tct2 ,None,None, None, None,None]) ix = 8 disp_box = wx.ComboBox(self, -1,size=(65,-1), style=wx.CB_READONLY, name = '%s'% name1) for key, value in self.polydisp.iteritems(): name_disp = str(key) disp_box.Append(name_disp,value) disp_box.SetStringSelection("gaussian") wx.EVT_COMBOBOX(disp_box,-1, self._on_disp_func) self.sizer4_4.Add(disp_box,(iy,ix),(1,1), wx.EXPAND) self.fittable_param.append([cb,name1,ctl1,text2, ctl2, ctl3, ctl4, disp_box]) self.orientation_params_disp.append([cb,name1,ctl1, text2, ctl2, ctl3, ctl4, disp_box]) if self.data.__class__.__name__ == "Data2D" or \ self.enable2D: disp_box.Show(True) else: disp_box.Hide() self.state.disp_cb_dict = copy.deepcopy(self.disp_cb_dict) self.state.model = self.model.clone() ## save state into self.state.cb1 = self.cb1.GetValue() self._copy_parameters_state(self.parameters, self.state.parameters) self._copy_parameters_state(self.orientation_params_disp, self.state.orientation_params_disp) self._copy_parameters_state(self.fittable_param, self.state.fittable_param) self._copy_parameters_state(self.fixed_param, self.state.fixed_param) wx.PostEvent(self.parent, StatusEvent(status=\ " Selected Distribution: Gaussian")) #Fill the list of fittable parameters #self.select_all_param(event=None) self.get_all_checked_params() self.Layout() def _onDraw(self, event): """ Update and Draw the model """ if self.model ==None: msg="Please select a Model first..." wx.MessageBox(msg, 'Info') return """ if not self.data.is_data: self.npts_x = self.Npts_total.GetValue() self.Npts_fit.SetValue(self.npts_x) self.create_default_data() """ flag = self._update_paramv_on_fit() wx.CallAfter(self._onparamEnter_helper) if not flag: msg= "The parameters are invalid" wx.PostEvent(self.parent.parent, StatusEvent(status= msg )) return def _onFit(self, event): """ Allow to fit """ if self.fit_started: self._StopFit() if event != None: event.Skip() if len(self.parent._manager.fit_thread_list)>0 and\ self.parent._manager._fit_engine != "park" and\ self._manager.sim_page != None and \ self._manager.sim_page.uid == self.uid: msg = "The FitEnging will be set to 'ParkMC'\n" msg += " to fit with more than one data set..." wx.MessageBox(msg, 'Info') #wx.PostEvent(self._manager.parent, StatusEvent(status=\ # "Fitting: %s"%msg)) if self.data is None: msg = "Please get Data first..." wx.MessageBox(msg, 'Info') wx.PostEvent(self._manager.parent, StatusEvent(status=\ "Fit: %s" % msg)) return if self.model is None: msg = "Please select a Model first..." wx.MessageBox(msg, 'Info') wx.PostEvent(self._manager.parent, StatusEvent(status=\ "Fit: %s"%msg, type="stop")) return if len(self.param_toFit) <= 0: msg= "Select at least one parameter to fit" wx.MessageBox(msg, 'Info') wx.PostEvent(self._manager.parent, StatusEvent(status= msg, type="stop" )) return flag = self._update_paramv_on_fit() if self.batch_on and not self._is_2D(): if not self._validate_Npts_1D(): return if not flag: msg= "Fitting range or parameters are invalid" wx.PostEvent(self.parent.parent, StatusEvent(status= msg, type="stop")) return self.select_param(event =None) #Clear errors if exist from previous fitting #self._clear_Err_on_Fit() # Remove or do not allow fitting on the Q=0 point, especially # when y(q=0)=None at x[0]. self.qmin_x = float(self.qmin.GetValue()) self.qmax_x = float(self.qmax.GetValue()) self._manager._reset_schedule_problem(value=0, uid=self.uid) self._manager.schedule_for_fit(uid=self.uid,value=1) self._manager.set_fit_range(uid=self.uid,qmin=self.qmin_x, qmax=self.qmax_x) #single fit self._manager.onFit(uid=self.uid) self.fit_started = True self.btFit.SetLabel("Stop") def get_weight_flag(self): """ Get flag corresponding to a given weighting dI data. """ button_list = [self.dI_noweight, self.dI_didata, self.dI_sqrdata, self.dI_idata] flag = 1 for item in button_list: if item.GetValue(): if button_list.index(item) == 0: flag = 0 #dy = numpy.ones_like(dy_data) elif button_list.index(item) == 1: flag = 1 #dy = dy_data elif button_list.index(item) == 2: flag = 2 #dy = numpy.sqrt(numpy.abs(data)) elif button_list.index(item) == 3: flag = 3 # dy = numpy.abs(data) break return flag def bind_fit_button(self): """ bind the fit button to either fit handler or stop fit handler """ self.btFit.Unbind(event=wx.EVT_BUTTON, id= self.btFit.GetId()) if self.btFit.GetLabel().lower() == "stop": self.fit_started = True self.btFit.SetForegroundColour('red') self.btFit.Bind(event=wx.EVT_BUTTON, handler=self._StopFit, id=self.btFit.GetId()) elif self.btFit.GetLabel().lower() == "fit": self.fit_started = False self.btFit.SetDefault() self.btFit.SetForegroundColour('black') #self.btFit.SetBackgroundColour(self.default_bt_colour) self.btFit.Bind(event=wx.EVT_BUTTON, handler=self._onFit, id=self.btFit.GetId()) else: msg = "FitPage: fit button has unknown label" raise RuntimeError, msg self._manager._reset_schedule_problem(value=0) def is_fitting(self): if self.fit_started: self._StopFit(event=None) def _StopFit(self, event=None): """ Stop fit """ #time.sleep(0.1) if event != None: event.Skip() #if self.engine_type=="scipy": self._manager.stop_fit(self.uid) self._manager._reset_schedule_problem(value=0) self._on_fit_complete() def rename_model(self): """ find a short name for model """ if self.model is not None: self.model.name = "M" + str(self.index_model) def _on_select_model(self, event=None): """ call back for model selection """ self.Show(False) copy_flag = False is_poly_enabled = None if event != None: if (event.GetEventObject() == self.formfactorbox\ and self.structurebox.GetLabel() != 'None')\ or event.GetEventObject() == self.structurebox\ or event.GetEventObject() == self.multifactorbox: copy_flag = self.get_copy_params() is_poly_enabled = self.enable_disp.GetValue() self._on_select_model_helper() self.set_model_param_sizer(self.model) if self.model is None: self._set_bookmark_flag(False) self._keep.Enable(False) self._set_save_flag(False) self.enable_disp.SetValue(False) self.disable_disp.SetValue(True) try: self.set_dispers_sizer() except: pass #self.btFit.SetFocus() self.state.enable_disp = self.enable_disp.GetValue() self.state.disable_disp = self.disable_disp.GetValue() self.state.pinhole_smearer = self.pinhole_smearer.GetValue() self.state.slit_smearer = self.slit_smearer.GetValue() self.state.structurecombobox = self.structurebox.GetLabel()#.GetCurrentSelection() self.state.formfactorcombobox = self.formfactorbox.GetLabel()#.GetCurrentSelection() self.enable_fit_button() if self.model != None: self.m_name = self.model.name self.state.m_name = self.m_name self.rename_model() self._set_copy_flag(True) self._set_paste_flag(True) if self.data is not None: is_data = check_data_validity(self.data) if is_data: self._set_bookmark_flag(True) self._keep.Enable(True) self._set_save_flag(True) # Reset smearer, model and data if not copy_flag: self.disable_smearer.SetValue(True) self.enable_smearer.SetValue(False) # more disables for 2D self._set_smear_buttons() try: # update smearer sizer #if not self.enable_smearer.GetValue(): # self.disable_smearer.SetValue(True) self.onSmear(None) temp_smear = None if not self.disable_smearer.GetValue(): # Set the smearer environments temp_smear = self.current_smearer except: raise ## error occured on chisqr computation #pass ## event to post model to fit to fitting plugins (ModelEventbox, EVT_MODEL_BOX) = wx.lib.newevent.NewEvent() ## set smearing value whether or not # the data contain the smearing info evt = ModelEventbox(model=self.model, smearer=temp_smear, enable_smearer=not self.disable_smearer.GetValue(), qmin=float(self.qmin_x), uid=self.uid, caption=self.window_caption, qmax=float(self.qmax_x)) self._manager._on_model_panel(evt=evt) self.mbox_description.SetLabel("Model [ %s ]" % str(self.model.name)) self.mbox_description.SetForegroundColour(wx.BLUE) self.state.model = self.model.clone() self.state.model.name = self.model.name if event != None: ## post state to fit panel new_event = PageInfoEvent(page = self) wx.PostEvent(self.parent, new_event) #update list of plugins if new plugin is available if self.plugin_rbutton.GetValue(): temp = self.parent.update_model_list() if temp: self.model_list_box = temp current_val = self.formfactorbox.GetLabel() pos = self.formfactorbox.GetSelection() self._show_combox_helper() self.formfactorbox.SetSelection(pos) self.formfactorbox.SetValue(current_val) # when select a model only from guictr/button if is_poly_enabled != None: self.enable_disp.SetValue(is_poly_enabled) self.disable_disp.SetValue(not is_poly_enabled) self._set_dipers_Param(event=None) self.state.enable_disp = self.enable_disp.GetValue() self.state.disable_disp = self.disable_disp.GetValue() # Keep the previous param values if copy_flag: self.get_paste_params(copy_flag) wx.CallAfter(self._onDraw, None) else: self._draw_model() if self.batch_on: self.slit_smearer.Enable(False) self.pinhole_smearer.Enable(False) self.btEditMask.Disable() self.EditMask_title.Disable() self.Show(True) self.SetupScrolling() def _onparamEnter(self,event): """ when enter value on panel redraw model according to changed """ if self.model ==None: msg="Please select a Model first..." wx.MessageBox(msg, 'Info') #wx.PostEvent(self._manager.parent, StatusEvent(status=\ # "Parameters: %s"%msg)) return #default flag flag = False self.fitrange = True #get event object tcrtl = event.GetEventObject() #wx.PostEvent(self._manager.parent, StatusEvent(status=" \ # updating ... ",type="update")) #Clear msg if previously shown. msg= "" wx.PostEvent(self.parent.parent, StatusEvent(status = msg )) if check_float(tcrtl): flag = self._onparamEnter_helper() self.set_npts2fit() if self.fitrange: temp_smearer = None if not self.disable_smearer.GetValue(): temp_smearer= self.current_smearer ## set smearing value whether or not # the data contain the smearing info if self.slit_smearer.GetValue(): flag1 = self.update_slit_smear() flag = flag or flag1 elif self.pinhole_smearer.GetValue(): flag1 = self.update_pinhole_smear() flag = flag or flag1 elif self.data.__class__.__name__ != "Data2D" and \ not self.enable2D: self._manager.set_smearer(smearer=temp_smearer, fid=self.data.id, uid=self.uid, qmin= float(self.qmin_x), qmax= float(self.qmax_x), enable_smearer=not self.disable_smearer.GetValue(), draw=True) if flag: #self.compute_chisqr(smearer= temp_smearer) ## new state posted if self.state_change: #self._undo.Enable(True) event = PageInfoEvent(page = self) wx.PostEvent(self.parent, event) self.state_change= False else: # invalid fit range: do nothing here: # msg already displayed in validate return else: self.save_current_state() msg= "Cannot Plot :Must enter a number!!! " wx.PostEvent(self.parent.parent, StatusEvent(status = msg )) self.save_current_state() return def _onparamRangeEnter(self, event): """ Check validity of value enter in the parameters range field """ #if self.check_invalid_panel(): # return tcrtl= event.GetEventObject() #Clear msg if previously shown. msg= "" wx.PostEvent(self.parent.parent, StatusEvent(status = msg )) # Flag to register when a parameter has changed. is_modified = False if tcrtl.GetValue().lstrip().rstrip()!="": try: value = float(tcrtl.GetValue()) tcrtl.SetBackgroundColour(wx.WHITE) self._check_value_enter(self.fittable_param ,is_modified) self._check_value_enter(self.parameters ,is_modified) except: tcrtl.SetBackgroundColour("pink") msg= "Model Error:wrong value entered : %s"% sys.exc_value wx.PostEvent(self.parent.parent, StatusEvent(status = msg )) return else: tcrtl.SetBackgroundColour(wx.WHITE) #self._undo.Enable(True) self.save_current_state() event = PageInfoEvent(page = self) wx.PostEvent(self.parent, event) self.state_change= False def _onQrangeEnter(self, event): """ Check validity of value enter in the Q range field """ tcrtl = event.GetEventObject() #Clear msg if previously shown. msg= "" wx.PostEvent(self.parent.parent, StatusEvent(status = msg )) # For theory mode if not self.data.is_data: self.npts_x = self.Npts_total.GetValue() self.Npts_fit.SetValue(self.npts_x) self.create_default_data() # Flag to register when a parameter has changed. is_modified = False if tcrtl.GetValue().lstrip().rstrip()!="": try: value = float(tcrtl.GetValue()) tcrtl.SetBackgroundColour(wx.WHITE) # If qmin and qmax have been modified, update qmin and qmax if self._validate_qrange( self.qmin, self.qmax): tempmin = float(self.qmin.GetValue()) if tempmin != self.qmin_x: self.qmin_x = tempmin tempmax = float(self.qmax.GetValue()) if tempmax != self.qmax_x: self.qmax_x = tempmax else: tcrtl.SetBackgroundColour("pink") msg= "Model Error:wrong value entered : %s"% sys.exc_value wx.PostEvent(self.parent.parent, StatusEvent(status = msg )) return except: tcrtl.SetBackgroundColour("pink") msg= "Model Error:wrong value entered : %s"% sys.exc_value wx.PostEvent(self.parent.parent, StatusEvent(status = msg )) return #Check if # of points for theory model are valid(>0). # check for 2d if self.data.__class__.__name__ == "Data2D" or \ self.enable2D: # set mask radius= numpy.sqrt(self.data.qx_data*self.data.qx_data + self.data.qy_data*self.data.qy_data ) index_data = ((self.qmin_x <= radius)& \ (radius<= self.qmax_x)) index_data = (index_data)&(self.data.mask) index_data = (index_data)&(numpy.isfinite(self.data.data)) if len(index_data[index_data]) < 10: msg = "Cannot Plot :No or too little npts in" msg += " that data range!!! " wx.PostEvent(self.parent.parent, StatusEvent(status=msg)) return else: #self.data.mask = index_data #self.Npts_fit.SetValue(str(len(self.data.mask))) self.set_npts2fit() else: index_data = ((self.qmin_x <= self.data.x)& \ (self.data.x <= self.qmax_x)) self.Npts_fit.SetValue(str(len(self.data.x[index_data]))) self.npts_x = self.Npts_total.GetValue() self.create_default_data() self._save_plotting_range() else: tcrtl.SetBackgroundColour("pink") msg= "Model Error:wrong value entered!!!" wx.PostEvent(self.parent.parent, StatusEvent(status = msg )) self._draw_model() self.save_current_state() event = PageInfoEvent(page = self) wx.PostEvent(self.parent, event) self.state_change= False return def _clear_Err_on_Fit(self): """ hide the error text control shown after fitting """ if self.is_mac: return if hasattr(self,"text2_3"): self.text2_3.Hide() if len(self.parameters)>0: for item in self.parameters: #Skip t ifhe angle parameters if 1D data if self.data.__class__.__name__ != "Data2D" and \ not self.enable2D: if item in self.orientation_params: continue if item in self.param_toFit: continue ## hide statictext +/- if len(item) < 4 : continue if item[3]!=None and item[3].IsShown(): item[3].Hide() ## hide textcrtl for error after fit if item[4]!=None and item[4].IsShown(): item[4].Hide() if len(self.fittable_param)>0: for item in self.fittable_param: #Skip t ifhe angle parameters if 1D data if self.data.__class__.__name__ != "Data2D" and \ not self.enable2D: if item in self.orientation_params: continue if item in self.param_toFit: continue if len(item) < 4 : continue ## hide statictext +/- if item[3]!=None and item[3].IsShown(): item[3].Hide() ## hide textcrtl for error after fit if item[4]!=None and item[4].IsShown(): item[4].Hide() return def _get_defult_custom_smear(self): """ Get the defult values for custum smearing. """ # get the default values if self.dxl == None: self.dxl = 0.0 if self.dxw == None: self.dxw = "" if self.dx_min == None: self.dx_min = SMEAR_SIZE_L if self.dx_max == None: self.dx_max = SMEAR_SIZE_H def _get_smear_info(self): """ Get the smear info from data. :return: self.smear_type, self.dq_l and self.dq_r, respectively the type of the smear, dq_min and dq_max for pinhole smear data while dxl and dxw for slit smear """ # default self.smear_type = None self.dq_l = None self.dq_r = None data = self.data if self.data is None: return elif self.data.__class__.__name__ == "Data2D" or \ self.enable2D: if data.dqx_data == None or data.dqy_data ==None: return elif self.current_smearer != None and (data.dqx_data.any()!=0) and \ (data.dqx_data.any()!=0): self.smear_type = "Pinhole2d" self.dq_l = format_number(numpy.average(data.dqx_data)) self.dq_r = format_number(numpy.average(data.dqy_data)) return else: return # check if it is pinhole smear and get min max if it is. if data.dx != None and all(data.dx !=0): self.smear_type = "Pinhole" self.dq_l = data.dx[0] self.dq_r = data.dx[-1] # check if it is slit smear and get min max if it is. elif data.dxl != None or data.dxw != None: self.smear_type = "Slit" if data.dxl != None and all(data.dxl !=0): self.dq_l = data.dxl[0] if data.dxw != None and all(data.dxw !=0): self.dq_r = data.dxw[0] #return self.smear_type,self.dq_l,self.dq_r def _show_smear_sizer(self): """ Show only the sizers depending on smear selection """ # smear disabled if self.disable_smearer.GetValue(): self.smear_description_none.Show(True) # 2Dsmear elif self._is_2D(): self.smear_description_accuracy_type.Show(True) self.smear_accuracy.Show(True) self.smear_description_accuracy_type.Show(True) self.smear_description_2d.Show(True) self.smear_description_2d_x.Show(True) self.smear_description_2d_y.Show(True) if self.pinhole_smearer.GetValue(): self.smear_pinhole_min.Show(True) self.smear_pinhole_max.Show(True) # smear from data elif self.enable_smearer.GetValue(): self.smear_description_dqdata.Show(True) if self.smear_type != None: self.smear_description_smear_type.Show(True) if self.smear_type == 'Slit': self.smear_description_slit_height.Show(True) self.smear_description_slit_width.Show(True) elif self.smear_type == 'Pinhole': self.smear_description_pin_min.Show(True) self.smear_description_pin_max.Show(True) self.smear_description_smear_type.Show(True) self.smear_description_type.Show(True) self.smear_data_left.Show(True) self.smear_data_right.Show(True) # custom pinhole smear elif self.pinhole_smearer.GetValue(): if self.smear_type == 'Pinhole': self.smear_message_new_p.Show(True) self.smear_description_pin_min.Show(True) self.smear_description_pin_max.Show(True) self.smear_pinhole_min.Show(True) self.smear_pinhole_max.Show(True) # custom slit smear elif self.slit_smearer.GetValue(): self.smear_message_new_s.Show(True) self.smear_description_slit_height.Show(True) self.smear_slit_height.Show(True) self.smear_description_slit_width.Show(True) self.smear_slit_width.Show(True) def _hide_all_smear_info(self): """ Hide all smearing messages in the set_smearer sizer """ self.smear_description_none.Hide() self.smear_description_dqdata.Hide() self.smear_description_type.Hide() self.smear_description_smear_type.Hide() self.smear_description_accuracy_type.Hide() self.smear_description_2d_x.Hide() self.smear_description_2d_y.Hide() self.smear_description_2d.Hide() self.smear_accuracy.Hide() self.smear_data_left.Hide() self.smear_data_right.Hide() self.smear_description_pin_min.Hide() self.smear_pinhole_min.Hide() self.smear_description_pin_max.Hide() self.smear_pinhole_max.Hide() self.smear_description_slit_height.Hide() self.smear_slit_height.Hide() self.smear_description_slit_width.Hide() self.smear_slit_width.Hide() self.smear_message_new_p.Hide() self.smear_message_new_s.Hide() def _set_accuracy_list(self): """ Set the list of an accuracy in 2D custum smear: Xhigh, High, Med, or Low """ # list of accuracy choices list = ['Low','Med','High','Xhigh'] for idx in range(len(list)): self.smear_accuracy.Append(list[idx],idx) def _set_fun_box_list(self,fun_box): """ Set the list of func for multifunctional models """ # Check if it is multi_functional model if self.model.__class__ not in self.model_list_box["Multi-Functions"] \ and not self.temp_multi_functional: return None # Get the func name list list = self.model.fun_list if len(list) == 0: return None # build function (combo)box ind = 0 while(ind < len(list)): for key, val in list.iteritems(): if (val == ind): fun_box.Append(key,val) break ind += 1 def _on_select_accuracy(self,event): """ Select an accuracy in 2D custom smear: Xhigh, High, Med, or Low """ #event.Skip() # Check if the accuracy is same as before #self.smear2d_accuracy = event.GetEventObject().GetValue() self.smear2d_accuracy = self.smear_accuracy.GetValue() if self.pinhole_smearer.GetValue(): self.onPinholeSmear(event=None) else: self.onSmear(event=None) if self.current_smearer != None: self.current_smearer.set_accuracy(accuracy = self.smear2d_accuracy) event.Skip() def _on_fun_box(self,event): """ Select an func: Erf,Rparabola,LParabola """ fun_val = None fun_box = event.GetEventObject() name = fun_box.Name value = fun_box.GetValue() if self.model.fun_list.has_key(value): fun_val = self.model.fun_list[value] self.model.setParam(name,fun_val) # save state self._copy_parameters_state(self.str_parameters, self.state.str_parameters) # update params self._update_paramv_on_fit() # draw self._draw_model() self.Refresh() # get ready for new event event.Skip() def _onMask(self, event): """ Build a panel to allow to edit Mask """ from sans.guiframe.local_perspectives.plotting.masking \ import MaskPanel as MaskDialog self.panel = MaskDialog(base=self, data=self.data, id=wx.NewId()) #self.panel.Bind(wx.EVT_CLOSE, self._draw_masked_model) self.panel.ShowModal() #wx.PostEvent(self.parent, event) def _draw_masked_model(self, event): """ Draw model image w/mask """ #event.Skip() is_valid_qrange = self._update_paramv_on_fit() if is_valid_qrange and self.model != None: #self.panel.Show(0) #self.panel.Destroy() # frame self.panel.MakeModal(False) event.Skip() # try re draw the model plot if it exists self._draw_model() self.set_npts2fit() elif self.model == None: #self.panel.Show(0) #self.panel.Destroy() # frame self.panel.MakeModal(False) event.Skip() self.set_npts2fit() msg= "No model is found on updating MASK in the model plot... " wx.PostEvent(self.parent.parent, StatusEvent(status = msg )) else: event.Skip() msg = ' Please consider your Q range, too.' self.panel.ShowMessage(msg) def _set_smear(self, data): """ """ if data is None: return self.current_smearer = smear_selection(data, self.model) flag = self.disable_smearer.GetValue() self.disable_smearer.SetValue(flag) if self.current_smearer == None: self.enable_smearer.Disable() else: self.enable_smearer.Enable() if not flag: self.onSmear(None) def _mac_sleep(self, sec=0.2): """ Give sleep to MAC """ if self.is_mac: time.sleep(sec) def get_view_mode(self): """ return True if the panel allow 2D or False if 1D """ return self.enable2D def compute_data_set_range(self, data_list): """ find the range that include all data in the set return the minimum and the maximum values """ if data_list is not None and data_list != []: for data in data_list: qmin, qmax, npts = self.compute_data_range(data) self.qmin_data_set = min(self.qmin_data_set, qmin) self.qmax_data_set = max(self.qmax_data_set, qmax) self.npts_data_set += npts return self.qmin_data_set, self.qmax_data_set, self.npts_data_set def compute_data_range(self, data): """ compute the minimum and the maximum range of the data return the npts contains in data :param data: """ qmin, qmax, npts = None, None, None if data is not None: if not hasattr(data,"data"): qmin = min(data.x) # Maximum value of data qmax = max(data.x) npts = len(data.x) else: qmin = 0 x = max(math.fabs(data.xmin), math.fabs(data.xmax)) y = max(math.fabs(data.ymin), math.fabs(data.ymax)) ## Maximum value of data qmax = math.sqrt(x*x + y*y) npts = len(data.data) return qmin, qmax, npts def set_data(self, data): """ reset the current data """ from sans.guiframe.dataFitting import check_data_validity id = None flag = False is_data = False if self.data is not None: is_data = check_data_validity(self.data) if not is_data and data is not None: flag = True if data is not None: id = data.id if is_data: self.graph_id = self.data.group_id flag = (data.id != self.data.id) self.data = data if check_data_validity(data): self.graph_id = data.group_id self.data.group_id = self.graph_id if self.data is None: data_name = "" self._set_bookmark_flag(False) self._keep.Enable(False) self._set_save_flag(False) else: if self.model != None: self._set_bookmark_flag(True) self._keep.Enable(True) self._set_save_flag(True) self._set_preview_flag(True) self._set_smear(data) # more disables for 2D if self.data.__class__.__name__ == "Data2D" or \ self.enable2D: self.slit_smearer.Disable() self.pinhole_smearer.Enable(True) self.default_mask = copy.deepcopy(self.data.mask) if self.data.err_data == None or\ (self.data.err_data == 1).all() or\ (self.data.err_data == 0).all(): self.dI_didata.Enable(False) self.dI_noweight.SetValue(True) self.weightbt_string = self.dI_noweight.GetLabelText() else: self.dI_didata.Enable(True) self.dI_didata.SetValue(True) self.weightbt_string = self.dI_didata.GetLabelText() else: self.slit_smearer.Enable(True) self.pinhole_smearer.Enable(True) if self.data.dy == None or\ (self.data.dy == 1).all() or\ (self.data.dy == 0).all(): self.dI_didata.Enable(False) self.dI_noweight.SetValue(True) self.weightbt_string = self.dI_noweight.GetLabelText() else: self.dI_didata.Enable(True) self.dI_didata.SetValue(True) self.weightbt_string = self.dI_didata.GetLabelText() # Enable weighting radio uttons self.dI_noweight.Enable(True) self.dI_sqrdata.Enable(True) self.dI_idata.Enable(True) self.formfactorbox.Enable() self.structurebox.Enable() data_name = self.data.name _, _, npts = self.compute_data_range(self.data) #set maximum range for x in linear scale if not hasattr(self.data, "data"): #Display only for 1D data fit self.btEditMask.Disable() self.EditMask_title.Disable() else: self.btEditMask.Enable() self.EditMask_title.Enable() self.Npts_total.SetValue(str(npts)) #default:number of data points selected to fit self.Npts_fit.SetValue(str(npts)) self.Npts_total.SetEditable(False) self.Npts_total.SetBackgroundColour(\ self.GetParent().GetBackgroundColour()) self.Npts_total.Bind(wx.EVT_MOUSE_EVENTS, self._npts_click) self.dataSource.SetValue(data_name) self.state.data = data self.enable_fit_button() # send graph_id to page_finder self._manager.set_graph_id(uid=self.uid, graph_id=self.graph_id) #focus the page if check_data_validity(data): self.data_box_description.SetForegroundColour(wx.BLUE) if self.batch_on: self.slit_smearer.Enable(False) self.pinhole_smearer.Enable(False) self.btEditMask.Disable() self.EditMask_title.Disable() self.on_set_focus(None) self.Refresh() #update model plot with new data information if flag: #set model view button if not self.enable_smearer.GetValue(): self.disable_smearer.SetValue(True) self.onSmear(None) #self._set_smear(self.data) if self.data.__class__.__name__ == "Data2D": self.enable2D = True self.model_view.SetLabel("2D Mode") else: self.enable2D = False self.model_view.SetLabel("1D Mode") self.model_view.Disable() #replace data plot on combo box selection #by removing the previous selected data wx.PostEvent(self._manager.parent, NewPlotEvent(action="remove", group_id=self.graph_id, id=id)) #plot the current selected data wx.PostEvent(self._manager.parent, NewPlotEvent(plot=self.data, title=str(self.data.title))) #self._manager.store_data(uid=self.uid, data_list=self.data_list, # caption=self.window_name) self._draw_model() def _npts_click(self, event): """ Prevent further handling of the mouse event on Npts_total by not calling Skip(). """ pass def reset_page(self, state,first=False): """ reset the state """ self.reset_page_helper(state) self.select_param(event = None) #Save state_fit self.save_current_state_fit() self._lay_out() self.Refresh() def get_range(self): """ return the fitting range """ return float(self.qmin_x) , float(self.qmax_x) def get_npts2fit(self): """ return numbers of data points within qrange :Note: This is for Park where chi2 is not normalized by Npts of fit """ if self.data is None: return npts2fit = 0 qmin,qmax = self.get_range() if self.data.__class__.__name__ == "Data2D" or \ self.enable2D: radius= numpy.sqrt( self.data.qx_data*self.data.qx_data + self.data.qy_data*self.data.qy_data ) index_data = (self.qmin_x <= radius)&(radius<= self.qmax_x) index_data= (index_data)&(self.data.mask) index_data = (index_data)&(numpy.isfinite(self.data.data)) npts2fit = len(self.data.data[index_data]) else: for qx in self.data.x: if qx >= qmin and qx <= qmax: npts2fit += 1 return npts2fit def set_npts2fit(self): """ setValue Npts for fitting """ self.Npts_fit.SetValue(str(self.get_npts2fit())) def get_chi2(self): """ return the current chi2 """ return self.tcChi.GetValue() def get_param_list(self): """ :return self.param_toFit: list containing references to TextCtrl checked.Theses TextCtrl will allow reference to parameters to fit. :raise: if return an empty list of parameter fit will nnote work properly so raise ValueError,"missing parameter to fit" """ if self.param_toFit !=[]: return self.param_toFit else: msg = "missing parameters to fit" wx.MessageBox(msg, 'warning') return False #raise ValueError,"missing parameters to fit" def onsetValues(self, chisqr, p_name, out, cov): """ Build the panel from the fit result :param chisqr: Value of the goodness of fit metric :param p_name: the name of parameters :param out: list of parameter with the best value found during fitting :param cov: Covariance matrix """ # make sure stop button to fit button all the time self._on_fit_complete() if out == None or not numpy.isfinite(chisqr): raise ValueError,"Fit error occured..." is_modified = False has_error = False dispersity = '' #Hide textctrl boxes of errors. self._clear_Err_on_Fit() #Check if chi2 is finite if chisqr != None and numpy.isfinite(chisqr): #format chi2 if self.engine_type == "park": npt_fit = float(self.get_npts2fit()) # Taking care this in parkemgine #if npt_fit > 0: # chisqr =chisqr/npt_fit chi2 = format_number(chisqr, True) self.tcChi.SetValue(chi2) self.tcChi.Refresh() else: self.tcChi.SetValue("-") #Hide error title if self.text2_3.IsShown() and not self.is_mac: self.text2_3.Hide() try: if self.enable_disp.GetValue(): if hasattr(self,"text_disp_1" ): if self.text_disp_1 != None and not self.is_mac: self.text_disp_1.Hide() except: dispersity = None pass i = 0 #Set the panel when fit result are list for item in self.param_toFit: if len(item)>5 and item != None: ## reset error value to initial state if not self.is_mac: item[3].Hide() item[4].Hide() for ind in range(len(out)): if item[1] == p_name[ind]: break if len(out)<=len(self.param_toFit) and out[ind] !=None: val_out = format_number(out[ind], True) item[2].SetValue(val_out) if(cov !=None and len(cov) == len(out)): try: if dispersity !=None: if self.enable_disp.GetValue(): if hasattr(self,"text_disp_1" ): if self.text_disp_1!=None: if not self.text_disp_1.IsShown()\ and not self.is_mac: self.text_disp_1.Show(True) except: pass if cov[ind]!=None : if numpy.isfinite(float(cov[ind])): val_err = format_number(cov[ind], True) if not self.is_mac: item[3].Show(True) item[4].Show(True) item[4].SetValue(val_err) has_error = True i += 1 #Show error title when any errors displayed if has_error: if not self.text2_3.IsShown(): self.text2_3.Show(True) ## save current state self.save_current_state() #self._lay_out() if not self.is_mac: self.Layout() self.Refresh() self._mac_sleep(0.1) #plot model ( when drawing, do not update chisqr value again) self._draw_model(update_chisqr=False, source = 'fit') #PostStatusEvent #msg = "Fit completed!dddd " #wx.PostEvent(self._manager.parent, StatusEvent(status=msg)) def onWeighting(self, event): """ On Weighting radio button event, sets the weightbt_string """ self.weightbt_string = event.GetEventObject().GetLabelText() self._set_weight() def _set_weight(self, is_2D=None): """ Set weight in fit problem """ # compute weight for the current data from .utils import get_weight flag_weight = self.get_weight_flag() if is_2D == None: is_2D = self._is_2D() weight = get_weight(data=self.data, is2d=is_2D, flag=flag_weight) self._manager.set_fit_weight(uid=self.uid, flag=flag_weight, is2d=is_2D, fid=None) def onPinholeSmear(self, event): """ Create a custom pinhole smear object that will change the way residuals are compute when fitting :Note: accuracy is given by strings'High','Med', 'Low' FOR 2d, None for 1D """ if self.model == None: self.disable_smearer.SetValue(True) if event == None: return msg="Please select a Model first..." wx.MessageBox(msg, 'Info') wx.PostEvent(self._manager.parent, StatusEvent(status=\ "Smear: %s"%msg)) return # Need update param values self._update_paramv_on_fit() # msg default msg = None if event != None: tcrtl= event.GetEventObject() # event case of radio button if tcrtl.GetValue()== True: self.dx_min = 0.0 self.dx_max = 0.0 is_new_pinhole = True else: is_new_pinhole = self._is_changed_pinhole() else: is_new_pinhole = True # if any value is changed if is_new_pinhole: msg = self._set_pinhole_smear() # hide all silt sizer self._hide_all_smear_info() ##Calculate chi2 temp_smearer = self.current_smearer #self.compute_chisqr(smearer= temp_smearer) # show relevant slit sizers self._show_smear_sizer() self.sizer_set_smearer.Layout() self.Layout() if event != None: event.Skip() #self._undo.Enable(True) self.save_current_state() event = PageInfoEvent(page = self) wx.PostEvent(self.parent, event) def _is_changed_pinhole(self): """ check if any of pinhole smear is changed :return: True or False """ # get the values pin_min = self.smear_pinhole_min.GetValue() pin_max = self.smear_pinhole_max.GetValue() # Check changes in slit width try: dx_min = float(pin_min) except: return True if self.dx_min != dx_min: return True # Check changes in slit heigth try: dx_max = float(pin_max) except: return True if self.dx_max != dx_max: return True return False def _set_pinhole_smear(self): """ Set custom pinhole smear :return: msg """ # copy data data = copy.deepcopy(self.data) if self._is_2D(): self.smear_type = 'Pinhole2d' len_data = len(data.data) data.dqx_data = numpy.zeros(len_data) data.dqy_data = numpy.zeros(len_data) else: self.smear_type = 'Pinhole' len_data = len(data.x) data.dx = numpy.zeros(len_data) data.dxl = None data.dxw = None msg = None get_pin_min = self.smear_pinhole_min get_pin_max = self.smear_pinhole_max if not check_float(get_pin_min): get_pin_min.SetBackgroundColour("pink") msg= "Model Error:wrong value entered!!!" elif not check_float(get_pin_max ): get_pin_max.SetBackgroundColour("pink") msg= "Model Error:wrong value entered!!!" else: if len_data < 2: len_data = 2 self.dx_min = float(get_pin_min.GetValue()) self.dx_max = float(get_pin_max.GetValue()) if self.dx_min < 0: get_pin_min.SetBackgroundColour("pink") msg= "Model Error:This value can not be negative!!!" elif self.dx_max <0: get_pin_max.SetBackgroundColour("pink") msg= "Model Error:This value can not be negative!!!" elif self.dx_min != None and self.dx_max != None: if self._is_2D(): data.dqx_data[data.dqx_data==0] = self.dx_min data.dqy_data[data.dqy_data==0] = self.dx_max elif self.dx_min == self.dx_max: data.dx[data.dx==0] = self.dx_min else: step = (self.dx_max - self.dx_min)/(len_data-1) data.dx = numpy.arange(self.dx_min,self.dx_max+step/1.1, step) elif self.dx_min != None: if self._is_2D(): data.dqx_data[data.dqx_data==0] = self.dx_min else: data.dx[data.dx==0] = self.dx_min elif self.dx_max != None: if self._is_2D(): data.dqy_data[data.dqy_data==0] = self.dx_max else: data.dx[data.dx==0] = self.dx_max self.current_smearer = smear_selection(data, self.model) # 2D need to set accuracy if self._is_2D(): self.current_smearer.set_accuracy(accuracy = \ self.smear2d_accuracy) if msg != None: wx.PostEvent(self._manager.parent, StatusEvent(status = msg )) else: get_pin_min.SetBackgroundColour("white") get_pin_max.SetBackgroundColour("white") ## set smearing value whether or not the data contain the smearing info self._manager.set_smearer(smearer=self.current_smearer, fid=self.data.id, qmin=float(self.qmin_x), qmax= float(self.qmax_x), enable_smearer=not self.disable_smearer.GetValue(), uid=self.uid) return msg def update_pinhole_smear(self): """ called by kill_focus on pinhole TextCntrl to update the changes :return: False when wrong value was entered """ # msg default msg = None # check if any value is changed if self._is_changed_pinhole(): msg = self._set_pinhole_smear() #self._undo.Enable(True) wx.CallAfter(self.save_current_state) if msg != None: return False else: return True def onSlitSmear(self, event): """ Create a custom slit smear object that will change the way residuals are compute when fitting """ if self.model == None: self.disable_smearer.SetValue(True) if event == None: return msg="Please select a Model first..." wx.MessageBox(msg, 'Info') wx.PostEvent(self._manager.parent, StatusEvent(status=\ "Smear: %s"%msg)) return # Need update param values self._update_paramv_on_fit() # msg default msg = None # for event given if event != None: tcrtl= event.GetEventObject() # event case of radio button if tcrtl.GetValue(): self.dxl = 0.0 self.dxw = 0.0 is_new_slit = True else: is_new_slit = self._is_changed_slit() else: is_new_slit = True # if any value is changed if is_new_slit: msg = self._set_slit_smear() # hide all silt sizer self._hide_all_smear_info() ##Calculate chi2 #self.compute_chisqr(smearer= self.current_smearer) # show relevant slit sizers self._show_smear_sizer() self.sizer_set_smearer.Layout() self.Layout() if event != None: event.Skip() #self._undo.Enable(True) self.save_current_state() event = PageInfoEvent(page = self) wx.PostEvent(self.parent, event) if msg != None: wx.PostEvent(self._manager.parent, StatusEvent(status = msg)) def _is_changed_slit(self): """ check if any of slit lengths is changed :return: True or False """ # get the values width = self.smear_slit_width.GetValue() height = self.smear_slit_height.GetValue() # check and change the box bg color if it was pink # but it should be white now # because this is the case that _set_slit_smear() will not handle if height.lstrip().rstrip()=="": self.smear_slit_height.SetBackgroundColour(wx.WHITE) if width.lstrip().rstrip()=="": self.smear_slit_width.SetBackgroundColour(wx.WHITE) # Check changes in slit width if width == "": dxw = 0.0 else: try: dxw = float(width) except: return True if self.dxw != dxw: return True # Check changes in slit heigth if height == "": dxl = 0.0 else: try: dxl = float(height) except: return True if self.dxl != dxl: return True return False def _set_slit_smear(self): """ Set custom slit smear :return: message to inform the user about the validity of the values entered for slit smear """ if self.data.__class__.__name__ == "Data2D" or \ self.enable2D: return temp_smearer = None # make sure once more if it is smearer data = copy.deepcopy(self.data) data_len = len(data.x) data.dx = None data.dxl = None data.dxw = None msg = None try: self.dxl = float(self.smear_slit_height.GetValue()) data.dxl = self.dxl* numpy.ones(data_len) self.smear_slit_height.SetBackgroundColour(wx.WHITE) except: data.dxl = numpy.zeros(data_len) if self.smear_slit_height.GetValue().lstrip().rstrip()!="": self.smear_slit_height.SetBackgroundColour("pink") msg = "Wrong value entered... " else: self.smear_slit_height.SetBackgroundColour(wx.WHITE) try: self.dxw = float(self.smear_slit_width.GetValue()) self.smear_slit_width.SetBackgroundColour(wx.WHITE) data.dxw = self.dxw* numpy.ones(data_len) except: data.dxw = numpy.zeros(data_len) if self.smear_slit_width.GetValue().lstrip().rstrip()!="": self.smear_slit_width.SetBackgroundColour("pink") msg = "Wrong Fit value entered... " else: self.smear_slit_width.SetBackgroundColour(wx.WHITE) self.current_smearer = smear_selection(data, self.model) #temp_smearer = self.current_smearer ## set smearing value whether or not the data contain the smearing info self._manager.set_smearer(smearer=self.current_smearer, fid=self.data.id, qmin=float(self.qmin_x), qmax= float(self.qmax_x), enable_smearer=not self.disable_smearer.GetValue(), uid=self.uid) return msg def update_slit_smear(self): """ called by kill_focus on pinhole TextCntrl to update the changes :return: False when wrong value was entered """ # msg default msg = None # check if any value is changed if self._is_changed_slit(): msg = self._set_slit_smear() #self._undo.Enable(True) self.save_current_state() if msg != None: return False else: return True def onSmear(self, event): """ Create a smear object that will change the way residuals are compute when fitting """ if event != None: event.Skip() if self.data is None: return if self.model == None: self.disable_smearer.SetValue(True) if event == None: return msg="Please select a Model first..." wx.MessageBox(msg, 'Info') wx.PostEvent(self._manager.parent, StatusEvent(status=\ "Smear: %s"%msg)) return # Need update param values self._update_paramv_on_fit() temp_smearer = self.on_smear_helper() self.sizer_set_smearer.Layout() self.Layout() self._set_weight() ## set smearing value whether or not the data contain the smearing info wx.CallAfter(self._manager.set_smearer, uid=self.uid, smearer=temp_smearer, fid=self.data.id, qmin=float(self.qmin_x), qmax=float(self.qmax_x), enable_smearer=not self.disable_smearer.GetValue(), draw=True) self.state.enable_smearer= self.enable_smearer.GetValue() self.state.disable_smearer=self.disable_smearer.GetValue() self.state.pinhole_smearer = self.pinhole_smearer.GetValue() self.state.slit_smearer = self.slit_smearer.GetValue() def on_smear_helper(self, update=False): """ Help for onSmear :param update: force or not to update """ self._get_smear_info() temp_smearer = None #renew smear sizer if self.smear_type != None: self.smear_description_smear_type.SetValue(str(self.smear_type)) self.smear_data_left.SetValue(str(self.dq_l)) self.smear_data_right.SetValue(str(self.dq_r)) self._hide_all_smear_info() data = copy.deepcopy(self.data) # make sure once more if it is smearer temp_smearer = smear_selection(data, self.model) if self.current_smearer != temp_smearer or update: self.current_smearer = temp_smearer if self.enable_smearer.GetValue(): if hasattr(self.data,"dxl"): msg= ": Resolution smearing parameters" if hasattr(self.data,"dxw"): msg= ": Slit smearing parameters" if self.current_smearer ==None: wx.PostEvent(self._manager.parent, StatusEvent(status=\ "Data contains no smearing information")) else: wx.PostEvent(self._manager.parent, StatusEvent(status=\ "Data contains smearing information")) #self.smear_description_dqdata.Show(True) self.smear_data_left.Show(True) self.smear_data_right.Show(True) temp_smearer= self.current_smearer elif self.disable_smearer.GetValue(): self.smear_description_none.Show(True) elif self.pinhole_smearer.GetValue(): self.onPinholeSmear(None) elif self.slit_smearer.GetValue(): self.onSlitSmear(None) self._show_smear_sizer() return temp_smearer def on_complete_chisqr(self, event): """ Display result chisqr on the panel :event: activated by fitting/ complete after draw """ try: if event == None: output= "-" elif not numpy.isfinite(event.output): output= "-" else: output = event.output self.tcChi.SetValue(str(format_number(output, True))) self.state.tcChi = self.tcChi.GetValue() except: pass def get_all_checked_params(self): """ Found all parameters current check and add them to list of parameters to fit """ self.param_toFit = [] for item in self.parameters: if item[0].GetValue() and item not in self.param_toFit: self.param_toFit.append(item) for item in self.fittable_param: if item[0].GetValue() and item not in self.param_toFit: self.param_toFit.append(item) self.save_current_state_fit() event = PageInfoEvent(page = self) wx.PostEvent(self.parent, event) param2fit = [] for item in self.param_toFit: if item[0]: param2fit.append(item[1]) self.parent._manager.set_param2fit(self.uid, param2fit) def select_all_param(self, event): """ set to true or false all checkBox given the main checkbox value cb1 """ self.param_toFit = [] if self.parameters !=[]: if self.cb1.GetValue(): for item in self.parameters: ## for data2D select all to fit if self.data.__class__.__name__== "Data2D" or \ self.enable2D: item[0].SetValue(True) self.param_toFit.append(item) else: ## for 1D all parameters except orientation if not item in self.orientation_params: item[0].SetValue(True) self.param_toFit.append(item ) #if len(self.fittable_param)>0: for item in self.fittable_param: if self.data.__class__.__name__== "Data2D" or \ self.enable2D: item[0].SetValue(True) self.param_toFit.append(item) try: if len(self.values[item[1]]) > 0: item[0].SetValue(False) except: pass else: ## for 1D all parameters except orientation if not item in self.orientation_params_disp: item[0].SetValue(True) self.param_toFit.append(item ) try: if len(self.values[item[1]]) > 0: item[0].SetValue(False) except: pass else: for item in self.parameters: item[0].SetValue(False) for item in self.fittable_param: item[0].SetValue(False) self.param_toFit=[] self.save_current_state_fit() if event !=None: #self._undo.Enable(True) ## post state to fit panel event = PageInfoEvent(page = self) wx.PostEvent(self.parent, event) param2fit = [] for item in self.param_toFit: if item[0]: param2fit.append(item[1]) self.parent._manager.set_param2fit(self.uid, param2fit) def select_param(self,event): """ Select TextCtrl checked for fitting purpose and stores them in self.param_toFit=[] list """ self.param_toFit = [] for item in self.parameters: #Skip t ifhe angle parameters if 1D data if self.data.__class__.__name__ != "Data2D" and\ not self.enable2D: if item in self.orientation_params: continue #Select parameters to fit for list of primary parameters if item[0].GetValue(): if not (item in self.param_toFit): self.param_toFit.append(item ) else: #remove parameters from the fitting list if item in self.param_toFit: self.param_toFit.remove(item) #Select parameters to fit for list of fittable parameters # with dispersion for item in self.fittable_param: #Skip t ifhe angle parameters if 1D data if self.data.__class__.__name__ != "Data2D" and\ not self.enable2D: if item in self.orientation_params: continue if item[0].GetValue(): if not (item in self.param_toFit): self.param_toFit.append(item) else: #remove parameters from the fitting list if item in self.param_toFit: self.param_toFit.remove(item) #Calculate num. of angle parameters if self.data.__class__.__name__ == "Data2D" or \ self.enable2D: len_orient_para = 0 else: len_orient_para = len(self.orientation_params) #assume even len #Total num. of angle parameters if len(self.fittable_param) > 0: len_orient_para *= 2 #Set the value of checkbox that selected every checkbox or not if len(self.parameters)+len(self.fittable_param)-len_orient_para ==\ len(self.param_toFit): self.cb1.SetValue(True) else: self.cb1.SetValue(False) self.save_current_state_fit() if event !=None: #self._undo.Enable(True) ## post state to fit panel event = PageInfoEvent(page = self) wx.PostEvent(self.parent, event) param2fit = [] for item in self.param_toFit: if item[0]: param2fit.append(item[1]) self.parent._manager.set_param2fit(self.uid, param2fit) def set_model_param_sizer(self, model): """ Build the panel from the model content :param model: the model selected in combo box for fitting purpose """ self.sizer3.Clear(True) self.parameters = [] self.str_parameters = [] self.param_toFit=[] self.fittable_param=[] self.fixed_param=[] self.orientation_params=[] self.orientation_params_disp=[] if model ==None: self.sizer3.Layout() self.SetupScrolling() return ## the panel is drawn using the current value of the fit engine if self.engine_type==None and self._manager !=None: self.engine_type= self._manager._return_engine_type() box_description= wx.StaticBox(self, -1,str("Model Parameters")) boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL) sizer = wx.GridBagSizer(5,5) ## save the current model self.model = model keys = self.model.getParamList() #list of dispersion paramaters self.disp_list=self.model.getDispParamList() def custom_compare(a,b): """ Custom compare to order, first by alphabets then second by number. """ # number at the last digit a_last = a[len(a)-1] b_last = b[len(b)-1] # default num_a = None num_b = None # split the names a2 = a.lower().split('_') b2 = b.lower().split('_') # check length of a2, b2 len_a2 = len(a2) len_b2 = len(b2) # check if it contains a int number(<10) try: num_a = int(a_last) except: pass try: num_b = int(b_last) except: pass # Put 'scale' near the top; happens # when numbered param name exists if a == 'scale': return -1 # both have a number if num_a != None and num_b != None: if num_a > num_b: return -1 # same number elif num_a == num_b: # different last names if a2[len_a2-1] != b2[len_b2-1] and num_a != 0: return -cmp(a2[len_a2-1], b2[len_b2-1]) else: return cmp(a, b) else: return 1 # one of them has a number elif num_a != None: return 1 elif num_b != None: return -1 # no numbers else: return cmp(a.lower(), b.lower()) keys.sort(custom_compare) iy = 0 ix = 0 select_text = "Select All" self.cb1 = wx.CheckBox(self, -1,str(select_text), (10, 10)) wx.EVT_CHECKBOX(self, self.cb1.GetId(), self.select_all_param) self.cb1.SetToolTipString("To check/uncheck all the boxes below.") self.cb1.SetValue(True) sizer.Add(self.cb1,(iy, ix),(1,1),\ wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 5) ix +=1 self.text2_2 = wx.StaticText(self, -1, 'Value') sizer.Add(self.text2_2,(iy, ix),(1,1),\ wx.EXPAND|wx.ADJUST_MINSIZE, 0) ix +=2 self.text2_3 = wx.StaticText(self, -1, 'Error') sizer.Add(self.text2_3,(iy, ix),(1,1),\ wx.EXPAND|wx.ADJUST_MINSIZE, 0) if not self.is_mac: self.text2_3.Hide() ix +=1 self.text2_min = wx.StaticText(self, -1, 'Min') sizer.Add(self.text2_min,(iy, ix),(1,1),\ wx.EXPAND|wx.ADJUST_MINSIZE, 0) #self.text2_min.Hide() ix +=1 self.text2_max = wx.StaticText(self, -1, 'Max') sizer.Add(self.text2_max,(iy, ix),(1,1),\ wx.EXPAND|wx.ADJUST_MINSIZE, 0) #self.text2_max.Hide() ix += 1 self.text2_4 = wx.StaticText(self, -1, '[Units]') sizer.Add(self.text2_4,(iy, ix),(1,1),\ wx.EXPAND|wx.ADJUST_MINSIZE, 0) self.text2_4.Hide() CHECK_STATE = self.cb1.GetValue() for item in keys: if not item in self.disp_list and not item in \ self.model.orientation_params: ##prepare a spot to store errors if not self.model.details.has_key(item): self.model.details [item] = ["",None,None] iy += 1 ix = 0 if (self.model.__class__ in \ self.model_list_box["Multi-Functions"] or \ self.temp_multi_functional)\ and (item in self.model.non_fittable): non_fittable_name = wx.StaticText(self, -1, item ) sizer.Add(non_fittable_name,(iy, ix),(1,1),\ wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 21) ## add parameter value ix += 1 value= self.model.getParam(item) if len(self.model.fun_list) > 0: num = item.split('_')[1][5:7] fun_box = wx.ComboBox(self, -1,size=(100,-1), style=wx.CB_READONLY, name = '%s'% item) self._set_fun_box_list(fun_box) fun_box.SetSelection(0) #self.fun_box.SetToolTipString("A function # describing the interface") wx.EVT_COMBOBOX(fun_box,-1, self._on_fun_box) else: fun_box = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH,20), style=wx.TE_PROCESS_ENTER, name ='%s'% item) fun_box.SetToolTipString(\ "Hit 'Enter' after typing to update the plot.") fun_box.SetValue(format_number(value, True)) sizer.Add(fun_box, (iy,ix),(1,1), wx.EXPAND) self.str_parameters.append([None,item, fun_box, None, None, None, None, None]) else: ## add parameters name with checkbox for selecting to fit cb = wx.CheckBox(self, -1, item) cb.SetValue(CHECK_STATE) cb.SetToolTipString(" Check mark to fit.") #cb.SetValue(True) wx.EVT_CHECKBOX(self, cb.GetId(), self.select_param) sizer.Add( cb,( iy, ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 5) ## add parameter value ix += 1 value= self.model.getParam(item) ctl1 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH,20), style=wx.TE_PROCESS_ENTER) ctl1.SetToolTipString(\ "Hit 'Enter' after typing to update the plot.") ctl1.SetValue(format_number(value, True)) sizer.Add(ctl1, (iy,ix),(1,1), wx.EXPAND) ## text to show error sign ix += 1 text2=wx.StaticText(self, -1, '+/-') sizer.Add(text2,(iy, ix),(1,1),\ wx.EXPAND|wx.ADJUST_MINSIZE, 0) if not self.is_mac: text2.Hide() ix += 1 ctl2 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH/1.2,20), style=0) sizer.Add(ctl2, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0) if not self.is_mac: ctl2.Hide() ix += 1 ctl3 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH/1.9,20), style=wx.TE_PROCESS_ENTER, text_enter_callback = self._onparamRangeEnter) sizer.Add(ctl3, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0) ix += 1 ctl4 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH/1.9,20), style=wx.TE_PROCESS_ENTER, text_enter_callback = self._onparamRangeEnter) sizer.Add(ctl4, (iy,ix),(1,1), wx.EXPAND|wx.FIXED_MINSIZE, 0) ix +=1 # Units if self.model.details.has_key(item): units = wx.StaticText(self, -1, self.model.details[item][0], style=wx.ALIGN_LEFT) else: units = wx.StaticText(self, -1, "", style=wx.ALIGN_LEFT) sizer.Add(units, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0) ##[cb state, name, value, "+/-", error of fit, min, max , units] self.parameters.append([cb,item, ctl1, text2,ctl2, ctl3, ctl4,units]) iy+=1 sizer.Add((10,10),(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15) # type can be either Guassian or Array if len(self.model.dispersion.values())>0: type= self.model.dispersion.values()[0]["type"] else: type = "Gaussian" iy += 1 ix = 0 #Add tile for orientational angle for item in keys: if item in self.model.orientation_params: orient_angle = wx.StaticText(self, -1, '[For 2D only]:') sizer.Add(orient_angle,(iy, ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15) if not self.data.__class__.__name__ == "Data2D" and \ not self.enable2D: orient_angle.Hide() else: orient_angle.Show(True) break #For Gaussian only if type.lower() != "array": for item in self.model.orientation_params: if not item in self.disp_list: ##prepare a spot to store min max if not self.model.details.has_key(item): self.model.details [item] = ["",None,None] iy += 1 ix = 0 ## add parameters name with checkbox for selecting to fit cb = wx.CheckBox(self, -1, item ) cb.SetValue(CHECK_STATE) cb.SetToolTipString("Check mark to fit") wx.EVT_CHECKBOX(self, cb.GetId(), self.select_param) if self.data.__class__.__name__ == "Data2D" or \ self.enable2D: cb.Show(True) else: cb.Hide() sizer.Add( cb,( iy, ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 5) ## add parameter value ix += 1 value= self.model.getParam(item) ctl1 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH,20), style=wx.TE_PROCESS_ENTER) ctl1.SetToolTipString(\ "Hit 'Enter' after typing to update the plot.") ctl1.SetValue(format_number(value, True)) if self.data.__class__.__name__ == "Data2D" or \ self.enable2D: ctl1.Show(True) else: ctl1.Hide() sizer.Add(ctl1, (iy,ix),(1,1), wx.EXPAND) ## text to show error sign ix += 1 text2=wx.StaticText(self, -1, '+/-') sizer.Add(text2,(iy, ix),(1,1),\ wx.EXPAND|wx.ADJUST_MINSIZE, 0) text2.Hide() ix += 1 ctl2 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH/1.2,20), style=0) sizer.Add(ctl2, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0) ctl2.Hide() ix += 1 ctl3 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH/1.8,20), style=wx.TE_PROCESS_ENTER, text_enter_callback = self._onparamRangeEnter) sizer.Add(ctl3, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0) ctl3.Hide() ix += 1 ctl4 = self.ModelTextCtrl(self, -1, size=(_BOX_WIDTH/1.8,20), style=wx.TE_PROCESS_ENTER, text_enter_callback = self._onparamRangeEnter) sizer.Add(ctl4, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0) ctl4.Hide() if self.data.__class__.__name__ == "Data2D" or \ self.enable2D: if self.is_mac: text2.Show(True) ctl2.Show(True) ctl3.Show(True) ctl4.Show(True) ix +=1 # Units if self.model.details.has_key(item): units = wx.StaticText(self, -1, self.model.details[item][0], style=wx.ALIGN_LEFT) else: units = wx.StaticText(self, -1, "", style=wx.ALIGN_LEFT) if self.data.__class__.__name__ == "Data2D" or \ self.enable2D: units.Show(True) else: units.Hide() sizer.Add(units, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0) ##[cb state, name, value, "+/-", error of fit,min,max,units] self.parameters.append([cb,item, ctl1, text2,ctl2, ctl3, ctl4,units]) self.orientation_params.append([cb,item, ctl1, text2,ctl2, ctl3, ctl4,units]) iy+=1 #Display units text on panel for item in keys: if self.model.details.has_key(item): self.text2_4.Show() #Fill the list of fittable parameters self.get_all_checked_params() self.save_current_state_fit() boxsizer1.Add(sizer) self.sizer3.Add(boxsizer1,0, wx.EXPAND | wx.ALL, 10) self.sizer3.Layout() self.Layout() #self.Refresh() def on_right_down(self, event): """ Get key stroke event """ if self.data == None: return # Figuring out key combo: Cmd for copy, Alt for paste if event.AltDown() and event.ShiftDown(): self._manager.show_ftol_dialog() flag = True elif event.AltDown() or event.ShiftDown(): flag = False else: return # make event free event.Skip() # messages depending on the flag if not flag: msg = " Could not open ftol dialog;" msg += " Check if the Scipy fit engine is selected in the menubar." infor = 'warning' # inform msg to wx wx.PostEvent( self.parent.parent, StatusEvent(status= msg, info=infor)) def _onModel2D(self, event): """ toggle view of model from 1D to 2D or 2D from 1D """ if self.model_view.GetLabelText() == "Show 2D": self.model_view.SetLabel("Show 1D") self.enable2D = True else: self.model_view.SetLabel("Show 2D") self.enable2D = False self.Show(False) self.create_default_data() self._manager.store_data(self.uid, data_list=[self.data]) self.set_model_param_sizer(self.model) self._set_sizer_dispersion() self._set_weight(is_2D= self.enable2D) self._set_smear_buttons() self.Show(True) self.SetupScrolling() self._draw_model() self.state.enable2D = copy.deepcopy(self.enable2D) def _set_smear_buttons(self): """ Set semarer radio buttons """ # more disables for 2D if self.data.__class__.__name__ == "Data2D" or \ self.enable2D: self.slit_smearer.Disable() self.pinhole_smearer.Enable(True) self.default_mask = copy.deepcopy(self.data.mask) else: self.slit_smearer.Enable(True) self.pinhole_smearer.Enable(True) class BGTextCtrl(wx.TextCtrl): """ Text control used to display outputs. No editing allowed. The background is grayed out. User can't select text. """ def __init__(self, *args, **kwds): wx.TextCtrl.__init__(self, *args, **kwds) self.SetEditable(False) self.SetBackgroundColour(self.GetParent().parent.GetBackgroundColour()) # Bind to mouse event to avoid text highlighting # The event will be skipped once the call-back # is called. self.Bind(wx.EVT_MOUSE_EVENTS, self._click) def _click(self, event): """ Prevent further handling of the mouse event by not calling Skip(). """ pass