|
| 1 | +// Copyright CERN and copyright holders of ALICE O2. This software is |
| 2 | +// distributed under the terms of the GNU General Public License v3 (GPL |
| 3 | +// Version 3), copied verbatim in the file "COPYING". |
| 4 | +// |
| 5 | +// See http://alice-o2.web.cern.ch/license for full licensing information. |
| 6 | +// |
| 7 | +// In applying this license CERN does not waive the privileges and immunities |
| 8 | +// granted to it by virtue of its status as an Intergovernmental Organization |
| 9 | +// or submit itself to any jurisdiction. |
| 10 | + |
| 11 | +/// @file RootFileWriterSpec.cxx |
| 12 | +/// @author Matthias Richter |
| 13 | +/// @since 2018-04-19 |
| 14 | +/// @brief Processor spec for a ROOT file writer |
| 15 | + |
| 16 | +#include "RootFileWriterSpec.h" |
| 17 | +#include "Framework/ControlService.h" |
| 18 | +#include "DataFormatsTPC/TrackTPC.h" |
| 19 | +#include <TFile.h> |
| 20 | +#include <TTree.h> |
| 21 | +#include <memory> // for make_shared, make_unique, unique_ptr |
| 22 | +#include <stdexcept> |
| 23 | + |
| 24 | +using namespace o2::framework; |
| 25 | + |
| 26 | +namespace o2 |
| 27 | +{ |
| 28 | +namespace TPC |
| 29 | +{ |
| 30 | +/// create a processor spec |
| 31 | +/// read simulated TPC digits from file and publish |
| 32 | +DataProcessorSpec getRootFileWriterSpec() |
| 33 | +{ |
| 34 | + auto initFunction = [](InitContext& ic) { |
| 35 | + // get the option from the init context |
| 36 | + auto filename = ic.options().get<std::string>("outfile"); |
| 37 | + auto treename = ic.options().get<std::string>("treename"); |
| 38 | + auto nofEvents = ic.options().get<int>("nevents"); |
| 39 | + if (nofEvents < 0) { |
| 40 | + // this is a hack for the moment to workaround that there is no cleanup function |
| 41 | + // we require a number of events after which to close |
| 42 | + std::runtime_error("number of events required"); |
| 43 | + } |
| 44 | + |
| 45 | + auto outputfile = std::make_shared<TFile>(filename.c_str(), "RECREATE"); |
| 46 | + auto outputtree = std::make_shared<TTree>(treename.c_str(), treename.c_str()); |
| 47 | + auto tracks = std::make_shared<std::vector<o2::TPC::TrackTPC>>(); |
| 48 | + auto trackbranch = outputtree->Branch("Tracks", tracks.get()); |
| 49 | + |
| 50 | + // set up the processing function |
| 51 | + // using by-copy capture of the worker instance shared pointer |
| 52 | + // the shared pointer makes sure to clean up the instance when the processing |
| 53 | + // function gets out of scope |
| 54 | + auto processingFct = [outputfile, outputtree, tracks, nofEvents](ProcessingContext& pc) { |
| 55 | + auto indata = pc.inputs().get<std::vector<o2::TPC::TrackTPC>>("input"); |
| 56 | + LOG(INFO) << "RootFileWriter: get " << indata->size() << " track(s)"; |
| 57 | + *tracks.get() = std::move(*indata.get()); |
| 58 | + LOG(INFO) << "RootFileWriter: write " << tracks->size() << " track(s)"; |
| 59 | + outputtree->Fill(); |
| 60 | + |
| 61 | + // a cleanup callback is soon going to be supported in the framework |
| 62 | + if (outputtree->GetEntries() == nofEvents) { |
| 63 | + outputtree->Write(); |
| 64 | + outputfile->Close(); |
| 65 | + pc.services().get<ControlService>().readyToQuit(true); |
| 66 | + } |
| 67 | + }; |
| 68 | + |
| 69 | + // return the actual processing function as a lambda function using variables |
| 70 | + // of the init function |
| 71 | + return processingFct; |
| 72 | + }; |
| 73 | + |
| 74 | + return DataProcessorSpec{ "writer", |
| 75 | + { InputSpec{ "input", "TPC", "TRACKS", 0, Lifetime::Timeframe } }, // track input |
| 76 | + {}, // no output |
| 77 | + AlgorithmSpec(initFunction), |
| 78 | + Options{ |
| 79 | + { "outfile", VariantType::String, "tpctracks.root", { "Name of the input file" } }, |
| 80 | + { "treename", VariantType::String, "Tracks", { "Name of tree for tracks" } }, |
| 81 | + { "nevents", VariantType::Int, -1, { "number of events to run" } }, |
| 82 | + } }; |
| 83 | +} |
| 84 | +} // end namespace TPC |
| 85 | +} // end namespace o2 |
0 commit comments