diff --git a/Trigger/TrigConfiguration/TrigConfMuctpi/doc/TopoCellCenters2016.pdf b/Trigger/TrigConfiguration/TrigConfMuctpi/doc/TopoCellCenters2016.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..034660f08c98004de5b0c9623c6f3619a59b376d
Binary files /dev/null and b/Trigger/TrigConfiguration/TrigConfMuctpi/doc/TopoCellCenters2016.pdf differ
diff --git a/Trigger/TrigConfiguration/TrigConfMuctpi/doc/TopoCodes2016.pdf b/Trigger/TrigConfiguration/TrigConfMuctpi/doc/TopoCodes2016.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..91723f3e9e1421cdf8017d1cf247088831139f49
Binary files /dev/null and b/Trigger/TrigConfiguration/TrigConfMuctpi/doc/TopoCodes2016.pdf differ
diff --git a/Trigger/TrigConfiguration/TrigConfMuctpi/doc/TopoLayout2016.pdf b/Trigger/TrigConfiguration/TrigConfMuctpi/doc/TopoLayout2016.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..4889a9274fd6b2d1da80ee6922b7d21c55b2905e
Binary files /dev/null and b/Trigger/TrigConfiguration/TrigConfMuctpi/doc/TopoLayout2016.pdf differ
diff --git a/Trigger/TrigConfiguration/TrigConfMuctpi/doc/TopoLayout2016Eta.pdf b/Trigger/TrigConfiguration/TrigConfMuctpi/doc/TopoLayout2016Eta.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..7758158c7c2531cd8d9c43baed009a8676c1666d
Binary files /dev/null and b/Trigger/TrigConfiguration/TrigConfMuctpi/doc/TopoLayout2016Eta.pdf differ
diff --git a/Trigger/TrigConfiguration/TrigConfMuctpi/doc/TopoLayout2016Phi.pdf b/Trigger/TrigConfiguration/TrigConfMuctpi/doc/TopoLayout2016Phi.pdf
new file mode 100644
index 0000000000000000000000000000000000000000..c11cbad91c617f881e8e665ee849d818ac10c510
Binary files /dev/null and b/Trigger/TrigConfiguration/TrigConfMuctpi/doc/TopoLayout2016Phi.pdf differ
diff --git a/Trigger/TrigConfiguration/TrigConfMuctpi/python/Utils.py b/Trigger/TrigConfiguration/TrigConfMuctpi/python/Utils.py
index 703ea4c77cabc45584d1cc5eb6a84619acd1d643..80e879ad269b227befd025b249dac8472978adde 100644
--- a/Trigger/TrigConfiguration/TrigConfMuctpi/python/Utils.py
+++ b/Trigger/TrigConfiguration/TrigConfMuctpi/python/Utils.py
@@ -3,12 +3,12 @@
 import logging
 
 from PyUtils.Decorators import memoize
-from os.path import exists
+from os.path import exists, join, abspath
 
 
 @memoize
-def getLogger():
-    logger = logging.getLogger(__name__)
+def getLogger(name):
+    logger = logging.getLogger(name)
     logger.setLevel(logging.DEBUG)
 
     # create console handler and set level to debug
@@ -37,12 +37,12 @@ def findFileInXMLPATH(filename):
 
     filename = str(filename)
 
-    mlog = getLogger()
-    mlog.debug("Searching XML file %s" % filename)
+    mlog = getLogger(__name__)
+    mlog.debug("Searching for XML file %s" % filename)
     if filename.find('./') is 0: ## this expected to be local file, name starts from ./
         return filename
     else:
-        mlog.debug("Nonlocal XML config file")
+        mlog.debug("XML file is not in local directory")
         from os import environ
         ## even if ./ not as file name prefix look first in PWD
         if exists(filename):
@@ -55,7 +55,7 @@ def findFileInXMLPATH(filename):
             return filename
 
         xmlpath = environ['XMLPATH']
-        paths = split(xmlpath, ":")
+        paths = str.split(xmlpath, ":")
         for path in paths:
 
             test = join(path, filename)
diff --git a/Trigger/TrigConfiguration/TrigConfMuctpi/python/XMLReader.py b/Trigger/TrigConfiguration/TrigConfMuctpi/python/XMLReader.py
index ebadfe3cb2e2c7466a98721bd8de42b1dacf45c1..a330a7dbd8711005308afe843e4ed0ccd00da6f2 100644
--- a/Trigger/TrigConfiguration/TrigConfMuctpi/python/XMLReader.py
+++ b/Trigger/TrigConfiguration/TrigConfMuctpi/python/XMLReader.py
@@ -12,7 +12,7 @@ class TrigXMLElement:
         self.children = element.getchildren()
         self.readchildren()
     def __str__(self):
-        s = "<%s %s>" % (self.tag, " ".join(['%s="%s"' % x for x in self.items]))
+        s = "<%s%s>" % (" ".join([self.tag] + ['%s="%s"' % x for x in self.items]), "/" if len(self.children)==0 else "")
         return s
     def __repr__(self):
         return self.tag
@@ -22,7 +22,7 @@ class TrigXMLElement:
 
     def __getitem__(self,k):
         return dict(self.items)[k]
-
+    
     def strippedText(self):
         return self.element.text.strip()
 
@@ -37,16 +37,23 @@ class TrigXMLElement:
             if len(self._childtagdict[t])==1:
                 self.__dict__['%s'%t] = self._childtagdict[t][0]
 
+
+
 class TrigXMLDocumentReader(object):
     def __init__(self,filename):
         self.filename=filename
         from TrigConfMuctpi.Utils import findFileInXMLPATH
-        self.read(findFileInXMLPATH(filename))
+        self.fullFileName = findFileInXMLPATH(filename)
+        self.read(self.fullFileName)
+
     def read(self,filename):
         self.doc = ET.parse(filename)
         root = TrigXMLElement(self.doc.getroot())
         self.__dict__[root.tag] = root
 
+    def getFileName(self):
+        return self.fullFileName
+
 
 class MioctGeometryXMLReader(TrigXMLDocumentReader):
     def __init__(self,filename):
