CMS 3D CMS Logo

List of all members | Public Member Functions | Private Member Functions | Private Attributes
GenParticlePruner Class Reference
Inheritance diagram for GenParticlePruner:
edm::stream::EDProducer<>

Public Member Functions

 GenParticlePruner (const edm::ParameterSet &)
 
- Public Member Functions inherited from edm::stream::EDProducer<>
 EDProducer ()=default
 
bool hasAbilityToProduceInBeginLumis () const final
 
bool hasAbilityToProduceInBeginRuns () const final
 
bool hasAbilityToProduceInEndLumis () const final
 
bool hasAbilityToProduceInEndRuns () const final
 

Private Member Functions

void flagDaughters (const reco::GenParticle &, int)
 
void flagMothers (const reco::GenParticle &, int)
 
void getDaughterKeys (std::vector< size_t > &, std::vector< size_t > &, const reco::GenParticleRefVector &) const
 
void getMotherKeys (std::vector< size_t > &, std::vector< size_t > &, const reco::GenParticleRefVector &) const
 
void parse (const std::string &selection, helper::SelectCode &code, std::string &cut) const
 
void produce (edm::Event &, const edm::EventSetup &) override
 
void recursiveFlagDaughters (size_t, const reco::GenParticleCollection &, int, std::vector< size_t > &)
 
void recursiveFlagMothers (size_t, const reco::GenParticleCollection &, int, std::vector< size_t > &)
 

Private Attributes

bool firstEvent_
 
std::vector< int > flags_
 
std::vector< size_t > indices_
 
int keepOrDropAll_
 
std::vector< std::pair< StringCutObjectSelector< reco::GenParticle >, helper::SelectCode > > select_
 
std::vector< std::string > selection_
 
edm::EDGetTokenT< reco::GenParticleCollectionsrcToken_
 

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
 

Detailed Description

Definition at line 22 of file GenParticlePruner.cc.

Constructor & Destructor Documentation

◆ GenParticlePruner()

GenParticlePruner::GenParticlePruner ( const edm::ParameterSet cfg)

Definition at line 98 of file GenParticlePruner.cc.

99  : firstEvent_(true),
100  srcToken_(consumes<GenParticleCollection>(cfg.getParameter<InputTag>("src"))),
102  selection_(cfg.getParameter<vector<string>>("select")) {
103  using namespace ::helper;
104  produces<GenParticleCollection>();
105  produces<edm::Association<reco::GenParticleCollection>>();
106 }

Member Function Documentation

◆ flagDaughters()

void GenParticlePruner::flagDaughters ( const reco::GenParticle gen,
int  keepOrDrop 
)
private

Definition at line 108 of file GenParticlePruner.cc.

108  {
109  const GenParticleRefVector &daughters = gen.daughterRefVector();
110  for (GenParticleRefVector::const_iterator i = daughters.begin(); i != daughters.end(); ++i)
111  flags_[i->key()] = keepOrDrop;
112 }

References BPhysicsValidation_cfi::daughters, flags_, and mps_fire::i.

Referenced by produce().

◆ flagMothers()

void GenParticlePruner::flagMothers ( const reco::GenParticle gen,
int  keepOrDrop 
)
private

Definition at line 114 of file GenParticlePruner.cc.

114  {
115  const GenParticleRefVector &mothers = gen.motherRefVector();
116  for (GenParticleRefVector::const_iterator i = mothers.begin(); i != mothers.end(); ++i)
117  flags_[i->key()] = keepOrDrop;
118 }

References edm::RefVector< C, T, F >::begin(), edm::RefVector< C, T, F >::end(), flags_, and mps_fire::i.

Referenced by produce().

◆ getDaughterKeys()

void GenParticlePruner::getDaughterKeys ( std::vector< size_t > &  daIndxs,
std::vector< size_t > &  daNewIndxs,
const reco::GenParticleRefVector daughters 
) const
private

Definition at line 283 of file GenParticlePruner.cc.

