CMS 3D CMS Logo

List of all members | Public Member Functions | Static Public Member Functions | Private Member Functions | Private Attributes
PFCandidateRecalibrator Class Reference
Inheritance diagram for PFCandidateRecalibrator:
edm::stream::EDProducer<> edm::stream::EDProducerBase edm::ProducerBase edm::EDConsumerBase edm::ProductRegistryHelper

Public Member Functions

 PFCandidateRecalibrator (const edm::ParameterSet &)
 
 ~PFCandidateRecalibrator () override
 
- Public Member Functions inherited from edm::stream::EDProducer<>
 EDProducer ()=default
 
- Public Member Functions inherited from edm::stream::EDProducerBase
 EDProducerBase ()
 
ModuleDescription const & moduleDescription () const
 
 ~EDProducerBase () override
 
- Public Member Functions inherited from edm::ProducerBase
void callWhenNewProductsRegistered (std::function< void(BranchDescription const &)> const &func)
 
std::vector< edm::ProductResolverIndex > const & indiciesForPutProducts (BranchType iBranchType) const
 
 ProducerBase ()
 
std::vector< edm::ProductResolverIndex > const & putTokenIndexToProductResolverIndex () const
 
void registerProducts (ProducerBase *, ProductRegistry *, ModuleDescription const &)
 
std::function< void(BranchDescription const &)> registrationCallback () const
 used by the fwk to register list of products More...
 
void resolvePutIndicies (BranchType iBranchType, ModuleToResolverIndicies const &iIndicies, std::string const &moduleLabel)
 
virtual ~ProducerBase () noexcept(false)
 
- Public Member Functions inherited from edm::EDConsumerBase
std::vector< ConsumesInfoconsumesInfo () const
 
void convertCurrentProcessAlias (std::string const &processName)
 Convert "@currentProcess" in InputTag process names to the actual current process name. More...
 
 EDConsumerBase ()
 
 EDConsumerBase (EDConsumerBase const &)=delete
 
 EDConsumerBase (EDConsumerBase &&)=default
 
ProductResolverIndexAndSkipBit indexFrom (EDGetToken, BranchType, TypeID const &) const
 
void itemsMayGet (BranchType, std::vector< ProductResolverIndexAndSkipBit > &) const
 
void itemsToGet (BranchType, std::vector< ProductResolverIndexAndSkipBit > &) const
 
std::vector< ProductResolverIndexAndSkipBit > const & itemsToGetFrom (BranchType iType) const
 
void labelsForToken (EDGetToken iToken, Labels &oLabels) const
 
void modulesWhoseProductsAreConsumed (std::vector< ModuleDescription const * > &modules, ProductRegistry const &preg, std::map< std::string, ModuleDescription const * > const &labelsToDesc, std::string const &processName) const
 
EDConsumerBase const & operator= (EDConsumerBase const &)=delete
 
EDConsumerBaseoperator= (EDConsumerBase &&)=default
 
bool registeredToConsume (ProductResolverIndex, bool, BranchType) const
 
bool registeredToConsumeMany (TypeID const &, BranchType) const
 
void updateLookup (BranchType iBranchType, ProductResolverIndexHelper const &, bool iPrefetchMayGet)
 
virtual ~EDConsumerBase () noexcept(false)
 

Static Public Member Functions

static void fillDescriptions (edm::ConfigurationDescriptions &descriptions)
 
- Static Public Member Functions inherited from edm::stream::EDProducerBase
static const std::string & baseType ()
 
static void fillDescriptions (ConfigurationDescriptions &descriptions)
 
static void prevalidate (ConfigurationDescriptions &descriptions)
 

Private Member Functions

void beginRun (const edm::Run &iRun, edm::EventSetup const &iSetup) override
 
void endRun (const edm::Run &iRun, edm::EventSetup const &iSetup) override
 
void produce (edm::Event &, const edm::EventSetup &) override
 

Private Attributes

std::vector< HEChannelbadChHE_
 
std::vector< HFChannelbadChHF_
 
edm::ESWatcher< HcalRecNumberingRecordhcalDbWatcher_
 
edm::ESWatcher< HcalRespCorrsRcdhcalRCWatcher_
 
float longFibreThr_
 
edm::EDGetTokenT< reco::PFCandidateCollectionpfcandidates_
 
