diff --git a/Rich/RichMirrorAlignmentOnline/CMakeLists.txt b/Rich/RichMirrorAlignmentOnline/CMakeLists.txt
index e6785b46b68c16e7bd106358c23af2a26adadc0a..26972668e8ba4c114f4320df7211601d62e281d2 100644
--- a/Rich/RichMirrorAlignmentOnline/CMakeLists.txt
+++ b/Rich/RichMirrorAlignmentOnline/CMakeLists.txt
@@ -1,7 +1,7 @@
 ################################################################################
 # Package: RichMirrorAlignmentOnline
 ################################################################################
-gaudi_subdir(RichMirrorAlignmentOnline v3r3)
+gaudi_subdir(RichMirrorAlignmentOnline v3r4)
 
 gaudi_depends_on_subdirs(Online/Gaucho
                          Event/DAQEvent
diff --git a/Rich/RichMirrorAlignmentOnline/cmt/requirements b/Rich/RichMirrorAlignmentOnline/cmt/requirements
index f80efa2185c828ff320a14ce98b0d1b4c1d82eb2..77a096a2b7b86c1d8b224c0b8a4efd4c6e862981 100644
--- a/Rich/RichMirrorAlignmentOnline/cmt/requirements
+++ b/Rich/RichMirrorAlignmentOnline/cmt/requirements
@@ -3,7 +3,7 @@
 # Maintainer : Paras Naik, Claire Prouve
 #============================================================================
 package           RichMirrorAlignmentOnline
-version           v3r3
+version           v3r4
 
 #============================================================================
 # Structure, i.e. directories to process. 
diff --git a/Rich/RichMirrorAlignmentOnline/doc/release.notes b/Rich/RichMirrorAlignmentOnline/doc/release.notes
index 2424b490d5709bf02d641a84a4b173f505799e4e..77d6eb516d7ca8c6802c1b340cb18db735811bed 100644
--- a/Rich/RichMirrorAlignmentOnline/doc/release.notes
+++ b/Rich/RichMirrorAlignmentOnline/doc/release.notes
@@ -10,6 +10,36 @@ Get into the habit of committing on every change (that compiles of course)
 
 ! Improvements since the previous "tagged" release of this code was tagged should be noted here, if any:
 
+! Notes pertaining to already "tagged" releases:
+
+! 2017-07-04 - Paras Naik
+  - "Tagged" as v3r4 (internally, since only Panoptes gets a tag now).
+  - Changed name of AlignSummary.py to AlignMonitor.py
+  - Fixed code to provide monitoring histograms properly if the zeroth iteration is the only iteration.
+  - Added sanity check to prevent the alignment from updating automatically
+     if the changes in the mirror alignment are abnormally large.
+  - Added warningFactor configurable to Configuration.py
+      This configurable determines how many times the tolerance is the level of the sanity check
+      When the magnet polarity changes, this sanity check is currently made looser by a factor of 2 (2 is hard coded!)
+  - Added displayMode configurable to Configuration.py
+      This configurable allows an alternate plotting style for the monitoring to be tried
+  - 2D histograms with mirror numbers are now created
+      They now appear in AlignMonitor.pdf and AlignSummary.pdf 2D Histos
+      They are also sent to the monitoring/Presenter for later use
+  - Per iteration deltaTheta plots now available for experts in AlignSummary.pdf
+  - Added F and M ROOT options to the hist->fit to the deltaTheta plot in AlignMonitor.py
+  - Added monitor function to SetupHelper.py, which now performs the monitoring 
+      separately to the finalize function, and also returns the result of the sanity check.
+  - Added small offset to setTrunc and setDiv to make sure the color in the 2D histograms 
+      is correct if a value is exactly on the boundary.
+  - Now posting an "alignment starting" message to the RICH ELOG, 
+      which gets overwritten by the result if the alignment completes properly.
+  - Junk messages in the hlt02 log file are now removed, and the result is placed 
+      in an "hlt02reduced" log file.
+  - Now sending deltaTheta histograms to the monitoring/Presenter without hist->fit already performed.
+  - Now sending AlignMonitor.pdf and a message to the Alignment Monitoring ELOG.
+  - We now only overwrite the old magnet polarity name storage file if the alignment converges.
+  
 ! 2017-06-20 - Paras Naik
   - "Tagged" as v3r3 (internally, since only Panoptes gets a tag now).
   - Now sending monitoring plots to the Presenter/Monet!
@@ -61,8 +91,6 @@ Get into the habit of committing on every change (that compiles of course)
       This is not ideal, because "System_19" could change to something else if a new RICH System is added in the ELOG.
   - Added workDir to the .conf file writer for RichMirrCombinFit, in RichAlignmentHelper.py
 
-! Notes pertaining to already "tagged" releases:
-
 ! 2017-06-03 - Paras Naik
   - "Tagged" as v3r2 (internally, since only Panoptes gets a tag now).
   - We now make a copy of Rich/RichMirrorAlignmentOnline/python/RichMirrorAlignmentOnlineConfiguration.py every time we run.
diff --git a/Rich/RichMirrorAlignmentOnline/python/PyMirrAlignOnline/AlignSummary.py b/Rich/RichMirrorAlignmentOnline/python/PyMirrAlignOnline/AlignMonitor.py
similarity index 50%
rename from Rich/RichMirrorAlignmentOnline/python/PyMirrAlignOnline/AlignSummary.py
rename to Rich/RichMirrorAlignmentOnline/python/PyMirrAlignOnline/AlignMonitor.py
index d7b778291096152853644ce3917560df7caae27a..0a080ceead2f8eb916b00ba19493cedf3d1989a8 100644
--- a/Rich/RichMirrorAlignmentOnline/python/PyMirrAlignOnline/AlignSummary.py
+++ b/Rich/RichMirrorAlignmentOnline/python/PyMirrAlignOnline/AlignMonitor.py
@@ -1,29 +1,30 @@
 # Authors: Paras Naik, Claire Prouve
 
 import sys, numpy
-from ROOT import TH1D, TCanvas, TFile, TF1, gStyle, TGraph, TMultiGraph, TLine, TH2D
+from ROOT import TH1D, TCanvas, TFile, TF1, gStyle, TGraph, TMultiGraph, TLine, TH2D, TExec
 
-class AlignSummary:
+class AlignMonitor:
     def __init__(self, _alignConf, _maxIt, ):
         self.alignConf = _alignConf
         self.nameStr = self.alignConf.getProp('nameStr')
         self.whichRich = self.alignConf.getProp('Rich')
         self.workdir = self.alignConf.getProp('WorkDir')
+        self.displayMode = self.alignConf.getProp('displayMode')
+        self.warningFactor = self.alignConf.getProp('warningFactor')
         self.maxIt = _maxIt # the maximum labeled number of the iterations that we are looping through
-        self.prename =  "RichRecQCHistos_rich" + str(self.whichRich) + "_" + self.nameStr + "_"
-        self.fitMin = -0.007 # default: RICH1
-        self.fitMax = 0.007 # default: RICH1
-        if (self.whichRich == 2):
-            self.fitMin = -0.0039
-            self.fitMax = 0.0035
-        self.maxpri = 3 # default: RICH1
+        self.prename = "RichRecQCHistos_rich" + str(self.whichRich) + "_" + self.nameStr + "_"
+        # RICH1 settings
+        self.maxpri = 3
         self.binToPriMirr = [[2,3],
                              [0,1]]
-        self.maxsec = 15 # default: RICH1
+        self.maxsec = 15
         self.binToSecMirr = [[10,11,14,15],
                              [8,9,12,13],
                              [2,3,6,7],
                              [0,1,4,5]]
+        self.fitMin = -0.007
+        self.fitMax = 0.007
+        # if RICH2, use RICH2 settings
         if (self.whichRich == 2):
             self.maxpri = 55
             self.binToPriMirr = [[3,2,1,0,31,30,29,28],
@@ -39,10 +40,10 @@ class AlignSummary:
                                  [11,10,9,8,31,30,29,28],
                                  [15,14,13,12,35,34,33,32],
                                  [19,18,17,16,39,38,37,36]]
+            self.fitMin = -0.0039
+            self.fitMax = 0.0035
             
-        # Initialize Monitoring Job "Sender" to send plots to the presenter
-        # The Monitoring Job "Saver" is part of a monitoring script by Giulio Dujany
-        #   This monitoring script is always being run at the pit by the Alignment group
+        # Initialize the Monitoring Job "Sender" to send plots to the presenter
         from Configurables import MonitoringJob
         from Monitoring.MonitoringJob import start
         self.mj = MonitoringJob()
@@ -54,29 +55,38 @@ class AlignSummary:
         self.monitoring_folder = 'MoniOnlineAligRich' + str(self.whichRich)
         print "INFO: monitoring_folder = " + self.monitoring_folder
         sys.stdout.flush()
+        # The Monitoring Job "Saver" is part of a monitoring script by Giulio Dujany (elsewhere)
+        #   That monitoring script is always being run at the pit by the Alignment group
+        self.isInsane = False
     
-    def makeSummaryPlot(self, compareXML):
+    def performMonitoring(self, compareXML, forcedUpdate_ChMagPol):
         import os
         gStyle.SetOptFit(1111)
         gStyle.SetOptStat(000000000)
-                
-        saveName   = self.workdir + 'Rich' + str(self.whichRich) + '_AlignSummary.pdf'
-        saveNameDM = self.workdir + 'Rich' + str(self.whichRich) + '_AlignMonitor.pdf'
+
+        # File for the RICH piquet AND for the RICH mirror alignment experts
+        expertFile  = self.workdir + 'Rich' + str(self.whichRich) + '_AlignSummary.pdf'
+        # File for the Alignment piquet ("duplicating" what goes to the Presenter for the Data Manager)
+        monitorFile  = self.workdir + 'Rich' + str(self.whichRich) + '_AlignMonitor.pdf'
+        # File with for testing purposes
+        testingFile = self.workdir + 'Rich' + str(self.whichRich) + '_AlignTesting.pdf'
+        # Data Manager can only get histograms sent via self.monSvc
         
-        cPlot = TCanvas('cPlot', 'AlignExpert')
-        cPlot.Divide(2,2,0.001,0.001)
+        theCanvas = TCanvas('theCanvas', 'MirrAlign')
+        theCanvas.Divide(2,2,0.001,0.001)
         
-        dPlot = TCanvas('dPlot', 'AlignDM')
-        dPlot.Divide(2,2,0.001,0.001)
+        theCanvas2 = TCanvas('theCanvas2', 'MirrAlignTest')
+        theCanvas2.Divide(2,2,0.001,0.001)
 
+######### Start of 2D histos section
         # heatHistos
         from tiltObj import tiltObj
         mirrtilts = []
-        for its in range(0, self.maxIt + 1):
-            XMLFile = self.workdir + 'Rich' + str(self.whichRich) + 'CondDBUpdate_' + self.nameStr + '_i' + str(its + 1) + '.xml' 
+        for n_it in range(0, self.maxIt + 1):
+            XMLFile = self.workdir + 'Rich' + str(self.whichRich) + 'CondDBUpdate_' + self.nameStr + '_i' + str(n_it + 1) + '.xml' 
             mirrtilts.append( tiltObj(self.alignConf) )
             # fills mirrtilts with the exact change in mirror compensation from compareXML to XMLFile
-            mirrtilts[its].setChange([compareXML, XMLFile])
+            mirrtilts[n_it].setChange([compareXML, XMLFile])
         mgraphs = mirrtilts[self.maxIt].getGraphs()
         
         if (self.whichRich == 1):
@@ -84,11 +94,16 @@ class AlignSummary:
             heatHistoPriZ = TH2D('heatHistoPriZ', 'RICH' + str(self.whichRich) + ' Primary mirrors local Z rotation (mrad)', 2, -1, 1, 2, -1, 1)
             heatHistoSecY = TH2D('heatHistoSecY', 'RICH' + str(self.whichRich) + ' Secondary mirrors local Y rotation (mrad)', 4, -1, 1, 4, -1, 1)
             heatHistoSecZ = TH2D('heatHistoSecZ', 'RICH' + str(self.whichRich) + ' Secondary mirrors local Z rotation (mrad)', 4, -1, 1, 4, -1, 1)
+            numbersHistoPri = TH2D('numbersHistoPri', 'RICH' + str(self.whichRich) + ' Primary mirror numbers', 2, -1, 1, 2, -1, 1)
+            numbersHistoSec = TH2D('numbersHistoSec', 'RICH' + str(self.whichRich) + ' Secondary mirror numbers', 4, -1, 1, 4, -1, 1)
+            
         if (self.whichRich == 2):
             heatHistoPriY = TH2D('heatHistoPriY', 'RICH' + str(self.whichRich) + ' Primary mirrors local Y rotation (mrad)', 8, -1, 1, 7, -1, 1)
             heatHistoPriZ = TH2D('heatHistoPriZ', 'RICH' + str(self.whichRich) + ' Primary mirrors local Z rotation (mrad)', 8, -1, 1, 7, -1, 1)
             heatHistoSecY = TH2D('heatHistoSecY', 'RICH' + str(self.whichRich) + ' Secondary mirrors local Y rotation (mrad)', 8, -1, 1, 5, -1, 1)
             heatHistoSecZ = TH2D('heatHistoSecZ', 'RICH' + str(self.whichRich) + ' Secondary mirrors local Z rotation (mrad)', 8, -1, 1, 5, -1, 1)        
+            numbersHistoPri = TH2D('numbersHistoPri', 'RICH' + str(self.whichRich) + ' Primary mirror numbers', 8, -1, 1, 7, -1, 1)
+            numbersHistoSec = TH2D('numbersHistoSec', 'RICH' + str(self.whichRich) + ' Secondary mirror numbers', 8, -1, 1, 5, -1, 1)
         
         xTitle = 'relative global X position (not to scale)'
         yTitle = 'relative global Y position (not to scale)'
@@ -99,18 +114,18 @@ class AlignSummary:
         heatHistoPriZ.SetXTitle(xTitle)
         heatHistoPriZ.SetYTitle(yTitle)     
         heatHistoSecZ.SetXTitle(xTitle) 
-        heatHistoSecZ.SetYTitle(yTitle) 
-
-        heatHistoPriY.SetMarkerSize(2.0*heatHistoPriY.GetMarkerSize())
-        heatHistoPriZ.SetMarkerSize(2.0*heatHistoPriZ.GetMarkerSize())
-        heatHistoSecY.SetMarkerSize(2.0*heatHistoSecY.GetMarkerSize())
-        heatHistoSecZ.SetMarkerSize(2.0*heatHistoSecZ.GetMarkerSize())
-
-        # Color scheme before 2017 June 19
-        #self.colorsLow  = [923,921,0,390,622,624,627,631,636,635,634,633,632,807,797,800,400,416]
-        #self.colorsHigh = [416,432,867,857,600,616,617,618,619,620,615,611,608,606,590,920,922,1]
+        heatHistoSecZ.SetYTitle(yTitle)
+        numbersHistoPri.SetXTitle(xTitle)
+        numbersHistoPri.SetYTitle(yTitle)
+        numbersHistoSec.SetXTitle(xTitle)
+        numbersHistoSec.SetYTitle(yTitle)
+        
+        self.origMarkerSize = heatHistoPriY.GetMarkerSize() # default MarkerSize should be same for all histos
 
-        # Improved Color scheme
+        # Flexible Range Color scheme before 2017 June 19
+        #   self.colorsLow  = [923,921,0,390,622,624,627,631,636,635,634,633,632,807,797,800,400,416]
+        #   self.colorsHigh = [416,432,867,857,600,616,617,618,619,620,615,611,608,606,590,920,922,1]
+        # Flexible Range Improved Color scheme after 2017 June 19
         # 634 = kRed + 2
         # 632 = kRed
         # 797 = kOrange - 3
@@ -124,185 +139,258 @@ class AlignSummary:
         self.colorsLow  += [602,602,602,602,602,602,602,602,602,602,602,602,602,602,600,857,867,416]
         self.colorsHigh  = [416,400,797,632,634,634,634,634,634,634,634,634,634,634,634,634,634,634]
         self.colorsHigh += [634,634,634,634,634,634,634,634,634,634,634,634,634,634,634,634,634,634]
-        
-        colorsList = self.colorsLow + self.colorsHigh
-               
+        colorsListFlex = self.colorsLow + self.colorsHigh
+######### Fixed Range Color scheme 
+        if self.displayMode == 0: 
+            # Anatoly, define your color palette here, or use this if you agree with it, 
+            #   then there are places for you to set your style below.
+            colorsListFixed = [602,600,857,867,416,416,400,797,632,634] 
+#########
+
+        # We need to get a mechanism to get the stopTolerances used if stopToleranceMode is 0
+        # The best option, for consistency, is to calculate them in 
+        #    RichMirrCombinFit and/or RichMirrAlign, then print them to a file and
+        #    pick them up in RichMirrAlign and/or RichMirrorAlignmentOnline (via setProp).
+        # For now, we just use the stopTolerances from the Configuration in all cases.
         self.sTPY = float(self.alignConf.getProp('stopTolerancePriY'))
         self.sTPZ = float(self.alignConf.getProp('stopTolerancePriZ'))
         self.sTSY = float(self.alignConf.getProp('stopToleranceSecY'))
         self.sTSZ = float(self.alignConf.getProp('stopToleranceSecZ'))
-
         biggestTilt = [None] * (self.maxIt + 1)
 
-        for its in reversed(range(0, self.maxIt + 1)):
-            heatHistoPriY.SetTitle('#splitline{RICH' + str(self.whichRich) + ' Primary mirrors local Y rotation (mrad) after It. ' + str(its) + '}{Values truncated, not rounded}' )
-            heatHistoPriZ.SetTitle('#splitline{RICH' + str(self.whichRich) + ' Primary mirrors local Z rotation (mrad) after It. ' + str(its) + '}{Values truncated, not rounded}' )
-            heatHistoSecY.SetTitle('#splitline{RICH' + str(self.whichRich) + ' Secondary mirrors local Y rotation (mrad) after It. ' + str(its) + '}{Values truncated, not rounded}' )
-            heatHistoSecZ.SetTitle('#splitline{RICH' + str(self.whichRich) + ' Secondary mirrors local Z rotation (mrad) after It. ' + str(its) + '}{Values truncated, not rounded}' )
-            
+        for n_it in reversed(range(0, self.maxIt + 1)):
+        # Compensations Histograms           
             # sets priYtrunc, etc... otherwise these will be empty
-            mirrtilts[its].setTrunc()
+            mirrtilts[n_it].setTrunc(digits = 2)
             
             rowsPri = len(self.binToPriMirr)
             colsPri = len(self.binToPriMirr[0])
             for row in xrange(rowsPri):
                 for col in xrange(colsPri):
                     #truncated, not rounded
-                    heatHistoPriY.SetBinContent(col+1, row+1, mirrtilts[its].priYtrunc[self.binToPriMirr[row][col]]) 
-                    heatHistoPriZ.SetBinContent(col+1, row+1, mirrtilts[its].priZtrunc[self.binToPriMirr[row][col]])
+                    heatHistoPriY.SetBinContent(col+1, row+1, mirrtilts[n_it].priYtrunc[self.binToPriMirr[row][col]]) 
+                    heatHistoPriZ.SetBinContent(col+1, row+1, mirrtilts[n_it].priZtrunc[self.binToPriMirr[row][col]])
+                    numbersHistoPri.SetBinContent(col+1, row+1, self.binToPriMirr[row][col] if self.binToPriMirr[row][col] != 0 else 0.0000001)
     
             rowsSec = len(self.binToSecMirr)
             colsSec = len(self.binToSecMirr[0])
             for row in xrange(rowsSec):
                 for col in xrange(colsSec):
                     #truncated, not rounded
-                    heatHistoSecY.SetBinContent(col+1, row+1, mirrtilts[its].secYtrunc[self.binToSecMirr[row][col]])
-                    heatHistoSecZ.SetBinContent(col+1, row+1, mirrtilts[its].secZtrunc[self.binToSecMirr[row][col]])
+                    heatHistoSecY.SetBinContent(col+1, row+1, mirrtilts[n_it].secYtrunc[self.binToSecMirr[row][col]])
+                    heatHistoSecZ.SetBinContent(col+1, row+1, mirrtilts[n_it].secZtrunc[self.binToSecMirr[row][col]])
+                    numbersHistoSec.SetBinContent(col+1, row+1, self.binToSecMirr[row][col] if self.binToSecMirr[row][col] != 0 else 0.0000001)
 
-            # Get the maximum tilt in any plot, this lets us set the scales only as relevant, 
+            # Get the absolute value of the maximum tilt in any plot, 
+            #   this lets us set the scales only as relevant, 
             #   and in a controlled manner across all possible mirrors and tilts.    
-            biggestTilt[its] = mirrtilts[its].getAbsMax() 
-                     
-            if int(self.alignConf.getProp('stopToleranceMode')) == 1:
-                for n in reversed(range(0,35)):
-                    if biggestTilt[its][0] > n*self.sTPY or biggestTilt[its][1] > n*self.sTPZ or biggestTilt[its][2] > n*self.sTSY or biggestTilt[its][3] > n*self.sTSZ:
-                        break
-                heatHistoPriY.GetZaxis().SetRangeUser((n+2)*(0-self.sTPY), (n+2)*(self.sTPY))
-                heatHistoPriZ.GetZaxis().SetRangeUser((n+2)*(0-self.sTPZ), (n+2)*(self.sTPZ))
-                heatHistoSecY.GetZaxis().SetRangeUser((n+2)*(0-self.sTSY), (n+2)*(self.sTSY))
-                heatHistoSecZ.GetZaxis().SetRangeUser((n+2)*(0-self.sTSZ), (n+2)*(self.sTSZ))
-                colorsLowClone = list(self.colorsLow)
-                colorsLowClone.reverse()
-                colorsLowSubset = list(colorsLowClone[0:n+2])
-                colorsLowSubset.reverse()
-                colorsList = list(colorsLowSubset + self.colorsHigh[0:n+2])
-                levelsPY = []
-                levelsPZ = []
-                levelsSY = []
-                levelsSZ = []             
-                for i in range(-(n+2),(n+2)+1):
-                    levelsPY += [i*self.sTPY]
-                    levelsPZ += [i*self.sTPZ]
-                    levelsSY += [i*self.sTSY]
-                    levelsSZ += [i*self.sTSZ]
-            else:
-                 # for now this is OK, however it is wrong to rely on the values of the stop tolerances in the configuration file, since those are not actually being used
-                heatHistoPriY.GetZaxis().SetRangeUser(-36*self.sTPY, 36*self.sTPY) # Eventually we will have to extract these tolerances from RichMirrAlign
-                heatHistoPriZ.GetZaxis().SetRangeUser(-36*self.sTPZ, 36*self.sTPZ) # Eventually we will have to extract these tolerances from RichMirrAlign
-                heatHistoSecY.GetZaxis().SetRangeUser(-36*self.sTSY, 36*self.sTSY) # Eventually we will have to extract these tolerances from RichMirrAlign
-                heatHistoSecZ.GetZaxis().SetRangeUser(-36*self.sTSZ, 36*self.sTSZ) # Eventually we will have to extract these tolerances from RichMirrAlign
-                levelsPY = []
-                levelsPZ = []
-                levelsSY = []
-                levelsSZ = []         
-                for i in range(-(36),(36)+1):
-                    levelsPY += [i*self.sTPY]
-                    levelsPZ += [i*self.sTPZ]
-                    levelsSY += [i*self.sTSY]
-                    levelsSZ += [i*self.sTSZ]  
-
-            gStyle.SetPalette(len(list(colorsList)), numpy.array(list(colorsList), dtype = 'intc'))
+            biggestTilt[n_it] = mirrtilts[n_it].getAbsMax() 
             
+            # sanity check
+            if n_it == self.maxIt:
+                if not forcedUpdate_ChMagPol:
+                    crazy = self.warningFactor 
+                else:
+                    expandCrazyFactor = 2 # The choice of expandCrazyFactor is completely arbitrary, and should be re-evaluated later.
+                    crazy = expandCrazyFactor*self.warningFactor 
+                if biggestTilt[n_it][0] >= crazy*self.sTPY or biggestTilt[n_it][1] >= crazy*self.sTPZ or biggestTilt[n_it][2] >= crazy*self.sTSY or biggestTilt[n_it][3] >= crazy*self.sTSZ:
+                    self.isInsane = True
+                        
+            # Flexible range plotting style
+            for self.nFlex in reversed(range(0,35)):
+                if biggestTilt[n_it][0] >= self.nFlex*self.sTPY or biggestTilt[n_it][1] >= self.nFlex*self.sTPZ or biggestTilt[n_it][2] >= self.nFlex*self.sTSY or biggestTilt[n_it][3] >= self.nFlex*self.sTSZ:
+                    break
+            # max: heatHistoPriY.GetZaxis().SetRangeUser(-36*self.sTPY, 36*self.sTPY)
+            heatHistoPriY.GetZaxis().SetRangeUser((self.nFlex+2)*(0-self.sTPY), (self.nFlex+2)*(self.sTPY))
+            heatHistoPriZ.GetZaxis().SetRangeUser((self.nFlex+2)*(0-self.sTPZ), (self.nFlex+2)*(self.sTPZ))
+            heatHistoSecY.GetZaxis().SetRangeUser((self.nFlex+2)*(0-self.sTSY), (self.nFlex+2)*(self.sTSY))
+            heatHistoSecZ.GetZaxis().SetRangeUser((self.nFlex+2)*(0-self.sTSZ), (self.nFlex+2)*(self.sTSZ))
+            colorsLowClone = list(self.colorsLow)
+            colorsLowClone.reverse()
+            colorsLowSubset = list(colorsLowClone[0:self.nFlex+2])
+            colorsLowSubset.reverse()
+            colorsListFlex = list(colorsLowSubset + self.colorsHigh[0:self.nFlex+2])
+            levelsPY = []
+            levelsPZ = []
+            levelsSY = []
+            levelsSZ = []
+            # max: for i in range(-(36),(36)+1):
+            for i in range(-(self.nFlex+2),(self.nFlex+2)+1):
+                levelsPY += [i*self.sTPY]
+                levelsPZ += [i*self.sTPZ]
+                levelsSY += [i*self.sTSY]
+                levelsSZ += [i*self.sTSZ]
+            gStyle.SetPalette(len(list(colorsListFlex)), numpy.array(list(colorsListFlex), dtype = 'intc'))
             heatHistoPriY.SetContour(len(list(levelsPY)), numpy.array(list(levelsPY), dtype = 'float64'))
             heatHistoPriZ.SetContour(len(list(levelsPZ)), numpy.array(list(levelsPZ), dtype = 'float64'))
             heatHistoSecY.SetContour(len(list(levelsSY)), numpy.array(list(levelsSY), dtype = 'float64'))
             heatHistoSecZ.SetContour(len(list(levelsSZ)), numpy.array(list(levelsSZ), dtype = 'float64'))
+            heatHistoPriY.SetMarkerSize(1.8*self.origMarkerSize)
+            heatHistoPriZ.SetMarkerSize(1.8*self.origMarkerSize)
+            heatHistoSecY.SetMarkerSize(1.8*self.origMarkerSize)
+            heatHistoSecZ.SetMarkerSize(1.8*self.origMarkerSize)
+            numbersHistoPri.SetMarkerSize(1.2*self.origMarkerSize)
+            numbersHistoSec.SetMarkerSize(1.2*self.origMarkerSize)
+            heatHistoPriY.SetBarOffset(-0.175)
+            heatHistoPriZ.SetBarOffset(-0.175)
+            heatHistoSecY.SetBarOffset(-0.175)
+            heatHistoSecZ.SetBarOffset(-0.175)
+            numbersHistoPri.SetBarOffset(0.175)
+            numbersHistoSec.SetBarOffset(0.175)
+            heatHistoPriY.SetTitle('#splitline{RICH' + str(self.whichRich) + ' Primary mirrors local Y rotation (mrad) after It. ' + str(n_it) + '}{Values truncated, not rounded. Mirror number displayed smaller.}' )
+            heatHistoPriZ.SetTitle('#splitline{RICH' + str(self.whichRich) + ' Primary mirrors local Z rotation (mrad) after It. ' + str(n_it) + '}{Values truncated, not rounded. Mirror number displayed smaller.}' )
+            heatHistoSecY.SetTitle('#splitline{RICH' + str(self.whichRich) + ' Secondary mirrors local Y rotation (mrad) after It. ' + str(n_it) + '}{Values truncated, not rounded. Mirror number displayed smaller.}' )
+            heatHistoSecZ.SetTitle('#splitline{RICH' + str(self.whichRich) + ' Secondary mirrors local Z rotation (mrad) after It. ' + str(n_it) + '}{Values truncated, not rounded. Mirror number displayed smaller.}' )
+            # we need TExec in order to have multiple text formats drawn on the same TPad
+            execStyle1 = TExec("execStyle1","gStyle->SetPaintTextFormat(\"4.2f\");")  # formerly 5.3f
+            execStyle2 = TExec("execStyle2","gStyle->SetPaintTextFormat(\"2.0f\");")
 
-            gStyle.SetPaintTextFormat('4.2f') # formerly 5.3f
-
-            cPlot.cd(1)
+            theCanvas.cd(1)
             heatHistoPriY.Draw("COLZ")
+            execStyle1.Draw()
             heatHistoPriY.Draw("TEXT SAME")
-            cPlot.cd(2)
+            theCanvas.cd(2)
             heatHistoPriZ.Draw("COLZ")
+            execStyle1.Draw()
             heatHistoPriZ.Draw("TEXT SAME")
-            cPlot.cd(3)
+            theCanvas.cd(3)
             heatHistoSecY.Draw("COLZ")
+            execStyle1.Draw()
             heatHistoSecY.Draw("TEXT SAME")
-            cPlot.cd(4)
+            theCanvas.cd(4)
             heatHistoSecZ.Draw("COLZ")
+            execStyle1.Draw()
             heatHistoSecZ.Draw("TEXT SAME")
-            cPlot.Print(saveName + '(')
 
-            #dPlot 
+            theCanvas.cd(1)
+            execStyle2.Draw()
+            numbersHistoPri.Draw("TEXT SAME")
+            theCanvas.cd(2)
+            execStyle2.Draw()
+            numbersHistoPri.Draw("TEXT SAME")
+            theCanvas.cd(3)
+            execStyle2.Draw()
+            numbersHistoSec.Draw("TEXT SAME")
+            theCanvas.cd(4)
+            execStyle2.Draw()
+            numbersHistoSec.Draw("TEXT SAME")
             
-            heatHistoPriY.SetTitle('#splitline{RICH' + str(self.whichRich) + ' Primary mirrors local Y rotation divided by tolerance, after It. ' + str(its) + '}{Values truncated, not rounded}' )
-            heatHistoPriZ.SetTitle('#splitline{RICH' + str(self.whichRich) + ' Primary mirrors local Z rotation divided by tolerance, after It. ' + str(its) + '}{Values truncated, not rounded}' )
-            heatHistoSecY.SetTitle('#splitline{RICH' + str(self.whichRich) + ' Secondary mirrors local Y rotation divided by tolerance, after It. ' + str(its) + '}{Values truncated, not rounded}' )
-            heatHistoSecZ.SetTitle('#splitline{RICH' + str(self.whichRich) + ' Secondary mirrors local Z rotation divided by tolerance, after It. ' + str(its) + '}{Values truncated, not rounded}' )
+            theCanvas.Print(expertFile + '(')
+            
+############# Fixed range plotting style (testing)
+            if self.displayMode == 0: 
+                # Anatoly, change the plotting styles here only (but define colorsListFixed above)
+                # If you do not need to change a particular style setting then leave it out
+                #   and it will use the default from just above.
+                pass
+            
+                # Print to testing file
+                gStyle.SetPaintTextFormat('4.2f') # formerly 5.3f
+                theCanvas2.cd(1)
+                heatHistoPriY.Draw("COLZ")
+                heatHistoPriY.Draw("TEXT SAME")
+                theCanvas2.cd(2)
+                heatHistoPriZ.Draw("COLZ")
+                heatHistoPriZ.Draw("TEXT SAME")
+                theCanvas2.cd(3)
+                heatHistoSecY.Draw("COLZ")
+                heatHistoSecY.Draw("TEXT SAME")
+                theCanvas2.cd(4)
+                heatHistoSecZ.Draw("COLZ")
+                heatHistoSecZ.Draw("TEXT SAME")
+                gStyle.SetPaintTextFormat('2.0f')
+                theCanvas2.cd(1)
+                numbersHistoPri.Draw("TEXT SAME")
+                theCanvas2.cd(2)
+                numbersHistoPri.Draw("TEXT SAME")
+                theCanvas2.cd(3)
+                numbersHistoSec.Draw("TEXT SAME")
+                theCanvas2.cd(4)
+                numbersHistoSec.Draw("TEXT SAME")
+                
+                theCanvas2.Print(testingFile + '(')
+#############
 
+        # Compensations-divided-by-tolerances Histograms
             # sets priYdiv, etc... otherwise these will be empty            
-            mirrtilts[its].setDiv(tolerances = [self.sTPY,self.sTPZ,self.sTSY,self.sTSZ])
+            mirrtilts[n_it].setDiv(tolerances = [self.sTPY,self.sTPZ,self.sTSY,self.sTSZ])
             
             rowsPri = len(self.binToPriMirr)
             colsPri = len(self.binToPriMirr[0])
             for row in xrange(rowsPri):
                 for col in xrange(colsPri):
                     #truncated, not rounded
-                    heatHistoPriY.SetBinContent(col+1, row+1, mirrtilts[its].priYdiv[self.binToPriMirr[row][col]]) 
-                    heatHistoPriZ.SetBinContent(col+1, row+1, mirrtilts[its].priZdiv[self.binToPriMirr[row][col]])
+                    heatHistoPriY.SetBinContent(col+1, row+1, mirrtilts[n_it].priYdiv[self.binToPriMirr[row][col]]) 
+                    heatHistoPriZ.SetBinContent(col+1, row+1, mirrtilts[n_it].priZdiv[self.binToPriMirr[row][col]])
     
             rowsSec = len(self.binToSecMirr)
             colsSec = len(self.binToSecMirr[0])
             for row in xrange(rowsSec):
                 for col in xrange(colsSec):
                     #truncated, not rounded
-                    heatHistoSecY.SetBinContent(col+1, row+1, mirrtilts[its].secYdiv[self.binToSecMirr[row][col]])
-                    heatHistoSecZ.SetBinContent(col+1, row+1, mirrtilts[its].secZdiv[self.binToSecMirr[row][col]])
-
-            if int(self.alignConf.getProp('stopToleranceMode')) == 1:
-                # steal n from previous loop, the palette is also already set.
-                heatHistoPriY.GetZaxis().SetRangeUser((n+2)*(0-1), (n+2)*(1))
-                heatHistoPriZ.GetZaxis().SetRangeUser((n+2)*(0-1), (n+2)*(1))
-                heatHistoSecY.GetZaxis().SetRangeUser((n+2)*(0-1), (n+2)*(1))
-                heatHistoSecZ.GetZaxis().SetRangeUser((n+2)*(0-1), (n+2)*(1))
-                levelsPY = []
-                levelsPZ = []
-                levelsSY = []
-                levelsSZ = []              
-                for i in range(-(n+2),(n+2)+1):
-                    levelsPY += [i*1]
-                    levelsPZ += [i*1]
-                    levelsSY += [i*1]
-                    levelsSZ += [i*1]
-            else:
-                 # for now this is OK, however it is wrong to rely on the values of the stop tolerances in the configuration file, since those are not actually being used
-                heatHistoPriY.GetZaxis().SetRangeUser(-36*1, 36*1) # Eventually we will have to extract these tolerances from RichMirrAlign
-                heatHistoPriZ.GetZaxis().SetRangeUser(-36*1, 36*1) # Eventually we will have to extract these tolerances from RichMirrAlign
-                heatHistoSecY.GetZaxis().SetRangeUser(-36*1, 36*1) # Eventually we will have to extract these tolerances from RichMirrAlign
-                heatHistoSecZ.GetZaxis().SetRangeUser(-36*1, 36*1) # Eventually we will have to extract these tolerances from RichMirrAlign
-                levelsPY = []
-                levelsPZ = []
-                levelsSY = []
-                levelsSZ = []    
-                for i in range(-(36),(36)+1):
-                    levelsPY += [i*1]
-                    levelsPZ += [i*1]
-                    levelsSY += [i*1]
-                    levelsSZ += [i*1]
+                    heatHistoSecY.SetBinContent(col+1, row+1, mirrtilts[n_it].secYdiv[self.binToSecMirr[row][col]])
+                    heatHistoSecZ.SetBinContent(col+1, row+1, mirrtilts[n_it].secZdiv[self.binToSecMirr[row][col]])
 
+            # Flexible range plotting style
+            # self.nFlex should be unchanged from previous determination.
+            # max: heatHistoPriY.GetZaxis().SetRangeUser(-36*1, 36*1)
+            heatHistoPriY.GetZaxis().SetRangeUser((self.nFlex+2)*(0-1), (self.nFlex+2)*(1))
+            heatHistoPriZ.GetZaxis().SetRangeUser((self.nFlex+2)*(0-1), (self.nFlex+2)*(1))
+            heatHistoSecY.GetZaxis().SetRangeUser((self.nFlex+2)*(0-1), (self.nFlex+2)*(1))
+            heatHistoSecZ.GetZaxis().SetRangeUser((self.nFlex+2)*(0-1), (self.nFlex+2)*(1))
+            levelsPY = []
+            levelsPZ = []
+            levelsSY = []
+            levelsSZ = []           
+            #max: for i in range(-(36),(36)+1):
+            for i in range(-(self.nFlex+2),(self.nFlex+2)+1):
+                levelsPY += [i*1]
+                levelsPZ += [i*1]
+                levelsSY += [i*1]
+                levelsSZ += [i*1]
+            gStyle.SetPalette(len(list(colorsListFlex)), numpy.array(list(colorsListFlex), dtype = 'intc'))
             heatHistoPriY.SetContour(len(list(levelsPY)), numpy.array(list(levelsPY), dtype = 'float64'))
             heatHistoPriZ.SetContour(len(list(levelsPZ)), numpy.array(list(levelsPZ), dtype = 'float64'))
             heatHistoSecY.SetContour(len(list(levelsSY)), numpy.array(list(levelsSY), dtype = 'float64'))
-            heatHistoSecZ.SetContour(len(list(levelsSZ)), numpy.array(list(levelsSZ), dtype = 'float64'))
-            
+            heatHistoSecZ.SetContour(len(list(levelsSZ)), numpy.array(list(levelsSZ), dtype = 'float64'))        
+            heatHistoPriY.SetMarkerSize(1.8*self.origMarkerSize)
+            heatHistoPriZ.SetMarkerSize(1.8*self.origMarkerSize)
+            heatHistoSecY.SetMarkerSize(1.8*self.origMarkerSize)
+            heatHistoSecZ.SetMarkerSize(1.8*self.origMarkerSize)
+            numbersHistoPri.SetMarkerSize(1.2*self.origMarkerSize)
+            numbersHistoSec.SetMarkerSize(1.2*self.origMarkerSize)
+            heatHistoPriY.SetBarOffset(-0.175)
+            heatHistoPriZ.SetBarOffset(-0.175)
+            heatHistoSecY.SetBarOffset(-0.175)
+            heatHistoSecZ.SetBarOffset(-0.175)
+            numbersHistoPri.SetBarOffset(0.175)
+            numbersHistoSec.SetBarOffset(0.175)
+            heatHistoPriY.SetTitle('#splitline{RICH' + str(self.whichRich) + ' Primary mirrors local Y rotation divided by tolerance, after It. ' + str(n_it) + '}{Values truncated, not rounded. Mirror number displayed smaller.}' )
+            heatHistoPriZ.SetTitle('#splitline{RICH' + str(self.whichRich) + ' Primary mirrors local Z rotation divided by tolerance, after It. ' + str(n_it) + '}{Values truncated, not rounded. Mirror number displayed smaller.}' )
+            heatHistoSecY.SetTitle('#splitline{RICH' + str(self.whichRich) + ' Secondary mirrors local Y rotation divided by tolerance, after It. ' + str(n_it) + '}{Values truncated, not rounded. Mirror number displayed smaller.}' )
+            heatHistoSecZ.SetTitle('#splitline{RICH' + str(self.whichRich) + ' Secondary mirrors local Z rotation divided by tolerance, after It. ' + str(n_it) + '}{Values truncated, not rounded. Mirror number displayed smaller.}' )
+
             gStyle.SetPaintTextFormat('2.0f')
-            
-            dPlot.cd(1)
+            theCanvas.cd(1)
             heatHistoPriY.Draw("COLZ")
             heatHistoPriY.Draw("TEXT SAME")
-            dPlot.cd(2)
+            numbersHistoPri.Draw("TEXT SAME")
+            theCanvas.cd(2)
             heatHistoPriZ.Draw("COLZ")
             heatHistoPriZ.Draw("TEXT SAME")
-            dPlot.cd(3)
+            numbersHistoPri.Draw("TEXT SAME")
+            theCanvas.cd(3)
             heatHistoSecY.Draw("COLZ")
             heatHistoSecY.Draw("TEXT SAME")
-            dPlot.cd(4)
+            numbersHistoSec.Draw("TEXT SAME")
+            theCanvas.cd(4)
             heatHistoSecZ.Draw("COLZ")
             heatHistoSecZ.Draw("TEXT SAME")
-            dPlot.Print(saveNameDM + '(')
+            numbersHistoSec.Draw("TEXT SAME")
             
-            if its == self.maxIt:
+            theCanvas.Print(monitorFile + '(')
+
+            if n_it == self.maxIt:
                 self.monSvc.publishHistogram(self.monitoring_folder, heatHistoPriY.Clone(), add=False)
                 print "INFO: heatHistoPriY sent to Monitoring."
                 self.monSvc.publishHistogram(self.monitoring_folder, heatHistoPriZ.Clone(), add=False)
@@ -311,29 +399,70 @@ class AlignSummary:
                 print "INFO: heatHistoSecY sent to Monitoring."
                 self.monSvc.publishHistogram(self.monitoring_folder, heatHistoSecZ.Clone(), add=False)
                 print "INFO: heatHistoSecZ sent to Monitoring."
+                
+                self.monSvc.publishHistogram(self.monitoring_folder, numbersHistoPri.Clone("numbersHistoPriY"), add=False)
+                print "INFO: numbersHistoPriY sent to Monitoring."
+                self.monSvc.publishHistogram(self.monitoring_folder, numbersHistoPri.Clone("numbersHistoPriZ"), add=False)
+                print "INFO: numbersHistoPriZ sent to Monitoring."
+                self.monSvc.publishHistogram(self.monitoring_folder, numbersHistoSec.Clone("numbersHistoSecY"), add=False)
+                print "INFO: numbersHistoSecY sent to Monitoring."
+                self.monSvc.publishHistogram(self.monitoring_folder, numbersHistoSec.Clone("numbersHistoSecZ"), add=False)
+                print "INFO: numbersHistoSecZ sent to Monitoring."
+                
                 sys.stdout.flush()
 
-        # resHistograms           
-        dPlot.Clear()
-        cPlot.Clear()
+############# Fixed range plotting style (testing)
+            if self.displayMode == 0: 
+                # Anatoly, change the plotting styles here only (but define colorsListFixed above)
+                # If you do not need to change a particular style setting then leave it out
+                #   and it will use the default from just above.
+                pass
+            
+                # Print to testing file
+                theCanvas2.cd(1)
+                heatHistoPriY.Draw("COLZ")
+                heatHistoPriY.Draw("TEXT SAME")
+                numbersHistoPri.Draw("TEXT SAME")
+                theCanvas2.cd(2)
+                heatHistoPriZ.Draw("COLZ")
+                heatHistoPriZ.Draw("TEXT SAME")
+                numbersHistoPri.Draw("TEXT SAME")
+                theCanvas2.cd(3)
+                heatHistoSecY.Draw("COLZ")
+                heatHistoSecY.Draw("TEXT SAME")
+                numbersHistoSec.Draw("TEXT SAME")
+                theCanvas2.cd(4)
+                heatHistoSecZ.Draw("COLZ")
+                heatHistoSecZ.Draw("TEXT SAME")
+                numbersHistoSec.Draw("TEXT SAME")
+                
+                theCanvas2.Print(testingFile + ')')
+#############
+
+        # End of 2D histos section #############
+
+        theCanvas2.Clear()
+        theCanvas.Clear()
+        
+        # generate resHistograms           
         
         if self.maxIt == 0:
             pass
         elif self.maxIt < 2:
-            cPlot.Divide(2,1,0.0025,0.0025)
+            theCanvas.Divide(2,1,0.0025,0.0025)
         elif self.maxIt < 3:
-            cPlot.Divide(3,1,0.0025,0.0025)       
+            theCanvas.Divide(3,1,0.0025,0.0025)       
         elif self.maxIt < 4:
-            cPlot.Divide(2,2,0.0025,0.0025)    
+            theCanvas.Divide(2,2,0.0025,0.0025)    
         elif self.maxIt < 6:
-            cPlot.Divide(3,2,0.0025,0.0025)     
+            theCanvas.Divide(3,2,0.0025,0.0025)     
         elif self.maxIt < 8:
-            cPlot.Divide(4,2,0.0025,0.0025)  
+            theCanvas.Divide(4,2,0.0025,0.0025)  
         elif self.maxIt < 9:
-            cPlot.Divide(3,3,0.0025,0.0025)
+            theCanvas.Divide(3,3,0.0025,0.0025)
         else:
-            cPlot.Divide(4,4,0.0025,0.0025)
-            
+            theCanvas.Divide(4,4,0.0025,0.0025)
+                    
         # reserve spaces for resHistograms      
         resHistograms = [None] * (self.maxIt + 1) 
         polbkg = [None] * (self.maxIt + 1)
@@ -351,24 +480,32 @@ class AlignSummary:
             filename[j] = self.workdir + '/' + self.prename + 'i' +  str(j) + '.root'
             if os.path.exists(filename[j]):    
                 thisFile[j] = TFile(filename[j], 'read')
-                hist[j] = (thisFile[j].Get('RICH/RiCKResLongTightMirror/Rich' + str(self.whichRich) + 'Gas/ckResAll')).Clone()
+                hist[j] = (thisFile[j].Get('RICH/RiCKResLongTightMirror/Rich' + str(self.whichRich) + 'Gas/ckResAll')).Clone()  
+
+                if (j == 0) and (j == self.maxIt) :
+                    hist[j].SetName('resHisto0')
+                    self.monSvc.publishHistogram(self.monitoring_folder, hist[j].Clone(), add=False)
+                    print "INFO: resHisto0 sent to Monitoring."  
+                    hist[j].SetName('resHistoN')
+                    self.monSvc.publishHistogram(self.monitoring_folder, hist[j].Clone(), add=False)
+                    print "INFO: resHistoN sent to Monitoring."                  
+                elif (j == self.maxIt):
+                    hist[j].SetName('resHistoN')
+                    self.monSvc.publishHistogram(self.monitoring_folder, hist[j].Clone(), add=False)
+                    print "INFO: resHistoN sent to Monitoring."
+                elif (j == 0):
+                    hist[j].SetName('resHisto0')
+                    self.monSvc.publishHistogram(self.monitoring_folder, hist[j].Clone(), add=False)
+                    print "INFO: resHisto0 sent to Monitoring." 
+                if (j != 0):     
+                    hist[j].SetName('resHisto'+str(j))
+
                 fitRes[j] = self.fitCherenkovAngle(hist[j])
                 resHistograms[j] = fitRes[j][0]       
                 resHistoTrend.SetBinContent(j+1, fitRes[j][1] * 1000)
-                resHistoTrend.SetBinError(j+1, fitRes[j][2] * 1000)        
+                resHistoTrend.SetBinError(j+1, fitRes[j][2] * 1000)      
 
                 title[j] = 'RICH ' + str(self.whichRich) + ' Cherenkov angle resolution It. ' + str(j) 
-                if j == 0:
-                    resHistograms[j].SetName('resHisto0')
-                    self.monSvc.publishHistogram(self.monitoring_folder, resHistograms[j].Clone(), add=False)
-                    print "INFO: resHisto0 sent to Monitoring."
-                elif j == self.maxIt:
-                    resHistograms[j].SetName('resHistoN')
-                    self.monSvc.publishHistogram(self.monitoring_folder, resHistograms[j].Clone(), add=False)
-                    print "INFO: resHistoN sent to Monitoring."
-                else:
-                    resHistograms[j].SetName('resHisto'+str(j))
-
                 resHistograms[j].SetTitle(title[j])
                 resHistograms[j].SetXTitle('#Delta#theta_{Cherenkov} (rad)')
                 resHistograms[j].SetYTitle('Entries')
@@ -380,31 +517,37 @@ class AlignSummary:
                 polbkg[j].SetParameter(2, histFunc[j].GetParameter(5))
                 polbkg[j].SetParameter(3, histFunc[j].GetParameter(6))
                 polbkg[j].SetLineColor(4)
+
+                theCanvas2.cd()
+                resHistograms[j].Draw()
+                polbkg[j].Draw("SAME") 
                 
-                cPlot.cd(j+1)                      
+                theCanvas2.Print(expertFile)
+
+                theCanvas.cd()
+                theCanvas.cd(1+j)                      
                 resHistograms[j].Draw()
                 polbkg[j].Draw("SAME")   
             
-        cPlot.Print(saveName)
-        cPlot.Print(saveNameDM)
+        theCanvas.Print(monitorFile)
         
         sys.stdout.flush()
     
         # Make resHistoTrend iteration trend plot
         resHistoTrend.SetMarkerStyle(8)
         resHistoTrend.SetXTitle('iteration number')
-        resHistoTrend.SetYTitle('') # resHistoTrend.SetYTitle('Cherenkov angle resolution (mrad)')
-        
-        cPlot.Clear()
+        resHistoTrend.SetYTitle('#splitline{Cherenkov angle resolution (mrad)}{}') 
+
+        theCanvas2.Clear()
+        theCanvas.Clear()
         resHistoTrend.DrawCopy()
-        cPlot.Print(saveName)
-#        cPlot.Print(saveNameDM)
-        cPlot.Print(saveNameDM + ')')
+
+        theCanvas.Print(expertFile)
+        theCanvas.Print(monitorFile + ')')
         
         self.monSvc.publishHistogram(self.monitoring_folder, resHistoTrend.Clone(), add=False)
         print "INFO: resHistoTrend sent to Monitoring."
         sys.stdout.flush()
-        
 
         maxPriY = TLine(0, self.sTPY, self.maxpri, self.sTPY)
         minPriY = TLine(0, -self.sTPY, self.maxpri, -self.sTPY) 
@@ -435,7 +578,7 @@ class AlignSummary:
         minSecZ.SetLineStyle(21)
         
         # compensations graphs        
-        cPlot.Clear()
+        theCanvas.Clear()
         tops = self.sTPZ 
         if tops < self.sTPY: 
             tops = self.sTPY
@@ -454,9 +597,9 @@ class AlignSummary:
         mgraphs[0].GetXaxis().SetTitle("primary mirror number")
         mgraphs[0].GetYaxis().SetTitle("change in compensation (mrad) [{red, blue}: local {Y, Z}]")
 
-        cPlot.Print(saveName)
+        theCanvas.Print(expertFile)
         
-        cPlot.Clear()
+        theCanvas.Clear()
         tops = self.sTSZ 
         if tops < self.sTSY: 
             tops = self.sTSY
@@ -475,15 +618,19 @@ class AlignSummary:
         mgraphs[1].GetXaxis().SetTitle("secondary mirror number")
         mgraphs[1].GetYaxis().SetTitle("change in compensation (mrad) [{red, blue}: local {Y, Z}]")
 
-        cPlot.Print(saveName + ')')
+        theCanvas.Print(expertFile + ')')
         
-        for its in range(0, self.maxIt + 1):
+        for n_it in range(0, self.maxIt + 1):
             mirrtilts[self.maxIt].writeChange(self.maxIt +  1)
         mgraphs[0].Delete()
         mgraphs[1].Delete()
 
         # Close the Monitoring Job; the histograms are now in the presenter (Page Editor Online).
-        # To adjust the histos, see 
+        # New Histograms need to be added to the Histogram Database https://lbhistogramdb.cern.ch
+        #   in order to be viewed at the pit.
+        # This database is only accessible on the CERN network (or ssh to plus, start Firefox).
+        # One can adjust the histo styles on the presenter view there, 
+        #   but not all normal ROOT options are available.
         self.gaudi.stop()
         self.gaudi.finalize()
 
@@ -491,7 +638,7 @@ class AlignSummary:
         richStr = 'Rich' + str(self.whichRich)
         m_maxErrorForOK = 1e-3;
         
-        xPeak = hist.GetBinCenter( hist.GetMaximumBin() )
+        xPeak = hist.GetBinCenter(hist.GetMaximumBin())
         delta = 0
         if (richStr == 'Rich1'):
             delta = 0.0025
@@ -502,8 +649,8 @@ class AlignSummary:
         fitMax = xPeak + delta
         
         preFitFName = richStr + "PreFitF"
-        preFitF = TF1( preFitFName, "gaus", fitMin, fitMax )
-        preFitF.SetParameter(1, 0 )
+        preFitF = TF1(preFitFName, "gaus", fitMin, fitMax)
+        preFitF.SetParameter(1, 0)
         
         if (richStr == 'Rich1'):
             preFitF.SetParameter(2, 0.0015)
@@ -532,10 +679,10 @@ class AlignSummary:
             if ( nPol > 1 ):
                 nParamsToSet = 3 + nPol
                 
-            for p in range(0, nParamsToSet ):
+            for p in range(0, nParamsToSet):
                 fFitF.SetParameter(p,lastFitF.GetParameter(p));
                 
-            hist.Fit( fFitF, "RFQ" )
+            hist.Fit( fFitF, "RFQM" )
             lastFitF = fFitF
             fitOK = fFitF.GetParError(1) < m_maxErrorForOK 
             if fitOK:
@@ -543,7 +690,7 @@ class AlignSummary:
                 bestNPol = nPol
             else:
                 if ( nPol == nPolFull ):
-                    hist.Fit( fFitF, "RSE0Q" )
+                    hist.Fit( fFitF, "RFSE0QM" )
                     fitOK = True         
                 if nPol > 1:
                     break 
diff --git a/Rich/RichMirrorAlignmentOnline/python/PyMirrAlignOnline/Iterator.py b/Rich/RichMirrorAlignmentOnline/python/PyMirrAlignOnline/Iterator.py
index 38177c34964973662045ebdeff2b84fdbf4b08a7..7b99f5bf2fa0edb3d2b3e790b5331af805d8d116 100644
--- a/Rich/RichMirrorAlignmentOnline/python/PyMirrAlignOnline/Iterator.py
+++ b/Rich/RichMirrorAlignmentOnline/python/PyMirrAlignOnline/Iterator.py
@@ -17,7 +17,6 @@ from   subprocess import *
 from   distutils  import dir_util
 
 print "INFO: Iterator.py launched at " + strftime("%Y-%m-%d %H:%M:%S", gmtime()) + " UTC"
-print 'INFO: Claire says miezmiezmiez'
 sys.stdout.flush()
 
 ########################################################################################################################                                    
@@ -53,9 +52,9 @@ def run(whichRich):
   sys.stdout.flush()
 
   from HistoHelper import SaveSetRetriever
-  ssRetr = None  #the SavesetRetriever, this thing will give us the path to the histogram files produced by the analyzers
+  ssRetr = None  #the SaveSetRetriever, this thing will give us the path to the histogram files produced by the analyzers
   from HistoHelper import HistoCopier
-  histCopier = None  #the Histcopier, it will wait after each minor iteration for the savesets to be written and copy it under the approriate name into workdir
+  histCopier = None  #the HistoCopier, it will wait after each minor iteration for the savesets to be written and copy it under the approriate name into workdir
   from XMLFileHelper import XMLFileHelper
   xmlHelper = None  
   from RichAlignmentHelper import RichAlignmentHelper
@@ -103,7 +102,7 @@ def run(whichRich):
   ### before each new minor iteration the new xml file will be copied here
   currentXML = workdir + "CondDB_Rich" + str(whichRich) + ".xml"
 
-  ### path in the workdirectory of the database-file that the final database will be compared to  
+  ### path in the workdirectory of the database-file that the final database will be compared to in the AlignMonitor
   compareXML = workdir + 'Rich' + str(whichRich) + '_compareXMLFile.xml'
   
   # We do this before a "configure" because we need run and directoryTime info for the next part
@@ -122,7 +121,7 @@ def run(whichRich):
   print "INFO: runs = " + str(runs)
   print "INFO: fills = " + str(fills)
   polsStr = [str(item) for item in polarities]
-  print "INFO: polarities = " + str(polsStr) # gets rid of unicode flag preceding each string
+  print "INFO: polarities = " + str(polsStr) # str() gets rid of unicode flag preceding each string
   cancel = False
   preSubject, preText, postSubject, postText = [''] * 4 # this is a nice variable defining strategy, but note it does not work on mutable elements (such as lists)!
   for i in range(0, len(runs)):
@@ -133,11 +132,16 @@ def run(whichRich):
       break
     if (polarities[i] == 'OFF') or (polarities[i] != polarities[0]):
       cancel = True
-      setupHelper.sendEmail('RICH' + str(whichRich) + ' mirror alignment started, but skipped', 'Some of the chosen runs contain magnet OFF data *or* Data for these runs is of mixed polarity: \n Runs: ' + str(runs) + ' \n Fills: ' + str(fills) + ' \n Polarities: ' + str(polsStr) , setupHelper.emails)
+      cancelSubject = 'WARNING: RICH' + str(whichRich) + ' mirror alignment ' + setupHelper.directoryTime + 'started, but has been cancelled.'
+      cancelText = 'RICH' + str(whichRich) + ' mirror alignment ' + setupHelper.directoryTime + 'started, but has been cancelled. Some of the chosen runs contain magnet OFF data *or* Data for these runs is of mixed polarity: \n Runs: ' + str(runs) + ' \n Fills: ' + str(fills) + ' \n Polarities: ' + str(polsStr) 
+      setupHelper.sendEmail(cancelSubject, cancelText, setupHelper.emails)
       print 'INFO: Mirror alignment will be skipped. Some of these runs contain magnet OFF data *or* Data for these runs is of mixed polarity: ' + str(runs)
+      messageID = setupHelper.quickWriteInLogbook(cancelSubject, cancelText)      
       break      
   polarityDir = '/group/rich/AlignmentFiles/Polarity/'
   forcedUpdate_ChMagPol = False
+  ChMagPolSubject = ''
+  ChMagPolText = ''
   if (not cancel) and (polarities[0] is not None):
     oldPolarityFilename = polarityDir + 'previousPolarity_RICH' + str(whichRich) +'.txt'
     newPolarityFilename = polarityDir + 'currentPolarity_RICH' + str(whichRich) +'.txt'
@@ -148,17 +152,26 @@ def run(whichRich):
         first_line = previousAlignPolarityFile.readline()
       if (first_line != polarities[0] + '\n'):
         forcedUpdate_ChMagPol = True
-        postSubject += ' Magnet Polarity Changed; possibly forcing update.'
-        postText += ' \n If this alignment converges, the alignment will be updated due to a change in magnet polarity (unless autoUpdate is/becomes False, or testing is True).'
+        ChMagPolSubject += 'Magnet Polarity Changed; possibly forcing update.'
+        ChMagPolText += 'If this alignment converges, the alignment will be updated due to a change in magnet polarity (unless autoUpdate is/becomes False, or testing is True). If there are any problems with this alignment, please contact the Mirror Alignment expert! They should re-flip the magnet polarity in ' + polarityDir + ' in order to have the proper behavior on the next attempt!'       
+        postSubject += ' ' + ChMagPolSubject
+        postText += ' \n ' + ChMagPolText
         print 'INFO: Magnet Polarity Changed; if this alignment converges under normal conditions, then the alignment will be updated.'
-    shutil.copy2(newPolarityFilename, oldPolarityFilename) 
+        ChMagPolSubject = ' WARNING: The magnet polarity changed!'
+        ChMagPolText = ' \n WARNING: The magnet polarity changed! Make sure that everything (e.g. previousPolarity_RICH) is in order for the next alignment!!!'
+        # OUTDATED: The expert should re-flip the magnet polarity for this Rich detector in ' + polarityDir + ' in order to have the proper behavior on the next attempt!!!     
 
   if (not cancel):
     leadText = ''
     if testing is True:
       leadText += 'TEST [' + alignConf.getProp('dataVariant') + ']: '
-    setupHelper.sendEmail( leadText + preSubject + 'RICH' + str(whichRich) + ' alignment ' + setupHelper.directoryTime + ' has started.' + postSubject , preText + ' RICH' + str(whichRich) + ' mirror alignment ' + setupHelper.directoryTime + ' has started. \n Runs: ' + str(runs) + ' \n Fills: ' + str(fills) + ' \n Polarities: ' + str(polsStr) + postText + ' \n dataVariant: ' + alignConf.getProp('dataVariant'), setupHelper.emails)        
+    totalSubject = leadText + preSubject + 'RICH' + str(whichRich) + ' alignment ' + setupHelper.directoryTime + ' has started.' + postSubject
+    totalText = preText + ' RICH' + str(whichRich) + ' mirror alignment ' + setupHelper.directoryTime + ' has started. \n Runs: ' + str(runs) + ' \n Fills: ' + str(fills) + ' \n Polarities: ' + str(polsStr) + postText + ' \n dataVariant: ' + alignConf.getProp('dataVariant')
+    # setupHelper.sendEmail( totalSubject , totalText, setupHelper.emails)       
+    postText +=" \n \n If this alignment does not finish, please report this via the RICH ELOG. \n " 
+    totalText = preText + ' RICH' + str(whichRich) + ' mirror alignment ' + setupHelper.directoryTime + ' has started. \n Runs: ' + str(runs) + ' \n Fills: ' + str(fills) + ' \n Polarities: ' + str(polsStr) + postText + ' \n dataVariant: ' + alignConf.getProp('dataVariant')
     print 'INFO: RICH' + str(whichRich) + ' mirror alignment ' + setupHelper.directoryTime + ' has started, dataVariant: ' + alignConf.getProp('dataVariant')
+    messageID = setupHelper.quickWriteInLogbook(totalSubject, totalText)
 
   sys.stdout.flush()
 
@@ -339,6 +352,10 @@ def run(whichRich):
         ### check if the alignment has converged or failed
         conv = alignHelper.hasConverged()
         print "INFO: The alignment after Iteration", n_it, "returns converged =", conv
+
+        # if the alignment has converged, overwrite the old polarity file with the new polarity file
+        if conv:
+            shutil.copy2(newPolarityFilename, oldPolarityFilename)   
         
         if(conv or n_it >= maxIters):
           allDone = True
@@ -351,33 +368,47 @@ def run(whichRich):
 
           elapsed_runtimes['elapsed_time_run'] = time() - start_time_run # Actual total iterating time
           print "INFO: Elapsed time to run the Mirror Alignment set as", elapsed_runtimes['elapsed_time_run'], "seconds."
+          sys.stdout.flush()  
 
+          # Run the monitoring, send plots to the Presenter, and generate PDF files;
+          #   this returns True if any sanity check failed.
+          insane = setupHelper.monitor(n_it, compareXML, forcedUpdate_ChMagPol)
+          print "INFO: alignMonitor.isInsane = " + str(insane)
+          sys.stdout.flush()
+          
           nEventsListList = setupHelper.getNEventsListList(n_it)
           if nEventsListList[1] < int(alignConf.getProp('requiredEvents')):
-              if autoUpdate is True:
+              if autoUpdate:
                 autoUpdate = False
                 print "INFO: We processed an average number of events per iteration of " + str(nEventsListList[1]) + ", which is too low to allow mirror alignment " + setupHelper.directoryTime + " to automatically update, should an update be deemed necessary."
                 setupHelper.sendEmail( 'autoUpdate disabled for RICH' + str(whichRich) + ' alignment ' + setupHelper.directoryTime + '.' , 'RICH' + str(whichRich) + ' mirror alignment ' + setupHelper.directoryTime + ' will not automatically be updated, should an update be deemed necessary. \n Average number of events processed per iteration: ' + str(nEventsListList[1]) , setupHelper.emails)        
-
-          sys.stdout.flush()  
+          if insane: 
+              if autoUpdate:
+                autoUpdate = False
+                print "INFO: Sanity checks have failed, we will not allow mirror alignment " + setupHelper.directoryTime + " to automatically update, should an update be deemed necessary."
+                setupHelper.sendEmail( 'autoUpdate disabled for RICH' + str(whichRich) + ' alignment ' + setupHelper.directoryTime + '.' , 'RICH' + str(whichRich) + ' mirror alignment ' + setupHelper.directoryTime + ' will not automatically be updated, should an update be deemed necessary. \n Sanity checks have failed for this alignment.' , setupHelper.emails)        
+          sys.stdout.flush()                 
           
           if forcedUpdate_ChMagPol and conv:
               # if we are forcing the update we use the newXML from RichMirrAlign, not the currentXML
-              shutil.copy2(newXMLfile,currentXML) 
+              shutil.copy2(newXMLfile,currentXML)
           if (forcedUpdate_ChMagPol or updateHelper.updateDecision(n_it)) and conv:
               if autoUpdate:
-                xmlHelper.finalXML( str(int(latest_vN) + 1) , True) # current + 1
-                setupHelper.finalize(conv, n_it, compareXML, elapsed_time_config, elapsed_runtimes, True, nEventsListList)
+                vN_DB_str = 'v' + str(int(latest_vN) + 1)
+                xmlHelper.finalXML(vN_DB_str , True) # current + 1
+                setupHelper.finalize(vN_DB_str, conv, n_it, elapsed_time_config, elapsed_runtimes, True, nEventsListList, messageID)
                 if testing is not True:
                     updateHelper.updateDB( int(latest_vN) + 1 , True) # current + 1
               else:
-                xmlHelper.finalXML( str(int(latest_vN) + 1) + '_maybe_' + setupHelper.directoryTime, True) # (current + 1)_maybe
-                setupHelper.finalize(conv, n_it, compareXML, elapsed_time_config, elapsed_runtimes, None, nEventsListList)
+                vN_DB_str = 'v' + str(int(latest_vN) + 1) + '_maybe_' + setupHelper.directoryTime
+                xmlHelper.finalXML(vN_DB_str, True) # (current + 1)_maybe
+                setupHelper.finalize(vN_DB_str, conv, n_it, elapsed_time_config, elapsed_runtimes, None, nEventsListList, messageID)
                 if testing is not True:
                     updateHelper.updateDB( int(latest_vN) , False)
               #updateHelper.stopUpdateDIM()    
           else:
-              setupHelper.finalize(conv, n_it, compareXML, elapsed_time_config, elapsed_runtimes, False, nEventsListList)
+              vN_DB_str = 'v' + str(int(latest_vN))
+              setupHelper.finalize(vN_DB_str, conv, n_it, elapsed_time_config, elapsed_runtimes, False, nEventsListList, messageID)
               if testing is not True:
                   updateHelper.updateDB( int(latest_vN) , False) # current 
                   #updateHelper.stopUpdateDIM()  
@@ -419,7 +450,8 @@ def run(whichRich):
       elapsed_runtimes['elapsed_time_run'] = time() - start_time_run # Actual iterating time
       print "INFO: Elapsed time to run the Mirror Alignment set as", elapsed_runtimes['elapsed_time_run'], "seconds."
       nEventsListList = setupHelper.getNEventsListList(n_it)
-      setupHelper.finalize(conv, n_it, compareXML, elapsed_time_config, elapsed_runtimes, False, nEventsListList)
+      vN_DB_str = 'v' + str(int(latest_vN))
+      setupHelper.finalize(vN_DB_str, conv, n_it, elapsed_time_config, elapsed_runtimes, False, nEventsListList, messageID)
       if testing is not True:
           updateHelper.updateDB( int(latest_vN) , False) # current
           #updateHelper.stopUpdateDIM()   
@@ -445,7 +477,7 @@ def run(whichRich):
   print 'INFO: Iterator state = ' + str(state)
     
 ########################################################################################################################                                    
-##### This is where the party ends!
+##### This is where the party ends! (well, almost...)
 ########################################################################################################################   
     
   if not cancel:
@@ -464,43 +496,64 @@ def run(whichRich):
   sys.stdout.flush()
   
   if not os.path.exists(setupHelper.savedir):
-    print "INFO: Expect log file to be written to: " + loggingDir + 'Rich' + str(whichRich) + '_hlt02_' + setupHelper.directoryTime + '.log'
+    print "INFO: Expect log file to be written to: " + loggingDir + 'Rich' + str(whichRich) + '_' + setupHelper.directoryTime + '_hlt02.log'
+    print "INFO: Expect reduced log file to be written to: " + loggingDir + 'Rich' + str(whichRich) + '_' + setupHelper.directoryTime + '_hlt02reduced.log'
     if cancel:
       print "INFO: We choose to not execute the mirror alignment. "
       print "INFO: The input data is of mixed polarity, or some it is magnet OFF data."
-      subject = "has been cancelled."
-      text = "that it has been cancelled. The input data is of mixed polarity, or some it is magnet OFF data."
-      setupHelper.quickWriteInLogbook(subject, text)
     else:
-      setupHelper.sendEmail( 'WARNING: RICH' + str(whichRich) + ' mirror alignment ' + setupHelper.directoryTime + ' did not complete normally.', 'Warning: RICH' + str(whichRich) + ' mirror alignment ' + setupHelper.directoryTime + ' did not complete normally. \n No output directory was written. \n Log may be found on plus.cern.ch (via lbgw) in /group/rich/AlignmentFiles/Logging/ with timestamp ' + setupHelper.directoryTime + '. \n Runs: ' + str(runs) + ' \n Fills: ' + str(fills) + ' \n Polarities: ' + str(polsStr) + postText + ' \n dataVariant: ' + alignConf.getProp('dataVariant'), setupHelper.emails)        
+      setupHelper.sendEmail( 'WARNING: RICH' + str(whichRich) + ' mirror alignment ' + setupHelper.directoryTime + ' did not complete normally.' + ChMagPolSubject, 'Warning: RICH' + str(whichRich) + ' mirror alignment ' + setupHelper.directoryTime + ' did not complete normally. \n No output directory was written. \n Log may be found on plus.cern.ch (via lbgw) in /group/rich/AlignmentFiles/Logging/ with timestamp ' + setupHelper.directoryTime + '.' + ChMagPolText + ' \n Runs: ' + str(runs) + ' \n Fills: ' + str(fills) + ' \n Polarities: ' + str(polsStr) + postText + ' \n dataVariant: ' + alignConf.getProp('dataVariant'), setupHelper.emails)        
       print 'WARNING: RICH' + str(whichRich) + ' mirror alignment ' + setupHelper.directoryTime + ' did not complete normally. No output directory was written.'
-      
   else:
     print "INFO: Expect log file to be written to: " + setupHelper.savedir + 'hlt02.log'
+    print "INFO: Expect reduced log file to be written to: " + setupHelper.savedir + 'hlt02reduced.log'
   sys.stdout.flush()
 
   print "INFO: End of run(whichRich = " + str(whichRich) + "). Killing logProcess and writing hlt02 log file."
   sys.stdout.flush()  
+  
+  print "INFO: Now sleeping 5 seconds to let output be stored before hlt02 logProcess is killed."
+  sys.stdout.flush()  
+  sleep(5)
+  
+  logProcess.kill()
+  print "INFO: hlt02 logProcess killed."
+  sys.stdout.flush()
 
-  sleep(2)
+  # string used to help remove lines from the hlt02 log, using grep -vE (E = Enhanced Mode, required to parse the string)
+  removeExtraneous = '(tmSrv|LHCb2_HLT02_Hlt2Adder_0|Hlt2SaverSvc|MARK|GEN_hlt02_BusyMon)'
 
-  try:
-    logProcess.kill()
-    print "INFO: hlt02 logProcess killed."
-  except OSError:
-    # can't kill a dead process
-    print "INFO: hlt02 logProcess already dead."
-  sys.stdout.flush()
-    
-  try:
-    print "INFO: logging hlt02 ended, storing in file: " + setupHelper.savedir + 'hlt02.log'
+  if os.path.exists(setupHelper.savedir):
+    print 'INFO: logging hlt02 ended, storing in file: ' + setupHelper.savedir + 'hlt02.log'
+    sys.stdout.flush()  
     shutil.copy2(loggingDir + 'Rich' + str(whichRich) + '_' + 'hlt02.log', setupHelper.savedir + 'hlt02.log')  
-  except:
-    print "INFO: logging hlt02 ended, storing in file: " + loggingDir + 'Rich' + str(whichRich) + '_hlt02_' + setupHelper.directoryTime + '.log'
-    shutil.copy2(loggingDir + 'Rich' + str(whichRich) + '_' + 'hlt02.log', loggingDir + 'Rich' + str(whichRich) + '_hlt02_' + setupHelper.directoryTime + '.log')  
+    # remove what we currently believe are extraneous items
+    print 'INFO: storing reduced file: ' + setupHelper.savedir + 'hlt02reduced.log'
+    sys.stdout.flush()  
+    print 'INFO: Executing: ' + 'grep -vE "' + removeExtraneous + '" ' + setupHelper.savedir + 'hlt02.log > ' + setupHelper.savedir + 'hlt02reduced.log'
+    sys.stdout.flush()  
+    os.system('grep -vE "' + removeExtraneous + '" ' + setupHelper.savedir + 'hlt02.log > ' + setupHelper.savedir + 'hlt02reduced.log')
+  else:
+    print 'INFO: logging hlt02 ended, storing in file: ' + loggingDir + 'Rich' + str(whichRich) + '_' + setupHelper.directoryTime + '_hlt02.log'
+    shutil.copy2(loggingDir + 'Rich' + str(whichRich) + '_' + 'hlt02.log', loggingDir + 'Rich' + str(whichRich) + '_' + setupHelper.directoryTime + '_hlt02.log')  
+    sys.stdout.flush()  
+    # remove what we currently believe are extraneous items
+    print 'INFO: storing reduced file: ' + loggingDir + 'Rich' + str(whichRich) + '_' + setupHelper.directoryTime + '_hlt02reduced.log'
+    sys.stdout.flush()  
+    print 'INFO: Executing: ' + 'grep -vE "' + removeExtraneous + '" ' + loggingDir + 'Rich' + str(whichRich) + '_' + setupHelper.directoryTime + '_hlt02.log > ' + loggingDir + 'Rich' + str(whichRich) + '_' + setupHelper.directoryTime + '_hlt02reduced.log'
+    sys.stdout.flush()  
+    os.system('grep -vE "' + removeExtraneous + '" ' + loggingDir + 'Rich' + str(whichRich) + '_' + setupHelper.directoryTime + '_hlt02.log > ' + loggingDir + 'Rich' + str(whichRich) + '_' + setupHelper.directoryTime + '_hlt02reduced.log')
+  sys.stdout.flush()  
+
+  print "INFO: Now sleeping 25 seconds to let hlt02 and hlt02reduced log files to be stored."
   sys.stdout.flush()  
+
+  sleep(25)
   
-  sleep(5)
+  print "INFO: Goodbye from the Rich"+str(whichRich)+" Mirror Alignment!"
+  print 'INFO: Claire says miezmiezmiez'
+  sys.stdout.flush()  
+
      
 if __name__ == '__main__':
     run()
diff --git a/Rich/RichMirrorAlignmentOnline/python/PyMirrAlignOnline/SetupHelper.py b/Rich/RichMirrorAlignmentOnline/python/PyMirrAlignOnline/SetupHelper.py
index a0d03206a62ef657ec6a89171446231caebe46da..80e28b85b350725d4b5f4acb7785eb7221c175e1 100644
--- a/Rich/RichMirrorAlignmentOnline/python/PyMirrAlignOnline/SetupHelper.py
+++ b/Rich/RichMirrorAlignmentOnline/python/PyMirrAlignOnline/SetupHelper.py
@@ -13,7 +13,7 @@ from ROOT import TH1, TFile
 class SetupHelper:
     def __init__(self, _alignConf):
         self.alignConf = _alignConf
-        # maybe put combAndMirrSubsets here later somehow
+        # put combAndMirrSubsets here later somehow
         self.nameStr = self.alignConf.getProp('nameStr')
         self.tiltNames = self.alignConf.getProp('tiltNames')
         self.workdir = self.alignConf.getProp('WorkDir')
@@ -27,6 +27,7 @@ class SetupHelper:
         self.solutionMethod = self.alignConf.getProp('solutionMethod')
         self.coeffCalibTilt = self.alignConf.getProp('coeffCalibTilt')
         self.magnifDir = self.alignConf.getProp('magnifDir') 
+        self.testing = self.alignConf.getProp('testing')
         self.fixSinusoidShift = self.alignConf.getProp('fixSinusoidShift')
         self.fileprename = self.workdir + '/' + "RichRecQCHistos_rich" + str(self.whichRich) + "_" + self.nameStr + "_" +'i' 
         self.experts = ['Paras.Naik@cern.ch','samuel.maddrell-mander@cern.ch','matthew.george.chapman@cern.ch','claire.prouve@cern.ch']
@@ -34,11 +35,11 @@ class SetupHelper:
         self.emails = ['lhcb-rich-mirror-alignment-development@cern.ch','jonesc@hep.phy.cam.ac.uk','antonis.papanestis@stfc.ac.uk','m.mccann@imperial.ac.uk','silvia.gambetta@cern.ch']
         self.directoryTime = strftime("%Y%m%d_%H%M%S", gmtime())
         self.savedir = self.alignConf.getProp('SaveDir') + 'Rich' + str(self.whichRich) + '/' + self.directoryTime + '/'
+        self.dataVariant = self.alignConf.getProp('dataVariant')
 
     def setupMagnifFiles(self):
-        magnifDir = self.alignConf.getProp('magnifDir')
-        for f in os.listdir(magnifDir):
-            shutil.copy(magnifDir + "/" + f, self.workdir)
+        for f in os.listdir(self.magnifDir):
+            shutil.copy(self.magnifDir + "/" + f, self.workdir)
     
     def startMinIt(self, m_it):
         removeIt = (m_it - m_it % 9) / 9
@@ -62,10 +63,19 @@ class SetupHelper:
         if os.path.exists(self.workdir + "/" + rootFile):
             os.remove(self.workdir + "/" + rootFile)
 
-    def finalize(self, conv, n_it, compareXML, farm_config_time, elapsed_runtimes, DBUpdated, nEventsListList):
+    def monitor(self, n_it, compareXML, forcedUpdate_ChMagPol):
+        from AlignMonitor import AlignMonitor
+        alignMonitor = AlignMonitor(self.alignConf, n_it)
+        alignMonitor.performMonitoring(compareXML, forcedUpdate_ChMagPol)
+        return alignMonitor.isInsane
+
+    def finalize(self, vN_DB_str, conv, n_it, farm_config_time, elapsed_runtimes, DBUpdated, nEventsListList, edit = None):
         nEventsList = nEventsListList[0]
         nEvents = nEventsListList[1]
-
+        
+        summaryFile = self.workdir + "/summary.txt"
+        self.writeSummary(vN_DB_str, conv, n_it, farm_config_time, elapsed_runtimes, summaryFile, DBUpdated, nEvents, nEventsList)
+        
         if not os.path.exists(self.savedir):
             os.makedirs(self.savedir)
         for f in os.listdir(self.workdir):
@@ -74,34 +84,30 @@ class SetupHelper:
             else:
                 shutil.copy2(self.workdir + "/" + f, self.savedir)
         print "INFO: savedir " + self.savedir
-
-        summaryFile = self.workdir + "/summary.txt"
-        self.writeSummary(conv, n_it, farm_config_time, elapsed_runtimes, summaryFile, DBUpdated, nEvents, nEventsList)
-
-        shutil.copy2(summaryFile, self.savedir)
-
-        from AlignSummary import AlignSummary
-        alignSummary = AlignSummary(self.alignConf, n_it)
-        alignSummary.makeSummaryPlot(compareXML)
+        # NOTE: *Any file created after this in the workdir* 
+        #   needs to be *manually* saved in the savedir
 
         ChangeWRTDBFile  = self.workdir + "/Rich" + str(self.whichRich) + '_ChangeWRTDB_'+ str(n_it + 1) +'.txt'
-        shutil.copy2(ChangeWRTDBFile, self.savedir)
         AlignSummaryFile = self.workdir + "/Rich" + str(self.whichRich) + '_AlignSummary.pdf'    
-        shutil.copy2(AlignSummaryFile, self.savedir)
-        AlignMonitorFile = self.workdir + "/Rich" + str(self.whichRich) + '_AlignMonitor.pdf'    
-        shutil.copy2(AlignMonitorFile, self.savedir)
+        AlignMonitorFile = self.workdir + "/Rich" + str(self.whichRich) + '_AlignMonitor.pdf' # Not used just yet   
+        AlignTestingFile = self.workdir + "/Rich" + str(self.whichRich) + '_AlignTesting.pdf' # Not used just yet; May not exist   
 
-        # Write summary.txt, _AlignSummary.pdf, and _ChangeWRTDB.txt to the ELOG
+        # Write files and information to the RICH and Alignment Monitor ELOGs, and also send email
         alignment_time = elapsed_runtimes['elapsed_time_run']
-        self.writeInLogbook(conv, n_it, farm_config_time, alignment_time, summaryFile, ChangeWRTDBFile, AlignSummaryFile, DBUpdated, nEvents)
+        self.writeInLogbook(vN_DB_str, conv, n_it, farm_config_time, alignment_time, summaryFile, ChangeWRTDBFile, AlignSummaryFile, AlignMonitorFile, DBUpdated, nEvents, edit)
 
-    def writeInLogbook(self, conv, n_it, farm_config_time, alignment_time, summaryFile, ChangeWRTDBFile, AlignSummaryFile, DBUpdated, nEvents):
+    def writeInLogbook(self, vN_DB_str, conv, n_it, farm_config_time, alignment_time, summaryFile, ChangeWRTDBFile, AlignSummaryFile, AlignMonitorFile, DBUpdated, nEvents, edit):
         hh, r = divmod(farm_config_time, 3600)
         mm, ss = divmod(r, 60)
         farm_config_time_str = "{:0>2}:{:0>2}:{:05.2f}".format(int(hh),int(mm),ss)
         hh, r = divmod(alignment_time, 3600)
         mm, ss = divmod(r, 60)
         alignment_time_str = "{:0>2}:{:0>2}:{:05.2f}".format(int(hh),int(mm),ss)
+
+        import OnlineEnv as Online
+        FillAlignment = self.getFillNumber(Online.DeferredRuns[0])   
+        
+        # RICH ELOG
         host = 'lblogbook.cern.ch' 
         port = 8080
         username = 'common Common\\!'
@@ -118,8 +124,8 @@ class SetupHelper:
             subjText += ' needs MirrAlign expert decision,'
         else:
             subjText += ''
-        if self.alignConf.getProp('testing') is True:
-            subject += 'TEST [' + self.alignConf.getProp('dataVariant') + ']: '
+        if self.testing is True:
+            subject += 'TEST [' + self.dataVariant + ']: '
         text += "The Mirror "
         text += str(activity)
         text += " for RICH"
@@ -151,14 +157,20 @@ class SetupHelper:
         text += " and the output directory timestamp is "
         text += self.directoryTime
         text += "."
-        if DBUpdated:
-            text += " Due to a significant change from the alignment in the DB, or a change in magnet polarity, the DB was automatically updated." # We should probably provide more info here
         if DBUpdated is None:
-            text += " There was a significant change from the alignment in the DB, or a change in magnet polarity. However the automatic update feature is off (or was disabled during the alignment), so the DB was not updated. Please notify a MirrAlign expert to investigate whether this alignment should be installed." # We should maybe provide more info here
+            text += " There was a significant change from the alignment in the DB, or a change in magnet polarity. However the automatic update feature is off, or was disabled during the alignment, so the DB was not updated. If the automatic update feature was disabled, there may not have been enough events processed, or a sanity check was not satisfied. Please notify a MirrAlign expert to investigate whether this alignment (" + vN_DB_str + ") should be installed." # We should maybe provide more info here
+        elif DBUpdated:
+            text += " Due to a significant change from the alignment in the DB, or a change in magnet polarity, the DB was automatically updated to " + vN_DB_str + "." # We should probably provide more info here
+        else:
+            text += " The alignment in the DB is still " + vN_DB_str + "."          
         command = 'elog -h "'
         command += str(host)
         command += '" -p '
         command += str(port)
+        try:
+            command += ' -e ' + str(int(edit))
+        except:
+            pass
         command += ' -l "'
         command += str(logbook)
         command += '" -u '
@@ -166,13 +178,14 @@ class SetupHelper:
         command += ' -a "Author='
         command += str(author)
         #command += '" -a "System='
-        command += '" -a "System_19='
+        command += '" -a "System_19=' # Change 19 if Alignment changes its order in the ELOG (ask the current RICH expert)
         command += str(activity)
         command += '" -a "Subject='
         command += str(subject)
         command += '" "'
         command += str(text)
         command += '"'
+
         if os.path.exists(summaryFile):
             command += ' -f "{0}"'.format(summaryFile)
         if os.path.exists(ChangeWRTDBFile):
@@ -180,12 +193,71 @@ class SetupHelper:
         if os.path.exists(AlignSummaryFile):
             command += ' -f "{0}"'.format(AlignSummaryFile)
         cmd = shlex.split(command)
+        try:
+            elogret = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
+            messageID = int(re.search('.*Message successfully transmitted, ID=(\d*)', elogret).groups()[0])
+        except:
+            messageID = None
+  
+        # Alignment ELOG
+        logbookAlignment = 'Alignment monitoring' # always
+        authorAlignment = 'monibot' # always
+        activityAlignment = 'Rich' + str(self.whichRich) + ' Mirrors' # always
+        TypeAlignment = 'Convergence' # always
+        subjectAlignment = 'Only A Test: ' # change to '' when operational
+        textAlignment = 'Please Ignore: \n ' # change to '' when operational
+        StatusAlignment = 'Good' # or can be changed below to 'Unchecked' or 'Bad' (for now 'Bad' never happens) 
+        
+        if self.testing is True:
+            subjectAlignment += 'This is only a test: '
+            textAlignment += 'A test mirror alignment for Rich' + str(self.whichRich) + ' was performed for fill ' + str(FillAlignment) + ". No action necessary; ignore the following. \n "
+        if DBUpdated is None:
+            subjectAlignment += 'No alignment update: Needs MirrAlign expert decision'
+            textAlignment += 'Rich' + str(self.whichRich) + ' mirror alignment for fill ' + str(FillAlignment) + " is requesting an update be made, but for some reason this was not done automatically. Please ask the Rich Mirror Alignment experts to investigate the draft alignment (" + vN_DB_str + "). Monitoring plots in the attachment; shifter's instructions can be found at: " + instruction_file
+            StatusAlignment = 'Unchecked'
+        elif DBUpdated:
+            subjectAlignment += 'Monitoring plots'
+            textAlignment += 'Updated Rich' + str(self.whichRich) + ' mirror alignment for fill ' + str(FillAlignment) + " (" + vN_DB_str + "), monitoring plots in the attachment; shifter's instructions can be found at: " + instruction_file
+            StatusAlignment = 'Unchecked'
+        else:
+            subjectAlignment += 'No alignment update'
+            textAlignment += 'No Rich' + str(self.whichRich) + ' alignment update needed for fill ' + str(FillAlignment) + '. The DB alignment is still ' + vN_DB_str + '.'            
+
+        command = 'elog -h "'
+        command += str(host)
+        command += '" -p '
+        command += str(port)
+        command += ' -l "'
+        command += str(logbookAlignment)
+        command += '" -u '
+        command += str(username)
+        command += ' -a "Author='
+        command += str(authorAlignment)
+        command += '" -a "System='
+        command += str(activityAlignment)
+        command += '" -a "Subject='
+        command += str(subjectAlignment)
+        command += '" -a "Type='
+        command += str(TypeAlignment)
+        command += '" -a "Fill='
+        command += str(FillAlignment)
+        command += '" -a "Status='
+        command += str(StatusAlignment)
+        command += '" "'
+        command += str(text)
+        command += '"'
+        
+        if DBUpdated or DBUpdated is None:
+            if os.path.exists(AlignMonitorFile):
+                command += ' -f "{0}"'.format(AlignMonitorFile)
+        cmd = shlex.split(command)
         FNULL = open(os.devnull, 'w')
         subprocess.call(cmd, stdout=FNULL, stderr=subprocess.STDOUT)
-
+        
+        # Email
         subj2 = ''
-        if self.alignConf.getProp('testing') is True:
-            subj2 += 'TEST [' + self.alignConf.getProp('dataVariant') + ']: '        
+        if self.testing is True:
+            subj2 += 'TEST [' + self.dataVariant + ']: '        
         text2 = "The Mirror "
         text2 += str(activity)
         text2 += " for RICH"
@@ -204,18 +276,21 @@ class SetupHelper:
         text2 += " events per iteration were processed. "
         text2 += str(n_it + 1)
         text2 += " iteration(s) occured. \n"
-        if DBUpdated:
-            text2 += "\n Due to a significant change from the alignment in the DB, or a change in magnet polarity, the DB was automatically updated. \n" # We should probably provide more info here
         if DBUpdated is None:
-            text2 += "\n There was a significant change from the alignment in the DB, or a change in magnet polarity. However the automatic update feature is off (or was disabled during the alignment), so the DB was not updated. Please notify a MirrAlign expert to investigate whether this alignment should be installed. \n" # We should probably provide more info here
+            text2 += "\n There was a significant change from the alignment in the DB, or a change in magnet polarity. However the automatic update feature is off, or was disabled during the alignment, so the DB was not updated. If the automatic update feature was disabled, there may not have been enough events processed, or a sanity check was not satisfied. A MirrAlign expert should investigate whether this draft alignment (" + vN_DB_str + ") should be installed. \n" # We should probably provide more info here
+        elif DBUpdated:
+            text2 += "\n Due to a significant change from the alignment in the DB, or a change in magnet polarity, the DB was automatically updated to " + vN_DB_str + ". \n" # We should probably provide more info here
+        else:
+            text2 += "\n The alignment in the DB is still " + vN_DB_str + "."   
+            
         text2 += "\n More information is available at the following link: \n\n "
         text2 += 'https://lblogbook.cern.ch/RICH/?System=%5EAlignment%24&Subject={0}&mode=full'.format(self.directoryTime)
         
         self.sendEmail(subj2, text2, self.emails)
   
-        return 0
+        return messageID
 
-    def writeSummary(self, conv, n_it, farm_config_time, elapsed_runtimes, summaryFile, DBUpdated, nEvents, nEventsList):
+    def writeSummary(self, vN_DB_str, conv, n_it, farm_config_time, elapsed_runtimes, summaryFile, DBUpdated, nEvents, nEventsList):
         hh, r = divmod(farm_config_time, 3600)
         mm, ss = divmod(r, 60)
         farm_config_time_str = "{:0>2}:{:0>2}:{:05.2f}".format(int(hh),int(mm),ss)
@@ -255,13 +330,14 @@ class SetupHelper:
         args += 'DB updated              = ' + str(DBUpdated) + '\n'
         if DBUpdated is None:
             args += '                          (Alignment changed, but autoUpdate is False or was disabled) \n '
+        args += 'resulting DB            = ' + str(vN_DB_str) + '\n'
         args += 'converged               = ' + str(conv) + '\n'
         args += 'Number of iterations    = ' + str(n_it + 1) + '\n'
         args += 'Number of events        = ' + str(nEvents) + '\n'
         args += 'runs                    = ' + runsString + '\n'
         args += 'fills                   = ' + fillsString + '\n'
         args += 'polarities              = ' + polaritiesString + '\n'
-        args += 'dataVariant             = ' + str(self.alignConf.getProp('dataVariant')) + '\n'
+        args += 'dataVariant             = ' + str(self.dataVariant) + '\n'
         args += 'magnFactorsMode         = ' + str(self.magnFactorsMode) + '\n'
         args += 'savedir                 = ' + self.savedir + '\n'
         print "INFO: LHCbA config time (readable): " + farm_config_time_str
@@ -272,7 +348,7 @@ class SetupHelper:
         args += '\n'
         args += 'Final iteration label   = ' + 'i' + str(n_it) + '\n'
         args += 'autoUpdate              = ' + str(self.autoUpdate) + '\n'
-        args += 'testing                 = ' + str(self.alignConf.getProp('testing')) + '\n'
+        args += 'testing                 = ' + str(self.testing) + '\n'
         args += 'requiredEvents          = ' + str(self.alignConf.getProp('requiredEvents')) + '\n'
         args += 'magnifDir               = ' + str(self.magnifDir) + '\n'
         args += 'minAverageBinPop        = ' + str(self.minAverageBinPop) + '\n'
@@ -379,7 +455,7 @@ class SetupHelper:
         nEvents = int( round( float(sum(nEventsList)) / float(n_it + 1) ) ) # If mag factors float, this only reports for the data with untilted XML
         return [nEventsList , nEvents]
 
-    def quickWriteInLogbook(self, subjectB, textB):
+    def quickWriteInLogbook(self, subject, text, edit = None):
         host = 'lblogbook.cern.ch' 
         port = 8080
         username = 'common Common\\!'
@@ -388,23 +464,7 @@ class SetupHelper:
         activity = 'Alignment'
         instruction_file = 'https://twiki.cern.ch/twiki/bin/view/LHCb/LHCbRichMirrorAlignShiftInfo'
 
-        if subjectB is None:
-            subjectB = ''            
-        subject  = ''
-        if self.alignConf.getProp('testing') is True:
-            subject += 'TEST [' + self.alignConf.getProp('dataVariant') + ']: '
-        subject += 'RICH' + str(self.whichRich) + ' alignment ' + subjectB
-
-        if textB is None:
-            textB = ''
-        text  = ''
-        text += "The Mirror "
-        text += str(activity)
-        text += " for RICH"
-        text += str(self.whichRich)
-        text += "is reporting "
-        text += textB
-        text += " Shifter's instructions can be found at "
+        text += " \n Shifter's instructions can be found at "
         text += str(instruction_file)
         text += "."
         
@@ -412,6 +472,10 @@ class SetupHelper:
         command += str(host)
         command += '" -p '
         command += str(port)
+        try:
+            command += ' -e ' + str(int(edit))
+        except:
+            pass
         command += ' -l "'
         command += str(logbook)
         command += '" -u '
@@ -419,7 +483,7 @@ class SetupHelper:
         command += ' -a "Author='
         command += str(author)
         #command += '" -a "System='
-        command += '" -a "System_19='
+        command += '" -a "System_19=' # Change 19 if Alignment changes its order in the ELOG (ask the current RICH expert)
         command += str(activity)
         command += '" -a "Subject='
         command += str(subject)
@@ -427,8 +491,12 @@ class SetupHelper:
         command += str(text)
         command += '"'
         cmd = shlex.split(command)
-        FNULL = open(os.devnull, 'w')
-        subprocess.call(cmd, stdout=FNULL, stderr=subprocess.STDOUT)
+        try:
+            elogret = subprocess.check_output(cmd, stderr=subprocess.STDOUT)
+            messageID = int(re.search('.*Message successfully transmitted, ID=(\d*)', elogret).groups()[0])
+        except:
+            messageID = None
   
-        return 0
+        return messageID
+    
     
\ No newline at end of file
diff --git a/Rich/RichMirrorAlignmentOnline/python/PyMirrAlignOnline/XMLFileHelper.py b/Rich/RichMirrorAlignmentOnline/python/PyMirrAlignOnline/XMLFileHelper.py
index 16d8ebd655b8211a7432598b990edb8f672ca93f..aacf3cd8db340d7a6829d65b48018af70f31cee5 100644
--- a/Rich/RichMirrorAlignmentOnline/python/PyMirrAlignOnline/XMLFileHelper.py
+++ b/Rich/RichMirrorAlignmentOnline/python/PyMirrAlignOnline/XMLFileHelper.py
@@ -126,7 +126,7 @@ class XMLFileHelper:
                     outfile.write(line)
                 outfile.write('</DDDB> \n')
 
-    def finalXML(self, N_DB_str, Update):
+    def finalXML(self, vN_DB_str, Update):
         workdir = self.alignConf.getProp('WorkDir')
         
         finalXML = workdir + "CondDB_Update_Rich" + str(self.whichRich) + ".xml"
@@ -140,7 +140,7 @@ class XMLFileHelper:
                     if "<?xml version=\'1.0\' encoding=\'iso-8859-1\'?>" not in line and '<!DOCTYPE DDDB SYSTEM "conddb:/DTD/structure.dtd">' not in line and '<DDDB>' not in line and '</DDDB>' not in line:
                         outfile.write(line)
         if Update:
-            latest = 'v' + N_DB_str + '.xml'
+            latest = vN_DB_str + '.xml'
             latest = os.path.join(self.base_dir, latest)
             shutil.copyfile(finalXML, latest)
     
diff --git a/Rich/RichMirrorAlignmentOnline/python/PyMirrAlignOnline/tiltObj.py b/Rich/RichMirrorAlignmentOnline/python/PyMirrAlignOnline/tiltObj.py
index 10ad3be8169e48d4b831410cb23555f65e47df20..a613ee50fd11c55bd74e446eb441d55e31a7f570 100644
--- a/Rich/RichMirrorAlignmentOnline/python/PyMirrAlignOnline/tiltObj.py
+++ b/Rich/RichMirrorAlignmentOnline/python/PyMirrAlignOnline/tiltObj.py
@@ -159,7 +159,7 @@ class tiltObj:
         return biggestTilt
     
     def setTrunc(self, digits = 2):
-        # must be done after a setChange(files)
+        # can only be done *after* a setChange(files)
         # truncated-not-rounded-version of the mirror compensations already stored in self.priY, self.priZ, etc...
         import math
         if int(digits) < 0:
@@ -167,35 +167,35 @@ class tiltObj:
         divisor = float(math.pow(10, int(digits)))
         for pY in self.priY.keys():
             if not abs(self.priY[pY]) < math.pow(10, int(0-digits)):
-                self.priYtrunc[pY] = math.floor(self.priY[pY]*divisor)/divisor if self.priY[pY] >= 0. else math.ceil(self.priY[pY]*divisor)/divisor
+                self.priYtrunc[pY] = math.floor(self.priY[pY]*divisor)/divisor + 0.0000001 if self.priY[pY] >= 0. else math.ceil(self.priY[pY]*divisor)/divisor - 0.0000001
             elif self.priY[pY] >= 0:
                 self.priYtrunc[pY] = 0.0000001
             else:
                 self.priYtrunc[pY] = -0.0000001               
         for pZ in self.priZ.keys():
             if not abs(self.priZ[pZ]) < math.pow(10, int(0-digits)):
-                self.priZtrunc[pZ] = math.floor(self.priZ[pZ]*divisor)/divisor if self.priZ[pZ] >= 0. else math.ceil(self.priZ[pZ]*divisor)/divisor
+                self.priZtrunc[pZ] = math.floor(self.priZ[pZ]*divisor)/divisor + 0.0000001 if self.priZ[pZ] >= 0. else math.ceil(self.priZ[pZ]*divisor)/divisor - 0.0000001
             elif self.priZ[pZ] >= 0:
                 self.priZtrunc[pZ] = 0.0000001
             else:
                 self.priZtrunc[pZ] = -0.0000001     
         for sY in self.secY.keys():
             if not abs(self.secY[sY]) < math.pow(10, int(0-digits)):
-                self.secYtrunc[sY] = math.floor(self.secY[sY]*divisor)/divisor if self.secY[sY] >= 0. else math.ceil(self.secY[sY]*divisor)/divisor
+                self.secYtrunc[sY] = math.floor(self.secY[sY]*divisor)/divisor + 0.0000001 if self.secY[sY] >= 0. else math.ceil(self.secY[sY]*divisor)/divisor - 0.0000001
             elif self.secY[sY] >= 0:
                 self.secYtrunc[sY] = 0.0000001
             else:
                 self.secYtrunc[sY] = -0.0000001        
         for sZ in self.secZ.keys():
             if not abs(self.secZ[sZ]) < math.pow(10, int(0-digits)):
-                self.secZtrunc[sZ] = math.floor(self.secZ[sZ]*divisor)/divisor if self.secZ[sZ] >= 0. else math.ceil(self.secZ[sZ]*divisor)/divisor
+                self.secZtrunc[sZ] = math.floor(self.secZ[sZ]*divisor)/divisor + 0.0000001 if self.secZ[sZ] >= 0. else math.ceil(self.secZ[sZ]*divisor)/divisor - 0.0000001
             elif self.secZ[sZ] >= 0:
                 self.secZtrunc[sZ] = 0.0000001
             else:
                 self.secZtrunc[sZ] = -0.0000001        
                 
     def setDiv(self, digits = 0, tolerances = None): # [pYtol,pZtol,sYtol,sZtol]
-        # must be done after a setChange(files)
+        # can only be done *after* a setChange(files)
         # truncated-not-rounded-version of the mirror compensations, already stored in self.priY, self.priZ, etc..., divided by the tolerances
         # NOTE: If digits = 0, values within the tolerances will all show up as "-0" or "0"
         import math
@@ -207,28 +207,28 @@ class tiltObj:
             tolerances = [0.1,0.1,0.1,0.1]
         for pY in self.priY.keys():
             if not abs(self.priY[pY]/tolerances[0]) < math.pow(10, int(0-digits)):
-                self.priYdiv[pY] = math.floor(self.priY[pY]/tolerances[0]*divisor)/divisor if self.priY[pY] >= 0. else math.ceil(self.priY[pY]/tolerances[0]*divisor)/divisor
+                self.priYdiv[pY] = math.floor(self.priY[pY]/tolerances[0]*divisor)/divisor + 0.0000001 if self.priY[pY] >= 0. else math.ceil(self.priY[pY]/tolerances[0]*divisor)/divisor - 0.0000001 
             elif self.priY[pY] >= 0:
                 self.priYdiv[pY] = 0.0000001
             else:
                 self.priYdiv[pY] = -0.0000001    
         for pZ in self.priZ.keys():
             if not abs(self.priZ[pZ]/tolerances[1]) < math.pow(10, int(0-digits)):
-                self.priZdiv[pZ] = math.floor(self.priZ[pZ]/tolerances[1]*divisor)/divisor if self.priZ[pZ] >= 0. else math.ceil(self.priZ[pZ]/tolerances[1]*divisor)/divisor
+                self.priZdiv[pZ] = math.floor(self.priZ[pZ]/tolerances[1]*divisor)/divisor + 0.0000001 if self.priZ[pZ] >= 0. else math.ceil(self.priZ[pZ]/tolerances[1]*divisor)/divisor - 0.0000001 
             elif self.priZ[pZ] >= 0:
                 self.priZdiv[pZ] = 0.0000001
             else:
                 self.priZdiv[pZ] = -0.0000001   
         for sY in self.secY.keys():
             if not abs(self.secY[sY]/tolerances[2]) < math.pow(10, int(0-digits)):
-                self.secYdiv[sY] = math.floor(self.secY[sY]/tolerances[2]*divisor)/divisor if self.secY[sY] >= 0. else math.ceil(self.secY[sY]/tolerances[2]*divisor)/divisor
+                self.secYdiv[sY] = math.floor(self.secY[sY]/tolerances[2]*divisor)/divisor + 0.0000001 if self.secY[sY] >= 0. else math.ceil(self.secY[sY]/tolerances[2]*divisor)/divisor - 0.0000001 
             elif self.secY[sY] >= 0:
                 self.secYdiv[sY] = 0.0000001
             else:
                 self.secYdiv[sY] = -0.0000001  
         for sZ in self.secZ.keys():
             if not abs(self.secZ[sZ]/tolerances[3]) < math.pow(10, int(0-digits)):
-                self.secZdiv[sZ] = math.floor(self.secZ[sZ]/tolerances[3]*divisor)/divisor if self.secZ[sZ] >= 0. else math.ceil(self.secZ[sZ]/tolerances[3]*divisor)/divisor
+                self.secZdiv[sZ] = math.floor(self.secZ[sZ]/tolerances[3]*divisor)/divisor + 0.0000001 if self.secZ[sZ] >= 0. else math.ceil(self.secZ[sZ]/tolerances[3]*divisor)/divisor - 0.0000001 
             elif self.secZ[sZ] >= 0:
                 self.secZdiv[sZ] = 0.0000001
             else:
diff --git a/Rich/RichMirrorAlignmentOnline/python/RichMirrorAlignmentOnline/Configuration.py b/Rich/RichMirrorAlignmentOnline/python/RichMirrorAlignmentOnline/Configuration.py
index b5c2b9ec26207857cd8be37407749e2773dbb70b..1e36f0e5d5ddfe3574084955d0fe1019f484a2c9 100644
--- a/Rich/RichMirrorAlignmentOnline/python/RichMirrorAlignmentOnline/Configuration.py
+++ b/Rich/RichMirrorAlignmentOnline/python/RichMirrorAlignmentOnline/Configuration.py
@@ -3,6 +3,9 @@
 # @date   08/07/2015
 __authors__  = "Claire Prouve <Claire.Prouve@cern.ch>, Paras Naik <Paras.Naik@cern.ch>"
 
+### The Configurables below can be picked up and used by RichMirrorAlignmentOnline
+### The Configurables below can also be sent by RichMirrorAlignmentOnline to RichMirrCombinFit and RichMirrAlign
+
 ### NOTE: these are not installed yet, but they exist and can be provided to MirrCombinFit if deemed necessary:
 # ("sinusoidShift"       , po::value<double>(& m_sinusoidShift         )->default_value( 0.0 ), "shift parameter in fitting formula; if fixSinusoidShift !=0, it is fixed at this value; othrewise this is just initial value"    )
 # ("zeroGlobalFitMean"   , po::value<int   >(& m_zeroGlobalFitMean     )->default_value( 0   ), "default =0 : \"mean\" in global fit is not fixed; if !=0 it is fixed at zero"                                                    )
@@ -10,10 +13,9 @@ __authors__  = "Claire Prouve <Claire.Prouve@cern.ch>, Paras Naik <Paras.Naik@ce
 # ("combAndMirrSubsets"  , po::value<string>(& m_combAndMirrSubsetsFile)                      , "File with chosen mirrors and combinations subsets"                                                                               )
 # ("backgroundOrder"     , po::value<int   >(& m_backgroundOrder       )->default_value( 2   ), "order for the polynomial background"                                                                                             )
 # ("plotOutputLevel"     , po::value<int   >(& m_plotOutputLevel       )->default_value( 2   ), "what plots should be saved (0) plot nothing (1) plot ...(2) only plot fits with chi2 worse than 3.0 (3) plot everything"         )
-# ("warningFactor"       , po::value<double>(& m_warningFactor         )->default_value( 20  ), "alerts the alignment shifter if any of the mirrors have shifted more than warningFactor*stopTolerance"                           )
 ### NOTE: these are not installed yet, but they exist and can be provided to RichMirrAlign if deemed necessary:
-# ("combAndMirrSubsets"  , po::value<string>(&combAndMirrSubsetsFile  )->default_value( ""         ), "file with subsets of mirror combinations and mirrors"                                                        )
-# ("usePremisaligned"    , po::bool_switch  (&usePremisaligned        )->default_value( false, "no"), "if true, then pre-misaligned xml files will be used (MC case), default=false"                                )
+# ("combAndMirrSubsets"  , po::value<string>(&combAndMirrSubsetsFile   )->default_value( ""         ), "file with subsets of mirror combinations and mirrors"                                                                     )
+# ("usePremisaligned"    , po::bool_switch  (&usePremisaligned         )->default_value( false, "no"), "if true, then pre-misaligned xml files will be used (MC case), default=false"                                             )
 
 #===============================================================================
 # regularizationMode has changed from 1 (used in 2016) to 0 (used in 2017). 
@@ -33,7 +35,6 @@ __authors__  = "Claire Prouve <Claire.Prouve@cern.ch>, Paras Naik <Paras.Naik@ce
 # In light of this, the RICH2 tolerances for 2017 should be set to: [0.032, 0.030, 0.043, 0.057] mrad
 #===============================================================================
 
-
 import os
 from Gaudi.Configuration  import *
 import GaudiKernel.ProcessJobOptions
@@ -42,12 +43,12 @@ from Configurables import (LHCbConfigurableUser)
 class Rich1MirrAlignOnConf(LHCbConfigurableUser):
     __used_configurables__ = [ ]
     __slots__ = {
-       #### Only change these if you want to pick up from where you left off in iterations, experts only
-        "MajItStart"             : 0
-       ,"MinItStart"             : 0
        #### Do not change these!!! Just DON'T!
-       ,"Rich"                   : 1
+        "Rich"                   : 1
        ,"HistoDir"               : ""
+       #### Only change these if you want to pick up from where you left off in iterations, experts only
+       ,"MajItStart"             : 0
+       ,"MinItStart"             : 0
        ### Better not change these, only for very very VERY good reasons
        ,"WorkDir"                : "/group/online/AligWork/Rich1/"
        ,"SaveDir"                : "/group/online/AligWork/MirrorAlignments/"
@@ -78,10 +79,12 @@ class Rich1MirrAlignOnConf(LHCbConfigurableUser):
        ,"stopTolerancePriZ"      : 0.03
        ,"stopToleranceSecY"      : 0.46
        ,"stopToleranceSecZ"      : 0.37
+       ,"warningFactor"          : 3
        ,"EvtMax"                 : -1
        ,"dataVariant"            : "Collision17"
        ,"fixSinusoidShift"       : 1
        ,"nameStr"                : ""
+       ,"displayMode"            : 1
         }
 
     _propertyDocDct = {
@@ -116,10 +119,12 @@ class Rich1MirrAlignOnConf(LHCbConfigurableUser):
        ,"stopTolerancePriZ"      : """ RICH-dependent tolerance for primary   mirrors rotation around Z correction in mrad to stop the alignment """
        ,"stopToleranceSecY"      : """ RICH-dependent tolerance for secondary mirrors rotation around Y correction in mrad to stop the alignment """
        ,"stopToleranceSecZ"      : """ RICH-dependent tolerance for secondary mirrors rotation around Z correction in mrad to stop the alignment """
+       ,"warningFactor"          : """ alerts the alignment if any of the mirrors have shifted more than warningFactor times a particular mirror rotation stopTolerance """
        ,"EvtMax"                 : """ maximal number of events processed by brunel PER NODE (hlt farm has ~1500 nodes), -1 = infinite """
        ,"dataVariant"            : """ Helps us decide which Brunel options to use; also used for the naming convention. """
        ,"fixSinusoidShift"       : """ 1 : fix at sinusoidShift; 0 : it is not fixed """
        ,"nameStr"                : """ Right now this is used only for the naming convention, but will be set when initiating the Configuration. """
+       ,"displayMode"            : """ 1 : Current TH2D display style (auto-scaling Z-axis, granular colors, using same colors for > 4*threshold); 0: Anatoly's development TH2D display style (similar, but with printed mirror number also, and fixed scale)"""
         }
 
     def setNameStr(self):
@@ -172,12 +177,12 @@ class Rich2MirrAlignOnConf(LHCbConfigurableUser):
     __used_configurables__ = [ ]
 
     __slots__ = {
-       #### Only change these if you want to pick up from where you left off in iterations, experts only
-        "MajItStart"             : 0
-       ,"MinItStart"             : 0
        #### Do not ever change these!!! Just DONT!
-       ,"Rich"                   : 2
+        "Rich"                   : 2
        ,"HistoDir"               : ""
+       #### Only change these if you want to pick up from where you left off in iterations, experts only
+       ,"MajItStart"             : 0
+       ,"MinItStart"             : 0
        ### Better not change these, only for very very VERY good reasons
        ,"WorkDir"                : "/group/online/AligWork/Rich2/"
        ,"SaveDir"                : "/group/online/AligWork/MirrorAlignments/"
@@ -208,10 +213,12 @@ class Rich2MirrAlignOnConf(LHCbConfigurableUser):
        ,"stopTolerancePriZ"      : 0.03
        ,"stopToleranceSecY"      : 0.05
        ,"stopToleranceSecZ"      : 0.06
+       ,"warningFactor"          : 3
        ,"EvtMax"                 : -1
        ,"dataVariant"            : "Collision17"
        ,"fixSinusoidShift"       : 1
        ,"nameStr"                : ""
+       ,"displayMode"            : 1
         }
 
     _propertyDocDct = {
@@ -246,10 +253,12 @@ class Rich2MirrAlignOnConf(LHCbConfigurableUser):
        ,"stopTolerancePriZ"      : """ RICH-dependent tolerance for primary   mirrors rotation around Z correction in mrad to stop the alignment """
        ,"stopToleranceSecY"      : """ RICH-dependent tolerance for secondary mirrors rotation around Y correction in mrad to stop the alignment """
        ,"stopToleranceSecZ"      : """ RICH-dependent tolerance for secondary mirrors rotation around Z correction in mrad to stop the alignment """
+       ,"warningFactor"          : """ alerts the alignment if any of the mirrors have shifted more than warningFactor times a particular mirror rotation stopTolerance """
        ,"EvtMax"          	     : """ maximal number of events processed by brunel PER NODE (hlt farm has ~1500 nodes), -1 = infinite """
        ,"dataVariant"            : """ Helps us decide which Brunel options to use; also used for the naming convention. """
        ,"fixSinusoidShift"       : """ 1 : fix at sinusoidShift; 0 : it is not fixed """
        ,"nameStr"                : """ Right now this is used only for the naming convention, but will be set when initiating the Configuration. """
+       ,"displayMode"            : """ 1 : Current TH2D display style (auto-scaling Z-axis, granular colors, using same colors for > 4*threshold); 0: Anatoly's development TH2D display style (similar, but with printed mirror number also, and fixed scale)"""
         }
 
     ### Dont mess with this filename!!!