AGAPRO_TreeBuilder.cpp 13 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/***************************************************************************
 *   Copyright (C) 2004 by Jeremie Dudouet                                 *
 *   jeremie.dudouet(AT)csnsm.in2p3.fr                                     *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

/** \file TreeBuilder.cpp compiled in libADF.so */
22
#include "AGAPROConfig.h"
23 24 25 26 27

#ifndef AGAPRO_TreeBuilder
#include "AGAPRO_TreeBuilder.h"
#endif

28
#include "AGAPRO_TB_AGATA.h"
29 30

#ifdef HAS_MFM
31 32
#include "AGAPRO_TB_NEDA.h"
#include "AGAPRO_TB_DIAMANT.h"
33 34 35
#endif

#if defined(HAS_MFM) && defined(HAS_VAMOS)
36
#include "AGAPRO_TB_VAMOS.h"
37
#endif
38 39

#include "ConfReader.h"
40 41 42

#include "TTree.h"
#include "TFile.h"
43
#include "TROOT.h"
44 45 46 47 48 49

using namespace AGAPRO;

string TreeBuilder::gMotherClass = "TreeBuilder";
string TreeBuilder::gActualClass;

50
TreeBuilder::TreeBuilder() = default;
51 52 53 54 55

TreeBuilder::~TreeBuilder()
{
    cServer.Finish();

56
    if(fFile != nullptr) {
57 58 59 60
        cout << " ####################################  " << endl;
        cout << " Number of read events                 " << fReadEvts << endl;
        cout << " ####################################  " << endl;

61
        fFile->cd();
62 63 64
        fTree->Write();
        fFile->Close();

65
        // in principle not needed ... just in case reset it has not been called by narval
66
        UInt_t error = 0; process_reset(&error) ;
67
    }
68

69
    for(auto det : fListOfDets){
70 71
        delete det;
    }
72 73 74 75
}

void TreeBuilder::process_config(const Char_t *directory_path, UInt_t *error_code)
{
76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98
    *error_code = 0;
    cout << gMotherClass + "::process_config() called with directory_path = " << directory_path << endl;

    // first init narval stuff
    NarvalInterface::process_config(directory_path, error_code);
    if( *error_code )
        return;

    // Get name of daughter class from configuration directory_path/gMotherClass.conf
    int rv = getKeyFromFile(GetGlobalConfPath() + gMotherClass + ".conf", "ActualClass", gActualClass);
    if(rv == 2)
        *error_code = 102; // Fatal error because the configuration file MUST be present
}


void TreeBuilder::process_initialise (UInt_t *error_code)
{
    Log.ClearMessage();
    Log.GetProcessName() = gMotherClass;
    Log.SetProcessMethod("process_initialise");
    Log.SetPID(GetPID());

    *error_code = GetParameters(GetConfPath() + gMotherClass + ".conf");
99
    if(*error_code) {
100 101 102 103 104 105 106 107 108 109 110 111 112
        Log << dolog;
        return;
    }

    UInt_t rerr = 0;
    std::cout << std::endl;

    rerr |= BuildTrigger();

    // the trigger is registered
    if( !fFrameIO.Register(fTrigger) )
        rerr |= 2;

113
    if(rerr) {
114 115 116 117 118 119 120 121 122 123 124 125 126
        std::cout << "Trigger definition error " << rerr << " in TreeBuilder::process_initialise()" << std::endl;
        *error_code = 100 + rerr;
        Log << dolog;
        return;
    }

    // state set to kIdle so that the data can be treated
    fFrameIO.SetStatus(BaseFrameIO::kIdle);

    cServer.SetCommandFile(GetConfPath() + gActualClass + ".live");

    cServer.Start(gActualClass);

127
    for(auto det: fListOfDets) det->Init();
128 129 130 131

    NewTree();

    Log << dolog;
132 133 134 135 136 137 138 139 140 141 142
}

