diff --git a/LumiBlock/LumiBlockComps/CMakeLists.txt b/LumiBlock/LumiBlockComps/CMakeLists.txt
index 6578270449e8abff67760cff090aceff6d01cec6..5ebe896b39802a63dd0b4157156378fde423c779 100644
--- a/LumiBlock/LumiBlockComps/CMakeLists.txt
+++ b/LumiBlock/LumiBlockComps/CMakeLists.txt
@@ -10,6 +10,7 @@ atlas_depends_on_subdirs( PUBLIC
                           Control/AthenaBaseComps
                           Control/AthenaKernel
                           Control/StoreGate
+                          Control/xAODRootAccess
                           Database/AthenaPOOL/AthenaPoolKernel
                           Database/CoolLumiUtilities
                           Event/xAOD/xAODLuminosity
@@ -48,6 +49,11 @@ atlas_add_dictionary( LumiBlockCompsDict
                       INCLUDE_DIRS ${COOL_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS} ${CORAL_INCLUDE_DIRS}
                       LINK_LIBRARIES ${COOL_LIBRARIES} ${ROOT_LIBRARIES} ${CORAL_LIBRARIES} AthenaBaseComps AthenaKernel StoreGateLib SGtests CoolLumiUtilitiesLib xAODLuminosity GaudiKernel LumiBlockCoolQuery GoodRunsListsLib AthenaPoolUtilities DBDataModel EventInfo LumiBlockCompsLib )
 
+atlas_add_executable( getLumi
+                      util/getLumi.cxx
+                      INCLUDE_DIRS ${COOL_INCLUDE_DIRS} ${ROOT_INCLUDE_DIRS} ${CORAL_INCLUDE_DIRS}
+                      LINK_LIBRARIES ${COOL_LIBRARIES} ${ROOT_LIBRARIES} ${CORAL_LIBRARIES} AthenaBaseComps AthenaKernel StoreGateLib SGtests CoolLumiUtilitiesLib xAODLuminosity GaudiKernel LumiBlockCoolQuery GoodRunsListsLib AthenaPoolUtilities DBDataModel EventInfo LumiBlockCompsLib )
+
 # Install files from the package:
 atlas_install_python_modules( python/*.py )
 atlas_install_joboptions( share/*.py )
diff --git a/LumiBlock/LumiBlockComps/LumiBlockComps/LuminosityTool.h b/LumiBlock/LumiBlockComps/LumiBlockComps/LuminosityTool.h
index a13b7753ac57b09511d17e84539a35159886cc34..9cd2921932cd343d680cafa52dc256c150e7a6f8 100644
--- a/LumiBlock/LumiBlockComps/LumiBlockComps/LuminosityTool.h
+++ b/LumiBlock/LumiBlockComps/LumiBlockComps/LuminosityTool.h
@@ -138,9 +138,17 @@ class LuminosityTool: public AthAlgTool, virtual public ILuminosityTool {
 
   // Channel to use to get muToLumi from calibration tool
   unsigned int m_calibChannel;
+
+  // Backup channel in case calibChannel doesn't exist in online calibration folder
+  unsigned int m_calibBackupChannel;
+
+  // Flag to control whether invalid data is skipped (True - default) returning a zero luminosity,
+  // or whether the available luminosity values are returned anyways (False).
+  bool m_skipInvalid;
+
 };
 
 
 #endif
 
-#endif
\ No newline at end of file
+#endif
diff --git a/LumiBlock/LumiBlockComps/Root/LumiBlockMetaDataTool.cxx b/LumiBlock/LumiBlockComps/Root/LumiBlockMetaDataTool.cxx
index 16bf606005e5f17966f5d6882a44f08b4846bb92..4958b2a3e36d84365394df8e200e818b131736e0 100755
--- a/LumiBlock/LumiBlockComps/Root/LumiBlockMetaDataTool.cxx
+++ b/LumiBlock/LumiBlockComps/Root/LumiBlockMetaDataTool.cxx
@@ -5,7 +5,7 @@
 /** Modified from @file ReadMeta.cxx
  *  @brief The LumiBlockMetaDataTool reads luminosity metadata from input files and transfers it to output files
  *  @author Marjorie Shapiro <mdshapiro@lbl.gov> based on work from Peter van Gemmeren <gemmeren@anl.gov> 
- *  $Id: LumiBlockMetaDataTool.cxx 716108 2015-12-29 03:49:11Z ssnyder $
+ *  $Id: LumiBlockMetaDataTool.cxx 725529 2016-02-22 16:07:11Z will $
  **/
 
 #include "LumiBlockComps/LumiBlockMetaDataTool.h"
@@ -244,7 +244,7 @@ StatusCode   LumiBlockMetaDataTool::finishUp() {
 // 
 // stop() is called whenever the event loop is finished.
 // ======================================================
-   ATH_MSG_INFO(  " finishUp: write lumiblocks to meta data store " );
+   ATH_MSG_VERBOSE(  " finishUp: write lumiblocks to meta data store " );
 
    xAOD::LumiBlockRangeContainer* piovComplete = new xAOD::LumiBlockRangeContainer();
    xAOD::LumiBlockRangeAuxContainer* piovCompleteAux = new xAOD::LumiBlockRangeAuxContainer();
@@ -261,7 +261,7 @@ StatusCode   LumiBlockMetaDataTool::finishUp() {
    xAOD::LumiBlockRangeContainer::const_iterator it;
 
    if(m_cacheSuspectOutputRangeContainer->size()>0) {
-     msg(MSG::INFO) <<  "Suspect OutputRangeCollection with size " << m_cacheSuspectOutputRangeContainer->size() << endreq;
+     ATH_MSG_VERBOSE("Suspect OutputRangeCollection with size " << m_cacheSuspectOutputRangeContainer->size());
      for(it=m_cacheSuspectOutputRangeContainer->begin(); it!=m_cacheSuspectOutputRangeContainer->end(); it++) {
        xAOD::LumiBlockRange* iovr = new xAOD::LumiBlockRange(*(*it));
        piovSuspect->push_back(iovr);
@@ -269,7 +269,7 @@ StatusCode   LumiBlockMetaDataTool::finishUp() {
    }
 
    if(m_cacheOutputRangeContainer->size()>0) {
-     msg(MSG::INFO) <<  "OutputRangeCollection with size " << m_cacheOutputRangeContainer->size() << endreq;
+     ATH_MSG_VERBOSE("OutputRangeCollection with size " << m_cacheOutputRangeContainer->size());
      m_cacheOutputRangeContainer->sort(xAOD::SortLumiBlockRangeByStart());
 
      //  Use tmp collection to do the merging
@@ -284,7 +284,7 @@ StatusCode   LumiBlockMetaDataTool::finishUp() {
      xAOD::LumiBlockRangeContainer::const_iterator ilast = m_cacheOutputRangeContainer->begin();
      xAOD::LumiBlockRange* iovr = new xAOD::LumiBlockRange(*(*i));
      p_tempLBColl->push_back(iovr);
-     ATH_MSG_INFO(  "Push_back tmpLBColl with run  " 
+     ATH_MSG_VERBOSE(  "Push_back tmpLBColl with run  " 
 		<< (*i)->startRunNumber() << " LB " << (*i)->startLumiBlockNumber() << " events seen "     
 		    << (*ilast)->eventsSeen() << " expected " << (*i)->eventsExpected());
      i++;
@@ -299,7 +299,7 @@ StatusCode   LumiBlockMetaDataTool::finishUp() {
 	 	 		  << (*ilast)->eventsExpected() << " and " << (*i)->eventsExpected() );
 	 }
          else {
-	   ATH_MSG_INFO(  "Merge Run " << (*i)->startRunNumber() << " LB " << (*i)->startLumiBlockNumber() 
+	   ATH_MSG_VERBOSE(  "Merge Run " << (*i)->startRunNumber() << " LB " << (*i)->startLumiBlockNumber() 
 			               << " events seen "  << iovr->eventsSeen() << "+" 
                                        << (*i)->eventsSeen() << " and events expected "
 				       << iovr->eventsExpected() );
@@ -310,7 +310,7 @@ StatusCode   LumiBlockMetaDataTool::finishUp() {
        else {
          iovr = new xAOD::LumiBlockRange(*(*i));
 
-         ATH_MSG_INFO(  "Push_back tmpLBColl with run  " 
+         ATH_MSG_VERBOSE(  "Push_back tmpLBColl with run  " 
 		<< iovr->startRunNumber() << " LB " << iovr->startLumiBlockNumber() << " events seen "     
 		    << iovr->eventsSeen() << " expected " << iovr->eventsExpected());
 
@@ -333,7 +333,7 @@ StatusCode   LumiBlockMetaDataTool::finishUp() {
 
 
   if(piovComplete->size()>0) {
-    ATH_MSG_INFO( "Number of Complete LumiBlocks:" << piovComplete->size() );
+    ATH_MSG_DEBUG( "Number of Complete LumiBlocks:" << piovComplete->size() );
     xAOD::LumiBlockRangeContainer::const_iterator it;
     for(it=piovComplete->begin(); it!=piovComplete->end(); it++) {
       msg(MSG::INFO) << "\t [ ("
@@ -348,7 +348,7 @@ StatusCode   LumiBlockMetaDataTool::finishUp() {
   }
 
   if(piovUnfinished->size()>0) {
-    ATH_MSG_INFO( "Number of Unfinished LumiBlocks:" << piovUnfinished->size() );
+    ATH_MSG_DEBUG( "Number of Unfinished LumiBlocks:" << piovUnfinished->size() );
     xAOD::LumiBlockRangeContainer::const_iterator it;
     for(it=piovUnfinished->begin(); it!=piovUnfinished->end(); it++) {
       msg(MSG::INFO) << "\t [ ("
@@ -362,7 +362,7 @@ StatusCode   LumiBlockMetaDataTool::finishUp() {
     }
   }
   if(piovSuspect->size()>0) {
-    ATH_MSG_INFO( "Number of Suspect LumiBlocks:"  << piovSuspect->size() );
+    ATH_MSG_DEBUG( "Number of Suspect LumiBlocks:"  << piovSuspect->size() );
     xAOD::LumiBlockRangeContainer::const_iterator it;
     for(it=piovSuspect->begin(); it!=piovSuspect->end(); it++) {
       msg(MSG::INFO) << "\t [ ("
diff --git a/LumiBlock/LumiBlockComps/cmt/requirements b/LumiBlock/LumiBlockComps/cmt/requirements
index 265b144e924ad6d8098dbcdb6833d4d5034e34cc..1aac930427150885e11f9a19474d78b04391ffde 100644
--- a/LumiBlock/LumiBlockComps/cmt/requirements
+++ b/LumiBlock/LumiBlockComps/cmt/requirements
@@ -31,6 +31,7 @@ use CoraCool   			CoraCool-*   		Database -no_auto_imports
 use DBDataModel                 DBDataModel-*           Database/AthenaPOOL
 use EventInfo                   EventInfo-*             Event
 use GoodRunsLists		GoodRunsLists-*	     DataQuality
+end_private
 
 # Create a dual_use library since the lcgdict pattern doesn't work with component libraries using cmake.
 # This pollutes the linkopts for clients, but is otherwise harmless.
@@ -44,6 +45,11 @@ apply_pattern declare_joboptions files="*.py"
 # Create dictionary for LumiBlockComps
 private
 use AtlasReflex  AtlasReflex-*  External
-
 apply_pattern lcgdict dict=LumiBlockComps selectionfile=selection.xml headerfiles="../LumiBlockComps/LumiBlockCompsDict.h"
+end_private
+
+use_if tag=AthAnalysisBase pkg=xAODRootAccess ver=xAODRootAccess-* root=Control
+application getLumi ../util/getLumi.cxx
+macro_append getLumi_dependencies " GoodRunsLists LumiBlockCompsLib "
+
 
diff --git a/LumiBlock/LumiBlockComps/python/LuminosityToolDefault.py b/LumiBlock/LumiBlockComps/python/LuminosityToolDefault.py
index d036e3160618e64bd1e00cd3bd729635f880741c..e7576467a52b77b54722db069917584c9273a30c 100644
--- a/LumiBlock/LumiBlockComps/python/LuminosityToolDefault.py
+++ b/LumiBlock/LumiBlockComps/python/LuminosityToolDefault.py
@@ -159,6 +159,9 @@ class LuminosityToolOnline(LuminosityTool):
         super (LuminosityToolOnline, self).__init__(name)
 
         mlog = logging.getLogger(name)
+
+        # Keep values for invalid data
+        self.SkipInvalid = False
         
         from IOVDbSvc.CondDB import conddb
         if conddb.dbdata == "COMP200": # Run1
diff --git a/LumiBlock/LumiBlockComps/src/LuminosityTool.cxx b/LumiBlock/LumiBlockComps/src/LuminosityTool.cxx
index b22c5ddfdb6d2df1302c58a7d835cb7bfd9b27b5..bb779609599ac232400d2796c0e030db8b133217 100644
--- a/LumiBlock/LumiBlockComps/src/LuminosityTool.cxx
+++ b/LumiBlock/LumiBlockComps/src/LuminosityTool.cxx
@@ -38,7 +38,9 @@ LuminosityTool::LuminosityTool(const std::string& type,
     m_preferredChannel(0),
     m_luminousBunches(0),
     m_bunchInstLumiBlob(NULL),
-    m_calibChannel(0)
+    m_calibChannel(0),
+    m_calibBackupChannel(112),
+    m_skipInvalid(true)
 {
   declareInterface<ILuminosityTool>(this);
   declareProperty("LumiFolderName", m_lumiFolderName);
@@ -48,6 +50,8 @@ LuminosityTool::LuminosityTool(const std::string& type,
   declareProperty("BunchGroupTool", m_bunchGroupTool);
   declareProperty("OnlineLumiCalibrationTool", m_onlineLumiCalibrationTool);
   declareProperty("LBLBFolderName", m_lblbFolderName);
+  declareProperty("CalibBackupChannel", m_calibBackupChannel);
+  declareProperty("SkipInvalid", m_skipInvalid);
 
   m_LBAvInstLumi = 0.;
   m_LBAvEvtsPerBX = 0.;
@@ -291,15 +295,19 @@ LuminosityTool::updateAvgLumi( IOVSVC_CALLBACK_ARGS_P(/*idx*/, /*keys*/) )
   }
 
   if (attrList["Valid"].isNull()) {
-    ATH_MSG_WARNING( " NULL validity information ... set lumi to 0" );
-    return StatusCode::SUCCESS;
+      ATH_MSG_WARNING( " NULL validity information ... set lumi to 0" );
+      return StatusCode::SUCCESS;
   }
 
   // Check validity (don't bother continuing if invalid)
   m_Valid = attrList["Valid"].data<cool::UInt32>();
   if (m_Valid & 0x01) {
-    ATH_MSG_WARNING( " Invalid LB Average luminosity ... set lumi to 0" );
-    return StatusCode::SUCCESS;
+    if (m_skipInvalid) {
+      ATH_MSG_WARNING( " Invalid LB Average luminosity ... set lumi to 0" );
+      return StatusCode::SUCCESS;
+    } else {
+      ATH_MSG_WARNING( " Invalid LB Average luminosity ... continuing because skipInvalid == FALSE" );
+    }
   }
 
   // Get preferred channel (needed for per-BCID calculation)
@@ -350,7 +358,7 @@ LuminosityTool::updateAvgLumi( IOVSVC_CALLBACK_ARGS_P(/*idx*/, /*keys*/) )
 
   // Check validity of per-BCID luminosity (will issue warning in recalcPerBCIDLumi
   int perBcidValid = (m_Valid/10) % 10;
-  if (perBcidValid > 0) {
+  if ((perBcidValid > 0) && m_skipInvalid) {
     return StatusCode::SUCCESS;
   }
 
@@ -427,6 +435,20 @@ LuminosityTool::recalculatePerBCIDLumi()
     // This is the only correct way to do this!
     // The division below gives average mu (over all bunches) to total lumi
     m_MuToLumi = m_onlineLumiCalibrationTool->getMuToLumi(m_calibChannel);
+
+    // Check if this is reasonable
+    if (m_MuToLumi < 0.) {
+      ATH_MSG_INFO(" Found muToLumi = " << m_MuToLumi << " for channel " << m_calibChannel << ". Try backup channel..." );
+      m_MuToLumi = m_onlineLumiCalibrationTool->getMuToLumi(m_calibBackupChannel);
+      ATH_MSG_INFO(" Found muToLumi = " << m_MuToLumi << " for channel " << m_calibBackupChannel);
+
+      if (m_MuToLumi < 0.) {
+	ATH_MSG_WARNING(" Found invalid muToLumi = " << m_MuToLumi << " for backup channel " << m_calibBackupChannel << "!");
+	m_MuToLumi = 0.;
+      }
+
+    }
+
     //} else if (m_LBAvEvtsPerBX > 0.) {
     //m_MuToLumi = m_LBAvInstLumi / m_LBAvEvtsPerBX;
   } else {
@@ -609,4 +631,4 @@ LuminosityTool::recalculatePerBCIDLumi()
   return;
 }
 
-#endif
\ No newline at end of file
+#endif
diff --git a/LumiBlock/LumiBlockComps/util/getLumi.cxx b/LumiBlock/LumiBlockComps/util/getLumi.cxx
new file mode 100644
index 0000000000000000000000000000000000000000..65669a894062cc8aa8ef51c2514ececea942a682
--- /dev/null
+++ b/LumiBlock/LumiBlockComps/util/getLumi.cxx
@@ -0,0 +1,474 @@
+/*
+  Copyright (C) 2002-2017 CERN for the benefit of the ATLAS collaboration
+*/
+
+///getLumi - the lumi helper application
+///author: Will Buttinger (will@cern.ch)
+///Small program to quickly get luminosity out of files with LumiMetaData folder
+///Uses a root file generated using lumicalc service (atlas-lumicalc.cern.ch)
+///usage:
+/// getLumi.exe lumicalc.root /path/to/some/files*.root
+///  option: -m   shows which runs from the lumicalc file are not covered by the files you gave it
+///               useful option for checking you have run over all data that your GRL covers
+/// Note: This code is based on some old code I wrote a while ago, so it is by no means pretty!
+
+
+#include <iostream>
+
+#ifndef XAOD_ANALYSIS
+int main(int argc, char* argv[]) {
+   std::cout << " This application is currently only available in the analysis releases \n \
+      Please setup an AthAnalysisBase release to use this application." << std::endl;
+   return 0;
+}
+
+#else
+
+
+#include "TROOT.h"
+#include "TFile.h"
+#include "TTree.h"
+#include "TBranch.h"
+#include "TApplication.h"
+#include "TKey.h"
+#include "TDirectory.h"
+#include "TSystem.h"
+
+#include <getopt.h>
+#include <cstdlib>
+#include <vector>
+
+#include "GoodRunsLists/TGoodRunsListReader.h"
+
+#include "xAODRootAccess/Init.h"
+#include "xAODRootAccess/TEvent.h"
+#include "xAODLuminosity/LumiBlockRangeContainer.h"
+#include "xAODLuminosity/LumiBlockRangeAuxContainer.h"
+
+struct lbx {
+   lbx() : nExpected(0),nSeen(0) {}
+   long nExpected;
+   long nSeen;
+};
+
+int main(int argc, char* argv[]) {
+   const char* optstring = "m";
+   bool showMissing = false;
+static struct option long_options[] = 
+  {
+    /* name    has_arg       flag      val */
+    {"showMissing", no_argument ,  NULL,     'm'}
+ };
+
+   int longindex;
+  int option;
+  //int begin =   0;
+  //int end   = 999;
+  int nOptions = 0;
+  while ((option = getopt_long(argc, argv,
+          optstring, long_options, &longindex)) != -1) {
+      switch (option) {
+          case 'm' :
+            showMissing = true;nOptions++;
+            break;
+          case '?' : 
+            printf("Please supply a valid option to the program.  Exiting\n");
+            exit(1); 
+            break;
+      }
+  }
+
+
+
+   //first arg is the lumicalc file
+   if(argc<3+nOptions) {
+      std::cout << "Usage: <lumicalcfile.root> <list of xAOD or D3PD>" << std::endl;
+      std::cout << "Option: -m     lists run numbers with any missing lumi" << std::endl;
+      std::cout << "" << std::endl;
+      std::cout << "Further Documentation: see https://twiki.cern.ch/twiki/bin/view/AtlasProtected/AthAnalysisBase#How_to_check_the_luminosity_cove " <<std::endl;
+      return 0;
+   }
+   gSystem->Load("libTree.so");
+
+   bool readXML=false;
+   Root::TGoodRunsList fromXAOD;Root::TGoodRunsList fromXAODIncomplete;Root::TGoodRunsList fromXAODSuspect;
+   std::map<uint, std::map<uint, lbx> > lbxs;
+   Root::TGoodRunsListReader grlReader;
+
+   bool hasMask(false);
+   Root::TGoodRunsListReader grlMaskReader;
+   //hunt for xml files... we will use these as 'masks' for the included lumi
+   for(int i=2+nOptions;i<argc;i++) {
+      std::string s(argv[i]);
+      if(s.find(".xml")==std::string::npos) continue;
+      grlMaskReader.AddXMLFile( s );
+      hasMask=true;
+   }
+   Root::TGoodRunsList grlMask; 
+   if(hasMask) {
+      grlMaskReader.Interpret();grlMask.AddGRL(grlMaskReader.GetMergedGoodRunsList());
+   }
+
+
+   //open all the d3pd-like files, and hunt for their lumi strings
+   for(int i=2+nOptions;i<argc;i++) {
+      //require to have ".root" in it
+      std::string s(argv[i]);
+      if(s.find(".root")==std::string::npos) continue;
+      TFile *file = TFile::Open(argv[i]);
+      if(file==0) continue;
+      std::cout << s;
+      //try to get lumi
+
+      //if this is xAOD, it will have a MetaData tree ... 
+      if(file->Get("MetaData")!=0) {
+         TTree* metaTree = static_cast<TTree*>(file->Get("MetaData"));
+         //use TEvent if the MetaData tree contains an EventFormat branch and only 1 entry 
+         bool useTEvent(false);
+         if(metaTree->GetEntries()==1 && metaTree->FindBranch("EventFormat")) {
+            useTEvent = true;
+         } else {
+            metaTree->SetMakeClass(1);
+         }
+         std::vector<unsigned int> startRunNumber;
+         std::vector<unsigned int> stopRunNumber;
+         std::vector<unsigned int> startLumiBlockNumber;
+         std::vector<unsigned int> stopLumiBlockNumber;
+         std::vector<unsigned int> eventsExpected;
+         std::vector<unsigned int> eventsSeen;
+
+         //use TEvent to read the lumiblocks, if we can
+         bool ok(false);
+         xAOD::TEvent event;
+         const xAOD::LumiBlockRangeContainer* lbrs = 0;
+         xAOD::LumiBlockRangeAuxContainer* lbrs_aux = 0;
+         if(useTEvent && event.readFrom(file,true,"MetaData").isSuccess()) {
+            if(event.containsMeta<xAOD::LumiBlockRangeContainer>("LumiBlocks")) {
+               event.retrieveMetaInput<xAOD::LumiBlockRangeContainer>(lbrs, "LumiBlocks").isSuccess();
+            }
+         } else {
+            useTEvent=false;
+            if(metaTree->FindBranch("LumiBlocksAux.")) {
+               if(metaTree->FindBranch("LumiBlocksAux.")->GetSplitLevel()==0) {
+                  std::cout << " Unable to read unsplit LumiBlocksAux" << std::endl;
+               }
+               lbrs = new xAOD::LumiBlockRangeContainer();
+               lbrs_aux = new xAOD::LumiBlockRangeAuxContainer;
+               const_cast<xAOD::LumiBlockRangeContainer*>(lbrs)->setStore( lbrs_aux );
+               metaTree->SetBranchAddress("LumiBlocksAux.startRunNumber",&startRunNumber);
+               metaTree->SetBranchAddress("LumiBlocksAux.stopRunNumber",&stopRunNumber);
+               metaTree->SetBranchAddress("LumiBlocksAux.startLumiBlockNumber",&startLumiBlockNumber);
+               metaTree->SetBranchAddress("LumiBlocksAux.stopLumiBlockNumber",&stopLumiBlockNumber);
+               metaTree->SetBranchAddress("LumiBlocksAux.eventsExpected",&eventsExpected);
+               metaTree->SetBranchAddress("LumiBlocksAux.eventsSeen",&eventsSeen);
+            }
+         }
+
+         if(lbrs) {
+            std::cout << "...xAOD LumiBlocks";
+            for(int ii=0;ii<metaTree->GetEntries();ii++) {
+               if(!useTEvent) {
+                  const_cast<xAOD::LumiBlockRangeContainer*>(lbrs)->clear();
+                  metaTree->GetEntry(ii);
+                  for(unsigned int j=0;j<startRunNumber.size();j++) {
+                     xAOD::LumiBlockRange* r = new xAOD::LumiBlockRange; const_cast<xAOD::LumiBlockRangeContainer*>(lbrs)->push_back(r);
+                     r->setStartRunNumber(startRunNumber.at(j));r->setStopRunNumber(stopRunNumber.at(j));
+                     r->setStartLumiBlockNumber(startLumiBlockNumber.at(j));r->setStopLumiBlockNumber(stopLumiBlockNumber.at(j));
+                     r->setEventsExpected(eventsExpected.at(j));r->setEventsSeen(eventsSeen.at(j));
+                  }
+               }
+
+               //add lb to grl 
+               for(auto lbr : *lbrs) {
+                  for(uint runNum = lbr->startRunNumber(); runNum <= lbr->stopRunNumber(); runNum++) {
+                     if(lbr->startLumiBlockNumber()!=lbr->stopLumiBlockNumber()) {std::cout << " Unexpected behaviour. Please report! " << std::endl; exit(1);}
+                     for(uint lb = lbr->startLumiBlockNumber(); lb <= lbr->stopLumiBlockNumber(); lb++) {
+                        //std::cout << runNum << ":" << lb << " ss=" << lbr->eventsSeen() << " exp="<< lbr->eventsExpected() << std::endl;
+                        //if(lbr->startLumiBlockNumber()==97) std::cout << " seen = " << lbr->eventsSeen() << " vs " << lbr->eventsExpected() << std::endl;
+                        lbxs[runNum][lb].nSeen += lbr->eventsSeen(); 
+//if(lbxs[runNum][lb].nSeen > lbr->eventsExpected()) { std::cout << file->GetName() << " AA: " << lbr->eventsSeen() << " (total = " << lbxs[runNum][lb].nSeen << ") vs " << lbr->eventsExpected() << std::endl; }
+                        if(lbxs[runNum][lb].nExpected!=0 && lbxs[runNum][lb].nExpected != lbr->eventsExpected()) {std::cout << "...mismatch on expected events in [run,lb]=[" << runNum << "," << lb << "] got " << lbr->eventsExpected() << " but had " << lbxs[runNum][lb].nExpected << std::endl; exit(1); }
+                        else if(lbxs[runNum][lb].nExpected==0) lbxs[runNum][lb].nExpected=lbr->eventsExpected();
+                        //fromXAOD.AddRunLumiBlock(runNum,lb);
+                     }
+                  }
+               }
+               ok=true;
+            }
+            std::cout << "...ok" << std::endl;
+            if(!useTEvent) { delete lbrs; delete lbrs_aux; }
+         }
+
+         lbrs = 0;lbrs_aux=0;
+         if(useTEvent && event.readFrom(file,true,"MetaData").isSuccess()) {
+            if(event.containsMeta<xAOD::LumiBlockRangeContainer>("IncompleteLumiBlocks")) {
+               event.retrieveMetaInput<xAOD::LumiBlockRangeContainer>(lbrs, "IncompleteLumiBlocks").isSuccess();
+            }
+         } else {
+            useTEvent=false;
+            if(metaTree->FindBranch("IncompleteLumiBlocksAux.")) {
+               if(metaTree->FindBranch("IncompleteLumiBlocksAux.")->GetSplitLevel()==0) {
+                  std::cout << " Unable to read unsplit IncompleteLumiBlocksAux" << std::endl;
+               }
+               lbrs = new xAOD::LumiBlockRangeContainer();
+               lbrs_aux = new xAOD::LumiBlockRangeAuxContainer;
+               const_cast<xAOD::LumiBlockRangeContainer*>(lbrs)->setStore( lbrs_aux );
+               metaTree->ResetBranchAddresses();
+               metaTree->SetBranchAddress("IncompleteLumiBlocksAux.startRunNumber",&startRunNumber);
+               metaTree->SetBranchAddress("IncompleteLumiBlocksAux.stopRunNumber",&stopRunNumber);
+               metaTree->SetBranchAddress("IncompleteLumiBlocksAux.startLumiBlockNumber",&startLumiBlockNumber);
+               metaTree->SetBranchAddress("IncompleteLumiBlocksAux.stopLumiBlockNumber",&stopLumiBlockNumber);
+               metaTree->SetBranchAddress("IncompleteLumiBlocksAux.eventsExpected",&eventsExpected);
+               metaTree->SetBranchAddress("IncompleteLumiBlocksAux.eventsSeen",&eventsSeen);
+            }
+         }
+
+         if(lbrs) {
+            std::cout << "...xAOD IncompleteLumiBlocks";
+            for(int ii=0;ii<metaTree->GetEntries();ii++) {
+               if(!useTEvent) {
+                  const_cast<xAOD::LumiBlockRangeContainer*>(lbrs)->clear();
+                  metaTree->GetEntry(ii);
+                  for(unsigned int j=0;j<startRunNumber.size();j++) {
+                     xAOD::LumiBlockRange* r = new xAOD::LumiBlockRange; const_cast<xAOD::LumiBlockRangeContainer*>(lbrs)->push_back(r);
+                     r->setStartRunNumber(startRunNumber.at(j));r->setStopRunNumber(stopRunNumber.at(j));
+                     r->setStartLumiBlockNumber(startLumiBlockNumber.at(j));r->setStopLumiBlockNumber(stopLumiBlockNumber.at(j));
+                     r->setEventsExpected(eventsExpected.at(j));r->setEventsSeen(eventsSeen.at(j));
+                  }
+               }
+
+               //add lb to grl 
+               for(auto lbr : *lbrs) {
+                  for(uint runNum = lbr->startRunNumber(); runNum <= lbr->stopRunNumber(); runNum++) {
+                     if(lbr->startLumiBlockNumber()!=lbr->stopLumiBlockNumber()) {std::cout << " Unexpected behaviour. Please report! " << std::endl; exit(1);}
+                     for(uint lb = lbr->startLumiBlockNumber(); lb <= lbr->stopLumiBlockNumber(); lb++) {
+                        //std::cout << runNum << ":" << lb << " ss=" << lbr->eventsSeen() << " exp="<< lbr->eventsExpected() << std::endl;
+                        //if(lbr->startLumiBlockNumber()==97) std::cout << " seen = " << lbr->eventsSeen() << " vs " << lbr->eventsExpected() << std::endl;
+                        lbxs[runNum][lb].nSeen += lbr->eventsSeen(); 
+//if(lbxs[runNum][lb].nSeen > lbr->eventsExpected()) { std::cout << file->GetName() << " AA: " << lbr->eventsSeen() << " (total = " << lbxs[runNum][lb].nSeen << ") vs " << lbr->eventsExpected() << std::endl; }
+                        if(lbxs[runNum][lb].nExpected!=0 && lbxs[runNum][lb].nExpected != lbr->eventsExpected()) {std::cout << "...mismatch on expected events in [run,lb]=[" << runNum << "," << lb << "] got " << lbr->eventsExpected() << " but had " << lbxs[runNum][lb].nExpected << std::endl; exit(1); }
+                        else if(lbxs[runNum][lb].nExpected==0) lbxs[runNum][lb].nExpected=lbr->eventsExpected();
+                        //fromXAOD.AddRunLumiBlock(runNum,lb);
+                     }
+                  }
+               }
+               ok=true;
+            }
+            std::cout << "...ok" << std::endl;
+            if(!useTEvent) { delete lbrs; lbrs = 0; delete lbrs_aux; lbrs_aux=0; }
+         }
+
+
+
+         lbrs = 0;lbrs_aux=0;
+         if(useTEvent && event.readFrom(file,true,"MetaData").isSuccess()) {
+            if(event.containsMeta<xAOD::LumiBlockRangeContainer>("SuspectLumiBlocks")) {
+               event.retrieveMetaInput<xAOD::LumiBlockRangeContainer>(lbrs, "SuspectLumiBlocks").isSuccess();
+            }
+         } else {
+            useTEvent=false;
+            if(metaTree->FindBranch("SuspectLumiBlocksAux.")) {
+               if(metaTree->FindBranch("SuspectLumiBlocksAux.")->GetSplitLevel()==0) {
+                  std::cout << " Unable to read unsplit SuspectLumiBlocks" << std::endl;
+               }
+               lbrs = new xAOD::LumiBlockRangeContainer();
+               lbrs_aux = new xAOD::LumiBlockRangeAuxContainer;
+               const_cast<xAOD::LumiBlockRangeContainer*>(lbrs)->setStore( lbrs_aux );
+               metaTree->ResetBranchAddresses();
+               metaTree->SetBranchAddress("SuspectLumiBlocksAux.startRunNumber",&startRunNumber);
+               metaTree->SetBranchAddress("SuspectLumiBlocksAux.stopRunNumber",&stopRunNumber);
+               metaTree->SetBranchAddress("SuspectLumiBlocksAux.startLumiBlockNumber",&startLumiBlockNumber);
+               metaTree->SetBranchAddress("SuspectLumiBlocksAux.stopLumiBlockNumber",&stopLumiBlockNumber);
+               metaTree->SetBranchAddress("SuspectLumiBlocksAux.eventsExpected",&eventsExpected);
+               metaTree->SetBranchAddress("SuspectLumiBlocksAux.eventsSeen",&eventsSeen);
+            }
+         }
+
+         if(lbrs) {
+            std::cout << "...xAOD SuspectLumiBlocksAux";
+            for(int ii=0;ii<metaTree->GetEntries();ii++) {
+               if(!useTEvent) {
+                  const_cast<xAOD::LumiBlockRangeContainer*>(lbrs)->clear();
+                  metaTree->GetEntry(ii);
+                  for(unsigned int j=0;j<startRunNumber.size();j++) {
+                     xAOD::LumiBlockRange* r = new xAOD::LumiBlockRange; const_cast<xAOD::LumiBlockRangeContainer*>(lbrs)->push_back(r);
+                     r->setStartRunNumber(startRunNumber.at(j));r->setStopRunNumber(stopRunNumber.at(j));
+                     r->setStartLumiBlockNumber(startLumiBlockNumber.at(j));r->setStopLumiBlockNumber(stopLumiBlockNumber.at(j));
+                     r->setEventsExpected(eventsExpected.at(j));r->setEventsSeen(eventsSeen.at(j));
+                  }
+               }
+std::cout << lbrs->size() << " is size"<<std::endl;
+               //add lb to grl 
+               for(auto lbr : *lbrs) {
+                  for(uint runNum = lbr->startRunNumber(); runNum <= lbr->stopRunNumber(); runNum++) {
+                     if(lbr->startLumiBlockNumber()!=lbr->stopLumiBlockNumber()) {std::cout << " Unexpected behaviour. Please report! " << std::endl; exit(1);}
+                     for(uint lb = lbr->startLumiBlockNumber(); lb <= lbr->stopLumiBlockNumber(); lb++) {
+                        //std::cout << runNum << ":" << lb << " ss=" << lbr->eventsSeen() << " exp="<< lbr->eventsExpected() << std::endl;
+                        //if(lbr->startLumiBlockNumber()==97) std::cout << " seen = " << lbr->eventsSeen() << " vs " << lbr->eventsExpected() << std::endl;
+                        lbxs[runNum][lb].nSeen += lbr->eventsSeen(); 
+//if(lbxs[runNum][lb].nSeen > lbr->eventsExpected()) { std::cout << file->GetName() << " AA: " << lbr->eventsSeen() << " (total = " << lbxs[runNum][lb].nSeen << ") vs " << lbr->eventsExpected() << std::endl; }
+                        if(lbxs[runNum][lb].nExpected!=0 && lbxs[runNum][lb].nExpected != lbr->eventsExpected()) {std::cout << "...mismatch on expected events in [run,lb]=[" << runNum << "," << lb << "] got " << lbr->eventsExpected() << " but had " << lbxs[runNum][lb].nExpected << std::endl; exit(1); }
+                        else if(lbxs[runNum][lb].nExpected==0) lbxs[runNum][lb].nExpected=lbr->eventsExpected();
+                        //fromXAOD.AddRunLumiBlock(runNum,lb);
+                     }
+                  }
+               }
+               ok=true;
+            }
+            std::cout << "...ok" << std::endl;
+            if(!useTEvent) { delete lbrs; lbrs = 0; delete lbrs_aux; lbrs_aux=0; }
+         }
+
+         if(ok) continue; //don't try to read Lumi folder
+      }
+
+
+      if(file->GetDirectory("Lumi")==0) { std::cout  << "...no Lumi folder. Skipping" << std::endl; }
+      else {
+         file->cd("Lumi");
+         //look for lumiTree first
+         TTree* lumiTree = dynamic_cast<TTree*>(gDirectory->Get("lumiTree"));
+         if(lumiTree) {
+            std::cout << "...lumiTree";
+            //use the lumitree instead
+            TString *in = 0;
+            lumiTree->SetBranchAddress("lumi",&in);
+            for(int j=0;j<lumiTree->GetEntries();j++) {
+               lumiTree->GetEntry(j);
+               grlReader.AddXMLString(*in); readXML=true;
+            }
+            std::cout << "...ok" << std::endl;
+         } else {
+            TList* keys = gDirectory->GetListOfKeys();
+	    //loop over all that are objstrings
+	    for( Int_t j = 0; j < keys->GetEntries(); ++j ) {
+	      TKey *key = dynamic_cast<TKey*>( keys->At( j ) );
+	      TObjString* ostring = (TObjString*) key->ReadObjectAny( TObjString::Class() );
+	      if( ! ostring ) { std::cout << "...skipping object: " << key->GetName() << std::endl; continue;}
+	      // Check that it has the right format:
+	      if( ostring->GetString().BeginsWith( "<?xml version=" ) && ostring->GetString().Contains( "DOCTYPE LumiRangeCollection" ) ) {
+		grlReader.AddXMLString( ostring->GetString() ); readXML=true;
+		std::cout << "...ok" << std::endl;
+	      }
+	    }
+         }
+      }
+      file->Close();
+      delete file;
+   }
+
+   //loop over lbx and build up the complete/incomplete/suspect list:
+   for(auto& it : lbxs) {
+      uint runNum = it.first;
+      for(auto& it2 : it.second) {
+         uint lbn = it2.first;
+         if(it2.second.nSeen==it2.second.nExpected) { fromXAOD.AddRunLumiBlock(runNum,lbn); }
+         else if(it2.second.nSeen > it2.second.nExpected) { 
+           // std::cout << " suspect = " << it2.second.nSeen << " vs " << it2.second.nExpected << std::endl;
+            fromXAODSuspect.AddRunLumiBlock(runNum,lbn); }
+         else { fromXAODIncomplete.AddRunLumiBlock(runNum,lbn); }
+      }
+   }
+
+   Root::TGoodRunsList l;Root::TGoodRunsList lIncomplete;Root::TGoodRunsList lSuspect;
+   l.AddGRL(fromXAOD); lIncomplete.AddGRL(fromXAODIncomplete); lSuspect.AddGRL(fromXAODSuspect);//have to do this because of weird GRL behaviour
+   if(readXML) {
+      grlReader.Interpret();
+      l.AddGRL(grlReader.GetMergedGoodRunsList());
+   }
+
+   TFile *lumicalcFile = TFile::Open(argv[1+nOptions]);
+   if(lumicalcFile==0) {
+      std::cout << "Could not open lumicalc file: " << argv[1+nOptions] << std::endl;
+      return 0;
+   }
+
+   TTree *tmp = (TTree*)lumicalcFile->Get( "LumiMetaData" );
+   if(!tmp) {
+      std::cout << "Could not find LumiMetaData tree in lumicalc file: " << argv[1+nOptions] << std::endl;
+      return 0;
+   }
+
+   Root::TGoodRunsList providedL; //keeps track of what came from lumicalc file
+
+   std::cout << "Reading LumiMetaData...";
+
+   //structure expected is as given by iLumiCalc:
+   //   RunNbr, AvergeInteractionPerXing, IntLumi
+   UInt_t runNbr=0;Float_t intLumi=0;TBranch *b_runNbr;TBranch *b_intLumi;
+   UInt_t lb=0.; TBranch *b_lb;
+   if(tmp->SetBranchAddress("RunNbr",&runNbr,&b_runNbr)!=0) {
+      std::cout << "Could not find RunNbr branch in LumiMetaData TTree" << std::endl; return 0;
+   }
+   if(tmp->SetBranchAddress("LBStart",&lb,&b_lb)!=0) {
+      std::cout << "Could not find LBStart branch in Data TTree" << std::endl; return 0;
+   }
+   if(tmp->SetBranchAddress("IntLumi",&intLumi,&b_intLumi)!=0) {
+      std::cout << "Could not find IntLumi branch in Data TTree" << std::endl; return 0;
+   }
+   long nEntries = tmp->GetEntries();
+   double totalLumi = 0; double totalLumiIncomplete = 0; double totalLumiSuspect=0;
+   int startMissingBlock = -1;UInt_t lastRunNumber=0;UInt_t lastLb=0;double missingLumi=0; double allMissing=0;
+   std::map<UInt_t, bool> missingRuns;std::map<UInt_t,bool> allRuns;std::set<UInt_t> incompleteRuns;
+   for(long i=0;i<nEntries;i++) {
+      b_runNbr->GetEntry(i);b_intLumi->GetEntry(i);b_lb->GetEntry(i);
+      if(hasMask && !grlMask.HasRunLumiBlock(runNbr,lb)) continue;
+      providedL.AddRunLumiBlock(runNbr,lb);
+      bool hasLumi = l.HasRunLumiBlock(runNbr,lb);
+
+      if(hasLumi) totalLumi += intLumi;
+      else if(lIncomplete.HasRunLumiBlock(runNbr,lb)) {hasLumi=true; totalLumiIncomplete += intLumi; incompleteRuns.insert(runNbr);} //else if ensures we never double count lumi
+      else if(lSuspect.HasRunLumiBlock(runNbr,lb)) {hasLumi=true;totalLumiSuspect += intLumi;}
+
+      if(!hasLumi && intLumi==0.) hasLumi=true; //if there is no lumi, it's as good as having some
+      if((lastRunNumber!=runNbr&&startMissingBlock>=0) || (hasLumi && startMissingBlock>=0)) {
+         //print now, if startMissingBlock not negative
+         if(showMissing) std::cout << "[" << lastRunNumber << "," << startMissingBlock << "-" << lastLb << "," << missingLumi << "]";missingRuns[lastRunNumber]=true;
+         allMissing+=missingLumi; missingLumi=0;
+         startMissingBlock=-1;
+      }
+      if(!hasLumi && startMissingBlock==-1) {startMissingBlock=lb;missingLumi=intLumi/1E6;}
+      else if(!hasLumi) { missingLumi+=(intLumi/1E6); }
+      lastRunNumber=runNbr;lastLb=lb;
+      allRuns[runNbr] = true;
+   }
+   lumicalcFile->Close();
+   allMissing += missingLumi;
+   if(missingRuns.size()>0 && showMissing) {
+      std::cout << std::endl << "Runs with incomplete blocks: ";
+      for(auto r : incompleteRuns) {
+         std::cout << r << ",";
+      }
+      std::cout << std::endl << "Runs with missing blocks: ";
+      for(std::map<UInt_t,bool>::iterator it=missingRuns.begin();it!=missingRuns.end();++it) {
+         std::cout << it->first << ",";
+      }
+      std::cout << std::endl << "Complete runs: ";
+      for(std::map<UInt_t,bool>::iterator it=allRuns.begin();it!=allRuns.end();++it) {
+         if(missingRuns.find(it->first) == missingRuns.end()) std::cout << it->first << ",";
+      }
+      std::cout << std::endl;
+   }
+   std::cout << "Done" << std::endl;
+
+   std::cout << "Complete Luminosity = " << totalLumi/1E6 << " pb-1" << std::endl;
+   if(totalLumiIncomplete) std::cout << "Incomplete Luminosity = " << totalLumiIncomplete/1E6 << " pb-1" << std::endl;
+   if(totalLumiSuspect) std::cout << "Suspect Luminosity = " << totalLumiSuspect/1E6 << " pb-1" << std::endl;
+   std::cout << "(Complete+Incomplete+Suspect) Luminosity = " << (totalLumi+totalLumiIncomplete+totalLumiSuspect)/1E6 << " pb-1" << std::endl;
+   if(missingLumi) {
+      std::cout << "(Missing Lumonisity = " << allMissing << " pb-1)"; //already divided by 1E6 in loop above
+      if(!showMissing) std::cout << " rerun with the '-m' option to see runs where this luminosity resides";
+      std::cout << std::endl; 
+   }
+
+   /*
+   Root::TGoodRunsList allL(l); allL.AddGRL(lIncomplete);allL.AddGRL(lSuspect);
+   auto uncovered = allL.GetPartNotIn(providedL);
+   if(!uncovered.IsEmpty()) {
+      std::cout << "Input files contain following lumiblocks not covered by lumicalc file:" << std::endl;
+      uncovered.Summary(1);
+   }*/
+
+}
+
+#endif