285  {
286  for (GenParticleRefVector::const_iterator j = daughters.begin(); j != daughters.end(); ++j) {
287  GenParticleRef dau = *j;
288  if (find(daIndxs.begin(), daIndxs.end(), dau.key()) == daIndxs.end()) {
289  daIndxs.push_back(dau.key());
290  int idx = flags_[dau.key()];
291  if (idx > 0) {
292  daNewIndxs.push_back(idx);
293  } else {
294  const GenParticleRefVector &daus = dau->daughterRefVector();
295  if (!daus.empty())
296  getDaughterKeys(daIndxs, daNewIndxs, daus);
297  }
298  }
299  }
300 }

References BPhysicsValidation_cfi::daughters, edm::RefVector< C, T, F >::empty(), spr::find(), flags_, training_settings::idx, dqmiolumiharvest::j, and edm::Ref< C, T, F >::key().

Referenced by produce().

◆ getMotherKeys()

void GenParticlePruner::getMotherKeys ( std::vector< size_t > &  moIndxs,
std::vector< size_t > &  moNewIndxs,
const reco::GenParticleRefVector mothers 
) const
private

Definition at line 302 of file GenParticlePruner.cc.

304  {
305  for (GenParticleRefVector::const_iterator j = mothers.begin(); j != mothers.end(); ++j) {
306  GenParticleRef mom = *j;
307  if (find(moIndxs.begin(), moIndxs.end(), mom.key()) == moIndxs.end()) {
308  moIndxs.push_back(mom.key());
309  int idx = flags_[mom.key()];
310  if (idx >= 0) {
311  moNewIndxs.push_back(idx);
312  } else {
313  const GenParticleRefVector &moms = mom->motherRefVector();
314  if (!moms.empty())
315  getMotherKeys(moIndxs, moNewIndxs, moms);
316  }
317  }
318  }
319 }

References edm::RefVector< C, T, F >::begin(), edm::RefVector< C, T, F >::empty(), edm::RefVector< C, T, F >::end(), spr::find(), flags_, training_settings::idx, dqmiolumiharvest::j, and edm::Ref< C, T, F >::key().

Referenced by produce().

◆ parse()

void GenParticlePruner::parse ( const std::string &  selection,
helper::SelectCode code,
std::string &  cut 
) const
private

Definition at line 50 of file GenParticlePruner.cc.

50  {
51  using namespace ::helper;
52  size_t f = selection.find_first_not_of(' ');
53  size_t n = selection.size();
54  string command;
55  char c;
56  for (; (c = selection[f]) != ' ' && f < n; ++f) {
57  command.push_back(c);
58  }
59  if (command[0] == '+') {
60  command.erase(0, 1);
61  if (command[0] == '+') {
62  command.erase(0, 1);
63  code.mothersDepth_ = SelectCode::kAll;
64  } else {
65  code.mothersDepth_ = SelectCode::kFirst;
66  }
67  } else
69 
70  if (command[command.size() - 1] == '+') {
71  command.erase(command.size() - 1);
72  if (command[command.size() - 1] == '+') {
73  command.erase(command.size() - 1);
74  code.daughtersDepth_ = SelectCode::kAll;
75  } else {
76  code.daughtersDepth_ = SelectCode::kFirst;
77  }
78  } else
80 
81  if (command == "keep")
82  code.keepOrDrop_ = SelectCode::kKeep;
83  else if (command == "drop")
84  code.keepOrDrop_ = SelectCode::kDrop;
85  else {
86  throw Exception(errors::Configuration) << "invalid selection command: " << command << "\n" << endl;
87  }
88  for (; f < n; ++f) {
89  if (selection[f] != ' ')
90  break;
91  }
92  cut = string(selection, f);
93  if (cut[0] == '*')
94  cut = string(cut, 0, cut.find_first_of(' '));
95  code.all_ = cut == "*";
96 }

References helper::SelectCode::all_, HltBtagPostValidation_cff::c, mps_check::command, edm::errors::Configuration, TkAlMuonSelectors_cfi::cut, helper::SelectCode::daughtersDepth_, Exception, f, helper::SelectCode::keepOrDrop_, WDecay::kNone, helper::SelectCode::mothersDepth_, dqmiodumpmetadata::n, corrVsCorr::selection, and AlCaHLTBitMon_QueryRunRegistry::string.

Referenced by produce().

◆ produce()