void TreeBuilder::process_start (UInt_t *error_code)
{
    Log.GetProcessName() = "TreeBuilder";
    Log.SetProcessMethod("process_start");
    cServer.Start(gActualClass);
    *error_code = 0;
    Log << dolog;
}

143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163
void TreeBuilder::process_reset (UInt_t *error_code)
{
    *error_code = 0;
    Log.ClearMessage();
    Log.SetProcessMethod("process_reset");
    fFrameIO.Print(Log());

    //cServer.Reset();
    Log << dolog;
}

void TreeBuilder::process_stop (UInt_t *error_code)
{
    std::cout << "-TreeBuilder::process_stop called with GetPID() " << GetPID() << std::endl;
    *error_code = 0;

    cServer.Finish();
}

Int_t TreeBuilder::SetInput()
{
164
    if(fMergerMode) {
165 166
        fAgataComposite = dynamic_cast< AgataCompositeFrame *> ( fTrigger->GetInputFrame() );
        fAgataComposite->Scan();
167
        timestamp = dynamic_cast<AgataKey*>(fAgataComposite->GetKey())->GetTimeStamp();
168
    }
169

170
    //    cout<<AgataKeyFactory::theFactory()->GetMessage(((AgataKey*)fAgataComposite->GetKey())->GetMessage())<<endl;
171

172 173 174 175
    //    for(int i=0 ; i<fAgataComposite->GetNbSubFrame() ; i++)
    //    {
    //        cout<<AgataKeyFactory::theFactory()->GetMessage( ((AgataKey*)fAgataComposite->GetSubKey(i))->GetMessage() )<<" ";
    //    }
176

177
    //    cout<<endl;
178

179
    for(size_t idet=0 ; idet<fListOfDets.size() ; idet ++) {
180 181 182 183
        TB_Detector *det = fListOfDets[idet];

        det->InitValues();

184
        if(!fMergerMode)
185 186 187
            det->SetTriggered(fTrigger->IsIndividualFired(0));
        else
            det->SetTriggered(fTrigger->IsIndividualFired(idet+1)); // +1 because the first value is for the global trigger
188 189 190 191 192
    }

    return 0;
}

193 194 195
UInt_t TreeBuilder::ProcessBlock(ADF::FrameBlock &inBlock)
{
    // attach the input/output buffer to the FrameIO system
196
    fFrameIO.Attach(&inBlock, nullptr);
197 198 199 200 201 202 203 204

    // start the processing
    UInt_t error_code = 0;
    UInt_t nevs = 0;

    if(fFile->GetEND()>fMaxFileSize)
        NewTree();

205
    while ( fFrameIO.Notify() ) {
206 207 208
        // fill local variables with data from the input
        error_code = SetInput();

209
        if( error_code == 1) {
210 211 212 213 214
            LOCK_COUT;
            Log.SetProcessMethod("ProcessBlock");
            Log << error << " During : SetInput()" << dolog;
            break;
        }
215

216 217 218 219 220 221 222
        bool has_triggered = false;
        for(size_t idet=0 ; idet<fListOfDets.size() ; idet ++) {
            TB_Detector *det = fListOfDets[idet];
            if(det->IsTriggered()) {
                has_triggered = true;
                det->Process(idet);
            }
223 224
        }

225 226 227
        if(has_triggered)
            fTree->Fill();

228 229
        nevs++;
        fReadEvts++;
230 231

        if(fReadEvts%fAutoSave == 0) {
232
            fTree->AutoSave();
233
        }
234 235
    }

236
    fFrameIO.Detach(&inBlock, nullptr);
237 238 239 240 241 242 243 244 245 246 247 248

    cServer.Exec(timestamp, nevs);

    LOCK_COUT;
    cServer.Prompt(GetPID(), (int)nevs, UInt_t(inBlock.GetSize()), true );

    return error_code;
}


