DD4hep  1.30.0
Detector Description Toolkit for High Energy Physics
EDM4hepFileReader.cpp
Go to the documentation of this file.
1 //==========================================================================
2 // AIDA Detector description implementation
3 //--------------------------------------------------------------------------
4 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
5 // All rights reserved.
6 //
7 // For the licensing terms see $DD4hepINSTALL/LICENSE.
8 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
9 //
10 // Author : A.Sailer
11 //
12 //==========================================================================
13 
24 #include <CLHEP/Units/SystemOfUnits.h>
25 
26 #include <DDG4/EventParameters.h>
27 #include <DDG4/Factories.h>
28 #include <DDG4/FileParameters.h>
29 #include <DDG4/Geant4InputAction.h>
30 #include <DDG4/RunParameters.h>
31 
32 #include <edm4hep/EventHeaderCollection.h>
33 #include <edm4hep/MCParticleCollection.h>
34 
35 #include <podio/Frame.h>
36 #include <podio/Reader.h>
37 
38 typedef dd4hep::detail::ReferenceBitMask<int> PropertyMask;
39 
40 
41 namespace dd4hep::sim {
42 
43  // we use the index of the objectID to identify particles
44  // we will not support MCParticles from different collections
45  using MCPARTICLE_MAP=std::map<int, int>;
46 
49  template <class T=podio::GenericParameters> void EventParameters::ingestParameters(T const& source) {
50  for(auto const& key: source.template getKeys<int>()) {
51  m_intValues[key] = source.template get<std::vector<int>>(key).value();
52  }
53  for(auto const& key: source.template getKeys<float>()) {
54  m_fltValues[key] = source.template get<std::vector<float>>(key).value();
55  }
56  for(auto const& key: source.template getKeys<double>()) {
57  m_dblValues[key] = source.template get<std::vector<double>>(key).value();
58  }
59  for(auto const& key: source.template getKeys<std::string>()) {
60  m_strValues[key] = source.template get<std::vector<std::string>>(key).value();
61  }
62  }
63 
66  template <class T=podio::GenericParameters> void RunParameters::ingestParameters(T const& source) {
67  for(auto const& key: source.template getKeys<int>()) {
68  m_intValues[key] = source.template get<std::vector<int>>(key).value();
69  }
70  for(auto const& key: source.template getKeys<float>()) {
71  m_fltValues[key] = source.template get<std::vector<float>>(key).value();
72  }
73  for(auto const& key: source.template getKeys<double>()) {
74  m_dblValues[key] = source.template get<std::vector<double>>(key).value();
75  }
76  for(auto const& key: source.template getKeys<std::string>()) {
77  m_strValues[key] = source.template get<std::vector<std::string>>(key).value();
78  }
79  }
80 
81  template <class T=podio::GenericParameters> void FileParameters::ingestParameters(T const& source) {
82  for(auto const& key: source.template getKeys<int>()) {
83  m_intValues[key] = source.template get<std::vector<int>>(key).value();
84  }
85  for(auto const& key: source.template getKeys<float>()) {
86  m_fltValues[key] = source.template get<std::vector<float>>(key).value();
87  }
88  for(auto const& key: source.template getKeys<double>()) {
89  m_dblValues[key] = source.template get<std::vector<double>>(key).value();
90  }
91  for(auto const& key: source.template getKeys<std::string>()) {
92  m_strValues[key] = source.template get<std::vector<std::string>>(key).value();
93  }
94  }
95 
97 
102  protected:
104  podio::Reader m_reader;
106  std::string m_collectionName;
109 
110  public:
112  EDM4hepFileReader(const std::string& nam);
113 
115  virtual EventReaderStatus setParameters(std::map< std::string, std::string >& parameters);
116 
118  virtual EventReaderStatus readParticles(int event_number, Vertices& vertices, std::vector<Particle*>& particles);
120  void registerRunParameters();
121 
122  };
123 
126  : Geant4EventReader(nam)
127  , m_reader(podio::makeReader(nam))
128  , m_collectionName("MCParticles")
129  , m_eventHeaderCollectionName("EventHeader")
130  {
131  printout(INFO,"EDM4hepFileReader","Created file reader. Try to open input %s",nam.c_str());
132  m_directAccess = true;
133  }
134 
136  try {
137  auto *parameters = new RunParameters();
138  try {
139  podio::Frame runFrame = m_reader.readFrame("runs", 0);
140  parameters->ingestParameters(runFrame.getParameters());
141  } catch (std::runtime_error& e) {
142  // we ignore if we do not have runs information
143  } catch(std::invalid_argument&) {
144  // we ignore if we do not have runs information
145  }
146  context()->run().addExtension<RunParameters>(parameters);
147  } catch(std::exception &e) {
148  printout(ERROR,"EDM4hepFileReader::registerRunParameters","Failed to register run parameters: %s", e.what());
149  }
150 
151  try {
152  auto *fileParameters = new FileParameters();
153  try {
154  podio::Frame metaFrame = m_reader.readFrame("metadata", 0);
155  fileParameters->ingestParameters(metaFrame.getParameters());
156  } catch (std::runtime_error& e) {
157  // we ignore if we do not have metadata information
158  } catch(std::invalid_argument&) {
159  // we ignore if we do not have metadata information
160  }
161  context()->run().addExtension<FileParameters>(fileParameters);
162  } catch(std::exception &e) {
163  printout(ERROR,"EDM4hepFileReader::registerRunParameters","Failed to register file parameters: %s", e.what());
164  }
165  }
166 
167  namespace {
169  inline int GET_ENTRY(MCPARTICLE_MAP const& mcparts, int partID) {
170  MCPARTICLE_MAP::const_iterator ip = mcparts.find(partID);
171  if ( ip == mcparts.end() ) {
172  throw std::runtime_error("Unknown particle identifier look-up!");
173  }
174  return (*ip).second;
175  }
176  }
177 
180  EDM4hepFileReader::readParticles(int event_number, Vertices& vertices, std::vector<Particle*>& particles) {
181  m_currEvent = event_number;
182  podio::Frame frame = m_reader.readFrame("events", event_number);
183  const auto& primaries = frame.get<edm4hep::MCParticleCollection>(m_collectionName);
184  int eventNumber = event_number, runNumber = 0;
185  if (primaries.isValid()) {
186  //Read the event header collection and add it to the context as an extension
187  const auto& eventHeaderCollection = frame.get<edm4hep::EventHeaderCollection>(m_eventHeaderCollectionName);
188  if(eventHeaderCollection.isValid() && eventHeaderCollection.size() == 1){
189  const auto& eh = eventHeaderCollection.at(0);
190  eventNumber = eh.getEventNumber();
191  runNumber = eh.getRunNumber();
192  try {
193  Geant4Context* ctx = context();
194  ctx->event().addExtension<edm4hep::MutableEventHeader>(new edm4hep::MutableEventHeader(eh.clone()));
195  } catch(std::exception& ) {}
196  // Create input event parameters context
197  try {
198  Geant4Context* ctx = context();
199  EventParameters *parameters = new EventParameters();
200  parameters->setRunNumber(runNumber);
201  parameters->setEventNumber(eventNumber);
202  parameters->ingestParameters(frame.getParameters());
203  ctx->event().addExtension<EventParameters>(parameters);
204  } catch(std::exception &) {}
205  } else {
206  printout(WARNING,"EDM4hepFileReader","No EventHeader collection found or too many event headers!");
207  try {
208  Geant4Context* ctx = context();
209  EventParameters *parameters = new EventParameters();
210  parameters->setRunNumber(0);
211  parameters->setEventNumber(event_number);
212  parameters->ingestParameters(frame.getParameters());
213  ctx->event().addExtension<EventParameters>(parameters);
214  } catch(std::exception &) {}
215  }
216  printout(INFO,"EDM4hepFileReader","read collection %s from event %d in run %d ",
217  m_collectionName.c_str(), eventNumber, runNumber);
218 
219  } else {
220  return EVENT_READER_EOF;
221  }
222 
223  printout(INFO,"EDM4hepFileReader", "We read the particle collection");
224  int NHEP = primaries.size();
225  // check if there is at least one particle
226  if ( NHEP == 0 ) {
227  printout(WARNING,"EDM4hepFileReader", "We have no particles");
229  }
230 
231  MCPARTICLE_MAP mcparts;
232  std::vector<int> mcpcoll;
233  mcpcoll.resize(NHEP);
234  for(int i=0; i<NHEP; ++i ) {
235  edm4hep::MCParticle p = primaries.at(i);
236  mcparts[p.getObjectID().index] = i;
237  mcpcoll[i] = p.getObjectID().index;
238  }
239 
240  // build collection of MCParticles
241  for(int i=0; i<NHEP; ++i ) {
242  const auto& mcp = primaries.at(i);
243  Geant4ParticleHandle p(new Particle(i));
244  const auto mom = mcp.getMomentum();
245  const auto vsx = mcp.getVertex();
246  const auto vex = mcp.getEndpoint();
247  const auto spin = mcp.getSpin();
248  const int pdg = mcp.getPDG();
249  p->pdgID = pdg;
250  p->charge = int(mcp.getCharge()*3.0);
251  p->psx = mom[0]*CLHEP::GeV;
252  p->psy = mom[1]*CLHEP::GeV;
253  p->psz = mom[2]*CLHEP::GeV;
254  p->time = mcp.getTime()*CLHEP::ns;
255  p->properTime = mcp.getTime()*CLHEP::ns;
256  p->vsx = vsx[0]*CLHEP::mm;
257  p->vsy = vsx[1]*CLHEP::mm;
258  p->vsz = vsx[2]*CLHEP::mm;
259  p->vex = vex[0]*CLHEP::mm;
260  p->vey = vex[1]*CLHEP::mm;
261  p->vez = vex[2]*CLHEP::mm;
262  p->process = 0;
263  p->spin[0] = spin[0];
264  p->spin[1] = spin[1];
265  p->spin[2] = spin[2];
266  p->colorFlow[0] = 0;
267  p->colorFlow[1] = 0;
268  p->mass = mcp.getMass()*CLHEP::GeV;
269  const auto par = mcp.getParents(), &dau=mcp.getDaughters();
270  for(int num=dau.size(),k=0; k<num; ++k) {
271  edm4hep::MCParticle dau_k = dau[k];
272  p->daughters.insert(GET_ENTRY(mcparts,dau_k.getObjectID().index));
273  }
274  for(int num=par.size(),k=0; k<num; ++k) {
275  auto par_k = par[k];
276  p->parents.insert(GET_ENTRY(mcparts, par_k.getObjectID().index));
277  }
278 
279  PropertyMask status(p->status);
280  int genStatus = mcp.getGeneratorStatus();
281  // Copy raw generator status
282  p->genStatus = genStatus&G4PARTICLE_GEN_STATUS_MASK;
283  if(m_inputAction) {
284  // in some tests we do not set up the inputAction
285  m_inputAction->setGeneratorStatus(genStatus, status);
286  }
287 
288  //fg: we simply add all particles without parents as with their own vertex.
289  // This might include the incoming beam particles, e.g. in
290  // the case of lcio files written with Whizard2, which is slightly odd,
291  // however should be treated correctly in Geant4InputHandling.cpp.
292  // We no longer make an attempt to identify the incoming particles
293  // based on the generator status, as this varies widely with different
294  // generators.
295 
296  if ( p->parents.size() == 0 ) {
297 
298  Geant4Vertex* vtx = new Geant4Vertex ;
299  vertices.emplace_back( vtx );
300  vtx->x = p->vsx;
301  vtx->y = p->vsy;
302  vtx->z = p->vsz;
303  vtx->time = p->time;
304 
305  vtx->out.insert(p->id) ;
306  }
307 
308  if ( mcp.isCreatedInSimulation() ) status.set(G4PARTICLE_SIM_CREATED);
309  if ( mcp.isBackscatter() ) status.set(G4PARTICLE_SIM_BACKSCATTER);
310  if ( mcp.vertexIsNotEndpointOfParent() ) status.set(G4PARTICLE_SIM_PARENT_RADIATED);
311  if ( mcp.isDecayedInTracker() ) status.set(G4PARTICLE_SIM_DECAY_TRACKER);
312  if ( mcp.isDecayedInCalorimeter() ) status.set(G4PARTICLE_SIM_DECAY_CALO);
313  if ( mcp.hasLeftDetector() ) status.set(G4PARTICLE_SIM_LEFT_DETECTOR);
314  if ( mcp.isStopped() ) status.set(G4PARTICLE_SIM_STOPPED);
315  if ( mcp.isOverlay() ) status.set(G4PARTICLE_SIM_OVERLAY);
316  particles.emplace_back(p);
317  }
318  return EVENT_READER_OK;
319  }
320 
324  dd4hep::sim::EDM4hepFileReader::setParameters( std::map< std::string, std::string > & parameters ) {
325  _getParameterValue(parameters, "MCParticleCollectionName", m_collectionName, m_collectionName);
326  _getParameterValue(parameters, "EventHeaderCollectionName", m_eventHeaderCollectionName, m_eventHeaderCollectionName);
327  return EVENT_READER_OK;
328  }
329 
330 } //end dd4hep::sim
331 
dd4hep::sim::G4PARTICLE_SIM_CREATED
@ G4PARTICLE_SIM_CREATED
Definition: Geant4Particle.h:85
dd4hep::sim::EDM4hepFileReader::setParameters
virtual EventReaderStatus setParameters(std::map< std::string, std::string > &parameters)
Read parameters set for this action.
Definition: EDM4hepFileReader.cpp:324
dd4hep::sim::Geant4EventReader::EVENT_READER_EOF
@ EVENT_READER_EOF
Definition: Geant4InputAction.h:75
dd4hep::sim::Geant4Particle::vsz
double vsz
Definition: Geant4Particle.h:124
dd4hep::sim::Geant4EventReader::context
Geant4Context * context() const
Get the context (from the input action)
Definition: Geant4InputAction.cpp:41
dd4hep::sim::EDM4hepFileReader::EDM4hepFileReader
EDM4hepFileReader(const std::string &nam)
Initializing constructor.
Definition: EDM4hepFileReader.cpp:125
dd4hep::sim::G4PARTICLE_SIM_PARENT_RADIATED
@ G4PARTICLE_SIM_PARENT_RADIATED
Definition: Geant4Particle.h:91
dd4hep::sim::Geant4Vertex::y
double y
Definition: Geant4Vertex.h:53
dd4hep::sim::Geant4Particle::mass
double mass
Particle mass.
Definition: Geant4Particle.h:132
dd4hep::sim::Geant4Particle::vey
double vey
Definition: Geant4Particle.h:126
dd4hep::sim::Geant4EventReader::EventReaderStatus
EventReaderStatus
Status codes of the event reader object. Anything with NOT low-bit set is an error.
Definition: Geant4InputAction.h:68
dd4hep::exception
void exception(const std::string &src, const std::string &msg)
Definition: RootDictionary.h:69
dd4hep::sim::ExtensionParameters::m_strValues
std::map< std::string, std::vector< std::string > > m_strValues
Definition: ExtensionParameters.h:35
dd4hep::sim::Geant4Context::run
Geant4Run & run() const
Access the geant4 run – valid only between BeginRun() and EndRun()!
Definition: Geant4Context.cpp:72
dd4hep::sim::Geant4Particle::id
int id
not persistent
Definition: Geant4Particle.h:108
dd4hep::sim::EventParameters::setRunNumber
void setRunNumber(int runNumber)
Set the event parameters.
Definition: EventParameters.cpp:20
dd4hep::sim::EDM4hepFileReader::m_collectionName
std::string m_collectionName
Name of the MCParticle collection to read.
Definition: EDM4hepFileReader.cpp:106
dd4hep::sim::EDM4hepFileReader::readParticles
virtual EventReaderStatus readParticles(int event_number, Vertices &vertices, std::vector< Particle * > &particles)
Read an event and fill a vector of MCParticles.
Definition: EDM4hepFileReader.cpp:180
dd4hep::sim::Geant4Particle::pdgID
int pdgID
Definition: Geant4Particle.h:115
dd4hep::sim::EventParameters::setEventNumber
void setEventNumber(int eventNumber)
Definition: EventParameters.cpp:23
dd4hep::sim::Geant4Particle::psz
double psz
Definition: Geant4Particle.h:128
DECLARE_GEANT4_EVENT_READER_NS
#define DECLARE_GEANT4_EVENT_READER_NS(name_space, name)
Plugin defintion to create event reader objects.
Definition: Factories.h:240
dd4hep::sim::Geant4Context::event
Geant4Event & event() const
Access the geant4 event – valid only between BeginEvent() and EndEvent()!
Definition: Geant4Context.cpp:84
dd4hep::sim::G4PARTICLE_GEN_STATUS_MASK
@ G4PARTICLE_GEN_STATUS_MASK
Definition: Geant4Particle.h:83
m_reader
UriReader * m_reader
Pointer to URI reader.
Definition: DocumentHandler.cpp:155
dd4hep::sim::G4PARTICLE_SIM_BACKSCATTER
@ G4PARTICLE_SIM_BACKSCATTER
Definition: Geant4Particle.h:86
RunParameters.h
dd4hep::sim::Geant4EventReader::m_currEvent
int m_currEvent
Current event number.
Definition: Geant4InputAction.h:83
dd4hep::sim::RunParameters
Extension to pass input run data to output run data.
Definition: RunParameters.h:28
FileParameters.h
dd4hep::sim::Geant4EventReader::Particle
Geant4Particle Particle
Definition: Geant4InputAction.h:64
dd4hep::sim::G4PARTICLE_SIM_STOPPED
@ G4PARTICLE_SIM_STOPPED
Definition: Geant4Particle.h:89
EDM4hepFileReader
Plugin to read EDM4hep files.
EventParameters.h
dd4hep::sim::EDM4hepFileReader::m_reader
podio::Reader m_reader
Reference to reader object.
Definition: EDM4hepFileReader.cpp:104
dd4hep::sim::Geant4Run::addExtension
void * addExtension(unsigned long long int k, ExtensionEntry *e)
Add an extension object to the detector element.
Definition: Geant4Context.h:84
dd4hep::sim::EventParameters::ingestParameters
void ingestParameters(T const &source)
Copy the parameters from source.
Definition: EDM4hepFileReader.cpp:49
dd4hep::sim::Geant4Particle::vez
double vez
Definition: Geant4Particle.h:126
dd4hep::sim::G4PARTICLE_SIM_DECAY_CALO
@ G4PARTICLE_SIM_DECAY_CALO
Definition: Geant4Particle.h:87
dd4hep::sim::EDM4hepFileReader::registerRunParameters
void registerRunParameters()
Call to register the run parameters.
Definition: EDM4hepFileReader.cpp:135
dd4hep::sim::Geant4Vertex::x
double x
Vertex data.
Definition: Geant4Vertex.h:53
dd4hep::sim::Geant4Particle::colorFlow
int colorFlow[2]
Definition: Geant4Particle.h:117
dd4hep::sim::Geant4Particle::spin
float spin[3]
Definition: Geant4Particle.h:121
dd4hep::sim::Geant4Particle::genStatus
unsigned short genStatus
Definition: Geant4Particle.h:118
dd4hep::sim::ExtensionParameters::m_intValues
std::map< std::string, std::vector< int > > m_intValues
Definition: ExtensionParameters.h:33
dd4hep::sim::Geant4Particle::status
int status
Definition: Geant4Particle.h:116
dd4hep::sim::Geant4EventReader::m_directAccess
bool m_directAccess
Flag if direct event access is supported. To be explicitly set by subclass constructors.
Definition: Geant4InputAction.h:81
dd4hep::sim::G4PARTICLE_SIM_OVERLAY
@ G4PARTICLE_SIM_OVERLAY
Definition: Geant4Particle.h:92
dd4hep::sim::Geant4Particle::daughters
Particles daughters
The list of daughters of this MC particle.
Definition: Geant4Particle.h:140
dd4hep::sim::G4PARTICLE_SIM_DECAY_TRACKER
@ G4PARTICLE_SIM_DECAY_TRACKER
Definition: Geant4Particle.h:88
dd4hep::sim::FileParameters
Extension to pass input run data to output run data.
Definition: FileParameters.h:28
dd4hep::sim::ExtensionParameters::m_dblValues
std::map< std::string, std::vector< double > > m_dblValues
Definition: ExtensionParameters.h:36
dd4hep::sim::Geant4InputAction::setGeneratorStatus
void setGeneratorStatus(int generatorStatus, PropertyMask &status)
Convert the generator status into a common set of generator status bits.
dd4hep::sim::Geant4Particle::time
double time
Particle creation time.
Definition: Geant4Particle.h:134
dd4hep::sim::Geant4Particle::process
const G4VProcess * process
Reference to the G4VProcess, which created this track.
Definition: Geant4Particle.h:145
dd4hep::sim::Geant4EventReader::m_inputAction
Geant4InputAction * m_inputAction
The input action context.
Definition: Geant4InputAction.h:85
dd4hep::sim::Geant4EventReader
Basic geant4 event reader class. This interface/base-class must be implemented by concrete readers.
Definition: Geant4InputAction.h:60
dd4hep::sim::MCPARTICLE_MAP
std::map< int, int > MCPARTICLE_MAP
Definition: EDM4hepFileReader.cpp:45
dd4hep::sim::Geant4Vertex::out
Particles out
The list of outgoing particles.
Definition: Geant4Vertex.h:55
dd4hep::sim::Geant4Particle::vex
double vex
The end vertex.
Definition: Geant4Particle.h:126
dd4hep::sim::ExtensionParameters::m_fltValues
std::map< std::string, std::vector< float > > m_fltValues
Definition: ExtensionParameters.h:34
dd4hep::sim::Geant4Particle::vsx
double vsx
The starting vertex.
Definition: Geant4Particle.h:124
dd4hep::sim::Geant4Particle::psx
double psx
The track momentum at the start vertex.
Definition: Geant4Particle.h:128
dd4hep::sim::Geant4Event::addExtension
void * addExtension(unsigned long long int k, ExtensionEntry *e)
Add an extension object to the detector element.
Definition: Geant4Context.h:140
Factories.h
dd4hep::sim::G4PARTICLE_SIM_LEFT_DETECTOR
@ G4PARTICLE_SIM_LEFT_DETECTOR
Definition: Geant4Particle.h:90
key
unsigned char key
Definition: AlignmentsCalculator.cpp:69
dd4hep::sim
Namespace for the Geant4 based simulation part of the AIDA detector description toolkit.
Definition: EDM4hepFileReader.cpp:41
Geant4InputAction.h
dd4hep::sim::EventParameters
Event extension to pass input event data to output event.
Definition: EventParameters.h:28
dd4hep::sim::Geant4EventReader::EVENT_READER_OK
@ EVENT_READER_OK
Definition: Geant4InputAction.h:70
dd4hep::sim::Geant4ParticleHandle
Data structure to access derived MC particle information.
Definition: Geant4Particle.h:181
dd4hep::sim::Geant4Vertex::time
double time
Definition: Geant4Vertex.h:53
dd4hep::sim::Geant4Particle::parents
Particles parents
The list of parents of this MC particle.
Definition: Geant4Particle.h:138
dd4hep::sim::Geant4Particle::vsy
double vsy
Definition: Geant4Particle.h:124
dd4hep::sim::Geant4Vertex::z
double z
Definition: Geant4Vertex.h:53
dd4hep::sim::Geant4EventReader::EVENT_READER_NO_PRIMARIES
@ EVENT_READER_NO_PRIMARIES
Definition: Geant4InputAction.h:72
dd4hep::sim::Geant4Vertex
Data structure to store the MC vertex information.
Definition: Geant4Vertex.h:45
dd4hep::sim::Geant4Particle::charge
char charge
Definition: Geant4Particle.h:119
PropertyMask
dd4hep::detail::ReferenceBitMask< int > PropertyMask
Definition: EDM4hepFileReader.cpp:38
dd4hep::sim::FileParameters::ingestParameters
void ingestParameters(T const &source)
Copy the parameters from source.
Definition: EDM4hepFileReader.cpp:81
dd4hep::sim::Geant4EventReader::Vertices
std::vector< Vertex * > Vertices
Definition: Geant4InputAction.h:66
dd4hep::sim::Geant4Particle::psy
double psy
Definition: Geant4Particle.h:128
dd4hep::sim::RunParameters::ingestParameters
void ingestParameters(T const &source)
Copy the parameters from source.
Definition: EDM4hepFileReader.cpp:66
dd4hep::sim::EDM4hepFileReader::m_eventHeaderCollectionName
std::string m_eventHeaderCollectionName
Name of the EventHeader collection to read.
Definition: EDM4hepFileReader.cpp:108
dd4hep::sim::Geant4Particle::properTime
double properTime
Proper time.
Definition: Geant4Particle.h:136
dd4hep::sim::Geant4Context
Generic context to extend user, run and event information.
Definition: Geant4Context.h:201