diff --git a/Framework/PythonInterface/plugins/algorithms/IntegratePeaksProfileFitting.py b/Framework/PythonInterface/plugins/algorithms/IntegratePeaksProfileFitting.py
index a3418ba4f677720fbf4eaac5417a8e341ddf0af5..111b06c4dc39c8492bbc30c1b89a32867e1733d6 100644
--- a/Framework/PythonInterface/plugins/algorithms/IntegratePeaksProfileFitting.py
+++ b/Framework/PythonInterface/plugins/algorithms/IntegratePeaksProfileFitting.py
@@ -43,12 +43,9 @@ class IntegratePeaksProfileFitting(PythonAlgorithm):
 
         self.declareProperty("RunNumber", defaultValue=0,
                              doc="Run Number to integrate")
-        self.declareProperty("DQPixel", defaultValue=0.003, validator=FloatBoundedValidator(lower=0., exclusive=True),
-                             doc="The side length of each voxel in the non-MD histogram used for fitting (1/Angstrom)")
-
         self.declareProperty(FileProperty(name="UBFile",defaultValue="",action=FileAction.OptionalLoad,
                              extensions=[".mat"]),
-                             doc="File containing the UB Matrix in ISAW format.")
+                             doc="File containing the UB Matrix in ISAW format. Leave blank to use loaded UB Matrix.")
         self.declareProperty(FileProperty(name="ModeratorCoefficientsFile",
                              defaultValue="",action=FileAction.OptionalLoad,
                              extensions=[".dat"]),
@@ -59,22 +56,13 @@ class IntegratePeaksProfileFitting(PythonAlgorithm):
         self.declareProperty("IntensityCutoff", defaultValue=0., doc="Minimum number of counts to force a profile")
         edgeDocString = 'Pixels within EdgeCutoff from a detector edge will be have a profile forced.  Currently for 256x256 cameras only.'
         self.declareProperty("EdgeCutoff", defaultValue=0., doc=edgeDocString)
-        self.declareProperty("FracHKL", defaultValue=0.5, validator=FloatBoundedValidator(lower=0., exclusive=True),
-                             doc="Fraction of HKL to consider for profile fitting.")
         self.declareProperty("FracStop", defaultValue=0.05, validator=FloatBoundedValidator(lower=0., exclusive=True),
                              doc="Fraction of max counts to include in peak selection.")
 
         self.declareProperty("MinpplFrac", defaultValue=0.9, doc="Min fraction of predicted background level to check")
         self.declareProperty("MaxpplFrac", defaultValue=1.1, doc="Max fraction of predicted background level to check")
-        mindtBinWidthDocString = "Smallest spacing (in microseconds) between data points for TOF profile fitting."
-        self.declareProperty("MindtBinWidth", defaultValue=15, doc=mindtBinWidthDocString)
-
-        self.declareProperty("NTheta", defaultValue=50, doc="Number of bins for bivarite Gaussian along the scattering angle.")
-        self.declareProperty("NPhi", defaultValue=50,  doc="Number of bins for bivariate Gaussian along the azimuthal angle.")
 
         self.declareProperty("DQMax", defaultValue=0.15, doc="Largest total side length (in Angstrom) to consider for profile fitting.")
-        self.declareProperty("DtSpread", defaultValue=0.03, validator=FloatBoundedValidator(lower=0., exclusive=True),
-                             doc="The fraction of the peak TOF to consider for TOF profile fitting.")
         self.declareProperty("PeakNumber", defaultValue=-1,  doc="Which Peak to fit.  Leave negative for all.")
 
     def PyExec(self):
@@ -83,10 +71,8 @@ class IntegratePeaksProfileFitting(PythonAlgorithm):
         from mantid.simpleapi import LoadIsawUB
         import pickle
         from scipy.ndimage.filters import convolve
-
         MDdata = self.getProperty('InputWorkspace').value
         peaks_ws = self.getProperty('PeaksWorkspace').value
-        fracHKL = self.getProperty('FracHKL').value
         fracStop = self.getProperty('FracStop').value
         dQMax = self.getProperty('DQMax').value
         UBFile = self.getProperty('UBFile').value
@@ -96,11 +82,17 @@ class IntegratePeaksProfileFitting(PythonAlgorithm):
         edgeCutoff = self.getProperty('EdgeCutoff').value
         peakNumberToFit = self.getProperty('PeakNumber').value
 
-        LoadIsawUB(InputWorkspace=peaks_ws, FileName=UBFile)
+        if UBFile == '' and peaks_ws.sample().hasOrientedLattice():
+            logger.information("Using UB file already available in PeaksWorkspace")
+        else:
+            try:
+                LoadIsawUB(InputWorkspace=peaks_ws, FileName=UBFile)
+            except:
+                logger.error("peaks_ws does not have a UB matrix loaded.  Must provide a file")
+
         UBMatrix = peaks_ws.sample().getOrientedLattice().getUB()
         dQ = np.abs(ICCFT.getDQFracHKL(UBMatrix, frac=0.5))
         dQ[dQ>dQMax] = dQMax
-        dQPixel = self.getProperty('DQPixel').value
         q_frame='lab'
         mtd['MDdata'] = MDdata
 
@@ -113,21 +105,40 @@ class IntegratePeaksProfileFitting(PythonAlgorithm):
         else:
             strongPeakParams = None #This will not force any profiles
 
-        nTheta = self.getProperty('NTheta').value
-        nPhi = self.getProperty('NPhi').value
         zBG = 1.96
-        mindtBinWidth = self.getProperty('MindtBinWidth').value
         pplmin_frac = self.getProperty('MinpplFrac').value
         pplmax_frac = self.getProperty('MaxpplFrac').value
         sampleRun = self.getProperty('RunNumber').value
+
+        # There are a few instrument specific parameters that we define here.  In some cases,
+        # it may improve fitting to set tweak these parameters, but for simplicity we define these here
+        # The default values are good for MaNDi - new instruments can be added by adding a different elif
+        # statement.
+        # If you change these values or add an instrument, documentation should also be changed.
+        try:
+            nTheta = peaks_ws.getInstrument().getIntParameter("numBinsTheta")[0]
+            nPhi = peaks_ws.getInstrument().getIntParameter("numBinsPhi")[0]
+            mindtBinWidth = peaks_ws.getInstrument().getNumberParameter("mindtBinWidth")[0]
+            maxdtBinWidth = peaks_ws.getInstrument().getNumberParameter("maxdtBinWidth")[0]
+            fracHKL = peaks_ws.getInstrument().getNumberParameter("fracHKL")[0]
+            dQPixel = peaks_ws.getInstrument().getNumberParameter("dQPixel")[0]
+            peakMaskSize = peaks_ws.getInstrument().getIntParameter("peakMaskSize")[0]
+
+        except:
+            raise
+            logger.error("Cannot find all parameters in instrument parameters file.")
+            sys.exit(1)
+
         neigh_length_m=3
         qMask = ICCFT.getHKLMask(UBMatrix, frac=fracHKL, dQPixel=dQPixel,dQ=dQ)
 
+        iccFitDict = ICCFT.parseConstraints(peaks_ws) #Contains constraints and guesses for ICC Fitting
+
         numgood = 0
         numerrors = 0
 
         # Create the parameters workspace
-        keys =  ['peakNumber','Alpha', 'Beta', 'R', 'T0', 'bgBVG', 'chiSq3d', 'dQ', 'KConv', 'MuPH',
+        keys =  ['peakNumber','Alpha', 'Beta', 'R', 'T0', 'bgBVG', 'chiSq3d', 'chiSq', 'dQ', 'KConv', 'MuPH',
                  'MuTH', 'newQ', 'Scale', 'scale3d', 'SigP', 'SigX', 'SigY', 'Intens3d', 'SigInt3d']
         datatypes = ['float']*len(keys)
         datatypes[np.where(np.array(keys)=='newQ')[0][0]] = 'V3D'
@@ -153,13 +164,16 @@ class IntegratePeaksProfileFitting(PythonAlgorithm):
                     box = ICCFT.getBoxFracHKL(peak, peaks_ws, MDdata, UBMatrix, peakNumber,
                                               dQ, fracHKL=0.5, dQPixel=dQPixel, q_frame=q_frame)
                     # Will force weak peaks to be fit using a neighboring peak profile
-                    Y3D, goodIDX, pp_lambda, params = BVGFT.get3DPeak(peak, box, padeCoefficients,qMask,
+                    Y3D, goodIDX, pp_lambda, params = BVGFT.get3DPeak(peak, peaks_ws, box, padeCoefficients,qMask,
                                                                       nTheta=nTheta, nPhi=nPhi, plotResults=False,
                                                                       zBG=zBG,fracBoxToHistogram=1.0,bgPolyOrder=1,
                                                                       strongPeakParams=strongPeakParams,
                                                                       q_frame=q_frame, mindtBinWidth=mindtBinWidth,
+                                                                      maxdtBinWidth=maxdtBinWidth,
                                                                       pplmin_frac=pplmin_frac, pplmax_frac=pplmax_frac,
-                                                                      forceCutoff=forceCutoff, edgeCutoff=edgeCutoff)
+                                                                      forceCutoff=forceCutoff, edgeCutoff=edgeCutoff,
+                                                                      peakMaskSize=peakMaskSize,
+                                                                      iccFitDict=iccFitDict)
 
                     # First we get the peak intensity
                     peakIDX = Y3D/Y3D.max() > fracStop
diff --git a/docs/source/algorithms/IntegratePeaksProfileFitting-v1.rst b/docs/source/algorithms/IntegratePeaksProfileFitting-v1.rst
index 1efc25edf46d931d73494296237e68d0744c20c3..6641913f21ccc541071976363ecc71625cf2e5c6 100644
--- a/docs/source/algorithms/IntegratePeaksProfileFitting-v1.rst
+++ b/docs/source/algorithms/IntegratePeaksProfileFitting-v1.rst
@@ -34,6 +34,43 @@ The algorithms takes two input workspaces:
 -  The OutputParamsWorkspace is a TableWorkspace containing the fit parameters.
    Peaks which could not be fit are omitted.
 
+Instrument-Defined Parameters
+-----------------------------
+In addition to the input parameters defined above, there are several other parameters
+to be aware of which are pre-defined for each instrument.  The instrument is determined
+from the instrument that is loaded into PeaksWorkspace. If the instrument parameters file
+does not contain paramters, the algorithm defaults to MaNDi parameters. Default 
+values are below:
+
++--------------+----------------------------+----------+----------+---------+
+| Parameter    |  Description               |  MaNDi   |  TOPAZ   | CORELLI |
++==============+============================+==========+==========+=========+
+| DQPixel      | The side length for each   |          |          |         |
+|              | voxel used for fitting.    | 0.003    | 0.01     | 0.007   |
+|              | Units: 1/Angstrom          |          |          |         |
++--------------+----------------------------+----------+----------+---------+
+| FracHKL      | The distance between peaks |          |          |         |
+|              | (in fraction of hkl) that  | 0.4      | 0.4      | 0.4     |
+|              | is used for fitting.       |          |          |         |
++--------------+----------------------------+----------+----------+---------+
+| MinDtBinWidth| The smallest time bin used |          |          |         |
+|              | for fitting the TOF profile| 15       | 2        | 2       |
+|              | Units: microseconds        |          |          |         |
++--------------+----------------------------+----------+----------+---------+
+| MaxDtBinWidth| The largest time bin used  |          |          |         |
+|              | for fitting the TOF profile| 50       | 15       | 60      |
+|              | Units: microseconds        |          |          |         |
++--------------+----------------------------+----------+----------+---------+
+| NTheta       | The number of bins along   |          |          |         |
+|              | the scattering direction   | 50       | 50       | 50      |
+|              | used for BVG fitting.      |          |          |         |
++--------------+----------------------------+----------+----------+---------+
+| NPhi         | The number of bins along   |          |          |         |
+|              | the azimuthal direction    | 50       | 50       | 50      |
+|              | used for BVG fitting.      |          |          |         |
++--------------+----------------------------+----------+----------+---------+
+
+
 Calculations
 ------------
 This algorithm will fit a set of peaks in a PeaksWorkspace.  The intensity profile
@@ -114,10 +151,9 @@ Usage
     LoadIsawPeaks(Filename='/SNS/MANDI/shared/ProfileFitting/demo_5921.integrate', OutputWorkspace='peaks_ws')
 
     IntegratePeaksProfileFitting(OutputPeaksWorkspace='peaks_ws_out', OutputParamsWorkspace='params_ws',
-            InputWorkspace='MANDI_5921_md', PeaksWorkspace='peaks_ws', RunNumber=5921, DtSpread=0.015,
-            UBFile='/SNS/MANDI/shared/ProfileFitting/demo_5921.mat',
+            InputWorkspace='MANDI_5921_md', PeaksWorkspace='peaks_ws', RunNumber=5921,
+            UBFile='/SNS/MANDI/shared/ProfileFitting/demo_5921.mat', MinpplFrac=0.9, MaxpplFrac=1.1,
             ModeratorCoefficientsFile='/SNS/MANDI/shared/ProfileFitting/franz_coefficients_2017.dat',
-            MinpplFrac=0.9, MaxpplFrac=1.1, MindtBinWidth=15,
             StrongPeakParamsFile='/SNS/MANDI/shared/ProfileFitting/strongPeakParams_beta_lac_mut_mbvg.pkl',
             peakNumber=30)
 
diff --git a/docs/source/release/v3.14.0/diffraction.rst b/docs/source/release/v3.14.0/diffraction.rst
index a1cc728f84ecdcb97b7557595cc0ca681f434918..a1d75415248c3d8d43beffa6e050af3a35a991e2 100644
--- a/docs/source/release/v3.14.0/diffraction.rst
+++ b/docs/source/release/v3.14.0/diffraction.rst
@@ -10,3 +10,12 @@ Diffraction Changes
     improvements, followed by bug fixes.
 
 :ref:`Release 3.14.0 <v3.14.0>`
+
+
+Single Crystal Diffraction
+--------------------------
+
+Improvements
+############
+
+- :ref:`IntegratePeaksProfileFitting <algm-IntegratePeaksProfileFitting>` now supports MaNDi, TOPAZ, and CORELLI. Other instruments can easily be added as well.
diff --git a/instrument/CORELLI_Parameters.xml b/instrument/CORELLI_Parameters.xml
index e9cf3f940d4ea06da9e75f25eb91b28d9f51c7c2..1fde9c8970ce8946ff84970c19103b0c7095d366 100644
--- a/instrument/CORELLI_Parameters.xml
+++ b/instrument/CORELLI_Parameters.xml
@@ -14,6 +14,88 @@
       <value val="(101.9 * incidentEnergy^(-0.41) * exp(-incidentEnergy/282.0))" />
     </parameter>
 
+
+    <!-- Need to fill in gaps for peak profile fitting -->
+    <parameter name="fitConvolvedPeak" type="bool">
+     <value val="true"/>
+    </parameter>
+
+    <!-- Multiplier for profile fitting for BVG polar angle -->
+    <parameter name="sigX0Scale">
+     <value val="2." />
+    </parameter>
+
+    <!-- Multiplier for profile fitting for BVG azimuthal angle -->
+    <parameter name="sigY0Scale">
+     <value val="2." />
+    </parameter>
+
+    <!-- Number of rows between detector gaps for profile fitting -->
+    <parameter name="numDetRows" type="int">
+     <value val="255" />
+    </parameter>
+
+    <!-- Number of cols between detector gaps for profile fitting -->
+    <parameter name="numDetCols" type="int">
+     <value val="16" />
+    </parameter>
+
+    <!-- Number of polar bins for BVG histogramming when profile fitting -->
+    <parameter name="numBinsTheta" type="int">
+     <value val="50" />
+    </parameter>
+
+    <!-- Number of azimuthal bins for BVG histogramming when profile fitting -->
+    <parameter name="numBinsPhi" type="int">
+     <value val="50" />
+    </parameter>
+
+    <!-- Fraction along (h,k,l) to use for profile fitting. 0.5 is the next peak. -->
+    <parameter name="fracHKL">
+     <value val="0.4" />
+    </parameter>
+
+    <!-- Side length of each voxel for fitting in units of angstrom^-1 -->
+    <parameter name="dQPixel">
+     <value val="0.007" />
+    </parameter>
+
+    <!-- Minimum spacing for profile fitting the TOF profile. Units of microseconds -->
+    <parameter name="mindtBinWidth">
+     <value val="2" />
+    </parameter>
+
+    <!-- Maximum spacing for profile fitting the TOF profile. Units of microseconds -->
+    <parameter name="maxdtBinWidth">
+     <value val="60" />
+    </parameter>
+
+    <!-- Size of peak mask for background calculation in units of dQPixel -->
+    <parameter name="peakMaskSize" type="int">
+     <value val="10" />
+    </parameter>
+
+    <!-- Constraints for ICC fitting.  Valid names are iccA, iccB, iccR, iccT0, iccScale0
+         iccHatWidth and iccKConv.  Inputs are strings with values separated by
+         spaces which are prased by the IntegratePeaksProfileFitting algorithm.  
+         If two values are given they are treated as the lower and upper bounds. If 
+         three are given they are the lower bound, upper bound, and initial guess.-->
+    <parameter name="iccA" type="string">
+     <value val="0.25 0.75 0.5" />
+    </parameter>
+
+    <parameter name="iccB" type="string">
+     <value val="0.001 0.3 0.005" />
+    </parameter>
+
+    <parameter name="iccR" type="string">
+     <value val="0.05 0.15 0.1" />
+    </parameter>
+
+    <parameter name="iccKConv" type="string">
+     <value val="10.0 800.0 100.0" />
+    </parameter>
+
   </component-link>
 
 </parameter-file>
diff --git a/instrument/MANDI_Parameters.xml b/instrument/MANDI_Parameters.xml
index a617566959d86d03cf807d8d316bf02b43a8db00..9ac7e699e5c294a906f17ebcabf9ddf4a6a87296 100644
--- a/instrument/MANDI_Parameters.xml
+++ b/instrument/MANDI_Parameters.xml
@@ -8,6 +8,66 @@
   <value val="1"/>
 </parameter>
 
+<!-- Need to fill in gaps for peak profile fitting -->
+<parameter name="fitConvolvedPeak" type="bool">
+ <value val="true"/>
+</parameter>
+
+<!-- Multiplier for profile fitting for BVG polar angle -->
+<parameter name="sigX0Scale">
+ <value val="2." />
+</parameter>
+
+<!-- Multiplier for profile fitting for BVG azimuthal angle -->
+<parameter name="sigY0Scale">
+ <value val="2." />
+</parameter>
+
+<!-- Number of rows between detector gaps for profile fitting -->
+<parameter name="numDetRows" type="int">
+ <value val="255" />
+</parameter>
+
+<!-- Number of cols between detector gaps for profile fitting -->
+<parameter name="numDetCols" type="int">
+ <value val="255" />
+</parameter>
+
+<!-- Number of polar bins for BVG histogramming when profile fitting -->
+<parameter name="numBinsTheta" type="int">
+ <value val="50" />
+</parameter>
+
+<!-- Number of azimuthal bins for BVG histogramming when profile fitting -->
+<parameter name="numBinsPhi" type="int">
+ <value val="50" />
+</parameter>
+
+<!-- Fraction along (h,k,l) to use for profile fitting. 0.5 is the next peak. -->
+<parameter name="fracHKL">
+ <value val="0.4" />
+</parameter>
+
+<!-- Side length of each voxel for fitting in units of angstrom^-1 -->
+<parameter name="dQPixel">
+ <value val="0.003" />
+</parameter>
+
+<!-- Minimum spacing for profile fitting the TOF profile. Units of microseconds -->
+<parameter name="mindtBinWidth">
+ <value val="15" />
+</parameter>
+
+<!-- Maximum spacing for profile fitting the TOF profile. Units of microseconds -->
+<parameter name="maxdtBinWidth">
+ <value val="50" />
+</parameter>
+
+<!-- Size of peak mask for background calculation in units of dQPixel -->
+<parameter name="peakMaskSize" type="int">
+ <value val="5" />
+</parameter>
+
 </component-link>
 
 </parameter-file>
diff --git a/instrument/MANDI_Parameters_2015_08_01.xml b/instrument/MANDI_Parameters_2015_08_01.xml
index 52ba77f6fdbe47c82b3dc7d2b3fc290aec796878..2de3d3e50778bb6b52a523910e4af3c8a03a82a0 100644
--- a/instrument/MANDI_Parameters_2015_08_01.xml
+++ b/instrument/MANDI_Parameters_2015_08_01.xml
@@ -8,4 +8,65 @@
 </parameter>
 </component-link>
 
+<!-- Need to fill in gaps for peak profile fitting -->
+<parameter name="fitConvolvedPeak" type="bool">
+ <value val="true"/>
+</parameter>
+
+<!-- Multiplier for profile fitting for BVG polar angle -->
+<parameter name="sigX0Scale">
+ <value val="2." />
+</parameter>
+
+<!-- Multiplier for profile fitting for BVG azimuthal angle -->
+<parameter name="sigY0Scale">
+ <value val="2." />
+</parameter>
+
+<!-- Number of rows between detector gaps for profile fitting -->
+<parameter name="numDetRows" type="int">
+ <value val="255" />
+</parameter>
+
+<!-- Number of cols between detector gaps for profile fitting -->
+<parameter name="numDetCols" type="int">
+ <value val="255" />
+</parameter>
+
+<!-- Number of polar bins for BVG histogramming when profile fitting -->
+<parameter name="numBinsTheta" type="int">
+ <value val="50" />
+</parameter>
+
+<!-- Number of azimuthal bins for BVG histogramming when profile fitting -->
+<parameter name="numBinsPhi" type="int">
+ <value val="50" />
+</parameter>
+
+<!-- Fraction along (h,k,l) to use for profile fitting. 0.5 is the next peak. -->
+<parameter name="fracHKL">
+ <value val="0.4" />
+</parameter>
+
+<!-- Side length of each voxel for fitting in units of angstrom^-1 -->
+<parameter name="dQPixel">
+ <value val="0.003" />
+</parameter>
+
+<!-- Minimum spacing for profile fitting the TOF profile. Units of microseconds -->
+<parameter name="mindtBinWidth">
+ <value val="15" />
+</parameter>
+
+<!-- Maximum spacing for profile fitting the TOF profile. Units of microseconds -->
+<parameter name="maxdtBinWidth">
+ <value val="50" />
+</parameter>
+
+<!-- Size of peak mask for background calculation in units of dQPixel -->
+<parameter name="peakMaskSize" type="int">
+ <value val="5" />
+</parameter>
+
+
 </parameter-file>
diff --git a/instrument/MANDI_Parameters_2016_02_01.xml b/instrument/MANDI_Parameters_2016_02_01.xml
index 5172ef8dff0345ed75af05507ca19f83af787b98..5c875a8014aefca8597163bd2113d3bd668a3d31 100644
--- a/instrument/MANDI_Parameters_2016_02_01.xml
+++ b/instrument/MANDI_Parameters_2016_02_01.xml
@@ -6,6 +6,66 @@
 <parameter name="T0">
  <value val="-1.185000"/>
 </parameter>
-</component-link>
 
+<!-- Need to fill in gaps for peak profile fitting -->
+<parameter name="fitConvolvedPeak" type="bool">
+ <value val="true"/>
+</parameter>
+
+<!-- Multiplier for profile fitting for BVG polar angle -->
+<parameter name="sigX0Scale">
+ <value val="2." />
+</parameter>
+
+<!-- Multiplier for profile fitting for BVG azimuthal angle -->
+<parameter name="sigY0Scale">
+ <value val="2." />
+</parameter>
+
+<!-- Number of rows between detector gaps for profile fitting -->
+<parameter name="numDetRows" type="int">
+ <value val="255" />
+</parameter>
+
+<!-- Number of cols between detector gaps for profile fitting -->
+<parameter name="numDetCols" type="int">
+ <value val="255" />
+</parameter>
+
+<!-- Number of polar bins for BVG histogramming when profile fitting -->
+<parameter name="numBinsTheta" type="int">
+ <value val="50" />
+</parameter>
+
+<!-- Number of azimuthal bins for BVG histogramming when profile fitting -->
+<parameter name="numBinsPhi" type="int">
+ <value val="50" />
+</parameter>
+
+<!-- Fraction along (h,k,l) to use for profile fitting. 0.5 is the next peak. -->
+<parameter name="fracHKL">
+ <value val="0.4" />
+</parameter>
+
+<!-- Side length of each voxel for fitting in units of angstrom^-1 -->
+<parameter name="dQPixel">
+ <value val="0.003" />
+</parameter>
+
+<!-- Minimum spacing for profile fitting the TOF profile. Units of microseconds -->
+<parameter name="mindtBinWidth">
+ <value val="15" />
+</parameter>
+
+<!-- Maximum spacing for profile fitting the TOF profile. Units of microseconds -->
+<parameter name="maxdtBinWidth">
+ <value val="50" />
+</parameter>
+
+<!-- Size of peak mask for background calculation in units of dQPixel -->
+<parameter name="peakMaskSize" type="int">
+ <value val="5" />
+</parameter>
+
+</component-link>
 </parameter-file>
diff --git a/instrument/TOPAZ_Parameters.xml b/instrument/TOPAZ_Parameters.xml
index d0f57f5ff91415d011e034685985e5a84ee23d93..d2956eb6df187922bd173b30c6e5b95099a2aa24 100644
--- a/instrument/TOPAZ_Parameters.xml
+++ b/instrument/TOPAZ_Parameters.xml
@@ -83,6 +83,79 @@ detScale={13:1.046504,14:1.259293,16:1.02449,17:1.18898,18:0.88014,19:0.98665,\
 <parameter name="detScale49">
  <value val="0.79420"/>
 </parameter>
+
+<!-- Need to fill in gaps for peak profile fitting -->
+<parameter name="fitConvolvedPeak" type="bool">
+ <value val="false"/>
+</parameter>
+
+<!-- Multiplier for profile fitting for BVG polar angle -->
+<parameter name="sigX0Scale">
+ <value val="3." />
+</parameter>
+
+<!-- Multiplier for profile fitting for BVG azimuthal angle -->
+<parameter name="sigY0Scale">
+ <value val="3." />
+</parameter>
+
+<!-- Number of rows between detector gaps for profile fitting -->
+<parameter name="numDetRows" type="int">
+ <value val="255" />
+</parameter>
+
+<!-- Number of cols between detector gaps for profile fitting -->
+<parameter name="numDetCols" type="int">
+ <value val="255" />
+</parameter>
+
+<!-- Number of polar bins for BVG histogramming when profile fitting -->
+<parameter name="numBinsTheta" type="int">
+ <value val="50" />
+</parameter>
+
+<!-- Number of azimuthal bins for BVG histogramming when profile fitting -->
+<parameter name="numBinsPhi" type="int">
+ <value val="50" />
+</parameter>
+
+<!-- Fraction along (h,k,l) to use for profile fitting. 0.5 is the next peak. -->
+<parameter name="fracHKL">
+ <value val="0.4" />
+</parameter>
+
+<!-- Side length of each voxel for fitting in units of angstrom^-1 -->
+<parameter name="dQPixel">
+ <value val="0.01" />
+</parameter>
+
+<!-- Minimum spacing for profile fitting the TOF profile. Units of microseconds -->
+<parameter name="mindtBinWidth">
+ <value val="2" />
+</parameter>
+
+<!-- Maximum spacing for profile fitting the TOF profile. Units of microseconds -->
+<parameter name="maxdtBinWidth">
+ <value val="15" />
+</parameter>
+
+<!-- Size of peak mask for background calculation in units of dQPixel -->
+<parameter name="peakMaskSize" type="int">
+ <value val="15" />
+</parameter>
+
+<!-- Constraints for ICC fitting.  Valid names are iccA, iccB, iccR, iccT0, iccScale0
+     iccHatWidth and iccKConv.  Inputs are strings with values separated by
+     spaces which are prased by the IntegratePeaksProfileFitting algorithm.  
+     If two values are given they are treated as the lower and upper bounds. If 
+     three are given they are the lower bound, upper bound, and initial guess.-->
+<parameter name="iccB" type="string">
+ <value val="0.001 0.3 0.005" />
+</parameter>
+
+<parameter name="iccKConv" type="string">
+ <value val="10.0 800.0 100.0" />
+</parameter>
 </component-link>
 
 </parameter-file>
diff --git a/scripts/SCD_Reduction/BVGFitTools.py b/scripts/SCD_Reduction/BVGFitTools.py
index 3a2aa938e19f7025e0dfb85720f9b37e16ba0d17..7fbf60c1295ecec73dbf5e3b70f4da661a252a01 100644
--- a/scripts/SCD_Reduction/BVGFitTools.py
+++ b/scripts/SCD_Reduction/BVGFitTools.py
@@ -11,11 +11,11 @@ import BivariateGaussian as BivariateGaussian
 plt.ion()
 
 
-def get3DPeak(peak, box, padeCoefficients, qMask, nTheta=150, nPhi=150, fracBoxToHistogram=1.0,
+def get3DPeak(peak, peaks_ws, box, padeCoefficients, qMask, nTheta=150, nPhi=150, fracBoxToHistogram=1.0,
               plotResults=False, zBG=1.96, bgPolyOrder=1, fICCParams=None, oldICCFit=None,
               strongPeakParams=None, forceCutoff=250, edgeCutoff=15,
               neigh_length_m=3, q_frame='sample', dtSpread=0.03, pplmin_frac=0.8, pplmax_frac=1.5, mindtBinWidth=1,
-              figureNumber=2):
+              maxdtBinWidth=50, figureNumber=2, peakMaskSize=5, iccFitDict=None):
     n_events = box.getNumEventsArray()
 
     if q_frame == 'lab':
@@ -30,13 +30,14 @@ def get3DPeak(peak, box, padeCoefficients, qMask, nTheta=150, nPhi=150, fracBoxT
         goodIDX, pp_lambda = ICCFT.getBGRemovedIndices(
                     n_events, peak=peak, box=box, qMask=qMask, calc_pp_lambda=True, padeCoefficients=padeCoefficients,
                     neigh_length_m=neigh_length_m, pp_lambda=None, pplmin_frac=pplmin_frac,
-                    pplmax_frac=pplmax_frac, mindtBinWidth=mindtBinWidth)
-
+                    pplmax_frac=pplmax_frac, mindtBinWidth=mindtBinWidth, maxdtBinWidth=maxdtBinWidth,
+                    peakMaskSize=peakMaskSize, iccFitDict=iccFitDict)
         YTOF, fICC, x_lims = fitTOFCoordinate(
                     box, peak, padeCoefficients, dtSpread=dtSpread, qMask=qMask, bgPolyOrder=bgPolyOrder, zBG=zBG,
                     plotResults=plotResults, pp_lambda=pp_lambda, neigh_length_m=neigh_length_m, pplmin_frac=pplmin_frac,
-                    pplmax_frac=pplmax_frac, mindtBinWidth=mindtBinWidth)
-
+                    pplmax_frac=pplmax_frac, mindtBinWidth=mindtBinWidth, maxdtBinWidth=maxdtBinWidth,
+                    peakMaskSize=peakMaskSize, iccFitDict=iccFitDict)
+        chiSqTOF = mtd['fit_Parameters'].column(1)[-1]
     else:  # we already did I-C profile, so we'll just read the parameters
         pp_lambda = fICCParams[-1]
         fICC = ICC.IkedaCarpenterConvoluted()
@@ -49,7 +50,9 @@ def get3DPeak(peak, box, padeCoefficients, qMask, nTheta=150, nPhi=150, fracBoxT
         fICC['HatWidth'] = fICCParams[10]
         fICC['KConv'] = fICCParams[11]
         goodIDX, _ = ICCFT.getBGRemovedIndices(
-            n_events, pp_lambda=pp_lambda, qMask=qMask)
+            n_events, pp_lambda=pp_lambda, qMask=qMask, peakMaskSize=peakMaskSize,
+            iccFitDict=iccFitDict)
+        chiSqTOF = fICCParams[4] #Last entry
 
         # Get the 3D TOF component, YTOF
         if oldICCFit is not None:
@@ -71,8 +74,34 @@ def get3DPeak(peak, box, padeCoefficients, qMask, nTheta=150, nPhi=150, fracBoxT
         goodIDX *= qMask
     X = boxToTOFThetaPhi(box, peak)
     dEdge = edgeCutoff
+
+    # This section defines detector size to determine if a peak is too
+    # close to the edge.  Order is [NROWS, NCOLS].
+    try:
+        numDetRows = peaks_ws.getInstrument().getIntParameter("numDetRows")[0]
+        numDetCols = peaks_ws.getInstrument().getIntParameter("numDetCols")[0]
+        nPixels = [numDetRows, numDetCols]
+    except:
+        UserWarning('Detector size not found in instrument parameters file. Assuming a 255*255 detector!')
+        nPixels = [255,255]
+
     useForceParams = peak.getIntensity() < forceCutoff or peak.getRow() <= dEdge or peak.getRow(
-    ) >= 255 - dEdge or peak.getCol() <= dEdge or peak.getCol() >= 255 - dEdge
+    ) >= nPixels[0] - dEdge or peak.getCol() <= dEdge or peak.getCol() >= nPixels[1] - dEdge
+
+    #Here we retrieve some instrument specific parameters
+    try:
+        doPeakConvolution = peaks_ws.getInstrument().getBoolParameter("fitConvolvedPeak")[0]
+    except:
+        doPeakConvolution = False
+    try:
+        sigX0Scale = peaks_ws.getInstrument().getNumberParameter("sigX0Scale")[0]
+    except:
+        sigX0Scale = 1.0
+    try:
+        sigY0Scale = peaks_ws.getInstrument().getNumberParameter("sigY0Scale")[0]
+    except:
+        sigY0Scale = 1.0
+
     if strongPeakParams is not None and useForceParams:  # We will force parameters on this fit
         ph = np.arctan2(q0[1], q0[0])
         th = np.arctan2(q0[2], np.hypot(q0[0], q0[1]))
@@ -85,10 +114,12 @@ def get3DPeak(peak, box, padeCoefficients, qMask, nTheta=150, nPhi=150, fracBoxT
                                                                                              phthPeak[0],
                                                                                              phthPeak[1]))
         params, h, t, p = doBVGFit(box, nTheta=nTheta, nPhi=nPhi, fracBoxToHistogram=fracBoxToHistogram,
-                                   goodIDX=goodIDX, forceParams=strongPeakParams[nnIDX])
+                                   goodIDX=goodIDX, forceParams=strongPeakParams[nnIDX],
+                                   doPeakConvolution=doPeakConvolution, sigX0Scale=sigX0Scale, sigY0Scale=sigY0Scale)
     else:  # Just do the fit - no nearest neighbor assumptions
         params, h, t, p = doBVGFit(
-            box, nTheta=nTheta, nPhi=nPhi, fracBoxToHistogram=fracBoxToHistogram, goodIDX=goodIDX)
+            box, nTheta=nTheta, nPhi=nPhi, fracBoxToHistogram=fracBoxToHistogram, goodIDX=goodIDX,
+            doPeakConvolution=doPeakConvolution, sigX0Scale=sigX0Scale, sigY0Scale=sigY0Scale)
 
     if plotResults:
         compareBVGFitData(
@@ -113,7 +144,10 @@ def get3DPeak(peak, box, padeCoefficients, qMask, nTheta=150, nPhi=150, fracBoxT
     YBVG = bvg(1.0, mu, sigma, XTHETA, XPHI, 0)
 
     # Do scaling to the data
-    Y, redChiSq, scaleFactor = fitScaling(n_events, box, YTOF, YBVG)
+    if doPeakConvolution: #This means peaks will have gaps, so we only use good data to scale
+        Y, redChiSq, scaleFactor = fitScaling(n_events, box, YTOF, YBVG, goodIDX=goodIDX)
+    else:
+        Y, redChiSq, scaleFactor = fitScaling(n_events, box, YTOF, YBVG)
     YBVG2 = bvg(1.0, mu, sigma, XTHETA, XPHI, 0)
     YTOF2 = getYTOF(fICC, XTOF, x_lims)
     Y2 = YTOF2 * YBVG2
@@ -139,6 +173,7 @@ def get3DPeak(peak, box, padeCoefficients, qMask, nTheta=150, nPhi=150, fracBoxT
     retParams['bgBVG'] = bgBVG
     retParams['scale3d'] = scaleFactor
     retParams['chiSq3d'] = redChiSq
+    retParams['chiSq'] = chiSqTOF
     retParams['dQ'] = np.linalg.norm(newCenter - q0)
     retParams['newQ'] = newCenter
 
@@ -176,8 +211,7 @@ def fitScaling(n_events, box, YTOF, YBVG, goodIDX=None, neigh_length_m=3):
         goodIDX[max(fitMaxIDX[0] - dP, 0):min(fitMaxIDX[0] + dP, goodIDX.shape[0]),
                 max(fitMaxIDX[1] - dP, 0):min(fitMaxIDX[1] + dP, goodIDX.shape[1]),
                 max(fitMaxIDX[2] - dP, 0):min(fitMaxIDX[2] + dP, goodIDX.shape[2])] = True
-        goodIDX = np.logical_and(goodIDX, conv_n_events > 0)
-
+    goodIDX = np.logical_and(goodIDX, conv_n_events > 0)
     # A1 = slope, A0 = offset
     scaleLinear = Polynomial(n=1)
     scaleLinear.constrain("A1>0")
@@ -217,7 +251,8 @@ def getXTOF(box, peak):
 
 def fitTOFCoordinate(box, peak, padeCoefficients, dtSpread=0.03, minFracPixels=0.01,
                      neigh_length_m=3, zBG=1.96, bgPolyOrder=1, qMask=None, plotResults=False,
-                     fracStop=0.01, pp_lambda=None, pplmin_frac=0.8, pplmax_frac=1.5, mindtBinWidth=1):
+                     fracStop=0.01, pp_lambda=None, pplmin_frac=0.8, pplmax_frac=1.5, mindtBinWidth=1,
+                     maxdtBinWidth=50, peakMaskSize=5, iccFitDict=None):
 
     # Get info from the peak
     tof = peak.getTOF()  # in us
@@ -235,10 +270,13 @@ def fitTOFCoordinate(box, peak, padeCoefficients, dtSpread=0.03, minFracPixels=0
                                 dtSpread=dtSpread, minFracPixels=minFracPixels,
                                 neigh_length_m=neigh_length_m, zBG=zBG, pp_lambda=pp_lambda,
                                 pplmin_frac=pplmin_frac, pplmax_frac=pplmax_frac,
-                                mindtBinWidth=mindtBinWidth)
+                                mindtBinWidth=mindtBinWidth, maxdtBinWidth=maxdtBinWidth,
+                                peakMaskSize=peakMaskSize,
+                                iccFitDict=iccFitDict)
 
     fitResults, fICC = ICCFT.doICCFit(tofWS, energy, flightPath,
-                                      padeCoefficients, fitOrder=bgPolyOrder, constraintScheme=1)
+                                      padeCoefficients, fitOrder=bgPolyOrder, constraintScheme=1,
+                                      iccFitDict=iccFitDict)
 
     for i, param in enumerate(['A', 'B', 'R', 'T0', 'Scale', 'HatWidth', 'KConv']):
         fICC[param] = mtd['fit_Parameters'].row(i)['Value']
