diff --git a/RecoLuminosity/LumiProducer/README.md b/RecoLuminosity/LumiProducer/README.md
new file mode 100644
index 0000000000000..8f057def2add0
--- /dev/null
+++ b/RecoLuminosity/LumiProducer/README.md
@@ -0,0 +1,19 @@
+# RecoLuminosity/LumiProducer
+
+This package contains utilities for producing luminosity information in CMSSW. Most of the plugins here are obsolete and only for Run 1; they are kept here for backwards compatibility but are not actively maintained.
+
+For Run 2, the plugin `LumiProducerFromBrilcalc` is available. This allows you to add luminosity information to your CMSSW job by reading in a CSV output file produced by the `brilcalc` utility. In order to use it, add the following to your `cfg` file:
+
+```
+process.LumiInfo = cms.EDProducer('LumiProducerFromBrilcalc',
+ lumiFile = cms.string("./myLumiFile.csv"),
+ throwIfNotFound = cms.bool(False),
+ doBunchByBunch = cms.bool(False))
+```
+where `lumiFile` is the output file created by `brilcalc`, `throwIfNotFound` will determine the behavior if the csv file does not contain information for an event in your input file (if `True`, an exception will be thrown; if `False`, the luminosity will just be taken to be zero for that event), and `doBunchByBunch` should remain `False`, since bunch-by-bunch luminosity is not currently supported.
+
+Add `LumiInfo` to your path, and then you can access the `LumiInfo` object produced under the input tag `("LumiInfo", "brilcalc")`.
+
+For more information on the proper way to use `brilcalc` to produce a luminosity csv file, please consult the [LumiPOG twiki](https://twiki.cern.ch/twiki/bin/view/CMS/TWikiLUM#LumiCMSSW).
+
+
\ No newline at end of file
diff --git a/RecoLuminosity/LumiProducer/plugins/BuildFile.xml b/RecoLuminosity/LumiProducer/plugins/BuildFile.xml
index 170de258ebd07..579ab6031efc5 100644
--- a/RecoLuminosity/LumiProducer/plugins/BuildFile.xml
+++ b/RecoLuminosity/LumiProducer/plugins/BuildFile.xml
@@ -103,3 +103,9 @@
+
+
+
+
+
+
diff --git a/RecoLuminosity/LumiProducer/plugins/LumiProducerFromBrilcalc.cc b/RecoLuminosity/LumiProducer/plugins/LumiProducerFromBrilcalc.cc
new file mode 100644
index 0000000000000..e405550435a83
--- /dev/null
+++ b/RecoLuminosity/LumiProducer/plugins/LumiProducerFromBrilcalc.cc
@@ -0,0 +1,174 @@
+// -*- C++ -*-
+//
+// Package: RecoLuminosity/LumiProducer
+// Class: LumiProducerFromBrilcalc
+//
+/**\class LumiProducerFromBrilcalc LumiProducerFromBrilcalc.cc RecoLuminosity/LumiProducer/plugins/LumiProducerFromBrilcalc.cc
+
+ Description: Takes a csv file with luminosity information produced by brilcalc and reads it into the event.
+
+ Implementation:
+ [Notes on implementation]
+*/
+//
+// Original Author: Paul Lujan
+// Created: Fri, 28 Feb 2020 16:32:38 GMT
+//
+//
+
+// system include files
+#include
+#include
+#include
+
+// user include files
+#include "FWCore/Framework/interface/Frameworkfwd.h"
+#include "FWCore/Framework/interface/global/EDProducer.h"
+
+#include "FWCore/Framework/interface/Event.h"
+#include "FWCore/Framework/interface/MakerMacros.h"
+
+#include "FWCore/ParameterSet/interface/ParameterSet.h"
+#include "FWCore/Utilities/interface/StreamID.h"
+
+#include "FWCore/MessageLogger/interface/MessageLogger.h"
+
+#include "DataFormats/Luminosity/interface/LumiInfo.h"
+
+//
+// class declaration
+//
+
+class LumiProducerFromBrilcalc : public edm::global::EDProducer<> {
+public:
+ explicit LumiProducerFromBrilcalc(const edm::ParameterSet&);
+ ~LumiProducerFromBrilcalc() = default;
+
+ static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
+
+private:
+ virtual void produce(edm::StreamID, edm::Event&, const edm::EventSetup&) const override;
+
+ // ----------member data ---------------------------
+ const std::string lumiFile_;
+ const bool throwIfNotFound_;
+ const bool doBunchByBunch_;
+ std::map, std::pair > lumiData_;
+};
+
+//
+// constructor
+//
+
+LumiProducerFromBrilcalc::LumiProducerFromBrilcalc(const edm::ParameterSet& iConfig)
+ : lumiFile_(iConfig.getParameter("lumiFile")),
+ throwIfNotFound_(iConfig.getParameter("throwIfNotFound")),
+ doBunchByBunch_(iConfig.getParameter("doBunchByBunch")) {
+ //register your products
+ produces("brilcalc");
+
+ //now do what ever other initialization is needed
+ if (doBunchByBunch_) {
+ throw cms::Exception("LumiProducerFromBrilcalc")
+ << "Sorry, bunch-by-bunch luminosity is not yet supported. Please bug your friendly lumi expert!";
+ }
+
+ // Read luminosity data and store it in lumiData_.
+ edm::LogInfo("LumiProducerFromBrilcalc") << "Reading luminosity data from " << lumiFile_ << "...one moment...";
+ std::ifstream lumiFile(lumiFile_);
+ if (!lumiFile.is_open()) {
+ throw cms::Exception("LumiProducerFromBrilcalc") << "Failed to open input luminosity file " << lumiFile_;
+ }
+
+ int nLS = 0;
+ std::string line;
+ while (1) {
+ std::getline(lumiFile, line);
+ if (lumiFile.eof() || lumiFile.fail())
+ break;
+ if (line.empty())
+ continue; // skip blank lines
+ if (line.at(0) == '#')
+ continue; // skip comment lines
+
+ // Break into fields. These should be, in order: run:fill, brills:cmsls, time, beam status, beam energy,
+ // delivered lumi, recorded lumi, average pileup, source.
+ std::stringstream ss(line);
+ std::string field;
+ std::vector fields;
+
+ while (std::getline(ss, field, ','))
+ fields.push_back(field);
+
+ if (fields.size() != 9) {
+ edm::LogWarning("LumiProducerFromBrilcalc") << "Malformed line in csv file: " << line;
+ continue;
+ }
+
+ // Extract the run number from fields[0] and the lumisection number from fields[1]. Fortunately since the
+ // thing we want is before the colon, we don't have to split them again.
+ int run, ls;
+ std::stringstream runfill(fields[0]);
+ runfill >> run;
+ std::stringstream lsls(fields[1]);
+ lsls >> ls;
+
+ // Extract the delivered and recorded lumi from fields[5] and fields[6].
+ float lumiDel, lumiRec, dtFrac;
+ std::stringstream lumiDelString(fields[5]);
+ lumiDelString >> lumiDel;
+ std::stringstream lumiRecString(fields[6]);
+ lumiRecString >> lumiRec;
+
+ // Calculate the deadtime fraction
+ dtFrac = 1.0 - lumiRec / lumiDel;
+
+ // Finally, store it all.
+ lumiData_[std::make_pair(run, ls)] = std::make_pair(lumiDel, dtFrac);
+ nLS++;
+ }
+ edm::LogInfo("LumiProducerFromBrilcalc") << "Read " << nLS << " lumisections from " << lumiFile_;
+ lumiFile.close();
+}
+
+//
+// member functions
+//
+
+// ------------ method called to produce the data ------------
+void LumiProducerFromBrilcalc::produce(edm::StreamID iStreamID,
+ edm::Event& iEvent,
+ const edm::EventSetup& iSetup) const {
+ std::vector bxlumi(3564, 0);
+ std::pair runls = std::make_pair(iEvent.run(), iEvent.luminosityBlock());
+ if (lumiData_.count(runls) == 1) {
+ // if we have data for this run/LS, put it in the event
+ LogDebug("LumiProducerFromBrilcalc") << "Filling for run " << runls.first << " ls " << runls.second
+ << " with delivered " << lumiData_.at(runls).first << " dt "
+ << lumiData_.at(runls).second;
+ iEvent.put(std::make_unique(lumiData_.at(runls).second, bxlumi, lumiData_.at(runls).first), "brilcalc");
+ } else {
+ if (throwIfNotFound_) {
+ throw cms::Exception("LumiProducerFromBrilcalc")
+ << "Failed to find luminosity for run " << runls.first << " LS " << runls.second;
+ } else {
+ // just put in zeroes
+ edm::LogWarning("LumiProducerFromBrilcalc")
+ << "Failed to find luminosity for run " << runls.first << " ls " << runls.second;
+ iEvent.put(std::make_unique(0, bxlumi, 0), "brilcalc");
+ }
+ }
+}
+
+// ------------ method fills 'descriptions' with the allowed parameters for the module ------------
+void LumiProducerFromBrilcalc::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
+ // Allowed parameters
+ edm::ParameterSetDescription desc;
+ desc.add("lumiFile");
+ desc.add("throwIfNotFound", false);
+ desc.add("doBunchByBunch", false);
+ descriptions.addDefault(desc);
+}
+
+//define this as a plug-in
+DEFINE_FWK_MODULE(LumiProducerFromBrilcalc);
diff --git a/RecoLuminosity/LumiProducer/test/BuildFile.xml b/RecoLuminosity/LumiProducer/test/BuildFile.xml
index d593fd417e167..9c14b5d74b98c 100755
--- a/RecoLuminosity/LumiProducer/test/BuildFile.xml
+++ b/RecoLuminosity/LumiProducer/test/BuildFile.xml
@@ -105,3 +105,6 @@
+
+
+
diff --git a/RecoLuminosity/LumiProducer/test/TestLumiProducerFromBrilcalc.cc b/RecoLuminosity/LumiProducer/test/TestLumiProducerFromBrilcalc.cc
new file mode 100644
index 0000000000000..7f91995b539c5
--- /dev/null
+++ b/RecoLuminosity/LumiProducer/test/TestLumiProducerFromBrilcalc.cc
@@ -0,0 +1,109 @@
+// -*- C++ -*-
+//
+// Package: RecoLuminosity/TestLumiProducerFromBrilcalc
+// Class: TestLumiProducerFromBrilcalc
+//
+/**\class TestLumiProducerFromBrilcalc TestLumiProducerFromBrilcalc.cc RecoLuminosity/LumiProducer/test/TestLumiProducerFromBrilcalc.cc
+
+ Description: A simple analyzer class to test the functionality of TestLumiProducerFromBrilcalc.
+
+ Implementation:
+ Get the luminosity and prints it out.
+*/
+//
+// Original Author: Paul Lujan
+// Created: Fri, 20 Mar 2020 09:32:27 GMT
+//
+//
+
+// system include files
+#include
+#include
+
+// user include files
+#include "FWCore/Framework/interface/Frameworkfwd.h"
+#include "FWCore/Framework/interface/one/EDAnalyzer.h"
+
+#include "FWCore/Framework/interface/Event.h"
+#include "FWCore/Framework/interface/MakerMacros.h"
+
+#include "FWCore/ParameterSet/interface/ParameterSet.h"
+#include "FWCore/Utilities/interface/InputTag.h"
+
+#include "DataFormats/Luminosity/interface/LumiInfo.h"
+
+//
+// class declaration
+//
+
+// If the analyzer does not use TFileService, please remove
+// the template argument to the base class so the class inherits
+// from edm::one::EDAnalyzer<>
+// This will improve performance in multithreaded jobs.
+
+class TestLumiProducerFromBrilcalc : public edm::one::EDAnalyzer<> {
+public:
+ explicit TestLumiProducerFromBrilcalc(const edm::ParameterSet&);
+ ~TestLumiProducerFromBrilcalc();
+
+ static void fillDescriptions(edm::ConfigurationDescriptions& descriptions);
+
+private:
+ virtual void beginJob() override;
+ virtual void analyze(const edm::Event&, const edm::EventSetup&) override;
+ virtual void endJob() override;
+
+ // ----------member data ---------------------------
+ edm::InputTag inputTag_;
+ edm::EDGetTokenT lumiToken_;
+};
+
+//
+// constants, enums and typedefs
+//
+
+//
+// static data member definitions
+//
+
+//
+// constructors and destructor
+//
+TestLumiProducerFromBrilcalc::TestLumiProducerFromBrilcalc(const edm::ParameterSet& iConfig)
+ : inputTag_(iConfig.getUntrackedParameter("inputTag")), lumiToken_(consumes(inputTag_)) {}
+
+TestLumiProducerFromBrilcalc::~TestLumiProducerFromBrilcalc() {
+ // do anything here that needs to be done at destruction time
+ // (e.g. close files, deallocate resources etc.)
+}
+
+//
+// member functions
+//
+
+// ------------ method called for each event ------------
+void TestLumiProducerFromBrilcalc::analyze(const edm::Event& iEvent, const edm::EventSetup& iSetup) {
+ using namespace edm;
+
+ const LumiInfo& lumi = iEvent.get(lumiToken_);
+
+ std::cout << "Luminosity for " << iEvent.run() << " LS " << iEvent.luminosityBlock() << " is "
+ << lumi.getTotalInstLumi() << std::endl;
+}
+
+// ------------ method called once each job just before starting event loop ------------
+void TestLumiProducerFromBrilcalc::beginJob() {}
+
+// ------------ method called once each job just after ending the event loop ------------
+void TestLumiProducerFromBrilcalc::endJob() {}
+
+// ------------ method fills 'descriptions' with the allowed parameters for the module ------------
+void TestLumiProducerFromBrilcalc::fillDescriptions(edm::ConfigurationDescriptions& descriptions) {
+ // Allowed parameters
+ edm::ParameterSetDescription desc;
+ desc.addUntracked("inputTag");
+ descriptions.addDefault(desc);
+}
+
+//define this as a plug-in
+DEFINE_FWK_MODULE(TestLumiProducerFromBrilcalc);
diff --git a/RecoLuminosity/LumiProducer/test/TestLumiProducerFromBrilcalc_cfg.py b/RecoLuminosity/LumiProducer/test/TestLumiProducerFromBrilcalc_cfg.py
new file mode 100755
index 0000000000000..c084efa38c1ac
--- /dev/null
+++ b/RecoLuminosity/LumiProducer/test/TestLumiProducerFromBrilcalc_cfg.py
@@ -0,0 +1,30 @@
+import FWCore.ParameterSet.Config as cms
+
+process = cms.Process("TestLumiProducerFromBrilcalc")
+
+process.load("FWCore.MessageLogger.MessageLogger_cfi")
+process.MessageLogger = cms.Service("MessageLogger",
+ destinations = cms.untracked.vstring("cout"),
+ categories = cms.untracked.vstring("LumiProducerFromBrilcalc"),
+ debugModules = cms.untracked.vstring("LumiInfo"),
+ cout = cms.untracked.PSet(
+ threshold = cms.untracked.string('DEBUG')
+ )
+)
+
+# just use a random relval which has meaningless run/LS numbers, and then a corresponding test file
+process.source = cms.Source("PoolSource",
+ fileNames = cms.untracked.vstring("/store/relval/CMSSW_10_2_7/RelValMinBias_13/GEN-SIM/102X_mc2017_realistic_v4_AC_v01-v1/20000/BB654FAE-5375-164F-BBFE-B330713759C6.root")
+)
+process.maxEvents = cms.untracked.PSet(input = cms.untracked.int32(10))
+
+process.LumiInfo = cms.EDProducer('LumiProducerFromBrilcalc',
+ lumiFile = cms.string("./testLumiFile.csv"),
+ throwIfNotFound = cms.bool(False),
+ doBunchByBunch = cms.bool(False))
+
+process.test = cms.EDAnalyzer('TestLumiProducerFromBrilcalc',
+ inputTag = cms.untracked.InputTag("LumiInfo", "brilcalc"))
+
+process.p = cms.Path(process.LumiInfo*process.test)
+
diff --git a/RecoLuminosity/LumiProducer/test/testLumiFile.csv b/RecoLuminosity/LumiProducer/test/testLumiFile.csv
new file mode 100644
index 0000000000000..9f163255772dd
--- /dev/null
+++ b/RecoLuminosity/LumiProducer/test/testLumiFile.csv
@@ -0,0 +1,4 @@
+# This is a dummy file for TestLumiProducerFromBrilcalc.
+#run:fill,ls,time,beamstatus,E(GeV),delivered(hz/ub),recorded(hz/ub),avgpu,source
+1:1,1:1,04/17/18 10:54:40,STABLE BEAMS,6500,16.507442576,16.080153561,58.7,HFOC
+1:1,2:2,04/17/18 10:55:03,STABLE BEAMS,6500,16.483134426,1.668723696,58.6,HFOC