28 Root::MagnifySink::~MagnifySink()
36 fn = cfg[
"input_filename"].asString();
37 if (fn.empty() and !cfg[
"shunt"].empty()) {
38 log->error(
"MagnifySink: asked to shunt but not given input file name");
42 fn = cfg[
"output_filename"].asString();
47 auto anode_tn = get<std::string>(
cfg,
"anode",
"AnodePlane");
48 m_anode = Factory::find_tn<IAnodePlane>(anode_tn);
52 m_nrebin = get<int>(
cfg,
"nrebin", m_nrebin);
62 cfg[
"anode"] =
"AnodePlane";
65 cfg[
"input_filename"] =
"";
68 cfg[
"shunt"] = Json::arrayValue;
71 cfg[
"output_filename"] =
"";
74 cfg[
"frames"] = Json::arrayValue;
79 cfg[
"trace_has_tag"] =
true;
82 cfg[
"cmmtree"] = Json::arrayValue;
88 cfg[
"root_file_mode"] =
"RECREATE";
94 cfg[
"runinfo"] = Json::nullValue;
101 cfg[
"summaries"] = Json::arrayValue;
108 cfg[
"summary_operator"] = Json::objectValue;
117 for (
auto jone : cfg) {
118 ret.insert(jone.asString());
146 std::vector<int> uvwt[4];
147 for (
auto trace : traces) {
148 const int chid =
trace->channel();
149 auto wpid = anode->resolve(chid);
150 const int iplane = wpid.index();
151 if (iplane<0 || iplane>=3) {
154 uvwt[iplane].push_back(chid);
155 byplane[iplane].push_back(
trace);
156 uvwt[3].push_back(
trace->tbin());
157 uvwt[3].push_back(
trace->tbin() +
trace->charge().size());
160 std::vector<Binning> binnings(4);
161 for (
int ind=0; ind<4; ++ind) {
162 auto const& one = uvwt[ind];
166 std::cerr <<
"[wgu] plane: " << ind <<
" has not traces. " <<
std::endl;
169 auto mme = std::minmax_element(one.begin(), one.end());
170 const int vmin = *mme.first;
171 const int vmax = *mme.second;
173 const int n = vmax - vmin;
175 binnings.at(ind) = Binning(n, vmin, vmax);
179 const double diff = vmax - vmin;
181 binnings.at(ind) = Binning(diff+1, vmin-0.5, vmax+0.5);
188 void Root::MagnifySink::create_file() {
189 const std::string ofname = m_cfg[
"output_filename"].asString();
191 TFile* output_tf = TFile::Open(ofname.c_str(), mode.c_str());
192 output_tf->Close(
"R");
198 void Root::MagnifySink::do_shunt(TFile* output_tf)
200 std::stringstream ss;
201 auto truncfg = m_cfg[
"runinfo"];
202 if (!truncfg.empty()) {
203 TTree *rtree =
new TTree(
"Trun",
"Trun");
204 rtree->SetDirectory(output_tf);
205 ss <<
"MagnifySink: making Tree RunInfo:\n";
207 std::vector<int> ints;
213 std::vector<float> floats;
214 floats.push_back(0.0);
217 int celltree_input = 0;
218 for (
auto name : truncfg.getMemberNames()) {
219 auto jval = truncfg[
name];
220 ss <<
"\t" <<
name <<
" = " << jval <<
"\n";
221 if(
name ==
"eventNo") frame_number = std::stoi(jval.asString());
222 if(
name ==
"Celltree") {
223 celltree_input = jval.asInt();
227 ints.push_back(jval.asInt());
228 rtree->Branch(
name.c_str(), &ints.back(), (
name+
"/I").c_str());
231 if (jval.isDouble()) {
232 floats.push_back(jval.asFloat());
233 rtree->Branch(
name.c_str(), &floats.back(), (
name+
"/F").c_str());
236 if (jval.isString()) {
237 ints.push_back(std::stoi(jval.asString()));
238 rtree->Branch(
name.c_str(), &ints.back(), (
name+
"/I").c_str());
241 log->warn(
"MagnifySink: warning: got unknown type for run info entry: \"{}\" = {}",
244 if (ss.str().size() > 0) {
245 log->debug(ss.str());
250 TFile *input_runinfo = TFile::Open((m_cfg[
"input_filename"].asString()).c_str());
251 TTree *
run = (TTree*)input_runinfo->Get(
"/Event/Sim");
253 log->warn(
"MagnifySink: runinfo: no tree: /Event/Sim in input file");
256 run->SetBranchStatus(
"*",0);
258 int run_no, subrun_no, event_no;
259 run->SetBranchStatus(
"eventNo",1);
260 run->SetBranchAddress(
"eventNo" , &event_no);
261 run->SetBranchStatus(
"runNo",1);
262 run->SetBranchAddress(
"runNo" , &run_no);
263 rtree->Branch(
"runNo",&run_no,
"runNo/I");
264 run->SetBranchStatus(
"subRunNo",1);
265 run->SetBranchAddress(
"subRunNo", &subrun_no);
266 rtree->Branch(
"subRunNo",&subrun_no,
"subRunNo/I");
268 unsigned int entries = run->GetEntries();
269 bool legalevt =
false;
270 for(
unsigned int ent = 0; ent<entries; ent++)
272 int siz = run->GetEntry(ent);
273 if(siz>0 && event_no == frame_number )
282 delete input_runinfo;
283 input_runinfo =
nullptr;
292 std::string ifname = m_cfg[
"input_filename"].asString();
293 if (ifname.empty()) {
297 auto toshunt =
getset(m_cfg[
"shunt"]);
298 if (toshunt.empty()) {
299 log->warn(
"MagnifySink: no objects to copy but given input: {}", ifname);
302 log->debug(
"MagnifySink: sneaking peaks into input file: {}", ifname);
305 TFile *input_tf = TFile::Open(ifname.c_str());
306 for (
auto name : toshunt) {
307 if (
name ==
"Trun" && !truncfg.empty()) {
310 TObject* obj = input_tf->Get(
name.c_str());
313 log->warn(
"MagnifySink: warning: failed to find input object: \"{}\" for copying to output",
name);
316 TTree* tree =
dynamic_cast<TTree*
>(obj);
318 log->debug(
"MagnifySink: copying tree: \"{}\"",
name);
319 tree = tree->CloneTree();
320 tree->SetDirectory(output_tf);
324 TH1*
hist =
dynamic_cast<TH1*
>(obj);
326 log->debug(
"MagnifySink: copying hist: \"{}\"",
name);
327 hist->SetDirectory(output_tf);
331 log->warn(
"MagnifySink: warning: not copying object of unknown type: \"{}\"",
name);
344 log->debug(
"MagnifySink: EOS");
347 if (frame->traces()->empty()) {
348 log->debug(
"MagnifySink: passing through empty frame ID {}", frame->ident());
352 const std::string ofname = m_cfg[
"output_filename"].asString();
353 const std::string mode = m_cfg[
"root_file_mode"].asString();
354 log->debug(
"MagnifySink: opening for output: {} with mode {}", ofname, mode);
355 TFile* output_tf = TFile::Open(ofname.c_str(), mode.c_str());
357 for (
auto tag :
getset(m_cfg[
"frames"])) {
359 auto trace_tag =
tag;
360 auto trace_has_tag = m_cfg[
"trace_has_tag"].asBool();
363 log->debug(
"MagnifySink: set desired trace tag to \"\" as cfg::trace_has_tag=false");
367 if (traces.empty()) {
368 log->warn(
"MagnifySink: no tagged traces for \"{}\"",
tag);
372 log->debug(
"MagnifySink: tag: \"{}\" with {} traces",
tag, traces.size());
377 for (
int iplane=0; iplane < 3; ++iplane) {
378 if (traces_byplane[iplane].
empty())
continue;
380 Binning cbin = binnings[iplane];
381 std::stringstream ss;
383 <<
" cbin:"<<cbin.
nbins()<<
"["<<cbin.min() <<
"," << cbin.max() <<
"]" 384 <<
" tbin:"<<tbin.
nbins()<<
"["<<tbin.
min() <<
"," << tbin.
max() <<
"]";
385 log->debug(ss.str());
390 TH2F*
hist =
new TH2F(name.c_str(), name.c_str(),
391 cbin.nbins(), cbin.min(), cbin.max(),
394 hist->SetDirectory(output_tf);
396 for (
auto trace : traces_byplane[iplane]) {
397 const int tbin1 =
trace->tbin();
398 const int ch =
trace->channel();
399 auto const& charges =
trace->charge();
400 for (
size_t itick=0; itick < charges.size(); ++itick) {
409 int ibin = (tbin1-tbin.
min()+itick)/m_nrebin;
411 hist->SetBinContent(cbin.bin(ch)+1, ibin+1,
412 charges[itick]+hist->GetBinContent(cbin.bin(ch)+1, ibin+1));
421 for (
auto tag :
getset(m_cfg[
"summaries"])) {
424 if (traces.empty()) {
425 log->warn(
"MagnifySink: no traces tagged with \"{}\", skipping summary",
tag);
428 auto const&
summary = frame->trace_summary(
tag);
430 log->warn(
"MagnifySink: warning: empty summary tagged with \"{}\", skipping summary",
tag);
434 std::string oper = get<std::string>(m_cfg[
"summary_operator"],
tag,
"sum");
436 log->debug(
"MagnifySink: saving summaries tagged with \"{}\" into per-plane hists", tag);
441 const int ntot = traces.size();
442 std::vector<int> perplane_channels[3];
443 std::vector<double> perplane_values[3];
444 for (
int ind=0; ind<
ntot; ++ind) {
445 const int chid = traces[ind]->channel();
446 const int iplane = m_anode->resolve(chid).index();
447 perplane_channels[iplane].push_back(chid);
448 perplane_values[iplane].push_back(
summary[ind]);
450 for (
int iplane=0; iplane<3; ++iplane) {
451 std::vector<int>& chans = perplane_channels[iplane];
452 std::vector<double>& vals = perplane_values[iplane];
453 if (!chans.empty()) {
454 auto mme = std::minmax_element(chans.begin(), chans.end());
455 const int ch0 = *mme.first;
456 const int chf = *mme.second;
457 const std::string hname = Form(
"h%c_%s",
'u'+iplane, tag.c_str());
458 TH1F*
hist =
new TH1F(hname.c_str(), hname.c_str(),
459 chf-ch0+1, ch0, chf);
460 for (
size_t ind=0; ind<chans.size(); ++ind) {
461 const int x = chans[ind]+0.5;
462 const double val = vals[ind];
464 int bin = hist->FindBin(x);
465 hist->SetBinContent(bin, val);
471 hist->SetDirectory(output_tf);
478 std::unordered_map<std::string, std::string> cmmkey2treename;
479 for (
auto jcmmtree : m_cfg[
"cmmtree"]) {
480 cmmkey2treename[jcmmtree[0].asString()] = jcmmtree[1].asString();
484 for (
auto const& it: input_cmm) {
485 auto cmmkey = it.first;
486 auto ct = cmmkey2treename.find(cmmkey);
487 if (ct == cmmkey2treename.end()) {
488 log->warn(
"MagnifySink: warning: found channel mask \"{}\", but no tree configured to accept it",
493 auto treename = ct->second;
495 log->debug(
"MagnifySink: saving channel mask \"{}\" to tree \"{}\"",
498 TTree *tree =
new TTree(treename.c_str(), treename.c_str());
499 int chid=0, plane=0, start_time=0, end_time=0;
500 tree->Branch(
"chid",&chid,
"chid/I");
501 tree->Branch(
"plane",&plane,
"plane/I");
502 tree->Branch(
"start_time",&start_time,
"start_time/I");
503 tree->Branch(
"end_time",&end_time,
"end_time/I");
504 tree->SetDirectory(output_tf);
506 for (
auto const &chmask : it.second){
508 plane = m_anode->resolve(chid).index();
509 auto mask = chmask.second;
510 for (
size_t ind = 0; ind <
mask.size(); ++ind){
511 start_time =
mask[ind].first;
512 end_time =
mask[ind].second;
522 auto count = output_tf->Write();
523 log->debug(
"MagnifySink: closing output file {}, wrote {} bytes", ofname, count);
std::shared_ptr< const IFrame > pointer
std::vector< WireCell::Binning > collate_byplane(const ITrace::vector &traces, const IAnodePlane::pointer anode, ITrace::vector byplane[])
boost::error_info< struct tag_errmsg, std::string > errmsg
std::vector< pointer > vector
std::unordered_set< std::string > string_set_t
static ITrace::vector tagged_traces(IFrame::pointer frame, IFrame::tag_t tag)
WIRECELL_FACTORY(MagnifySink, WireCell::Root::MagnifySink, WireCell::IFrameFilter, WireCell::IConfigurable) using namespace WireCell
logptr_t logger(std::string name)
Thrown when a wrong value has been encountered.
void log(source_loc source, level::level_enum lvl, const char *fmt, const Args &...args)
Json::Value Configuration
QTextStream & bin(QTextStream &s)
string_set_t getset(const WireCell::Configuration &cfg)
const GenericPointer< typename T::ValueType > & pointer
decltype(auto) constexpr empty(T &&obj)
ADL-aware version of std::empty.
QTextStream & endl(QTextStream &s)