@@ -391,7 +429,8 @@ def compareBVGFitData(box, params, nTheta=200, nPhi=200, figNumber=2, fracBoxToH
 
 
 def doBVGFit(box, nTheta=200, nPhi=200, zBG=1.96, fracBoxToHistogram=1.0, goodIDX=None,
-             forceParams=None, forceTolerance=0.1, dth=10, dph=10):
+             forceParams=None, forceTolerance=0.1, dth=10, dph=10,
+             doPeakConvolution=False, sigX0Scale=1., sigY0Scale=1.):
     """
     doBVGFit takes a binned MDbox and returns the fit of the peak shape along the non-TOF direction.  This is done in one of two ways:
         1) Standard least squares fit of the 2D histogram.
@@ -408,6 +447,8 @@ def doBVGFit(box, nTheta=200, nPhi=200, zBG=1.96, fracBoxToHistogram=1.0, goodID
         forceParams: set of parameters to force.  These are the same format as a row in strongPeaksParams
         forceTolerance: the factor we allow sigX, sigY, sigP to change when forcing peaks.  Not used if forceParams is None.
         dth, dph: The peak center may move by (dth, dph) from predicted position (in units of histogram pixels).
+        doPeakConvolution: boolean stating whether we should fit a convolved (smoothed) peak.  This is useful for filling in
+                gaps for 3He detector tube packs.
 
     """
     h, thBins, phBins = getAngularHistogram(
@@ -454,6 +495,17 @@ def doBVGFit(box, nTheta=200, nPhi=200, zBG=1.96, fracBoxToHistogram=1.0, goodID
         boundsDict['SigP'] = [-1., 1.]
         boundsDict['Bg'] = [0, np.inf]
 
+        # Here we can make instrument-specific changes to our initial guesses and boundaries
+        sigX0 = sigX0*sigX0Scale
+        sigY0 = sigY0*sigY0Scale
+
+        if doPeakConvolution:
+            neigh_length_m = 5
+            convBox = 1.0*np.ones([neigh_length_m, neigh_length_m]) / neigh_length_m**2
+            conv_h = convolve(h, convBox)
+            H[:,:,0] = conv_h
+            H[:,:,1] = conv_h
+
         # Set our initial guess
         m = BivariateGaussian.BivariateGaussian()
         m.init()
@@ -468,13 +520,15 @@ def doBVGFit(box, nTheta=200, nPhi=200, zBG=1.96, fracBoxToHistogram=1.0, goodID
         m.setAttributeValue('nX', h.shape[0])
         m.setAttributeValue('nY', h.shape[1])
         m.setConstraints(boundsDict)
+
         # Do the fit
+        #bvgWS = CreateWorkspace(OutputWorkspace='bvgWS', DataX=pos.ravel(
+        #), DataY=H.ravel(), DataE=np.sqrt(H.ravel()))
         bvgWS = CreateWorkspace(OutputWorkspace='bvgWS', DataX=pos.ravel(
         ), DataY=H.ravel(), DataE=np.sqrt(H.ravel()))
 
         fitResults = Fit(Function=m, InputWorkspace='bvgWS', Output='bvgfit',
                          Minimizer='Levenberg-MarquardtMD')
-
     elif forceParams is not None:
         p0 = np.zeros(7)
         p0[0] = np.max(h)
@@ -508,6 +562,16 @@ def doBVGFit(box, nTheta=200, nPhi=200, zBG=1.96, fracBoxToHistogram=1.0, goodID
         boundsDict['SigX'] = [bounds[0][3], bounds[1][3]]
         boundsDict['SigY'] = [bounds[0][4], bounds[1][4]]
         boundsDict['SigP'] = [bounds[0][5], bounds[1][5]]
+
+        # Here we can make instrument-specific changes to our initial guesses and boundaries
+
+        if doPeakConvolution:
+            neigh_length_m = 5
+            convBox = 1.0*np.ones([neigh_length_m, neigh_length_m]) / neigh_length_m**2
+            conv_h = convolve(h, convBox)
+            H[:,:,0] = conv_h
+            H[:,:,1] = conv_h
+
         # Set our initial guess
         m = BivariateGaussian.BivariateGaussian()
         m.init()
diff --git a/scripts/SCD_Reduction/ICCFitTools.py b/scripts/SCD_Reduction/ICCFitTools.py
index e450536bfa6ddfebe0b90009dfc23122327869b1..a7186882ac598707262b638480986fbeec87ad34 100644
--- a/scripts/SCD_Reduction/ICCFitTools.py
+++ b/scripts/SCD_Reduction/ICCFitTools.py
@@ -13,6 +13,21 @@ from scipy.ndimage.filters import convolve
 plt.ion()
 
 
+def parseConstraints(peaks_ws):
+    """
+    returns a dictionary containing parameters for ICC fitting. Parameters
+    are derived from instrument parameters files (see MANDI_Parameters.xml
+    for an example).
+    """
+    possibleKeys = ['iccA', 'iccB', 'iccR', 'iccT0', 'iccScale0', 'iccHatWidth', 'iccKConv']
+    d = {}
+    for paramName in possibleKeys:
+        if peaks_ws.getInstrument().hasParameter(paramName):
+            vals = np.array(peaks_ws.getInstrument().getStringParameter(paramName)[0].split(),dtype=float)
+            d[paramName] = vals
+    return d
+
+
 def scatFun(x, A, bg):
     """
     scatFun: returns A/x+bg.  Used for background estimation.
@@ -92,7 +107,8 @@ def getQXQYQZ(box):
 
 
 def getQuickTOFWS(box, peak, padeCoefficients, goodIDX=None, dtSpread=0.03, qMask=None,
-                  pp_lambda=None, minppl_frac=0.8, maxppl_frac=1.5, mindtBinWidth=1, constraintScheme=1):
+                  pp_lambda=None, minppl_frac=0.8, maxppl_frac=1.5, mindtBinWidth=1, maxdtBinWidth=50,
+                  constraintScheme=1, peakMaskSize=5, iccFitDict=None):
     """
     getQuickTOFWS - generates a quick-and-dirty TOFWS.  Useful for determining the background.
     Input:
@@ -106,7 +122,9 @@ def getQuickTOFWS(box, peak, padeCoefficients, goodIDX=None, dtSpread=0.03, qMas
         pp_lambda - nominal background level.  Will be calculated if set to None.
         minppl_frac, maxppl_frac: fraction of the predicted pp_lambda to try if calculating pp_lambda
         mindtBinWidth - the minimum binwidth (in us) that we will allow when histogramming.
+        maxdtBinWidth - the maximum binwidth (in us) that we will allow when histogramming.
         constraintScheme - which constraint scheme we use.  Typically set to 1
+        iccFitDict - a dictionary containing ICC fit constraints and possibly initial guesses
     Output:
         chiSq - reduced chiSquared from fitting the TOF profile
         h - list of [Y, X], with Y and X being numpy arrays of the Y and X of the tof profile
@@ -128,9 +146,11 @@ def getQuickTOFWS(box, peak, padeCoefficients, goodIDX=None, dtSpread=0.03, qMas
     tofWS, ppl = getTOFWS(box, flightPath, scatteringHalfAngle, tof, peak, qMask, dtSpread=dtSpread,
                           minFracPixels=0.01, neigh_length_m=3, zBG=1.96, pp_lambda=pp_lambda,
                           calc_pp_lambda=calc_pp_lambda, pplmin_frac=minppl_frac, pplmax_frac=minppl_frac,
-                          mindtBinWidth=mindtBinWidth)
+                          mindtBinWidth=mindtBinWidth, maxdtBinWidth=maxdtBinWidth,
+                          peakMaskSize=peakMaskSize, iccFitDict=iccFitDict)
     fitResults, fICC = doICCFit(
-        tofWS, energy, flightPath, padeCoefficients, fitOrder=1, constraintScheme=constraintScheme)
+        tofWS, energy, flightPath, padeCoefficients, fitOrder=1, constraintScheme=constraintScheme,
+        iccFitDict=iccFitDict)
     h = [tofWS.readY(0), tofWS.readX(0)]
     chiSq = fitResults.OutputChi2overDoF
 
@@ -193,7 +213,8 @@ def getPoissionGoodIDX(n_events, zBG=1.96, neigh_length_m=3):
 
 def getOptimizedGoodIDX(n_events, padeCoefficients, zBG=1.96, neigh_length_m=3, qMask=None,
                         peak=None, box=None, pp_lambda=None, peakNumber=-1, minppl_frac=0.8,
-                        maxppl_frac=1.5, mindtBinWidth=1, constraintScheme=1):
+                        maxppl_frac=1.5, mindtBinWidth=1, maxdtBinWidth=50,
+                        constraintScheme=1, peakMaskSize=5, iccFitDict=None):
     """
     getOptimizedGoodIDX - returns a numpy arrays which is true if the voxel contains events at
             the zBG z level (1.96=95%CI).  Rather than using Poission statistics, this function
@@ -211,9 +232,11 @@ def getOptimizedGoodIDX(n_events, padeCoefficients, zBG=1.96, neigh_length_m=3,
         pp_lambda - Currently unused.  Leave as None. TODO: remove this.
         peakNumber - currently unused.  TODO: Remove this.
         minppl_frac, maxppl_frac; range around predicted pp_lambda to check.
-        mindtBinWidth - the small dt (in us) allowed for constructing the TOF profile.
+        mindtBinWidth - the smallest dt (in us) allowed for constructing the TOF profile.
+        mindtBinWidth - the largest dt (in us) allowed for constructing the TOF profile.
         constraintScheme - sets the constraints for TOF profile fitting.  Leave as 1 if you're
                 not sure how to modify this.
+        iccFitDict - a dictionary containing ICC fit constraints and possibly initial guesses
 
     Output:
         goodIDX: a numpy arrays the same size as n_events that is True of False for if it contains
@@ -239,7 +262,8 @@ def getOptimizedGoodIDX(n_events, padeCoefficients, zBG=1.96, neigh_length_m=3,
     cX = nX//2
     cY = nY//2
     cZ = nZ//2
-    dP = 5
+    dP = peakMaskSize
+
     peakMask = qMask.copy()
     peakMask[cX-dP:cX+dP, cY-dP:cY+dP, cZ-dP:cZ+dP] = 0
     neigh_length_m=3
@@ -274,9 +298,10 @@ def getOptimizedGoodIDX(n_events, padeCoefficients, zBG=1.96, neigh_length_m=3,
             try:
                 chiSq, h, intens, sigma = getQuickTOFWS(box, peak, padeCoefficients, goodIDX=goodIDX, qMask=qMask, pp_lambda=pp_lambda,
                                                         minppl_frac=minppl_frac, maxppl_frac=maxppl_frac, mindtBinWidth=mindtBinWidth,
-                                                        constraintScheme=constraintScheme)
+                                                        maxdtBinWidth=maxdtBinWidth, constraintScheme=constraintScheme,
+                                                        peakMaskSize=peakMaskSize, iccFitDict=iccFitDict)
             except:
-                # raise
+                #raise
                 break
             chiSqList[i] = chiSq
             ISIGList[i] = intens/sigma
@@ -288,6 +313,7 @@ def getOptimizedGoodIDX(n_events, padeCoefficients, zBG=1.96, neigh_length_m=3,
         except RuntimeError:
             # This is caused by there being fewer datapoints remaining than parameters.  For now, we just hope
             # we found a satisfactory answer.
+            raise
             break
         except KeyboardInterrupt:
             sys.exit()
@@ -296,7 +322,9 @@ def getOptimizedGoodIDX(n_events, padeCoefficients, zBG=1.96, neigh_length_m=3,
     goodIDX, _ = getBGRemovedIndices(n_events, pp_lambda=pp_lambda)
     chiSq, h, intens, sigma = getQuickTOFWS(box, peak, padeCoefficients, goodIDX=goodIDX, qMask=qMask,
                                             pp_lambda=pp_lambda, minppl_frac=minppl_frac, maxppl_frac=maxppl_frac,
-                                            mindtBinWidth=mindtBinWidth)
+                                            mindtBinWidth=mindtBinWidth, maxdtBinWidth=maxdtBinWidth,
+                                            peakMaskSize=peakMaskSize,
+                                            iccFitDict=iccFitDict)
     if qMask is not None:
         return goodIDX*qMask, pp_lambda
     return goodIDX, pp_lambda
@@ -304,7 +332,8 @@ def getOptimizedGoodIDX(n_events, padeCoefficients, zBG=1.96, neigh_length_m=3,
 
 def getBGRemovedIndices(n_events, zBG=1.96, calc_pp_lambda=False, neigh_length_m=3, qMask=None,
                         peak=None, box=None, pp_lambda=None, peakNumber=-1, padeCoefficients=None,
-                        pplmin_frac=0.8, pplmax_frac=1.5, mindtBinWidth=1, constraintScheme=1):
+                        pplmin_frac=0.8, pplmax_frac=1.5, mindtBinWidth=1, maxdtBinWidth=50,
+                        constraintScheme=1, peakMaskSize=5, iccFitDict=None):
     """
     getBGRemovedIndices - A wrapper for getOptimizedGoodIDX
     Input:
@@ -319,9 +348,11 @@ def getBGRemovedIndices(n_events, zBG=1.96, calc_pp_lambda=False, neigh_length_m
         pp_lambda - Currently unused.  Leave as None. TODO: remove this.
         peakNumber - currently unused.  TODO: Remove this.
         minppl_frac, maxppl_frac; range around predicted pp_lambda to check.
-        mindtBinWidth - the small dt (in us) allowed for constructing the TOF profile.
+        mindtBinWidth - the smallest dt (in us) allowed for constructing the TOF profile.
+        maxdtBinWidth - the largest dt (in us) allowed for constructing the TOF profile.
         constraintScheme - sets the constraints for TOF profile fitting.  Leave as 1 if you're
                 not sure how to modify this.
+        iccFitDict - a dictionary containing ICC fit constraints and possibly initial guesses
 
     Output:
         goodIDX: a numpy arrays the same size as n_events that is True of False for if it contains
@@ -337,8 +368,6 @@ def getBGRemovedIndices(n_events, zBG=1.96, calc_pp_lambda=False, neigh_length_m
         sys.exit(
             'Error in ICCFT:getBGRemovedIndices: calc_pp_lambda is True, but no moderator coefficients are provided.')
 
-    # TODO: this result should be multiplied by qMask if qMask is not None - but I need to check that that change won't affect
-    # other workflows.
     if pp_lambda is not None:
         # Set up some things to only consider good pixels
         hasEventsIDX = n_events > 0
@@ -361,7 +390,9 @@ def getBGRemovedIndices(n_events, zBG=1.96, calc_pp_lambda=False, neigh_length_m
                 return getOptimizedGoodIDX(n_events, padeCoefficients, zBG=1.96, neigh_length_m=neigh_length_m,
                                            minppl_frac=pplmin_frac, maxppl_frac=pplmax_frac, qMask=qMask, peak=peak,
                                            box=box, pp_lambda=pp_lambda, peakNumber=peakNumber,
-                                           mindtBinWidth=mindtBinWidth, constraintScheme=constraintScheme)
+                                           mindtBinWidth=mindtBinWidth, maxdtBinWidth=maxdtBinWidth,
+                                           constraintScheme=constraintScheme,
+                                           peakMaskSize=peakMaskSize, iccFitDict=iccFitDict)
             except KeyboardInterrupt:
                 sys.exit()
             except:
@@ -521,8 +552,8 @@ def get_pp_lambda(n_events, hasEventsIDX):
 
 def getTOFWS(box, flightPath, scatteringHalfAngle, tofPeak, peak, qMask, zBG=-1.0, dtSpread=0.02,
              minFracPixels=0.005, workspaceNumber=None, neigh_length_m=0, pp_lambda=None, calc_pp_lambda=False,
-             padeCoefficients=None, pplmin_frac=0.8, pplmax_frac=1.5,
-             mindtBinWidth=1, constraintScheme=1):
+             padeCoefficients=None, pplmin_frac=0.8, pplmax_frac=1.5, peakMaskSize=5,
+             mindtBinWidth=1, maxdtBinWidth=50, constraintScheme=1, iccFitDict=None):
     """
     Builds a TOF profile from the data in box which is nominally centered around a peak.
     Input:
@@ -545,8 +576,10 @@ def getTOFWS(box, flightPath, scatteringHalfAngle, tofPeak, peak, qMask, zBG=-1.
             want to, you can feed the value in as pp_lambda (calculated elsewhere).
         minppl_frac, maxppl_frac; range around predicted pp_lambda to check.
         mindtBinWidth - the small dt (in us) allowed for constructing the TOF profile.
+        maxdtBinWidth - the largest dt (in us) allowed for constructing the TOF profile.
         constraintScheme - sets the constraints for TOF profile fitting.  Leave as 1 if you're
                 not sure how to modify this.
+        iccFitDict - a dictionary containing ICC fit constraints and possibly initial guesses
 
     Output:
         tofWS - a mantid containing the TOF profile.  X-axis is TOF (units: us) and
@@ -563,8 +596,9 @@ def getTOFWS(box, flightPath, scatteringHalfAngle, tofPeak, peak, qMask, zBG=-1.
         goodIDX, pp_lambda = getBGRemovedIndices(n_events, box=box, qMask=qMask, peak=peak, pp_lambda=pp_lambda,
                                                  calc_pp_lambda=calc_pp_lambda, padeCoefficients=padeCoefficients,
                                                  pplmin_frac=pplmin_frac, pplmax_frac=pplmax_frac,
-                                                 mindtBinWidth=mindtBinWidth, constraintScheme=constraintScheme)
-        # TODO bad naming, but a lot of the naming in this function assumes it
+                                                 mindtBinWidth=mindtBinWidth, maxdtBinWidth=maxdtBinWidth,
+                                                 constraintScheme=constraintScheme,
+                                                 peakMaskSize=peakMaskSize, iccFitDict=iccFitDict)
         hasEventsIDX = np.logical_and(goodIDX, qMask)
         boxMeanIDX = np.where(hasEventsIDX)
     else:  # don't do background removal - just consider one pixel at a time
@@ -608,7 +642,7 @@ def getTOFWS(box, flightPath, scatteringHalfAngle, tofPeak, peak, qMask, zBG=-1.
         [qx[qx.shape[0]//2 + 1], qy[qy.shape[0]//2+1], qz[qz.shape[0]//2+1]])
     dtBinWidth = np.abs(tD-tC)
     dtBinWidth = max(mindtBinWidth, dtBinWidth)
-    dtBinWidth = min(50, dtBinWidth)
+    dtBinWidth = min(maxdtBinWidth, dtBinWidth)
     tBins = np.arange(tMin, tMax, dtBinWidth)
     weightList = n_events[hasEventsIDX]  # - pp_lambda
     h = np.histogram(tList, tBins, weights=weightList)
@@ -792,7 +826,8 @@ def getBoxFracHKL(peak, peaks_ws, MDdata, UBMatrix, peakNumber, dQ, dQPixel=0.00
     return Box
 
 
-def doICCFit(tofWS, energy, flightPath, padeCoefficients, constraintScheme=None, outputWSName='fit', fitOrder=1):
+def doICCFit(tofWS, energy, flightPath, padeCoefficients, constraintScheme=None, outputWSName='fit', fitOrder=1,
+             iccFitDict=None):
     """
     doICCFit - Carries out the actual least squares fit for the TOF workspace.
     Intput:
@@ -811,6 +846,7 @@ def doICCFit(tofWS, energy, flightPath, padeCoefficients, constraintScheme=None,
         outputWSName - the base name for output workspaces.  Leave as 'fit' unless you are
             doing multiple fits.
         fitOrder - the background polynomial order
+        iccFitDict - a dictionary containing ICC fit constraints and possibly initial guesses
     Returns:
         fitResults - the output from Mantid's Fit() routine
         fICC - an IkedaCarpenterConvoluted function with parameters set to the fit values.
@@ -833,12 +869,30 @@ def doICCFit(tofWS, energy, flightPath, padeCoefficients, constraintScheme=None,
     fICC.setParameter(4, x0[4])
     #fICC.setPenalizedConstraints(A0=[0.01, 1.0], B0=[0.005, 1.5], R0=[0.01, 1.0], T00=[0,1.0e10], KConv0=[10,500],penalty=1.0e20)
     if constraintScheme == 1:
+        # Set these bounds as defaults - they can be changed for each instrument
+        # They can be changed by setting parameters in the INSTRUMENT_Parameters.xml file.
+        A0 = [0.5*x0[0], 1.5*x0[0]]
+        B0 = [0.5*x0[1], 1.5*x0[1]]
+        R0 = [0.5*x0[2], 1.5*x0[2]]
+        T00 = [0.,1.e10]
+        HatWidth0 = [0., 5.]
+        Scale0 = [0., np.inf]
+        KConv0 = [100, 140]
+
+        # Now we see what instrument specific parameters we have
+        if iccFitDict is not None:
+            possibleKeys = ['iccA', 'iccB', 'iccR', 'iccT0', 'iccScale0', 'iccHatWidth', 'iccKConv']
+            for keyIDX, (key, bounds) in enumerate(zip(possibleKeys, [A0, B0, R0, T00, Scale0, HatWidth0, KConv0])):
+                if key in iccFitDict:
+                    bounds[0] = iccFitDict[key][0]
+                    bounds[1] = iccFitDict[key][1]
+                    if len(iccFitDict[key] == 3):
+                        x0[keyIDX] = iccFitDict[key][2]
+                        fICC.setParameter(keyIDX, x0[keyIDX])
         try:
-            fICC.setPenalizedConstraints(A0=[0.5*x0[0], 1.5*x0[0]], B0=[0.5*x0[1], 1.5*x0[1]], R0=[
-                                         0.5*x0[2], 1.5*x0[2]], T00=[0., 1.e10], KConv0=[100, 140], penalty=1.0e10)
+            fICC.setPenalizedConstraints(A0=A0, B0=B0, R0=R0, T00=T00, KConv0=KConv0, penalty=1.0e10)
         except:
-            fICC.setPenalizedConstraints(A0=[0.5*x0[0], 1.5*x0[0]], B0=[0.5*x0[1], 1.5*x0[1]], R0=[
-                                         0.5*x0[2], 1.5*x0[2]], T00=[0., 1.e10], KConv0=[100, 140], penalty=None)
+            fICC.setPenalizedConstraints(A0=A0, B0=B0, R0=R0, T00=T00, KConv0=KConv0, penalty=None)
     if constraintScheme == 2:
         try:
             fICC.setPenalizedConstraints(A0=[0.0001, 1.0], B0=[0.005, 1.5], R0=[0.00, 1.], Scale0=[
@@ -862,7 +916,8 @@ def integrateSample(run, MDdata, peaks_ws, paramList, UBMatrix, dQ, qMask, padeC
                     figsFormat=None, dtSpread=0.02, fracHKL=0.5, minFracPixels=0.0000, fracStop=0.01,
                     dQPixel=0.005, p=None, neigh_length_m=0, zBG=-1.0, bgPolyOrder=1,
                     doIterativeBackgroundFitting=False, q_frame='sample',
-                    progressFile=None, minpplfrac=0.8, maxpplfrac=1.5, mindtBinWidth=1, keepFitDict=False, constraintScheme=1):
+                    progressFile=None, minpplfrac=0.8, maxpplfrac=1.5, mindtBinWidth=1, maxdtBinWidth=50,
+                    keepFitDict=False, constraintScheme=1, peakMaskSize=5, iccFitDict=None):
     """
     integrateSample contains the loop that integrates over all of the peaks in a run and saves the results.  Importantly, it also handles
     errors (mostly by passing and recording special values for failed fits.)
@@ -894,9 +949,11 @@ def integrateSample(run, MDdata, peaks_ws, paramList, UBMatrix, dQ, qMask, padeC
         minpplfrac, maxpplfrac - the range of pp_lambdas to check around the predicted pp_lambda as a fraction
             of pp_lambda
         mindtBinWidth - the smallest dt bin width (in us) allowed for TOF profile construction
+        mindtBinWidth - the largest dt bin width (in us) allowed for TOF profile construction
         keepFitDict= bool; if True then each fit will be saved in a dictionary and returned.  For large peak sets,
             this can take a lot of memory.
         constraintScheme - which constraint scheme we will use - leave as 1 if you're not sure what this does.
+        iccFitDict - a dictionary containing ICC fit constraints and possibly initial guesses
     Returns:
         peaks_ws - the peaks_ws with updated I, sig(I)
         paramList - a list of fit parameters for each peak.  Parameters are in the order:
@@ -934,13 +991,16 @@ def integrateSample(run, MDdata, peaks_ws, paramList, UBMatrix, dQ, qMask, padeC
                 goodIDX, pp_lambda = getBGRemovedIndices(n_events, peak=peak, box=Box, qMask=qMask,
                                                          calc_pp_lambda=True, padeCoefficients=padeCoefficients,
                                                          mindtBinWidth=mindtBinWidth,
+                                                         maxdtBinWidth=maxdtBinWidth,
                                                          pplmin_frac=minpplfrac, pplmax_frac=maxpplfrac,
-                                                         constraintScheme=constraintScheme)
+                                                         constraintScheme=constraintScheme,
+                                                         peakMaskSize=peakMaskSize, iccFitDict=iccFitDict)
                 # --IN PRINCIPLE!!! WE CALCULATE THIS BEFORE GETTING HERE
                 tofWS = mtd['tofWS']
 
                 fitResults, fICC = doICCFit(
-                    tofWS, energy, flightPath, padeCoefficients, fitOrder=bgPolyOrder, constraintScheme=constraintScheme)
+                    tofWS, energy, flightPath, padeCoefficients, fitOrder=bgPolyOrder, constraintScheme=constraintScheme,
+                    iccFitDict=iccFitDict)
                 chiSq = fitResults.OutputChi2overDoF
 
                 r = mtd['fit_Workspace']