diff --git a/Trigger/TrigConfiguration/TrigConfMuctpi/scripts/ReadRPCRun2DataFile.py b/Trigger/TrigConfiguration/TrigConfMuctpi/scripts/ReadRPCRun2DataFile.py
new file mode 100755
index 0000000000000000000000000000000000000000..3c06884998890d664ab59c906e4cecb0eb6c4181
--- /dev/null
+++ b/Trigger/TrigConfiguration/TrigConfMuctpi/scripts/ReadRPCRun2DataFile.py
@@ -0,0 +1,566 @@
+#!/usr/bin/env python
+
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+import sys, time, os, re, argparse
+from itertools import groupby
+from operator import attrgetter, itemgetter
+from TrigConfMuctpi.XMLReader import MioctGeometryXMLReader
+from math import copysign, pi as PI
+from TrigConfMuctpi.Utils import getLogger
+from copy import copy
+
+# since this reads the geometry data from the .dat file and the 2015 geometry xml
+# it is best to define a new (small) class hierarchy to hold this data
+class ROI(object):
+    def __init__( self, eta=0, phi=0, phimin=0, phimax=0, etamin=0, etamax=0,
+                  etacode=0, phicode=0, roiid=0 ):
+        self.eta = eta
+        self.phi = phi
+        self.phimin = phimin
+        self.phimax = phimax
+        self.etamin = etamin
+        self.etamax = etamax
+        self.etacode = etacode
+        self.phicode = phicode
+        self.roiid = roiid
+
+    @classmethod
+    def fromROIelement(cls,roi):
+        newroi = cls( eta=float(roi['eta']), phi=float(roi['phi']), phimin=float(roi['phimin']), phimax=float(roi['phimax']), etamin=float(roi['etamin']), etamax=float(roi['etamax']),
+                      etacode=int(roi['etacode'],16), phicode=int(roi['phicode'],16), roiid=int(roi['roiid']))
+        return newroi
+    def asXML(self,depth):
+        s = ' ' * depth + '<ROI eta="%f" phi="%f" etacode="0x%s" phicode="0x%s" etamin="%f" etamax="%f" phimin="%f" phimax="%f" roiid="%i"/>\n' % (self.eta, self.phi, self.etacode, self.phicode, self.etamin, self.etamax, self.phimin, self.phimax, self.roiid )
+        return s
+    def getStats(self,stats):
+        pass
+
+
+class Sector(object):
+    def __init__(self, name, connector, rois=[]):
+        self.name = name
+        self.connector = connector
+        self.id = int(name.lstrip('BECFA'))
+        self.rois = copy(rois)
+    def addROI(self,roi):
+        self.rois += [ roi ]
+    def isBarrel(self):
+        return self.name.startswith('B')
+    def getStats(self,stats):
+        stats['rois'] += len(self.rois)
+        for roi in self.rois:
+            roi.getStats(stats)
+    def asXML(self, depth):
+        s  = ' '*depth + '<Sector connector="%s" name="%s">\n' % (self.connector, self.name)
+        s += ' '*depth + '    <!-- contains %i ROIs -->\n' % len(self.rois)
+        s += ' '*depth + '    <!-- mapping from ROI to coding scheme -->\n'
+        for roi in sorted(self.rois, key=lambda roi: int(roi.roiid)):
+            s += roi.asXML(depth + 4 )
+        s += ' '*depth + "</Sector>\n"
+        return s
+
+
+class TopoCell(object):
+    def __init__(self, etacode, phicode, eta, phi, ieta, iphi, etamin, etamax , phimin, phimax):
+        self.etacode = etacode
+        self.phicode = phicode
+        self.eta     = eta    
+        self.phi     = phi    
+        self.ieta    = ieta   
+        self.iphi    = iphi   
+        self.etamin  = etamin 
+        self.etamax  = etamax 
+        self.phimin  = phimin 
+        self.phimax  = phimax 
+
+    @classmethod
+    def fromTopoCellElement(cls,tc):
+        newtc = cls( etacode=int(tc['etacode'],16), phicode=int(tc['phicode'],16),
+                     eta=float(tc['eta']), phi=float(tc['phi']),
+                     ieta=float(tc['ieta']), iphi=float(tc['iphi']),
+                     etamin=float(tc['etamin']), etamax=float(tc['etamax']), phimin=float(tc['phimin']), phimax=float(tc['phimax']) )
+        return newtc
+    def asXML(self, depth):
+        return ' '*depth + '<TopoCell etacode="0x%s" phicode="0x%s" eta="%f" phi="%f" ieta="%i" iphi="%i" etamin="%f" etamax="%f" phimin="%f" phimax="%f"/>\n' % (self.etacode, self.phicode,
+                                                                                                                                                                  self.eta, self.phi,
+                                                                                                                                                                  self.ieta, self.iphi,
+                                                                                                                                                                  self.etamin, self.etamax, self.phimin, self.phimax)
+
+
+class Decodes(object):
+    def __init__(self, topocells=[]):
+        self.topocells = copy(topocells)
+
+    @classmethod
+    def fromAllRois(cls,allrois):
+        newDecodes = cls()
+        for (etacode,phicode), roisInCell in groupby( sorted(allrois, key=attrgetter('etacode','phicode')), key=attrgetter('etacode','phicode')):
+            # make a new cell
+            (eta, phi, ieta, iphi, etamin, etamax, phimin, phimax) = cls.getTopoCellPosition(etacode, phicode, roisInCell)
+            newDecodes.addTopoCell( TopoCell(etacode=etacode, phicode=phicode, eta=eta, phi=phi, ieta=ieta, iphi=iphi, etamin=etamin, etamax=etamax, phimin=phimin, phimax=phimax) )
+        return newDecodes
+
+    @classmethod
+    def getTopoCellPosition(cls, etacode, phicode, rois):
+        rois = list(rois)
+
+        # ETA
+
+        # eta min and max are different in the RPC (barrel) and TGC (endcap and forward)
+        # in the RPC: abs(etamin)<abs(etamax)
+        # in the TGC: etamin<etamax
+        # we are going to use the TGC definition: etamin<etamax
+
+        cellsEta = [(min(e.etamin,e.etamax), max(e.etamin,e.etamax)) for e in rois]
+        etamins, etamaxs = zip(*cellsEta)  # transpose
+        etamin = min( [ min(e.etamin,e.etamax) for e in rois] )
+        etamax = max( [ max(e.etamin,e.etamax) for e in rois] )
+        eta = (etamin+etamax)/2
+
+
+        # PHI CONVENTION
+        cellsPhi = [(e.phimin, e.phimax) for e in rois]
+
+        # check if there are cells on both sides of the PI boundary
+        upperedge = any([e.phi>6.2 for e in rois])
+        loweredge = any([e.phi<0.2 for e in rois])
+        splitTopoCell = upperedge and loweredge
+
+
+        if splitTopoCell:
+            maxAtLowerEdge = max([e.phimax for e in rois if e.phi<1])
+            minAtUpperEdge = min([e.phimin for e in rois if e.phi>5])
+            centerTopoCell = minAtUpperEdge + maxAtLowerEdge
+            if centerTopoCell>=2*PI: # shift down
+                phimin = minAtUpperEdge - 2 * PI
+                phimax = maxAtLowerEdge
+            else: # shift up
+                phimin = minAtUpperEdge
+                phimax = maxAtLowerEdge + 2 * PI
+            phi = (phimin+phimax)/2
+        else:
+
+            phimins, phimaxs = zip(*cellsPhi)  # transpose
+            phimin = min(phimins)
+            phimax = max(phimaxs)
+            phi = (phimin+phimax)/2
+
+
+        # IETA
+        ieta = round(eta*10)
+        if ieta== 12: ieta= 11
+        if ieta==-12: ieta=-11
+        if ieta== 9: ieta= 8
+        if ieta==-9: ieta=-8
+
+        # IPHI
+        iphi = int(phi*10)
+        if abs(ieta) in [2,5]:
+            if phi>2.05 and phi<2.35: iphi += 1
+            if phi>2.75 and phi<3.25: iphi += 1
+            if phi>3.45: iphi += 1
+
+        if abs(ieta) == 8:
+            if phi>2.05 and phi<2.35: iphi += 1
+            if phi>2.75 and phi<3.25: iphi += 1
+            if phi>3.45 and phi<4.95: iphi += 1
+            if phi>5.05: iphi += 1
+        
+        if abs(ieta) in [15,18]:
+            if phi>2.65: iphi += 1
+
+        if abs(ieta) == 11:
+            if phi>2.15 and phi<2.35: iphi += 1
+            if phi>2.65 and phi<3.25: iphi += 1
+            if phi>3.35: iphi += 1
+        
+        if abs(ieta) == 22:
+            if phi>0.05 and phi<5.35: iphi += 1
+            if phi>5.35: iphi += 2
+
+        return (eta, phi, ieta, iphi, etamin, etamax, phimin, phimax)
+        
+    def addTopoCell(self,topocell):
+        self.topocells += [ topocell ]
+    def getStats(self,stats):
+        stats['decodes'] += 1
+        stats['topocells'] += len(self.topocells)
+    def asXML(self, depth):
+        s = ' '*depth + '<Decode>\n'
+        for tc in self.topocells:
+            s += tc.asXML(depth+4)
+        s += ' '*depth + '</Decode>\n'
+        return s
+
+
+class Mioct(object):
+    def __init__(self, id, slot, sectors=[]):
+        self.id = id
+        self.slot = slot
+        self.sectors = copy(sectors)
+        self.sectordic = dict([ (s.connector, s) for s in sectors ])
+        self.decodes = None
+    def getSector(self,connector):
+        return self.sectordic.get(connector)
+    def addSector(self,sector):
+        if sector.connector in self.sectordic:
+            raise RuntimeError("Sector with connector %i already exists" % sector.connector)
+        self.sectors += [ sector ]
+        self.sectordic[sector.connector] = sector
+        return sector
+    def getStats(self,stats):
+        stats['sectors'] += len(self.sectors)
+        for sector in self.sectors:
+            sector.getStats(stats)
+        if self.decodes:
+            self.decodes.getStats(stats)
+    def asXML(self, depth):
+        sectorNames = [s.name for s in self.sectors]
+        s  = ' '*depth + '<MIOCT id="%s" slot="%i">\n' % (self.id, self.slot)
+        s += ' '*depth + '    <!-- contains sectors %s -->\n' % ", ".join(sorted(sectorNames))
+        for sector in self.sectors:
+            s += sector.asXML(depth + 4)
+        if self.decodes:
+            s += self.decodes.asXML(depth + 4)
+        s += ' '*depth + "</MIOCT>"
+        return s
+    def fillTopoCells( self):
+        # add all ROIs in this MIOCT
+        allROIsInMioct = []
+        for sector in self.sectors:
+            allROIsInMioct += sector.rois
+        self.decodes = Decodes.fromAllRois(allROIsInMioct)
+
+
+class MuonGeometry(object):
+    def __init__(self, name, miocts=[]):
+        self.name = name
+        self.miocts = copy(miocts)
+        self.mioctdic = dict([ (m.id, m) for m in miocts])
+    def getMioct(self,mioctId):
+        return self.mioctdic.get(mioctId)
+    def addMioct(self,mioct):
+        if mioct.id in self.mioctdic:
+            raise RuntimeError("MIOCT with ID %i already exists" % mioct.id)
+        self.miocts += [ mioct ]
+        self.mioctdic[mioct.id] = mioct
+        return mioct
+    def writeXML(self,outfilename):
+        f = open(outfilename,"write")
+        print >> f, '<?xml version="1.0" ?>\n'
+        print >> f, '<!DOCTYPE MuCTPiGeometry SYSTEM "MUCTPIGeometry.dtd">\n'
+        print >> f, '<MuCTPiGeometry>'
+        for mioct in sorted(self.miocts,key=lambda m:m.id):
+            print >> f, mioct.asXML(4)
+        print >> f,'    <PtEncoding>'
+        print >> f,'        <PtCodeElement pt="1" code="0" value="4"/>'
+        print >> f,'        <PtCodeElement pt="2" code="1" value="6"/>'
+        print >> f,'        <PtCodeElement pt="3" code="2" value="10"/>'
+        print >> f,'        <PtCodeElement pt="4" code="2" value="11"/>'
+        print >> f,'        <PtCodeElement pt="5" code="2" value="15"/>'
+        print >> f,'        <PtCodeElement pt="6" code="2" value="20"/>'
+        print >> f,'    </PtEncoding>'
+        print >> f, "</MuCTPiGeometry>"
+        f.close()
+        print "Wrote %s" % outfilename
+    def getStats(self,stats):
+        stats['miocts'] = len(self.miocts)
+        for mioct in self.miocts:
+            mioct.getStats(stats)
+    def printStats(self):
+        stats = {'miocts' : 0, 'sectors' : 0, 'rois' : 0, 'decodes' : 0, 'topocells' : 0}
+        self.getStats(stats)
+        print "Numbers for %s" % self.name
+        print "#MIOCTs    : %i" % stats['miocts']
+        print "#Sectors   : %i" % stats['sectors']
+        print "#Decodes   : %i" % stats['decodes']
+        print "#ROIs      : %i" % stats['rois']
+        print "#Topocells : %i" % stats['topocells']
+        
+
+
+
+
+def rpcMioctAndSectorInfo(sectorID):
+    sectorName = "B%02i" % sectorID
+    sectorConnector = (sectorID+2) % 4
+
+    mioctID = ( (sectorID+2) % 32 ) / 4
+    mioctSlot = mioctID + 4
+    if sectorID >= 32:
+        mioctID += 8
+        mioctSlot = mioctID + 6
+
+    return mioctID, mioctSlot, sectorConnector, sectorName
+
+
+
+def read2015Geometry( fn ):
+    xmlgeometry = MioctGeometryXMLReader(fn)
+    miocts = []
+    for MIOCT in xmlgeometry.getMIOCTs():
+        sectors = []
+        for sector in MIOCT.Sectors:
+            #if sn.startswith('B'): continue
+            rois = []
+            for roiElem in sector.ROIs:
+                rois += [ ROI.fromROIelement(roiElem) ]
+            sectors += [ Sector(name=sector['name'], connector=int(sector['connector']), rois=rois) ]
+        miocts += [ Mioct( id=int(MIOCT['id']), slot=int(MIOCT['slot']), sectors=sectors) ]
+        decodes = Decodes()
+        for tc in MIOCT.Decode.TopoCells:
+            decodes.addTopoCell( TopoCell.fromTopoCellElement(tc) )
+        miocts[-1].decodes=decodes
+    return MuonGeometry("full geometry 2015", miocts=miocts)
+
+
+
+def read2015RPCCodeMapping( geometry ):
+    mapping = {}  
+    for mioct in geometry.miocts:
+        for sector in mioct.sectors:
+            if sector.isBarrel():
+                mapping[sector.id] = dict( [ (roi.roiid, (roi.etacode, roi.phicode)) for roi in sector.rois ] )
+    return mapping
+
+
+
+
+def feetRegionMapping(sectorId, roiId):
+    """ provides the new mapping for the feet and elevator region
+    The numbers can be found in doc/roi_map_R2.pdf
+    """
+
+    etacode = -1
+    phicode = -1
+    
+    if sectorId in [23,24,55,56]:
+        # elevator region
+
+        # eta
+        etaMap = { 23 : [ [0,1,2,3,5,7], [4,6,8,9,10,11], range(12,20) + [21,23], [20,22] + range(24,28) ],
+                   24 : [ [0,1,2,3,4,6], [5,7,8,9,10,11], range(12,20) + [20,22], [21,23] + range(24,28) ] }
+        etaMap[55] = etaMap[24]
+        etaMap[56] = etaMap[23]
+                
+        for ec, tt in enumerate(etaMap[sectorId]):
+            if roiId in tt:
+                etacode = ec
+                break
+
+        # phi
+        if sectorId in [23,55]:
+            if roiId in [2,3,6,7,10,11,18,19,22,23,27]:
+                phicode = 2
+            if roiId in [0,1,4,5,8,9,12,13,14,15,16,17,20,21,25]:
+                phicode = 3
+        elif sectorId in [24,56]:
+            if roiId in [0,1,4,5,8,9,12,13,14,15,16,17,20,21,24]:
+                phicode = 4
+            if roiId in [2,3,6,7,10,11,18,19,22,23,26]:
+                phicode = 5
+
+        if sectorId == 23:
+            if roiId == 27: phicode = 2
+            elif roiId == 25: phicode = 3
+        elif sectorId == 24:
+            if roiId == 24: phicode = 4
+            elif roiId == 26: phicode = 5
+        elif sectorId == 55:
+            if roiId == 24: phicode = 3
+            elif roiId == 26: phicode = 2
+        elif sectorId == 56:
+            if roiId == 27: phicode = 5
+            elif roiId == 25: phicode = 4
+
+
+
+    elif [21,22,25,26,53,54,57,58]:
+        # feet region
+
+        # eta
+        etaMap = { 21 : [ range(0,8), range(8,16) + [17,19], [16,18] + range(20,32) ],
+                   22 : [ range(0,8), range(8,16) + [16,18], [17,19] + range(20,32) ] }
+        etaMap[25] = etaMap[21]
+        etaMap[26] = etaMap[22]
+        etaMap[53] = etaMap[22]
+        etaMap[54] = etaMap[21]
+        etaMap[57] = etaMap[53]
+        etaMap[58] = etaMap[54]
+                
+        for ec, tt in enumerate(etaMap[sectorId]):
+            if roiId in tt:
+                etacode = ec
+                break
+
+        # phi
+        if sectorId in [21,53]:
+            if roiId in [2,3,6,7,10,11,14,15,18,19,22,23,26,27,30,31]:
+                phicode = 6
+            elif roiId in [0,1,4,5,8,9,12,13,16,17,20,21,24,25,28,29]:
+                phicode = 7
+        elif sectorId in [22,54]:
+            if roiId in [0,1,4,5,8,9,12,13,16,17,20,21,24,25,28,29]:
+                phicode = 0
+            elif roiId in [2,3,6,7,10,11,14,15,18,19,22,23,26,27,30,31]:
+                phicode = 1
+        elif sectorId in [25,57]:
+            if roiId in [2,3,6,7,10,11,14,15,18,19,22,23,26,27,30,31]:
+                phicode = 6
+            elif roiId in [0,1,4,5,8,9,12,13,16,17,20,21,24,25,28,29]:
+                phicode = 7
+        elif sectorId in [26,58]:
+            if roiId in [0,1,4,5,8,9,12,13,16,17,20,21,24,25,28,29]:
+                phicode = 0
+            elif roiId in [2,3,6,7,10,11,14,15,18,19,22,23,26,27,30,31]:
+                phicode = 1
+
+    if etacode == -1:
+        raise RuntimeError("No etacode for SL %i and ROI %i" % (sectorId, roiId))
+    if phicode == -1:
+        raise RuntimeError("No phicode for SL %i and ROI %i" % (sectorId, roiId))
+
+    return (etacode,phicode)
+
+
+
+
+def read2016RPCGeomData(fn, oldMapping):
+
+    rpcGeometry2016 = MuonGeometry("RPC geometry 2016")
+    log = getLogger(__file__+".read2016RPCGeomData")
+
+
+    log.info("Reading %s" % fn)
+    f = open(fn,"read")
+    for line in f:
+        if line.lstrip().startswith("#"): # remove comments
+            continue
+        ls = line.split()
+        side     = int(ls[0])
+        sector   = int(ls[1]) 
+        roiid    = int(ls[2]) 
+        etamin   = float(ls[3])
+        etamax   = float(ls[4])
+        phimin   = float(ls[5])
+        phimax   = float(ls[6])
+        if max(phimin, phimax) < 0:
+            phimin += 2 * PI
+            phimax += 2 * PI
+        eta = (etamin + etamax) / 2
+        phi = (phimin + phimax) / 2
+
+        sectorId = sector + 32 * side
+        if sectorId in [21,22,23,24,25,26,53,54,55,56,57,58]:
+            (etacode, phicode) = feetRegionMapping(sectorId, roiid)
+        else:
+            (etacode, phicode) = oldMapping[sectorId][roiid]
+
+        roi = ROI( eta=eta, phi=phi, phimin=phimin, phimax=phimax, etamin=etamin, etamax=etamax, etacode=etacode, phicode=phicode, roiid=roiid )
+
+        # now find MIOCT and Sector where to add the ROI to
+        mioctId, mioctSlot, sectorConnector, sectorName = rpcMioctAndSectorInfo(sectorId)
+        mioct = rpcGeometry2016.getMioct(mioctId)
+        if not mioct:
+            mioct = rpcGeometry2016.addMioct(Mioct(id=mioctId, slot=mioctSlot))
+
+        sector = mioct.getSector(sectorConnector)
+        if not sector:
+            sector = mioct.addSector( Sector(name=sectorName, connector=sectorConnector) )
+            
+        sector.addROI( roi )
+
+    return rpcGeometry2016
+
+
+def updateGeometryTGC(newGeometry, oldGeometry):
+    newGeometry.name = "updated full geometry for 2016"
+    for mioct in newGeometry.miocts:
+        oldMioct = oldGeometry.getMioct(mioct.id)
+        for sector in oldMioct.sectors:
+            if sector.isBarrel(): continue
+            mioct.addSector(sector)
+        mioct.fillTopoCells()
+
+
+
+def sectorAsXML_2(sector, depth, stats):
+    attr = ["connector", "name"]
+    s = ' '*depth + "<%s %s>\n" % (sector.tag, " ".join(['%s="%s"' % (a, sector[a]) for a in attr]) )
+    s += ' '*depth + '    <!-- contains %i ROIs -->\n' % len(sector.ROIs)
+    s += ' '*depth + '    <!-- mapping from ROI to coding scheme -->\n'
+    for roi in sorted(sector.ROIs, key=lambda roi: int(roi['roiid'])):
+        s += roiAsXML_2(roi, depth + 4 )
+    s += ' '*depth + "</%s>\n" % sector.tag
+    stats['rois'] += len(sector.ROIs)
+    return s
+
+def roiAsXML_2(roi, depth):
+    attr = ["eta", "phi", "etacode", "phicode", "etamin", "etamax", "phimin", "phimax", "roiid"]
+    s = ' ' * depth + "<ROI %s/>\n" % (" ".join(['%s="%s"' % (a, roi[a]) for a in attr]) )
+    return s
+
+
+def sectorAsXML((connector, name, rois), depth, stats):
+    s = ' '*depth + '<Sector connector="%s" name="%s">\n' % (connector, name)
+    s += ' '*depth + '    <!-- contains %i ROIs -->\n' % len(rois)
+    s += ' '*depth + '    <!-- mapping from ROI to coding scheme -->\n'
+    for roi in rois:
+        s += roiAsXML(roi, depth + 4 )
+    s += ' '*depth + "</Sector>\n"
+    stats['rois'] += len(rois)
+    return s
+
+def roiAsXML(roi, depth):
+    roi['eta'] = (float(roi['etamin']) + float(roi['etamax'])) / 2
+    roi['phi'] =  (float(roi['phimin']) + float(roi['phimax'])) / 2
+    s = ' ' * depth + '<ROI eta="%f" phi="%f" etacode="0x%s" phicode="0x%s" etamin="%f" etamax="%f" phimin="%f" phimax="%f" roiid="%i"/>\n' % (roi["eta"], roi["phi"], roi["etacode"], roi["phicode"], roi["etamin"], roi["etamax"], roi["phimin"], roi["phimax"], roi["roiid"] )
+    return s
+
+
+
+
+
+
+
+
+
+def main(args):
+
+    # read 2015 geometry xml file
+    muonGeometry2015 = read2015Geometry( args.infile2015 )
+
+    muonGeometry2015.printStats()
+
+    # maps roi number to etacode and phicode
+    rpcCodeMapping = read2015RPCCodeMapping( muonGeometry2015 )
+
+
+    muonGeometry2016 = read2016RPCGeomData( args.infile, rpcCodeMapping )
+    muonGeometry2016.printStats()
+
+    
+    updateGeometryTGC(muonGeometry2016, muonGeometry2015)
+    muonGeometry2016.printStats()
+
+    # write out the RPC info and the TGC info
+    muonGeometry2016.writeXML("TestMioctGeometry2016.xml")
+
+
+
+
+if __name__=="__main__":
+
+    parser = argparse.ArgumentParser( description=__doc__, 
+                                      formatter_class = argparse.RawTextHelpFormatter)
+
+    parser.add_argument('-i', dest='infile', default="../data/TestMioctGeometry2016.dat", type=str,
+                        help='name of input RPC muon geometry file for 2016 [../data/TestMioctGeometry2016.dat]')
+
+    parser.add_argument('-i1', dest='infile2015', default="../data/TestMioctGeometry.xml", type=str,
+                        help='name of input RPC muon geometry file used in 2015 [../data/TestMioctGeometry.xml]')
+
+    args = parser.parse_args()
+
+    sys.exit( main(args) )
diff --git a/Trigger/TrigConfiguration/TrigConfMuctpi/scripts/SeparateEncodingFile.py b/Trigger/TrigConfiguration/TrigConfMuctpi/scripts/SeparateEncodingFile.py
new file mode 100755
index 0000000000000000000000000000000000000000..ef9193e4bd9c48bb23468f63d10d2af6618aaa64
--- /dev/null
+++ b/Trigger/TrigConfiguration/TrigConfMuctpi/scripts/SeparateEncodingFile.py
@@ -0,0 +1,106 @@
+#!/usr/bin/env python
+
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+import sys, time, os, re, argparse
+from TrigConfMuctpi.XMLReader import MioctGeometryXMLReader
+
+def readXML(filename):
+    return MioctGeometryXMLReader(filename)
+
+
+def mioctAsXML(mioct, depth, filter, stats):
+    attr = ["id", "slot"]
+    s = ' '*depth + "<%s %s>\n" % (mioct.tag, " ".join(['%s="%s"' % (a, mioct[a]) for a in attr]) )
+    s += ' '*depth + '    <!-- contains sectors __SECTORS__ -->\n'
+    sectorList = []
+    for sector in mioct.Sectors:
+        if not filter(sector):
+            continue
+        sectorList += [sector['name']]
+        s += sectorAsXML(sector, depth + 4, stats )
+    s += ' '*depth + "</%s>\n" % mioct.tag
+    s = s.replace('__SECTORS__', ", ".join(sorted(sectorList)) )
+    stats['sectors'] += len(sectorList)
+    return s
+
+
+def sectorAsXML(sector, depth, stats):
+    attr = ["connector", "name"]
+    s = ' '*depth + "<%s %s>\n" % (sector.tag, " ".join(['%s="%s"' % (a, sector[a]) for a in attr]) )
+    s += ' '*depth + '    <!-- contains %i ROIs -->\n' % len(sector.ROIs)
+    s += ' '*depth + '    <!-- mapping from ROI to coding scheme -->\n'
+    for roi in sorted(sector.ROIs, key=lambda roi: int(roi['roiid'])):
+        s += roiAsXML(roi, depth + 4 )
+    s += ' '*depth + "</%s>\n" % sector.tag
+    stats['rois'] += len(sector.ROIs)
+    return s
+
+def roiAsXML(roi, depth):
+    attr = ["eta", "phi", "etacode", "phicode", "etamin", "etamax", "phimin", "phimax", "roiid"]
+    s = ' ' * depth + "<ROI %s/>\n" % (" ".join(['%s="%s"' % (a, roi[a]) for a in attr]) )
+    return s
+
+
+def writeXML(geometry, dettype):
+
+    if dettype != "RPC" and dettype != "TGC":
+        return
+
+    stats = {'miocts' : 0, 'sectors' : 0, 'rois' : 0}
+
+    infile = geometry.getFileName()
+    outfile = infile.replace(".","_%s." % dettype)
+
+    if dettype == 'RPC':
+        sectorFilter = lambda s : s['name'].startswith('B')
+    else:
+        sectorFilter = lambda s : s['name'].startswith('E') or s['name'].startswith('F')
+
+    f = open(outfile,"write")
+
+    print >> f, '<?xml version="1.0" ?>\n'
+    print >> f, '<!DOCTYPE MuCTPiGeometry SYSTEM "MUCTPIGeometry.dtd">\n'
+    print >> f, geometry.MuCTPiGeometry
+    for mioct in geometry.getMIOCTs():
+        print >> f, mioctAsXML(mioct, 4, sectorFilter, stats)
+
+    print >> f, "</%s>" % geometry.MuCTPiGeometry.tag
+    stats['miocts'] = len(geometry.getMIOCTs())
+    print "Wrote %s" % outfile
+
+    print "Numbers for %s" % dettype
+    print "#MIOCTs  : %i" % stats['miocts']
+    print "#Sectors : %i" % stats['sectors']
+    print "#ROIs    : %i" % stats['rois']
+
+    f.close()
+
+
+
+def main(args):
+
+    print "Using input %s" % args.infile
+    geometry = readXML( args.infile )
+
+    writeXML(geometry, "RPC")
+    writeXML(geometry, "TGC")
+
+
+
+if __name__=="__main__":
+
+
+    parser = argparse.ArgumentParser( description=__doc__, 
+                                      formatter_class = argparse.RawTextHelpFormatter)
+
+    parser.add_argument('-i', dest='infile', default="TrigConfMuctpi/TestMioctGeometry.xml", type=str,
+                        help='name of input combined muon geometry file')
+
+    args = parser.parse_args()
+
+    #try:
+    sys.exit( main(args) )
+    #except Exception, ex:
+    #    print "exception caught %r" % ex
+    #    sys.exit(1)
diff --git a/Trigger/TrigConfiguration/TrigConfMuctpi/scripts/validateMioctEncodingFile.py b/Trigger/TrigConfiguration/TrigConfMuctpi/scripts/validateMioctEncodingFile.py
index a923fedda0dbbb5394e3cc4a8776ef6720c1d063..c7030d1f063704961e035105d437c82c62aae87d 100755
--- a/Trigger/TrigConfiguration/TrigConfMuctpi/scripts/validateMioctEncodingFile.py
+++ b/Trigger/TrigConfiguration/TrigConfMuctpi/scripts/validateMioctEncodingFile.py
@@ -2,29 +2,52 @@
 
 # Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
 
