Index: src/sas/sasgui/perspectives/fitting/fitpage.py
===================================================================
--- src/sas/sasgui/perspectives/fitting/fitpage.py	(revision ba1c14560ba5f607c084c317e9b98cd8acfbfaa7)
+++ src/sas/sasgui/perspectives/fitting/fitpage.py	(revision ca4f40d38aa2c0abd8d7a1571cf953a85a676091)
@@ -13,8 +13,10 @@
 import time
 import traceback
+import logging
 
 from sasmodels.weights import MODELS as POLYDISPERSITY_MODELS
 
 from sas.sascalc.fit.qsmearing import smear_selection
+from sas.sascalc.dataloader.data_info import Data1D, Data2D
 
 from sas.sasgui.guiframe.events import StatusEvent, NewPlotEvent, \
@@ -28,4 +30,6 @@
     PageInfoEvent
 from .basepage import ModelTextCtrl
+
+logger = logging.getLogger(__name__)
 
 (Chi2UpdateEvent, EVT_CHI2_UPDATE) = wx.lib.newevent.NewEvent()
@@ -184,6 +188,5 @@
         :return: True or False
         """
-        if self.data.__class__.__name__ == "Data2D" or \
-                        self.enable2D:
+        if isinstance(self.data, Data2D) or self.enable2D:
             return True
         return False
@@ -199,6 +202,5 @@
 
         # Check if data is 2D
-        if self.data.__class__.__name__ == "Data2D" or \
-                        self.enable2D:
+        if isinstance(self.data, Data2D) or self.enable2D:
             is_2d_data = True
 
@@ -213,7 +215,9 @@
         smear_message_new_psmear = \
               "Please enter a fixed percentage to be applied to all Q values..."
-        smear_message_2d_x_title = "<dQp>[1/A]:"
-        smear_message_2d_y_title = "<dQs>[1/A]:"
-        smear_message_pinhole_percent_title = "dQ[%]:"
+        smear_message_2d_x_title = "<dQ/Q>_r[%]:"
+        smear_message_2d_y_title = "<dQ/Q>_phi[%]:"
+        smear_message_pinhole_percent_min_title = "[dQ/Q]min(%):"
+        smear_message_pinhole_percent_max_title = "[dQ/Q]max(%):"
+        smear_message_pinhole_percent_title = "dQ/Q(%):"
         smear_message_slit_height_title = "Slit height[1/A]:"
         smear_message_slit_width_title = "Slit width[1/A]:"
@@ -418,9 +422,15 @@
                             smear_message_2d_x_title, style=wx.ALIGN_LEFT)
         self.smear_description_2d_x.SetToolTipString(
-                                        "  dQp(parallel) in q_r direction.")
+                                        "  dQ_r q_r in polar coordinates.")
         self.smear_description_2d_y = wx.StaticText(self, wx.ID_ANY,
                             smear_message_2d_y_title, style=wx.ALIGN_LEFT)
         self.smear_description_2d_y.SetToolTipString(
-                                    " dQs(perpendicular) in q_phi direction.")
+                                    " dQ_phi q_phi in polar coordinates.")
+        self.smear_description_pin_percent_min = wx.StaticText(self, wx.ID_ANY,
+                                            smear_message_pinhole_percent_min_title,
+                                            style=wx.ALIGN_LEFT)
+        self.smear_description_pin_percent_max = wx.StaticText(self, wx.ID_ANY,
+                                            smear_message_pinhole_percent_max_title,
+                                            style=wx.ALIGN_LEFT)
         self.smear_description_pin_percent = wx.StaticText(self, wx.ID_ANY,
                                             smear_message_pinhole_percent_title,
@@ -449,7 +459,12 @@
         self.sizer_new_smear.Add((15, -1))
         self.sizer_new_smear.Add(self.smear_description_2d_x, 0, wx.CENTER, 10)
+        self.sizer_new_smear.Add(self.smear_description_pin_percent_min,
+                                 0, wx.CENTER, 10)
+        self.sizer_new_smear.Add(self.smear_description_pin_percent,
+                                 0, wx.CENTER, 10)
         self.sizer_new_smear.Add(self.smear_description_slit_height,
                                  0, wx.CENTER, 10)
 
+        self.sizer_new_smear.Add(self.smear_pinhole_percent, 0, wx.CENTER, 10)
         self.sizer_new_smear.Add(self.smear_slit_height, 0, wx.CENTER, 10)
         self.sizer_new_smear.Add(self.smear_data_left, 0, wx.CENTER, 10)
@@ -457,10 +472,9 @@
         self.sizer_new_smear.Add(self.smear_description_2d_y,
                                  0, wx.CENTER, 10)
-        self.sizer_new_smear.Add(self.smear_description_pin_percent,
+        self.sizer_new_smear.Add(self.smear_description_pin_percent_max,
                                  0, wx.CENTER, 10)
         self.sizer_new_smear.Add(self.smear_description_slit_width,
                                  0, wx.CENTER, 10)
 
-        self.sizer_new_smear.Add(self.smear_pinhole_percent, 0, wx.CENTER, 10)
         self.sizer_new_smear.Add(self.smear_slit_width, 0, wx.CENTER, 10)
         self.sizer_new_smear.Add(self.smear_data_right, 0, wx.CENTER, 10)
@@ -503,5 +517,5 @@
 
         # check if it is 2D data
-        if self.data.__class__.__name__ == "Data2D" or self.enable2D:
+        if isinstance(self.data, Data2D) or self.enable2D:
             is_2d_data = True
 
@@ -806,6 +820,5 @@
                         self.sizer4_4.Add(cb, (iy, ix), (1, 1),
                                 wx.LEFT | wx.EXPAND | wx.ADJUST_MINSIZE, 5)
-                        if self.data.__class__.__name__ == "Data2D" or \
-                                    self.enable2D:
+                        if isinstance(self.data, Data2D) or self.enable2D:
                             cb.Show(True)
                         elif cb.IsShown():
@@ -819,6 +832,5 @@
                         ctl1.SetToolTipString(poly_tip)
                         ctl1.SetValue(str(format_number(value, True)))
-                        if self.data.__class__.__name__ == "Data2D" or \
-                                    self.enable2D:
+                        if isinstance(self.data, Data2D) or self.enable2D:
                             if first_orient:
                                 values.SetLabel('PD[ratio], Sig[deg]')
@@ -854,6 +866,5 @@
 
                         ctl2.Hide()
-                        if self.data.__class__.__name__ == "Data2D" or \
-                                self.enable2D:
+                        if isinstance(self.data, Data2D) or self.enable2D:
                             if self.is_mac:
                                 text2.Show(True)
@@ -880,6 +891,5 @@
                         ctl4.Hide()
 
-                        if self.data.__class__.__name__ == "Data2D" or \
-                                self.enable2D:
+                        if isinstance(self.data, Data2D) or self.enable2D:
                             ctl3.Show(True)
                             ctl4.Show(True)
@@ -893,6 +903,5 @@
 
                         Tctl.SetValue(str(format_number(value)))
-                        if self.data.__class__.__name__ == "Data2D" or \
-                                self.enable2D:
+                        if isinstance(self.data, Data2D) or self.enable2D:
                             Tctl.Show(True)
                         else:
@@ -913,6 +922,5 @@
 
                         Tct2.SetValue(str(format_number(value)))
-                        if self.data.__class__.__name__ == "Data2D" or \
-                                self.enable2D:
+                        if isinstance(self.data, Data2D) or self.enable2D:
                             Tct2.Show(True)
                         else:
@@ -941,6 +949,5 @@
                                             text2, ctl2, ctl3, ctl4, disp_box])
 
-                if self.data.__class__.__name__ == "Data2D" or \
-                                self.enable2D:
+                if isinstance(self.data, Data2D) or self.enable2D:
                     disp_box.Show(True)
                 else:
@@ -1327,6 +1334,5 @@
                         flag1 = self.update_pinhole_smear()
                         flag = flag or flag1
-                elif self.data.__class__.__name__ != "Data2D" and \
-                        not self.enable2D:
+                elif not isinstance(self.data, Data2D) and not self.enable2D:
                     enable_smearer = not self.disable_smearer.GetValue()
                     self._manager.set_smearer(smearer=temp_smearer,
@@ -1401,5 +1407,5 @@
         if event is not None:
             event.Skip()
-        if self.data.__class__.__name__ == "Data2D":
+        if isinstance(self.data, Data2D):
             return
         is_click = event.LeftDown()
@@ -1419,5 +1425,5 @@
         if event is not None:
             event.Skip()
-        if self.data.__class__.__name__ == "Data2D":
+        if isinstance(self.data, Data2D):
             return
         act_ctrl = event.GetEventObject()
@@ -1435,5 +1441,5 @@
         """
         event.Skip()