float shortFibreThr_
 

Additional Inherited Members

- Public Types inherited from edm::stream::EDProducer<>
typedef CacheContexts< T... > CacheTypes
 
typedef CacheTypes::GlobalCache GlobalCache
 
typedef AbilityChecker< T... > HasAbility
 
typedef CacheTypes::LuminosityBlockCache LuminosityBlockCache
 
typedef LuminosityBlockContextT< LuminosityBlockCache, RunCache, GlobalCacheLuminosityBlockContext
 
typedef CacheTypes::LuminosityBlockSummaryCache LuminosityBlockSummaryCache
 
typedef CacheTypes::RunCache RunCache
 
typedef RunContextT< RunCache, GlobalCacheRunContext
 
typedef CacheTypes::RunSummaryCache RunSummaryCache
 
- Public Types inherited from edm::stream::EDProducerBase
typedef EDProducerAdaptorBase ModuleType
 
- Public Types inherited from edm::ProducerBase
using ModuleToResolverIndicies = std::unordered_multimap< std::string, std::tuple< edm::TypeID const *, const char *, edm::ProductResolverIndex >>
 
typedef ProductRegistryHelper::TypeLabelList TypeLabelList
 
- Public Types inherited from edm::EDConsumerBase
typedef ProductLabels Labels
 
- Protected Member Functions inherited from edm::EDConsumerBase
template<typename ProductType , BranchType B = InEvent>
EDGetTokenT< ProductType > consumes (edm::InputTag const &tag)
 
EDGetToken consumes (const TypeToGet &id, edm::InputTag const &tag)
 
template<BranchType B>
EDGetToken consumes (TypeToGet const &id, edm::InputTag const &tag)
 
ConsumesCollector consumesCollector ()
 Use a ConsumesCollector to gather consumes information from helper functions. More...
 
template<typename ProductType , BranchType B = InEvent>
void consumesMany ()
 
void consumesMany (const TypeToGet &id)
 
template<BranchType B>
void consumesMany (const TypeToGet &id)
 
template<typename ProductType , BranchType B = InEvent>
EDGetTokenT< ProductType > mayConsume (edm::InputTag const &tag)
 
EDGetToken mayConsume (const TypeToGet &id, edm::InputTag const &tag)
 
template<BranchType B>
EDGetToken mayConsume (const TypeToGet &id, edm::InputTag const &tag)
 

Detailed Description

Definition at line 54 of file PFCandidateRecalibrator.cc.

Constructor & Destructor Documentation

PFCandidateRecalibrator::PFCandidateRecalibrator ( const edm::ParameterSet iConfig)

Definition at line 78 of file PFCandidateRecalibrator.cc.

78  :
79  pfcandidates_(consumes<reco::PFCandidateCollection>(iConfig.getParameter<edm::InputTag>("pfcandidates"))),
80  shortFibreThr_(iConfig.getParameter<double>("shortFibreThr")),
81  longFibreThr_(iConfig.getParameter<double>("longFibreThr"))
82 {
83  produces<reco::PFCandidateCollection>();
84  produces<reco::PFCandidateCollection>("discarded");
85  produces<edm::ValueMap<reco::PFCandidateRef>>();
86 }
T getParameter(std::string const &) const
edm::EDGetTokenT< reco::PFCandidateCollection > pfcandidates_
PFCandidateRecalibrator::~PFCandidateRecalibrator ( )
inlineoverride

Definition at line 57 of file PFCandidateRecalibrator.cc.

References Ecal2004TBTDCRanges_v1_cff::endRun.

57 {};

Member Function Documentation

void PFCandidateRecalibrator::beginRun ( const edm::Run iRun,
edm::EventSetup const &  iSetup 
)
overrideprivate

Definition at line 88 of file PFCandidateRecalibrator.cc.

References funct::abs(), badChHE_, badChHF_, edm::ESWatcher< T >::check(), HcalDetId::depth(), PV3DBase< T, PVType, FrameType >::eta(), f, edm::EventSetup::get(), HcalDbService::getHcalRespCorr(), HcalGeometry::getPosition(), CaloGeometry::getSubdetectorGeometry(), HcalGeometry::getValidDetIds(), HcalRespCorr::getValue(), DetId::Hcal, hcalDbWatcher_, HcalEndcap, HcalForward, hcalRCWatcher_, HcalDetId::ieta(), HcalDetId::iphi(), PV3DBase< T, PVType, FrameType >::phi(), edm::ESHandle< T >::product(), particleFlowDisplacedVertex_cfi::ratio, and HcalCondObjectContainerBase::setTopo().