-import sys,os
+import sys, time, os, re, argparse
+from TrigConfMuctpi.XMLReader import MioctGeometryXMLReader
 
-def main():
 
-    if len(sys.argv)<=1:
-        print "Usage:\n%s TestGeomety.xml" % sys.argv[0]
-        return 1
+def readXML(filename):
+    return MioctGeometryXMLReader(filename)
+
+def validate(geometry):
+    stats = {'miocts' : 0, 'sectors' : 0, 'rois' : 0, 'decodes' : 0, 'topocells' : 0}
+
+    stats['miocts'] = len(geometry.getMIOCTs())
+
+    for mioct in geometry.getMIOCTs():
+        stats['sectors'] += len(mioct.Sectors)
+        for sector in mioct.Sectors:
+            stats['rois'] += len(sector.ROIs)
+            #print "M %2s  S %-4s  #R %3i" % (mioct['id'], sector['name'], len(sector.ROIs) )
+
+        stats['decodes'] += len(mioct.Decodes)
+        for decode in mioct.Decodes:
+            stats['topocells'] += len(decode.TopoCells)
+    print "#MIOCTs    : %i" % stats['miocts']
+    print "#Sectors   : %i" % stats['sectors']
+    print "#ROIs      : %i" % stats['rois']
+    print "#Decodes   : %i" % stats['decodes']
+    print "#TopoCells : %i" % stats['topocells']
+
 