-        if self.data.__class__.__name__ == "Data2D":
+        if isinstance(self.data, Data2D):
             return
         ctrl = event.GetEventObject()
@@ -1496,6 +1502,5 @@
             # Check if # of points for theory model are valid(>0).
             # check for 2d
-            if self.data.__class__.__name__ == "Data2D" or \
-                    self.enable2D:
+            if isinstance(self.data, Data2D) or self.enable2D:
                 # set mask
                 radius = np.sqrt(self.data.qx_data * self.data.qx_data +
@@ -1549,6 +1554,5 @@
                 if item[0].IsShown():
                     # Skip the angle parameters if 1D data
-                    if self.data.__class__.__name__ != "Data2D" and \
-                            not self.enable2D:
+                    if not isinstance(self.data, Data2D) and not self.enable2D:
                         if item in self.orientation_params:
                             continue
@@ -1568,6 +1572,5 @@
                 if item[0].IsShown():
                     # Skip the angle parameters if 1D data
-                    if self.data.__class__.__name__ != "Data2D" and \
-                            not self.enable2D:
+                    if not isinstance(self.data, Data2D) and not self.enable2D:
                         if item in self.orientation_params:
                             continue
@@ -1601,41 +1604,68 @@
 
         :return: self.smear_type, self.dq_l and self.dq_r,
-            respectively the type of the smear, dq_min and
-            dq_max for pinhole smear data
-            while dxl and dxw for slit smear
-        """
-        # default
+            respectively the type of the smear, The average <dq/q> radial(p)
+            and <dq/q> theta (s)s for 2D pinhole resolution in % (slit is not
+            currently supported in 2D), (dq/q)_min and (dq/q)_max for 1D pinhole
+            smeared data, again in %, and dxl and/or dxw for slit smeared data
+            given in 1/A and assumed constant.
+        """
+        # set up defaults
         self.smear_type = None
         self.dq_l = None
         self.dq_r = None
         data = self.data
+        #sanity check - this should only be called if data exits
         if self.data is None:
             return
-        elif self.data.__class__.__name__ == "Data2D" or \
-            self.enable2D:
-            if data.dqx_data is None or data.dqy_data is None:
-                return
-            elif self.current_smearer is not None \
-                and data.dqx_data.any() != 0 \
-                and data.dqx_data.any() != 0:
+        #First check if data is 2D
+        #If so check that data set has smearing info and that none are zero.
+        #Otherwise no smearing can be applied using smear from data (a Gaussian
+        #width of zero will cause a divide by zero error)
+        if isinstance(self.data, Data2D):
+            if data.dqx_data is not None and data.dqy_data is not None \
+              and data.dqx_data.all()and data.dqy_data.all():
                 self.smear_type = "Pinhole2d"
-                self.dq_l = format_number(np.average(data.dqx_data))
-                self.dq_r = format_number(np.average(data.dqy_data))
-                return
+                #report as average dQ/Q % as for 1D pinhole
+                self.dq_l = format_number(np.average(data.dqx_data
+                                                     / abs(data.qx_data)) * 100)
+                self.dq_r = format_number(np.average(data.dqy_data
+                                                     / abs(data.qy_data)) * 100)
+            #if not then log that data did not contain resolutin info                                         / abs(data.qy_data)) * 100)
             else:
-                return
-        # check if it is pinhole smear and get min max if it is.
-        if data.dx is not None and np.any(data.dx):
-            self.smear_type = "Pinhole"
-            self.dq_l = data.dx[0]
-            self.dq_r = data.dx[-1]
-
-        # check if it is slit smear and get min max if it is.
-        elif data.dxl is not None or data.dxw is not None:
-            self.smear_type = "Slit"
-            if data.dxl is not None and np.all(data.dxl, 0):
-                self.dq_l = data.dxl[0]
-            if data.dxw is not None and np.all(data.dxw, 0):
-                self.dq_r = data.dxw[0]
+                self.msg = "2D Data did not contain recognizable " \
+                           "resolution info."
+                logger.info(self.msg)
+        #If not check that data is 1D
+        #If so check for pinhole vs slit by veryfing whehter dx or dxl or dxw
+        #have data (currently sasview only supports either dx or dxl/dxw but
+        #not both simultaneously) and, as for 2D, are non zero .
+        #Otherwise no smearing can be applied using smear from data (a Gaussian
+        #width of zero will cause a divide by zero error)
+        elif isinstance(self.data, Data1D):
+            #is it valid 1D pinhole resolution data?
+            if data.dx is not None and np.all(data.dx):
+                self.smear_type = "Pinhole"
+                #report in % for display makes more sense than absolute value
+                #for pinhole smearing .. but keep old names of dq_l
+                self.dq_l = format_number(data.dx[0] / data.x[0] * 100,1)
+                self.dq_r = format_number(data.dx[-1] / data.x[-1] * 100,1)
+            #If not, is it valid 1D slit resolution data?
+            elif (data.dxl is not None or data.dxw is not None) \
+                and (np.all(data.dxl, 0) or np.all(data.dxw, 0)):
+                self.smear_type = "Slit"
+                #for slit units of 1/A make most sense
+                if data.dxl is not None and np.all(data.dxl, 0):
+                    self.dq_l = format_number(data.dxl[0],1)
+                if data.dxw is not None and np.all(data.dxw, 0):
+                    self.dq_r = format_number(data.dxw[0],1)
+            #otherwise log that the data did not conatain resolution info
+            else:
+                self.msg = "1D Data did not contain recognizable " \
+                           "resolution info."
+                logger.info(self.msg)
+        #If drops to here it is neither data1D or data2D so log that
+        else:
+            self.msg = "Data was not recognized as either 1D or 2D data."
+            logger.info(self.msg)
         # return self.smear_type,self.dq_l,self.dq_r
 
@@ -1644,40 +1674,49 @@
         Show only the sizers depending on smear selection
         """
-        # smear disabled
+        # smear disabled = No Smearing used
         if self.disable_smearer.GetValue():
             self.smear_description_none.Show(True)
-        # 2Dsmear
+        # 2Dsmearing - for use with 2D data only
         elif self._is_2D():
             self.smear_description_accuracy_type.Show(True)
             self.smear_accuracy.Show(True)
-            self.smear_description_accuracy_type.Show(True)
             self.smear_description_2d.Show(True)
-            self.smear_description_2d_x.Show(True)
-            self.smear_description_2d_y.Show(True)
+            #2D custom pinhole smearing
             if self.pinhole_smearer.GetValue():
+                self.smear_description_pin_percent.Show(True)
                 self.smear_pinhole_percent.Show(True)
-        # smear from data
+            #get 2D smearing from data
+            elif self.enable_smearer.GetValue():
+                self.smear_description_2d_x.Show(True)
+                self.smear_description_2d_y.Show(True)
+                self.smear_data_left.Show(True)
+                self.smear_data_right.Show(True)
+            #Currently 2D custom slit smearing is not currently supported
+            else:
+                logger.error("2D custom smearing cannot use slit smearing")
+
+        # 1D smearing from data
         elif self.enable_smearer.GetValue():
-
             self.smear_description_dqdata.Show(True)
             if self.smear_type is not None:
                 self.smear_description_smear_type.Show(True)
+                #1D data has slit smearing
                 if self.smear_type == 'Slit':
                     self.smear_description_slit_height.Show(True)
                     self.smear_description_slit_width.Show(True)
+                #1D data has pinhole smearing
                 elif self.smear_type == 'Pinhole':
-                    self.smear_description_pin_percent.Show(True)
+                    self.smear_description_pin_percent_min.Show(True)
+                    self.smear_description_pin_percent_max.Show(True)
                 self.smear_description_smear_type.Show(True)
                 self.smear_description_type.Show(True)
                 self.smear_data_left.Show(True)
                 self.smear_data_right.Show(True)
-        # custom pinhole smear
+        # 1D custom pinhole smearing
         elif self.pinhole_smearer.GetValue():
-            if self.smear_type == 'Pinhole':
-                self.smear_message_new_p.Show(True)
-                self.smear_description_pin_percent.Show(True)
-
+            self.smear_message_new_p.Show(True)
+            self.smear_description_pin_percent.Show(True)
             self.smear_pinhole_percent.Show(True)
-        # custom slit smear
+        # 1D custom slit smear
         elif self.slit_smearer.GetValue():
             self.smear_message_new_s.Show(True)
@@ -1686,4 +1725,6 @@
             self.smear_description_slit_width.Show(True)
             self.smear_slit_width.Show(True)
+        else:
+            logger.error("smearing type is not defined")
 
     def _hide_all_smear_info(self):
@@ -1703,4 +1744,6 @@
         self.smear_data_left.Hide()
         self.smear_data_right.Hide()
+        self.smear_description_pin_percent_min.Hide()
+        self.smear_description_pin_percent_max.Hide()
         self.smear_description_pin_percent.Hide()
         self.smear_pinhole_percent.Hide()
@@ -1920,6 +1963,5 @@
             di_flag = False
             dq_flag = False
-            if self.data.__class__.__name__ == "Data2D" or \
-                        self.enable2D:
+            if isinstance(self.data, Data2D) or self.enable2D:
                 self.slit_smearer.Disable()
                 self.pinhole_smearer.Enable(True)
@@ -2006,5 +2048,5 @@
         # update model plot with new data information
         if flag:
-            if self.data.__class__.__name__ == "Data2D":
+            if isinstance(self.data, Data2D):
                 self.enable2D = True
                 self.model_view.SetLabel("2D Mode")
@@ -2073,6 +2115,5 @@
         npts2fit = 0
         qmin, qmax = self.get_range()
-        if self.data.__class__.__name__ == "Data2D" or \
-                        self.enable2D:
+        if isinstance(self.data, Data2D) or self.enable2D:
             radius = np.sqrt(self.data.qx_data * self.data.qx_data +
                                 self.data.qy_data * self.data.qy_data)
@@ -2464,5 +2505,5 @@
             of the values entered for slit smear
         """
-        if self.data.__class__.__name__ == "Data2D" or self.enable2D:
+        if isinstance(self.data, Data2D) or self.enable2D:
             return
         # make sure once more if it is smearer
@@ -2660,6 +2701,5 @@
         for item in self.parameters:
             # Skip t ifhe angle parameters if 1D data
-            if self.data.__class__.__name__ != "Data2D" and\
-                        not self.enable2D:
+            if not isinstance(self.data, Data2D) and not self.enable2D:
                 if item in self.orientation_params:
                     continue
@@ -2677,6 +2717,5 @@
         for item in self.fittable_param:
             # Skip t ifhe angle parameters if 1D data
-            if self.data.__class__.__name__ != "Data2D" and\
-                        not self.enable2D:
+            if not isinstance(self.data, Data2D) and not self.enable2D:
                 if item in self.orientation_params:
                     continue
@@ -2690,6 +2729,5 @@
 
         # Calculate num. of angle parameters
-        if self.data.__class__.__name__ == "Data2D" or \
-                       self.enable2D:
+        if isinstance(self.data, Data2D) or self.enable2D:
             len_orient_para = 0
         else:
@@ -2984,5 +3022,5 @@
                 if not self._has_magnetic:
                     mag_on_button.Show(False)
-                elif not self.data.__class__.__name__ == "Data2D":
+                elif not isinstance(self.data, Data2D):
                     mag_on_button.Show(False)
                 else:
@@ -3000,6 +3038,5 @@
                         mag_angle_help_button.Show(False)
 
-                if not self.data.__class__.__name__ == "Data2D" and \
-                        not self.enable2D:
+                if not isinstance(self.data, Data2D) and not self.enable2D:
                     orient_angle.Hide()
                 else:
@@ -3025,6 +3062,5 @@
                     cb.SetToolTipString("Check mark to fit")
                     wx.EVT_CHECKBOX(self, cb.GetId(), self.select_param)
-                    if self.data.__class__.__name__ == "Data2D" or \
-                            self.enable2D:
+                    if isinstance(self.data, Data2D) or self.enable2D:
                         cb.Show(True)
                     else:
@@ -3041,6 +3077,5 @@
                                 "Hit 'Enter' after typing to update the plot.")
                     ctl1.SetValue(format_number(value, True))