89 {
90  if (hcalDbWatcher_.check(iSetup) || hcalRCWatcher_.check(iSetup))
91  {
92  //Get Calib Constants from current GT
94  iSetup.get<HcalDbRecord>().get(gtCond);
95 
96  //Get Calib Constants from bugged tag
98  iSetup.get<HcalRecNumberingRecord>().get(htopo);
99  const HcalTopology* theHBHETopology = htopo.product();
100 
101  edm::ESHandle<HcalRespCorrs> buggedCond;
102  iSetup.get<HcalRespCorrsRcd>().get("bugged", buggedCond);
103  HcalRespCorrs buggedRespCorrs(*buggedCond.product());
104  buggedRespCorrs.setTopo(theHBHETopology);
105 
106  //access calogeometry
108  iSetup.get<CaloGeometryRecord>().get(calogeom);
109  const CaloGeometry* cgeo = calogeom.product();
110  const HcalGeometry* hgeom = static_cast<const HcalGeometry*>(cgeo->getSubdetectorGeometry(DetId::Hcal,HcalForward));
111 
112  //reset the bad channel containers
113  badChHE_.clear();
114  badChHF_.clear();
115 
116  //fill bad cells HE (use eta, phi)
117  const std::vector<DetId>& cellsHE = hgeom->getValidDetIds(DetId::Detector::Hcal, HcalEndcap);
118  for( auto id : cellsHE)
119  {
120  float currentRespCorr = gtCond->getHcalRespCorr(id)->getValue();
121  float buggedRespCorr = buggedRespCorrs.getValues(id)->getValue();
122  if (buggedRespCorr == 0.)
123  continue;
124 
125  float ratio = currentRespCorr/buggedRespCorr;
126  if( std::abs(ratio - 1.f) > 0.001 )
127  {
128  GlobalPoint pos = hgeom->getPosition(id);
129  badChHE_.push_back(HEChannel(pos.eta(),pos.phi(),ratio));
130  }
131  }
132 
133  //fill bad cells HF (use ieta, iphi)
134  auto const& cellsHF = hgeom->getValidDetIds(DetId::Detector::Hcal, HcalForward);
135  for( auto id : cellsHF)
136  {
137  float currentRespCorr = gtCond->getHcalRespCorr(id)->getValue();
138  float buggedRespCorr = buggedRespCorrs.getValues(id)->getValue();
139  if (buggedRespCorr == 0.)
140  continue;
141 
142  float ratio = currentRespCorr/buggedRespCorr;
143  if( std::abs(ratio - 1.f) > 0.001 )
144  {
145  HcalDetId dummyId(id);
146  badChHF_.push_back(HFChannel(dummyId.ieta(), dummyId.iphi(), dummyId.depth(), ratio));
147  }
148  }
149  }
150 }
const CaloSubdetectorGeometry * getSubdetectorGeometry(const DetId &id) const
access the subdetector geometry for the given subdetector directly
Definition: CaloGeometry.cc:45
edm::ESWatcher< HcalRecNumberingRecord > hcalDbWatcher_
const std::vector< DetId > & getValidDetIds(DetId::Detector det=DetId::Detector(0), int subdet=0) const override
Get a list of valid detector ids (for the given subdetector)
Definition: HcalGeometry.cc:76
Geom::Phi< T > phi() const
Definition: PV3DBase.h:69
std::vector< HEChannel > badChHE_
const HcalRespCorr * getHcalRespCorr(const HcalGenericDetId &fId) const
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
double f[11][100]
GlobalPoint getPosition(const DetId &id) const
edm::ESWatcher< HcalRespCorrsRcd > hcalRCWatcher_
std::vector< HFChannel > badChHF_
bool check(const edm::EventSetup &iSetup)
Definition: ESWatcher.h:57
T eta() const
Definition: PV3DBase.h:76
float getValue() const
Definition: HcalRespCorr.h:20
T const * product() const
Definition: ESHandle.h:86
void setTopo(const HcalTopology *topo)
void PFCandidateRecalibrator::endRun ( const edm::Run iRun,
edm::EventSetup const &  iSetup 
)
overrideprivate