void TreeBuilder::NewTree()
{
249 250
    if(fFile) {
        fFile->cd();
251
        fTree->Write();
252
        fTree->SetDirectory(nullptr);
253
        fFile->Close();
254
    }
255 256 257

    TString Name = Form("%s/%s%.4d.root",fSaveDir.data(),fNamePatern.data(),fCurrentFileNumber);
    fFile = new TFile(Name,"recreate");
258 259
    // default compression level, good compression and processing time
    fFile->SetCompressionLevel();
260

261 262
    if(fTree == nullptr) {
        fTree = new TTree(fTreeName.data(),fTreeName.data());
263

264 265 266
        for(auto &det: fListOfDets) {
            det->SetTree(fTree);
            det->InitTree();
267 268 269 270 271
        }
    }
    else {
        fTree->Reset();
        fTree->SetDirectory(fFile);
272
    }
273 274

    fCurrentFileNumber++;
275 276
}

277
UInt_t TreeBuilder::GetParameters(const std::string& confFile, Bool_t doList)
278
{
279 280 281 282
    Log.ClearMessage();
    Log.GetProcessName() = gMotherClass;
    Log.SetProcessMethod(Form("GetParameters(confFile=%s,doList=%d)",confFile.data(),doList));
    Log.SetPID(GetPID());
283

284 285 286
    string Detector;
    string ADFKey;
    int MandatoryMode;
287

288 289 290 291 292
    ConfReader conf;
    conf.Add("ActualClass",         "name of daughter class",
             &gActualClass);
    conf.Add("SaveDataDir",         "Save root file dir (SaveDir, NamePatern, TreeName)",
             &fSaveDir, &fNamePatern, &fTreeName);
293 294 295
    conf.Add("MergerMode",          "If the EventMerger is used (first trigger will be done on event:data frames)",
             &fMergerMode);
    conf.Add("AddDetector",         "Add a detector in the Tree (DetName, ADF key, Mode [-1: Must NOT be present, 0: Can be present, 1: Must be present]), accepted detectors: AGATA_PSA,AGATA_BUILDER, AGATA_TRACKING, NEDA, DIAMANT, VAMOS",
296
             &Detector, &ADFKey, &MandatoryMode);
297

298
    if(doList) {conf.Show(gMotherClass); return 0;}
299

300 301 302
    int rv = conf.Read(gMotherClass, confFile);
    if(rv)
        return rv;    // Read() error
303

304 305 306 307
    if(!conf.Seen("SaveDataDir")) {
        Log << error << " The SaveDataDir parameters must be given" << dolog;
        rv = 200;
    }
308

309 310 311 312 313
    if(conf.Seen("AddDetector")) {
        int which = conf.Find("AddDetector");
        int times = conf.Times(which);
        for(int nn = 0; nn < times; nn++) {
            conf.Restore(which, nn);
314

315 316 317 318 319 320 321 322 323 324 325
            if(!fMergerMode && ((TString)ADFKey).Contains("anc")) {
                Log << error << " Ancillary detector set, but MergerMode is not used..." << dolog;
            }
            else if(fMergerMode && Detector == "AGATA_PSA") {
                Log << error << " MergerMode cannot be used to read local level PSA data..." << dolog;
            }
            else if(fMergerMode && Detector == "AGATA_CRYSTAL") {
                Log << error << " MergerMode cannot be used to read local level Crystal data..." << dolog;
            }
            else {
                AddDetector(Detector,ADFKey,MandatoryMode);
326
            }
327

328 329 330
        }
    }

331
    if(fListOfDets.empty()) {
332 333 334
        Log << error << " No detector added in the Tree" << dolog;
        rv = 201;
    }
335

336 337
    if(!fMergerMode && fListOfDets.size()>1) {
        Log << error << " Only one detector type can be defined when MergerMode is not used" << dolog;
338 339 340
        rv = 202;
    }

341
    return rv;
342 343
}