-    xmlfile = sys.argv[1]
 
-    checkResult = os.system("get_files -xmls -symlink MUCTPIGeometry.dtd")
-    if checkResult != 0:
-        print "ERROR Could not find MUCTPIGeometry.dtd in $DATAPATH"
-        return 1
     
-    checkResult = os.system("xmllint --noout --dtdvalid MUCTPIGeometry.dtd %s" % xmlfile)
-    if checkResult == 0:
-        print "XML file %s is conform with MUCTPIGeometry.dtd" % xmlfile
-    else:
-        print "ERROR the XML does not follow the document type definition MUCTPIGeometry.dtd"
-        return 1
 
-    return 0
+def main(args):
+
+    print "Using input %s" % args.infile
+    geometry = readXML( args.infile )
+
+    validate(geometry)
 
 if __name__=="__main__":
-    sys.exit(main())
+
+    parser = argparse.ArgumentParser( description=__doc__, 
+                                      formatter_class = argparse.RawTextHelpFormatter)
+
+    parser.add_argument('-i', dest='infile', default="TrigConfMuctpi/TestMioctGeometry2016.xml", type=str,
+                        help='name of input combined muon geometry filei [TrigConfMuctpi/TestMioctGeometry2016.xml]')
+
+    opts = parser.parse_args()
+
+    sys.exit( main(opts) )
diff --git a/Trigger/TrigConfiguration/TrigConfMuctpi/scripts/validateMioctEncodingFileDTD.py b/Trigger/TrigConfiguration/TrigConfMuctpi/scripts/validateMioctEncodingFileDTD.py
new file mode 100755
index 0000000000000000000000000000000000000000..a923fedda0dbbb5394e3cc4a8776ef6720c1d063
--- /dev/null
+++ b/Trigger/TrigConfiguration/TrigConfMuctpi/scripts/validateMioctEncodingFileDTD.py
@@ -0,0 +1,30 @@
+#!/bin/env python
+
+# Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+
+import sys,os
+
+def main():
+
+    if len(sys.argv)<=1:
+        print "Usage:\n%s TestGeomety.xml" % sys.argv[0]
+        return 1
+
+    xmlfile = sys.argv[1]
+
+    checkResult = os.system("get_files -xmls -symlink MUCTPIGeometry.dtd")
+    if checkResult != 0:
+        print "ERROR Could not find MUCTPIGeometry.dtd in $DATAPATH"
+        return 1
+    
+    checkResult = os.system("xmllint --noout --dtdvalid MUCTPIGeometry.dtd %s" % xmlfile)
+    if checkResult == 0:
+        print "XML file %s is conform with MUCTPIGeometry.dtd" % xmlfile
+    else:
+        print "ERROR the XML does not follow the document type definition MUCTPIGeometry.dtd"
+        return 1
+
+    return 0
+
+if __name__=="__main__":
+    sys.exit(main())
diff --git a/Trigger/TrigConfiguration/TrigConfMuctpi/scripts/visualize.py b/Trigger/TrigConfiguration/TrigConfMuctpi/scripts/visualize.py
index 46c396d35d3ad2fa276b2f4baba64b4dc63d9a1f..73d9fb1c62d6af1ba3fe55ea35af5ad9b9284003 100755
--- a/Trigger/TrigConfiguration/TrigConfMuctpi/scripts/visualize.py
+++ b/Trigger/TrigConfiguration/TrigConfMuctpi/scripts/visualize.py
@@ -2,10 +2,10 @@
 
 # Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
 