Definition at line 152 of file PFCandidateRecalibrator.cc.

153 {
154 }
void PFCandidateRecalibrator::fillDescriptions ( edm::ConfigurationDescriptions descriptions)
static

Definition at line 341 of file PFCandidateRecalibrator.cc.

References edm::ConfigurationDescriptions::add(), edm::ParameterSetDescription::add(), and DEFINE_FWK_MODULE.

342 {
344 
345  desc.add<edm::InputTag>("pfcandidates", edm::InputTag("particleFlow"));
346  desc.add<double>("shortFibreThr", 1.4);
347  desc.add<double>("longFibreThr", 1.4);
348 
349  descriptions.add("pfCandidateRecalibrator", desc);
350 
351 }
ParameterDescriptionBase * add(U const &iLabel, T const &value)
void add(std::string const &label, ParameterSetDescription const &psetDescription)
void PFCandidateRecalibrator::produce ( edm::Event iEvent,
const edm::EventSetup iSetup 
)
overrideprivate

Definition at line 156 of file PFCandidateRecalibrator.cc.

References funct::abs(), badChHE_, badChHF_, popcon2dropbox::copy(), reco::deltaR2(), edm::helper::Filler< Map >::fill(), objects.autophobj::filler, edm::EventSetup::get(), edm::Event::getByToken(), HcalGeometry::getClosestCell(), CaloGeometry::getSubdetectorGeometry(), DetId::Hcal, HcalForward, mps_fire::i, edm::helper::Filler< Map >::insert(), LogDebug, longFibreThr_, eostools::move(), lumidbDDL::newToOld(), lumidbDDL::oldToNew(), packedPFCandidateRefMixer_cfi::pf, packedPFCandidateRefMixer_cfi::pf2pf, pfcandidates_, edm::ESHandle< T >::product(), edm::Event::put(), and shortFibreThr_.

Referenced by JSONExport.JsonExport::export(), HTMLExport.HTMLExport::export(), and HTMLExport.HTMLExportStatic::export().

