1 /**************************************************************************
2 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
4 * Author: The ALICE Off-line Project. *
5 * Contributors are mentioned in the code where appropriate. *
7 * Permission to use, copy, modify and distribute this software and its *
8 * documentation strictly for non-commercial purposes is hereby granted *
9 * without fee, provided that the above copyright notice appears in all *
10 * copies and that both the copyright notice and this permission notice *
11 * appear in the supporting documentation. The authors make no claims *
12 * about the suitability of this software for any purpose. It is *
13 * provided "as is" without express or implied warranty. *
14 **************************************************************************/
18 ///////////////////////////////////////////////////////////////////////////////
20 // class for running the reconstruction //
22 // Clusters and tracks are created for all detectors and all events by //
25 // AliReconstruction rec; //
28 // The Run method returns kTRUE in case of successful execution. //
30 // If the input to the reconstruction are not simulated digits but raw data, //
31 // this can be specified by an argument of the Run method or by the method //
33 // rec.SetInput("..."); //
35 // The input formats and the corresponding argument are: //
36 // - DDL raw data files: directory name, ends with "/" //
37 // - raw data root file: root file name, extension ".root" //
38 // - raw data DATE file: DATE file name, any other non-empty string //
39 // - MC root files : empty string, default //
41 // The name of the galice file can be changed from the default //
42 // "galice.root" by passing it as argument to the AliReconstruction //
43 // constructor or by //
45 // rec.SetGAliceFile("..."); //
47 // The local reconstruction can be switched on or off for individual //
50 // rec.SetRunLocalReconstruction("..."); //
52 // The argument is a (case sensitive) string with the names of the //
53 // detectors separated by a space. The special string "ALL" selects all //
54 // available detectors. This is the default. //
56 // The reconstruction of the primary vertex position can be switched off by //
58 // rec.SetRunVertexFinder(kFALSE); //
60 // The tracking in ITS, TPC and TRD and the creation of ESD tracks can be //
63 // rec.SetRunTracking(kFALSE); //
65 // The filling of additional ESD information can be steered by //
67 // rec.SetFillESD("..."); //
69 // Again, the string specifies the list of detectors. The default is "ALL". //
71 // The reconstruction requires digits or raw data as input. For the creation //
72 // of digits and raw data have a look at the class AliSimulation. //
74 // For debug purposes the method SetCheckPointLevel can be used. If the //
75 // argument is greater than 0, files with ESD events will be written after //
76 // selected steps of the reconstruction for each event: //
77 // level 1: after tracking and after filling of ESD (final) //
78 // level 2: in addition after each tracking step //
79 // level 3: in addition after the filling of ESD for each detector //
80 // If a final check point file exists for an event, this event will be //
81 // skipped in the reconstruction. The tracking and the filling of ESD for //
82 // a detector will be skipped as well, if the corresponding check point //
83 // file exists. The ESD event will then be loaded from the file instead. //
85 ///////////////////////////////////////////////////////////////////////////////
91 #include <TPluginManager.h>
92 #include <TStopwatch.h>
94 #include "AliReconstruction.h"
95 #include "AliRunLoader.h"
97 #include "AliRawReaderFile.h"
98 #include "AliRawReaderDate.h"
99 #include "AliRawReaderRoot.h"
100 #include "AliTracker.h"
102 #include "AliESDVertex.h"
103 #include "AliVertexer.h"
104 #include "AliHeader.h"
105 #include "AliGenEventHeader.h"
106 #include "AliESDpid.h"
109 ClassImp(AliReconstruction)
112 //_____________________________________________________________________________
113 const char* AliReconstruction::fgkDetectorName[AliReconstruction::fgkNDetectors] = {"ITS", "TPC", "TRD", "TOF", "PHOS", "RICH", "EMCAL", "MUON", "FMD", "ZDC", "PMD", "START", "VZERO", "CRT", "HLT"};
115 //_____________________________________________________________________________
116 AliReconstruction::AliReconstruction(const char* gAliceFilename,
117 const char* name, const char* title) :
120 fRunLocalReconstruction("ALL"),
121 fRunVertexFinder(kTRUE),
124 fGAliceFileName(gAliceFilename),
126 fStopOnError(kFALSE),
144 // create reconstruction object with default parameters
148 //_____________________________________________________________________________
149 AliReconstruction::AliReconstruction(const AliReconstruction& rec) :
152 fRunLocalReconstruction(rec.fRunLocalReconstruction),
153 fRunVertexFinder(rec.fRunVertexFinder),
154 fRunTracking(rec.fRunTracking),
155 fFillESD(rec.fFillESD),
156 fGAliceFileName(rec.fGAliceFileName),
158 fStopOnError(rec.fStopOnError),
178 for (Int_t i = 0; i < fOptions.GetEntriesFast(); i++) {
179 if (rec.fOptions[i]) fOptions.Add(rec.fOptions[i]->Clone());
183 //_____________________________________________________________________________
184 AliReconstruction& AliReconstruction::operator = (const AliReconstruction& rec)
186 // assignment operator
188 this->~AliReconstruction();
189 new(this) AliReconstruction(rec);
193 //_____________________________________________________________________________
194 AliReconstruction::~AliReconstruction()
203 //_____________________________________________________________________________
204 void AliReconstruction::SetGAliceFile(const char* fileName)
206 // set the name of the galice file
208 fGAliceFileName = fileName;
211 //_____________________________________________________________________________
212 void AliReconstruction::SetOption(const char* detector, const char* option)
214 // set options for the reconstruction of a detector
216 TObject* obj = fOptions.FindObject(detector);
217 if (obj) fOptions.Remove(obj);
218 fOptions.Add(new TNamed(detector, option));
222 //_____________________________________________________________________________
223 Bool_t AliReconstruction::Run(const char* input)
225 // run the reconstruction
228 if (!input) input = fInput.Data();
229 TString fileName(input);
230 if (fileName.EndsWith("/")) {
231 fRawReader = new AliRawReaderFile(fileName);
232 } else if (fileName.EndsWith(".root")) {
233 fRawReader = new AliRawReaderRoot(fileName);
234 } else if (!fileName.IsNull()) {
235 fRawReader = new AliRawReaderDate(fileName);
236 fRawReader->SelectEvents(7);
239 // open the run loader
240 fRunLoader = AliRunLoader::Open(fGAliceFileName.Data());
242 Error("Run", "no run loader found in file %s",
243 fGAliceFileName.Data());
247 fRunLoader->LoadgAlice();
248 AliRun* aliRun = fRunLoader->GetAliRun();
250 Error("Run", "no gAlice object found in file %s",
251 fGAliceFileName.Data());
257 // load the reconstructor objects
258 TPluginManager* pluginManager = gROOT->GetPluginManager();
259 for (Int_t iDet = 0; iDet < fgkNDetectors; iDet++) {
260 TString detName = fgkDetectorName[iDet];
261 TString recName = "Ali" + detName + "Reconstructor";
262 if (!gAlice->GetDetector(detName) && detName != "HLT") continue;
264 if(detName == "HLT") {
265 if (!gROOT->GetClass("AliLevel3")) {
266 gSystem->Load("libAliL3Src.so");
267 gSystem->Load("libAliL3Misc.so");
268 gSystem->Load("libAliL3Hough.so");
269 gSystem->Load("libAliL3Comp.so");
273 AliReconstructor* reconstructor = NULL;
274 // first check if a plugin is defined for the reconstructor
275 TPluginHandler* pluginHandler =
276 pluginManager->FindHandler("AliReconstructor", detName);
277 // if not, but the reconstructor class is implemented, add a plugin for it
278 if (!pluginHandler && gROOT->GetClass(recName.Data())) {
279 Info("Run", "defining plugin for %s", recName.Data());
280 pluginManager->AddHandler("AliReconstructor", detName,
281 recName, detName, recName + "()");
282 pluginHandler = pluginManager->FindHandler("AliReconstructor", detName);
284 if (pluginHandler && (pluginHandler->LoadPlugin() == 0)) {
285 reconstructor = (AliReconstructor*) pluginHandler->ExecPlugin(0);
287 // if there is no reconstructor class for the detector use the dummy one
288 if (!reconstructor && gAlice->GetDetector(detName)) {
289 Info("Run", "using dummy reconstructor for %s", detName.Data());
290 reconstructor = new AliDummyReconstructor(gAlice->GetDetector(detName));
293 TObject* obj = fOptions.FindObject(detName.Data());
294 if (obj) reconstructor->SetOption(obj->GetTitle());
295 fReconstructors.Add(reconstructor);
299 // local reconstruction
300 if (!fRunLocalReconstruction.IsNull()) {
301 if (!RunLocalReconstruction(fRunLocalReconstruction)) {
302 if (fStopOnError) {CleanUp(); return kFALSE;}
305 if (!fRunVertexFinder && !fRunTracking && fFillESD.IsNull()) return kTRUE;
308 if (fRunVertexFinder && !CreateVertexer()) {
315 // get loaders and trackers
316 if (fRunTracking && !CreateTrackers()) {
323 // create the ESD output file and tree
324 TFile* file = TFile::Open("AliESDs.root", "RECREATE");
325 if (!file->IsOpen()) {
326 Error("Run", "opening AliESDs.root failed");
327 if (fStopOnError) {CleanUp(file); return kFALSE;}
329 AliESD* esd = new AliESD;
330 TTree* tree = new TTree("esdTree", "Tree with ESD objects");
331 tree->Branch("ESD", "AliESD", &esd);
336 if (fRawReader) fRawReader->RewindEvents();
337 for (Int_t iEvent = 0; iEvent < fRunLoader->GetNumberOfEvents(); iEvent++) {
338 Info("Run", "processing event %d", iEvent);
339 fRunLoader->GetEvent(iEvent);
340 if (fRawReader) fRawReader->NextEvent();
343 sprintf(fileName, "ESD_%d.%d_final.root",
344 aliRun->GetRunNumber(), aliRun->GetEvNumber());
345 if (!gSystem->AccessPathName(fileName)) continue;
348 esd->SetRunNumber(aliRun->GetRunNumber());
349 esd->SetEventNumber(aliRun->GetEvNumber());
350 esd->SetMagneticField(aliRun->Field()->SolenoidField());
353 if (fRunVertexFinder) {
354 if (!ReadESD(esd, "vertex")) {
355 if (!RunVertexFinder(esd)) {
356 if (fStopOnError) {CleanUp(file); return kFALSE;}
358 if (fCheckPointLevel > 0) WriteESD(esd, "vertex");
364 if (!ReadESD(esd, "tracking")) {
365 if (!RunTracking(esd)) {
366 if (fStopOnError) {CleanUp(file); return kFALSE;}
368 if (fCheckPointLevel > 0) WriteESD(esd, "tracking");
373 if (!fFillESD.IsNull()) {
374 if (!FillESD(esd, fFillESD)) {
375 if (fStopOnError) {CleanUp(file); return kFALSE;}
380 AliESDpid::MakePID(esd);
381 if (fCheckPointLevel > 1) WriteESD(esd, "PID");
386 if (fCheckPointLevel > 0) WriteESD(esd, "final");
398 //_____________________________________________________________________________
399 Bool_t AliReconstruction::RunLocalReconstruction(const TString& detectors)
401 // run the local reconstruction
403 TStopwatch stopwatch;
406 TString detStr = detectors;
407 for (Int_t iDet = 0; iDet < fReconstructors.GetEntriesFast(); iDet++) {
408 AliReconstructor* reconstructor =
409 (AliReconstructor*) fReconstructors[iDet];
410 TString detName = reconstructor->GetDetectorName();
411 if (IsSelected(detName, detStr)) {
412 Info("RunLocalReconstruction", "running reconstruction for %s",
414 TStopwatch stopwatchDet;
415 stopwatchDet.Start();
417 fRawReader->RewindEvents();
418 reconstructor->Reconstruct(fRunLoader, fRawReader);
420 reconstructor->Reconstruct(fRunLoader);
422 Info("RunLocalReconstruction", "execution time for %s:", detName.Data());
423 stopwatchDet.Print();
427 if ((detStr.CompareTo("ALL") != 0) && !detStr.IsNull()) {
428 Error("RunLocalReconstruction",
429 "the following detectors were not found: %s", detStr.Data());
430 if (fStopOnError) return kFALSE;
433 Info("RunLocalReconstruction", "execution time:");
439 //_____________________________________________________________________________
440 Bool_t AliReconstruction::RunVertexFinder(AliESD*& esd)
442 // run the barrel tracking
444 TStopwatch stopwatch;
447 AliESDVertex* vertex = NULL;
448 Double_t vtxPos[3] = {0, 0, 0};
449 Double_t vtxErr[3] = {0.07, 0.07, 0.1};
451 if (fRunLoader->GetHeader() && fRunLoader->GetHeader()->GenEventHeader()) {
452 fRunLoader->GetHeader()->GenEventHeader()->PrimaryVertex(mcVertex);
453 for (Int_t i = 0; i < 3; i++) vtxPos[i] = mcVertex[i];
457 Info("RunVertexFinder", "running the ITS vertex finder");
458 fITSVertexer->SetDebug(1);
459 vertex = fITSVertexer->FindVertexForCurrentEvent(fRunLoader->GetEventNumber());
461 Warning("RunVertexFinder","Vertex not found \n");
462 vertex = new AliESDVertex();
465 vertex->SetTruePos(vtxPos); // store also the vertex from MC
469 Info("RunVertexFinder", "getting the primary vertex from MC");
470 vertex = new AliESDVertex(vtxPos, vtxErr);
474 vertex->GetXYZ(vtxPos);
475 vertex->GetSigmaXYZ(vtxErr);
477 Warning("RunVertexFinder", "no vertex reconstructed");
478 vertex = new AliESDVertex(vtxPos, vtxErr);
480 esd->SetVertex(vertex);
481 if (fITSTracker) fITSTracker->SetVertex(vtxPos, vtxErr);
482 if (fTPCTracker) fTPCTracker->SetVertex(vtxPos, vtxErr);
483 if (fTRDTracker) fTRDTracker->SetVertex(vtxPos, vtxErr);
486 Info("RunVertexFinder", "execution time:");
492 //_____________________________________________________________________________
493 Bool_t AliReconstruction::RunTracking(AliESD*& esd)
495 // run the barrel tracking
497 TStopwatch stopwatch;
501 Error("RunTracking", "no TPC tracker");
506 Info("RunTracking", "TPC tracking");
507 fTPCLoader->LoadRecPoints("read");
508 TTree* tpcTree = fTPCLoader->TreeR();
510 Error("RunTracking", "Can't get the TPC cluster tree");
513 fTPCTracker->LoadClusters(tpcTree);
514 if (fTPCTracker->Clusters2Tracks(esd) != 0) {
515 Error("RunTracking", "TPC Clusters2Tracks failed");
518 if (fCheckPointLevel > 1) WriteESD(esd, "TPC.tracking");
521 Warning("RunTracking", "no ITS tracker");
524 GetReconstructor("TPC")->FillESD(fRunLoader, esd); // preliminary
525 AliESDpid::MakePID(esd); // PID for the ITS tracker
528 Info("RunTracking", "ITS tracking");
529 fITSLoader->LoadRecPoints("read");
530 TTree* itsTree = fITSLoader->TreeR();
532 Error("RunTracking", "Can't get the ITS cluster tree");
535 fITSTracker->LoadClusters(itsTree);
536 if (fITSTracker->Clusters2Tracks(esd) != 0) {
537 Error("RunTracking", "ITS Clusters2Tracks failed");
540 if (fCheckPointLevel > 1) WriteESD(esd, "ITS.tracking");
543 Warning("RunTracking", "no TRD tracker");
545 // ITS back propagation
546 Info("RunTracking", "ITS back propagation");
547 if (fITSTracker->PropagateBack(esd) != 0) {
548 Error("RunTracking", "ITS backward propagation failed");
551 if (fCheckPointLevel > 1) WriteESD(esd, "ITS.back");
553 // TPC back propagation
554 Info("RunTracking", "TPC back propagation");
555 if (fTPCTracker->PropagateBack(esd) != 0) {
556 Error("RunTracking", "TPC backward propagation failed");
559 if (fCheckPointLevel > 1) WriteESD(esd, "TPC.back");
561 // TRD back propagation
562 Info("RunTracking", "TRD back propagation");
563 fTRDLoader->LoadRecPoints("read");
564 TTree* trdTree = fTRDLoader->TreeR();
566 Error("RunTracking", "Can't get the TRD cluster tree");
569 fTRDTracker->LoadClusters(trdTree);
570 if (fTRDTracker->PropagateBack(esd) != 0) {
571 Error("RunTracking", "TRD backward propagation failed");
574 if (fCheckPointLevel > 1) WriteESD(esd, "TRD.back");
577 Warning("RunTracking", "no TOF tracker");
579 // TOF back propagation
580 Info("RunTracking", "TOF back propagation");
581 fTOFLoader->LoadDigits("read");
582 TTree* tofTree = fTOFLoader->TreeD();
584 Error("RunTracking", "Can't get the TOF digits tree");
587 fTOFTracker->LoadClusters(tofTree);
588 if (fTOFTracker->PropagateBack(esd) != 0) {
589 Error("RunTracking", "TOF backward propagation failed");
592 if (fCheckPointLevel > 1) WriteESD(esd, "TOF.back");
593 fTOFTracker->UnloadClusters();
594 fTOFLoader->UnloadDigits();
598 Info("RunTracking", "TRD inward refit");
599 if (fTRDTracker->RefitInward(esd) != 0) {
600 Error("RunTracking", "TRD inward refit failed");
603 if (fCheckPointLevel > 1) WriteESD(esd, "TRD.refit");
604 fTRDTracker->UnloadClusters();
605 fTRDLoader->UnloadRecPoints();
608 Info("RunTracking", "TPC inward refit");
609 if (fTPCTracker->RefitInward(esd) != 0) {
610 Error("RunTracking", "TPC inward refit failed");
613 if (fCheckPointLevel > 1) WriteESD(esd, "TPC.refit");
616 Info("RunTracking", "ITS inward refit");
617 if (fITSTracker->RefitInward(esd) != 0) {
618 Error("RunTracking", "ITS inward refit failed");
621 if (fCheckPointLevel > 1) WriteESD(esd, "ITS.refit");
624 fITSTracker->UnloadClusters();
625 fITSLoader->UnloadRecPoints();
628 fTPCTracker->UnloadClusters();
629 fTPCLoader->UnloadRecPoints();
631 Info("RunTracking", "execution time:");
637 //_____________________________________________________________________________
638 Bool_t AliReconstruction::FillESD(AliESD*& esd, const TString& detectors)
640 // fill the event summary data
642 TStopwatch stopwatch;
645 TString detStr = detectors;
646 for (Int_t iDet = 0; iDet < fReconstructors.GetEntriesFast(); iDet++) {
647 AliReconstructor* reconstructor =
648 (AliReconstructor*) fReconstructors[iDet];
649 TString detName = reconstructor->GetDetectorName();
650 if (IsSelected(detName, detStr)) {
651 if (!ReadESD(esd, detName.Data())) {
652 Info("FillESD", "filling ESD for %s", detName.Data());
654 reconstructor->FillESD(fRunLoader, fRawReader, esd);
656 reconstructor->FillESD(fRunLoader, esd);
658 if (fCheckPointLevel > 2) WriteESD(esd, detName.Data());
663 if ((detStr.CompareTo("ALL") != 0) && !detStr.IsNull()) {
664 Error("FillESD", "the following detectors were not found: %s",
666 if (fStopOnError) return kFALSE;
669 Info("FillESD", "execution time:");
676 //_____________________________________________________________________________
677 Bool_t AliReconstruction::IsSelected(TString detName, TString& detectors) const
679 // check whether detName is contained in detectors
680 // if yes, it is removed from detectors
682 // check if all detectors are selected
683 if ((detectors.CompareTo("ALL") == 0) ||
684 detectors.BeginsWith("ALL ") ||
685 detectors.EndsWith(" ALL") ||
686 detectors.Contains(" ALL ")) {
691 // search for the given detector
692 Bool_t result = kFALSE;
693 if ((detectors.CompareTo(detName) == 0) ||
694 detectors.BeginsWith(detName+" ") ||
695 detectors.EndsWith(" "+detName) ||
696 detectors.Contains(" "+detName+" ")) {
697 detectors.ReplaceAll(detName, "");
701 // clean up the detectors string
702 while (detectors.Contains(" ")) detectors.ReplaceAll(" ", " ");
703 while (detectors.BeginsWith(" ")) detectors.Remove(0, 1);
704 while (detectors.EndsWith(" ")) detectors.Remove(detectors.Length()-1, 1);
709 //_____________________________________________________________________________
710 AliReconstructor* AliReconstruction::GetReconstructor(const char* detName) const
712 // get the reconstructor object for a detector
714 for (Int_t iDet = 0; iDet < fReconstructors.GetEntriesFast(); iDet++) {
715 AliReconstructor* reconstructor =
716 (AliReconstructor*) fReconstructors[iDet];
717 if (strcmp(reconstructor->GetDetectorName(), detName) == 0) {
718 return reconstructor;
724 //_____________________________________________________________________________
725 Bool_t AliReconstruction::CreateVertexer()
727 // create the vertexer
730 AliReconstructor* itsReconstructor = GetReconstructor("ITS");
731 if (itsReconstructor) {
732 fITSVertexer = itsReconstructor->CreateVertexer(fRunLoader);
735 Warning("CreateVertexer", "couldn't create a vertexer for ITS");
736 if (fStopOnError) return kFALSE;
742 //_____________________________________________________________________________
743 Bool_t AliReconstruction::CreateTrackers()
745 // get the loaders and create the trackers
748 fITSLoader = fRunLoader->GetLoader("ITSLoader");
750 Warning("CreateTrackers", "no ITS loader found");
751 if (fStopOnError) return kFALSE;
753 AliReconstructor* itsReconstructor = GetReconstructor("ITS");
754 if (itsReconstructor) {
755 fITSTracker = itsReconstructor->CreateTracker(fRunLoader);
758 Warning("CreateTrackers", "couldn't create a tracker for ITS");
759 if (fStopOnError) return kFALSE;
764 fTPCLoader = fRunLoader->GetLoader("TPCLoader");
766 Error("CreateTrackers", "no TPC loader found");
767 if (fStopOnError) return kFALSE;
769 AliReconstructor* tpcReconstructor = GetReconstructor("TPC");
770 if (tpcReconstructor) {
771 fTPCTracker = tpcReconstructor->CreateTracker(fRunLoader);
774 Error("CreateTrackers", "couldn't create a tracker for TPC");
775 if (fStopOnError) return kFALSE;
780 fTRDLoader = fRunLoader->GetLoader("TRDLoader");
782 Warning("CreateTrackers", "no TRD loader found");
783 if (fStopOnError) return kFALSE;
785 AliReconstructor* trdReconstructor = GetReconstructor("TRD");
786 if (trdReconstructor) {
787 fTRDTracker = trdReconstructor->CreateTracker(fRunLoader);
790 Warning("CreateTrackers", "couldn't create a tracker for TRD");
791 if (fStopOnError) return kFALSE;
796 fTOFLoader = fRunLoader->GetLoader("TOFLoader");
798 Warning("CreateTrackers", "no TOF loader found");
799 if (fStopOnError) return kFALSE;
801 AliReconstructor* tofReconstructor = GetReconstructor("TOF");
802 if (tofReconstructor) {
803 fTOFTracker = tofReconstructor->CreateTracker(fRunLoader);
806 Warning("CreateTrackers", "couldn't create a tracker for TOF");
807 if (fStopOnError) return kFALSE;
814 //_____________________________________________________________________________
815 void AliReconstruction::CleanUp(TFile* file)
817 // delete trackers and the run loader and close and delete the file
819 fReconstructors.Delete();
844 //_____________________________________________________________________________
845 Bool_t AliReconstruction::ReadESD(AliESD*& esd, const char* recStep) const
847 // read the ESD event from a file
849 if (!esd) return kFALSE;
851 sprintf(fileName, "ESD_%d.%d_%s.root",
852 esd->GetRunNumber(), esd->GetEventNumber(), recStep);
853 if (gSystem->AccessPathName(fileName)) return kFALSE;
855 Info("ReadESD", "reading ESD from file %s", fileName);
856 TFile* file = TFile::Open(fileName);
857 if (!file || !file->IsOpen()) {
858 Error("ReadESD", "opening %s failed", fileName);
865 esd = (AliESD*) file->Get("ESD");
871 //_____________________________________________________________________________
872 void AliReconstruction::WriteESD(AliESD* esd, const char* recStep) const
874 // write the ESD event to a file
878 sprintf(fileName, "ESD_%d.%d_%s.root",
879 esd->GetRunNumber(), esd->GetEventNumber(), recStep);
881 Info("WriteESD", "writing ESD to file %s", fileName);
882 TFile* file = TFile::Open(fileName, "recreate");
883 if (!file || !file->IsOpen()) {
884 Error("WriteESD", "opening %s failed", fileName);