void GenParticlePruner::produce ( edm::Event evt,
const edm::EventSetup es 
)
overrideprivate

Definition at line 162 of file GenParticlePruner.cc.

162  {
163  if (firstEvent_) {
164  PdgEntryReplacer rep(es);
165  for (vector<string>::const_iterator i = selection_.begin(); i != selection_.end(); ++i) {
166  string cut;
167  ::helper::SelectCode code;
168  parse(*i, code, cut);
169  if (code.all_) {
170  if (i != selection_.begin())
172  << "selections \"keep *\" and \"drop *\" can be used only as first options. Here used in position # "
173  << (i - selection_.begin()) + 1 << "\n"
174  << endl;
175  switch (code.keepOrDrop_) {
176  case ::helper::SelectCode::kDrop:
178  break;
179  case ::helper::SelectCode::kKeep:
181  };
182  } else {
183  cut = rep.replace(cut);
184  select_.push_back(make_pair(StringCutObjectSelector<GenParticle>(cut), code));
185  }
186  }
187  firstEvent_ = false;
188  }
189 
190  using namespace ::helper;
192  evt.getByToken(srcToken_, src);
193  const size_t n = src->size();
194  flags_.clear();
195  flags_.resize(n, keepOrDropAll_);
196  for (size_t j = 0; j < select_.size(); ++j) {
197  const pair<StringCutObjectSelector<GenParticle>, SelectCode> &sel = select_[j];
198  SelectCode code = sel.second;
200  for (size_t i = 0; i < n; ++i) {
201  const GenParticle &p = (*src)[i];
202  if (cut(p)) {
203  int keepOrDrop = keep;
204  switch (code.keepOrDrop_) {
205  case SelectCode::kKeep:
206  keepOrDrop = keep;
207  break;
208  case SelectCode::kDrop:
209  keepOrDrop = drop;
210  };
211  flags_[i] = keepOrDrop;
212  std::vector<size_t> allIndicesDa;
213  std::vector<size_t> allIndicesMo;
214  switch (code.daughtersDepth_) {
215  case SelectCode::kAll:
216  recursiveFlagDaughters(i, *src, keepOrDrop, allIndicesDa);
217  break;
218  case SelectCode::kFirst:
219  flagDaughters(p, keepOrDrop);
220  break;
221  case SelectCode::kNone:;
222  };
223  switch (code.mothersDepth_) {
224  case SelectCode::kAll:
225  recursiveFlagMothers(i, *src, keepOrDrop, allIndicesMo);
226  break;
227  case SelectCode::kFirst:
228  flagMothers(p, keepOrDrop);
229  break;
230  case SelectCode::kNone:;
231  };
232  }
233  }
234  }
235  indices_.clear();
236  int counter = 0;
237  for (size_t i = 0; i < n; ++i) {
238  if (flags_[i] == keep) {
239  indices_.push_back(i);
240  flags_[i] = counter++;
241  } else {
242  flags_[i] = -1; //set to invalid ref
243  }
244  }
245 
246  auto out = std::make_unique<GenParticleCollection>();
248  out->reserve(counter);
249 
250  for (vector<size_t>::const_iterator i = indices_.begin(); i != indices_.end(); ++i) {
251  size_t index = *i;
252  const GenParticle &gen = (*src)[index];
253  const LeafCandidate &part = gen;
254  out->push_back(GenParticle(part));
255  GenParticle &newGen = out->back();
256  //fill status flags
257  newGen.statusFlags() = gen.statusFlags();
258  // The "daIndxs" and "moIndxs" keep a list of the keys for the mother/daughter
259  // parentage/descendency. In some cases, a circular referencing is encountered,
260  // which would result in an infinite loop. The list is checked to
261  // avoid this.
262  vector<size_t> daIndxs, daNewIndxs;
263  getDaughterKeys(daIndxs, daNewIndxs, gen.daughterRefVector());
264  std::sort(daNewIndxs.begin(), daNewIndxs.end());
265  for (size_t i = 0; i < daNewIndxs.size(); ++i)
266  newGen.addDaughter(GenParticleRef(outRef, daNewIndxs[i]));
267 
268  vector<size_t> moIndxs, moNewIndxs;
269  getMotherKeys(moIndxs, moNewIndxs, gen.motherRefVector());
270  std::sort(moNewIndxs.begin(), moNewIndxs.end());
271  for (size_t i = 0; i < moNewIndxs.size(); ++i)
272  newGen.addMother(GenParticleRef(outRef, moNewIndxs[i]));
273  }
274 
276  auto orig2new = std::make_unique<edm::Association<reco::GenParticleCollection>>(oh);
278  orig2newFiller.insert(src, flags_.begin(), flags_.end());
279  orig2newFiller.fill();
280  evt.put(std::move(orig2new));
281 }