157 {
158  //access calogeometry
160  iSetup.get<CaloGeometryRecord>().get(calogeom);
161  const CaloGeometry* cgeo = calogeom.product();
162  const HcalGeometry* hgeom = static_cast<const HcalGeometry*>(cgeo->getSubdetectorGeometry(DetId::Hcal,HcalForward));
163 
164  //access PFCandidates
166  iEvent.getByToken(pfcandidates_, pfcandidates);
167 
168  int nPfCand = pfcandidates->size();
169  std::unique_ptr<reco::PFCandidateCollection> copy(new reco::PFCandidateCollection());
170  std::unique_ptr<reco::PFCandidateCollection> discarded(new reco::PFCandidateCollection());
171  copy->reserve(nPfCand);
172  std::vector<int> oldToNew(nPfCand), newToOld, badToOld;
173  newToOld.reserve(nPfCand);
174 
175  LogDebug("PFCandidateRecalibrator") << "NEW EV:";
176 
177  //loop over PFCandidates
178  int i = -1;
179  for (const reco::PFCandidate &pf : *pfcandidates)
180  {
181  ++i;
182  float absEta = std::abs(pf.eta());
183 
184  //deal with HE
185  if( pf.particleId() == reco::PFCandidate::ParticleType::h0 &&
186  !badChHE_.empty() && //don't touch if no miscalibration is found
187  absEta > 1.4 && absEta < 3.)
188  {
189  bool toKill = false;
190  for(auto const& badIt: badChHE_)
191  if( reco::deltaR2(pf.eta(), pf.phi(), badIt.eta, badIt.phi) < 0.07 )
192  toKill = true;
193 
194 
195  if(toKill)
196  {
197  discarded->push_back(pf);
198  oldToNew[i] = (-discarded->size());
199  badToOld.push_back(i);
200  continue;
201  }
202  else
203  {
204  copy->push_back(pf);
205  oldToNew[i] = (copy->size());
206  newToOld.push_back(i);
207  }
208  }
209  //deal with HF
210  else if( (pf.particleId() == reco::PFCandidate::ParticleType::h_HF || pf.particleId() == reco::PFCandidate::ParticleType::egamma_HF) &&
211  !badChHF_.empty() && //don't touch if no miscalibration is found
212  absEta >= 3.)
213  {
214  const math::XYZPointF& ecalPoint = pf.positionAtECALEntrance();
215  GlobalPoint ecalGPoint(ecalPoint.X(),ecalPoint.Y(),ecalPoint.Z());
216  HcalDetId closestDetId(hgeom->getClosestCell(ecalGPoint));
217 
218  if(closestDetId.subdet() == HcalForward)
219  {
220  HcalDetId hDetId(closestDetId.subdet(),closestDetId.ieta(),closestDetId.iphi(),1); //depth1
221 
222  //raw*calEnergy() is the same as *calEnergy() - no corrections are done for HF
223  float longE = pf.rawEcalEnergy() + pf.rawHcalEnergy()/2.; //depth1
224  float shortE = pf.rawHcalEnergy()/2.; //depth2
225 
226  float ecalEnergy = pf.rawEcalEnergy();
227  float hcalEnergy = pf.rawHcalEnergy();
228  float totEnergy = ecalEnergy + hcalEnergy;
229  float totEnergyOrig = totEnergy;
230 
231  bool toKill = false;
232 
233  for(auto const& badIt: badChHF_)
234  {
235  if ( hDetId.ieta() == badIt.ieta &&
236  hDetId.iphi() == badIt.iphi )
237  {
238  LogDebug("PFCandidateRecalibrator") << "==> orig en (tot,H,E): "
239  << pf.energy() << " " << pf.rawHcalEnergy() << " " << pf.rawEcalEnergy();
240  if(badIt.depth == 1) //depth1
241  {
242  longE *= badIt.ratio;
243  ecalEnergy = ((longE - shortE) > 0.) ? (longE - shortE) : 0.;
244  totEnergy = ecalEnergy + hcalEnergy;
245  }
246  else //depth2
247  {
248  shortE *= badIt.ratio;
249  hcalEnergy = 2*shortE;
250  ecalEnergy = ((longE - shortE) > 0.) ? (longE - shortE) : 0.;
251  totEnergy = ecalEnergy + hcalEnergy;
252  }
253  //kill candidate if goes below thr
254  if((pf.particleId() == reco::PFCandidate::ParticleType::h_HF && shortE < shortFibreThr_) ||
255  (pf.particleId() == reco::PFCandidate::ParticleType::egamma_HF && longE < longFibreThr_))
256  toKill = true;
257 
258  LogDebug("PFCandidateRecalibrator") << "====> ieta,iphi,depth: "
259  << badIt.ieta << " " << badIt.iphi << " " << badIt.depth << " corr: " << badIt.ratio;
260  LogDebug("PFCandidateRecalibrator") << "====> recal en (tot,H,E): "
261  << totEnergy << " " << hcalEnergy << " " << ecalEnergy;
262 
263  }
264  }
265 
266  if(toKill)
267  {
268  discarded->push_back(pf);
269  oldToNew[i] = (-discarded->size());
270  badToOld.push_back(i);
271 
272  LogDebug("PFCandidateRecalibrator") << "==> KILLED ";
273  }
274  else
275  {
276  copy->push_back(pf);
277  oldToNew[i] = (copy->size());
278  newToOld.push_back(i);
279 
280  copy->back().setHcalEnergy(hcalEnergy, hcalEnergy);
281  copy->back().setEcalEnergy(ecalEnergy, ecalEnergy);
282 
283  float scalingFactor = totEnergy/totEnergyOrig;
284  math::XYZTLorentzVector recalibP4 = pf.p4() * scalingFactor;
285  copy->back().setP4( recalibP4 );
286 
287  LogDebug("PFCandidateRecalibrator") << "====> stored en (tot,H,E): "
288  << copy->back().energy() << " " << copy->back().hcalEnergy() << " " << copy->back().ecalEnergy();
289  }
290  }
291  else
292  {
293  copy->push_back(pf);
294  oldToNew[i] = (copy->size());
295  newToOld.push_back(i);
296  }
297  }
298  else
299  {
300  copy->push_back(pf);
301  oldToNew[i] = (copy->size());
302  newToOld.push_back(i);
303  }
304  }
305 
306  // Now we put things in the event
308  edm::OrphanHandle<reco::PFCandidateCollection> badpf = iEvent.put(std::move(discarded), "discarded");
309 
310  std::unique_ptr<edm::ValueMap<reco::PFCandidateRef>> pf2pf(new edm::ValueMap<reco::PFCandidateRef>());
312  std::vector<reco::PFCandidateRef> refs; refs.reserve(nPfCand);
313 
314  // old to new
315  for (auto iOldToNew : oldToNew){
316  if (iOldToNew > 0) {
317  refs.push_back(reco::PFCandidateRef(newpf, iOldToNew-1));
318  } else {
319  refs.push_back(reco::PFCandidateRef(badpf,-iOldToNew-1));
320  }
321  }
322  filler.insert(pfcandidates, refs.begin(), refs.end());
323  // new good to old
324  refs.clear();
325  for (int i : newToOld) {
326  refs.push_back(reco::PFCandidateRef(pfcandidates,i));
327  }
328  filler.insert(newpf, refs.begin(), refs.end());
329  // new bad to old
330  refs.clear();
331  for (int i : badToOld) {
332  refs.push_back(reco::PFCandidateRef(pfcandidates,i));
333  }
334  filler.insert(badpf, refs.begin(), refs.end());
335  // done
336  filler.fill();
337  iEvent.put(std::move(pf2pf));
338 }
#define LogDebug(id)
const CaloSubdetectorGeometry * getSubdetectorGeometry(const DetId &id) const
access the subdetector geometry for the given subdetector directly
Definition: CaloGeometry.cc:45
OrphanHandle< PROD > put(std::unique_ptr< PROD > product)
Put a new product.
Definition: Event.h:127
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:508
std::vector< HEChannel > badChHE_
ROOT::Math::PositionVector3D< ROOT::Math::Cartesian3D< float > > XYZPointF
point in space with cartesian internal representation
Definition: Point3D.h:10
XYZTLorentzVectorD XYZTLorentzVector
Lorentz vector with cylindrical internal representation using pseudorapidity.
Definition: LorentzVector.h:29
def oldToNew(schema)
Definition: lumidbDDL.py:399
Abs< T >::type abs(const T &t)
Definition: Abs.h:22
std::vector< reco::PFCandidate > PFCandidateCollection
collection of PFCandidates
const T & get() const
Definition: EventSetup.h:55
std::vector< HFChannel > badChHF_
edm::EDGetTokenT< reco::PFCandidateCollection > pfcandidates_
T1 deltaR2(T1 eta1, T2 phi1, T3 eta2, T4 phi2)
Definition: deltaR.h:36
Particle reconstructed by the particle flow algorithm.
Definition: PFCandidate.h:39
def newToOld(schema)
Definition: lumidbDDL.py:413
T const * product() const
Definition: ESHandle.h:86
def move(src, dest)
Definition: eostools.py:510
DetId getClosestCell(const GlobalPoint &r) const override