344
void TreeBuilder::AddDetector(const TString &Name, TString ADFKey, Int_t MandatoryMode)
345 346
{
    Log.ClearMessage();
347 348
    Log.GetProcessName() = gMotherClass;
    Log.SetProcessMethod(Form("AddDetector(Name=%s,ADFKey=%s,MandatoryMode=%d)",Name.Data(),ADFKey.Data(),MandatoryMode));
349 350
    Log.SetPID(GetPID());

351
    UInt_t mess;
352
    if( ! AgataKeyFactory::theFactory()->GetMessage(ADFKey.Data(),mess)) {
353 354 355
        Log << error << ADFKey << " Unkown adf key" << dolog;
        return;
    }
356

357
    if(MandatoryMode<-1 || MandatoryMode>1) {
358 359 360
        Log << error << " MandatoryMode must be either -1 (must not be present) , 0 (can be present) or 1 (must be present)" << dolog;
        return;
    }
361

362 363 364 365
    if(MandatoryMode == -1)
        ADFKey.Prepend("!");
    else if(MandatoryMode == 0)
        ADFKey.Prepend("|");
366

367 368
    TString NameTest = Name.Copy();
    NameTest.ToLower();
369

370
    TB_Detector *det = nullptr;
371

372 373 374
    if(NameTest == "agata_crystal") {
        det = new TB_AGATA_CRYSTAL(NameTest,ADFKey);
    }
375
    else if(NameTest == "agata_psa") {
376 377
        det = new TB_AGATA_PSA(NameTest,ADFKey);
    }
378 379
    else if(NameTest == "agata_builder" && ADFKey.Contains("crystal")) {
        det = new TB_AGATA_Builder_CRYSTAL(NameTest,ADFKey);
380
    }
381 382 383 384
    else if(NameTest == "agata_builder" && ADFKey.Contains("psa")) {
        det = new TB_AGATA_Builder_PSA(NameTest,ADFKey);
    }
    else if(NameTest == "agata_tracking") {
385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404
        det = new TB_AGATA_Tracking(NameTest,ADFKey);
    }
    else if(NameTest == "neda")
    {
#ifdef HAS_MFM
        det = new TB_NEDA(NameTest,ADFKey);
#else
        Log << error << " MFM not found, NEDA TreeBuilder ignored" << dolog;
        return;
#endif
    }
    else if(NameTest == "diamant")
    {
#ifdef HAS_MFM
        det = new TB_DIAMANT(NameTest,ADFKey);
#else
        Log << error << " MFM not found, DIAMANT TreeBuilder ignored" << dolog;
        return;
#endif
    }
405
    else if(NameTest == "vamos") {
406
#if defined(HAS_MFM) && defined(HAS_VAMOS)
407 408
        det = new TB_VAMOS(NameTest,ADFKey);
#else
409
        Log << error << " Vamos lib and/or MFM lib not found, VAMOS TreeBuilder ignored" << dolog;
410 411
        return;
#endif
412 413
    }

414
    if(det) {
415
        det->SetConfPath(GetConfPath());
416
        det->SetOutputPath(fSaveDir);
417
        det->SetMergerMode(fMergerMode);
418 419
        fListOfDets.push_back(det);
    }
420
    else {
421
        Log << error << Name << " ; " << ADFKey << " ==> Unkonwn detector of trigger" << dolog;
422
        return;
423
    }
424
}
425

426 427
Int_t TreeBuilder::BuildTrigger()
{
428
    if(!fMergerMode)
429 430 431
        fTriggerName="";
    else
        fTriggerName = "event:data ";
432

433
    for(auto &det: fListOfDets) fTriggerName += det->GetTriggerName() + " ";
434 435

    fTriggerName.Remove(fTriggerName.Length()-1); // remove the last empty space
436 437 438

    fTrigger = AgataFrameTrigger::Build("Event", fTriggerName.Data());

439
    if ( fTrigger) {
440
        for(auto det: fListOfDets) det->SetTrigger(fTrigger);
441 442 443 444 445
    }
    else
        return 1;

    return 0;
446
}