LEMMixer_module.cc
Go to the documentation of this file.
1 ////////////////////////////////////////////////////////////////////////
2 // \file LEMMixer_module.cc
3 // \author Christopher Backhouse - bckhouse@caltech.edu
4 ////////////////////////////////////////////////////////////////////////
5 
6 #include "LEM/PIDDetails.h"
7 
8 // Framework includes
12 
14 
15 #include "ifdh.h"
16 
17 namespace lem
18 {
19  class LEMMixer
20  {
21  public:
22  explicit LEMMixer(const fhicl::ParameterSet& pset,
23  art::MixHelper& helper);
24 
25  size_t nSecondaries() {return 1;}
26 
27  /// Fetch the matching lempart file from SAM
28  virtual void respondToOpenInputFile(const art::FileBlock& fb);
29 
30  protected:
31  /// Tell ART what file to mix with
33 
34  /// Locate the release string within the filename
35  void FindRelease(const std::string& fname,
36  size_t& pos, size_t& len) const;
37 
38  /// Locate the version string within the filename
39  void FindVersion(const std::string& fname,
40  size_t& pos, size_t& len) const;
41 
42  /// Rewrite filename to find the corresponding lempart file
43  std::string LEMPartFor(std::string fname) const;
44 
45  /// Do the actual mixing
46  bool MixPIDDetails(const std::vector<const std::vector<PIDDetails>*>& pids,
47  std::vector<PIDDetails>& out,
48  const art::PtrRemapper& rm);
49 
50  bool fFromSAM; ///< Are we fetching lempart files from SAM?
51  std::string fLempartFilename; ///< If so, this is the file we got
52 
53  std::string fLempartRelease; ///< Override lempart release to look for
54  std::string fLempartVersion; ///< Override lempart version to look for
55 
57 
58  /// Detect re-entry into \ref getSecondaryFilename
60  };
61 
62  //......................................................................
64  art::MixHelper& helper)
65  : fFromSAM(pset.get<bool>("FetchLempartFromSAM")),
66  fLempartRelease(pset.get<std::string>("LempartRelease")),
67  fLempartVersion(pset.get<std::string>("LempartVersion")),
68  fUserSAMTag(pset.get<std::string>("UserSAMTag")),
70  {
71  helper.declareMixOp(art::InputTag(pset.get<std::string>("PIDLabel"), ""),
72  &LEMMixer::MixPIDDetails, *this);
73 
74  // If we're getting files from SAM, register this so that ART knows what
75  // file we fetched. Otherwise it comes from the fclx
77  }
78 
79  //......................................................................
81  {
83  mf::LogError("LEMMixer") << "getSecondaryFilename() called a second time. Is the lempart file too short? Aborting";
84  abort();
85  }
87 
88  assert(!fLempartFilename.empty());
89  mf::LogInfo("LEMMixer") << "Merging with " << fLempartFilename << " from SAM...";
90  return fLempartFilename;
91  }
92 
93  //......................................................................
94  bool LEMMixer::MixPIDDetails(const std::vector<const std::vector<PIDDetails>*>& pids,
95  std::vector<PIDDetails>& out,
96  const art::PtrRemapper& rm)
97  {
98  assert(pids.size() == 1);
99 
100  if(!pids[0]){
101  mf::LogError("LEMMixer") << "PIDDetails missing from lempart stream. Normally this means that there were never even any slices. Go check your upstream files...";
102  return true;
103  }
104 
105  out = *pids[0];
106 
107  return true;
108  }
109 
110  //......................................................................
112  size_t& pos, size_t& len) const
113  {
114  // Could check for a "1", but then we have a 2020 bug. Assume nothing
115  // else in the filename will ever be capital.
116  pos = fname.find("S");
117  // Could also be an FA or R release
118  if(pos == std::string::npos) pos = fname.find("FA");
119  if(pos == std::string::npos) pos = fname.find("R");
120  // But it must be one of those
121  assert(pos != std::string::npos);
122 
123  // The release finishes at the next underscore (don't know how many
124  // characters because it could have a ".a" suffix etc.
125  const size_t posend = fname.find("_", pos);
126  assert(posend != std::string::npos);
127 
128  len = posend-pos;
129  }
130 
131  //......................................................................
133  size_t& pos, size_t& len) const
134  {
135  // Hope there's no other fields that ever begin with a v
136  pos = fname.find("_v");
137  assert(pos != std::string::npos);
138  ++pos;
139  assert(pos != std::string::npos);
140  size_t posend = fname.find("_", pos);
141  // Make sure the field was exactly the right length, because of worries
142  // about other fields beginning "v". This will break if we ever get to a
143  // v10. I really hope that never happens...
144  assert(posend == pos+2);
145 
146  len = posend-pos;
147  }
148 
149  //......................................................................
151  {
152  // Remove any path information from the input file to get the basename
153  size_t pos = fname.rfind("/");
154  if(pos != std::string::npos) fname = fname.substr(pos+1);
155 
156  mf::LogInfo("LEMMixer") << "Input file basename is " << fname << std::endl;
157 
158  // Convert the filename to the matching lempart file
159  pos = fname.find("pidpart");
160  assert(pos != std::string::npos);
161  fname.replace(pos, 7, "lempart");
162 
163  if(!fLempartRelease.empty()){
164  size_t len;
165  FindRelease(fname, pos, len);
166  fname = fname.substr(0, pos) + fLempartRelease + fname.substr(pos+len, std::string::npos);
167  }
168 
169  if(!fLempartVersion.empty()){
170  size_t len;
171  FindVersion(fname, pos, len);
172  fname = fname.substr(0, pos) + fLempartVersion + fname.substr(pos+len, std::string::npos);
173  }
174 
175  if(!fUserSAMTag.empty()){
176  // If using user SAM the input lempart file might have a UUID on
177  // the front. Detect it by the pattern of hyphens and strip it
178  // out.
179  if(fname.size() > 37 &&
180  fname[8] == '-' && fname[13] == '-' &&
181  fname[18] == '-' && fname[23] == '-' && fname[36] == '-')
182  fname = &fname.c_str()[37];
183 
184  std::vector<std::string> fnames;
185  ifdh i;
186  i.set_debug("0"); // shut up
187  // User SAM files have a UUID on the front. Wildcard over that
188  fnames = i.translateConstraints(TString::Format("file_name %%%s and dataset.tag %s", fname.c_str(), fUserSAMTag.c_str()).Data());
189 
190  // ifdh likes to return empty strings at the end...
191  while(!fnames.empty() && fnames.back().empty()) fnames.pop_back();
192 
193  if(fnames.empty()){
194  std::cout << "Error: no lemsum file found matching " << fname
195  << " and user tag " << fUserSAMTag << std::endl;
196  abort();
197  }
198  if(fnames.size() > 1){
199  std::cout << "Error: multiple lemsums found matching " << fname
200  << " and user tag " << fUserSAMTag << std::endl;
201  for(const std::string& s: fnames) std::cout << s << std::endl;
202  abort();
203  }
204 
205  fname = fnames[0];
206  }
207 
208  return fname;
209  }
210 
211  //......................................................................
213  {
214  if(!fFromSAM) return;
215 
217 
218  mf::LogInfo("LEMMixer") << "Fetching " << fLempartFilename << " from SAM...";
219 
220  // lempart file is small, safe to fetch into current directory
221  const int status = system(("ifdh_fetch -e nova "+fLempartFilename).c_str());
222  assert(status == 0);
223 
224 
225  // Fill in some metadata, because it doesn't automatically inherit
227  if(fLempartRelease.empty()){
228  size_t pos, len;
229  FindRelease(fb.fileName(), pos, len);
230  mm.AddMetadata("lempart.base_release", fb.fileName().substr(pos, len));
231  }
232  else{
233  mm.AddMetadata("lempart.base_release", fLempartRelease);
234  }
235 
236  if(fLempartVersion.empty()){
237  size_t pos, len;
238  FindVersion(fb.fileName(), pos, len);
239  mm.AddMetadata("lempart.version", fb.fileName().substr(pos, len));
240  }
241  else{
242  mm.AddMetadata("lempart.version", fLempartVersion);
243  }
244 
245  mm.AddMetadata("lempart.file_name", fLempartFilename);
246  }
247 
249 
250 } //namespace lem
251 ////////////////////////////////////////////////////////////////////////
bool fProvidedSecondaryFilename
Detect re-entry into getSecondaryFilename.
const XML_Char int len
Definition: expat.h:262
void registerSecondaryFileNameProvider(ProviderFunc_ func)
static MetadataManager & getInstance()
std::string fLempartVersion
Override lempart version to look for.
std::string LEMPartFor(std::string fname) const
Rewrite filename to find the corresponding lempart file.
system("rm -rf microbeam.root")
void FindRelease(const std::string &fname, size_t &pos, size_t &len) const
Locate the release string within the filename.
int status
Definition: fabricate.py:1613
size_t nSecondaries()
MaybeLogger_< ELseverityLevel::ELsev_info, false > LogInfo
std::string const & fileName() const
Definition: FileBlock.h:38
bool fFromSAM
Are we fetching lempart files from SAM?
bool MixPIDDetails(const std::vector< const std::vector< PIDDetails > * > &pids, std::vector< PIDDetails > &out, const art::PtrRemapper &rm)
Do the actual mixing.
MaybeLogger_< ELseverityLevel::ELsev_error, false > LogError
DEFINE_ART_MODULE(TestTMapFile)
PID
Definition: FillPIDs.h:14
const XML_Char * s
Definition: expat.h:262
std::string fLempartFilename
If so, this is the file we got.
virtual void respondToOpenInputFile(const art::FileBlock &fb)
Fetch the matching lempart file from SAM.
std::string fLempartRelease
Override lempart release to look for.
void declareMixOp(InputTag const &inputTag, MixFunc< PROD, OPROD > mixFunc, bool outputProduct=true)
Definition: MixHelper.h:428
void FindVersion(const std::string &fname, size_t &pos, size_t &len) const
Locate the version string within the filename.
T get(std::string const &key) const
Definition: ParameterSet.h:231
ifdh
Definition: ProjMan.py:8
void AddMetadata(std::string key, std::string value)
OStream cout
Definition: OStream.cxx:6
static constexpr Double_t mm
Definition: Munits.h:136
::xsd::cxx::tree::string< char, simple_type > string
Definition: Database.h:154
std::string fUserSAMTag
assert(nhit_max >=nhit_nbins)
void Format(TGraph *gr, int lcol, int lsty, int lwid, int mcol, int msty, double msiz)
Definition: Style.cxx:154
std::string getSecondaryFilename()
Tell ART what file to mix with.
LEMMixer(const fhicl::ParameterSet &pset, art::MixHelper &helper)