-                    if self.data.__class__.__name__ == "Data2D" or \
-                            self.enable2D:
+                    if isinstance(self.data, Data2D) or self.enable2D:
                         ctl1.Show(True)
                     else:
@@ -3082,6 +3117,5 @@
                     ctl4.Hide()
 
-                    if self.data.__class__.__name__ == "Data2D" or \
-                            self.enable2D:
+                    if isinstance(self.data, Data2D) or self.enable2D:
                         if self.is_mac:
                             text2.Show(True)
@@ -3099,6 +3133,5 @@
                         units = wx.StaticText(self, -1, "",
                                               style=wx.ALIGN_LEFT)
-                    if self.data.__class__.__name__ == "Data2D" or \
-                            self.enable2D:
+                    if isinstance(self.data, Data2D) or self.enable2D:
                         units.Show(True)
                     else:
@@ -3179,12 +3212,17 @@
         """
         # more disables for 2D
-        if self.data.__class__.__name__ == "Data2D" or \
-                    self.enable2D:
+        if isinstance(self.data, Data2D) or self.enable2D:
             self.slit_smearer.Disable()
-            self.pinhole_smearer.Enable(True)
             self.default_mask = copy.deepcopy(self.data.mask)
-        else:
-            self.slit_smearer.Enable(True)
-            self.pinhole_smearer.Enable(True)
+            if self.model is not None:
+                self.pinhole_smearer.Enable(True)
+
+        elif isinstance(self.data, Data1D):
+            if self.model is not None:
+                self.slit_smearer.Enable(True)
+                self.pinhole_smearer.Enable(True)
+        else:
+            msg="data is not recognized as either 1D or 2D"
+            logger.info(msg)
 
 