References reco::CompositeRefCandidateT< D >::addDaughter(), reco::CompositeRefCandidateT< D >::addMother(), edm::errors::Configuration, TkAlMuonSelectors_cfi::cut, drop, Exception, firstEvent_, flagDaughters(), flagMothers(), flags_, relval_steps::gen(), GenParticle::GenParticle, edm::Event::getByToken(), getDaughterKeys(), getMotherKeys(), edm::Event::getRefBeforePut(), mps_fire::i, indices_, dqmiolumiharvest::j, keep, keepOrDropAll_, WDecay::kNone, eostools::move(), dqmiodumpmetadata::n, MillePedeFileConverter_cfg::out, AlCaHLTBitMon_ParallelJobs::p, parse(), edm::Event::put(), recursiveFlagDaughters(), recursiveFlagMothers(), cuy::rep, EgammaValidation_Wenu_cff::sel, select_, selection_, TrackRefitter_38T_cff::src, srcToken_, and reco::GenParticle::statusFlags().

◆ recursiveFlagDaughters()

void GenParticlePruner::recursiveFlagDaughters ( size_t  index,
const reco::GenParticleCollection src,
int  keepOrDrop,
std::vector< size_t > &  allIndices 
)
private

Definition at line 120 of file GenParticlePruner.cc.

123  {
124  GenParticleRefVector daughters = src[index].daughterRefVector();
125  // avoid infinite recursion if the daughters are set to "this" particle.
126  size_t cachedIndex = index;
127  for (GenParticleRefVector::const_iterator i = daughters.begin(); i != daughters.end(); ++i) {
128  index = i->key();
129  // To also avoid infinite recursion if a "loop" is found in the daughter list,
130  // check to make sure the index hasn't already been added.
131  if (find(allIndices.begin(), allIndices.end(), index) == allIndices.end()) {
132  allIndices.push_back(index);
133  if (cachedIndex != index) {
134  flags_[index] = keepOrDrop;
135  recursiveFlagDaughters(index, src, keepOrDrop, allIndices);
136  }
137  }
138  }
139 }

References BPhysicsValidation_cfi::daughters, spr::find(), flags_, mps_fire::i, and TrackRefitter_38T_cff::src.

Referenced by produce().

◆ recursiveFlagMothers()

void GenParticlePruner::recursiveFlagMothers ( size_t  index,
const reco::GenParticleCollection src,
int  keepOrDrop,
std::vector< size_t > &  allIndices 
)
private

Definition at line 141 of file GenParticlePruner.cc.

144  {
145  GenParticleRefVector mothers = src[index].motherRefVector();
146  // avoid infinite recursion if the mothers are set to "this" particle.
147  size_t cachedIndex = index;
148  for (GenParticleRefVector::const_iterator i = mothers.begin(); i != mothers.end(); ++i) {
149  index = i->key();
150  // To also avoid infinite recursion if a "loop" is found in the daughter list,
151  // check to make sure the index hasn't already been added.
152  if (find(allIndices.begin(), allIndices.end(), index) == allIndices.end()) {
153  allIndices.push_back(index);
154  if (cachedIndex != index) {
155  flags_[index] = keepOrDrop;
156  recursiveFlagMothers(index, src, keepOrDrop, allIndices);
157  }
158  }
159  }
160 }

References edm::RefVector< C, T, F >::begin(), edm::RefVector< C, T, F >::end(), spr::find(), flags_, mps_fire::i, and TrackRefitter_38T_cff::src.

Referenced by produce().

Member Data Documentation

◆ firstEvent_

bool GenParticlePruner::firstEvent_
private