Member Data Documentation

std::vector<HEChannel> PFCandidateRecalibrator::badChHE_
private

Definition at line 71 of file PFCandidateRecalibrator.cc.

Referenced by beginRun(), and produce().

std::vector<HFChannel> PFCandidateRecalibrator::badChHF_
private

Definition at line 72 of file PFCandidateRecalibrator.cc.

Referenced by beginRun(), and produce().

edm::ESWatcher<HcalRecNumberingRecord> PFCandidateRecalibrator::hcalDbWatcher_
private

Definition at line 66 of file PFCandidateRecalibrator.cc.

Referenced by beginRun().

edm::ESWatcher<HcalRespCorrsRcd> PFCandidateRecalibrator::hcalRCWatcher_
private

Definition at line 67 of file PFCandidateRecalibrator.cc.

Referenced by beginRun().

float PFCandidateRecalibrator::longFibreThr_
private

Definition at line 75 of file PFCandidateRecalibrator.cc.

Referenced by produce().

edm::EDGetTokenT<reco::PFCandidateCollection> PFCandidateRecalibrator::pfcandidates_
private

Definition at line 69 of file PFCandidateRecalibrator.cc.

Referenced by produce().

float PFCandidateRecalibrator::shortFibreThr_
private

Definition at line 74 of file PFCandidateRecalibrator.cc.

Referenced by produce().