Index: sansview/perspectives/fitting/basepage.py
===================================================================
--- sansview/perspectives/fitting/basepage.py	(revision c77d8592395f6684cf45ee976c1cac9db9c00110)
+++ sansview/perspectives/fitting/basepage.py	(revision c77d8592395f6684cf45ee976c1cac9db9c00110)
@@ -0,0 +1,829 @@
+
+import sys
+import wx
+import numpy
+
+from sans.guiframe.utils import format_number
+from sans.guicomm.events import StatusEvent   
+
+_BOX_WIDTH = 80
+
+class BasicPage(wx.ScrolledWindow):
+    """
+        This class provide general structure of  fitpanel page
+    """
+    ## Internal name for the AUI manager
+    window_name = "Fit page"
+    ## Title to appear on top of the window
+    window_caption = "Fit Page"
+    name=""
+    def __init__(self,parent, pageinfo, name):
+        wx.ScrolledWindow.__init__(self, parent)
+        ## store name
+        self.name = name
+        ## store info of panel
+        self.page_info= pageinfo
+        self.page_info.page_name = name
+        ## parent of the page
+        self.parent = parent
+        ## owner of the page (fitting plugin)
+        self.event_owner= None
+        ## create the basic structure of the panel with empty sizer
+        self.define_page_structure()
+        ## dictionary containing list of models
+        self.model_list_box={}
+        ## Data member to store the dispersion object created
+        self._disp_obj_dict = {}
+        self.disp_cb_dict ={}
+        ##list of model parameters. each item must have same length
+        ## each item related to a given parameters
+        ##[cb state, name, value, "+/-", error of fit, min, max , units]
+        self.parameters=[]
+        ## list of parameters to fit , must be like self.parameters
+        self.param_toFit=[]
+        ## list of looking like parameters but with non fittable parameters info
+        self.fixed_param=[]
+        ## list of looking like parameters but with  fittable parameters info
+        self.fittable_param=[]
+        ##list of dispersion parameters
+        self.disp_list=[]
+        
+        ##enable model 2D draw
+        self.enable2D= False
+        ## check that the fit range is correct to plot the model again
+        self.fitrange= True
+        ## current model
+        self.model= None
+        ## data
+        self.data=None
+        ## Q range
+        self.qmin_x= 0.001
+        self.qmax_x= 0.1
+        self.num_points= 100
+        ## changing initial values given page_info value
+        if self.page_info !=None and len(self.page_info.model_list_box) >0:
+            self.model_list_box = self.page_info.model_list_box
+            ## current model
+            self.model=self.page_info.model
+            self.data = self.page_info.data
+            self.event_owner = self.page_info.event_owner
+            if self.model !=None:
+                self.disp_list= self.model.getDispParamList()
+        ## drawing Initial dispersion parameters sizer 
+        self.set_dispers_sizer()
+        ## layout
+        self.set_layout()
+       
+        
+    def define_page_structure(self):
+        """
+            Create empty sizer for a panel
+        """
+        self.vbox  = wx.BoxSizer(wx.VERTICAL)
+        self.sizer0 = wx.BoxSizer(wx.VERTICAL)
+        self.sizer1 = wx.BoxSizer(wx.VERTICAL)
+        self.sizer2 = wx.BoxSizer(wx.VERTICAL)
+        self.sizer3 = wx.BoxSizer(wx.VERTICAL)
+       
+        self.sizer4 = wx.BoxSizer(wx.VERTICAL)
+        self.sizer5 = wx.BoxSizer(wx.VERTICAL)
+        
+        self.vbox.Add(self.sizer0)
+        self.vbox.Add(self.sizer1)
+        self.vbox.Add(self.sizer2)
+        self.vbox.Add(self.sizer3)
+        self.vbox.Add(self.sizer4)
+        self.vbox.Add(self.sizer5)
+        
+    def set_layout(self):
+        """
+             layout
+        """
+        self.vbox.Layout()
+        self.vbox.Fit(self) 
+        self.SetSizer(self.vbox)
+       
+        self.set_scroll()
+        self.Centre()
+        
+    def set_scroll(self):
+        self.SetScrollbars(20,20,200,100)
+        self.Layout()   
+         
+    def set_owner(self,owner):
+        """ 
+            set owner of fitpage
+            @param owner: the class responsible of plotting
+        """
+        self.event_owner = owner    
+        self.page_info.event_owner = owner
+  
+    def set_manager(self, manager):
+        """
+             set panel manager
+             @param manager: instance of plugin fitting
+        """
+        self.manager = manager  
+        self.page_info.manager = manager
+        
+    def populate_box(self, dict):
+        """
+             Store list of model
+             @param dict: dictionary containing list of models
+        """
+        self.model_list_box = dict
+        if self.page_info!=None:
+            self.page_info.model_list_box = self.model_list_box
+            
+    
+        
+    def set_dispers_sizer(self):
+        """
+            fill sizer containing dispersity info
+        """
+        self.sizer4.Clear(True)
+        box_description= wx.StaticBox(self, -1,"PolyDispersity")
+        boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL)
+        #----------------------------------------------------
+        self.disable_disp = wx.RadioButton(self, -1, 'No', (10, 10), style=wx.RB_GROUP)
+        self.enable_disp = wx.RadioButton(self, -1, 'Yes', (10, 30))
+        self.Bind(wx.EVT_RADIOBUTTON, self._set_dipers_Param, id=self.disable_disp.GetId())
+        self.Bind(wx.EVT_RADIOBUTTON, self._set_dipers_Param, id=self.enable_disp.GetId())
+        
+        sizer_dispersion = wx.BoxSizer(wx.HORIZONTAL)
+        sizer_dispersion.Add((20,20))
+        sizer_dispersion.Add(wx.StaticText(self,-1,'Polydispersity: '))
+        sizer_dispersion.Add(self.enable_disp )
+        sizer_dispersion.Add((20,20))
+        sizer_dispersion.Add(self.disable_disp )
+        sizer_dispersion.Add((10,10))
+        
+        ## fill a sizer with the combobox to select dispersion type
+        sizer_select_dispers = wx.BoxSizer(wx.HORIZONTAL)  
+        self.model_disp = wx.StaticText(self, -1, 'Model Disp')
+            
+        import sans.models.dispersion_models 
+        self.polydisp= sans.models.dispersion_models.models
+        self.disp_box = wx.ComboBox(self, -1)
+        self.disp_box.SetValue("GaussianModel")
+        
+        for key in self.polydisp.iterkeys():
+            name = str(key.__name__)
+            if name=="ArrayDispersion":
+                # Remove the option until the rest of the code is ready for it
+                self.disp_box.Append("Select customized Model",key)
+                pass  
+            else:
+                self.disp_box.Append(name,key) 
+        wx.EVT_COMBOBOX(self.disp_box,-1, self._on_select_Disp) 
+             
+        sizer_select_dispers.Add((10,10)) 
+        sizer_select_dispers.Add(self.model_disp) 
+        sizer_select_dispers.Add(self.disp_box) 
+        sizer_select_dispers.Add((10,10)) 
+        self.model_disp.Hide()
+        self.disp_box.Hide()
+        
+        boxsizer1.Add( sizer_dispersion )
+        boxsizer1.Add( (10,10) )
+        boxsizer1.Add( sizer_select_dispers )
+        self.sizer4_4 = wx.GridBagSizer(5,5)
+        boxsizer1.Add( self.sizer4_4  )
+        #-----------------------------------------------------
+        self.sizer4.Add(boxsizer1,0, wx.EXPAND | wx.ALL, 10)
+        self.sizer4.Layout()
+        self.SetScrollbars(20,20,200,100)
+    
+    def select_disp_angle(self, event): 
+        """
+            Event for when a user select a parameter to average over.
+            @param event: check box event
+        """
+        
+        
+        # Go through the list of dispersion check boxes to identify which one has changed 
+        for p in self.disp_cb_dict:
+            # Catch which one of the box was just checked or unchecked.
+            if event.GetEventObject() == self.disp_cb_dict[p]:              
+
+                
+                if self.disp_cb_dict[p].GetValue() == True:
+                    # The user wants this parameter to be averaged. 
+                    # Pop up the file selection dialog.
+                    path = self._selectDlg()
+                    
+                    # If nothing was selected, just return
+                    if path is None:
+                        self.disp_cb_dict[p].SetValue(False)
+                        return
+                    
+                    try:
+                        values,weights = self.read_file(path)
+                    except:
+                        msg="Could not read input file"
+                        wx.PostEvent(self.parent.parent, StatusEvent(status= msg))
+                        return
+                    
+                    # If any of the two arrays is empty, notify the user that we won't
+                    # proceed 
+                    if values is None or weights is None:
+                        wx.PostEvent(self.parent.parent, StatusEvent(status=\
+                            "The loaded %s distrubtion is corrupted or empty" % p))
+                        return
+                        
+                    # Tell the user that we are about to apply the distribution
+                    wx.PostEvent(self.parent.parent, StatusEvent(status=\
+                            "Applying loaded %s distribution: %s" % (p, path)))  
+                    
+                    # Create the dispersion objects
+                    from sans.models.dispersion_models import ArrayDispersion
+                    disp_model = ArrayDispersion()
+                    disp_model.set_weights(values, weights)
+                    # Store the object to make it persist outside the scope of this method
+                    #TODO: refactor model to clean this up?
+                    self._disp_obj_dict[p] = disp_model
+                    
+                    # Set the new model as the dispersion object for the selected parameter
+                    self.model.set_dispersion(p, disp_model)
+                          
+                else:
+                    # The parameter was un-selected. Go back to Gaussian model (with 0 pts)
+                    self._reset_dispersity()
+                    
+                ## Redraw the model
+                self._draw_model()
+        return
+    
+         
+   
+    
+    def read_file(self, path):
+        """
+            Read two columns file
+            @param path: the path to the file to read
+        """
+        try:
+            if path==None:
+                wx.PostEvent(self.parent.parent, StatusEvent(status=\
+                            " Selected Distribution was not loaded: %s"%path))
+                return None, None
+            input_f = open(path, 'r')
+            buff = input_f.read()
+            lines = buff.split('\n')
+            
+            angles = []
+            weights=[]
+            for line in lines:
+                toks = line.split()
+                if len(toks)==2:
+                    try:
+                        angle = float(toks[0])
+                        weight = float(toks[1])
+                    except:
+                        # Skip non-data lines
+                        pass
+                    angles.append(angle)
+                    weights.append(weight)
+            return numpy.array(angles), numpy.array(weights)
+        except:
+            raise 
+     
+         
+    def _selectDlg(self):
+        """
+            open a dialog file to selected the customized dispersity 
+        """
+        import os
+        dlg = wx.FileDialog(self, "Choose a weight file", os.getcwd(), "", "*.*", wx.OPEN)
+        path = None
+        if dlg.ShowModal() == wx.ID_OK:
+            path = dlg.GetPath()
+        dlg.Destroy()
+        return path
+          
+    
+    def _onparamEnter_helper(self):
+        """
+             check if values entered by the user are changed and valid to replot 
+             model
+             use : _check_value_enter 
+        """
+        if self.model !=None:
+            # Flag to register when a parameter has changed.
+            is_modified = False
+            is_modified =self._check_value_enter( self.fittable_param ,is_modified)
+            is_modified =self._check_value_enter( self.fixed_param ,is_modified)
+            is_modified =self._check_value_enter( self.parameters ,is_modified)        
+           
+            # Here we should check whether the boundaries have been modified.
+            # If qmin and qmax have been modified, update qmin and qmax and 
+            # set the is_modified flag to True
+            from sans.guiframe.utils import check_value
+            if check_value( self.qmin, self.qmax):
+                if float(self.qmin.GetValue()) != self.qmin_x:
+                    self.qmin_x = float(self.qmin.GetValue())
+                    is_modified = True
+                if float(self.qmax.GetValue()) != self.qmax_x:
+                    self.qmax_x = float(self.qmax.GetValue())
+                    is_modified = True
+                self.fitrange = True
+            else:
+                self.fitrange = False
+            if self.npts != None:
+                if float(self.npts.GetValue()) !=  self.num_points:
+                    self.num_points = float(self.npts.GetValue())
+                    is_modified = True
+            ## if any value is modify draw model with new value
+            if is_modified:
+                self._draw_model() 
+                
+                
+    def _set_model_sizer_selection(self, model):
+        """
+            Display the sizer according to the type of the current model
+        """
+        if hasattr(model ,"model2"):
+            
+            class_name= model.model2.__class__
+            name= model.model2.name
+            flag= name != "NoStructure"
+            if flag and (class_name in self.model_list_box["Structure Factors"]):
+                self.structurebox.Show(True)
+                self.text2.Show(True)
+                self.multip_cb.SetValue(True)
+                items = self.structurebox.GetItems()
+                self.sizer1.Layout()
+                self.SetScrollbars(20,20,200,100)
+                for i in range(len(items)):
+                    if items[i]== str(name):
+                        self.structurebox.SetSelection(i)
+                        break
+                    
+        if hasattr(model ,"model1"):
+            class_name = model.model1.__class__
+            name = model.model1.name
+            self.formfactorbox.Clear()
+            
+            for k, list in self.model_list_box.iteritems():
+                if k == "shapes":
+                    self.shape_rbutton.SetValue(True)
+                elif k == "Shape-independent":
+                    self.shape_indep_rbutton.SetValue(True)
+                elif k == "Structure Factors":
+                     self.struct_rbutton.SetValue(True)
+                else:
+                    self.plugin_rbutton.SetValue(True)
+                    
+                if class_name in list:
+                    ## fill the form factor list with new model
+                    self._populate_box(self.formfactorbox, list)
+                    items = self.formfactorbox.GetItems()
+                    ## set comboxbox to the selected item
+                    for i in range(len(items)):
+                        if items[i]== str(name):
+                            self.formfactorbox.SetSelection(i)
+                            break
+                    break
+        else:
+            ## Select the model from the combo box
+            class_name = model.__class__
+            name = model.name
+            self.formfactorbox.Clear()
+            items = self.formfactorbox.GetItems()
+            for k, list in self.model_list_box.iteritems():
+                if k == "shapes":
+                    self.shape_rbutton.SetValue(True)
+                elif k == "Shape-independent":
+                    self.shape_indep_rbutton.SetValue(True)
+                elif k == "Structure Factors":
+                     self.struct_rbutton.SetValue(True)
+                else:
+                    self.plugin_rbutton.SetValue(True)
+                if class_name in list:
+                ## fill the form factor list with new model
+                    self._populate_box(self.formfactorbox, list)
+                    items = self.formfactorbox.GetItems()
+                    ## set comboxbox to the selected item
+                    for i in range(len(items)):
+                        if items[i]== str(name):
+                            self.formfactorbox.SetSelection(i)
+                            break
+                    break
+                    
+        
+        
+    def _draw_model(self):
+        """
+            Method to draw or refresh a plotted model.
+            The method will use the data member from the model page
+            to build a call to the fitting perspective manager.
+            
+            [Note to coder: This way future changes will be done in only one place.] 
+        """
+        if self.model !=None:
+            self.manager.draw_model(self.model, data=self.data,
+                                    qmin=self.qmin_x, qmax=self.qmax_x,
+                                    qstep= self.num_points,
+                                    enable2D=self.enable2D) 
+        
+    def _set_model_sizer(self, sizer, title="", object=None):
+        """
+            Use lists to fill a sizer for model info
+        """
+       
+        sizer.Clear(True)
+        box_description= wx.StaticBox(self, -1,str(title))
+        boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL)
+        #--------------------------------------------------------
+        self.shape_rbutton = wx.RadioButton(self, -1, 'Shape', style=wx.RB_GROUP)
+        self.shape_indep_rbutton = wx.RadioButton(self, -1, "Shape Independent")
+        self.struct_rbutton = wx.RadioButton(self, -1, "Structure ")
+        self.plugin_rbutton = wx.RadioButton(self, -1, "customized Model")
+        self.multip_cb = wx.CheckBox(self, -1,"P(Q)*S(Q)")
+        
+       
+        
+        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() )  
+        wx.EVT_CHECKBOX(self, self.multip_cb.GetId() , self._show_combox )              
+        ## store state
+        self.page_info.save_radiobox_state( self.shape_rbutton )
+        self.page_info.save_radiobox_state( self.shape_indep_rbutton )
+        self.page_info.save_radiobox_state( self.struct_rbutton )
+        self.page_info.save_radiobox_state( self.plugin_rbutton )
+       
+        
+        sizer_radiobutton = wx.GridSizer(3, 3,5, 5)
+        sizer_radiobutton.Add(self.shape_rbutton)
+        sizer_radiobutton.Add(self.shape_indep_rbutton)
+        sizer_radiobutton.Add(self.multip_cb)
+        sizer_radiobutton.Add(self.plugin_rbutton)
+        sizer_radiobutton.Add(self.struct_rbutton)
+        
+        sizer_selection = wx.BoxSizer(wx.HORIZONTAL)
+        
+        self.text1 = wx.StaticText( self,-1,"P(Q)" )
+        self.text2 = wx.StaticText( self,-1,"* S(Q)" )
+        
+        self.text2.Hide()
+        
+        self.formfactorbox = wx.ComboBox(self, -1)
+        if self.model!=None:
+            self.formfactorbox.SetValue(self.model.name)
+        
+        self.structurebox = wx.ComboBox(self, -1)
+        wx.EVT_COMBOBOX(self.formfactorbox,-1, self._on_select_model)
+        wx.EVT_COMBOBOX(self.structurebox,-1, self._on_select_model)
+        self.structurebox.Hide()
+        
+        ## fill combox box
+        if len(self.model_list_box)>0:
+            self._populate_box( self.formfactorbox,self.model_list_box["shapes"])
+       
+        if len(self.model_list_box)>0:
+            self._populate_box( self.structurebox,
+                                self.model_list_box["Structure Factors"])
+        
+         ## 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)
+        sizer_selection.Add((5,5))
+        
+        boxsizer1.Add( sizer_radiobutton )
+        boxsizer1.Add( (20,20))
+        boxsizer1.Add( sizer_selection )
+        if object !=None:
+            boxsizer1.Add( (20,20))
+            boxsizer1.Add( object )
+        #--------------------------------------------------------
+        sizer.Add(boxsizer1,0, wx.EXPAND | wx.ALL, 10)
+        sizer.Layout()
+        self.SetScrollbars(20,20,200,100)
+        
+        
+    def _show_combox(self, event):
+        """
+            Show combox box associate with type of model selected
+        """
+        self.page_info.save_radiobox_state( self.shape_rbutton )
+        self.page_info.save_radiobox_state( self.shape_indep_rbutton )
+        self.page_info.save_radiobox_state( self.struct_rbutton )
+        self.page_info.save_radiobox_state( self.plugin_rbutton )
+        
+        
+        
+        if self.shape_rbutton.GetValue():
+            ##fill the comboxbox with form factor list
+            self.structurebox.Hide()
+            self.text2.Hide()
+            self.formfactorbox.Clear()
+            self._populate_box( self.formfactorbox,self.model_list_box["shapes"])
+            
+        if self.shape_indep_rbutton.GetValue():
+            ##fill the comboxbox with shape independent  factor list
+            self.structurebox.Hide()
+            self.text2.Hide()
+            self.formfactorbox.Clear()
+            self._populate_box( self.formfactorbox,
+                                self.model_list_box["Shape-independent"])
+            
+        if self.struct_rbutton.GetValue():
+            ##fill the comboxbox with structure factor list
+            self.structurebox.Hide()
+            self.text2.Hide()
+            self.formfactorbox.Clear()
+            self._populate_box( self.formfactorbox,
+                                self.model_list_box["Structure Factors"])
+           
+        if self.plugin_rbutton.GetValue():
+            ##fill the comboxbox with form factor list
+            self.structurebox.Hide()
+            self.text2.Hide()
+            self.formfactorbox.Clear()
+            self._populate_box( self.formfactorbox,
+                                self.model_list_box["Added models"])
+            
+            
+        if self.multip_cb.GetValue():
+            ## multplication not available for structure factor
+            if self.struct_rbutton.GetValue():
+                self.multip_cb.SetValue(False)
+                self.structurebox.Hide()
+                return
+            ##fill the comboxbox with form factor list
+            self.structurebox.Show(True)
+            self.text2.Show(True)
+       
+        self.set_scroll()
+        
+        
+   
+            
+    def _populate_box(self, combobox, list):
+        """
+            fill combox box with dict item
+            @param list: contains item to fill the combox
+            item must model class
+        """
+        for models in list:
+            model= models()
+            name = model.__class__.__name__
+            if hasattr(model, "name"):
+                name = model.name
+            combobox.Append(name,models)
+            
+        wx.EVT_COMBOBOX(combobox,-1, self._on_select_model) 
+        return 0
+   
+   
+    def _on_select_model_helper(self,event): 
+        """
+             call back for model selection
+        """
+        f_id = self.formfactorbox.GetCurrentSelection()
+        s_id = self.structurebox.GetCurrentSelection()
+        form_factor = self.formfactorbox.GetClientData( f_id )
+        struct_factor = self.structurebox.GetClientData( s_id )
+       
+        if self.multip_cb.GetValue():
+            if struct_factor != None and struct_factor.__name__ != "NoStructure":
+                from sans.models.MultiplicationModel import MultiplicationModel
+                if form_factor != None:
+                    self.model= MultiplicationModel(form_factor(),struct_factor())
+            msg= "select one P(Q) and one S(Q) to plot"
+            wx.PostEvent(self.parent.parent, StatusEvent(status= msg))
+        else:
+            if form_factor != None:
+                self.model= form_factor()
+       
+        
+    def _onparamEnter(self,event):
+        """ 
+            when enter value on panel redraw model according to changed
+        """
+        self._onparamEnter_helper()
+        
+        
+    def _check_value_enter(self, list, modified):
+        """
+            @param list: model parameter and panel info
+            each item of the list should be as follow:
+            item=[cb state, name, value, "+/-", error of fit, min, max , units]
+        """  
+        is_modified =  modified
+        if len(list)==0:
+            return is_modified
+        for item in list:
+            try:
+                 name = str(item[1])
+                 value= float(item[2].GetValue())
+                 # If the value of the parameter has changed,
+                 # update the model and set the is_modified flag
+                 if value != self.model.getParam(name):
+                     self.model.setParam(name,value)
+                     is_modified = True    
+            except:
+                msg= "Model Drawing  Error:wrong value entered : %s"% sys.exc_value
+                wx.PostEvent(self.parent.parent, StatusEvent(status = msg ))
+                return 
+        return is_modified 
+        
+        
+ 
+    def _set_dipers_Param(self, event):
+        """
+            Add more item to select user dispersity
+        """
+        if self.model == None:
+            msg= " Select non - model value:%s !"%self.model
+            wx.PostEvent(self.parent.parent, StatusEvent(status= msg))
+            return 
+        else:
+            if self.enable_disp.GetValue():
+                self.model_disp.Show(True)
+                self.disp_box.Show(True)
+                ## layout for model containing no dispersity parameters
+                if len(self.disp_list)==0:
+                    self._layout_sizer_noDipers()  
+                else:
+                    ## set gaussian sizer 
+                    self._set_sizer_gaussian()  
+            else:
+                self.model_disp.Hide()
+                self.disp_box.Hide()
+                self.sizer4_4.Clear(True)
+                self._reset_dispersity()
+                self._draw_model()
+            
+            self.sizer4_4.Layout()
+            self.sizer4.Layout()
+            self.SetScrollbars(20,20,200,100)
+        
+        
+    def _layout_sizer_noDipers(self):
+        """
+            Draw a sizer with no dispersity info
+        """
+        ix=0
+        iy=1
+        self.fittable_param=[]
+        self.fixed_param=[]
+        self.model_disp.Hide()
+        self.disp_box.Hide()
+        self.sizer4_4.Clear(True)
+        model_disp = wx.StaticText(self, -1, 'No PolyDispersity for this model')
+        self.sizer4_4.Add(model_disp,( iy, ix),(1,1),  wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
+        self.sizer4_4.Layout()
+        self.sizer4.Layout()
+        self.SetScrollbars(20,20,200,100)
+        return 
+    
+    def _reset_gaussian_dispers(self):
+        """
+            reset model paramaters to gaussian
+            TO IMPLEMENT
+        """
+    
+        return
+        from sans.models.dispersion_models import GaussianDispersion
+        if self.model==None:
+            return
+        list= self.model.dispersion.keys()
+        for key in list:
+           
+            ## The parameter was un-selected. Go back to Gaussian model (with 0 pts)
+            disp_model = GaussianDispersion()
+            ## Set the new model as the dispersion object for the selected parameter
+            self.model.set_dispersion(key,disp_model)
+            self._draw_model()
+            
+            
+    def _reset_dispersity(self):
+        """
+             put gaussian dispersity into current model
+        """
+        self.fittable_param=[]
+        self.fixed_param=[]
+        from sans.models.dispersion_models import GaussianDispersion
+        if len(self.disp_cb_dict)==0:
+            return 
+        
+        for p in self.disp_cb_dict:
+            # The parameter was un-selected. Go back to Gaussian model (with 0 pts)
+            disp_model = GaussianDispersion()
+            # Store the object to make it persist outside the scope of this method
+            #TODO: refactor model to clean this up?
+            self._disp_obj_dict[p] = disp_model
+            
+            # Set the new model as the dispersion object for the selected parameter
+            self.model.set_dispersion(p, disp_model)
+            
+            # Redraw the model
+            
+            
+            
+    def _on_select_Disp(self,event):
+        """
+             allow selecting different dispersion
+             self.disp_list should change type later .now only gaussian
+        """
+        dispersity  =event.GetClientData()
+        name= dispersity.__name__
+        
+        if name == "GaussianModel":
+            self._set_sizer_gaussian()
+            
+        if  name=="ArrayDispersion":
+            self._set_sizer_arraydispersion()
+            
+            
+            
+    
+    def _set_sizer_arraydispersion(self):
+        """
+            draw sizer with array dispersity  parameters
+        """
+        self.sizer4_4.Clear(True) 
+        ix=0
+        iy=1     
+        disp1 = wx.StaticText(self, -1, 'Array Dispersion')
+        self.sizer4_4.Add(disp1,( iy, ix),(1,1),  wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
+        
+        # Look for model parameters to which we can apply an ArrayDispersion model
+        # Add a check box for each parameter.
+        self.disp_cb_dict = {}
+        for p in self.model.dispersion.keys():
+            ix+=1 
+            self.disp_cb_dict[p] = wx.CheckBox(self, -1, p, (10, 10))
+            
+            wx.EVT_CHECKBOX(self, self.disp_cb_dict[p].GetId(), self.select_disp_angle)
+            self.sizer4_4.Add(self.disp_cb_dict[p], (iy, ix), (1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
+        
+        ix =0
+        iy +=1 
+        self.sizer4_4.Add((20,20),(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)        
+        self.sizer4_4.Layout()
+        self.sizer4.Layout()
+        self.SetScrollbars(20,20,200,100)
+        
+        
+    def _set_range_sizer(self, title, object1=None,object=None):
+        """
+            Fill the 
+        """
+        self.sizer5.Clear(True)
+        box_description= wx.StaticBox(self, -1,str(title))
+        boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL)
+        #--------------------------------------------------------------
+        self.qmin    = wx.TextCtrl(self, -1,size=(_BOX_WIDTH,20))
+        self.qmin.SetValue(format_number(self.qmin_x))
+        self.qmin.SetToolTipString("Minimun value of Q in linear scale.")
+        self.qmin.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
+        self.qmin.Bind(wx.EVT_TEXT_ENTER, self._onparamEnter)
+     
+        self.qmax    = wx.TextCtrl(self, -1,size=(_BOX_WIDTH,20))
+        self.qmax.SetValue(format_number(self.qmax_x))
+        self.qmax.SetToolTipString("Maximum value of Q in linear scale.")
+        self.qmax.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
+        self.qmax.Bind(wx.EVT_TEXT_ENTER, self._onparamEnter)
+     
+        sizer_horizontal=wx.BoxSizer(wx.HORIZONTAL)
+        sizer= wx.GridSizer(3, 3,5, 5)
+        
+        sizer.Add((5,5))
+        sizer.Add(wx.StaticText(self, -1, 'Min'))
+        sizer.Add(wx.StaticText(self, -1, 'Max'))
+        sizer.Add(wx.StaticText(self, -1, 'Q range'))
+             
+        sizer.Add(self.qmin)
+        sizer.Add(self.qmax)
+        sizer_horizontal.Add(sizer)
+        if object!=None:
+            sizer_horizontal.Add(object)
+        
+        if object1!=None:
+           boxsizer1.Add(object1) 
+           boxsizer1.Add((10,10))
+        boxsizer1.Add(sizer_horizontal)
+       
+        #----------------------------------------------------------------
+        self.sizer5.Add(boxsizer1,0, wx.EXPAND | wx.ALL, 10)
+        self.sizer5.Layout()
+        self.SetScrollbars(20,20,200,100)
+    
+        
+                
Index: sansview/perspectives/fitting/fit_thread.py
===================================================================
--- sansview/perspectives/fitting/fit_thread.py	(revision bb18ef1c74ed79eb0630f198735ad2b14e7913ab)
+++ sansview/perspectives/fitting/fit_thread.py	(revision c77d8592395f6684cf45ee976c1cac9db9c00110)
@@ -102,6 +102,5 @@
     """Thread performing the fit """
     
-    def __init__(self,parent, fn,pars=None,cpage=None, qmin=None,qmax=None,ymin=None, ymax=None,
-                 xmin=None,xmax=None,
+    def __init__(self,parent, fn,pars=None,cpage=None, qmin=None,qmax=None,
                  completefn = None,
                  updatefn   = None,
@@ -118,10 +117,8 @@
         self.pars = pars
         self.starttime = 0
+        
         self.qmin = qmin
         self.qmax = qmax
-        self.xmin = xmin
-        self.xmax = xmax
-        self.ymin = ymin
-        self.ymax = ymax
+       
         self.done= False
         wx.PostEvent(self.parent, StatusEvent(status=\
@@ -165,8 +162,5 @@
                           qmin = self.qmin,
                           qmax = self.qmax,
-                          xmin= self.xmin,
-                          xmax= self.xmax,
-                          ymin = self.ymin,
-                          ymax = self.ymax, 
+                          
                           elapsed=elapsed )
         except KeyboardInterrupt:
Index: sansview/perspectives/fitting/fitpage.py
===================================================================
--- sansview/perspectives/fitting/fitpage.py	(revision c77d8592395f6684cf45ee976c1cac9db9c00110)
+++ sansview/perspectives/fitting/fitpage.py	(revision c77d8592395f6684cf45ee976c1cac9db9c00110)
@@ -0,0 +1,826 @@
+import sys
+import wx
+import wx.lib.newevent
+import numpy
+import copy
+import math
+from sans.models.dispersion_models import ArrayDispersion, GaussianDispersion
+
+from sans.guicomm.events import StatusEvent   
+from sans.guiframe.utils import format_number
+(ModelEventbox, EVT_MODEL_BOX) = wx.lib.newevent.NewEvent()
+_BOX_WIDTH = 80
+
+import basepage
+from basepage import BasicPage
+
+
+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, page_info, name=""):
+        BasicPage.__init__(self, parent, page_info,name)
+        """ 
+            Initialization of the Panel
+        """
+        ## fit page does not content npts txtcrtl
+        self.npts=None
+        ## if no dispersity parameters is avaible 
+        self.text_disp_1=None
+        
+        self._fill_datainfo_sizer()
+        self._fill_model_sizer( self.sizer1)
+        self._fill_range_sizer() 
+        if hasattr(self.page_info,"model"):
+            self.set_model_param_sizer(self.model)
+            
+        
+    def _on_display_description(self, event):
+        """
+            Show or Hide description
+            @param event: wx.EVT_RADIOBUTTON
+        """
+        self._on_display_description_helper()
+        
+        
+        
+    def _on_display_description_helper(self):
+        """
+            Show or Hide description
+            @param event: wx.EVT_RADIOBUTTON
+        """
+        ## save state of radiobox
+        self.page_info. save_radiobox_state( self.description_hide )
+        self.page_info. save_radiobox_state( self.description_show )
+        ## Show description
+        if not self.description_show.GetValue():
+            self.sizer_description.Clear(True)
+            
+        else:
+            model=self.page_info.model
+            description=""
+            if model!=None:
+                description = self.page_info.model.description
+            self.description = wx.StaticText( self,-1,str(description) )
+            self.sizer_description.Add( self.description, 1, wx.EXPAND | wx.ALL, 10 )
+           
+        self.Layout()
+    
+    
+    def _fill_range_sizer(self):
+        """
+            Fill the sizer containing the plotting range
+            add  access to npts
+        """
+        sizer_fit = wx.GridSizer(2, 2,0, 0)
+    
+        self.btFit = wx.Button(self,wx.NewId(),'Fit')
+        self.btFit.Bind(wx.EVT_BUTTON, self._onFit,id= self.btFit.GetId())
+        self.btFit.SetToolTipString("Perform fit.")
+        
+        self.btStopFit = wx.Button(self,wx.NewId(),'Stop Fit')
+        #self.btStopFit.Bind(wx.EVT_BUTTON, self.onStopFit,id= self.btStopFit.GetId())
+        self.btStopFit.SetToolTipString("Stop Current fit job.")
+        #self.btStopFit.Hide()
+        
+        sizer_fit.Add((5,5),1, wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 5)        
+        sizer_fit.Add((5,5))
+        sizer_fit.Add(self.btFit,1, wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 5) 
+        sizer_fit.Add(self.btStopFit,1, wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 5) 
+        
+        sizer_smearer = wx.BoxSizer(wx.HORIZONTAL)
+        #Filling the sizer containing instruments smearing info.
+        self.disable_smearer = wx.RadioButton(self, -1, 'No', style=wx.RB_GROUP)
+        self.enable_smearer = wx.RadioButton(self, -1, 'Yes')
+        self.Bind(wx.EVT_RADIOBUTTON, self.onSmear, id=self.disable_smearer.GetId())
+        self.Bind(wx.EVT_RADIOBUTTON, self.onSmear, id=self.enable_smearer.GetId())
+        
+        sizer_smearer.Add(wx.StaticText(self,-1,'Instrument Smearing? '))
+        sizer_smearer.Add((10, 10))
+        sizer_smearer.Add( self.enable_smearer )
+        sizer_smearer.Add((10,10))
+        sizer_smearer.Add( self.disable_smearer )
+        
+        self._set_range_sizer( title="Fitted Q Range",
+                               object1=sizer_smearer, object= sizer_fit)
+       
+       
+    def _fill_datainfo_sizer(self):
+        """
+            fill sizer 0 with data info
+        """
+        self.sizer0.Clear(True)
+        ## no loaded data , don't fill the sizer
+        if self.data== None:
+            self.sizer0.Layout()
+            return
+        
+        box_description= wx.StaticBox(self, -1, 'Loaded Data')
+        boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL)
+        #----------------------------------------------------------
+        sizer_data = wx.GridSizer(3, 3,5, 5)
+        #Filling the sizer containing data related fields
+        DataSource  =wx.StaticText(self, -1,str(self.data.name))
+
+        sizer_data.Add(wx.StaticText(self, -1, 'Data Source Name : '))
+        sizer_data.Add(DataSource )
+        sizer_data.Add( (5,5) )
+        
+        #---------sizer 2 draw--------------------------------
+        #set maximum range for x in linear scale
+        if not hasattr(self.data,"data"): #Display only for 1D data fit
+            # Minimum value of data   
+            data_min = str(format_number(numpy.min(self.data.x)))
+            # Maximum value of data  
+            data_max = str(format_number(numpy.max(self.data.x)))
+            text4_3 = wx.StaticText(self, -1, 'Maximum Q Range(Linear)',
+                                     style=wx.ALIGN_LEFT)
+            sizer_data.Add( text4_3 )
+            sizer_data.Add(wx.StaticText(self, -1, "Min : %s"%data_min))
+            sizer_data.Add(wx.StaticText(self, -1, "Max : %s"%data_max))
+            
+        else:
+            radius_min= 0
+            x= numpy.max(self.data.xmin, self.data.xmax)
+            y= numpy.max(self.data.ymin, self.data.ymax)
+            radius_max = math.sqrt(x*x + y*y)
+            # Minimum value of data   
+            data_min = str(format_number(radius_min))
+            # Maximum value of data  
+            data_max = str(format_number(radius_max))
+            text4_3 = wx.StaticText(self, -1, 'Maximum Q Range',
+                                     style=wx.ALIGN_LEFT)
+            sizer_data.Add( text4_3 )
+            sizer_data.Add(wx.StaticText(self, -1, "Min : %s"%data_min))
+            sizer_data.Add(wx.StaticText(self, -1, "Max : %s"%data_max))
+            
+        boxsizer1.Add(sizer_data)
+        #------------------------------------------------------------
+        self.sizer0.Add(boxsizer1,0, wx.EXPAND | wx.ALL, 10)
+        self.sizer0.Layout()
+        
+        self.qmin_x= data_min
+        self.qmax_x= data_max
+        
+    def _fill_model_sizer(self, sizer):
+        """
+            fill sizer containing model info
+        """
+        sizer_tcChi = wx.GridSizer(2, 2,5, 5)
+        self.tcChi    =  wx.StaticText(self, -1, str(0), style=wx.ALIGN_LEFT)
+        #self.tcChi.Hide()
+        
+        self.text1_1 = wx.StaticText(self, -1, 'Chi2/dof', style=wx.ALIGN_LEFT)
+        #self.text1_1.Hide()
+        
+        self.btChi = wx.Button(self,wx.NewId(),'View Chi')
+        self.btChi.Bind(wx.EVT_BUTTON, self._onFit,id= self.btChi.GetId())
+        self.btChi.SetToolTipString("View data - model.")
+        
+        sizer_tcChi.Add(self.text1_1,1, wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 5)
+        sizer_tcChi.Add(self.btChi,1, wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 5)        
+        sizer_tcChi.Add(self.tcChi,1, wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 5)        
+        sizer_tcChi.Add((5,5),1, wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 5)
+            
+        ## class base method  to add view 2d button    
+        self._set_model_sizer(sizer=sizer, title="Model",object=  sizer_tcChi )    
+    
+    
+    def _set_sizer_gaussian(self):
+        """
+            draw sizer with gaussian dispersity parameters
+        """
+        self.fittable_param=[]
+        self.fixed_param=[]
+        ##reset model dispersity to gaussian
+        self._reset_gaussian_dispers()
+        
+        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 
+        ix=0
+        iy=1
+        disp = wx.StaticText(self, -1, 'Names')
+        self.sizer4_4.Add(disp,( iy, ix),(1,1), 
+                           wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
+        ix += 1 
+        values = wx.StaticText(self, -1, 'Values')
+        self.sizer4_4.Add(values,( iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
+        ix +=2 
+        self.text_disp_1 = wx.StaticText(self, -1, 'Errors')
+        self.sizer4_4.Add( self.text_disp_1,(iy, ix),(1,1),\
+                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
+        self.text_disp_1.Hide()
+        ix += 1 
+        npts = wx.StaticText(self, -1, 'Npts')
+        self.sizer4_4.Add(npts,( iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
+        ix += 1 
+        nsigmas = wx.StaticText(self, -1, 'Nsigmas')
+        self.sizer4_4.Add(nsigmas,( iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
+       
+        for item in self.model.dispersion.keys():
+            name1=item+".width"
+            name2=item+".npts"
+            name3=item+".nsigmas"
+            iy += 1
+            for p in self.model.dispersion[item].keys():
+    
+                if p=="width":
+                    ix = 0
+                    cb = wx.CheckBox(self, -1, name1, (10, 10))
+                    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, 15)
+                    ix = 1
+                    value= self.model.getParam(name1)
+                    ctl1 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20),
+                                        style=wx.TE_PROCESS_ENTER)
+                    
+                    ctl1.SetValue(str (format_number(value)))
+                    ctl1.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
+                    ctl1.Bind(wx.EVT_TEXT_ENTER,self._onparamEnter)
+                    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() 
+                    ## txtcrtl to add error from fit
+                    ix = 3
+                    ctl2 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20), style=wx.TE_PROCESS_ENTER)
+                    self.sizer4_4.Add(ctl2, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
+                    ctl2.Hide()
+                    
+                    self.fittable_param.append([cb,name1,ctl1,text2,
+                                                ctl2, None, None,None])
+                elif p=="npts":
+                        ix = 4
+                        value= self.model.getParam(name2)
+                        Tctl = wx.TextCtrl(self, -1, size=(_BOX_WIDTH/2,20),
+                                            style=wx.TE_PROCESS_ENTER)
+                        
+                        Tctl.SetValue(str (format_number(value)))
+                        Tctl.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
+                        Tctl.Bind(wx.EVT_TEXT_ENTER,self._onparamEnter)
+                        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 = 5
+                        value= self.model.getParam(name3)
+                        Tctl = wx.TextCtrl(self, -1, size=(_BOX_WIDTH/2,20),
+                                            style=wx.TE_PROCESS_ENTER)
+                        Tctl.SetValue(str (format_number(value)))
+                        Tctl.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
+                        Tctl.Bind(wx.EVT_TEXT_ENTER,self._onparamEnter)
+                        self.sizer4_4.Add(Tctl, (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, Tctl
+                                                 ,None,None, None, None,None])
+                
+        wx.PostEvent(self.parent, StatusEvent(status=\
+                        " Selected Distribution: Gaussian"))   
+        ix =0
+        iy +=1 
+        self.sizer4_4.Add((20,20),(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)        
+        self.sizer4_4.Layout()
+        self.sizer4.Layout()
+        self.SetScrollbars(20,20,200,100)
+        
+    def _onFit(self, event):     
+        """
+            Allow to fit
+        """
+        from sans.guiframe.utils import check_value
+        flag = check_value( self.qmin, self.qmax) 
+        
+        if not flag:
+            msg= "Fitting range invalid"
+            wx.PostEvent(self.parent.parent, StatusEvent(status= msg ))
+            return 
+        
+        if len(self.param_toFit) <= 0:
+            msg= "Select at least one parameter to fit"
+            wx.PostEvent(self.parent.parent, StatusEvent(status= msg ))
+            return 
+        
+        self.qmin_x=float(self.qmin.GetValue())
+        self.qmax_x =float( self.qmax.GetValue())
+        
+        self.manager.schedule_for_fit( value=1,fitproblem =None) 
+       
+        #single fit 
+        self.manager.on_single_fit(qmin=self.qmin_x,qmax=self.qmax_x)
+            
+        self.sizer5.Layout()
+        self.SetScrollbars(20,20,55,40)
+        
+        
+    def _on_select_model(self, event): 
+        """
+             call back for model selection
+        """    
+        self._on_select_model_helper(event) 
+        self.set_model_param_sizer(self.model)
+        self._set_sizer_gaussian()
+        
+        evt = ModelEventbox(model=self.model)
+        wx.PostEvent(self.event_owner, evt)   
+        try:
+            self.compute_chisqr()
+            self.text1_1.Show()
+            self.tcChi.Show()
+        except:
+            ## error occured on chisqr computation
+            pass
+        
+        
+        
+    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:
+            raise ValueError,"missing parameter to fit"    
+      
+    def onsetValues(self,chisqr, out,cov):
+        """
+            Build the panel from the fit result
+            @param chisqr:Value of the goodness of fit metric
+            @param out:list of parameter with the best value found during fitting
+            @param cov:Covariance matrix
+       
+        """
+        self.tcChi.SetLabel(format_number(chisqr))
+        params = {}
+        is_modified = False
+        has_error = False
+        #set the panel when fit result are float not list
+        if out.__class__==numpy.float64:
+            self.param_toFit[0][2].SetValue(format_number(out))
+            self.param_toFit[0][2].Refresh()
+            if cov !=None :
+                self.text2_3.Show(True)
+                if self.text_disp_1!=None:
+                    self.text_disp_1.Show(True)
+                    
+                self.param_toFit[0][3].Show(True)
+                self.param_toFit[0][4].Clear()
+                self.param_toFit[0][4].SetValue(format_number(cov[0]))
+                self.param_toFit[0][4].Show(True)
+        else:
+            i=0
+            j=0
+            #Set the panel when fit result are list
+            for item in self.param_toFit:
+                if( out != None ) and len(out)<=len(self.param_toFit)and i < len(out):
+                    item[2].SetValue(format_number(self.model.getParam(item[1])))
+                    item[2].Refresh()
+                if(cov !=None)and len(cov)<=len(self.param_toFit)and i < len(cov):
+                    self.text2_3.Show(True) 
+                    if self.text_disp_1!=None:
+                        self.text_disp_1.Show(True)
+                    item[3].Show(True)
+                    item[4].Clear()
+                    for j in range(len(out)):
+                        if out[j]==self.model.getParam(item[1]):
+                            break
+                    item[4].SetValue(format_number(cov[j]))
+                    item[4].Refresh()
+                    item[4].Show(True)   
+                i+=1
+        
+        self.sizer3.Layout()
+        self.sizer4_4.Layout()
+        self.sizer4.Layout()
+        self.SetScrollbars(20,20,200,100)
+        
+        
+      
+    def onSmear(self, event):
+        """
+            Create a smear object that will change the way residuals
+            are compute when fitting
+        """
+        smear =None
+        msg=""
+        if self.enable_smearer.GetValue():
+            from DataLoader.qsmearing import smear_selection
+            smear =smear_selection( self.data )
+            if hasattr(self.data,"dxl"):
+                msg= ": Resolution smearing parameters"
+            if hasattr(self.data,"dxw"):
+                msg= ": Slit smearing parameters"
+            if smear ==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 %s"%msg))
+        self.manager.set_smearer(smear, qmin= self.qmin_x, qmax= self.qmax_x)   
+              
+        
+        
+    def compute_chisqr2D(self):
+        """ 
+            compute chi square given a model and data 2D and set the value
+            to the tcChi txtcrl
+        """
+        from sans.guiframe.utils import check_value
+        flag = check_value( self.qmin, self.qmax)
+       
+        res=[]
+        if flag== True:
+            try:
+                self.qmin_x = float(self.qmin.GetValue())
+                self.qmax_x = float(self.qmax.GetValue())
+                for i in range(len(self.data.x_bins)):
+                    for j in range(len(self.data.y_bins)):
+                        #Check the range containing data between self.qmin_x and self.qmax_x
+                        if math.pow(self.data.x_bins[i],2)+math.pow(self.data.y_bins[j],2)>=math.pow(self.qmin_x,2):
+                            if math.pow(self.data.x_bins[i],2)+math.pow(self.data.y_bins[j],2)<=math.pow(self.qmax_x,2):
+                                chisqrji=(self.data.data[j][i]- self.model.runXY(\
+                                                                                    [self.data.y_bins[j],self.data.x_bins[i]]))\
+                                                                                    /self.data.err_data[j][i]
+                                #Vector containing residuals
+                                res.append( math.pow(chisqrji,2) )
+                # compute sum of residual
+                sum=0
+                for item in res:
+                    if numpy.isfinite(item):
+                        sum +=item
+                self.tcChi.SetLabel(format_number(math.fabs(sum/ len(res))))
+            except:
+                wx.PostEvent(self.parent.GrandParent, StatusEvent(status=\
+                            "Chisqr cannot be compute: %s"% sys.exc_value))
+                return
+    
+        
+    def compute_chisqr(self):
+        """ 
+            compute chi square given a model and data 1D and set the value
+            to the tcChi txtcrl
+        """
+        from sans.guiframe.utils import check_value
+        flag = check_value( self.qmin, self.qmax)
+       
+        if flag== True:
+            try:
+                if hasattr(self.data,"data"):
+                    self.compute_chisqr2D()
+                    return
+                else:
+                    self.qmin_x = float(self.qmin.GetValue())
+                    self.qmax_x = float(self.qmax.GetValue())
+                    # return residuals within self.qmin_x and self.qmax_x
+                    x,y,dy = [numpy.asarray(v) for v in (self.data.x,self.data.y,self.data.dy)]
+                    if self.qmin_x==None and self.qmax_x==None: 
+                        fx =numpy.asarray([self.model.run(v) for v in x])
+                        temp=(y - fx)/dy
+                        res= temp*temp
+                    else:
+                        idx = (x>= self.qmin_x) & (x <=self.qmax_x)
+                        fx = numpy.asarray([self.model.run(item)for item in x[idx ]])
+                        temp=(y[idx] - fx)/dy[idx]
+                        res= temp*temp
+                    #sum of residuals
+                    sum=0
+                    for item in res:
+                        if numpy.isfinite(item):
+                            sum +=item
+                    self.tcChi.SetLabel(format_number(math.fabs(sum/ len(res))))
+            except:
+                wx.PostEvent(self.parent.GrandParent, StatusEvent(status=\
+                            "Chisqr cannot be compute: %s"% sys.exc_value))
+                return 
+            
+    
+    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()==True:
+                for item in self.parameters:
+                    item[0].SetValue(True)
+                    self.param_toFit.append(item )
+                if len(self.fittable_param)>0:
+                    for item in self.fittable_param:
+                        item[0].SetValue(True)
+                        self.param_toFit.append(item )
+            else:
+                for item in self.parameters:
+                    item[0].SetValue(False)
+                for item in self.fittable_param:
+                    item[0].SetValue(False)
+                self.param_toFit=[]
+               
+                
+                
+    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:
+            #Select parameters to fit for list of primary parameters
+            if item[0].GetValue()==True:
+                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:
+            if item[0].GetValue()==True:
+                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)           
+        #Set the value of checkbox that selected every checkbox or not            
+        if len(self.parameters)+len(self.fittable_param) ==len(self.param_toFit):
+            self.cb1.SetValue(True)
+        else:
+            self.cb1.SetValue(False)
+    
+    
+    def set_model_description(self,description,sizer):
+        """
+            fill a sizer with description
+            @param description: of type string
+            @param sizer: wx.BoxSizer()
+        """
+    
+        sizer.Clear(True)
+        box_description= wx.StaticBox(self, -1, 'Model Description')
+        boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL)
+                
+        self.description = wx.StaticText( self,-1,str(description) )
+        sizer_selection=wx.BoxSizer(wx.HORIZONTAL)
+        
+        
+        self.description_show = wx.RadioButton(self, -1, 'Show', style=wx.RB_GROUP)
+        self.description_hide = wx.RadioButton(self, -1, 'Hide')
+        
+        self.Bind( wx.EVT_RADIOBUTTON, self._on_display_description,
+                   id=self.description_hide.GetId() )
+        
+        self.Bind( wx.EVT_RADIOBUTTON, self._on_display_description,
+                   id=self.description_show.GetId() )
+        
+        self.model_description = wx.Button(self, -1, "More Details")
+     
+        
+        self.page_info.save_radiobox_state( self.description_hide )
+        self.page_info.save_radiobox_state( self.description_show )
+        
+        sizer_selection.Add( self.description_show )
+        sizer_selection.Add( (20,20)) 
+        sizer_selection.Add( self.description_hide )
+        sizer_selection.Add( (20,20)) 
+        sizer_selection.Add( self.model_description )
+        
+         
+        self.sizer_description=wx.BoxSizer(wx.HORIZONTAL)
+        self.sizer_description.Add( self.description, 1, wx.EXPAND | wx.ALL, 10 )
+       
+        boxsizer1.Add( sizer_selection) 
+        boxsizer1.Add( (20,20)) 
+        boxsizer1.Add( self.sizer_description) 
+    
+
+        sizer.Add(boxsizer1,0, wx.EXPAND | wx.ALL, 10)
+        sizer.Layout()
+   
+   
+        
+        
+    def set_model_param_sizer(self, model, engine_type="park"):
+        """
+            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.param_toFit=[]
+        self.fittable_param=[]
+        self.fixed_param=[]
+        
+        if model ==None:
+            self.sizer3.Layout()
+            self.SetScrollbars(20,20,200,100)
+            return
+        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()
+       
+        keys.sort()
+    
+        iy = 1
+        ix = 0
+        self.cb1 = wx.CheckBox(self, -1,"Select all", (10, 10))
+        wx.EVT_CHECKBOX(self, self.cb1.GetId(), self.select_all_param)
+        self.cb1.SetValue(False)
+        
+        sizer.Add(self.cb1,(iy, ix),(1,1),\
+                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
+        ix +=1
+        self.text2_2 = wx.StaticText(self, -1, 'Values')
+        sizer.Add(self.text2_2,(iy, ix),(1,1),\
+                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
+        ix +=2 
+        self.text2_3 = wx.StaticText(self, -1, 'Errors')
+        sizer.Add(self.text2_3,(iy, ix),(1,1),\
+                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
+        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()
+        if  engine_type == "park":
+            self.text2_max.Show(True)
+            self.text2_min.Show(True)
+
+        for item in keys:
+            if not item in self.disp_list:
+                iy += 1
+                ix = 0
+                ## add parameters name with checkbox for selecting to fit
+                cb = wx.CheckBox(self, -1, item )
+                cb.SetValue(False)
+                wx.EVT_CHECKBOX(self, cb.GetId(), self.select_param)
+                sizer.Add( cb,( iy, ix),(1,1),
+                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
+                ## add parameter value
+                ix += 1
+                value= self.model.getParam(item)
+                ctl1 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20),
+                                    style=wx.TE_PROCESS_ENTER)
+                
+                ctl1.SetValue(str (format_number(value)))
+                ctl1.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
+                ctl1.Bind(wx.EVT_TEXT_ENTER,self._onparamEnter)
+                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() 
+                ## txtcrtl to add error from fit
+                ix += 1
+                ctl2 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20), style=wx.TE_PROCESS_ENTER)
+                sizer.Add(ctl2, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
+                ctl2.Hide()
+                
+                ix += 1
+                ctl3 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH/2,20), style=wx.TE_PROCESS_ENTER)
+                ctl3.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
+                ctl3.Bind(wx.EVT_TEXT_ENTER,self._onparamEnter)
+                sizer.Add(ctl3, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
+                ctl3.Hide()
+                
+                ix += 1
+                ctl4 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH/2,20), style=wx.TE_PROCESS_ENTER)
+                ctl4.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
+                ctl4.Bind(wx.EVT_TEXT_ENTER,self._onparamEnter)
+                sizer.Add(ctl4, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
+                ctl4.Hide()
+                if  engine_type == "park":
+                    ctl3.Show(True)
+                    ctl4.Show(True)
+                    
+                ix +=1
+                # Units
+                try:
+                    units = wx.StaticText(self, -1, self.model.details[item][0], style=wx.ALIGN_LEFT)
+                except:
+                    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,None])
+                
+        iy+=1
+        sizer.Add((20,20),(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
+        
+        #Display units text on panel
+        for item in keys:   
+            if self.model.details[item][0]!='':
+                self.text2_4.Show()
+                break
+            else:
+                self.text2_4.Hide()
+    
+        boxsizer1.Add(sizer)
+        
+        self.sizer3.Add(boxsizer1,0, wx.EXPAND | wx.ALL, 10)
+        self.sizer3.Layout()
+        self.SetScrollbars(20,20,200,100)
+        
+    
+            
+        
+class HelpWindow(wx.Frame):
+    def __init__(self, parent, id, title):
+        wx.Frame.__init__(self, parent, id, title, size=(570, 400))
+       
+        from sans.models.CylinderModel import CylinderModel
+        model = CylinderModel()
+        #from sans.models.LineModel import LineModel
+        #model = LineModel()
+        from danse.common.plottools.plottables import Data1D
+        data= Data1D(x=[1,2], y=[3,4], dy=[0.1, 0,1])
+    
+        from pageInfo import PageInfo
+        myinfo = PageInfo(self,  model, data=data )
+        
+        ## add data
+        
+        from models import ModelList
+        mylist= ModelList()
+
+        from sans.models.SphereModel import SphereModel
+        from sans.models.SquareWellStructure import SquareWellStructure
+        from sans.models.DebyeModel import DebyeModel
+        from sans.models.LineModel import LineModel
+        name= "shapes"
+        list1= [SphereModel]
+        mylist.set_list( name, list1)
+        
+        name= "Shape-independent"
+        list1= [DebyeModel]
+        mylist.set_list( name, list1)
+        
+        name= "Structure Factors"
+        list1= [SquareWellStructure]
+        mylist.set_list( name, list1)
+        
+        name= "Added models"
+        list1= [LineModel]
+        mylist.set_list( name, list1)
+        
+        myinfo.model_list_box = mylist.get_list()
+        
+        self.page = FitPage(self, myinfo) 
+        
+        
+        
+        self.Centre()
+        self.Show(True)
+
+
+   
+if __name__=="__main__":
+    app = wx.App()
+    HelpWindow(None, -1, 'HelpWindow')
+    app.MainLoop()
+                
Index: sansview/perspectives/fitting/fitpage1D.py
===================================================================
--- sansview/perspectives/fitting/fitpage1D.py	(revision bb18ef1c74ed79eb0630f198735ad2b14e7913ab)
+++ 	(revision )
@@ -1,613 +1,0 @@
-import sys
-import wx
-import wx.lib
-import numpy,math
-import copy
-
-from sans.guicomm.events import StatusEvent 
-from sans.guiframe.utils import format_number
-from modelpage import ModelPage  
-from modelpage import format_number
-(ModelEventbox, EVT_MODEL_BOX) = wx.lib.newevent.NewEvent()
-_BOX_WIDTH = 80
-
-
-#TODO: FitPage1D inherits from ModelPage but doesn't call its __init__ method!
-#TODO: refactor this class to have an __init__ that deals with data only, then calls a UI builder method.
-
-class FitPage1D(ModelPage):
-    """
-        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.
-    """
-    ## Internal name for the AUI manager
-    window_name = "Fit page"
-    ## Title to appear on top of the window
-    window_caption = "Fit Page"
-    
-    name=None
-    
-    def __init__(self, parent,data, *args, **kwargs):
-        wx.ScrolledWindow.__init__(self, parent, *args, **kwargs)
-        
-        """ 
-            Initialization of the Panel
-        """
-        #TODO: remove this once the inheritence is cleaned up
-        ## Data member to store the dispersion object created
-        self._disp_obj_dict = {}
-
-        #Data used for fitting 
-        self.data = data
-        # flag to allow data2D plot
-        self.enable2D=False
-        #fit page manager 
-        self.manager = None
-        #Store the parent of this panel parent
-        # For this application fitpanel is the parent
-        self.parent  = parent
-        # Event_owner is the owner of model event
-        self.event_owner = None
-        #panel interface
-        self.vbox  = wx.BoxSizer(wx.VERTICAL)
-    
-        self.sizer9 = wx.GridBagSizer(5,5)
-        self.sizer8 = wx.GridBagSizer(5,5)
-        self.sizer7 = wx.GridBagSizer(5,5)
-        self.sizer6 = wx.GridBagSizer(5,5)
-        self.sizer5 = wx.GridBagSizer(5,5)
-        self.sizer4 = wx.GridBagSizer(5,5)
-        self.sizer3 = wx.GridBagSizer(5,5)
-        self.sizer2 = wx.GridBagSizer(5,5)
-        self.sizer1 = wx.GridBagSizer(5,5)
-        # Add layer
-        #data info layer
-        self.vbox.Add(self.sizer1)
-        #data range 
-        self.vbox.Add(self.sizer2)
-        #instrument smearing selection layer
-        self.vbox.Add(self.sizer3)
-        #model selection
-        self.vbox.Add(wx.StaticLine(self, -1), 0, wx.EXPAND, 0)
-        self.vbox.Add(self.sizer4)
-        #model paramaters layer
-        self.vbox.Add(self.sizer5)
-        #polydispersion selected
-        self.vbox.Add(wx.StaticLine(self, -1), 0, wx.EXPAND, 0)
-        self.vbox.Add(self.sizer6)
-        #combox box for type of dispersion
-        self.vbox.Add(self.sizer7)
-        #dispersion parameters layer
-        self.vbox.Add(self.sizer8)
-        #fit info layer
-        self.vbox.Add(wx.StaticLine(self, -1), 0, wx.EXPAND, 0)
-        self.vbox.Add(self.sizer9)
-        #---------sizer 1 draw--------------------------------
-        #Filling the sizer containing data related fields
-        self.DataSource  =wx.StaticText(self, -1,str(data.name))
-        ix = 0
-        iy = 1
-        self.sizer1.Add(wx.StaticText(self, -1, 'Data Source Name : '),(iy,ix),\
-                 (1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
-        ix += 1
-        self.sizer1.Add(self.DataSource,(iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-        
-        #---------sizer 2 draw--------------------------------
-        #set maximum range for x in linear scale
-        if not hasattr(self.data,"data"): #Display only for 1D data fit
-            ix = 0
-            iy = 1
-            # Minimum value of data   
-            self.data_min    = wx.StaticText(self, -1,str(format_number(numpy.min(data.x))))
-            # Maximum value of data  
-            self.data_max    =  wx.StaticText(self, -1,str(format_number(numpy.max(data.x))))   
-            self.text4_3 = wx.StaticText(self, -1, 'Maximum Data Range(Linear)', style=wx.ALIGN_LEFT)
-            self.sizer2.Add(self.text4_3,(iy,ix),(1,1),\
-                   wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
-            ix += 2
-            self.sizer2.Add(wx.StaticText(self, -1, 'Min :'),(iy, ix),(1,1),\
-                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-            ix += 1
-            self.sizer2.Add(self.data_min,(iy, ix),(1,1),\
-                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-            ix += 1
-            self.sizer2.Add(wx.StaticText(self, -1, 'Max : '),(iy, ix),(1,1),\
-                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-            ix += 1
-            self.sizer2.Add(self.data_max,(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-        
-        #----sizer 3 draw--------------------------------
-        #Filling the sizer containing instruments smearing info.
-        self.disable_smearer = wx.RadioButton(self, -1, 'No', (10, 10), style=wx.RB_GROUP)
-        self.enable_smearer = wx.RadioButton(self, -1, 'Yes', (10, 30))
-        self.Bind(wx.EVT_RADIOBUTTON, self.onSmear, id=self.disable_smearer.GetId())
-        self.Bind(wx.EVT_RADIOBUTTON, self.onSmear, id=self.enable_smearer.GetId())
-        ix = 0
-        iy = 1
-        self.sizer3.Add(wx.StaticText(self,-1,'Instrument Smearing'),(iy,ix),(1,1)\
-                  , wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
-        ix += 1
-        self.sizer3.Add(self.enable_smearer,(iy,ix),(1,1),  wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-        ix += 1
-        self.sizer3.Add(self.disable_smearer,(iy,ix),(1,1),  wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-        ix =0
-        iy+=1
-        self.sizer3.Add((20,20),(iy,ix),(1,1),wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)  
-            
-        #------------------ sizer 4  draw------------------------   
-        # This sizer contains model list and chisqr value 
-        #filling sizer4
-        ## structure combox box
-        self.structbox = wx.ComboBox(self, -1)
-        # define combox box
-        self.modelbox = wx.ComboBox(self, -1)
-        
-        self.tcChi    =  wx.StaticText(self, -1, str(0), style=wx.ALIGN_LEFT)
-        self.tcChi.Hide()
-        self.text1_1 = wx.StaticText(self, -1, 'Chi2/dof', style=wx.ALIGN_LEFT)
-        self.text1_1.Hide()
-        ix = 0
-        iy = 1
-        self.sizer4.Add(wx.StaticText(self,-1,'Model'),(iy,ix),(1,1)\
-                  , wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
-        
-        ix += 1
-        self.sizer4.Add(self.modelbox,(iy,ix),(1,1),  wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-        ix +=1
-        self.text_mult= wx.StaticText(self,-1,' x ')
-        self.sizer4.Add(self.text_mult,(iy,ix),(1,1),  wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-        ix += 1
-        self.sizer4.Add(self.structbox,(iy,ix),(1,1),  wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-        
-        
-        
-        ix += 1
-        self.sizer4.Add(self.text1_1,(iy,ix),(1,1),\
-                   wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
-        ix += 1
-        self.sizer4.Add(self.tcChi,(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-        #----------sizer6-------------------------------------------------
-        #Sizer containing info on polydispersity
-        self.disable_disp = wx.RadioButton(self, -1, 'No', (10, 10), style=wx.RB_GROUP)
-        self.enable_disp = wx.RadioButton(self, -1, 'Yes', (10, 30))
-        self.Bind(wx.EVT_RADIOBUTTON, self.Set_DipersParam, id=self.disable_disp.GetId())
-        self.Bind(wx.EVT_RADIOBUTTON, self.Set_DipersParam, id=self.enable_disp.GetId())
-        ix= 0
-        iy=1
-        self.sizer6.Add(wx.StaticText(self,-1,'Polydispersity: '),(iy,ix),(1,1)\
-                  , wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
-        ix += 1
-        self.sizer6.Add(self.enable_disp ,(iy,ix),(1,1),  wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-        ix += 1
-        self.sizer6.Add(self.disable_disp ,(iy,ix),(1,1),  wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-        ix =0
-        iy+=1
-        self.sizer6.Add((20,20),(iy,ix),(1,1),wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)  
-        #---------sizer 9 draw----------------------------------------
-        
-        
-        id = wx.NewId()
-        self.btFit =wx.Button(self,id,'Fit')
-        self.btFit.Bind(wx.EVT_BUTTON, self.onFit,id=id)
-        self.btFit.SetToolTipString("Perform fit.")
-        ## Q range
-        # Reversed to the codes; Need to think  carefully about consistency in q between 2D plot and fitting
-        if not hasattr(self.data,"data"):
-            self.qmin_x= numpy.min(self.data.x)
-            self.qmax_x= numpy.max(self.data.x)
-            self.num_points= len(self.data.x)
-        else:
-            # Reversed to the codes; Need to think  carefully about consistency in q between 2D plot and fitting
-            radius1= math.sqrt(math.pow(self.data.xmin, 2)+ math.pow(self.data.ymin, 2))
-            radius2= math.sqrt(math.pow(self.data.xmax, 2)+ math.pow(self.data.ymin, 2))
-            radius3= math.sqrt(math.pow(self.data.xmin, 2)+ math.pow(self.data.ymax, 2))
-            radius4= math.sqrt(math.pow(self.data.xmax, 2)+ math.pow(self.data.ymax, 2))
-            
-            self.qmin_x= 0
-            self.qmax_x= math.sqrt(math.pow(max(math.fabs(self.data.xmax),math.fabs(self.data.xmin)),2)
-                            +math.pow(max(math.fabs(self.data.ymax),math.fabs(self.data.ymin)),2))#self.data.xmax           
-        
-        self.num_points= 100
-        # The minimum fitting range
-        self.qmin    = wx.TextCtrl(self, -1,size=(_BOX_WIDTH,20))
-        self.qmin.SetValue(str(format_number(self.qmin_x)))
-        self.qmin.SetToolTipString("Minimun value of x in linear scale.")
-        self.qmin.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
-        self.qmin.Bind(wx.EVT_TEXT_ENTER, self._onparamEnter)
-        self.qmin.Enable()
-        #The maximum fitting range
-        self.qmax    = wx.TextCtrl(self, -1,size=(_BOX_WIDTH,20))
-        self.qmax.SetValue(str(format_number(self.qmax_x)))
-        self.qmax.SetToolTipString("Maximum value of x in linear scale.")
-        self.qmax.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
-        self.qmax.Bind(wx.EVT_TEXT_ENTER, self._onparamEnter)
-        self.qmax.Enable()
-        #The number of points to plots
-        self.npts    = wx.TextCtrl(self, -1,size=(_BOX_WIDTH,20))
-        self.npts.SetValue(format_number(self.num_points))
-        self.npts.SetToolTipString("Number of point to plot.")
-        self.npts.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
-        self.npts.Bind(wx.EVT_TEXT_ENTER, self._onparamEnter)
-        self.npts.Disable()
-        self.npts.Hide()
-        ix = 0
-        iy = 1 
-        self.sizer9.Add(wx.StaticText(self, -1, 'Fitting Range'),(iy, ix),(1,1),\
-                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
-        ix += 1 
-        self.sizer9.Add(wx.StaticText(self, -1, 'Min'),(iy, ix),(1,1),\
-                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-        ix += 1
-        self.sizer9.Add(wx.StaticText(self, -1, 'Max'),(iy, ix),(1,1),\
-                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-        ix = 0
-        iy += 1
-        self.sizer9.Add(wx.StaticText(self, -1, 'Q range'),(iy, ix),(1,1),\
-                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
-        ix += 1
-        self.sizer9.Add(self.qmin,(iy, ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-        ix += 1
-        self.sizer9.Add(self.qmax,(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-        ix += 1
-        self.sizer9.Add(self.npts,(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-        
-        ix += 1
-        self.sizer9.Add(self.btFit,(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-       
-        ix =0
-        iy+=1 
-        self.sizer9.Add((20,20),(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-        
-        # Contains link between  model ,all its parameters, and panel organization
-        self.parameters=[]
-        # Contains list of parameters that cannot be fitted and reference to 
-        #panel objects 
-        self.fixed_param=[]
-        # Contains list of parameters with dispersity and reference to 
-        #panel objects 
-        self.fittable_param=[]
-        #list of dispersion paramaters
-        self.disp_list=[]
-        #contains link between a model and selected parameters to fit 
-        self.param_toFit=[]
-        # model on which the fit would be performed
-        self.model=None
-       
-        self.back_up_model= None
-        #dictionary of model name and model class
-        self.model_list_box={}    
-                     
-        if self.model == None:
-            self.qmin.Disable()
-            self.qmax.Disable() 
-        else:
-            self.qmin.Enable()
-            self.qmax.Enable() 
-
-    
-        self.vbox.Layout()
-        self.vbox.Fit(self) 
-        self.SetSizer(self.vbox)
-        self.SetScrollbars(20,20,55,40)
-        
-        self.Centre()
-        self.Layout()
-        
-        self.parent.GetSizer().Layout()
-   
-    def compute_chisqr2D(self):
-        """ 
-            compute chi square given a model and data 2D and set the value
-            to the tcChi txtcrl
-        """
-        from sans.guiframe.utils import check_value
-        flag = check_value( self.qmin, self.qmax)
-        #flag=self.checkFitRange()
-        res=[]
-        if flag== True:
-            try:
-                self.qmin_x = float(self.qmin.GetValue())
-                self.qmax_x = float(self.qmax.GetValue())
-                for i in range(len(self.data.x_bins)):
-                    for j in range(len(self.data.y_bins)):
-                        #Check the range containing data between self.qmin_x and self.qmax_x
-                        if math.pow(self.data.x_bins[i],2)+math.pow(self.data.y_bins[j],2)>=math.pow(self.qmin_x,2):
-                            if math.pow(self.data.x_bins[i],2)+math.pow(self.data.y_bins[j],2)<=math.pow(self.qmax_x,2):
-                                chisqrji=(self.data.data[j][i]- self.model.runXY(\
-                                                                                    [self.data.y_bins[j],self.data.x_bins[i]]))\
-                                                                                    /self.data.err_data[j][i]
-                                #Vector containing residuals
-                                res.append( math.pow(chisqrji,2) )
-                # compute sum of residual
-                sum=0
-                for item in res:
-                    if numpy.isfinite(item):
-                        sum +=item
-                self.tcChi.SetLabel(format_number(math.fabs(sum/ len(res))))
-            except:
-                wx.PostEvent(self.parent.GrandParent, StatusEvent(status=\
-                            "Chisqr cannot be compute: %s"% sys.exc_value))
-                return
-    
-        
-    def compute_chisqr(self):
-        """ 
-            compute chi square given a model and data 1D and set the value
-            to the tcChi txtcrl
-        """
-        from sans.guiframe.utils import check_value
-        flag = check_value( self.qmin, self.qmax)
-        #flag=self.checkFitRange()
-        if flag== True:
-            try:
-                if hasattr(self.data,"data"):
-                    self.compute_chisqr2D()
-                    return
-                else:
-                    self.qmin_x = float(self.qmin.GetValue())
-                    self.qmax_x = float(self.qmax.GetValue())
-                    # return residuals within self.qmin_x and self.qmax_x
-                    x,y,dy = [numpy.asarray(v) for v in (self.data.x,self.data.y,self.data.dy)]
-                    if self.qmin_x==None and self.qmax_x==None: 
-                        fx =numpy.asarray([self.model.run(v) for v in x])
-                        temp=(y - fx)/dy
-                        res= temp*temp
-                    else:
-                        idx = (x>= self.qmin_x) & (x <=self.qmax_x)
-                        fx = numpy.asarray([self.model.run(item)for item in x[idx ]])
-                        temp=(y[idx] - fx)/dy[idx]
-                        res= temp*temp
-                    #sum of residuals
-                    sum=0
-                    for item in res:
-                        if numpy.isfinite(item):
-                            sum +=item
-                    self.tcChi.SetLabel(format_number(math.fabs(sum/ len(res))))
-            except:
-                wx.PostEvent(self.parent.GrandParent, StatusEvent(status=\
-                            "Chisqr cannot be compute: %s"% sys.exc_value))
-                return 
-            
-    def _on_select_model(self,event):
-        """
-            react when a model is selected from page's combo box
-            post an event to its owner to draw an appropriate theory
-        """
-        self.btFit.SetFocus()
-        self.disable_disp.SetValue(True)
-        self.sizer8.Clear(True)
-        self.sizer7.Clear(True)       
-        self.vbox.Layout()
-        self.SetScrollbars(20,20,55,40)
-        self.Layout()
-        self.parent.GetSizer().Layout()
-
-       
-        name= self.modelbox.GetString(self.modelbox.GetCurrentSelection())
-        form_factor =self.modelbox.GetClientData(self.modelbox.GetCurrentSelection())
-        struct_factor =self.structbox.GetClientData(self.structbox.GetCurrentSelection())
-       
-      
-        if form_factor!="separator":
-            if struct_factor != None and struct_factor.__name__ != "NoStructure":
-                from sans.models.MultiplicationModel import MultiplicationModel
-                self.model= MultiplicationModel(form_factor(),struct_factor())
-            else:
-                 self.model= form_factor() 
-            self.back_up_model= self.model.clone()
-            name= self.model.name
-            if name == None:
-                self.qmin.Disable()
-                self.qmax.Disable() 
-            else:
-                self.qmin.Enable()
-                self.qmax.Enable() 
-            evt = ModelEventbox(model=self.model,name=name)
-            wx.PostEvent(self.event_owner, evt)   
-            self.text1_1.Show()
-            self.tcChi.Show()
-            self.compute_chisqr()
-        
-            
-        else:
-            self.model=None 
-            msg= " Select non - model value:%s ! Previous Model reloaded "%name 
-            wx.PostEvent(self.parent.parent, StatusEvent(status= msg))
-            
-        self.set_panel(self.model)
-            
-                 
-    def onFit(self,event):
-        """ 
-            signal for fitting .Perform single fit only
-        """
-        from sans.guiframe.utils import check_value
-        flag = check_value( self.qmin, self.qmax) 
-        
-        if not flag:
-            msg= "Fitting range invalid"
-            wx.PostEvent(self.parent.parent, StatusEvent(status= msg ))
-            return 
-        
-        if len(self.param_toFit) <= 0:
-            msg= "Select at least one parameter to fit"
-            wx.PostEvent(self.parent.parent, StatusEvent(status= msg ))
-            return 
-        
-        self.qmin_x=float(self.qmin.GetValue())
-        self.qmax_x =float( self.qmax.GetValue())
-        
-        self.manager.schedule_for_fit( value=1,fitproblem =None) 
-        if hasattr(self.data, "data"):
-            #single fit for Data2D
-            self.manager._on_single_fit(qmin=self.qmin_x,qmax=self.qmax_x,
-                                        ymin=self.data.ymin, ymax=self.data.ymax,
-                                        xmin=self.data.xmin,xmax=self.data.xmax)
-        else:
-            #single fit for Data1D
-            self.manager._on_single_fit(qmin=self.qmin_x,qmax=self.qmax_x)
-                
-            self.vbox.Layout()
-            self.SetScrollbars(20,20,55,40)
-            self.Layout()
-            self.parent.GetSizer().Layout()
-        
-            
-  
-   
-    
-    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:
-            raise ValueError,"missing parameter to fit"
-        
-    
-    def _onparamEnter(self,event):
-        """ 
-            when enter value on panel redraw model according to changed
-        """
-        self.set_model()
-        try:
-            self.compute_chisqr()
-        except:
-            pass
-        
-    def set_model(self): 
-        """
-            Hide panel object related to the previous fit and set
-            values entered by the used inside the model
-        """
-        if len(self.parameters) !=0 and self.model !=None:
-            # Flag to register when a parameter has changed.
-            for item in self.parameters:
-                try:
-                    self.text2_3.Hide()
-                    item[2].Hide()
-                    item[3].Clear()
-                    item[3].Hide()
-                except:
-                    pass
-        self.set_model_parameter()
-        
-    
-    def select_all_param(self,event): 
-        """
-             set to true or false all checkBox given the main checkbox value cb1
-        """
-        self.select_all_param_helper()
-                
-                
-    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:
-            #Select parameters to fit for list of primary parameters
-            if item[0].GetValue()==True:
-                list= [item[0],item[1],item[2],item[3]]
-                if not (list  in self.param_toFit):
-                    self.param_toFit.append(list )  
-            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:
-            if item[0].GetValue()==True:
-                list= [item[0],item[1],item[2],item[3]]
-                if not (list  in self.param_toFit):
-                    self.param_toFit.append(list )  
-            else:
-                #remove parameters from the fitting list
-                if item in self.param_toFit:
-                    self.param_toFit.remove(item)           
-        #Set the value of checkbox that selected every checkbox or not            
-        if len(self.parameters)+len(self.fittable_param) ==len(self.param_toFit):
-            self.cb1.SetValue(True)
-        else:
-            self.cb1.SetValue(False)
-       
-       
-    def onsetValues(self,chisqr, out,cov):
-        """
-            Build the panel from the fit result
-            @param chisqr:Value of the goodness of fit metric
-            @param out:list of parameter with the best value found during fitting
-            @param cov:Covariance matrix
-       
-        """
-        self.tcChi.SetLabel(format_number(chisqr))
-        params = {}
-        is_modified = False
-        has_error = False
-        #set the panel when fit result are float not list
-        if out.__class__==numpy.float64:
-            self.param_toFit[0][1].SetValue(format_number(out))
-            self.param_toFit[0][1].Refresh()
-            if cov !=None :
-                self.text2_3.Show()
-                self.param_toFit[0][2].Show()
-                self.param_toFit[0][3].Clear()
-                self.param_toFit[0][3].SetValue(format_number(cov[0]))
-                self.param_toFit[0][3].Show()
-        else:
-            i=0
-            j=0
-            #Set the panel when fit result are list
-            for item in self.param_toFit:
-                if( out != None ) and len(out)<=len(self.param_toFit)and i < len(out):
-                    item[1].SetValue(format_number(self.model.getParam(item[0].GetLabelText())))
-                    item[1].Refresh()
-                if(cov !=None)and len(cov)<=len(self.param_toFit)and i < len(cov):
-                    self.text2_3.Show() 
-                    item[2].Show()
-                    item[3].Clear()
-                    for j in range(len(out)):
-                        if out[j]==self.model.getParam(item[0].GetLabelText()):
-                            break
-                    item[3].SetValue(format_number(cov[j]))
-                    item[3].Show()   
-                i+=1
-        
-        self.vbox.Layout()
-        self.SetScrollbars(20,20,55,40)
-        self.Layout()
-        self.GrandParent.GetSizer().Layout()
-        
-        
-    def onSmear(self, event):
-        """
-            Create a smear object that will change the way residuals
-            are compute when fitting
-        """
-        smear =None
-        msg=""
-        if self.enable_smearer.GetValue():
-            from DataLoader.qsmearing import smear_selection
-            smear =smear_selection( self.data )
-            if hasattr(self.data,"dxl"):
-                msg= ": Resolution smearing parameters"
-            if hasattr(self.data,"dxw"):
-                msg= ": Slit smearing parameters"
-            if smear ==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 %s"%msg))
-        self.manager.set_smearer(smear)   
-            
-              
-        
-       
Index: sansview/perspectives/fitting/fitpanel.py
===================================================================
--- sansview/perspectives/fitting/fitpanel.py	(revision bb18ef1c74ed79eb0630f198735ad2b14e7913ab)
+++ sansview/perspectives/fitting/fitpanel.py	(revision c77d8592395f6684cf45ee976c1cac9db9c00110)
@@ -40,6 +40,5 @@
         #dictionary of miodel {model class name, model class}
         self.model_list_box={}
-        ## list of structure factor
-        self.struct_list_box=[]
+       
         # save the title of the last page tab added
         self.fit_page_name=[]
@@ -103,6 +102,21 @@
             @param owner: the class responsible of plotting
         """
-        self.event_owner=owner
-        
+        self.event_owner = owner
+    
+    def set_model_list(self,dict):
+         """ 
+             copy a dictionary of model into its own dictionary
+             @param dict: dictionnary made of model name as key and model class
+             as value
+         """
+         self.model_list_box = dict
+        
+  
+    def get_current_page(self):
+        """
+            @return the current page selected
+        """
+        return self.GetPage(self.GetSelection() )
+    
     def add_sim_page(self):
         """
@@ -125,8 +139,12 @@
         except:
             name = 'Fit'
+        from pageInfo import  PageInfo
+        myinfo = PageInfo( self, data=data )
+        myinfo.model_list_box = self.model_list_box.get_list()
+        myinfo.event_owner =self.event_owner 
         
         if not name in self.fit_page_name :
-            from fitpage1D import FitPage1D
-            panel = FitPage1D(self,data, -1)
+            from fitpage import FitPage
+            panel = FitPage(parent= self, page_info=myinfo, name=name )
             panel.name=name
             
@@ -135,5 +153,5 @@
             
             self.AddPage(page=panel,caption=name,select=True)
-            panel.populate_box( self.model_list_box)
+            #panel.populate_box( self.model_list_box)
             self.fit_page_name.append(name)
     
@@ -150,11 +168,18 @@
             @param npts: number of Q points
         """
+        ## storing page info
+        from pageInfo import  PageInfo
+        myinfo = PageInfo( self, model )
+        myinfo.model_list_box = self.model_list_box.get_list()
+        myinfo.event_owner =self.event_owner
+        
         from modelpage import ModelPage
-        #print "fitpanel model", model
-        panel = ModelPage(self,model,page_title, -1)
+        panel = ModelPage(self,myinfo,page_title)
         panel.set_manager(self.manager)
         panel.set_owner(self.event_owner)
+        
+        
         self.AddPage(page=panel,caption="Model",select=True)
-        panel.populate_box( self.model_list_box)
+        #panel.populate_box( self.model_list_box)
         panel.name = page_title
         self.draw_model_name=page_title
@@ -168,41 +193,6 @@
         # We just created a model page, we are ready to plot the model
         #self.manager.draw_model(model, model.name)
-        #FOR PLUGIN  for somereason model.name is = BASEcomponent
-        self.manager.draw_model(model, page_title)
-        
-    def new_help_add_model_page(self,model,description,page_title, qmin=0, qmax=0.1, npts=50):
-        """
-            #TODO: fill in description
-            
-            @param qmin: mimimum Q
-            @param qmax: maximum Q
-            @param npts: number of Q points
-        """
-        ## storing page info
-        from pageInfo import  PageInfo
-        myinfo = PageInfo( self, model )
-        myinfo.model_list_box = self.model_list_box
-        from modelpage import ModelPage
-        
-        panel = ModelPage(self,myinfo,page_title)
-        panel.set_manager(self.manager)
-        panel.set_owner(self.event_owner)
-        
-        
-        self.AddPage(page=panel,caption="Model",select=True)
-        panel.populate_box( self.model_list_box)
-        panel.name = page_title
-        self.draw_model_name=page_title
-        self.model_page_number=self.GetSelection()
-        self.model_page=self.GetPage(self.GetSelection())
-        
-        
-        # Set the range used to plot models
-        self.model_page.set_range(qmin, qmax, npts)
-        
-        # We just created a model page, we are ready to plot the model
-        #self.manager.draw_model(model, model.name)
         #FOR PLUGIN  for some reason model.name is = BASEcomponent
-        self.manager.draw_model(model, page_title)
+        self.manager.draw_model(model)
      
         
@@ -226,19 +216,6 @@
                 self.model_page.select_model(model, page_title)
           
-    def get_current_page(self):
-        """
-            @return the current page selected
-        """
-        #return self.nb.GetCurrentPage()
-        return self.GetPage(self.GetSelection() )
+   
   
-    
-     
-    def set_model_list(self,dict):
-         """ 
-             copy a dictionary of model into its own dictionary
-             @param dict: dictionnary made of model name as key and model class
-             as value
-         """
-         self.model_list_box = dict
-  
+   
+ 
Index: sansview/perspectives/fitting/fitting.py
===================================================================
--- sansview/perspectives/fitting/fitting.py	(revision bb18ef1c74ed79eb0630f198735ad2b14e7913ab)
+++ sansview/perspectives/fitting/fitting.py	(revision c77d8592395f6684cf45ee976c1cac9db9c00110)
@@ -14,5 +14,5 @@
 from fit_thread import FitThread
 import models
-import fitpage1D
+import fitpage
 
 DEFAULT_BEAM = 0.005
@@ -22,5 +22,18 @@
 import time
 import thread
-
+class PlotInfo:
+    """
+        store some plotting field
+    """
+    _xunit = 'A^{-1}'
+    _xaxis= "\\rm{Q}"
+    _yunit = "cm^{-1}"
+    _yaxis= "\\rm{Intensity} "
+    id = "Model"
+    group_id = "Model"
+    title= None
+    info= None
+    
+    
 class Plugin:
     """
@@ -40,5 +53,8 @@
         self.mypanels=[]
         # reference to the current running thread
-        self.calc_thread = None
+        self.calc_2D= None
+        self.calc_1D= None
+        self.calc_fit= None
+        
         # Start with a good default
         self.elapsed = 0.022
@@ -60,10 +76,5 @@
         self.err_dy={}
         
-    def _on_data_error(self, event):
-        """
-            receives and event from plotting plu-gins to store the data name and 
-            their errors of y coordinates for 1Data hide and show error
-        """
-        self.err_dy= event.err_dy
+   
         
     def populate_menu(self, id, owner):
@@ -79,4 +90,5 @@
         self.menu1.Append(id1, '&Simultaneous')
         wx.EVT_MENU(owner, id1, self.on_add_sim_page)
+        self.menu1.AppendSeparator()
         #Set park engine
         id3 = wx.NewId()
@@ -84,5 +96,5 @@
         self.menu1.Append(id3, "Scipy",scipy_help) 
         wx.EVT_MENU(owner, id3,  self._onset_engine_scipy)
-        
+        self.menu1.AppendSeparator()
         id3 = wx.NewId()
         park_help = "Park Engine: Perform Complex fit. More in Help window...."
@@ -99,5 +111,5 @@
         self.fit_panel.set_owner(owner)
         self.fit_panel.set_model_list(self.menu_mng.get_model_list())
-        owner.Bind(fitpage1D.EVT_MODEL_BOX,self._on_model_panel)
+        owner.Bind(fitpage.EVT_MODEL_BOX,self._on_model_panel)
         
         #create  menubar items
@@ -168,25 +180,4 @@
 
         
-    def _on_slicer_event(self, event):
-        """
-            Receive a panel as event and send it to guiframe 
-            @param event: event containing a panel
-        """
-        if event.panel!=None:
-            new_panel = event.panel
-            # Set group ID if available
-            event_id = self.parent.popup_panel(new_panel)
-            self.menu1.Append(event_id, new_panel.window_caption, 
-                             "Show %s plot panel" % new_panel.window_caption)
-            # Set UID to allow us to reference the panel later
-            new_panel.uid = event_id
-            new_panel
-            self.mypanels.append(new_panel) 
-        return    
-    
-        
-    def _on_show_panel(self, event):
-        print "_on_show_panel: fitting"
-      
       
     def get_perspective(self):
@@ -240,4 +231,336 @@
 
 
+   
+                    
+    def schedule_for_fit(self,value=0,fitproblem =None):  
+        """
+            Set the fit problem field to 0 or 1 to schedule that problem to fit.
+            Schedule the specified fitproblem or get the fit problem related to 
+            the current page and set value.
+            @param value : integer 0 or 1 
+            @param fitproblem: fitproblem to schedule or not to fit
+        """   
+        if fitproblem !=None:
+            fitproblem.schedule_tofit(value)
+        else:
+            current_pg=self.fit_panel.get_current_page() 
+            for page, val in self.page_finder.iteritems():
+                if page ==current_pg :
+                    val.schedule_tofit(value)
+                    break
+                      
+                    
+    def get_page_finder(self):
+        """ @return self.page_finder used also by simfitpage.py"""  
+        return self.page_finder 
+    
+    
+    def set_page_finder(self,modelname,names,values):
+        """
+             Used by simfitpage.py to reset a parameter given the string constrainst.
+             @param modelname: the name ot the model for with the parameter has to reset
+             @param value: can be a string in this case.
+             @param names: the paramter name
+             @note: expecting park used for fit.
+        """  
+        sim_page= self.sim_page
+        for page, value in self.page_finder.iteritems():
+            if page != sim_page:
+                list=value.get_model()
+                model = list[0]
+                if model.name== modelname:
+                    value.set_model_param(names,values)
+                    break
+
+   
+                            
+    def split_string(self,item): 
+        """
+            receive a word containing dot and split it. used to split parameterset
+            name into model name and parameter name example:
+            paramaterset (item) = M1.A
+            @return model_name =M1 , parameter name =A
+        """
+        if string.find(item,".")!=-1:
+            param_names= re.split("\.",item)
+            model_name=param_names[0]
+            param_name=param_names[1]  
+            return model_name,param_name
+        
+   
+    def stop_fit(self):
+        """
+            Stop the fit engine
+        """
+        if self.calc_fit!= None and self.calc_thread.isrunning():
+            self.calc_thread.stop()
+            wx.PostEvent(self.parent, StatusEvent(status="Fitting  \
+                is cancelled" , type="stop"))
+            
+      
+    def on_single_fit(self,id=None,qmin=None, qmax=None):
+        """ 
+            perform fit for the  current page  and return chisqr,out and cov
+            @param engineName: type of fit to be performed
+            @param id: unique id corresponding to a fit problem(model, set of data)
+            @param model: model to fit
+            
+        """
+        #set an engine to perform fit
+        from sans.fit.Fitting import Fit
+        self.fitter = Fit(self._fit_engine)
+        #Setting an id to store model and data in fit engine
+        self.fit_id = 0
+        if id!=None:
+            self.fit_id = id
+        
+        page_fitted = None
+        fit_problem = None
+        #Get information (model , data) related to the page on 
+        #with the fit will be perform
+        current_pg= self.fit_panel.get_current_page() 
+        simul_pg= self.sim_page
+        pars=[]   
+        ## Check that the current page is different from self.sim_page
+        if current_pg != simul_pg:
+            value = self.page_finder[current_pg]
+            metadata =  value.get_fit_data()
+            list = value.get_model()
+            model = list[0]
+            smearer = value.get_smearer()
+           
+            #Create list of parameters for fitting used
+            templist=[]
+            try:
+                ## get the list of parameter names to fit
+                templist = current_pg.get_param_list()
+            
+                for element in templist:
+                    pars.append(str(element[1]))
+    
+                pars.sort()
+                #Do the single fit
+                self.fitter.set_model(Model(model), self.fit_id, pars)
+                dy=[]
+                x=[]
+                y=[]
+                ## checking the validity of error
+                if metadata.__class__ in  ["Data1D","Theory1D"]:
+                    for i in range(len(metadata.dy)):
+                        if metadata.dy[i] !=0:
+                            dy.append(metadata.dy[i])
+                            x.append(metadata.x[i])
+                            y.append(metadata.y[i])
+                    if len(dy)>0:        
+                        metadata.dy=numpy.zeros(len(dy))
+                        metadata.dy=dy
+                        metadata.y=numpy.zeros(len(y))
+                        metadata.y=y
+                        metadata.x=numpy.zeros(len(x))
+                        metadata.x=x
+               
+                self.fitter.set_data(data=metadata,Uid=self.fit_id,
+                                     smearer=smearer,qmin= qmin,qmax=qmax )
+                
+                self.fitter.select_problem_for_fit(Uid= self.fit_id,
+                                                   value= value.get_scheduled())
+                page_fitted=current_pg
+               
+            except:
+                msg= "Single Fit error: %s" % sys.exc_value
+                wx.PostEvent(self.parent, StatusEvent(status= msg ))
+                return
+            # make sure to keep an alphabetic order 
+            #of parameter names in the list      
+            try:
+                ## If a thread is already started, stop it
+                if self.calc_fit!= None and self.calc_fit.isrunning():
+                    self.calc_fit.stop()
+                        
+                self.calc_fit=FitThread(parent =self.parent,
+                                            fn= self.fitter,
+                                            pars= pars,
+                                            cpage= page_fitted,
+                                           qmin=qmin,
+                                           qmax=qmax,
+                                          
+                                           completefn=self._single_fit_completed,
+                                           updatefn=None)
+                self.calc_fit.queue()
+                self.calc_fit.ready(2.5)
+             
+            except:
+                wx.PostEvent(self.parent, StatusEvent(status="Single Fit error: %s" % sys.exc_value))
+                return
+         
+    def on_simul_fit(self, id=None,qmin=None,qmax=None):
+        """ 
+            perform fit for all the pages selected on simpage and return chisqr,out and cov
+            @param engineName: type of fit to be performed
+            @param id: unique id corresponding to a fit problem(model, set of data)
+             in park_integration
+            @param model: model to fit
+            
+        """
+        ##Setting an id to store model and data
+        self.fit_id= 0
+        #Setting an id to store model and data
+        if id!=None:
+             self.fit_id= id
+        ##  count the number of fitproblem schedule to fit 
+        fitproblem_count= 0
+        for value in self.page_finder.itervalues():
+            if value.get_scheduled()==1:
+                fitproblem_count += 1
+        ## if simultaneous fit change automatically the engine to park
+        if fitproblem_count >1:
+            self._on_change_engine(engine='park')
+        from sans.fit.Fitting import Fit
+        self.fitter= Fit(self._fit_engine)
+        
+        
+        for page, value in self.page_finder.iteritems():
+            try:
+                if value.get_scheduled()==1:
+                    metadata = value.get_fit_data()
+                    list = value.get_model()
+                    model= list[0]
+                    ## store page
+                    cpage= page
+                    #Get list of parameters name to fit
+                    pars = []
+                    templist = []
+                    templist = page.get_param_list()
+                    for element in templist:
+                        try:
+                            name = str(element[0].GetLabelText())
+                            pars.append(name)
+                        except:
+                            wx.PostEvent(self.parent, StatusEvent(status="Simultaneous Fit error: %s" % sys.exc_value))
+                            return
+                    ## create a park model and reset parameter value if constraint
+                    ## is given
+                    new_model=Model(model)
+                    param=value.get_model_param()
+                    
+                    if len(param)>0:
+                        for item in param:
+                            param_value = item[1]
+                            param_name = item[0]
+    
+                            new_model.parameterset[ param_name].set( param_value )
+                        
+                    self.fitter.set_model(new_model, self.fit_id, pars) 
+                    ## check that non -zero value are send as dy in the fit engine
+                    dy=[]
+                    x=[]
+                    y=[]
+                    if metadata.__class__ in  ["Data1D","Theory1D"]:
+                        for i in range(len(metadata.dy)):
+                            if metadata.dy[i] !=0:
+                                dy.append(metadata.dy[i])
+                                x.append(metadata.x[i])
+                                y.append(metadata.y[i])
+                            if len(dy)>0:        
+                                metadata.dy=numpy.zeros(len(dy))
+                                metadata.dy=dy
+                                metadata.y=numpy.zeros(len(y))
+                                metadata.y=y
+                                metadata.x=numpy.zeros(len(x))
+                                metadata.x=x
+                                
+                    self.fitter.set_data(metadata,self.fit_id,qmin,qmax)
+                    self.fitter.select_problem_for_fit(Uid= self.fit_id,
+                                                       value= value.get_scheduled())
+                    self.fit_id += 1 
+                    value.clear_model_param()
+                   
+            except:
+                msg= "Simultaneous Fit error: %s" % sys.exc_value
+                wx.PostEvent(self.parent, StatusEvent(status= msg ))
+                return 
+            
+        #Do the simultaneous fit
+        try:
+            ## If a thread is already started, stop it
+            if self.calc_fit!= None and self.calc_fit.isrunning():
+                self.calc_fit.stop()
+			## perform single fit
+            if  fitproblem_count==1:
+                self.calc_fit=FitThread(parent =self.parent,
+                                        fn= self.fitter,
+                                       qmin=qmin,
+                                       qmax=qmax,
+                                       ymin= ymin,
+                                       ymax= ymax,
+                                       cpage=cpage,
+                                       pars= pars,
+                                       completefn= self._simul_fit_completed,
+                                       updatefn=None)
+                      
+            else:
+                ## Perform more than 1 fit at the time
+                self.calc_fit=FitThread(parent =self.parent,
+                                        fn= self.fitter,
+                                       qmin=qmin,
+                                       qmax=qmax,
+                                       ymin= ymin,
+                                       ymax= ymax,
+                                       completefn= self._simul_fit_completed,
+                                       updatefn=None)
+            self.calc_fit.queue()
+            self.calc_fit.ready(2.5)
+            
+        except:
+            msg= "Simultaneous Fit error: %s" % sys.exc_value
+            wx.PostEvent(self.parent, StatusEvent(status= msg ))
+            return
+      
+    def  set_smearer(self,smearer, qmin=None, qmax=None):
+        """
+            Get a smear object and store it to a fit problem
+            @param smearer: smear object to allow smearing data
+        """   
+        current_pg=self.fit_panel.get_current_page()
+        self.page_finder[current_pg].set_smearer(smearer)
+        ## draw model 1D with smeared data
+        data =  self.page_finder[current_pg].get_plotted_data()
+        list = self.page_finder[current_pg].get_model()
+        model = list[0]
+        smearer = value.get_smearer()
+        self.draw_model( model=model, data= data, smearer= smearer,
+                qmin= qmin, qmax= qmax)
+    
+    
+    
+    def draw_model(self, model, data= None,smearer= None,
+                   enable1D= True, enable2D= False,
+                   qmin= DEFAULT_QMIN, qmax= DEFAULT_QMAX, qstep= DEFAULT_NPTS):
+        """
+             Draw model.
+             @param model: the model to draw
+             @param name: the name of the model to draw
+             @param data: the data on which the model is based to be drawn
+             @param description: model's description
+             @param enable1D: if true enable drawing model 1D
+             @param enable2D: if true enable drawing model 2D
+             @param qmin:  Range's minimum value to draw model
+             @param qmax:  Range's maximum value to draw model
+             @param qstep: number of step to divide the x and y-axis
+             
+        """
+        ## draw model 1D with no loaded data
+        self._draw_model1D( model= model, data= data,enable1D=enable1D, smearer= smearer,
+                           qmin= qmin, qmax= qmax, qstep= qstep )
+        ## draw model 2D with no initial data
+        self._draw_model2D(model=model,
+                           data = data,
+                           enable2D= enable2D,
+                           qmin=qmin,
+                           qmax=qmax,
+                           qstep=qstep)
+          
+  
+  
     def _onSelect(self,event):
         """ 
@@ -284,64 +607,6 @@
                     %sys.exc_value))
                     return
-                    
-                    
-    def schedule_for_fit(self,value=0,fitproblem =None):  
-        """
-            Set the fit problem field to 0 or 1 to schedule that problem to fit.
-            Schedule the specified fitproblem or get the fit problem related to 
-            the current page and set value.
-            @param value : integer 0 or 1 
-            @param fitproblem: fitproblem to schedule or not to fit
-        """   
-        if fitproblem !=None:
-            fitproblem.schedule_tofit(value)
-        else:
-            current_pg=self.fit_panel.get_current_page() 
-            for page, val in self.page_finder.iteritems():
-                if page ==current_pg :
-                    val.schedule_tofit(value)
-                    break
-                      
-                    
-    def get_page_finder(self):
-        """ @return self.page_finder used also by simfitpage.py"""  
-        return self.page_finder 
-    
-    
-    def set_page_finder(self,modelname,names,values):
-        """
-             Used by simfitpage.py to reset a parameter given the string constrainst.
-             @param modelname: the name ot the model for with the parameter has to reset
-             @param value: can be a string in this case.
-             @param names: the paramter name
-             @note: expecting park used for fit.
-        """  
-        sim_page= self.sim_page
-        for page, value in self.page_finder.iteritems():
-            if page != sim_page:
-                list=value.get_model()
-                model = list[0]
-                if model.name== modelname:
-                    value.set_model_param(names,values)
-                    break
-
-   
-                            
-    def split_string(self,item): 
-        """
-            receive a word containing dot and split it. used to split parameterset
-            name into model name and parameter name example:
-            paramaterset (item) = M1.A
-            @return model_name =M1 , parameter name =A
-        """
-        if string.find(item,".")!=-1:
-            param_names= re.split("\.",item)
-            model_name=param_names[0]
-            param_name=param_names[1]  
-            return model_name,param_name
-        
-   
-    def _single_fit_completed(self,result,pars,cpage,qmin,qmax,elapsed=None,
-                              ymin=None, ymax=None, xmin=None, xmax=None):
+    
+    def _single_fit_completed(self,result,pars,cpage,qmin,qmax,elapsed=None):
         """
             Display fit result on one page of the notebook.
@@ -371,7 +636,9 @@
             cpage.onsetValues(result.fitness, result.pvec,result.stderr)
             ## plot the current model with new param
-            self.plot_helper(currpage=cpage,qmin=qmin,qmax=qmax,
-                             ymin=ymin, ymax=ymax,
-                             xmin=xmin, xmax=xmax,title=None)
+            metadata =  self.page_finder[cpage].get_fit_data()
+            list = self.page_finder[cpage].get_model()
+            model = list[0]
+            self.draw_model( model=model, data= metadata,qmin= qmin, qmax= qmax)
+            
         except:
             msg= "Single Fit completed but Following error occurred:"
@@ -429,233 +696,10 @@
                  return 
              
-             
-    def stop_fit(self):
-        """
-            Stop the fit engine
-        """
-        if self.calc_thread != None and self.calc_thread.isrunning():
-            self.calc_thread.stop()
-            wx.PostEvent(self.parent, StatusEvent(status="Fitting  \
-                is cancelled" , type="stop"))
-            
-            
-    def _on_single_fit(self,id=None,qmin=None, qmax=None,ymin=None, ymax=None,xmin=None,xmax=None):
-        """ 
-            perform fit for the  current page  and return chisqr,out and cov
-            @param engineName: type of fit to be performed
-            @param id: unique id corresponding to a fit problem(model, set of data)
-            @param model: model to fit
-            
-        """
-        #set an engine to perform fit
-        from sans.fit.Fitting import Fit
-        self.fitter = Fit(self._fit_engine)
-        #Setting an id to store model and data in fit engine
-        self.fit_id = 0
-        if id!=None:
-            self.fit_id = id
-        
-        page_fitted = None
-        fit_problem = None
-        #Get information (model , data) related to the page on 
-        #with the fit will be perform
-        current_pg= self.fit_panel.get_current_page() 
-        simul_pg= self.sim_page
-        pars=[]   
-        ## Check that the current page is different from self.sim_page
-        if current_pg != simul_pg:
-            value = self.page_finder[current_pg]
-            metadata =  value.get_fit_data()
-            list = value.get_model()
-            model = list[0]
-            smearer = value.get_smearer()
-           
-            #Create list of parameters for fitting used
-            templist=[]
-            try:
-                ## get the list of parameter names to fit
-                templist = current_pg.get_param_list()
-                for element in templist:
-                    pars.append(str(element[0].GetLabelText()))
-                pars.sort()
-                 
-                #Do the single fit
-                self.fitter.set_model(Model(model), self.fit_id, pars)
-                dy=[]
-                x=[]
-                y=[]
-                ## checking the validity of error
-                if metadata.__class__ in  ["Data1D","Theory1D"]:
-                    for i in range(len(metadata.dy)):
-                        if metadata.dy[i] !=0:
-                            dy.append(metadata.dy[i])
-                            x.append(metadata.x[i])
-                            y.append(metadata.y[i])
-                    if len(dy)>0:        
-                        metadata.dy=numpy.zeros(len(dy))
-                        metadata.dy=dy
-                        metadata.y=numpy.zeros(len(y))
-                        metadata.y=y
-                        metadata.x=numpy.zeros(len(x))
-                        metadata.x=x
-                        
-                self.fitter.set_data(data=metadata,Uid=self.fit_id,
-                                     smearer=smearer,qmin= qmin,qmax=qmax,
-                                     ymin=ymin,ymax=ymax)
-                
-                self.fitter.select_problem_for_fit(Uid= self.fit_id,
-                                                   value= value.get_scheduled())
-                page_fitted=current_pg
-               
-            except:
-                msg= "Single Fit error: %s" % sys.exc_value
-                wx.PostEvent(self.parent, StatusEvent(status= msg ))
-                return
-            # make sure to keep an alphabetic order 
-            #of parameter names in the list      
-            try:
-                ## If a thread is already started, stop it
-                if self.calc_thread != None and self.calc_thread.isrunning():
-                    self.calc_thread.stop()
-                        
-                self.calc_thread =FitThread(parent =self.parent,
-                                            fn= self.fitter,
-                                            pars= pars,
-                                            cpage= page_fitted,
-                                           qmin=qmin,
-                                           qmax=qmax,
-                                          
-                                           completefn=self._single_fit_completed,
-                                           updatefn=None)
-                self.calc_thread.queue()
-                self.calc_thread.ready(2.5)
-             
-            except:
-                wx.PostEvent(self.parent, StatusEvent(status="Single Fit error: %s" % sys.exc_value))
-                return
-         
-    def _on_simul_fit(self, id=None,qmin=None,qmax=None, ymin=None, ymax=None):
-        """ 
-            perform fit for all the pages selected on simpage and return chisqr,out and cov
-            @param engineName: type of fit to be performed
-            @param id: unique id corresponding to a fit problem(model, set of data)
-             in park_integration
-            @param model: model to fit
-            
-        """
-        ##Setting an id to store model and data
-        self.fit_id= 0
-        #Setting an id to store model and data
-        if id!=None:
-             self.fit_id= id
-        ##  count the number of fitproblem schedule to fit 
-        fitproblem_count= 0
-        for value in self.page_finder.itervalues():
-            if value.get_scheduled()==1:
-                fitproblem_count += 1
-        ## if simultaneous fit change automatically the engine to park
-        if fitproblem_count >1:
-            self._on_change_engine(engine='park')
-        from sans.fit.Fitting import Fit
-        self.fitter= Fit(self._fit_engine)
-        
-        
-        for page, value in self.page_finder.iteritems():
-            try:
-                if value.get_scheduled()==1:
-                    metadata = value.get_fit_data()
-                    list = value.get_model()
-                    model= list[0]
-                    ## store page
-                    cpage= page
-                    #Get list of parameters name to fit
-                    pars = []
-                    templist = []
-                    templist = page.get_param_list()
-                    for element in templist:
-                        try:
-                            name = str(element[0].GetLabelText())
-                            pars.append(name)
-                        except:
-                            wx.PostEvent(self.parent, StatusEvent(status="Simultaneous Fit error: %s" % sys.exc_value))
-                            return
-                    ## create a park model and reset parameter value if constraint
-                    ## is given
-                    new_model=Model(model)
-                    param=value.get_model_param()
-                    
-                    if len(param)>0:
-                        for item in param:
-                            param_value = item[1]
-                            param_name = item[0]
-    
-                            new_model.parameterset[ param_name].set( param_value )
-                        
-                    self.fitter.set_model(new_model, self.fit_id, pars) 
-                    ## check that non -zero value are send as dy in the fit engine
-                    dy=[]
-                    x=[]
-                    y=[]
-                    if metadata.__class__ in  ["Data1D","Theory1D"]:
-                        for i in range(len(metadata.dy)):
-                            if metadata.dy[i] !=0:
-                                dy.append(metadata.dy[i])
-                                x.append(metadata.x[i])
-                                y.append(metadata.y[i])
-                            if len(dy)>0:        
-                                metadata.dy=numpy.zeros(len(dy))
-                                metadata.dy=dy
-                                metadata.y=numpy.zeros(len(y))
-                                metadata.y=y
-                                metadata.x=numpy.zeros(len(x))
-                                metadata.x=x
-                                
-                    self.fitter.set_data(metadata,self.fit_id,qmin,qmax,ymin,ymax)
-                    self.fitter.select_problem_for_fit(Uid= self.fit_id,
-                                                       value= value.get_scheduled())
-                    self.fit_id += 1 
-                    value.clear_model_param()
-                   
-            except:
-                msg= "Simultaneous Fit error: %s" % sys.exc_value
-                wx.PostEvent(self.parent, StatusEvent(status= msg ))
-                return 
-            
-        #Do the simultaneous fit
-        try:
-            ## If a thread is already started, stop it
-            if self.calc_thread != None and self.calc_thread.isrunning():
-                self.calc_thread.stop()
-			## perform single fit
-            if  fitproblem_count==1:
-                self.calc_thread =FitThread(parent =self.parent,
-                                        fn= self.fitter,
-                                       qmin=qmin,
-                                       qmax=qmax,
-                                       ymin= ymin,
-                                       ymax= ymax,
-                                       cpage=cpage,
-                                       pars= pars,
-                                       completefn= self._simul_fit_completed,
-                                       updatefn=None)
-                      
-            else:
-                ## Perform more than 1 fit at the time
-                self.calc_thread =FitThread(parent =self.parent,
-                                        fn= self.fitter,
-                                       qmin=qmin,
-                                       qmax=qmax,
-                                       ymin= ymin,
-                                       ymax= ymax,
-                                       completefn= self._simul_fit_completed,
-                                       updatefn=None)
-            self.calc_thread.queue()
-            self.calc_thread.ready(2.5)
-            
-        except:
-            msg= "Simultaneous Fit error: %s" % sys.exc_value
-            wx.PostEvent(self.parent, StatusEvent(status= msg ))
-            return
-        
+                           
+        
+    def _on_show_panel(self, event):
+        print "_on_show_panel: fitting"
+      
+      
     def _onset_engine_park(self,event):
         """ 
@@ -671,4 +715,20 @@
         self._on_change_engine('scipy')
        
+    def _on_slicer_event(self, event):
+        """
+            Receive a panel as event and send it to guiframe 
+            @param event: event containing a panel
+        """
+        if event.panel!=None:
+            new_panel = event.panel
+            # Set group ID if available
+            event_id = self.parent.popup_panel(new_panel)
+            self.menu1.Append(event_id, new_panel.window_caption, 
+                             "Show %s plot panel" % new_panel.window_caption)
+            # Set UID to allow us to reference the panel later
+            new_panel.uid = event_id
+            new_panel
+            self.mypanels.append(new_panel) 
+        return    
     
     def _on_change_engine(self, engine='park'):
@@ -686,8 +746,8 @@
             @param evt: wx.combobox event
         """
-       
         model = evt.model
-        name = evt.name
-       
+        if model ==None:
+            return
+        name = model.name
         sim_page=self.sim_page
         current_pg = self.fit_panel.get_current_page() 
@@ -711,170 +771,12 @@
             self.page_finder[current_pg].set_model(model,M_name)
             
-                
             # save model name
-            self.plot_helper(currpage= current_pg,qmin= None,qmax= None)
+            self.draw_model( model=model, data= metadata)
+            
             if self.sim_page!=None:
                 self.sim_page.add_model(self.page_finder)
         
         
-        
-    def  set_smearer(self,smearer):
-        """
-            Get a smear object and store it to a fit problem
-            @param smearer: smear object to allow smearing data
-        """   
-        current_pg=self.fit_panel.get_current_page()
-        self.page_finder[current_pg].set_smearer(smearer)
-         
-         
-    def redraw_model(self,qmin= None,qmax= None):
-        """
-            Draw a theory according to model changes or data range.
-            @param qmin: the minimum value plotted for theory
-            @param qmax: the maximum value plotted for theory
-        """
-        current_pg=self.fit_panel.get_current_page()
-        for page, value in self.page_finder.iteritems():
-            if page ==current_pg :
-                break 
-        self.plot_helper(currpage=page,qmin= qmin,qmax= qmax)
-        
-        
-        
-    def plot_helper(self,currpage, qmin=None,qmax=None,
-                    ymin=None,ymax=None, xmin=None, xmax=None,title=None ):
-        """
-            Plot a theory given a model and data
-            @param model: the model from where the theory is derived
-            @param currpage: page in a dictionary referring to some data
-        """
-        if self.fit_panel.GetPageCount() >1:
-            for page in self.page_finder.iterkeys():
-                if  page == currpage :  
-                    data= self.page_finder[page].get_plotted_data()
-                    list= self.page_finder[page].get_model()
-                    smearer = self.page_finder[page].get_smearer()
-                    model = list[0]
-                    break 
-            ## create Model 1D
-            if data != None and data.__class__.__name__ != 'Data2D':
-                x= numpy.zeros(len(data.x))  
-                y= numpy.zeros(len(data.y)) 
-                
-                theory = Theory1D(x=x, y=y)
-                theory.name = model.name
-                if hasattr(data ,"group_id"):
-                    theory.group_id = data.group_id
-                theory.id = "Model"
-                
-                x_name, x_units = data.get_xaxis() 
-                y_name, y_units = data.get_yaxis() 
-                theory.xaxis(x_name, x_units)
-                theory.yaxis(y_name, y_units)
-                if qmin == None :
-                    qmin = min(data.x)
-                if qmax == None :
-                    qmax = max(data.x)
-                
-                j=0
-                try:
-                    tempx = qmin
-                    tempy = model.run(qmin)
-                    theory.x[j]=tempx
-                    theory.y[j]=tempy
-                    j+=1
-                except :
-                        wx.PostEvent(self.parent, StatusEvent(status="fitting \
-                        skipping point x %g %s" %(qmin, sys.exc_value)))
-                           
-                for i in range(len(data.x)):
-                    try:
-                        if data.x[i]> qmin and data.x[i]< qmax: 
-                            tempx = data.x[i]
-                            tempy = model.run(tempx)
-                            
-                            if j< i:
-                                theory.x[j]=tempx 
-                                theory.y[j]=tempy
-                                j+=1
-                           
-                    except:
-                        wx.PostEvent(self.parent, StatusEvent(status="fitting \
-                        skipping point x %g %s" %(data.x[i], sys.exc_value)))   
-                try:
-                    tempx = qmax
-                    tempy = model.run(qmax)
-                
-                    theory.x[j]=tempx 
-                    theory.y[j]=tempy
-                    j+=1
-                except:
-                    wx.PostEvent(self.parent, StatusEvent(status="fitting \
-                        skipping point x %g %s" %(qmin, sys.exc_value)) )
-                
-                if smearer!=None:
-                    theory.y= smearer(theory.y)   
-                wx.PostEvent(self.parent, NewPlotEvent(plot=theory,
-                                                title=str(data.name)))
-            else:
-                ## create Model 2D
-                theory=Data2D(data.data, data.err_data)
-                theory.name= model.name
-                if title !=None:
-                    self.title = title
-                    theory.id= self.title
-                    theory.group_id= self.title+data.name
-                else:
-                    self.title= "Analytical model 2D "
-                    theory.id= "Model"
-                    theory.group_id= "Model"+data.name
-                theory.x_bins= data.x_bins
-                theory.y_bins= data.y_bins
-                tempy=[]
-                
-                if qmin==None:
-                    qmin=0
-                if qmax==None:
-                    x= math.pow(max(math.fabs(data.xmax),math.fabs(data.xmin)),2)
-                    y= math.pow(max(math.fabs(data.ymax),math.fabs(data.ymin)),2)
-                    qmax=math.sqrt( x+y )
-                    
-                if ymin==None:
-                    ymin=data.ymin
-                if ymax==None:
-                    ymax=data.ymax
-                if xmin ==None:
-                    xmin=data.xmin
-                if xmax==None:
-                    xmax=data.xmax      
-                                  
-                theory.data = numpy.zeros((len(data.y_bins),len(data.x_bins)))
-                for j in range(len(data.y_bins)):
-                    for i in range(len(data.x_bins)):
-                        tempqij=math.sqrt(( math.pow(data.y_bins[j],2)\
-                                           +math.pow(data.x_bins[i],2) ))
-                        
-                        if tempqij>= qmin and tempqij<= qmax: 
-                            theory.data[j][i] = model.runXY([data.y_bins[j],
-                                                             data.x_bins[i]] )
-                        else:
-                            ## Later, We need to decide which of  0 and None is better.
-                            theory.data[j][i]=0 
-             
-                theory.detector= data.detector
-                theory.source= data.source
-                ## qmin, qmax will used later to define q range.
-                theory.qmin= qmin
-                theory.qmax= qmax
-                ## plot boundaries
-                theory.ymin= ymin
-                theory.ymax= ymax
-                theory.xmin= xmin
-                theory.xmax= xmax
-        
-                wx.PostEvent(self.parent, NewPlotEvent(plot=theory,
-                                                title=self.title +str(data.name)))
-        
-        
+  
     def _on_model_menu(self, evt):
         """
@@ -893,90 +795,8 @@
         self.fit_panel.add_model_page(model,description,name,topmenu=True)
     
-    def complete1D_from_data(self, output,model, data, x, elapsed, name):
-        """
-             plot model 1D with data info 
-        """
-        y= output
-        x= data.x
-        theory = Theory1D(x=x, y=y)
-        theory.name = model.name
-        theory.group_id = data.group_id
-        theory.id = "Model"
-        
-        x_name, x_units = data.get_xaxis() 
-        y_name, y_units = data.get_yaxis() 
-        theory.xaxis(x_name, x_units)
-        theory.yaxis(y_name, y_units)
-        wx.PostEvent(self.parent, NewPlotEvent(plot=theory,
-                                                title=str(data.name)))
-        
-    def draw_model1D_from_Data(self, data, model,name=None,
-                                qmin=None, qmax=None, smearer= None):
-        """
-            Draw model 1D from loaded data1D
-            @param data: loaded data
-            @param model: the model to plot
-        """
-        x = data.x
-        self.model= model
-        if qmin == None :
-           qmin = min(data.x)
-        if qmax == None :
-           qmax = max(data.x)
-        if name ==None:
-            name=model.name
-        try:
-            from model_thread import Calc1D
-            ## If a thread is already started, stop it
-            if self.calc_thread != None and self.calc_thread.isrunning():
-                self.calc_thread.stop()
-            self.calc_thread = Calc1D( x= x,
-                                      model= self.model, 
-                                       qmin= qmin,
-                                       qmax= qmax,
-                                       name= name,
-                                       smearer= smearer,
-                            completefn= self.complete1D_from_data,
-                            updatefn= self.update1D)
-            self.calc_thread.queue()
-            
-        except:
-            msg= " Error occurred when drawing %s Model 1D: "%self.model.name
-            msg+= " %s"%sys.exc_value
-            wx.PostEvent( self.parent, StatusEvent(status= msg ))
-            return  
-            
-    def draw_model(self, model, name, data= None, description= None,
-                   enable1D= True, enable2D= False,
-                   qmin= DEFAULT_QMIN, qmax= DEFAULT_QMAX, qstep= DEFAULT_NPTS):
-        """
-             Draw model.
-             @param model: the model to draw
-             @param name: the name of the model to draw
-             @param data: the data on which the model is based to be drawn
-             @param description: model's description
-             @param enable1D: if true enable drawing model 1D
-             @param enable2D: if true enable drawing model 2D
-             @param qmin:  Range's minimum value to draw model
-             @param qmax:  Range's maximum value to draw model
-             @param qstep: number of step to divide the x and y-axis
-             
-        """
-        ## draw model based on loaded data
-        if data !=None:
-            self.redraw_model(qmin,qmax)
-            return 
-        ## draw model 1D with no loaded data
-        self._draw_model1D(model,name,model.description, enable1D,qmin,qmax, qstep)
-        ## draw model 2D with no initial data
-        self._draw_model2D(model=model,
-                           description=model.description,
-                           enable2D= enable2D,
-                           qmin=qmin,
-                           qmax=qmax,
-                           qstep=qstep)
-        
-    
-    def update1D(self,x, output):
+   
+    
+    
+    def _update1D(self,x, output):
         """
             Update the output of plotting model 1D
@@ -984,98 +804,12 @@
         self.calc_thread.ready(1)
     
-    def complete1D(self, x,output, elapsed, name,data=None):
-        """
-            Complete plotting 1D data
-        """ 
-        try:
-            y = output
-            new_plot = Theory1D(x, y)
-            new_plot.name = name
-            new_plot.xaxis("\\rm{Q}", 'A^{-1}')
-            new_plot.yaxis("\\rm{Intensity} ","cm^{-1}")
-            new_plot.id ="Model"
-            new_plot.group_id ="Model"
-            # Pass the reset flag to let the plotting event handler
-            # know that we are replacing the whole plot
-            wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot,
-                             title="Analytical model 1D ", reset=True ))
-            
-        except:
-            msg= " Error occurred when drawing %s Model 1D: "%new_plot.name
-            msg+= " %s"%sys.exc_value
-            wx.PostEvent( self.parent, StatusEvent(status= msg ))
-            return  
-        
-                 
-    def _draw_model1D(self, model, name, description= None, enable1D= True,
-                      qmin= DEFAULT_QMIN, qmax= DEFAULT_QMAX, qstep= DEFAULT_NPTS):
-        """
-            Draw model 1D between qmin and qmax value
-            @param model: the model to draw
-            @param name: the name of the model
-            @param description: descripion of the model as string
-            @param enable1D:  allow to draw model 1D if True  else False
-            @param qmin: the minimum value of the range to draw the model
-            @param qmax: the maximum value of the range to draw the model
-            @param qstep: the number of points to draw  
-        """
-        x=  numpy.linspace(start= qmin,
-                           stop= qmax,
-                           num= qstep,
-                           endpoint=True
-                           )      
-        self.model= model
-        if enable1D:
-            try:
-                from model_thread import Calc1D
-                ## If a thread is already started, stop it
-                if self.calc_thread != None and self.calc_thread.isrunning():
-                    self.calc_thread.stop()
-                self.calc_thread = Calc1D( x= x,
-                                          model= self.model, 
-                                           qmin= qmin,
-                                           qmax= qmax,
-                                           name= name,
-                                           data=None,
-                                        smearer=None,
-                                completefn= self.complete1D,
-                                updatefn= self.update1D)
-                self.calc_thread.queue()
-                
-            except:
-                msg= " Error occurred when drawing %s Model 1D: "%self.model.name
-                msg+= " %s"%sys.exc_value
-                wx.PostEvent( self.parent, StatusEvent(status= msg ))
-                return  
-                
-
-
-        
-    def update2D(self, output,time=None):
-        """
-            Update the output of plotting model
-        """
-        wx.PostEvent(self.parent, StatusEvent(status="Plot \
-        #updating ... ",type="update"))
-        self.calc_thread.ready(0.01)
-        
-        
-    def complete2D(self, output, elapsed, model, qmin, qmax,qstep=DEFAULT_NPTS):
-        """
-            Complete get the result of modelthread and create model 2D
-            that can be plot.
-        """
-        msg = "Calc complete !"
-        wx.PostEvent( self.parent, StatusEvent( status= msg , type="stop" ))
-    
-        data = output
-        temp= numpy.zeros(numpy.shape(data))
-        temp[temp==0]=1
-        theory= Data2D(image=data, err_image=temp)
-    
+    def _fill_default_model2D(self, theory, qmax,qstep, qmin=None):
+        """
+            fill Data2D with default value 
+            @param theory: Data2D to fill
+        """
         from DataLoader.data_info import Detector, Source
         
         detector = Detector()
-        theory.detector=[]
         theory.detector.append(detector) 
             
@@ -1083,6 +817,5 @@
         theory.source= Source()
         theory.source.wavelength=2*math.pi/1e+32
-        theory.x_bins =[]
-        theory.y_bins =[]
+      
         ## Create detector for Model 2D
         xmax=2*theory.detector[0].distance*math.atan(\
@@ -1114,5 +847,4 @@
             theory.y_bins.append(qy)
            
-        theory.name= model.name
         theory.group_id ="Model"
         theory.id ="Model"
@@ -1122,11 +854,115 @@
         theory.ymin= -qmax
         theory.ymax= qmax
+        
+        
+    def _get_plotting_info(self, data=None):
+        """
+            get plotting info from data if data !=None
+            else use some default
+        """
+        my_info = PlotInfo()
+        if data !=None:
+            if hasattr(data,"info"):
+                x_name, x_units = data.get_xaxis() 
+                y_name, y_units = data.get_yaxis() 
+                
+                my_info._xunit = x_units
+                my_info._xaxis = x_name
+                my_info._yunit = y_units
+                my_info._yaxis = y_name
+                
+            my_info.title= data.name
+            if hasattr(data, "info"):
+                my_info.info= data.info
+            if hasattr(data, "group_id"):
+                my_info.group_id= data.group_id
+            
+        return my_info
+                
+    def _complete1D(self, x,y, elapsed,model,data=None):
+        """
+            Complete plotting 1D data
+        """ 
+        try:
+            new_plot = Theory1D(x=x, y=y)
+            my_info = self._get_plotting_info( data)
+            new_plot.name = model.name
+            new_plot.id = my_info.id
+            new_plot.group_id = my_info.group_id
+            
+            new_plot.xaxis( my_info._xaxis,  my_info._xunit)
+            new_plot.yaxis( my_info._yaxis, my_info._yunit)
+            
+            # Pass the reset flag to let the plotting event handler
+            # know that we are replacing the whole plot
+            title= my_info.title
+            if title== None:
+                title="Analytical model 1D "
+                wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot,
+                             title= str(title), reset=True ))
+            else:
+                wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot,
+                             title= str(title)))
+            
+        except:
+            msg= " Error occurred when drawing %s Model 1D: "%new_plot.name
+            msg+= " %s"%sys.exc_value
+            wx.PostEvent( self.parent, StatusEvent(status= msg ))
+            return  
+        
+                 
+    
+        
+    def _update2D(self, output,time=None):
+        """
+            Update the output of plotting model
+        """
+        wx.PostEvent(self.parent, StatusEvent(status="Plot \
+        #updating ... ",type="update"))
+        self.calc_thread.ready(0.01)
+        
+        
+    def _complete2D(self, image,data, model,  elapsed,qmin, qmax,qstep=DEFAULT_NPTS):
+        """
+            Complete get the result of modelthread and create model 2D
+            that can be plot.
+        """
+        msg = "Calc complete !"
+        wx.PostEvent( self.parent, StatusEvent( status= msg , type="stop" ))
+    
+        err_image = numpy.zeros(numpy.shape(image))
+        err_image[err_image==0]= 1
+        theory= Data2D(image= image , err_image= err_image)
+        
+        if data ==None:
+            self._fill_default_model2D(theory= theory, qmax=qmax,qstep=qstep, qmin= qmin)
+            theory.name= model.name
+        else:
+            theory.name= data.name
+            theory.id= "Model"
+            theory.group_id= "Model"+data.name
+            theory.x_bins= data.x_bins
+            theory.y_bins= data.y_bins
+            theory.detector= data.detector
+            theory.source= data.source
+            
+            ## plot boundaries
+            theory.ymin= data.ymin
+            theory.ymax= data.ymax
+            theory.xmin= data.xmin
+            theory.xmax= data.xmax
+        
         ## plot
         wx.PostEvent(self.parent, NewPlotEvent(plot=theory,
                          title="Analytical model 2D ", reset=True ))
          
-        
+    def _on_data_error(self, event):
+        """
+            receives and event from plotting plu-gins to store the data name and 
+            their errors of y coordinates for 1Data hide and show error
+        """
+        self.err_dy= event.err_dy
          
-    def _draw_model2D(self,model,description=None, enable2D=False,
+    def _draw_model2D(self,model,data=None,description=None, enable2D=False,
                       qmin=DEFAULT_QMIN, qmax=DEFAULT_QMAX, qstep=DEFAULT_NPTS):
         """
@@ -1140,4 +976,5 @@
             
         """
+        
         x=  numpy.linspace(start= -1*qmax,
                                stop= qmax,
@@ -1148,24 +985,86 @@
                                num= qstep,
                                endpoint=True )
-       
-        self.model= model
-        if enable2D:
-            try:
-                from model_thread import Calc2D
-                ## If a thread is already started, stop it
-                if self.calc_thread != None and self.calc_thread.isrunning():
-                    self.calc_thread.stop()
-                self.calc_thread = Calc2D( x= x,
-                                           y= y, model= self.model, 
-                                           qmin= qmin,
-                                           qmax= qmax,
-                                           qstep= qstep,
-                                completefn= self.complete2D,
-                                updatefn= self.update2D )
-                self.calc_thread.queue()
-                
-            except:
-                raise
-    
+        ## use data info instead
+        if data !=None:
+            ## check if data2D to plot
+            if hasattr(data, "x_bins"):
+                enable2D = True
+                x= data.x_bins
+                y= data.y_bins
+            
+        if not enable2D:
+            return
+        try:
+            from model_thread import Calc2D
+            ## If a thread is already started, stop it
+            if self.calc_2D != None and self.calc_2D.isrunning():
+                self.calc_2D.stop()
+            self.calc_2D = Calc2D(  x= x,
+                                    y= y,
+                                    model= model, 
+                                    data = data,
+                                    qmin= qmin,
+                                    qmax= qmax,
+                                    qstep= qstep,
+                                    completefn= self._complete2D,
+                                    updatefn= self._update2D )
+            self.calc_2D.queue()
+            
+        except:
+            msg= " Error occurred when drawing %s Model 2D: "%model.name
+            msg+= " %s"%sys.exc_value
+            wx.PostEvent( self.parent, StatusEvent(status= msg ))
+            return  
+   
+    def _draw_model1D(self, model, data=None, smearer= None,
+                qmin=DEFAULT_QMIN, qmax=DEFAULT_QMAX, qstep= DEFAULT_NPTS,enable1D= True):
+        """
+            Draw model 1D from loaded data1D
+            @param data: loaded data
+            @param model: the model to plot
+        """
+         
+        x=  numpy.linspace(start= qmin,
+                           stop= qmax,
+                           num= qstep,
+                           endpoint=True
+                           )
+        if data!=None:
+            ## check for data2D
+            if hasattr(data,"x_bins"):
+                return
+            x = data.x
+            if qmin == DEFAULT_QMIN :
+                qmin = min(data.x)
+            if qmax == DEFAULT_QMAX:
+                qmax = max(data.x)
+        
+        if not enable1D:
+            return
+    
+        try:
+            from model_thread import Calc1D
+            ## If a thread is already started, stop it
+            if self.calc_1D!= None and self.calc_1D.isrunning():
+                self.calc_1D.stop()
+            self.calc_1D= Calc1D( x= x,
+                                  data = data,
+                                  model= model, 
+                                  qmin = qmin,
+                                  qmax = qmax,
+                                  smearer = smearer,
+                                  completefn = self._complete1D,
+                                  updatefn = self._update1D  )
+            self.calc_1D.queue()
+            
+        except:
+            msg= " Error occurred when drawing %s Model 1D: "%model.name
+            msg+= " %s"%sys.exc_value
+            wx.PostEvent( self.parent, StatusEvent(status= msg ))
+            return  
+            
+   
+
+
    
 if __name__ == "__main__":
Index: sansview/perspectives/fitting/model_thread.py
===================================================================
--- sansview/perspectives/fitting/model_thread.py	(revision bb18ef1c74ed79eb0630f198735ad2b14e7913ab)
+++ sansview/perspectives/fitting/model_thread.py	(revision c77d8592395f6684cf45ee976c1cac9db9c00110)
@@ -90,5 +90,5 @@
     """
     
-    def __init__(self, x, y, model,qmin, qmax,qstep,
+    def __init__(self, x, y, data,model,qmin, qmax,qstep,
                  completefn = None,
                  updatefn   = None,
@@ -101,8 +101,9 @@
                  worktime)
         self.qmin= qmin
-        self.qmax=qmax
+        self.qmax= qmax
         self.qstep= qstep
         self.x = x
         self.y = y
+        self.data= data
         ## the model on to calculate
         self.model = model
@@ -128,13 +129,17 @@
         y = self.y
         output = numpy.zeros((len(x),len(y)))
-      
-        center_x=0
-        center_y=0
+        
+        if self.qmin==None:
+            self.qmin = 0
+        if self.qmax== None:
+            if data ==None:
+                return
+            newx= math.pow(max(math.fabs(data.xmax),math.fabs(data.xmin)),2)
+            newy= math.pow(max(math.fabs(data.ymax),math.fabs(data.ymin)),2)
+            self.qmax=math.sqrt( newx + newy )
         
         self.starttime = time.time()
         
-        
         lx = len(self.x)
-       
         for i_x in range(len(self.x)):
             # Check whether we need to bail out
@@ -143,19 +148,20 @@
        
             for i_y in range(int(len(self.y))):
-           
-                if (self.x[i_x]*self.x[i_x]+self.y[i_y]*self.y[i_y]) \
-                    < self.qmin * self.qmin:
-                    
-                    output[i_x] [i_y]=0   
+                radius = self.x[i_x]*self.x[i_x]+self.y[i_y]*self.y[i_y]
+                
+                if  self.qmin <= radius or radius<= self.qmax:
+                    value = self.model.runXY( [self.x[i_x], self.y[i_y]] )
+                    output[i_x] [i_y]=value   
                 else:
-                    value = self.model.runXY([self.x[i_x]-center_x, self.y[i_y]-center_y])
-                    output[i_x] [i_y]=value   
+                     output[i_x] [i_y]=0   
             
         elapsed = time.time()-self.starttime
-        self.complete(
-                      output=output, elapsed=elapsed,model= self.model,
-                      qmin= self.qmin,
-                      qmax=self.qmax,
-                      qstep=self.qstep)
+        self.complete( image = output,
+                       data = self.data , 
+                       model = self.model,
+                       elapsed = elapsed,
+                       qmin = self.qmin,
+                       qmax =self.qmax,
+                       qstep = self.qstep )
 
 
@@ -256,5 +262,4 @@
                  qmin=None,
                  qmax=None,
-                 name=None,
                  smearer=None,
                  completefn = None,
@@ -272,17 +277,15 @@
         self.qmax= qmax
         self.model = model
-        self.name= name
         self.smearer= smearer
         self.starttime = 0
         
     def compute(self):
+        """
+            Compute model 1d value given qmin , qmax , x value 
+        """
         import numpy
         
         output = numpy.zeros(len(self.x))
-        if self.qmin==None:
-            self.qmin= min(self.x)
-        if self.qmax==None:
-            self.qmax= max(self.x) 
-               
+       
         self.starttime = time.time()
         
@@ -294,10 +297,12 @@
                 value = self.model.run(self.x[i_x])
                 output[i_x] = value
+                
         if self.smearer!=None:
             output = self.smearer(output)
-                    
+            
+                      
         elapsed = time.time()-self.starttime
-        self.complete(x= self.x, output=output, 
-                      elapsed=elapsed, name=self.name, data=self.data)
+        self.complete(x= self.x, y= output, 
+                      elapsed=elapsed, model= self.model, data=self.data)
         
         
Index: sansview/perspectives/fitting/modelpage.py
===================================================================
--- sansview/perspectives/fitting/modelpage.py	(revision bb18ef1c74ed79eb0630f198735ad2b14e7913ab)
+++ sansview/perspectives/fitting/modelpage.py	(revision c77d8592395f6684cf45ee976c1cac9db9c00110)
@@ -1,3 +1,3 @@
-import sys
+
 import wx
 import wx.lib.newevent
@@ -12,8 +12,9 @@
 _BOX_WIDTH = 80
 
-
-
-
-class ModelPage(wx.ScrolledWindow):
+import basepage
+from basepage import BasicPage
+
+
+class ModelPage(BasicPage):
     """
         FitPanel class contains fields allowing to display results when
@@ -23,152 +24,62 @@
   
     """
-    ## Internal name for the AUI manager
-    window_name = "Fit page"
-    ## Title to appear on top of the window
-    window_caption = "Fit Page"
-    name=""
-    def __init__(self, parent,model,name, *args, **kwargs):
-        wx.ScrolledWindow.__init__(self, parent, *args, **kwargs)
+    def __init__(self,parent, page_info, name=""):
+        BasicPage.__init__(self, parent, page_info,name)
         """ 
             Initialization of the Panel
         """
-        # model on which the fit would be performed
-        self.model=model
-        # Data member to store the dispersion object created
-        self._disp_obj_dict = {}
-        self.back_up_model= model.clone()
-        #list of dispersion paramaters
-        self.disp_list=[]
-        try:
-            self.disp_list=self.model.getDispParamList()
-        except:
-            pass 
-        self.manager = None
-        self.parent  = parent
-        self.event_owner = None
-        # this panel does contain data .existing data allow a different drawing
-        #on set_model parameters
-        self.data=None
-        #panel interface
-        self.vbox  = wx.BoxSizer(wx.VERTICAL)
-        self.sizer11 = wx.BoxSizer(wx.HORIZONTAL)
-        #self.sizer10 = wx.GridBagSizer(5,5)
-        self.sizer9 = wx.GridBagSizer(5,5)
-        self.sizer8 = wx.GridBagSizer(5,5)
-        self.sizer7 = wx.GridBagSizer(5,5)
-        self.sizer6 = wx.GridBagSizer(5,5)
-        self.sizer5 = wx.GridBagSizer(5,5)
-        self.sizer4 = wx.GridBagSizer(5,5)
-       
-        #model selection
-        self.vbox.Add(wx.StaticLine(self, -1), 0, wx.EXPAND, 0)
-        self.vbox.Add(self.sizer4)
-        #model description
-        self.vbox.Add(self.sizer11)
-        #model paramaters layer
-        self.vbox.Add(self.sizer5)
-        #polydispersion selected
-        self.vbox.Add(wx.StaticLine(self, -1), 0, wx.EXPAND, 0)
-        self.vbox.Add(self.sizer6)
-        #combox box for type of dispersion
-        self.vbox.Add(self.sizer7)
-        #dispersion parameters layer
-        self.vbox.Add(self.sizer8)
-        # plotting range
-        self.vbox.Add(self.sizer9)
-        #close layer
-        #self.vbox.Add(wx.StaticLine(self, -1), 0, wx.EXPAND, 0)
-        #self.vbox.Add(self.sizer10)
-        
-      
-        #------------------ sizer 4  draw------------------------  
-       
-        ## structure combox box
-        self.structbox = wx.ComboBox(self, -1)
-        # define combox box
-        self.modelbox = wx.ComboBox(self, -1)
-        
-        #enable model 2D draw
-        self.enable2D= False
-        self.fitrange= True
-        #filling sizer2
-        ix = 0
-        iy = 1
-        self.sizer4.Add(wx.StaticText(self,-1,'Model'),(iy,ix),(1,1)\
-                  , wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
-        ix += 1
-        self.sizer4.Add(self.modelbox,(iy,ix),(1,1),  wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-        ix +=1
-        self.text_mult= wx.StaticText(self,-1,' x ')
-        self.sizer4.Add(self.text_mult,(iy,ix),(1,1),  wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-        ix += 1
-        self.sizer4.Add(self.structbox,(iy,ix),(1,1),  wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-        
-        if hasattr(model ,"model2"):
-            name= model.model2.name
-
-            self.structbox.SetValue(name)          
-        if hasattr(model ,"model1"):
-            name= model.model1.name
-            items = self.modelbox.GetItems()
-            self.modelbox.SetValue(name)
+        
+        self._fill_model_sizer( self.sizer1)  
+        self._fill_range_sizer() 
+        if hasattr(self.page_info,"model"):
+            model=self.page_info.model
+            description=""
+            if model!=None:
+                description = self.page_info.model.description
+            self.set_model_param_sizer(self.model)
+            self.set_model_description(description,self.sizer2)
+        
+    
+
+        
+    def _on_display_description(self, event):
+        """
+            Show or Hide description
+            @param event: wx.EVT_RADIOBUTTON
+        """
+        self._on_display_description_helper()
+        
+        
+        
+    def _on_display_description_helper(self):
+        """
+            Show or Hide description
+            @param event: wx.EVT_RADIOBUTTON
+        """
+        ## save state of radiobox
+        self.page_info. save_radiobox_state( self.description_hide )
+        self.page_info. save_radiobox_state( self.description_show )
+        ## Show description
+        if not self.description_show.GetValue():
+            self.sizer_description.Clear(True)
+            
         else:
-            #print "model view prev_model",name
-            self.modelbox.SetValue( name )
-        ix += 1
-        id = wx.NewId()
-        self.model_view =wx.Button(self,id,'View 2D')
-        self.model_view.Bind(wx.EVT_BUTTON, self.onModel2D,id=id)
-        self.model_view.SetToolTipString("View model in 2D")
-        
-        self.sizer4.Add(self.model_view,(iy,ix),(1,1),\
-                   wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
-        
-        self.model_view.Enable()
-        self.model_view.SetFocus()
-        
-        ix = 0
-        iy += 1
-        self.sizer4.Add((20,20),(iy,ix),(1,1),wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
-
-        #----------sizer6-------------------------------------------------
-        self.disable_disp = wx.RadioButton(self, -1, 'No', (10, 10), style=wx.RB_GROUP)
-        self.enable_disp = wx.RadioButton(self, -1, 'Yes', (10, 30))
-        self.Bind(wx.EVT_RADIOBUTTON, self.Set_DipersParam, id=self.disable_disp.GetId())
-        self.Bind(wx.EVT_RADIOBUTTON, self.Set_DipersParam, id=self.enable_disp.GetId())
-        ix= 0
-        iy=1
-        self.sizer6.Add(wx.StaticText(self,-1,'Polydispersity: '),(iy,ix),(1,1)\
-                  , wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
-        ix += 1
-        self.sizer6.Add(self.enable_disp ,(iy,ix),(1,1),  wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-        ix += 1
-        self.sizer6.Add(self.disable_disp ,(iy,ix),(1,1),  wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-        ix =0
-        iy+=1
-        self.sizer6.Add((20,20),(iy,ix),(1,1),wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)  
-
-        
-        #---------sizer 9 draw----------------------------------------
-       
-         ## Q range
-        self.qmin_x= 0.001
-        self.qmax_x= 0.1
-        self.num_points= 100
-        
-        
-        self.qmin    = wx.TextCtrl(self, -1,size=(_BOX_WIDTH,20))
-        self.qmin.SetValue(format_number(self.qmin_x))
-        self.qmin.SetToolTipString("Minimun value of Q in linear scale.")
-        self.qmin.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
-        self.qmin.Bind(wx.EVT_TEXT_ENTER, self._onparamEnter)
-     
-        self.qmax    = wx.TextCtrl(self, -1,size=(_BOX_WIDTH,20))
-        self.qmax.SetValue(format_number(self.qmax_x))
-        self.qmax.SetToolTipString("Maximum value of Q in linear scale.")
-        self.qmax.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
-        self.qmax.Bind(wx.EVT_TEXT_ENTER, self._onparamEnter)
-     
-
+            model=self.page_info.model
+            description=""
+            if model!=None:
+                description = self.page_info.model.description
+            self.description = wx.StaticText( self,-1,str(description) )
+            self.sizer_description.Add( self.description, 1, wx.EXPAND | wx.ALL, 10 )
+           
+        self.Layout()
+    
+    
+    def _fill_range_sizer(self):
+        """
+            Fill the sizer containing the plotting range
+            add  access to npts
+        """
+        sizer_npts= wx.GridSizer(1, 1,5, 5)
+    
         self.npts    = wx.TextCtrl(self, -1,size=(_BOX_WIDTH,20))
         self.npts.SetValue(format_number(self.num_points))
@@ -176,259 +87,133 @@
         self.npts.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
         self.npts.Bind(wx.EVT_TEXT_ENTER, self._onparamEnter)
-       
-        ix = 0
-        iy = 1 
-        self.sizer9.Add(wx.StaticText(self, -1, 'Plotting Range'),(iy, ix),(1,1),\
-                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
+        
+        sizer_npts.Add(wx.StaticText(self, -1, 'Npts'),1, wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 5)        
+        sizer_npts.Add(self.npts,1, wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 5) 
+        self._set_range_sizer( title="Plotted Q Range", object= sizer_npts)
+       
+    def _on_select_model(self, event): 
+        """
+             call back for model selection
+        """    
+        self._on_select_model_helper(event) 
+        self.set_model_param_sizer(self.model)
+        self._set_sizer_gaussian()
+        self.name = self.model.name
+        self.model_view.SetFocus()
+        self.parent.model_page.name = self.name
+        self.parent.draw_model_name = self.name
+        self._draw_model()  
+       
+    def _fill_model_sizer(self, sizer):
+        """
+            fill sizer containing model info
+        """
+        id = wx.NewId()
+        self.model_view =wx.Button(self,id,'View 2D')
+        self.model_view.Bind(wx.EVT_BUTTON, self._onModel2D,id=id)
+        self.model_view.SetToolTipString("View model in 2D")
+        
+        ## class base method  to add view 2d button    
+        self._set_model_sizer(sizer=sizer, title="Model",object= self.model_view )    
+    
+  
+    def _set_sizer_gaussian(self):
+        """
+            draw sizer with gaussian dispersity parameters
+        """
+        self.fittable_param=[]
+        self.fixed_param=[]
+        ##reset model dispersity to gaussian
+        self._reset_gaussian_dispers()
+        
+        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 
+        ix=0
+        iy=1
+        disp = wx.StaticText(self, -1, 'Names')
+        self.sizer4_4.Add(disp,( iy, ix),(1,1), 
+                           wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
         ix += 1 
-        self.sizer9.Add(wx.StaticText(self, -1, 'Min'),(iy, ix),(1,1),\
-                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-        ix += 1
-        self.sizer9.Add(wx.StaticText(self, -1, 'Max'),(iy, ix),(1,1),\
-                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-        ix += 1
-        self.sizer9.Add(wx.StaticText(self, -1, 'Npts'),(iy, ix),(1,1),\
-                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-        ix = 0
-        iy += 1
-        self.sizer9.Add(wx.StaticText(self, -1, 'Q range'),(iy, ix),(1,1),\
-                            wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
-        ix += 1
-        self.sizer9.Add(self.qmin,(iy, ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-        ix += 1
-        self.sizer9.Add(self.qmax,(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-        ix += 1
-        self.sizer9.Add(self.npts,(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-        
+        values = wx.StaticText(self, -1, 'Values')
+        self.sizer4_4.Add(values,( iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
+       
+        ix += 1 
+        npts = wx.StaticText(self, -1, 'Npts')
+        self.sizer4_4.Add(npts,( iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
+        ix += 1 
+        nsigmas = wx.StaticText(self, -1, 'Nsigmas')
+        self.sizer4_4.Add(nsigmas,( iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
+       
+        for item in self.model.dispersion.keys():
+            name1=item+".width"
+            name2=item+".npts"
+            name3=item+".nsigmas"
+            iy += 1
+            for p in self.model.dispersion[item].keys():
+                if p=="width":
+                    ix = 0
+                    name = wx.StaticText(self, -1,  name1)
+                    self.sizer4_4.Add( name,( iy, ix),(1,1),  
+                                       wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
+                    ix = 1
+                    value= self.model.getParam(name1)
+                    ctl1 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20),
+                                        style=wx.TE_PROCESS_ENTER)
+                    
+                    ctl1.SetValue(str (format_number(value)))
+                    ctl1.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
+                    ctl1.Bind(wx.EVT_TEXT_ENTER,self._onparamEnter)
+                    self.sizer4_4.Add(ctl1, (iy,ix),(1,1), wx.EXPAND)
+                    
+                    self.fittable_param.append([None,name1,ctl1,None,
+                                                None, None, None,None])
+                    
+                elif p=="npts":
+                        ix =2
+                        value= self.model.getParam(name2)
+                        Tctl1 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH/2,20),
+                                            style=wx.TE_PROCESS_ENTER)
+                        
+                        Tctl1.SetValue(str (format_number(value)))
+                        Tctl1.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
+                        Tctl1.Bind(wx.EVT_TEXT_ENTER,self._onparamEnter)
+                        self.sizer4_4.Add(Tctl1, (iy,ix),(1,1),
+                                           wx.EXPAND|wx.ADJUST_MINSIZE, 0)
+                        
+                        self.fixed_param.append([None,name2, Tctl1,None,None,
+                                                  None, None,None])
+                
+                elif p=="nsigmas":
+                        ix =3 
+                        value= self.model.getParam(name3)
+                        Tctl2 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH/2,20),
+                                            style=wx.TE_PROCESS_ENTER)
+                        Tctl2.SetValue(str (format_number(value)))
+                        Tctl2.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
+                        Tctl2.Bind(wx.EVT_TEXT_ENTER,self._onparamEnter)
+                        self.sizer4_4.Add(Tctl2, (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, Tctl2,
+                                                 None,None, None, None,None])
+        
+        msg = " Selected Distribution: Gaussian"        
+        wx.PostEvent(self.parent.parent, StatusEvent( status= msg ))   
         ix =0
-        iy+=1 
-        self.sizer9.Add((20,20),(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-        
-        # contains link between  model ,all its parameters, and panel organization
-        self.parameters=[]
-        self.fixed_param=[]
-        self.fittable_param=[]
-        self.polydisp= {}
-        #contains link between a model and selected parameters to fit 
-        self.param_toFit=[]
-        
-        #dictionary of model name and model class
-        self.model_list_box={}
-        #Draw initial panel
-         #-----sizer 11--------------------model description------
-        if self.model!=None:
-            self.set_panel(self.model)
-        self.theta_cb=None
-        
-       
-        self.vbox.Layout()
-        self.vbox.Fit(self) 
-        self.SetSizer(self.vbox)
-        self.SetScrollbars(20,20,55,40)
-        
-        self.Centre()
-        self.Layout()
-        self.parent.GetSizer().Layout()
-    def set_model_description(self, model=None):
-        
-        if model !=None:
-            description="description"
-        else:
-            description=""
-            if hasattr(model,description.lower())and self.data==None:
-                self.sizer11.Clear(True)
-                self.box_description= wx.StaticBox(self, -1, 'Model Description')
-                boxsizer1 = wx.StaticBoxSizer(self.box_description, wx.VERTICAL)
-                boxsizer1.SetMinSize((320,20))
-                self.description = wx.StaticText(self,-1,str(model.description))
-                boxsizer1.Add(self.description, 0, wx.EXPAND)  
-                self.sizer11.Add(boxsizer1,1, wx.EXPAND | wx.ALL, 2)
-      
-        
-    def set_owner(self,owner):
-        """ 
-            set owner of fitpage
-            @param owner: the class responsible of plotting
-        """
-        self.event_owner=owner    
-   
-  
-    def set_manager(self, manager):
-        """
-             set panel manager
-             @param manager: instance of plugin fitting
-        """
-        self.manager = manager  
-        
-    def populate_box(self, dict):
-        """
-            Populate each combox box of each page
-            @param page: the page to populate
-        """
-        
-        self.model_list_box = dict.get_list()
-       
-        for item , mylist in self.model_list_box.iteritems():
-            separator= "---%s---"%item
-            self.modelbox.Append(separator,"separator")
-            
-            for models in mylist:
-                model= models()
-                name = model.__class__.__name__
-                if hasattr(model, "name"):
-                    name = model.name
-                self.modelbox.Append(name,models)
-            wx.EVT_COMBOBOX(self.modelbox,-1, self._on_select_model)
-            if item == "Structure Factors" :
-                for structs in mylist:
-                    struct= structs()
-                    name = struct.__class__.__name__
-                    if hasattr(struct, "name"):
-                        name = struct.name
-                    self.structbox.Append(name,structs)
-                wx.EVT_COMBOBOX(self.structbox,-1, self._on_select_model)
-        
-        
-        return 0
-    
-
-    def Set_DipersParam(self, event):
-        if self.model ==None:
-            msg= " Select non - model value:%s !"%self.model
-            wx.PostEvent(self.parent.parent, StatusEvent(status= msg))
-            return 
-        if self.enable_disp.GetValue():
-            if len(self.disp_list)==0:
-                ix=0
-                iy=1
-                self.fittable_param=[]
-                self.fixed_param=[]
-                self.sizer8.Clear(True)
-                model_disp = wx.StaticText(self, -1, 'No PolyDispersity for this model')
-                self.sizer7.Add(model_disp,( iy, ix),(1,1),  wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
-                self.vbox.Layout()
-                self.SetScrollbars(20,20,55,40)
-                self.Layout()
-                self.parent.GetSizer().Layout()
-                return 
-            else:
-                if self.data !=None and self.model !=None: # allow to recognize data panel from model panel
-                    
-                
-                    self.cb1.SetValue(False)
-                    self.select_all_param_helper()
-                
-                self.populate_disp_box()
-                self.set_panel_dispers(self.disp_list)
-                
-        else:
-            if self.data !=None and self.model!=None:
-                if self.cb1.GetValue():
-                    self.select_all_param_helper()
-            
-            if self.back_up_model!=None:
-                keys = self.back_up_model.getDispParamList()
-                keys.sort()
-                #disperse param into the initial state
-                for item in keys:
-                    value= self.back_up_model.getParam(item)
-                    self.model.setParam(item, value)
-                self._draw_model() 
-            
-                
-            self.fittable_param=[]        
-            self.fixed_param=[]
-            self.sizer7.Clear(True)
-            self.sizer8.Clear(True)
-            self.vbox.Layout()
-            self.SetScrollbars(20,20,55,40)
-            self.Layout()
-            self.parent.GetSizer().Layout()
-            
-    def populate_disp_box(self):
-        self.sizer7.Clear(True)
-        if len(self.disp_list)>0:
-            ix=0
-            iy=1
-            model_disp = wx.StaticText(self, -1, 'Model Disp')
-            self.sizer7.Add(model_disp,( iy, ix),(1,1),  wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
-            ix += 1 
-            # set up the combox box
-            id = 0
-            import sans.models.dispersion_models 
-            self.polydisp= sans.models.dispersion_models.models
-            self.disp_box = wx.ComboBox(self, -1)
-            self.disp_box.SetValue("GaussianModel")
-            for k,v in self.polydisp.iteritems():
-                if str(v)=="MyModel":
-    				# Remove the option until the rest of the code is ready for it
-                    #self.disp_box.Insert("Select customized Model",id)
-                    pass  
-                else:
-                    self.disp_box.Insert(str(v),id)         
-                id+=1
-            
-            wx.EVT_COMBOBOX(self.disp_box,-1, self._on_select_Disp) 
-            self.sizer7.Add(self.disp_box,( iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-            self.vbox.Layout()
-            self.SetScrollbars(20,20,55,40)
-            self.Layout()
-            self.parent.GetSizer().Layout()  
-            
-            
-    def set_range(self, qmin_x, qmax_x, npts):
-        """
-            Set the range for the plotted models
-            @param qmin: minimum Q
-            @param qmax: maximum Q
-            @param npts: number of Q bins
-        """
-        # Set the data members
-        self.qmin_x = qmin_x
-        self.qmax_x = qmax_x
-        self.num_points = npts
-        
-        # Set the controls
-        self.qmin.SetValue(format_number(self.qmin_x))
-        self.qmax.SetValue(format_number(self.qmax_x))
-        self.npts.SetValue(format_number(self.num_points))
-    def checkFitRange(self):
-        """
-            Check the validity of fitting range
-            @note: qmin should always be less than qmax or else each control box
-            background is colored in pink.
-        """
-       
-        flag = True
-        valueMin = self.qmin.GetValue()
-        valueMax = self.qmax.GetValue()
-        # Check for possible values entered
-        #print "fitpage: checkfitrange:",valueMin,valueMax
-        try:
-            if (float(valueMax)> float(valueMin)):
-                self.qmax.SetBackgroundColour(wx.WHITE)
-                self.qmin.SetBackgroundColour(wx.WHITE)
-            else:
-                flag = False
-                self.qmin.SetBackgroundColour("pink")
-                self.qmax.SetBackgroundColour("pink")      
-        except:
-            flag = False
-            self.qmin.SetBackgroundColour("pink")
-            self.qmax.SetBackgroundColour("pink")
-            
-        self.qmin.Refresh()
-        self.qmax.Refresh()
-        return flag
-    
-
-        
-    def onClose(self,event):
-        """ close the page associated with this panel"""
-        self.parent.onClose()
-        
-  
-        
-    def onModel2D(self, event):
+        iy +=1 
+        self.sizer4_4.Add((20,20),(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)   
+        self.sizer4_4.Layout()
+        self.sizer4.Layout()
+        self.SetScrollbars(20,20,200,100)
+             
+    def _onModel2D(self, event):
         """
          call manager to plot model in 2D
@@ -442,7 +227,5 @@
             self._draw_model()
             self.model_view.Disable()
-       
-            
-    
+   
     def select_model(self, model, name):
         """
@@ -454,609 +237,230 @@
         self.parent.draw_model_name = name
         
-        self.set_panel(model)
+        self.set_model_param_sizer(self.model)
         self._draw_model()
-       
-        if hasattr(model ,"model2"):
-            name= model.model2.name
-            items = self.structbox.GetItems()
-            for i in range(len(items)):
-                if items[i]==name:
-                    self.structbox.SetSelection(i)
-                    
-        if hasattr(model ,"model1"):
-            name= model.model1.name
-            items = self.modelbox.GetItems()
-            for i in range(len(items)):
-                if items[i]==name:
-                    self.modelbox.SetSelection(i)
-        else:
-            # Select the model from the combo box
-            items = self.modelbox.GetItems()
-            for i in range(len(items)):
-                if items[i]==name:
-                    self.modelbox.SetSelection(i)
-            self.structbox.SetValue("No Structure")
-                    
+        ## keep the sizer view consistent with the model menu selecting
+        ##
+        self.structurebox.Hide()
+        self.text2.Hide()
+        self.multip_cb.SetValue(False)
+        
+        if hasattr( model,"model1"):
+            self._set_model_sizer_selection( model )
+        
         self.model_view.SetFocus()
-                
-    def _on_select_Disp(self,event):
-        """
-             allow selecting different dispersion
-             self.disp_list should change type later .now only gaussian
-        """
-        type =event.GetString()
-        self.set_panel_dispers( self.disp_list,type )
-                
-    def _on_select_model(self,event):
-        """
-            react when a model is selected from page's combo box
-            post an event to its owner to draw an appropriate theory
-        """
-        self.disable_disp.SetValue(True)
-        self.sizer8.Clear(True)
-        self.sizer7.Clear(True)       
-        self.vbox.Layout()
-        self.SetScrollbars(20,20,55,40)
-        self.Layout()
-        self.parent.GetSizer().Layout()
-        form_factor =self.modelbox.GetClientData(self.modelbox.GetCurrentSelection())
-        struct_factor =self.structbox.GetClientData(self.structbox.GetCurrentSelection())
-       
-        if form_factor!="separator":
-            if struct_factor != None and struct_factor.__name__ != "NoStructure":
-                from sans.models.MultiplicationModel import MultiplicationModel
-                self.model= MultiplicationModel(form_factor(),struct_factor())
-            else:
-                 self.model= form_factor()
-        else:
-            self.model=None 
-            msg= " Select non - model value:%s !Please select another model"%name 
-            wx.PostEvent(self.parent.parent, StatusEvent(status= msg))
-               
-        self.set_model_description(self.model)
-        self.set_panel(self.model)
-        self.name= self.model.name
-        self.model_view.SetFocus()
-        self.parent.model_page.name= self.name
-        self.parent.draw_model_name= self.name
-        self._draw_model()
+                         
+    
+    def set_model_description(self,description,sizer):
+        """
+            fill a sizer with description
+            @param description: of type string
+            @param sizer: wx.BoxSizer()
+        """
+    
+        sizer.Clear(True)
+        box_description= wx.StaticBox(self, -1, 'Model Description')
+        boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL)
             
-    def get_model_box(self): 
-        """ return reference to combox box self.model"""
-        return self.modelbox
-
-    
-    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:
-            raise ValueError,"missing parameter to fit"
-        
-        
-    def set_panel(self,model):
+        sizer_selection=wx.BoxSizer(wx.HORIZONTAL)
+      
+        self.description_show = wx.RadioButton(self, -1, 'Show', style=wx.RB_GROUP)
+        self.description_hide = wx.RadioButton(self, -1, 'Hide')
+        
+        if description=="":
+            self.description_hide.SetValue(True)
+            description=" Description unavailable. Click for details"
+            
+        self.description = wx.StaticText( self,-1,str(description) )
+        
+        self.Bind( wx.EVT_RADIOBUTTON, self._on_display_description,
+                   id=self.description_hide.GetId() )
+        
+        self.Bind( wx.EVT_RADIOBUTTON, self._on_display_description,
+                   id=self.description_show.GetId() )
+        
+        self.model_description = wx.Button(self, -1, "More Details")
+        self.model_description.SetToolTipString("See more description in help menu.")
+        
+        self.page_info.save_radiobox_state( self.description_hide )
+        self.page_info.save_radiobox_state( self.description_show )
+        
+        sizer_selection.Add( self.description_show )
+        sizer_selection.Add( (20,20)) 
+        sizer_selection.Add( self.description_hide )
+        sizer_selection.Add( (20,20)) 
+        sizer_selection.Add( self.model_description )
+        
+         
+        self.sizer_description=wx.BoxSizer(wx.HORIZONTAL)
+        self.sizer_description.Add( self.description, 1, wx.EXPAND | wx.ALL, 10 )
+       
+        boxsizer1.Add( sizer_selection) 
+        boxsizer1.Add( (20,20)) 
+        boxsizer1.Add( self.sizer_description) 
+    
+
+        sizer.Add(boxsizer1,0, wx.EXPAND | wx.ALL, 10)
+        sizer.Layout()
+   
+   
+   
+    def set_range(self, qmin, qmax, npts):
+        """
+            Set the range for the plotted models
+            @param qmin: minimum Q
+            @param qmax: maximum Q
+            @param npts: number of Q bins
+        """
+        # Set the data members
+        self.qmin_x = qmin_x
+        self.qmax_x = qmax_x
+        self.num_points = npts
+        
+        # Set the controls
+        self.qmin.SetValue(format_number(self.qmin_x))
+        self.qmax.SetValue(format_number(self.qmax_x))
+        self.npts.SetValue(format_number(self.num_points))
+        
+        
+    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.sizer5.Clear(True)
+        self.sizer3.Clear(True)
         self.parameters = []
         self.param_toFit=[]
         self.fixed_param=[]
-        if model !=None:
-            self.model = model
+        
+        if model ==None:
+            ##no model avaiable to draw sizer 
+            return
+        box_description= wx.StaticBox(self, -1,str("Model Parameters"))
+        boxsizer1 = wx.StaticBoxSizer(box_description, wx.VERTICAL)
+        sizer = wx.GridBagSizer(5,5)
+        
+        self.model = model
+        self.set_model_description(self.model.description,self.sizer2)
+       
+        keys = self.model.getParamList()
+        #list of dispersion paramaters
+        self.disp_list=self.model.getDispParamList()
+       
+        keys.sort()
+    
+        iy = 1
+        ix = 0
+        self.text1_2 = wx.StaticText(self, -1, 'Names')
+        sizer.Add(self.text1_2,(iy, ix),(1,1),\
+                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
+        ix +=1
+        self.text2_2 = wx.StaticText(self, -1, 'Values')
+        sizer.Add(self.text2_2,(iy, ix),(1,1),\
+                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
+        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()
+        
+
+        for item in keys:
+            if not item in self.disp_list:
+                iy += 1
+                ix = 0
+    
+                name = wx.StaticText(self, -1,item)
+                sizer.Add( name,( iy, ix),(1,1),
+                             wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
+               
+                ix += 1
+                value= self.model.getParam(item)
+                ctl1 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20),
+                                    style=wx.TE_PROCESS_ENTER)
+                
+                ctl1.SetValue(str (format_number(value)))
+                ctl1.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
+                ctl1.Bind(wx.EVT_TEXT_ENTER,self._onparamEnter)
+                sizer.Add(ctl1, (iy,ix),(1,1), wx.EXPAND)
+        
+                ix +=1
+                # Units
+                try:
+                    units = wx.StaticText(self, -1, self.model.details[item][0], style=wx.ALIGN_LEFT)
+                except:
+                    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([None,item, ctl1,
+                                        None,None, None, None,None])
+                
+        iy+=1
+        sizer.Add((20,20),(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
+        
+        #Display units text on panel
+        for item in keys:   
+            if self.model.details[item][0]!='':
+                self.text2_4.Show()
+                break
+            else:
+                self.text2_4.Hide()
+        
+        boxsizer1.Add(sizer)
+        
+        self.sizer3.Add(boxsizer1,0, wx.EXPAND | wx.ALL, 10)
+        self.sizer3.Layout()
+        self.SetScrollbars(20,20,200,100)
+        
+    
             
-            self.set_model_description( self.model) 
-            
-            keys = self.model.getParamList()
-            #list of dispersion paramaters
-            self.disp_list=self.model.getDispParamList()
-           
-            keys.sort()
-            ik=0
-            im=1
-            
-            iy = 1
-            ix = 0
-            self.cb1 = wx.CheckBox(self, -1,"Select all", (10, 10))
-            if self.data!=None:
-                wx.EVT_CHECKBOX(self, self.cb1.GetId(), self.select_all_param)
-                self.cb1.SetValue(False)
-            else:
-                self.cb1.Disable()
-                self.cb1.Hide()
-           
-            self.sizer5.Add(self.cb1,(iy, ix),(1,1),\
-                              wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
-            ix +=1
-            self.text2_2 = wx.StaticText(self, -1, 'Values')
-            self.sizer5.Add(self.text2_2,(iy, ix),(1,1),\
-                                wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
-            ix +=2
-            self.text2_3 = wx.StaticText(self, -1, 'Errors')
-            self.sizer5.Add(self.text2_3,(iy, ix),(1,1),\
-                                wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-            self.text2_3.Hide() 
-            
-           
-            ix +=1
-            self.text2_4 = wx.StaticText(self, -1, 'Units')
-            self.sizer5.Add(self.text2_4,(iy, ix),(1,1),\
-                                wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
-            self.text2_4.Hide()
-            disp_list=self.model.getDispParamList()
-            for item in keys:
-                if not item in disp_list:
-                    iy += 1
-                    ix = 0
-        
-                    cb = wx.CheckBox(self, -1, item, (10, 10))
-                    if self.data!=None:
-                        cb.SetValue(False)
-                        wx.EVT_CHECKBOX(self, cb.GetId(), self.select_param)
-                    else:
-                        cb.Disable()
-                    self.sizer5.Add( cb,( iy, ix),(1,1),  wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
-                   
-                    ix += 1
-                    value= self.model.getParam(item)
-                    ctl1 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20), style=wx.TE_PROCESS_ENTER)
-                    ctl1.SetValue(str (format_number(value)))
-                    ctl1.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
-                    ctl1.Bind(wx.EVT_TEXT_ENTER,self._onparamEnter)
-                    self.sizer5.Add(ctl1, (iy,ix),(1,1), wx.EXPAND)
-                    
-                    ix += 1
-                    text2=wx.StaticText(self, -1, '+/-')
-                    self.sizer5.Add(text2,(iy, ix),(1,1),\
-                                    wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
-                    text2.Hide()  
-                    ix += 1
-                    ctl2 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20), style=wx.TE_PROCESS_ENTER)
-                    self.sizer5.Add(ctl2, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-                    ctl2.Hide()
-                   
-                    ix +=1
-                    # Units
-                    try:
-                        units = wx.StaticText(self, -1, self.model.details[item][0], style=wx.ALIGN_LEFT)
-                    except:
-                        units = wx.StaticText(self, -1, "", style=wx.ALIGN_LEFT)
-                    self.sizer5.Add(units, (iy,ix),(1,1),  wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-               
-                    self.parameters.append([cb,ctl1,text2,ctl2])
-                    
-            iy+=1
-            self.sizer5.Add((20,20),(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
-            
-            #Display units text on panel
-            for item in keys:   
-                if self.model.details[item][0]!='':
-                    self.text2_4.Show()
-                    break
-                else:
-                    self.text2_4.Hide()
-            
-        self.vbox.Layout()
-        self.SetScrollbars(20,20,55,40)
-        self.Layout()
-        self.parent.GetSizer().Layout()
-        
-        
-        
-    def _selectDlg(self):
-        import os
-        dlg = wx.FileDialog(self, "Choose a weight file", os.getcwd(), "", "*.*", wx.OPEN)
-        path = None
-        if dlg.ShowModal() == wx.ID_OK:
-            path = dlg.GetPath()
-        dlg.Destroy()
-        return path
-    def read_file(self, path):
-        try:
-            if path==None:
-                wx.PostEvent(self.parent.parent, StatusEvent(status=\
-                            " Selected Distribution was not loaded: %s"%path))
-                return None, None
-            input_f = open(path, 'r')
-            buff = input_f.read()
-            lines = buff.split('\n')
-            
-            angles = []
-            weights=[]
-            for line in lines:
-                toks = line.split()
-                if len(toks)==2:
-                    try:
-                        angle = float(toks[0])
-                        weight = float(toks[1])
-                    except:
-                        # Skip non-data lines
-                        pass
-                    angles.append(angle)
-                    weights.append(weight)
-            return numpy.array(angles), numpy.array(weights)
-        except:
-            raise 
-        
-          
-    def select_disp_angle(self, event): 
-        """
-            Event for when a user select a parameter to average over.
-            @param event: check box event
-        """
-        
-        
-        # Go through the list of dispersion check boxes to identify which one has changed 
-        for p in self.disp_cb_dict:
-            # Catch which one of the box was just checked or unchecked.
-            if event.GetEventObject() == self.disp_cb_dict[p]:              
-
+        
+class HelpWindow(wx.Frame):
+    def __init__(self, parent, id, title):
+        wx.Frame.__init__(self, parent, id, title, size=(570, 400))
+       
+        from sans.models.CylinderModel import CylinderModel
+        model = CylinderModel()
+        #from sans.models.LineModel import LineModel
+        #model = LineModel()
+        from pageInfo import PageInfo
+        myinfo = PageInfo(self,model)
+        from models import ModelList
+        mylist= ModelList()
+        
+        from sans.models.SphereModel import SphereModel
+        from sans.models.SquareWellStructure import SquareWellStructure
+        from sans.models.DebyeModel import DebyeModel
+        from sans.models.LineModel import LineModel
+        name= "shapes"
+        list1= [SphereModel]
+        mylist.set_list( name, list1)
+        
+        name= "Shape-independent"
+        list1= [DebyeModel]
+        mylist.set_list( name, list1)
+        
+        name= "Structure Factors"
+        list1= [SquareWellStructure]
+        mylist.set_list( name, list1)
+        
+        name= "Added models"
+        list1= [LineModel]
+        mylist.set_list( name, list1)
+        
+        myinfo.model_list_box = mylist.get_list()
+        
+        self.page = ModelPage(self, myinfo) 
+        
+        
+        
+        self.Centre()
+        self.Show(True)
+
+
+   
+if __name__=="__main__":
+    app = wx.App()
+    HelpWindow(None, -1, 'HelpWindow')
+    app.MainLoop()
                 
-                if self.disp_cb_dict[p].GetValue() == True:
-                    # The user wants this parameter to be averaged. 
-                    # Pop up the file selection dialog.
-                    path = self._selectDlg()
-                    
-                    # If nothing was selected, just return
-                    if path is None:
-                        self.disp_cb_dict[p].SetValue(False)
-                        return
-                    
-                    try:
-                        values,weights = self.read_file(path)
-                    except:
-                        wx.PostEvent(self.parent.parent, StatusEvent(status=\
-                            "Could not read input file"))
-                        return
-                    
-                    # If any of the two arrays is empty, notify the user that we won't
-                    # proceed 
-                    if values is None or weights is None:
-                        wx.PostEvent(self.parent.parent, StatusEvent(status=\
-                            "The loaded %s distrubtion is corrupted or empty" % p))
-                        return
-                        
-                    # Tell the user that we are about to apply the distribution
-                    wx.PostEvent(self.parent.parent, StatusEvent(status=\
-                            "Applying loaded %s distribution: %s" % (p, path)))  
-                    
-                    # Create the dispersion objects
-                    disp_model = ArrayDispersion()
-                    disp_model.set_weights(values, weights)
-                    # Store the object to make it persist outside the scope of this method
-                    #TODO: refactor model to clean this up?
-                    self._disp_obj_dict[p] = disp_model
-                    
-                    # Set the new model as the dispersion object for the selected parameter
-                    self.model.set_dispersion(p, disp_model)
-                    
-                    
-                    # Redraw the model
-                    self._draw_model()
-                         
-                else:
-                    # The parameter was un-selected. Go back to Gaussian model (with 0 pts)
-                    disp_model = GaussianDispersion()
-                    # Store the object to make it persist outside the scope of this method
-                    #TODO: refactor model to clean this up?
-                    self._disp_obj_dict[p] = disp_model
-                    
-                    # Set the new model as the dispersion object for the selected parameter
-                    self.model.set_dispersion(p, disp_model)
-                    
-                    # Redraw the model
-                    self._draw_model()
-        return
-
-                      
-                      
-                      
-    def set_panel_dispers(self, disp_list, type="GaussianModel" ):
-        """
-        """
-        
-        self.fittable_param=[]
-        self.fixed_param=[]
-        
-        ix=0
-        iy=1
-                ### this will become a separate method
-        if type== "Select customized Model":
-            ix=0
-            iy=1
-            self.sizer8.Clear(True)        
-            disp1 = wx.StaticText(self, -1, 'Array Dispersion')
-            self.sizer8.Add(disp1,( iy, ix),(1,1),  wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
-            
-            # Look for model parameters to which we can apply an ArrayDispersion model
-            # Add a check box for each parameter.
-            self.disp_cb_dict = {}
-            for p in self.model.dispersion.keys():
-                ix+=1 
-                self.disp_cb_dict[p] = wx.CheckBox(self, -1, p, (10, 10))
-                
-                wx.EVT_CHECKBOX(self, self.disp_cb_dict[p].GetId(), self.select_disp_angle)
-                self.sizer8.Add(self.disp_cb_dict[p], (iy, ix), (1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-            
-            ix =0
-            iy +=1 
-            self.sizer8.Add((20,20),(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)        
-            self.vbox.Layout()
-            self.SetScrollbars(20,20,55,40)
-            self.Layout()
-            self.parent.GetSizer().Layout()  
-           
-        if type== "GaussianModel" :
-
-            self.sizer8.Clear(True)
-            disp = wx.StaticText(self, -1, 'Dispersion')
-            self.sizer8.Add(disp,( iy, ix),(1,1),  wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
-            ix += 1 
-            values = wx.StaticText(self, -1, 'Values')
-            self.sizer8.Add(values,( iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-            ix +=2
-            self.text2_3 = wx.StaticText(self, -1, 'Errors')
-            self.sizer8.Add(self.text2_3,(iy, ix),(1,1),\
-                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-            self.text2_3.Hide() 
-           
-            ix += 1 
-            npts = wx.StaticText(self, -1, 'Npts')
-            self.sizer8.Add(npts,( iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-            ix += 1 
-            nsigmas = wx.StaticText(self, -1, 'Nsigmas')
-            self.sizer8.Add(nsigmas,( iy, ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-            
-            disp_list.sort()
-            #print disp_list,self.model.dispersion
-            for item in self.model.dispersion.keys():
-                name1=item+".width"
-                name2=item+".npts"
-                name3=item+".nsigmas"
-                iy += 1
-                for p in self.model.dispersion[item].keys():
-                    #print "name 1 2 3", name1, name2, name3
-                    if p=="width":
-                        ix = 0
-                        cb = wx.CheckBox(self, -1, name1, (10, 10))
-                        if self.data !=None:
-                            cb.SetValue(False)
-                            wx.EVT_CHECKBOX(self, cb.GetId(), self.select_param)
-                        else:
-                            cb.Disable()
-                        self.sizer8.Add( cb,( iy, ix),(1,1),  wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
-                        ix = 1
-                        value= self.model.getParam(name1)
-                        ctl1 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20), style=wx.TE_PROCESS_ENTER)
-                        ctl1.SetValue(str (format_number(value)))
-                        ctl1.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
-                        ctl1.Bind(wx.EVT_TEXT_ENTER,self._onparamEnter)
-                        self.sizer8.Add(ctl1, (iy,ix),(1,1), wx.EXPAND)
-                        
-                        ix = 2
-                        text2=wx.StaticText(self, -1, '+/-')
-                        self.sizer8.Add(text2,(iy, ix),(1,1),\
-                                        wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
-                        text2.Hide()  
-                        ix = 3
-                        ctl2 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20), style=wx.TE_PROCESS_ENTER)
-                        self.sizer8.Add(ctl2, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-                        ctl2.Hide()
-                        self.fittable_param.append([cb,ctl1,text2,ctl2])
-                       
-                        
-                    elif p=="npts":
-                            ix =4 
-                            value= self.model.getParam(name2)
-                            Tctl = wx.TextCtrl(self, -1, size=(_BOX_WIDTH/2,20), style=wx.TE_PROCESS_ENTER)
-                            Tctl.SetValue(str (format_number(value)))
-                            Tctl.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
-                            Tctl.Bind(wx.EVT_TEXT_ENTER,self._onparamEnter)
-                            self.sizer8.Add(Tctl, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-                            self.fixed_param.append([name2, Tctl])
-                    elif p=="nsigmas":
-                            ix =5 
-                            value= self.model.getParam(name3)
-                            Tctl = wx.TextCtrl(self, -1, size=(_BOX_WIDTH/2,20), style=wx.TE_PROCESS_ENTER)
-                            Tctl.SetValue(str (format_number(value)))
-                            Tctl.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
-                            Tctl.Bind(wx.EVT_TEXT_ENTER,self._onparamEnter)
-                            self.sizer8.Add(Tctl, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-                            self.fixed_param.append([name3, Tctl])
-                wx.PostEvent(self.parent.parent, StatusEvent(status=\
-                            " Selected Distribution: Gaussian"))   
-            ix =0
-            iy +=1 
-            self.sizer8.Add((20,20),(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)        
-            self.vbox.Layout()
-            self.SetScrollbars(20,20,55,40)
-            self.Layout()
-            self.parent.GetSizer().Layout()  
-          
-    def checkFitValues(self,val_min, val_max):
-        """
-            Check the validity of input values
-        """
-        flag = True
-        min_value = val_min.GetValue()
-        max_value = val_max.GetValue()
-        # Check for possible values entered
-        if min_value.lstrip().rstrip() =="-inf":
-            min_value= -numpy.inf
-        if max_value.lstrip().rstrip() =="+inf":
-            max_value= numpy.inf
-        if  min_value==-numpy.inf and max_value== numpy.inf:
-            val_min.SetBackgroundColour(wx.WHITE)
-            val_min.Refresh()
-            val_max.SetBackgroundColour(wx.WHITE)
-            val_max.Refresh()
-            return flag
-        elif max_value== numpy.inf:
-            try:
-                float(min_value)
-                val_min.SetBackgroundColour(wx.WHITE)
-                val_min.Refresh()
-            except:
-                flag = False
-                val_min.SetBackgroundColour("pink")
-                val_min.Refresh()
-            return flag
-        elif min_value==-numpy.inf:
-            try:
-                float(max_value)
-                val_max.SetBackgroundColour(wx.WHITE)
-                val_max.Refresh()
-            except:
-                flag = False
-                val_max.SetBackgroundColour("pink")
-                val_max.Refresh()
-            return flag
-        else:    
-            if (float(min_value)< float(max_value)):
-                val_min.SetBackgroundColour(wx.WHITE)
-                val_min.Refresh()
-            else:
-                flag = False
-                val_min.SetBackgroundColour("pink")
-                val_min.Refresh()
-            return flag   
-           
-        
-    def _onparamEnter(self,event):
-        """ 
-            when enter value on panel redraw model according to changed
-        """
-        self.set_model_parameter()
-        
-    def set_model_parameter(self):
-        """
-        """
-        if len(self.parameters) !=0 and self.model !=None:
-            # Flag to register when a parameter has changed.
-            is_modified = False
-            for item in self.fittable_param:
-                try:
-                     name=str(item[0].GetLabelText())
-                     value= float(item[1].GetValue())
-                     # If the value of the parameter has changed,
-                     # update the model and set the is_modified flag
-                     if value != self.model.getParam(name):
-                         self.model.setParam(name,value)
-                         is_modified = True
-                         
-                except:
-                    #raise
-                    wx.PostEvent(self.parent.parent, StatusEvent(status=\
-                            "Model Drawing  Error:wrong value entered : %s"% sys.exc_value))
-                    return 
-                
-                
-            for item in self.fixed_param:
-                try:
-                     name=str(item[0])
-                     value= float(item[1].GetValue())
-                     # If the value of the parameter has changed,
-                     # update the model and set the is_modified flag
-                     if value != self.model.getParam(name):
-                         self.model.setParam(name,value)
-                         is_modified = True
-                         
-                except:
-                    raise
-                    wx.PostEvent(self.parent.parent, StatusEvent(status=\
-                            "Model Drawing  Error:wrong value entered : %s"% sys.exc_value))
-                
-            for item in self.parameters:
-                try:
-                     name=str(item[0].GetLabelText())
-                     value= float(item[1].GetValue())
-                     # If the value of the parameter has changed,
-                     # update the model and set the is_modified flag
-                     if value != self.model.getParam(name):
-                         self.model.setParam(name,value)
-                         is_modified = True
-                   
-                except:
-                    #raise 
-                    wx.PostEvent(self.parent.parent, StatusEvent(status=\
-                           "Model Drawing  Error:wrong value entered : %s"% sys.exc_value))
-                    return
-                
-                
-            # Here we should check whether the boundaries have been modified.
-            # If qmin and qmax have been modified, update qmin and qmax and 
-            # set the is_modified flag to True
-            from sans.guiframe.utils import check_value
-            if check_value( self.qmin, self.qmax):
-                if float(self.qmin.GetValue()) != self.qmin_x:
-                    self.qmin_x = float(self.qmin.GetValue())
-                    is_modified = True
-                if float(self.qmax.GetValue()) != self.qmax_x:
-                    self.qmax_x = float(self.qmax.GetValue())
-                    is_modified = True
-                self.fitrange = True
-            else:
-                self.fitrange = False
-            if float(self.npts.GetValue()) !=  self.num_points:
-                self.num_points = float(self.npts.GetValue())
-                is_modified = True
-          
-            if is_modified:
-                self._draw_model()            
-            
-    def _draw_model(self):
-        """
-            Method to draw or refresh a plotted model.
-            The method will use the data member from the model page
-            to build a call to the fitting perspective manager.
-            
-            [Note to coder: This way future changes will be done in only one place.] 
-        """
-        if self.model !=None:
-            self.manager.draw_model(self.model, self.model.name, data=self.data,
-                                    qmin=self.qmin_x, qmax=self.qmax_x,
-                                    qstep= self.num_points,
-                                    enable2D=self.enable2D)
-       
-    def select_param(self,event):
-        """
-        
-        """
-        pass
-    def select_all_param(self,event): 
-        """
-        
-        """
-        pass
-    def select_all_param_helper(self):
-        """
-             Allows selecting or delecting button
-        """
-        self.param_toFit=[]
-        if  self.parameters !=[]:
-            if  self.cb1.GetValue()==True:
-                for item in self.parameters:
-                    item[0].SetValue(True)
-                    list= [item[0],item[1],item[2],item[3]]
-                    self.param_toFit.append(list )
-                if len(self.fittable_param)>0:
-                    for item in self.fittable_param:
-                        item[0].SetValue(True)
-                        list= [item[0],item[1],item[2],item[3]]
-                        self.param_toFit.append(list )
-            else:
-                for item in self.parameters:
-                    item[0].SetValue(False)
-                for item in self.fittable_param:
-                    item[0].SetValue(False)
-                self.param_toFit=[]
-               
-                
-       
Index: sansview/perspectives/fitting/models.py
===================================================================
--- sansview/perspectives/fitting/models.py	(revision bb18ef1c74ed79eb0630f198735ad2b14e7913ab)
+++ sansview/perspectives/fitting/models.py	(revision c77d8592395f6684cf45ee976c1cac9db9c00110)
@@ -226,4 +226,8 @@
                          list1 = self.shape_indep_list,
                          list2 = self.struct_list )
+        self._fill_menu( menuinfo = ["Added models", added_models,
+                                            "List of additional models"],
+                                 list1= self.plugins,
+                                 list2 = self.struct_list)
         
         self._fill_simple_menu( menuinfo= ["Structure Factors",structure_factor,
@@ -231,7 +235,5 @@
                                 list1= self.struct_list )
         
-        self._fill_simple_menu( menuinfo = ["Added models", added_models,
-                                            "List of additional models"],
-                                 list1= self.plugins)
+        
         return 0
     
Index: sansview/perspectives/fitting/old_fit_thread.py
===================================================================
--- sansview/perspectives/fitting/old_fit_thread.py	(revision c77d8592395f6684cf45ee976c1cac9db9c00110)
+++ sansview/perspectives/fitting/old_fit_thread.py	(revision c77d8592395f6684cf45ee976c1cac9db9c00110)
@@ -0,0 +1,179 @@
+
+import sys, wx, logging
+import string, numpy, math
+from sans.guicomm.events import NewPlotEvent, StatusEvent  
+from sans.guiframe.calcthread import CalcThread
+import park
+from park.fitresult import FitHandler
+DEFAULT_BEAM = 0.005
+import time
+import thread
+ 
+class ConsoleUpdate(FitHandler):
+    """
+    Print progress to the console.
+    """
+    isbetter = False
+    """Record whether results improved since last update"""
+    progress_delta =  60
+    """Number of seconds between progress updates"""
+    improvement_delta = 5
+    """Number of seconds between improvement updates"""
+    def __init__(self,parent, quiet=False,progress_delta=60,improvement_delta=5):
+        """
+        If quiet is true, only print out final summary, not progress and
+        improvements.
+        """
+        self.parent= parent
+        self.progress_time = time.time()
+        self.progress_percent = 0
+        self.improvement_time = self.progress_time
+        self.isbetter = False
+        self.quiet = quiet
+        self.progress_delta = progress_delta
+        self.improvement_delta = improvement_delta
+
+    def progress(self, k, n):
+        """
+        Report on progress.
+        """
+        if self.quiet: return
+        t = time.time()
+        p = int((100*k)//n)
+        
+        # Show improvements if there are any
+        dt = t - self.improvement_time
+        if self.isbetter and dt > self.improvement_delta:
+            self.result.print_summary()
+            self.isbetter = False
+            self.improvement_time = t
+            
+            wx.PostEvent(self.parent, StatusEvent(status=\
+             "%d%% complete ..."%(p),type="update"))
+       
+        # Update percent complete
+        dp = p-self.progress_percent
+        if dp < 1: return
+        dt = t - self.progress_time
+        if dt > self.progress_delta:
+            if 1 <= dp <= 2:
+                self.progress_percent = p
+                self.progress_time = t
+                wx.PostEvent(self.parent, StatusEvent(status=\
+                                                      "%d%% complete ..."%(p),type="update"))
+       
+            elif 2 < dp <= 5:
+                if p//5 != self.progress_percent//5:
+                    wx.PostEvent(self.parent, StatusEvent(status=\
+                       "%d%% complete ..."%(5*(p//5)),type="update"))
+                    self.progress_percent = p
+                    self.progress_time = t
+            else:
+                if p//10 != self.progress_percent//10:
+                    self.progress_percent = p
+                    self.progress_time = t
+                    wx.PostEvent(self.parent, StatusEvent(status=\
+                   "%d%% complete ..."%(10*(p//10)),type="update"))
+        
+    def improvement(self):
+        """
+        Called when a result is observed which is better than previous
+        results from the fit.
+        """
+        self.isbetter = True
+    
+    def error(self, msg):
+        """
+        Model had an error; print traceback
+        """
+        if self.isbetter:
+            self.result.print_summary()
+        print msg
+
+    def finalize(self):
+        if self.isbetter:
+            self.result.print_summary()
+
+    def abort(self):
+        if self.isbetter:
+            self.result.print_summary()
+
+class FitThread(CalcThread):
+    """Thread performing the fit """
+    
+    def __init__(self,parent, fn,pars=None,cpage=None, qmin=None,qmax=None,ymin=None, ymax=None,
+                 xmin=None,xmax=None,
+                 completefn = None,
+                 updatefn   = None,
+                 yieldtime  = 0.01,
+                 worktime   = 0.01
+                 ):
+        CalcThread.__init__(self,completefn,
+                 updatefn,
+                 yieldtime,
+                 worktime)
+        self.parent = parent
+        self.fitter= fn
+        self.cpage= cpage
+        self.pars = pars
+        self.starttime = 0
+        self.qmin = qmin
+        self.qmax = qmax
+        self.xmin = xmin
+        self.xmax = xmax
+        self.ymin = ymin
+        self.ymax = ymax
+        self.done= False
+        wx.PostEvent(self.parent, StatusEvent(status=\
+                       "Start the computation  ",curr_thread=self,type="start"))
+    def isquit(self):
+        """
+             @raise KeyboardInterrupt: when the thread is interrupted
+        """
+        try:
+            CalcThread.isquit(self)
+        except KeyboardInterrupt:
+            wx.PostEvent(self.parent, StatusEvent(status=\
+                       "Calc %g interrupted"))
+            raise KeyboardInterrupt
+        
+    def update(self):
+        """
+            Is called when values of result are available
+        """
+        wx.PostEvent(self.parent, StatusEvent(status="Computing \
+        ... " ,curr_thread=self,type="update"))
+            
+    def compute(self):
+        """
+            Perform a fit 
+        """
+        try: 
+            self.starttime = time.time()
+            #Sending a progess message to the status bar
+            wx.PostEvent(self.parent, StatusEvent(status=\
+                       "Computing . ...",curr_thread=self,type="progress"))
+            #Handler used for park engine displayed message
+            handler= ConsoleUpdate(parent= self.parent,improvement_delta=0.1)
+            #Result from the fit
+            result = self.fitter.fit(handler= handler)
+        
+            elapsed = time.time()-self.starttime
+            self.complete(result= result,
+                          pars = self.pars,
+                          cpage= self.cpage,
+                          qmin = self.qmin,
+                          qmax = self.qmax,
+                          xmin= self.xmin,
+                          xmax= self.xmax,
+                          ymin = self.ymin,
+                          ymax = self.ymax, 
+                          elapsed=elapsed )
+        except KeyboardInterrupt:
+            # Thread was interrupted, just proceed and re-raise.
+            # Real code should not print, but this is an example...
+            raise
+        except:
+            wx.PostEvent(self.parent, StatusEvent(status="Fitting error: %s" % sys.exc_value))
+            return 
+    
Index: sansview/perspectives/fitting/old_fitpage1D.py
===================================================================
--- sansview/perspectives/fitting/old_fitpage1D.py	(revision 0b99881db3a31559d8bea44b140993d0b56d76fe)
+++ sansview/perspectives/fitting/old_fitpage1D.py	(revision c77d8592395f6684cf45ee976c1cac9db9c00110)
@@ -140,5 +140,9 @@
         # This sizer contains model list and chisqr value 
         #filling sizer4
+        ## structure combox box
+        self.structbox = wx.ComboBox(self, -1)
+        # define combox box
         self.modelbox = wx.ComboBox(self, -1)
+        
         self.tcChi    =  wx.StaticText(self, -1, str(0), style=wx.ALIGN_LEFT)
         self.tcChi.Hide()
@@ -149,6 +153,15 @@
         self.sizer4.Add(wx.StaticText(self,-1,'Model'),(iy,ix),(1,1)\
                   , wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
+        
         ix += 1
         self.sizer4.Add(self.modelbox,(iy,ix),(1,1),  wx.EXPAND|wx.ADJUST_MINSIZE, 0)
+        ix +=1
+        self.text_mult= wx.StaticText(self,-1,' x ')
+        self.sizer4.Add(self.text_mult,(iy,ix),(1,1),  wx.EXPAND|wx.ADJUST_MINSIZE, 0)
+        ix += 1
+        self.sizer4.Add(self.structbox,(iy,ix),(1,1),  wx.EXPAND|wx.ADJUST_MINSIZE, 0)
+        
+        
+        
         ix += 1
         self.sizer4.Add(self.text1_1,(iy,ix),(1,1),\
@@ -262,5 +275,5 @@
         # model on which the fit would be performed
         self.model=None
-        
+       
         self.back_up_model= None
         #dictionary of model name and model class
@@ -282,5 +295,6 @@
         self.Centre()
         self.Layout()
-        self.GrandParent.GetSizer().Layout()
+        
+        self.parent.GetSizer().Layout()
    
     def compute_chisqr2D(self):
@@ -289,5 +303,7 @@
             to the tcChi txtcrl
         """
-        flag=self.checkFitRange()
+        from sans.guiframe.utils import check_value
+        flag = check_value( self.qmin, self.qmax)
+        #flag=self.checkFitRange()
         res=[]
         if flag== True:
@@ -322,5 +338,7 @@
             to the tcChi txtcrl
         """
-        flag=self.checkFitRange()
+        from sans.guiframe.utils import check_value
+        flag = check_value( self.qmin, self.qmax)
+        #flag=self.checkFitRange()
         if flag== True:
             try:
@@ -367,9 +385,18 @@
         self.parent.GetSizer().Layout()
 
-        for item in self.model_list_box.itervalues():
-            name = item.__name__
-            if hasattr(item, "name"):
-                name = item.name
-            
+       
+        name= self.modelbox.GetString(self.modelbox.GetCurrentSelection())
+        form_factor =self.modelbox.GetClientData(self.modelbox.GetCurrentSelection())
+        struct_factor =self.structbox.GetClientData(self.structbox.GetCurrentSelection())
+       
+      
+        if form_factor!="separator":
+            if struct_factor != None and struct_factor.__name__ != "NoStructure":
+                from sans.models.MultiplicationModel import MultiplicationModel
+                self.model= MultiplicationModel(form_factor(),struct_factor())
+            else:
+                 self.model= form_factor() 
+            self.back_up_model= self.model.clone()
+            name= self.model.name
             if name == None:
                 self.qmin.Disable()
@@ -378,37 +405,48 @@
                 self.qmin.Enable()
                 self.qmax.Enable() 
-            
-            if name ==event.GetString():
-                try:
-                    self.model=item()
-                    self.back_up_model= self.model.clone()
-                    evt = ModelEventbox(model=self.model,name=name)
-                    wx.PostEvent(self.event_owner, evt)
-                    self.text1_1.Show()
-                    self.compute_chisqr()
-                    self.tcChi.Show()
-                except:
-                    raise #ValueError,"model.name is not equal to model class name"
-                break  
+            evt = ModelEventbox(model=self.model,name=name)
+            wx.PostEvent(self.event_owner, evt)   
+            self.text1_1.Show()
+            self.tcChi.Show()
+            self.compute_chisqr()
+        
+            
+        else:
+            self.model=None 
+            msg= " Select non - model value:%s ! Previous Model reloaded "%name 
+            wx.PostEvent(self.parent.parent, StatusEvent(status= msg))
+            
+        self.set_panel(self.model)
             
                  
     def onFit(self,event):
-        """ signal for fitting"""
-         
-        flag=self.checkFitRange()
-        self.set_manager(self.manager)
-     
+        """ 
+            signal for fitting .Perform single fit only
+        """
+        from sans.guiframe.utils import check_value
+        flag = check_value( self.qmin, self.qmax) 
+        
+        if not flag:
+            msg= "Fitting range invalid"
+            wx.PostEvent(self.parent.parent, StatusEvent(status= msg ))
+            return 
+        
+        if len(self.param_toFit) <= 0:
+            msg= "Select at least one parameter to fit"
+            wx.PostEvent(self.parent.parent, StatusEvent(status= msg ))
+            return 
+        
         self.qmin_x=float(self.qmin.GetValue())
         self.qmax_x =float( self.qmax.GetValue())
-        if len(self.param_toFit) >0 and flag==True:
-            self.manager.schedule_for_fit( value=1,fitproblem =None) 
-            if hasattr(self.data, "data"):
-                #single fit for Data2D
-                self.manager._on_single_fit(qmin=self.qmin_x,qmax=self.qmax_x,
-                                            ymin=self.data.ymin, ymax=self.data.ymax,
-                                            xmin=self.data.xmin,xmax=self.data.xmax)
-            else:
-                #single fit for Data1D
-                self.manager._on_single_fit(qmin=self.qmin_x,qmax=self.qmax_x)
+        
+        self.manager.schedule_for_fit( value=1,fitproblem =None) 
+        if hasattr(self.data, "data"):
+            #single fit for Data2D
+            self.manager._on_single_fit(qmin=self.qmin_x,qmax=self.qmax_x,
+                                        ymin=self.data.ymin, ymax=self.data.ymax,
+                                        xmin=self.data.xmin,xmax=self.data.xmax)
+        else:
+            #single fit for Data1D
+            self.manager._on_single_fit(qmin=self.qmin_x,qmax=self.qmax_x)
                 
             self.vbox.Layout()
@@ -416,24 +454,7 @@
             self.Layout()
             self.parent.GetSizer().Layout()
-        else:
-            wx.PostEvent(self.parent.parent, StatusEvent(status=\
-                            "Select at least one parameter to fit "))
+        
+            
   
-   
-    def _onTextEnter(self,event):
-        """
-            set a flag to determine if the fitting range entered by the user is valid
-        """
-      
-        try:
-            flag=self.checkFitRange()
-            if flag==True and self.model!=None:
-                self.manager.redraw_model(float(self.xmin.GetValue())\
-                                               ,float(self.xmax.GetValue()))
-        except:
-
-            wx.PostEvent(self.parent.GrandParent, StatusEvent(status=\
-                            "Drawing  Error:wrong value entered %s"% sys.exc_value))
-        
    
     
Index: sansview/perspectives/fitting/old_fitpanel.py
===================================================================
--- sansview/perspectives/fitting/old_fitpanel.py	(revision c77d8592395f6684cf45ee976c1cac9db9c00110)
+++ sansview/perspectives/fitting/old_fitpanel.py	(revision c77d8592395f6684cf45ee976c1cac9db9c00110)
@@ -0,0 +1,244 @@
+import wx
+import wx.aui
+import wx.lib
+import numpy
+import string ,re
+#import models
+_BOX_WIDTH = 80
+
+(FitPageEvent, EVT_FIT_PAGE)   = wx.lib.newevent.NewEvent()
+class FitPanel(wx.aui.AuiNotebook):    
+
+    """
+        FitPanel class contains fields allowing to fit  models and  data
+        @note: For Fit to be performed the user should check at least one parameter
+        on fit Panel window.
+       
+    """
+    ## Internal name for the AUI manager
+    window_name = "Fit panel"
+    ## Title to appear on top of the window
+    window_caption = "Fit Panel "
+    CENTER_PANE = True
+    def __init__(self, parent, *args, **kwargs):
+        wx.aui.AuiNotebook.__init__(self,parent,-1, style=wx.aui.AUI_NB_DEFAULT_STYLE  )
+        
+        
+        self.manager=None
+        self.parent=parent
+        self.event_owner=None
+        
+        pageClosedEvent = wx.aui.EVT_AUINOTEBOOK_PAGE_CLOSE
+        self.Bind(wx.aui.EVT_AUINOTEBOOK_PAGE_CLOSE, self.onClosePage)
+        #Creating the default page --welcomed page
+        self.about_page=None
+        from sans.guiframe.welcome_panel import PanelAbout
+        self.about_page = PanelAbout(self, -1)
+        self.AddPage(self.about_page,"welcome!")
+      
+       
+        #dictionary of miodel {model class name, model class}
+        self.model_list_box={}
+        ## list of structure factor
+        self.struct_list_box=[]
+        # save the title of the last page tab added
+        self.fit_page_name=[]
+        self.draw_model_name=None
+        #model page info
+        self.model_page_number=None
+       
+        self.model_page=None
+        self.sim_page=None
+        # increment number for model name
+        self.count=0
+        #updating the panel
+        self.Update()
+        self.Center()
+        
+        
+    def onClosePage(self, event):
+        """
+             close page and remove all references to the closed page
+        """
+        selected_page = self.GetPage(self.GetSelection())
+        page_number = self.GetSelection()
+        if self.sim_page != selected_page and selected_page!=self.about_page:
+            # remove the check box link to the model name of this page (selected_page)
+            if self.sim_page !=None :
+                self.sim_page.remove_model(selected_page)
+            #remove that page from page_finder of fitting module
+            page_finder=self.manager.get_page_finder() 
+            for page, value in page_finder.iteritems():
+                if page==selected_page:
+                    del page_finder[page]
+                    break
+            #Delete the page from notebook
+            if selected_page.name in self.fit_page_name:
+                self.fit_page_name.remove(selected_page.name)
+                
+            if selected_page.name== self.draw_model_name:
+                self.draw_model_name=None
+                self.model_page=None
+            if  page_number == 1:
+                self.model_page=None
+                self.draw_model_name=None
+            
+        elif selected_page==self.about_page:
+            self.about_page=None
+        else:
+            self.manager.sim_page=None  
+        
+        
+    def set_manager(self, manager):
+        """
+             set panel manager
+             @param manager: instance of plugin fitting
+        """
+        self.manager = manager
+
+        
+    def set_owner(self,owner):
+        """ 
+            set and owner for fitpanel
+            @param owner: the class responsible of plotting
+        """
+        self.event_owner=owner
+        
+    def add_sim_page(self):
+        """
+            Add the simultaneous fit page
+        """
+        from simfitpage import SimultaneousFitPage
+        self.sim_page = SimultaneousFitPage(self, id=-1)
+        self.AddPage(self.sim_page,caption="Simultaneous Fit",select=True)
+        self.sim_page.set_manager(self.manager)
+        return self.sim_page
+        
+    def add_fit_page( self,data ):
+        """ 
+            Add a fitting page on the notebook contained by fitpanel
+            @param data: data to fit
+            @return panel : page just added for futher used. is used by fitting module
+        """     
+        try:
+            name = data.name 
+        except:
+            name = 'Fit'
+        
+        if not name in self.fit_page_name :
+            from fitpage1D import FitPage1D
+            panel = FitPage1D(self,data, -1)
+            panel.name=name
+            
+            panel.set_manager(self.manager)
+            panel.set_owner(self.event_owner)
+            
+            self.AddPage(page=panel,caption=name,select=True)
+            panel.populate_box( self.model_list_box)
+            self.fit_page_name.append(name)
+    
+            return panel 
+        else:
+            return None 
+        
+    def _help_add_model_page(self,model,description,page_title, qmin=0, qmax=0.1, npts=50):
+        """
+            #TODO: fill in description
+            
+            @param qmin: mimimum Q
+            @param qmax: maximum Q
+            @param npts: number of Q points
+        """
+        from modelpage import ModelPage
+        #print "fitpanel model", model
+        panel = ModelPage(self,model,page_title, -1)
+        panel.set_manager(self.manager)
+        panel.set_owner(self.event_owner)
+        self.AddPage(page=panel,caption="Model",select=True)
+        panel.populate_box( self.model_list_box)
+        panel.name = page_title
+        self.draw_model_name=page_title
+        self.model_page_number=self.GetSelection()
+        self.model_page=self.GetPage(self.GetSelection())
+        
+        
+        # Set the range used to plot models
+        self.model_page.set_range(qmin, qmax, npts)
+        
+        # We just created a model page, we are ready to plot the model
+        #self.manager.draw_model(model, model.name)
+        #FOR PLUGIN  for somereason model.name is = BASEcomponent
+        self.manager.draw_model(model, page_title)
+        
+    def new_help_add_model_page(self,model,description,page_title, qmin=0, qmax=0.1, npts=50):
+        """
+            #TODO: fill in description
+            
+            @param qmin: mimimum Q
+            @param qmax: maximum Q
+            @param npts: number of Q points
+        """
+        ## storing page info
+        from pageInfo import  PageInfo
+        myinfo = PageInfo( self, model )
+        myinfo.model_list_box = self.model_list_box
+        from modelpage import ModelPage
+        
+        panel = ModelPage(self,myinfo,page_title)
+        panel.set_manager(self.manager)
+        panel.set_owner(self.event_owner)
+        
+        
+        self.AddPage(page=panel,caption="Model",select=True)
+        panel.populate_box( self.model_list_box)
+        panel.name = page_title
+        self.draw_model_name=page_title
+        self.model_page_number=self.GetSelection()
+        self.model_page=self.GetPage(self.GetSelection())
+        
+        
+        # Set the range used to plot models
+        self.model_page.set_range(qmin, qmax, npts)
+        
+        # We just created a model page, we are ready to plot the model
+        #self.manager.draw_model(model, model.name)
+        #FOR PLUGIN  for some reason model.name is = BASEcomponent
+        self.manager.draw_model(model, page_title)
+     
+        
+    def add_model_page(self,model,description,page_title, qmin=0, qmax=0.1, npts=50, topmenu=False):
+        """
+            Add a model page only one  to display any model selected from the menu or the page combo box.
+            when this page is closed than the user will be able to open a new one
+            
+            @param model: the model for which paramters will be changed
+            @param page_title: the name of the page
+            @param description: [Coder: fill your description!]
+            @param page_title: [Coder: fill your description!]
+            @param qmin: mimimum Q
+            @param qmax: maximum Q
+            @param npts: number of Q points
+        """
+        if topmenu==True:
+            if  self.draw_model_name ==None:
+                self._help_add_model_page(model,description,page_title, qmin=qmin, qmax=qmax, npts=npts)
+            else:
+                self.model_page.select_model(model, page_title)
+          
+    def get_current_page(self):
+        """
+            @return the current page selected
+        """
+        #return self.nb.GetCurrentPage()
+        return self.GetPage(self.GetSelection() )
+  
+    
+     
+    def set_model_list(self,dict):
+         """ 
+             copy a dictionary of model into its own dictionary
+             @param dict: dictionnary made of model name as key and model class
+             as value
+         """
+         self.model_list_box = dict
+  
Index: sansview/perspectives/fitting/old_fitting.py
===================================================================
--- sansview/perspectives/fitting/old_fitting.py	(revision c77d8592395f6684cf45ee976c1cac9db9c00110)
+++ sansview/perspectives/fitting/old_fitting.py	(revision c77d8592395f6684cf45ee976c1cac9db9c00110)
@@ -0,0 +1,1053 @@
+import  re
+import sys, wx, logging
+import string, numpy, math
+
+from copy import deepcopy 
+from danse.common.plottools.plottables import Data1D, Theory1D,Data2D
+from danse.common.plottools.PlotPanel import PlotPanel
+from sans.guicomm.events import NewPlotEvent, StatusEvent  
+from sans.guicomm.events import EVT_SLICER_PANEL,ERR_DATA
+
+from sans.fit.AbstractFitEngine import Model,FitData1D,FitData2D#,Data,
+from fitproblem import FitProblem
+from fitpanel import FitPanel
+from fit_thread import FitThread
+import models
+import fitpage1D
+
+DEFAULT_BEAM = 0.005
+DEFAULT_QMIN = 0.0
+DEFAULT_QMAX = 0.1
+DEFAULT_NPTS = 50
+import time
+import thread
+
+class Plugin:
+    """
+        Fitting plugin is used to perform fit 
+    """
+    def __init__(self):
+        ## Plug-in name
+        self.sub_menu = "Fitting"
+        
+        ## Reference to the parent window
+        self.parent = None
+        #Provide list of models existing in the application
+        self.menu_mng = models.ModelManager()
+        ## List of panels for the simulation perspective (names)
+        self.perspective = []
+        #list of panel to send to guiframe
+        self.mypanels=[]
+        # reference to the current running thread
+        self.calc_thread = None
+        # Start with a good default
+        self.elapsed = 0.022
+        # the type of optimizer selected, park or scipy
+        self.fitter  = None
+        #Flag to let the plug-in know that it is running stand alone
+        self.standalone=True
+        ## Fit engine
+        self._fit_engine = 'scipy'
+        #List of selected data
+        self.selected_data_list=[]
+        # Log startup
+        logging.info("Fitting plug-in started")   
+        # model 2D view
+        self.model2D_id=None
+        #keep reference of the simultaneous fit page
+        self.sim_page=None
+        #dictionary containing data name and error on dy of that data 
+        self.err_dy={}
+        
+    def _on_data_error(self, event):
+        """
+            receives and event from plotting plu-gins to store the data name and 
+            their errors of y coordinates for 1Data hide and show error
+        """
+        self.err_dy= event.err_dy
+        
+    def populate_menu(self, id, owner):
+        """
+            Create a menu for the Fitting plug-in
+            @param id: id to create a menu
+            @param owner: owner of menu
+            @ return : list of information to populate the main menu
+        """
+        #Menu for fitting
+        self.menu1 = wx.Menu()
+        id1 = wx.NewId()
+        self.menu1.Append(id1, '&Simultaneous')
+        wx.EVT_MENU(owner, id1, self.on_add_sim_page)
+        #Set park engine
+        id3 = wx.NewId()
+        self.menu1.AppendCheckItem(id3, "park") 
+        wx.EVT_MENU(owner, id3, self._onset_engine)
+        
+        #menu for model
+        menu2 = wx.Menu()
+    
+        self.menu_mng.populate_menu(menu2, owner)
+        id2 = wx.NewId()
+        owner.Bind(models.EVT_MODEL,self._on_model_menu)
+      
+        self.fit_panel.set_owner(owner)
+        self.fit_panel.set_model_list(self.menu_mng.get_model_list())
+        owner.Bind(fitpage1D.EVT_MODEL_BOX,self._on_model_panel)
+        
+        #create  menubar items
+        return [(id, self.menu1, "Fitting"),(id2, menu2, "Model")]
+    
+    def on_add_sim_page(self, event):
+        """
+        """
+        self.sim_page= self.fit_panel.add_sim_page()
+        self.sim_page.add_model(self.page_finder)
+        
+        
+    def help(self, evt):
+        """
+            Show a general help dialog. 
+            TODO: replace the text with a nice image
+        """
+        #from helpDialog import  HelpWindow
+        #dialog = HelpWindow(None, -1, 'HelpWindow')
+        #if dialog.ShowModal() == wx.ID_OK:
+        #    pass
+        #dialog.Destroy()
+        from helpPanel import  HelpWindow
+        frame = HelpWindow(None, -1, 'HelpWindow')    
+        frame.Show(True)
+        
+        
+    def get_context_menu(self, graph=None):
+        """
+            Get the context menu items available for P(r)
+            @param graph: the Graph object to which we attach the context menu
+            @return: a list of menu items with call-back function
+        """
+        self.graph=graph
+        for item in graph.plottables:
+            if item.__class__.__name__ is "Data2D":
+                return [["Select data  for Fitting",\
+                          "Dialog with fitting parameters ", self._onSelect]] 
+            else:
+                #if item.name==graph.selected_plottable and\
+                # item.__class__.__name__ is  "Data1D":
+                if item.name==graph.selected_plottable :
+                    return [["Select data  for Fitting", \
+                             "Dialog with fitting parameters ", self._onSelect]] 
+        return []   
+
+
+    def get_panels(self, parent):
+        """
+            Create and return a list of panel objects
+        """
+        self.parent = parent
+        # Creation of the fit panel
+        self.fit_panel = FitPanel(self.parent, -1)
+        #Set the manager forthe main panel
+        self.fit_panel.set_manager(self)
+        # List of windows used for the perspective
+        self.perspective = []
+        self.perspective.append(self.fit_panel.window_name)
+        # take care of saving  data, model and page associated with each other
+        self.page_finder = {}
+        #index number to create random model name
+        self.index_model = 0
+        self.index_theory= 0
+        self.parent.Bind(EVT_SLICER_PANEL, self._on_slicer_event)
+        self.parent.Bind( ERR_DATA, self._on_data_error)
+        
+        #create the fitting panel
+        #return [self.fit_panel]
+        
+        self.mypanels.append(self.fit_panel)
+        return self.mypanels
+
+        
+    def _on_slicer_event(self, event):
+        """
+        """
+        #print "fitting:slicer event ", event.panel
+        if event.panel!=None:
+            new_panel = event.panel
+            # Set group ID if available
+            event_id = self.parent.popup_panel(new_panel)
+            self.menu1.Append(event_id, new_panel.window_caption, 
+                             "Show %s plot panel" % new_panel.window_caption)
+            # Set UID to allow us to reference the panel later
+            new_panel.uid = event_id
+            new_panel
+            self.mypanels.append(new_panel) 
+        return    
+    
+        
+    def _on_show_panel(self, event):
+        print "_on_show_panel: fitting"
+      
+      
+    def get_perspective(self):
+        """
+            Get the list of panel names for this perspective
+        """
+        return self.perspective
+    
+    
+    def on_perspective(self, event):
+        """
+            Call back function for the perspective menu item.
+            We notify the parent window that the perspective
+            has changed.
+        """
+        self.parent.set_perspective(self.perspective)
+    
+    
+    def post_init(self):
+        """
+            Post initialization call back to close the loose ends
+            [Somehow openGL needs this call]
+        """
+        self.parent.set_perspective(self.perspective)
+
+
+    def copy_data(self, item, dy):
+        """
+        """
+        detector=None
+        source=None
+        dxl=None
+        dxw=None
+        if hasattr(item, "dxl"):
+            dxl = item.dxl
+        if hasattr(item, "dxw"):
+            dxw = item.dxw
+        if hasattr(item, "detector"):
+            detector =item.detector
+        if hasattr(item, "source"):
+            source =item.source
+        from sans.guiframe import dataFitting 
+        data= dataFitting.Data1D(x=item.x, y=item.y, dy=dy, dxl=dxl, dxw=dxw)
+        data.name=item.name
+        data.detector=detector
+        data.source= source
+        return data
+
+
+    def _onSelect(self,event):
+        """ 
+            when Select data to fit a new page is created .Its reference is 
+            added to self.page_finder
+        """
+        self.panel = event.GetEventObject()
+        for item in self.panel.graph.plottables:
+            if item.name == self.panel.graph.selected_plottable:
+                if len(self.err_dy)>0:
+                    if item.name in  self.err_dy.iterkeys():
+                        dy= self.err_dy[item.name]
+                        data= self.copy_data(item, dy)
+                    else:
+                        data= item
+                else:
+                    if item.dy==None:
+                        dy= numpy.zeros(len(item.y))
+                        dy[dy==0]=1
+                        data= self.copy_data(item, dy)
+                    else:
+                        data= item
+            else:
+                data= item
+                        
+                        
+            if item.name == self.panel.graph.selected_plottable or\
+                 item.__class__.__name__ is "Data2D":
+                #find a name for the page created for notebook
+                #print "fitting", self.panel
+                try:
+                   
+                    #page = self.fit_panel.add_fit_page(item)
+                    page = self.fit_panel.add_fit_page(data)
+                    #page, model_name = self.fit_panel.add_fit_page(item)
+                    # add data associated to the page created
+                   
+                    if page !=None:   
+                        #create a fitproblem storing all link to data,model,page creation
+                        self.page_finder[page]= FitProblem()
+                        #self.page_finder[page].save_model_name(model_name)  
+                        self.page_finder[page].add_plotted_data(item)
+                        self.page_finder[page].add_fit_data(data)
+                       
+                            
+                        wx.PostEvent(self.parent, StatusEvent(status="Page Created"))
+                    else:
+                        wx.PostEvent(self.parent, StatusEvent(status="Page was already Created"))
+                except:
+                    #raise
+                    wx.PostEvent(self.parent, StatusEvent(status="Creating Fit page: %s"\
+                    %sys.exc_value))
+                    return
+                    
+                    
+    def schedule_for_fit(self,value=0,fitproblem =None):  
+        """
+        
+        """   
+        if fitproblem !=None:
+            fitproblem.schedule_tofit(value)
+        else:
+            current_pg=self.fit_panel.get_current_page() 
+            for page, val in self.page_finder.iteritems():
+                if page ==current_pg :
+                    val.schedule_tofit(value)
+                    break
+                      
+                    
+    def get_page_finder(self):
+        """ @return self.page_finder used also by simfitpage.py"""  
+        return self.page_finder 
+    
+    
+    def set_page_finder(self,modelname,names,values):
+        """
+             Used by simfitpage.py to reset a parameter given the string constrainst.
+             @param modelname: the name ot the model for with the parameter has to reset
+             @param value: can be a string in this case.
+             @param names: the paramter name
+             @note: expecting park used for fit.
+        """  
+        #sim_page=self.fit_panel.GetPage(1) 
+        sim_page= self.sim_page
+        for page, value in self.page_finder.iteritems():
+            if page != sim_page:
+                list=value.get_model()
+                model=list[0]
+                #print "fitting",model.name,modelname, values
+                if model.name== modelname:
+                    value.set_model_param(names,values)
+                    break
+
+   
+                            
+    def split_string(self,item): 
+        """
+            receive a word containing dot and split it. used to split parameterset
+            name into model name and parameter name example:
+            paramaterset (item) = M1.A
+            @return model_name =M1 , parameter name =A
+        """
+        if string.find(item,".")!=-1:
+            param_names= re.split("\.",item)
+            model_name=param_names[0]
+            param_name=param_names[1]  
+            return model_name,param_name
+        
+   
+    def _single_fit_completed(self,result,pars,cpage,qmin,qmax,elapsed=None,
+                              ymin=None, ymax=None, xmin=None, xmax=None):
+        """
+            Display fit result on one page of the notebook.
+            @param result: result of fit 
+            @param pars: list of names of parameters fitted
+            @param current_pg: the page where information will be displayed
+            @param qmin: the minimum value of x to replot the model 
+            @param qmax: the maximum value of x to replot model
+          
+        """
+        
+        #print "single fit ", pars,result.pvec,result.stderr,result.fitness
+        wx.PostEvent(self.parent, StatusEvent(status="Single fit \
+        complete " , type="stop"))
+        try:
+            for page, value in self.page_finder.iteritems():
+                if page==cpage :
+                    #fitdata = value.get_data()
+                    list = value.get_model()
+                    model= list[0]
+                    break
+            i = 0
+          
+            for name in pars:
+                if result.pvec.__class__==numpy.float64:
+                    model.setParam(name,result.pvec)
+                else:
+                    #print "fitting result : chisqr",result.fitness
+                    #print "fitting result : pvec",result.pvec
+                    #print "fitting result : stderr",result.stderr
+                    model.setParam(name,result.pvec[i])
+                    #print "fitting: single fit", name, result.pvec[i]
+                    i += 1
+           
+           
+            cpage.onsetValues(result.fitness, result.pvec,result.stderr)
+            #title="Fitted model 2D "
+            self.plot_helper(currpage=cpage,qmin=qmin,qmax=qmax,
+                             ymin=ymin, ymax=ymax,
+                             xmin=xmin, xmax=xmax,title=None)
+        except:
+            #raise
+            wx.PostEvent(self.parent, StatusEvent(status="Fitting error: %s" % sys.exc_value))
+            return
+       
+       
+    def _simul_fit_completed(self,result,qmin,qmax, elapsed,pars=None,cpage=None,
+                             xmin=None, xmax=None, ymin=None, ymax=None):
+        """
+            Parameter estimation completed, 
+            display the results to the user
+            @param alpha: estimated best alpha
+            @param elapsed: computation time
+        """
+        if cpage!=None:
+            self._single_fit_completed(result=result,pars=pars,cpage=cpage,
+                                       qmin=qmin,qmax=qmax,
+                              ymin=ymin, ymax=ymax, xmin=xmin, xmax=xmax)
+            return
+        else:
+            wx.PostEvent(self.parent, StatusEvent(status="Simultaneous fit \
+            complete ", type="stop"))
+            #print "result",cpage,str(result),result.parameters,result.fitness,result.stderr
+            
+            try:
+                for page, value in self.page_finder.iteritems():
+                    if value.get_scheduled()==1:
+                        #fitdata = value.get_data()
+                        list = value.get_model()
+                        model= list[0]
+                       
+                        small_out = []
+                        small_cov = []
+                        i = 0
+                        #Separate result in to data corresponding to each page
+                        for p in result.parameters:
+                            model_name,param_name = self.split_string(p.name)  
+                            if model.name == model_name:
+                                small_out.append(p.value )
+                                if p.stderr==None:
+                                    p.stderr=numpy.nan
+                                small_cov.append(p.stderr)
+                                model.setParam(param_name,p.value)  
+                        # Display result on each page 
+                        #print "mmmm",p.value,p.stderr
+                        page.onsetValues(result.fitness, small_out,small_cov)
+                        #print "out,err",small_out,small_cov
+                        #Replot model
+                        self.plot_helper(currpage= page,qmin= qmin,qmax= qmax,
+                                         xmin=xmin, xmax=xmax,
+                                         ymin=ymin, ymax=ymax) 
+            except:
+                wx.PostEvent(self.parent, StatusEvent(status="Simultaneous Fitting error: %s" % sys.exc_value))
+                return
+            
+            
+    def stop_fit(self):
+        """
+        """
+        if self.calc_thread != None and self.calc_thread.isrunning():
+            #self.calc_thread.interrupt()
+            self.calc_thread.stop()
+            wx.PostEvent(self.parent, StatusEvent(status="Fitting  \
+                is cancelled" , type="stop"))
+            
+            
+    def _on_single_fit(self,id=None,qmin=None, qmax=None,ymin=None, ymax=None,xmin=None,xmax=None):
+        """ 
+            perform fit for the  current page  and return chisqr,out and cov
+            @param engineName: type of fit to be performed
+            @param id: unique id corresponding to a fit problem(model, set of data)
+            @param model: model to fit
+            
+        """
+        #print "in single fitting"
+        #set an engine to perform fit
+        from sans.fit.Fitting import Fit
+        self.fitter= Fit(self._fit_engine)
+        #Setting an id to store model and data in fit engine
+        self.fit_id= 0
+        if id!=None:
+            self.fit_id= id
+        
+        page_fitted=None
+        fit_problem=None
+        #Get information (model , data) related to the page on 
+        #with the fit will be perform
+        current_pg=self.fit_panel.get_current_page() 
+        #simul_pg=self.fit_panel.GetPage(1 )
+        simul_pg=self.sim_page
+        pars=[]   
+        #for page, value in self.page_finder.iteritems():
+        if current_pg!= simul_pg:
+        #    if  value.get_scheduled() ==1 :
+            value = self.page_finder[current_pg]
+            metadata =  value.get_fit_data()
+            list = value.get_model()
+            model = list[0]
+            smearer= value.get_smearer()
+           
+    
+            #Create list of parameters for fitting used
+            
+            templist=[]
+            try:
+                #templist=current_pg.get_param_list()
+                templist=current_pg.get_param_list()
+                for element in templist:
+                    pars.append(str(element[0].GetLabelText()))
+                pars.sort()
+                #Do the single fit
+                self.fitter.set_model(Model(model), self.fit_id, pars) 
+                if self._fit_engine=="scipy":
+                    wx.PostEvent(self.parent, StatusEvent(status="Parameters range will\
+                     be ignored for %s fitting engine"%str(self._fit_engine)))
+                #print "args...:",metadata,self.fit_id,smearer,qmin,qmax,ymin,ymax
+                dy=[]
+                x=[]
+                y=[]
+                if metadata.__class__ in  ["Data1D","Theory1D"]:
+                    for i in range(len(metadata.dy)):
+                        if metadata.dy[i] !=0:
+                            dy.append(metadata.dy[i])
+                            x.append(metadata.x[i])
+                            y.append(metadata.y[i])
+                    if len(dy)>0:        
+                        metadata.dy=numpy.zeros(len(dy))
+                        metadata.dy=dy
+                        metadata.y=numpy.zeros(len(y))
+                        metadata.y=y
+                        metadata.x=numpy.zeros(len(x))
+                        metadata.x=x
+                self.fitter.set_data(data=metadata,Uid=self.fit_id,
+                                     smearer=smearer,qmin= qmin,qmax=qmax,
+                                     ymin=ymin,ymax=ymax)
+                self.fitter.select_problem_for_fit(Uid=self.fit_id,value=value.get_scheduled())
+                page_fitted=current_pg
+                #self.fit_id+=1
+                #self.schedule_for_fit( 0,value) 
+            except:
+                wx.PostEvent(self.parent, StatusEvent(status="Single Fit error: %s" % sys.exc_value))
+                return
+            # make sure to keep an alphabetic order 
+            #of parameter names in the list      
+            try:
+                # If a thread is already started, stop it
+                if self.calc_thread != None and self.calc_thread.isrunning():
+                    self.calc_thread.stop()
+                        
+                self.calc_thread =FitThread(parent =self.parent,
+                                            fn= self.fitter,
+                                            pars= pars,
+                                            cpage= page_fitted,
+                                           qmin=qmin,
+                                           qmax=qmax,
+                                          
+                                           completefn=self._single_fit_completed,
+                                           updatefn=None)
+                self.calc_thread.queue()
+                self.calc_thread.ready(2.5)
+             
+            except:
+                wx.PostEvent(self.parent, StatusEvent(status="Single Fit error: %s" % sys.exc_value))
+                return
+         
+    def _on_simul_fit(self, id=None,qmin=None,qmax=None, ymin=None, ymax=None):
+        """ 
+            perform fit for all the pages selected on simpage and return chisqr,out and cov
+            @param engineName: type of fit to be performed
+            @param id: unique id corresponding to a fit problem(model, set of data)
+             in park_integration
+            @param model: model to fit
+            
+        """
+        #set an engine to perform fit
+        from sans.fit.Fitting import Fit
+        self.fitter= Fit(self._fit_engine)
+        self.fit_id= 0
+        #Setting an id to store model and data
+        if id!=None:
+             self.fit_id= id
+       
+        
+        for page, value in self.page_finder.iteritems():
+            try:
+                if value.get_scheduled()==1:
+                    metadata = value.get_fit_data()
+                    list = value.get_model()
+                    model= list[0]
+                    #Create dictionary of parameters for fitting used
+                    cpage= page
+                    print ""
+                    pars = []
+                    templist = []
+                    templist = page.get_param_list()
+                    for element in templist:
+                        try:
+                            name = str(element[0].GetLabelText())
+                            pars.append(name)
+                        except:
+                            wx.PostEvent(self.parent, StatusEvent(status="Simultaneous Fit error: %s" % sys.exc_value))
+                            return
+                    # need to check this print "new model "
+                    
+                    new_model=Model(model)
+                    param=value.get_model_param()
+                    
+                    if len(param)>0:
+                        for item in param:
+                            param_value = item[1]
+                            param_name = item[0]
+    
+                            new_model.parameterset[ param_name].set( param_value )
+                        
+                    self.fitter.set_model(new_model, self.fit_id, pars) 
+                    #print "sim-->model",metadata,model,self.fit_id, pars
+                    dy=[]
+                    x=[]
+                    y=[]
+                    if metadata.__class__ in  ["Data1D","Theory1D"]:
+                        for i in range(len(metadata.dy)):
+                            if metadata.dy[i] !=0:
+                                dy.append(metadata.dy[i])
+                                x.append(metadata.x[i])
+                                y.append(metadata.y[i])
+                            if len(dy)>0:        
+                                metadata.dy=numpy.zeros(len(dy))
+                                metadata.dy=dy
+                                metadata.y=numpy.zeros(len(y))
+                                metadata.y=y
+                                metadata.x=numpy.zeros(len(x))
+                                metadata.x=x
+                    self.fitter.set_data(metadata,self.fit_id,qmin,qmax,ymin,ymax)
+                    #print "sim---->value of problem",value.get_scheduled()
+                    self.fitter.select_problem_for_fit(Uid=self.fit_id,value=value.get_scheduled())
+                    self.fit_id += 1 
+                    value.clear_model_param()
+                    #self.schedule_for_fit( 0,value) 
+            except:
+                wx.PostEvent(self.parent, StatusEvent(status="Simultaneous Fit error: %s" % sys.exc_value))
+                return 
+        #Do the simultaneous fit
+        try:
+            # If a thread is already started, stop it
+            if self.calc_thread != None and self.calc_thread.isrunning():
+                self.calc_thread.stop()
+            if  self.fit_id==1:
+                self.calc_thread =FitThread(parent =self.parent,
+                                        fn= self.fitter,
+                                       qmin=qmin,
+                                       qmax=qmax,
+                                       ymin= ymin,
+                                       ymax= ymax,
+                                       cpage=cpage,
+                                       pars= pars,
+                                       completefn= self._simul_fit_completed,
+                                       updatefn=None)
+                      
+            else:
+                self.calc_thread =FitThread(parent =self.parent,
+                                        fn= self.fitter,
+                                       qmin=qmin,
+                                       qmax=qmax,
+                                       ymin= ymin,
+                                       ymax= ymax,
+                                       completefn= self._simul_fit_completed,
+                                       updatefn=None)
+            self.calc_thread.queue()
+            self.calc_thread.ready(2.5)
+            
+        except:
+            wx.PostEvent(self.parent, StatusEvent(status="Simultaneous Fit error: %s" % sys.exc_value))
+            return
+        
+        
+    def _onset_engine(self,event):
+        """ 
+            set engine to scipy
+        """
+        if self._fit_engine== 'park':
+            self._on_change_engine('scipy')
+        else:
+            self._on_change_engine('park')
+        wx.PostEvent(self.parent, StatusEvent(status="Engine set to: %s" % self._fit_engine))
+  
+    
+    def _on_change_engine(self, engine='park'):
+        """
+            Allow to select the type of engine to perform fit 
+            @param engine: the key work of the engine
+        """
+        self._fit_engine = engine
+   
+   
+    def _on_model_panel(self, evt):
+        """
+            react to model selection on any combo box or model menu.plot the model  
+        """
+       
+        model = evt.model
+        name = evt.name
+        
+        #print "name fitting", name
+        #sim_page=self.fit_panel.GetPage(1)
+        sim_page=self.sim_page
+        current_pg = self.fit_panel.get_current_page() 
+        if current_pg != sim_page:
+            current_pg.set_panel(model)
+            #model.name = self.page_finder[current_pg].get_name()
+            #print "model name", model.name
+            model.name="M"+str(self.index_model)
+            try:
+                metadata=self.page_finder[current_pg].get_data()
+                M_name=model.name+"= "+name+"("+metadata.group_id+")"
+            except:
+                M_name=model.name+"= "+name
+            self.index_model += 1  
+            
+            
+            # save model name
+            
+            # save the name containing the data name with the appropriate model
+            self.page_finder[current_pg].set_model(model,M_name)
+            self.plot_helper(currpage= current_pg,qmin= None,qmax= None)
+            if self.sim_page!=None:
+                self.sim_page.add_model(self.page_finder)
+        
+    def  set_smearer(self,smearer):
+        """
+        
+        """   
+        current_pg=self.fit_panel.get_current_page()
+        self.page_finder[current_pg].set_smearer(smearer)
+         
+    def redraw_model(self,qmin= None,qmax= None):
+        """
+            Draw a theory according to model changes or data range.
+            @param qmin: the minimum value plotted for theory
+            @param qmax: the maximum value plotted for theory
+        """
+        current_pg=self.fit_panel.get_current_page()
+        for page, value in self.page_finder.iteritems():
+            if page ==current_pg :
+                break 
+        self.plot_helper(currpage=page,qmin= qmin,qmax= qmax)
+        
+    def plot_helper(self,currpage, fitModel=None, qmin=None,qmax=None,
+                    ymin=None,ymax=None, xmin=None, xmax=None,title=None ):
+        """
+            Plot a theory given a model and data
+            @param model: the model from where the theory is derived
+            @param currpage: page in a dictionary referring to some data
+        """
+        if self.fit_panel.GetPageCount() >1:
+            for page in self.page_finder.iterkeys():
+                if  page==currpage :  
+                    data=self.page_finder[page].get_plotted_data()
+                    list=self.page_finder[page].get_model()
+                    model=list[0]
+                    break 
+            #print "model in fitting",model
+            if data!=None and data.__class__.__name__ != 'Data2D':
+                theory = Theory1D(x=[], y=[])
+                theory.name = model.name
+                theory.group_id = data.group_id
+                theory.id = "Model"
+                   
+                x_name, x_units = data.get_xaxis() 
+                y_name, y_units = data.get_yaxis() 
+                theory.xaxis(x_name, x_units)
+                theory.yaxis(y_name, y_units)
+                if qmin == None :
+                   qmin = min(data.x)
+                if qmax == None :
+                   qmax = max(data.x)
+                try:
+                    tempx = qmin
+                    tempy = model.run(qmin)
+                    theory.x.append(tempx)
+                    theory.y.append(tempy)
+                except :
+                        wx.PostEvent(self.parent, StatusEvent(status="fitting \
+                        skipping point x %g %s" %(qmin, sys.exc_value)))
+                           
+                for i in range(len(data.x)):
+                    try:
+                        if data.x[i]> qmin and data.x[i]< qmax: 
+                            tempx = data.x[i]
+                            tempy = model.run(tempx)
+                            theory.x.append(tempx) 
+                            theory.y.append(tempy)
+                           
+                    except:
+                        wx.PostEvent(self.parent, StatusEvent(status="fitting \
+                        skipping point x %g %s" %(data.x[i], sys.exc_value)))   
+                try:
+                    tempx = qmax
+                    tempy = model.run(qmax)
+                    theory.x.append(tempx)
+                    theory.y.append(tempy)
+                except:
+                    wx.PostEvent(self.parent, StatusEvent(status="fitting \
+                        skipping point x %g %s" %(qmin, sys.exc_value)) )
+                    
+                wx.PostEvent(self.parent, NewPlotEvent(plot=theory,
+                                                title=str(data.name)))
+            else:
+               
+                theory=Data2D(data.data, data.err_data)
+                theory.name= model.name
+                if title !=None:
+                    self.title = title
+                    theory.id= self.title
+                    theory.group_id= self.title+data.name
+                else:
+                    self.title= "Analytical model 2D "
+                    theory.id= "Model"
+                    theory.group_id= "Model"+data.name
+                theory.x_bins= data.x_bins
+                theory.y_bins= data.y_bins
+                tempy=[]
+                #print "max x,y",max(data.xmax,data.xmin),max(data.ymax,data.ymin)
+                if qmin==None:
+                    qmin=0#min(math.fabs(data.xmax),math.fabs(data.ymin))
+                if qmax==None:
+                    qmax=math.sqrt(math.pow(max(math.fabs(data.xmax),math.fabs(data.xmin)),2)/
+                                   +math.pow(max(math.fabs(data.ymax),math.fabs(data.ymin)),2))
+                if ymin==None:
+                    ymin=data.ymin
+                if ymax==None:
+                    ymax=data.ymax
+                if xmin ==None:
+                    xmin=data.xmin
+                if xmax==None:
+                    xmax=data.xmax      
+                                  
+                theory.data = numpy.zeros((len(data.y_bins),len(data.x_bins)))
+                for j in range(len(data.y_bins)):
+                    for i in range(len(data.x_bins)):
+                        tempqij=math.sqrt((math.pow(data.y_bins[j],2)+math.pow(data.x_bins[i],2)))
+                        if tempqij>= qmin and tempqij<= qmax: 
+                            theory.data[j][i]=model.runXY([data.y_bins[j],data.x_bins[i]])
+                        else:
+                            theory.data[j][i]=0 #None # Later, We need to decide which of  0 and None is better.
+                #print "len(data.x_bins),len(data.y_bins);",len(data.x_bins),len(data.y_bins),qmax
+                #print "fitting : plot_helper:", theory.image
+                #print "fitting : plot_helper:",theory.image
+                theory.detector= data.detector
+                theory.source= data.source
+                
+                theory.qmin= qmin
+                theory.qmax= qmax
+                theory.ymin= ymin
+                theory.ymax= ymax
+                theory.xmin= xmin
+                theory.xmax= xmax
+        
+                wx.PostEvent(self.parent, NewPlotEvent(plot=theory,
+                                                title=self.title +str(data.name)))
+        
+        
+    def _on_model_menu(self, evt):
+        """
+            Plot a theory from a model selected from the menu
+        """
+        name = evt.model.__name__
+        if hasattr(evt.model, "name"):
+            name = evt.model.name
+        #print "on model menu", name
+        model=evt.model()
+        description=model.description
+        
+        # Create a model page. If a new page is created, the model
+        # will be plotted automatically. If a page already exists,
+        # the content will be updated and the plot refreshed
+        self.fit_panel.add_model_page(model,description,name,topmenu=True)
+        
+    def draw_model(self,model,name ,data=None,description=None,enable1D=True, enable2D=False,
+                   qmin=DEFAULT_QMIN, qmax=DEFAULT_QMAX, qstep=DEFAULT_NPTS):
+        """
+             draw model with default data value
+        """
+        if data !=None:
+            self.redraw_model(qmin,qmax)
+            return 
+        self._draw_model1D(model,name,model.description, enable1D,qmin,qmax, qstep)
+        self._draw_model2D(model=model,
+                           description=model.description,
+                           enable2D= enable2D,
+                           qmin=qmin,
+                           qmax=qmax,
+                           qstep=qstep)
+        
+              
+    def _draw_model1D(self,model,name,description=None, enable1D=True,
+                      qmin=DEFAULT_QMIN, qmax=DEFAULT_QMAX, qstep=DEFAULT_NPTS):
+        """
+        
+        """
+        
+        if enable1D:
+            x=  numpy.linspace(start= qmin,
+                               stop= qmax,
+                               num= qstep,
+                               endpoint=True
+                               )      
+            xlen= len(x)
+            y = numpy.zeros(xlen)
+            if not enable1D:
+                for i in range(xlen):
+                    y[i] = model.run(x[i])
+                
+                try:
+                    new_plot = Theory1D(x, y)
+                    
+                    new_plot.name = name
+                    new_plot.xaxis("\\rm{Q}", 'A^{-1}')
+                    new_plot.yaxis("\\rm{Intensity} ","cm^{-1}")
+                    new_plot.id = "Model"
+                    new_plot.group_id ="Model"
+                    wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot, title="Analytical model 1D"))
+                except:
+                    wx.PostEvent(self.parent, StatusEvent(status="Draw model 1D error: %s" % sys.exc_value))
+                    #raise
+                    return
+            else:
+                for i in range(xlen):
+                    y[i] = model.run(x[i]) 
+                try:
+                    new_plot = Theory1D(x, y)
+                    #print "draw model 1D", name
+                    new_plot.name = name
+                    new_plot.xaxis("\\rm{Q}", 'A^{-1}')
+                    new_plot.yaxis("\\rm{Intensity} ","cm^{-1}")
+                    new_plot.id ="Model"
+                    new_plot.group_id ="Model"
+                    
+                    # Pass the reset flag to let the plotting event handler
+                    # know that we are replacing the whole plot
+                    wx.PostEvent(self.parent, NewPlotEvent(plot=new_plot,
+                                     title="Analytical model 1D ", reset=True ))
+                    
+                except:
+                    #raise
+                    wx.PostEvent(self.parent, StatusEvent(status="Draw model 1D error: %s" % sys.exc_value))
+                    return
+    
+    
+    
+    def update(self, output,time):
+        """
+        """
+        pass
+    
+    def complete(self, output, elapsed, model, qmin, qmax,qstep=DEFAULT_NPTS):
+        """
+        """
+        wx.PostEvent(self.parent, StatusEvent(status="Calc \
+        complete !" , type="stop"))
+        #print "complete",output, model,qmin, qmax
+        data = output
+        temp= numpy.zeros(numpy.shape(data))
+        temp[temp==0]=1
+        theory= Data2D(image=data, err_image=temp)
+    
+        from DataLoader.data_info import Detector, Source
+        
+        detector = Detector()
+        theory.detector=[]
+        theory.detector.append(detector) 
+            
+        theory.detector[0].distance=1e+32#13705.0
+        theory.source= Source()
+        theory.source.wavelength=2*math.pi/1e+32#8.4
+        theory.x_bins =[]
+        theory.y_bins =[]
+        #Now qmax is xmax.
+        xmax=2*theory.detector[0].distance*math.atan(qmax/(4*math.pi/theory.source.wavelength))
+        theory.detector[0].pixel_size.x= xmax/(qstep/2-0.5)#5.0
+        theory.detector[0].pixel_size.y= xmax/(qstep/2-0.5)#5.0
+        theory.detector[0].beam_center.x= qmax
+        theory.detector[0].beam_center.y= qmax
+        #print "xmax,qmax",xmax,qmax
+        # compute x_bins and y_bins
+        # Qx and Qy vectors
+    
+        distance   = theory.detector[0].distance
+        pixel      = qstep/2-1
+        theta      = pixel / distance / qstep#100.0
+        wavelength = theory.source.wavelength
+        pixel_width_x = theory.detector[0].pixel_size.x
+        pixel_width_y = theory.detector[0].pixel_size.y
+        center_x      = theory.detector[0].beam_center.x/pixel_width_x
+        center_y      = theory.detector[0].beam_center.y/pixel_width_y
+        
+        
+        size_x, size_y= numpy.shape(theory.data)
+        #print "size_x,size_y",size_x, size_y
+        #This case, q and x are equivalent to each other.
+        for i_x in range(size_x):
+            theta = (i_x-center_x)*pixel_width_x / distance #/ size_x#100.0
+            qx = 4.0*math.pi/wavelength * math.tan(theta/2.0)
+            theory.x_bins.append(qx)    
+        for i_y in range(size_y):
+            theta = (i_y-center_y)*pixel_width_y / distance #/ size_y#100.0
+            qy =4.0*math.pi/wavelength * math.tan(theta/2.0)
+            theory.y_bins.append(qy)
+           
+        #theory.err_data= numpy.    
+        theory.name= model.name
+        theory.group_id ="Model"
+        theory.id ="Model"
+        
+       
+        
+        theory.xmin= -qmax#/math.sqrt(2)#You can not do sqrt(2), that changes axis scale not data itself
+        theory.xmax= qmax#/math.sqrt(2)
+        theory.ymin= -qmax#/math.sqrt(2)
+        theory.ymax= qmax#/math.sqrt(2)
+        
+        #print "model draw comptele xmax",theory.xmax,model.name
+        wx.PostEvent(self.parent, NewPlotEvent(plot=theory,
+                         title="Analytical model 2D ", reset=True ))
+         
+        
+         
+    def _draw_model2D(self,model,description=None, enable2D=False,
+                      qmin=DEFAULT_QMIN, qmax=DEFAULT_QMAX, qstep=DEFAULT_NPTS):
+        
+        x=  numpy.linspace(start= -1*qmax,
+                               stop= qmax,
+                               num= qstep,
+                               endpoint=True )  
+        y = numpy.linspace(start= -1*qmax,
+                               stop= qmax,
+                               num= qstep,
+                               endpoint=True )
+       
+        lx = len(x)
+        #print x
+        #data=numpy.zeros([len(x),len(y)])
+        self.model= model
+        if enable2D:
+            try:
+                from sans.guiframe.model_thread import Calc2D
+               # print "in draw model 2d ",self.model
+                self.calc_thread = Calc2D(parent =self.parent,x=x,
+                                           y=y,model= self.model, 
+                                           qmin=qmin,
+                                           qmax=qmax,
+                                           qstep=qstep,
+                                completefn=self.complete,
+                                updatefn=None)
+                self.calc_thread.queue()
+                self.calc_thread.ready(2.5)
+            except:
+                raise
+            
+    def show_panel2D(self, id=None ):
+        self.parent.show_panel(self.model2D_id)
+           
+   
+if __name__ == "__main__":
+    i = Plugin()
+    
+    
+    
+    
Index: sansview/perspectives/fitting/old_modelpage.py
===================================================================
--- sansview/perspectives/fitting/old_modelpage.py	(revision 0b99881db3a31559d8bea44b140993d0b56d76fe)
+++ sansview/perspectives/fitting/old_modelpage.py	(revision c77d8592395f6684cf45ee976c1cac9db9c00110)
@@ -1,5 +1,5 @@
 import sys
 import wx
-import wx.lib
+import wx.lib.newevent
 import numpy
 import copy
@@ -84,13 +84,12 @@
         #------------------ sizer 4  draw------------------------  
        
-       
+        ## structure combox box
+        self.structbox = wx.ComboBox(self, -1)
         # define combox box
         self.modelbox = wx.ComboBox(self, -1)
-         # preview selected model name
-        self.prevmodel_name=name
-        #print "model view prev_model",name
-        self.modelbox.SetValue(self.prevmodel_name)
+        
         #enable model 2D draw
         self.enable2D= False
+        self.fitrange= True
         #filling sizer2
         ix = 0
@@ -100,4 +99,21 @@
         ix += 1
         self.sizer4.Add(self.modelbox,(iy,ix),(1,1),  wx.EXPAND|wx.ADJUST_MINSIZE, 0)
+        ix +=1
+        self.text_mult= wx.StaticText(self,-1,' x ')
+        self.sizer4.Add(self.text_mult,(iy,ix),(1,1),  wx.EXPAND|wx.ADJUST_MINSIZE, 0)
+        ix += 1
+        self.sizer4.Add(self.structbox,(iy,ix),(1,1),  wx.EXPAND|wx.ADJUST_MINSIZE, 0)
+        
+        if hasattr(model ,"model2"):
+            name= model.model2.name
+
+            self.structbox.SetValue(name)          
+        if hasattr(model ,"model1"):
+            name= model.model1.name
+            items = self.modelbox.GetItems()
+            self.modelbox.SetValue(name)
+        else:
+            #print "model view prev_model",name
+            self.modelbox.SetValue( name )
         ix += 1
         id = wx.NewId()
@@ -188,20 +204,5 @@
         iy+=1 
         self.sizer9.Add((20,20),(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-        #----------sizer 10 draw------------------------------------------------------
-        """
-        id = wx.NewId()
-        self.btClose =wx.Button(self,id,'Close')
-        self.btClose.Bind(wx.EVT_BUTTON, self.onClose,id=id)
-        self.btClose.SetToolTipString("Close page.")
-        
-        ix= 3
-        iy= 1
-        self.sizer10.Add((20,20),(iy,ix),(1,1),wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
-        ix +=1
-        self.sizer10.Add( self.btClose,(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-        ix =0
-        iy+=1
-        self.sizer10.Add((20,20),(iy,ix),(1,1),wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
-        """
+        
         # contains link between  model ,all its parameters, and panel organization
         self.parameters=[]
@@ -219,5 +220,5 @@
             self.set_panel(self.model)
         self.theta_cb=None
-       
+        
        
         self.vbox.Layout()
@@ -229,14 +230,18 @@
         self.Layout()
         self.parent.GetSizer().Layout()
-    def set_model_description(self, model):
-        
-        if model !=None and str(model.description)!=""and self.data==None:
-            self.sizer11.Clear(True)
-            self.box_description= wx.StaticBox(self, -1, 'Model Description')
-            boxsizer1 = wx.StaticBoxSizer(self.box_description, wx.VERTICAL)
-            boxsizer1.SetMinSize((320,20))
-            self.description = wx.StaticText(self,-1,str(model.description))
-            boxsizer1.Add(self.description, 0, wx.EXPAND)  
-            self.sizer11.Add(boxsizer1,1, wx.EXPAND | wx.ALL, 2)
+    def set_model_description(self, model=None):
+        
+        if model !=None:
+            description="description"
+        else:
+            description=""
+            if hasattr(model,description.lower())and self.data==None:
+                self.sizer11.Clear(True)
+                self.box_description= wx.StaticBox(self, -1, 'Model Description')
+                boxsizer1 = wx.StaticBoxSizer(self.box_description, wx.VERTICAL)
+                boxsizer1.SetMinSize((320,20))
+                self.description = wx.StaticText(self,-1,str(model.description))
+                boxsizer1.Add(self.description, 0, wx.EXPAND)  
+                self.sizer11.Add(boxsizer1,1, wx.EXPAND | wx.ALL, 2)
       
         
@@ -261,22 +266,35 @@
             @param page: the page to populate
         """
-        id=0
-        self.model_list_box=dict
-        list_name=[]
-        for item in  self.model_list_box.itervalues():
-            name = item.__name__
-            if hasattr(item, "name"):
-                name = item.name
-            list_name.append(name)
-        list_name.sort() 
-         
-        for name in list_name:
-            self.modelbox.Insert(name,int(id))
-            id+=1
-        wx.EVT_COMBOBOX(self.modelbox,-1, self._on_select_model) 
+        
+        self.model_list_box = dict.get_list()
+       
+        for item , mylist in self.model_list_box.iteritems():
+            separator= "---%s---"%item
+            self.modelbox.Append(separator,"separator")
+            
+            for models in mylist:
+                model= models()
+                name = model.__class__.__name__
+                if hasattr(model, "name"):
+                    name = model.name
+                self.modelbox.Append(name,models)
+            wx.EVT_COMBOBOX(self.modelbox,-1, self._on_select_model)
+            if item == "Structure Factors" :
+                for structs in mylist:
+                    struct= structs()
+                    name = struct.__class__.__name__
+                    if hasattr(struct, "name"):
+                        name = struct.name
+                    self.structbox.Append(name,structs)
+                wx.EVT_COMBOBOX(self.structbox,-1, self._on_select_model)
+        
         return 0
     
 
     def Set_DipersParam(self, event):
+        if self.model ==None:
+            msg= " Select non - model value:%s !"%self.model
+            wx.PostEvent(self.parent.parent, StatusEvent(status= msg))
+            return 
         if self.enable_disp.GetValue():
             if len(self.disp_list)==0:
@@ -417,8 +435,11 @@
         # If the 2D display is not currently enabled, plot the model in 2D 
         # and set the enable2D flag.
-        if self.enable2D==False:
-            self.enable2D=True
+        if self.fitrange:
+            self.enable2D = True
+            
+        if self.enable2D:
             self._draw_model()
             self.model_view.Disable()
+       
             
     
@@ -433,12 +454,28 @@
         
         self.set_panel(model)
-        self._draw_model(name)
-        
-        # Select the model from the combo box
-        items = self.modelbox.GetItems()
-        for i in range(len(items)):
-            if items[i]==name:
-                self.modelbox.SetSelection(i)
-                self.model_view.SetFocus()
+        self._draw_model()
+       
+        if hasattr(model ,"model2"):
+            name= model.model2.name
+            items = self.structbox.GetItems()
+            for i in range(len(items)):
+                if items[i]==name:
+                    self.structbox.SetSelection(i)
+                    
+        if hasattr(model ,"model1"):
+            name= model.model1.name
+            items = self.modelbox.GetItems()
+            for i in range(len(items)):
+                if items[i]==name:
+                    self.modelbox.SetSelection(i)
+        else:
+            # Select the model from the combo box
+            items = self.modelbox.GetItems()
+            for i in range(len(items)):
+                if items[i]==name:
+                    self.modelbox.SetSelection(i)
+            self.structbox.SetValue("No Structure")
+                    
+        self.model_view.SetFocus()
                 
     def _on_select_Disp(self,event):
@@ -462,19 +499,25 @@
         self.Layout()
         self.parent.GetSizer().Layout()
-        for item in self.model_list_box.itervalues():
-            name = item.__name__
-            if hasattr(item, "name"):
-                name = item.name
-            if name ==event.GetString():
-                model=item()
-                self.model= model
-                self.set_panel(model)
-                self.name= name
-                self.model_view.SetFocus()
-                self.parent.model_page.name=name
-                self.parent.draw_model_name=name
+        form_factor =self.modelbox.GetClientData(self.modelbox.GetCurrentSelection())
+        struct_factor =self.structbox.GetClientData(self.structbox.GetCurrentSelection())
+       
+        if form_factor!="separator":
+            if struct_factor != None and struct_factor.__name__ != "NoStructure":
+                from sans.models.MultiplicationModel import MultiplicationModel
+                self.model= MultiplicationModel(form_factor(),struct_factor())
+            else:
+                 self.model= form_factor()
+        else:
+            self.model=None 
+            msg= " Select non - model value:%s !Please select another model"%name 
+            wx.PostEvent(self.parent.parent, StatusEvent(status= msg))
                
-                self._draw_model(name)
-            
+        self.set_model_description(self.model)
+        self.set_panel(self.model)
+        self.name= self.model.name
+        self.model_view.SetFocus()
+        self.parent.model_page.name= self.name
+        self.parent.draw_model_name= self.name
+        self._draw_model()
             
     def get_model_box(self): 
@@ -506,97 +549,98 @@
         self.param_toFit=[]
         self.fixed_param=[]
-        self.model = model
-        
-        self.set_model_description( self.model) 
-        
-        keys = self.model.getParamList()
-        #list of dispersion paramaters
-        self.disp_list=self.model.getDispParamList()
-       
-        keys.sort()
-        ik=0
-        im=1
-        
-        iy = 1
-        ix = 0
-        self.cb1 = wx.CheckBox(self, -1,"Select all", (10, 10))
-        if self.data!=None:
-            wx.EVT_CHECKBOX(self, self.cb1.GetId(), self.select_all_param)
-            self.cb1.SetValue(False)
-        else:
-            self.cb1.Disable()
-            self.cb1.Hide()
-       
-        self.sizer5.Add(self.cb1,(iy, ix),(1,1),\
-                          wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
-        ix +=1
-        self.text2_2 = wx.StaticText(self, -1, 'Values')
-        self.sizer5.Add(self.text2_2,(iy, ix),(1,1),\
-                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
-        ix +=2
-        self.text2_3 = wx.StaticText(self, -1, 'Errors')
-        self.sizer5.Add(self.text2_3,(iy, ix),(1,1),\
-                            wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-        self.text2_3.Hide() 
-        
-       
-        ix +=1
-        self.text2_4 = wx.StaticText(self, -1, 'Units')
-        self.sizer5.Add(self.text2_4,(iy, ix),(1,1),\
-                            wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
-        self.text2_4.Hide()
-        disp_list=self.model.getDispParamList()
-        for item in keys:
-            if not item in disp_list:
-                iy += 1
-                ix = 0
-    
-                cb = wx.CheckBox(self, -1, item, (10, 10))
-                if self.data!=None:
-                    cb.SetValue(False)
-                    wx.EVT_CHECKBOX(self, cb.GetId(), self.select_param)
+        if model !=None:
+            self.model = model
+            
+            self.set_model_description( self.model) 
+            
+            keys = self.model.getParamList()
+            #list of dispersion paramaters
+            self.disp_list=self.model.getDispParamList()
+           
+            keys.sort()
+            ik=0
+            im=1
+            
+            iy = 1
+            ix = 0
+            self.cb1 = wx.CheckBox(self, -1,"Select all", (10, 10))
+            if self.data!=None:
+                wx.EVT_CHECKBOX(self, self.cb1.GetId(), self.select_all_param)
+                self.cb1.SetValue(False)
+            else:
+                self.cb1.Disable()
+                self.cb1.Hide()
+           
+            self.sizer5.Add(self.cb1,(iy, ix),(1,1),\
+                              wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
+            ix +=1
+            self.text2_2 = wx.StaticText(self, -1, 'Values')
+            self.sizer5.Add(self.text2_2,(iy, ix),(1,1),\
+                                wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
+            ix +=2
+            self.text2_3 = wx.StaticText(self, -1, 'Errors')
+            self.sizer5.Add(self.text2_3,(iy, ix),(1,1),\
+                                wx.EXPAND|wx.ADJUST_MINSIZE, 0)
+            self.text2_3.Hide() 
+            
+           
+            ix +=1
+            self.text2_4 = wx.StaticText(self, -1, 'Units')
+            self.sizer5.Add(self.text2_4,(iy, ix),(1,1),\
+                                wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
+            self.text2_4.Hide()
+            disp_list=self.model.getDispParamList()
+            for item in keys:
+                if not item in disp_list:
+                    iy += 1
+                    ix = 0
+        
+                    cb = wx.CheckBox(self, -1, item, (10, 10))
+                    if self.data!=None:
+                        cb.SetValue(False)
+                        wx.EVT_CHECKBOX(self, cb.GetId(), self.select_param)
+                    else:
+                        cb.Disable()
+                    self.sizer5.Add( cb,( iy, ix),(1,1),  wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
+                   
+                    ix += 1
+                    value= self.model.getParam(item)
+                    ctl1 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20), style=wx.TE_PROCESS_ENTER)
+                    ctl1.SetValue(str (format_number(value)))
+                    ctl1.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
+                    ctl1.Bind(wx.EVT_TEXT_ENTER,self._onparamEnter)
+                    self.sizer5.Add(ctl1, (iy,ix),(1,1), wx.EXPAND)
+                    
+                    ix += 1
+                    text2=wx.StaticText(self, -1, '+/-')
+                    self.sizer5.Add(text2,(iy, ix),(1,1),\
+                                    wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
+                    text2.Hide()  
+                    ix += 1
+                    ctl2 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20), style=wx.TE_PROCESS_ENTER)
+                    self.sizer5.Add(ctl2, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
+                    ctl2.Hide()
+                   
+                    ix +=1
+                    # Units
+                    try:
+                        units = wx.StaticText(self, -1, self.model.details[item][0], style=wx.ALIGN_LEFT)
+                    except:
+                        units = wx.StaticText(self, -1, "", style=wx.ALIGN_LEFT)
+                    self.sizer5.Add(units, (iy,ix),(1,1),  wx.EXPAND|wx.ADJUST_MINSIZE, 0)
+               
+                    self.parameters.append([cb,ctl1,text2,ctl2])
+                    
+            iy+=1
+            self.sizer5.Add((20,20),(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
+            
+            #Display units text on panel
+            for item in keys:   
+                if self.model.details[item][0]!='':
+                    self.text2_4.Show()
+                    break
                 else:
-                    cb.Disable()
-                self.sizer5.Add( cb,( iy, ix),(1,1),  wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
-               
-                ix += 1
-                value= self.model.getParam(item)
-                ctl1 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20), style=wx.TE_PROCESS_ENTER)
-                ctl1.SetValue(str (format_number(value)))
-                ctl1.Bind(wx.EVT_KILL_FOCUS, self._onparamEnter)
-                ctl1.Bind(wx.EVT_TEXT_ENTER,self._onparamEnter)
-                self.sizer5.Add(ctl1, (iy,ix),(1,1), wx.EXPAND)
-                
-                ix += 1
-                text2=wx.StaticText(self, -1, '+/-')
-                self.sizer5.Add(text2,(iy, ix),(1,1),\
-                                wx.EXPAND|wx.ADJUST_MINSIZE, 0) 
-                text2.Hide()  
-                ix += 1
-                ctl2 = wx.TextCtrl(self, -1, size=(_BOX_WIDTH,20), style=wx.TE_PROCESS_ENTER)
-                self.sizer5.Add(ctl2, (iy,ix),(1,1), wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-                ctl2.Hide()
-               
-                ix +=1
-                # Units
-                try:
-                    units = wx.StaticText(self, -1, self.model.details[item][0], style=wx.ALIGN_LEFT)
-                except:
-                    units = wx.StaticText(self, -1, "", style=wx.ALIGN_LEFT)
-                self.sizer5.Add(units, (iy,ix),(1,1),  wx.EXPAND|wx.ADJUST_MINSIZE, 0)
-           
-                self.parameters.append([cb,ctl1,text2,ctl2])
-                
-        iy+=1
-        self.sizer5.Add((20,20),(iy,ix),(1,1), wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
-        
-        #Display units text on panel
-        for item in keys:   
-            if self.model.details[item][0]!='':
-                self.text2_4.Show()
-                break
-            else:
-                self.text2_4.Hide()
-        
+                    self.text2_4.Hide()
+            
         self.vbox.Layout()
         self.SetScrollbars(20,20,55,40)
@@ -949,11 +993,15 @@
             # If qmin and qmax have been modified, update qmin and qmax and 
             # set the is_modified flag to True
-            if float(self.qmin.GetValue()) != self.qmin_x:
-                self.qmin_x = float(self.qmin.GetValue())
-                is_modified = True
-            if float(self.qmax.GetValue()) != self.qmax_x:
-                self.qmax_x = float(self.qmax.GetValue())
-                is_modified = True
-            
+            from sans.guiframe.utils import check_value
+            if check_value( self.qmin, self.qmax):
+                if float(self.qmin.GetValue()) != self.qmin_x:
+                    self.qmin_x = float(self.qmin.GetValue())
+                    is_modified = True
+                if float(self.qmax.GetValue()) != self.qmax_x:
+                    self.qmax_x = float(self.qmax.GetValue())
+                    is_modified = True
+                self.fitrange = True
+            else:
+                self.fitrange = False
             if float(self.npts.GetValue()) !=  self.num_points:
                 self.num_points = float(self.npts.GetValue())
@@ -963,5 +1011,5 @@
                 self._draw_model()            
             
-    def _draw_model(self, name=None):
+    def _draw_model(self):
         """
             Method to draw or refresh a plotted model.
@@ -971,11 +1019,9 @@
             [Note to coder: This way future changes will be done in only one place.] 
         """
-        if name==None:
-            name= self.model.name
-       
-        self.manager.draw_model(self.model, name, data=self.data,
-                                qmin=self.qmin_x, qmax=self.qmax_x,
-                                qstep= self.num_points,
-                                enable2D=self.enable2D)
+        if self.model !=None:
+            self.manager.draw_model(self.model, self.model.name, data=self.data,
+                                    qmin=self.qmin_x, qmax=self.qmax_x,
+                                    qstep= self.num_points,
+                                    enable2D=self.enable2D)
        
     def select_param(self,event):
Index: sansview/perspectives/fitting/old_simfitpage.py
===================================================================
--- sansview/perspectives/fitting/old_simfitpage.py	(revision c77d8592395f6684cf45ee976c1cac9db9c00110)
+++ sansview/perspectives/fitting/old_simfitpage.py	(revision c77d8592395f6684cf45ee976c1cac9db9c00110)
@@ -0,0 +1,261 @@
+
+import sys,re,string, wx   
+from sans.guicomm.events import StatusEvent    
+
+class SimultaneousFitPage(wx.ScrolledWindow):
+    """
+        Simultaneous fitting panel
+        All that needs to be defined are the
+        two data members window_name and window_caption
+    """
+    ## Internal name for the AUI manager
+    window_name = "simultaneous Fit page"
+    ## Title to appear on top of the window
+    window_caption = "Simultaneous Fit Page"
+    
+    
+    def __init__(self, parent, *args, **kwargs):
+        wx.ScrolledWindow.__init__(self, parent, *args, **kwargs)
+        """
+             Simultaneous page display
+        """
+        self.parent = parent
+        self.page_finder={}
+        self.sizer3 = wx.GridBagSizer(5,5)
+        self.sizer1 = wx.GridBagSizer(5,5)
+        self.sizer2  = wx.BoxSizer(wx.HORIZONTAL)
+        self.vbox  = wx.BoxSizer(wx.VERTICAL)
+        self.vbox.Add(self.sizer3)
+        self.vbox.Add(self.sizer1)
+        self.vbox.Add(self.sizer2)
+        id = wx.NewId()
+        self.btFit =wx.Button(self,id,'Constraint Fit')
+        self.btFit.Bind(wx.EVT_BUTTON, self.onFit,id=id)
+        self.btFit.SetToolTipString("Perform fit.")
+        ix = 0
+        iy = 1 
+        self.cb1 = wx.CheckBox(self, -1,'Models', (10, 10))
+        self.sizer3.Add(self.cb1,(iy, ix),(1,1),\
+                        wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
+        wx.EVT_CHECKBOX(self, self.cb1.GetId(), self.select_all_model_name)
+      
+        text=wx.StaticText(self, -1, 'Constraint')
+        self.sizer2.Add(text,0, wx.LEFT|wx.RIGHT|wx.ADJUST_MINSIZE, 10)
+
+        self.ctl2 = wx.TextCtrl(self, -1, style=wx.TE_MULTILINE)
+       
+        self.sizer2.Add(self.ctl2, 0, wx.LEFT|wx.RIGHT|wx.ADJUST_MINSIZE, 10)
+       
+        self.sizer2.Add(self.btFit, 0, wx.LEFT|wx.RIGHT|wx.ADJUST_MINSIZE, 10)
+        self.params=[]
+        self.model_list=[]
+        self.model_toFit=[]
+        
+        self.vbox.Layout()
+        self.vbox.Fit(self) 
+        self.SetSizer(self.vbox)
+        self.SetScrollbars(20,20,55,40)
+        self.Centre()
+        
+        
+    def onFit(self,event):
+        """ signal for fitting"""
+        for page in self.page_finder.iterkeys():
+            page.set_model_parameter()
+        if len(self.model_toFit) >= 1 :
+            self._onTextEnter()
+            self.set_model()
+            self.manager._on_simul_fit()
+        else:
+            wx.PostEvent(self.parent.Parent, StatusEvent(status=\
+                            "Select at least one model to fit "))
+           
+            
+            
+    def set_manager(self, manager):
+        """
+            set panel manager
+            @param manager: instance of plugin fitting
+        """
+        self.manager = manager
+        self.add_model( self.manager.page_finder)
+        
+        
+    def select_all_model_name(self,event):
+        """
+            check all models names
+        """
+        self.model_toFit=[] 
+        if self.cb1.GetValue()==True:
+            for item in self.model_list:
+                item[0].SetValue(True)
+                self.manager.schedule_for_fit( value=1,fitproblem =item[1]) 
+                self.model_toFit.append(item)
+        else:
+            for item in self.model_list:
+                item[0].SetValue(False) 
+                self.manager.schedule_for_fit( value=0,fitproblem =item[1]) 
+                
+            self.model_toFit=[]
+       
+            
+    def add_model(self,page_finder):
+        """
+            Receive a dictionary containing information to display model name
+            @param page_finder: the dictionary containing models information
+        """
+        if len(self.model_list)>0:
+            for item in self.model_list:
+                item[0].SetValue(False) 
+                self.manager.schedule_for_fit( value=0,fitproblem =item[1])
+        self.model_list=[]
+        self.model_toFit=[]
+        self.sizer1.Clear(True)
+        self.page_finder=page_finder
+        self.cb1.SetValue(False)
+        ix = 0
+        iy = 1 
+        list=[]
+        for page, value in page_finder.iteritems():
+            try:
+                list = value.get_model()
+                model = list[0]
+                modelname = list[1]
+                cb = wx.CheckBox(self, -1, modelname, (10, 10))
+                cb.SetValue(False)
+                self.sizer1.Add( cb,( iy,ix),(1,1),  wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
+                ix = 0
+                iy += 1 
+                wx.EVT_CHECKBOX(self, cb.GetId(), self.select_model_name)
+                self.model_list.append([cb,value,page,modelname])
+            except:
+                pass
+        iy +=1
+        self.sizer1.Add((20,20),( iy,ix),(1,1),  wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
+        self.sizer1.Layout()        
+        self.vbox.Layout()
+        
+        
+    def remove_model(self,delpage):
+        """
+             Remove  a checkbox and the name related to a model selected on page delpage
+             @param delpage: the page removed
+        """
+        self.model_list=[]
+        self.model_toFit=[]
+        self.sizer1.Clear(True)
+       
+        self.cb1.SetValue(False)
+        ix = 0
+        iy = 1 
+        list=[]
+        for page, value in self.page_finder.iteritems():
+            try:
+                if page!= delpage:
+                    list = value.get_model()
+                    model = list[0]
+                    modelname = list[1]
+                    cb = wx.CheckBox(self, -1, modelname, (10, 10))
+                    cb.SetValue(False)
+                    self.sizer1.Add( cb,( iy,ix),(1,1),  wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
+                    ix = 0
+                    iy += 1 
+                    wx.EVT_CHECKBOX(self, cb.GetId(), self.select_model_name)
+                    self.model_list.append([cb,value,page,modelname])
+            except:
+                pass
+        iy +=1
+        self.sizer1.Add((20,20),( iy,ix),(1,1),  wx.LEFT|wx.EXPAND|wx.ADJUST_MINSIZE, 15)
+        self.sizer1.Layout()        
+        self.vbox.Layout()
+        
+        
+    def select_model_name(self,event):
+        """
+            Save interformation related to checkbox and their states
+        """
+        self.model_toFit=[]
+        for item in self.model_list:
+            if item[0].GetValue()==True:
+                self.model_toFit.append(item)
+                self.manager.schedule_for_fit( value=1,fitproblem =item[1]) 
+            else:
+                self.manager.schedule_for_fit( value=0,fitproblem =item[1]) 
+                if item in self.model_toFit:
+                    self.model_toFit.remove(item)
+                    self.cb1.SetValue(False)
+                    
+        if len(self.model_list)==len(self.model_toFit):
+            self.cb1.SetValue(True)
+        else:
+            self.cb1.SetValue(False)
+     
+        
+   
+    def set_model(self):
+        """
+            set_model take values in self.params which are the values
+            entered by the user and try to assign them into the model 
+            concerned in self.manager. page.finder
+        """
+        if len(self.params) >0:
+            for item in self.model_toFit:
+                list=item[1].get_model()
+                model=list[0]
+                param_list=model.getParamList()
+                if self.params !=[]:
+                    for element in self.params:
+                        if model.name == str(element[0]):
+                            for item in param_list:
+                                if item==str(element[1]):
+                                    self.manager.set_page_finder(model.name,element[1],
+                                                                 str(element[2]))
+                           
+    
+    def _onTextEnter(self):
+        """
+            get values from the constrainst textcrtl ,parses them into model name
+            parameter name and parameters values.
+            store them in a list self.params .when when params is not empty set_model 
+            uses it to reset the appropriate model and its appropriates parameters
+        """
+        value= self.ctl2.GetValue()
+        if value:
+            self.params=[]
+            try:
+                expression='[\s,;]'
+                if re.search(expression,value) !=None:
+                    word=re.split(expression,value)
+                    for item in word:
+                        self.params.append(self.parser_helper(item))
+                else:
+                    self.params.append(self.parser_helper(value))  
+            except:
+                wx.PostEvent(self.parent.Parent, StatusEvent(status="Constraint Error: %s" % sys.exc_value))
+      
+        
+    def parser_helper(self,value):
+        """
+             @return  param:a list containing the name of a model ,its parameters 
+             value and name extracted from the constrainst controlbox
+        """
+        if string.find(value, "=") !=-1:
+            model_param= re.split("=",value)
+            param_name=model_param[0]
+            param_value=model_param[1]
+            
+            if string.find(param_name,".")!=-1:
+                param_names= re.split("\.",param_name)
+                model_name=param_names[0]
+                param_name=param_names[1]
+                param=[str(model_name),param_name,str(param_value)]
+                return param
+            else:
+                wx.PostEvent(self.parent.Parent,
+                              StatusEvent(status="cannot evaluate this expression"))
+                return
+        else:
+            wx.PostEvent(self.parent.Parent, StatusEvent(status="Missing '=' in expression"))
+            
+   
+    
Index: sansview/perspectives/fitting/pageInfo.py
===================================================================
--- sansview/perspectives/fitting/pageInfo.py	(revision c77d8592395f6684cf45ee976c1cac9db9c00110)
+++ sansview/perspectives/fitting/pageInfo.py	(revision c77d8592395f6684cf45ee976c1cac9db9c00110)
@@ -0,0 +1,73 @@
+
+
+import wx
+
+class PageInfo(object):
+    """
+        Contains info to reconstruct a page
+    """
+    def __init__(self, parent,model=None, data=None):
+        
+        """ 
+            Initialization of the Panel
+        """
+        #TODO: remove this once the inheritence is cleaned up
+        ## Data member to store the dispersion object created
+        self._disp_obj_dict = {}
+
+        #Data used for fitting 
+        self.data = data
+        # flag to allow data2D plot
+        self.enable2D=False
+        # model on which the fit would be performed
+        self.model = model
+        #fit page manager 
+        self.manager = None
+        #Store the parent of this panel parent
+        # For this application fitpanel is the parent
+        self.parent  = parent
+        # Event_owner is the owner of model event
+        self.event_owner = None
+      
+        # Contains link between  model ,all its parameters, and panel organization
+        self.parameters=[]
+        # Contains list of parameters that cannot be fitted and reference to 
+        #panel objects 
+        self.fixed_param=[]
+        # Contains list of parameters with dispersity and reference to 
+        #panel objects 
+        self.fittable_param=[]
+        #list of dispersion paramaters
+        self.disp_list=[]
+        #contains link between a model and selected parameters to fit 
+        self.param_toFit=[]
+        #dictionary of model type and model class
+        self.model_list_box =None
+        ## list of check box   
+        self.list_of_radiobox={} 
+        ## save  current value of combobox
+        self.formfactorcombobox = ""
+        self.structurecombobox  = ""
+        ## Qrange
+        self.qmin=None
+        self.qmax=None
+        self.npts=None
+        ##page name
+        self.page_name=""
+        
+                  
+    def save_radiobox_state(self, object ):
+        """
+            save  radiobox state 
+            @param object: radiobox
+            self.list_of_check= ["label", id, state]
+           
+        """
+        label = object.GetLabel()
+        id = object.GetId()
+        state = object.GetValue()
+        self.list_of_radiobox[label]=[label, id, state]    
+    
+
+
+       