Definition at line 28 of file GenParticlePruner.cc.

Referenced by produce().

◆ flags_

std::vector<int> GenParticlePruner::flags_
private

◆ indices_

std::vector<size_t> GenParticlePruner::indices_
private

Definition at line 34 of file GenParticlePruner.cc.

Referenced by produce().

◆ keepOrDropAll_

int GenParticlePruner::keepOrDropAll_
private

Definition at line 30 of file GenParticlePruner.cc.

Referenced by produce().

◆ select_

std::vector<std::pair<StringCutObjectSelector<reco::GenParticle>, helper::SelectCode> > GenParticlePruner::select_
private

Definition at line 32 of file GenParticlePruner.cc.

Referenced by produce().

◆ selection_

std::vector<std::string> GenParticlePruner::selection_
private

Definition at line 31 of file GenParticlePruner.cc.

Referenced by produce().

◆ srcToken_

edm::EDGetTokenT<reco::GenParticleCollection> GenParticlePruner::srcToken_
private

Definition at line 29 of file GenParticlePruner.cc.

Referenced by produce().

edm::RefProd< GenParticleCollection >
counter
Definition: counter.py:1
edm::Event::getRefBeforePut
RefProd< PROD > getRefBeforePut()
Definition: Event.h:157
GenParticlePruner::selection_
std::vector< std::string > selection_
Definition: GenParticlePruner.cc:31
mps_fire.i
i
Definition: mps_fire.py:355
GenParticlePruner::flagDaughters
void flagDaughters(const reco::GenParticle &, int)
Definition: GenParticlePruner.cc:108
edm::Association::Filler
Definition: Association.h:78
dqmiodumpmetadata.n
n
Definition: dqmiodumpmetadata.py:28
helper::SelectCode::keepOrDrop_
KeepOrDrop keepOrDrop_
Definition: GenParticlePruner.cc:16
TkAlMuonSelectors_cfi.cut
cut
Definition: TkAlMuonSelectors_cfi.py:5
f
double f[11][100]
Definition: MuScleFitUtils.cc:78
AlCaHLTBitMon_ParallelJobs.p
p
Definition: AlCaHLTBitMon_ParallelJobs.py:153
GenParticlePruner::select_
std::vector< std::pair< StringCutObjectSelector< reco::GenParticle >, helper::SelectCode > > select_
Definition: GenParticlePruner.cc:32
edm::RefVector::begin
const_iterator begin() const
Initialize an iterator over the RefVector.
Definition: RefVector.h:223
reco::CompositeRefCandidateT::addMother
void addMother(const typename mothers::value_type &)
add a daughter via a reference
reco::GenParticleCollection
std::vector< GenParticle > GenParticleCollection
collection of GenParticles
Definition: GenParticleFwd.h:13
GenParticlePruner::indices_
std::vector< size_t > indices_
Definition: GenParticlePruner.cc:34
GenParticlePruner::flags_
std::vector< int > flags_
Definition: GenParticlePruner.cc:33
GenParticlePruner::parse
void parse(const std::string &selection, helper::SelectCode &code, std::string &cut) const
Definition: GenParticlePruner.cc:50
GenParticlePruner::flagMothers
void flagMothers(const reco::GenParticle &, int)
Definition: GenParticlePruner.cc:114
edm::RefVector< GenParticleCollection >
spr::find
void find(edm::Handle< EcalRecHitCollection > &hits, DetId thisDet, std::vector< EcalRecHitCollection::const_iterator > &hit, bool debug=false)
Definition: FindCaloHit.cc:19
mps_check.command
list command
Definition: mps_check.py:25
GenParticlePruner::recursiveFlagMothers
void recursiveFlagMothers(size_t, const reco::GenParticleCollection &, int, std::vector< size_t > &)
Definition: GenParticlePruner.cc:141
edm::Handle
Definition: AssociativeIterator.h:50
training_settings.idx
idx
Definition: training_settings.py:16
GenParticle
Definition: GenParticle.py:1
edm::Ref< GenParticleCollection >
PdgEntryReplacer
Definition: PdgEntryReplacer.h:9
edm::RefVector::end
const_iterator end() const
Termination of iteration.
Definition: RefVector.h:228
part
part
Definition: HCALResponse.h:20
edm::RefVector::empty
bool empty() const
Is the RefVector empty.
Definition: RefVector.h:99
BPhysicsValidation_cfi.daughters
daughters
Definition: BPhysicsValidation_cfi.py:11
helper::SelectCode::all_
bool all_
Definition: GenParticlePruner.cc:18
corrVsCorr.selection
selection
main part
Definition: corrVsCorr.py:100
edm::Event::getByToken
bool getByToken(EDGetToken token, Handle< PROD > &result) const
Definition: Event.h:528
GenParticlePruner::recursiveFlagDaughters
void recursiveFlagDaughters(size_t, const reco::GenParticleCollection &, int, std::vector< size_t > &)
Definition: GenParticlePruner.cc:120
gen
Definition: PythiaDecays.h:13
AlCaHLTBitMon_QueryRunRegistry.string
string
Definition: AlCaHLTBitMon_QueryRunRegistry.py:256
GenParticlePruner::keepOrDropAll_
int keepOrDropAll_
Definition: GenParticlePruner.cc:30
TrackRefitter_38T_cff.src
src
Definition: TrackRefitter_38T_cff.py:24
GenParticlePruner::srcToken_
edm::EDGetTokenT< reco::GenParticleCollection > srcToken_
Definition: GenParticlePruner.cc:29
reco::GenParticle::statusFlags
const GenStatusFlags & statusFlags() const
Definition: GenParticle.h:38
helper
Definition: helper.py:1
GenParticlePruner::firstEvent_
bool firstEvent_
Definition: GenParticlePruner.cc:28
edm::Event::put
OrphanHandle< PROD > put(std::unique_ptr< PROD > product)
Put a new product.
Definition: Event.h:132
cuy.rep
rep
Definition: cuy.py:1190
HltBtagPostValidation_cff.c
c
Definition: HltBtagPostValidation_cff.py:31
looper.cfg
cfg
Definition: looper.py:297
WDecay::kNone
Definition: TopGenEvent.h:27
GenParticle.GenParticle
GenParticle
Definition: GenParticle.py:18
eostools.move
def move(src, dest)
Definition: eostools.py:511
edm::OrphanHandle
Definition: EDProductfwd.h:39
helper::SelectCode::daughtersDepth_
FlagDepth daughtersDepth_
Definition: GenParticlePruner.cc:17
GenParticlePruner::getMotherKeys
void getMotherKeys(std::vector< size_t > &, std::vector< size_t > &, const reco::GenParticleRefVector &) const
Definition: GenParticlePruner.cc:302
StringCutObjectSelector
Definition: StringCutObjectSelector.h:16
Exception
Definition: hltDiff.cc:246
edm::RefVectorIterator
Definition: EDProductfwd.h:33
GenParticlePruner::getDaughterKeys
void getDaughterKeys(std::vector< size_t > &, std::vector< size_t > &, const reco::GenParticleRefVector &) const
Definition: GenParticlePruner.cc:283
relval_steps.gen
def gen(fragment, howMuch)
Production test section ####.
Definition: relval_steps.py:500
AlignmentPI::index
index
Definition: AlignmentPayloadInspectorHelper.h:46
helper::SelectCode::mothersDepth_
FlagDepth mothersDepth_
Definition: GenParticlePruner.cc:17
edm::Ref::key
key_type key() const
Accessor for product key.
Definition: Ref.h:250
MillePedeFileConverter_cfg.out
out
Definition: MillePedeFileConverter_cfg.py:31
reco::CompositeRefCandidateT::addDaughter
void addDaughter(const typename daughters::value_type &)
add a daughter via a reference
drop
const int drop
Definition: GenParticlePruner.cc:48
reco::LeafCandidate
Definition: LeafCandidate.h:16
EgammaValidation_Wenu_cff.sel
sel
Definition: EgammaValidation_Wenu_cff.py:33
dqmiolumiharvest.j
j
Definition: dqmiolumiharvest.py:66
keep
const int keep
Definition: GenParticlePruner.cc:48
edm::errors::Configuration
Definition: EDMException.h:36
edm::InputTag
Definition: InputTag.h:15