-import sys
-from ROOT import gROOT, gStyle, TH2F, TCanvas, TBox, TLegend, TArc
+import sys, argparse
 from TrigConfMuctpi.XMLReader import MioctGeometryXMLReader
 from math import pi as PI
+import math
 
 global box, c, h, leg
 
@@ -18,6 +18,12 @@ colorMap = [  1, 13,
               30, 51,
               6, 38 ]
 
+colorMap2 = [
+    1, 8, 801, 9, 50, 4,
+    2, 11, 7, 30, 51, 6, 38 ]
+fillStyleMap2 = [ 3004, 3012, 3005, 3010 ]
+
+
 drawOrder = [ 0,  8,
               7, 15,
               6, 14,
@@ -34,19 +40,20 @@ def readXML(filename):
     return geom
 
 
-def drawGeometry(geometry):
+def drawROIGeometry(geometry, is2016):
 
+    outfn = "ROILayout%s.pdf" % ("2016" if is2016 else "2015")
 
     global box, c, h, leg
 
     gROOT.Reset()
     gStyle.SetOptStat(0)
     
-    c = TCanvas('c',"MuCTPi Geometry",1100,950)
+    c = TCanvas('c',"MuCTPi Geometry %s" % "2016" if is2016 else "2015",1400,950)
     c.Draw()
 
     #h = TH2F("h","Muon Geometry",10,-2.6,2.6,10,-6.4,6.4)
-    h = TH2F("h","Muon Geometry",10,-2.6,2.6,10,-0.15,6.4)
+    h = TH2F("h","Muon Geometry %s" % "2016" if is2016 else "2015",10,-2.6,2.6,10,-0.15,6.4)
     h.SetXTitle("#eta")
     h.SetYTitle("#phi")
     h.Draw();
@@ -54,7 +61,18 @@ def drawGeometry(geometry):
     box = TBox()
     box.SetFillStyle(0)
     box.SetLineColor(3)
+    box.SetLineColor(3)
 
+    text = TLatex()
+    text.SetTextSize(0.005)
+    text.SetTextFont(42)
+    text.SetTextAlign(22)
+    
+    secLabel = TLatex()
+    secLabel.SetTextSize(0.008)
+    secLabel.SetTextFont(42)
+    secLabel.SetTextAlign(22)
+    
     leg = TLegend(0.7,0.1,0.9,0.4)
     leg.SetEntrySeparation(0.05)
     leg.SetNColumns(2)
@@ -64,41 +82,55 @@ def drawGeometry(geometry):
         MIOCT = geometry.getMIOCT(MioctID)
         firstBox = True
         color = colorMap[colorIndex % len(colorMap)]
-        print "Using color ",color
+        #print "Using color ",color
         box.SetLineColor(color)
         box.SetLineWidth(1)
         
         for Sector in MIOCT.Sectors:
+            ymin = 10
+            ymax = -10
             for ROI in Sector.ROIs:
                 c1_x = float(ROI["etamin"])
                 c1_y = float(ROI["phimin"])
                 c2_x = float(ROI["etamax"])
                 c2_y = float(ROI["phimax"])
+                ymin = min(ymin,c1_y)
+                ymax = max(ymax,c2_y)
                 #print "eta [%f - %f], phi [%f - %f]" % (c1_x,c2_x,c1_y,c2_y)
                 b = box.DrawBox(c1_x,c1_y,c2_x,c2_y)
+                text.DrawText( (c1_x + c2_x)/2, (c1_y + c2_y)/2 ,ROI["roiid"])
                 if firstBox:
                     firstBox = False
                     leg.AddEntry(b,"Slot %s" % MIOCT["slot"],"l")
-
+            if Sector["name"].startswith("B"):
+                if int(Sector["name"][1:])<32:
+                    xpos = -0.02
+                    ypos = (ymin+ymax)/2 - 0.05
+                else:
+                    xpos = 0.02
+                    ypos = (ymin+ymax)/2 + 0.03
+                secLabel.DrawText(xpos,ypos,Sector["name"])
 
     leg.Draw()
 
     c.Update()
-    c.SaveAs("ROILayout.pdf")
+    c.SaveAs(outfn)
 
 
 
-def drawTopoGeometry(geometry):
+def drawTopoGeometry(geometry, is2016):
+
+    outfn = "TopoLayout%s.pdf" % ("2016" if is2016 else "2015")
 
     global box, c, h, leg
 
     gROOT.Reset()
     gStyle.SetOptStat(0)
     
-    c = TCanvas('c',"MuCTPi to Topo Geometry",1100,950)
+    c = TCanvas('c',"MuCTPi to Topo Geometry",1400,950)
     c.Draw()
 
-    h = TH2F("h","Muon Topo Geometry",10,-2.6,2.6,10,-0.15,6.4)
+    h = TH2F("h","Muon Topo Geometry %s" % "2016" if is2016 else "2015",10,-2.6,2.6,10,-0.15,6.4)
     h.SetXTitle("#eta")
     h.SetYTitle("#phi")
     h.Draw();
@@ -109,12 +141,8 @@ def drawTopoGeometry(geometry):
 
     circle = TArc()
 
-    drawn=False
-
-    #for MIOCT in geometry.getMIOCTs():
     for colorIndex,MioctID in enumerate(drawOrder):
         MIOCT = geometry.getMIOCT(MioctID)
-        firstBox = True
         color = colorMap[colorIndex % len(colorMap)]
         box.SetLineColor(color)
         box.SetFillColor(color)
@@ -148,25 +176,249 @@ def drawTopoGeometry(geometry):
             circle.DrawArc(c_x/10.,c_y/10.,0.02)
 
     c.Update()
-    c.SaveAs("TopoLayout.pdf")
+    c.SaveAs(outfn)
+    
+
+
+def drawTopoGeometryEtaPhi(geometry, eta, is2016):
+
+    global box, c, h, leg
+
+    gROOT.Reset()
+    gStyle.SetOptStat(0)
+    
+    c = TCanvas('c',"MuCTPi to Topo Geometry",1400,950)
+    c.Draw()
+
+    h = TH2F("h","Muon Topo Geometry %i" % (2016 if is2016 else 2015),10,-2.6,2.6,10,-0.15,6.4)
+    h.SetXTitle("#eta")
+    h.SetYTitle("#phi")
+    h.Draw();
+
+    box = TBox()
+    box.SetFillStyle(0)
+    box.SetLineColor(3)
+
+    circle = TArc()
+
+    leg = TLegend(0.8,0.1,0.9,0.35)
+    #leg.SetEntrySeparation(0.05)
+    #leg.SetNColumns(2)
+
+
+    codeInLegend = []
+    for MioctID in drawOrder:
+    #for MioctID in [3,4,5,6,7]:
+        MIOCT = geometry.getMIOCT(MioctID)
+
+        fillStyle = 3004
+        for cellIdx,TopoCell in enumerate(MIOCT.Decode.TopoCells):
+
+            if eta:
+                code = int(TopoCell["etacode"],16)
+            else:
+                code = int(TopoCell["phicode"],16)
+            color = colorMap2[code % len(colorMap)]
+            fillStyle = fillStyleMap2[code % 4]
+            box.SetLineColor(color)
+            box.SetFillColor(color)
+
+            circle.SetLineColor(color)
+            circle.SetFillColor(color)
+        
+            # corner 1
+            c1_x = float(TopoCell["etamin"])
+            c1_y = float(TopoCell["phimin"])
+            # corner 2
+            c2_x = float(TopoCell["etamax"])
+            c2_y = float(TopoCell["phimax"])
+            # center 
+            c_x = float(TopoCell["ieta"])
+            c_y = float(TopoCell["iphi"])
+
+            #print "cell %i : eta [%f - %f], phi [%f - %f]" % (cellIdx, c1_x, c2_x, c1_y, c2_y)
+
+            box.SetFillStyle(fillStyle)
+            b = box.DrawBox(c1_x,c1_y,c2_x,c2_y)
+            box.SetFillStyle(0)
+            box.DrawBox(c1_x,c1_y,c2_x,c2_y)
+
+            circle.DrawArc(c_x/10.,c_y/10.,0.02)
+
+
+            if not code in codeInLegend:
+                codeInLegend += [code]
+                if eta:
+                    leg.AddEntry(b,"etacode %i" % code,"lf")
+                else:
+                    leg.AddEntry(b,"phicode %i" % code,"f")
+
+    leg.Draw()
+
+    c.Update()
+    c.SaveAs("TopoLayout%s%s.pdf" % ("2016" if is2016 else "2015", "Eta" if eta else "Phi"))
+    
+
+
+def drawCodeValues(geometry, is2016):
+
+    global h,c
+
+    gROOT.Reset()
+    gStyle.SetOptStat(0)
+    
+    c = TCanvas('c',"Topo encoding",1400,950)
+    c.Draw()
+
+    h = TH2F("h","Muon Topo encoding %i" % (2016 if is2016 else 2015),8,0,8,8,0,8)
+    h.SetXTitle("#eta")
+    h.SetYTitle("#phi")
+    h.Draw();
+
+    for MioctID in drawOrder:
+    #for MioctID in [3,4,5,6,7]:
+        MIOCT = geometry.getMIOCT(MioctID)
+        for tc in MIOCT.Decode.TopoCells:
+            h.Fill(int(tc['etacode'],16),int(tc['phicode'],16))
+
+    h.Draw("colz")
+    c.Update()
+    c.SaveAs("TopoCodes%s.pdf" % "2016" if is2016 else "2015")
+    
+
+def drawIValues(geometry, is2016):
+
+    global h,c
+
+    gROOT.Reset()
+    gStyle.SetOptStat(0)
+    
+    c = TCanvas('c',"Topo encoding",1400,950)
+    c.Draw()
+
+    h = TH2F("h","Muon Topo encoding %i" % (2016 if is2016 else 2015),48,-24,24,64,0,64)
+    h.SetXTitle("#eta_{index}")
+    h.SetYTitle("#phi_{index}")
+    h.Draw();
+
+    for MioctID in drawOrder:
+        MIOCT = geometry.getMIOCT(MioctID)
+        for tc in MIOCT.Decode.TopoCells:
+            h.Fill(int(tc['ieta'])+0.5,int(tc['iphi'])+0.5)
+
+    h.Draw("colz")
+    c.Update()
+    c.SaveAs("TopoCellCenters%s.pdf" % "2016" if is2016 else "2015")
     
 
+
+def drawRoiDeltaR(geometry, is2016):
+
+    def getTopoCell(mioct, etacode, phicode):
+        global mioctTCmap
+        mioctTCmap = {}
+        mioctid = mioct['id']
+        if not mioctid in mioctTCmap:
+            d = {}
+            for tc in mioct.Decode.TopoCells:
+                key = ( int(tc['etacode'],16), int(tc['phicode'],16))
+                d[key] = tc
+            mioctTCmap[mioctid] = d
+        return mioctTCmap[mioctid][(etacode,phicode)]
+
+    global h,c,hB,hEC,hFW
+
+    gROOT.Reset()
+    gStyle.SetOptStat(0)
+    
+    c = TCanvas('c',"Topo encoding",1400,950)
+    c.Divide(2,2)
+    c.Draw()
+
+    hB = TH2F("hb","Delta R between ROI and TopoCell %i in Barrel" % (2016 if is2016 else 2015),64,0,64,32,0,32)
+    hB.SetXTitle("SL")
+    hB.SetYTitle("ROI ID")
+
+    hEC = TH2F("hec","Delta R between ROI and TopoCell %i in Endcap" % (2016 if is2016 else 2015),96,0,96,148,0,148)
+    hEC.SetXTitle("SL")
+    hEC.SetYTitle("ROI ID")
+
+    hFW = TH2F("hfw","Delta R between ROI and TopoCell %i in Forward" % (2016 if is2016 else 2015),48,0,48,64,0,64)
+    hFW.SetXTitle("SL")
+    hFW.SetYTitle("ROI ID")
+
+    for MioctID in drawOrder:
+        mioct = geometry.getMIOCT(MioctID)
+        
+        for sector in mioct.Sectors:
+            for roi in sector.ROIs:
+                tc = getTopoCell(mioct, int(roi['etacode'],16), int(roi['phicode'],16))
+                deltaEta = float(roi['eta'])-float(tc['ieta'])/10.
+                deltaPhi = float(roi['phi'])-float(tc['iphi'])/10.
+                if deltaPhi>math.pi:
+                    deltaPhi -= 2*math.pi # some topocells are made up from ROIs that are on both sides of 0
+                deltaR = math.sqrt(deltaEta*deltaEta+deltaPhi*deltaPhi)
+                sectorid = int(sector['name'].lstrip('ABCDEF'))
+                roiid = int(roi['roiid'])
+                if sector['name'].startswith('B'):
+                    hB.Fill(sectorid,roiid,deltaR)
+                elif sector['name'].startswith('E'):
+                    if sector['name'].startswith('EA'):
+                        sectorid += 48
+                    hEC.Fill(sectorid,roiid,deltaR)
+                elif sector['name'].startswith('F'):
+                    if sector['name'].startswith('FA'):
+                        sectorid += 24
+                    hFW.Fill(sectorid,roiid,deltaR)
+
+
+    c.cd(1)
+    hB.Draw("colz")
+    c.cd(2)
+    hEC.Draw("colz")
+    c.cd(3)
+    hFW.Draw("colz")
+    c.Update()
+    c.SaveAs("ROIDeltaR%s.pdf" % "2016" if is2016 else "2015")
+
+
+
 def main():
 
-    filename = "TestMioctGeometry.xml"
+    parser = argparse.ArgumentParser( description=__doc__, 
+                                      formatter_class = argparse.RawTextHelpFormatter)
+
+    parser.add_argument( '-i', dest='filename', default="TrigConfMuctpi/TestMioctGeometry2016.xml", type=str,
+                         help='name of muon geometry xml file')
+
+    args = parser.parse_args()
+
+    is2016 = '2016' in args.filename
+
+    print "Using input %s" % args.filename
+
+    geometry = readXML(args.filename)
+
+    from ROOT import gROOT, gStyle, TH2F, TCanvas, TBox, TLegend, TArc, TLatex
+    global gROOT, gStyle, TH2F, TCanvas, TBox, TLegend, TArc, TLatex
+
+    drawROIGeometry(geometry, is2016 = is2016)
+
+    drawTopoGeometry(geometry, is2016 = is2016)
+
+    drawTopoGeometryEtaPhi(geometry, eta=True, is2016 = is2016)
+
+    drawTopoGeometryEtaPhi(geometry, eta=False, is2016 = is2016)
 
-    if len(sys.argv)>=2:
-        filename = sys.argv[1]
+    drawCodeValues(geometry, is2016 = is2016)
 
-    print "Using input %s" % filename
+    drawIValues(geometry, is2016 = is2016)
 
-    geometry = readXML(filename)
+    drawRoiDeltaR(geometry, is2016 = is2016)
 
-    #drawGeometry(geometry)
 
-    drawTopoGeometry(geometry)
+    input("Press Enter to continue...")
 
 
 if __name__=="__main__":
     main()
-    #sys.exit(main())