--- /dev/null
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* *
+* Author: The ALICE Off-line Project. *
+* Contributors are mentioned in the code where appropriate. *
+* *
+* Permission to use, copy, modify and distribute this software and its *
+* documentation strictly for non-commercial purposes is hereby granted *
+* without fee, provided that the above copyright notice appears in all *
+* copies and that both the copyright notice and this permission notice *
+* appear in the supporting documentation. The authors make no claims *
+* about the suitability of this software for any purpose. It is *
+* provided "as is" without express or implied warranty. *
+**************************************************************************/
+
+// $Id$
+
+#include "AliMUON2DStoreValidator.h"
+
+#include "AliLog.h"
+#include "AliMUONCalibParam1I.h"
+#include "AliMpIntPair.h"
+#include "AliMpManuList.h"
+#include "AliMUONV2DStore.h"
+#include "TList.h"
+#include "TObjArray.h"
+#include "AliMUONCheckItem.h"
+#include "AliMUONCheckItemIterator.h"
+#include "AliMpDEManager.h"
+#include "TObjString.h"
+#include "AliMUONConstants.h"
+#include "Riostream.h"
+
+/// \class AliMUON2DStoreValidator
+///
+/// Determine which channels, manus, DEs, stations are missing
+/// from a 2DStore. This is mainly to be used during (shuttle) preprocessing
+/// to insure that what we'll put in the CDB is as complete as possible,
+/// and to detect possible problem.
+///
+/// We made an effort to present the result of the validation in the most
+/// concise way (i.e. if all channels of a DE are missing, we do not list
+/// them, we just write "DE dead" ;-) )
+///
+/// The list of missing things is kept in a structure of objects defined as :
+///
+/// fMissing = TObjArray[0..N tracking chambers]
+/// fMissing[iChamber] = AliMUONCheckItem which contains n AliMUONCheckItem,
+/// where n is the number of DE for that chamber
+/// fMissing[iChamber]->GetItem(de) = AliMUONCheckItem which contains m
+/// AliMUONCheckItem where m is the number of Manu for that DE
+/// fMissing[iChamber]->GetItem(de)->GetItem(manu) = AliMUONCheckItem which
+/// contains k TObjString = Form("%d",manuChannel)
+///
+/// \author Laurent Aphecetche
+
+/// \cond CLASSIMP
+ClassImp(AliMUON2DStoreValidator)
+/// \endcond
+
+//_____________________________________________________________________________
+AliMUON2DStoreValidator::AliMUON2DStoreValidator()
+: TObject(),
+ fManuList(0x0),
+ fChambers(0x0)
+{
+ /// ctor
+}
+
+//_____________________________________________________________________________
+AliMUON2DStoreValidator::~AliMUON2DStoreValidator()
+{
+ /// dtor
+ delete fManuList;
+ delete fChambers;
+}
+
+//_____________________________________________________________________________
+AliMUONCheckItem*
+AliMUON2DStoreValidator::GetChamber(Int_t chamberID)
+{
+ /// Return (and create if not present) the given chamber
+ /// chamberID in 0..NCh()
+
+ if ( chamberID < 0 || chamberID >= AliMUONConstants::NCh() )
+ {
+ AliFatal(Form("Invalid chamber number %d",chamberID));
+ return 0x0;
+ }
+
+ if (!fChambers)
+ {
+ fChambers = new TObjArray(AliMUONConstants::NCh());
+ }
+
+ AliMUONCheckItem* chamber =
+ static_cast<AliMUONCheckItem*>(fChambers->At(chamberID));
+
+ if (!chamber)
+ {
+ chamber = new AliMUONCheckItem(chamberID,
+ AliMpDEManager::GetNofDEInChamber(chamberID),
+ "Chamber");
+ fChambers->AddAt(chamber,chamberID);
+ }
+ return chamber;
+}
+
+//_____________________________________________________________________________
+AliMUONCheckItem*
+AliMUON2DStoreValidator::GetDE(Int_t detElemId)
+{
+ /// Return (and create if not present) a given detection element
+
+ Int_t chamberID = AliMpDEManager::GetChamberId(detElemId);
+ AliMUONCheckItem* chamber = GetChamber(chamberID);
+ AliMUONCheckItem* de =
+ static_cast<AliMUONCheckItem*>(chamber->GetItem(detElemId));
+ if (!de)
+ {
+ AliDebug(3,Form("Did not find DE %4d into chamber %d, will create it",
+ detElemId,chamberID));
+ de = new AliMUONCheckItem(detElemId,
+ AliMpManuList::NumberOfManus(detElemId),
+ "Detection Element");
+ Bool_t ok = chamber->AddItem(detElemId,de);
+ if (!ok)
+ {
+ AliError(Form("Could not add DE %4d into chamber %2d",detElemId,chamberID));
+ }
+ }
+ return de;
+}
+
+//_____________________________________________________________________________
+AliMUONCheckItem*
+AliMUON2DStoreValidator::GetManu(Int_t detElemId, Int_t manuId)
+{
+ /// Return (and create) a given manu
+
+ AliMUONCheckItem* de = GetDE(detElemId);
+ AliMUONCheckItem* manu = static_cast<AliMUONCheckItem*>(de->GetItem(manuId));
+ if (!manu)
+ {
+ manu = new AliMUONCheckItem(manuId,AliMpManuList::NumberOfChannels(detElemId,manuId),"Manu");
+ Bool_t ok = de->AddItem(manuId,manu);
+ if (!ok)
+ {
+ AliError(Form("Could not add manu %4d into DE %4d",manuId,detElemId));
+ }
+
+ }
+ return manu;
+}
+
+//_____________________________________________________________________________
+void
+AliMUON2DStoreValidator::AddMissingChannel(Int_t detElemId,
+ Int_t manuId, Int_t manuChannel)
+{
+ /// Add one missing channel to the list of missing things
+
+ AliDebug(3,Form("DE %4d Manu %4d Channel %2d is missing",
+ detElemId,manuId,manuChannel));
+
+ AliMUONCheckItem* manu = GetManu(detElemId,manuId);
+ Bool_t ok = manu->AddItem(manuChannel,new TObjString(Form("%2d",manuChannel)));
+ if (!ok)
+ {
+ AliError(Form("Could not add channel %2d to manuId %4d in DE %4d",
+ manuChannel,manuId,detElemId));
+ }
+}
+
+//_____________________________________________________________________________
+void
+AliMUON2DStoreValidator::AddMissingManu(Int_t detElemId, Int_t manuId)
+{
+ /// Add one missing manu to the list of missing things
+
+ AliDebug(3,Form("DE %4d Manu %4d is completely missing",
+ detElemId,manuId));
+
+ Int_t n(AliMpManuList::NumberOfChannels(detElemId,manuId));
+
+ for ( Int_t i = 0; i < n; ++i )
+ {
+ AddMissingChannel(detElemId,manuId,i);
+ }
+}
+
+//_____________________________________________________________________________
+void
+AliMUON2DStoreValidator::ReportManu(AliMUONCheckItem& manu)
+{
+ /// Report list of missing channels from this manu
+
+ TObjString* channel(0x0);
+ AliMUONCheckItemIterator it(manu);
+
+ it.First();
+
+ while ( ( channel = static_cast<TObjString*>(it.Next()) ) )
+ {
+ cout << Form("\t\t\tChannel %s is missing",channel->GetString().Data()) << endl;
+ }
+
+}
+
+//_____________________________________________________________________________
+void
+AliMUON2DStoreValidator::ReportDE(AliMUONCheckItem& de)
+{
+ /// Report list of missing manus from this de
+ AliMUONCheckItem* manu(0x0);
+ AliMUONCheckItemIterator it(de);
+
+ cout << Form("\tDE %4d",de.GetID()) << endl;
+
+ it.First();
+
+ while ( ( manu = static_cast<AliMUONCheckItem*>(it.Next()) ) )
+ {
+ if ( manu->IsDead() )
+ {
+ cout << Form("\t\tManu %4d is missing",manu->GetID()) << endl;
+ }
+ else
+ {
+ ReportManu(*manu);
+ }
+ }
+}
+
+//_____________________________________________________________________________
+void
+AliMUON2DStoreValidator::ReportChamber(AliMUONCheckItem& chamber)
+{
+ /// Report list of missing de from this chamber
+
+ AliMUONCheckItem* de(0x0);
+ AliMUONCheckItemIterator it(chamber);
+
+ it.First();
+
+ while ( ( de = static_cast<AliMUONCheckItem*>(it.Next()) ) )
+ {
+ if ( de->IsDead() )
+ {
+ cout << Form("\tDE %4d is missing",de->GetID()) << endl;
+ }
+ else
+ {
+ ReportDE(*de);
+ }
+ }
+}
+
+//_____________________________________________________________________________
+void
+AliMUON2DStoreValidator::Report(const TObjArray& chambers)
+{
+ /// Reports what is missing, trying to be as concise as possible.
+
+ for ( Int_t iChamber = 0; iChamber <= chambers.GetLast(); ++iChamber )
+ {
+ AliMUONCheckItem* chamber = static_cast<AliMUONCheckItem*>(chambers.At(iChamber));
+ if ( chamber )
+ {
+ if ( chamber->IsDead() )
+ {
+ cout << Form("Chamber %2d is missing",iChamber) << endl;
+ }
+ else
+ {
+ ReportChamber(*chamber);
+ }
+ }
+ }
+}
+
+//_____________________________________________________________________________
+TObjArray*
+AliMUON2DStoreValidator::Validate(const AliMUONV2DStore& store,
+ Float_t invalidFloatValue)
+{
+ /// Validate the store.
+ /// The invalidFloatValue is used to decide if a store content value
+ /// is valid or not.
+
+ delete fChambers;
+ fChambers = 0x0;
+
+ if (!fManuList) fManuList = AliMpManuList::ManuList();
+
+ // Now checks if some full manus are missing
+ TIter next(fManuList);
+ AliMpIntPair* p;
+
+ while ( ( p = (AliMpIntPair*)next() ) )
+ {
+ Int_t detElemId = p->GetFirst();
+ Int_t manuId = p->GetSecond();
+ AliMUONVCalibParam* test =
+ static_cast<AliMUONVCalibParam*>(store.Get(detElemId,manuId));
+ if (!test)
+ {
+ // completely missing manu
+ AddMissingManu(detElemId,manuId);
+ }
+ else
+ {
+ // manu is there, check all its channels
+ for ( Int_t manuChannel = 0 ; manuChannel < test->Size(); ++manuChannel )
+ {
+ if ( AliMpManuList::DoesChannelExist(detElemId,manuId,manuChannel) &&
+ ( test->ValueAsFloat(manuChannel,0) == invalidFloatValue ||
+ test->ValueAsFloat(manuChannel,1) == invalidFloatValue ) )
+ {
+ AddMissingChannel(detElemId,manuId,manuChannel);
+ }
+ }
+ }
+ }
+ return fChambers;
+}
+
+
--- /dev/null
+#ifndef ALIMUON2DSTOREVALIDATOR_H
+#define ALIMUON2DSTOREVALIDATOR_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* See cxx source for full Copyright notice */
+
+// $Id$
+
+/// \ingroup shuttle
+/// \class AliMUON2DStoreValidator
+/// \brief Determine which channels, manus, DEs, stations are missing
+/// from a 2DStore.
+///
+/// \author Laurent Aphecetche
+
+#ifndef ROOT_TObject
+# include "TObject.h"
+#endif
+
+class AliMUONV2DStore;
+class TList;
+class TObjArray;
+class AliMUONCheckItem;
+
+class AliMUON2DStoreValidator : public TObject
+{
+public:
+ AliMUON2DStoreValidator();
+ virtual ~AliMUON2DStoreValidator();
+
+ TObjArray* Validate(const AliMUONV2DStore& store, Float_t invalidFloatValue);
+ void Report() const { Report(*fChambers); }
+
+ static void Report(const TObjArray& chambers);
+
+private:
+
+ AliMUON2DStoreValidator(const AliMUON2DStoreValidator&);
+ AliMUON2DStoreValidator& operator=(const AliMUON2DStoreValidator&);
+
+ void AddMissingChannel(Int_t detElemId, Int_t manuId, Int_t manuChannel);
+
+ void AddMissingManu(Int_t detElemId, Int_t manuId);
+
+ AliMUONCheckItem* GetChamber(Int_t chamberID);
+ AliMUONCheckItem* GetDE(Int_t detElemId);
+ AliMUONCheckItem* GetManu(Int_t detElemId, Int_t manuId);
+
+ static void ReportChamber(AliMUONCheckItem& chamber);
+ static void ReportDE(AliMUONCheckItem& de);
+ static void ReportManu(AliMUONCheckItem& manu);
+
+private:
+ TList* fManuList; //! List of (DE,manuID) pairs.
+ TObjArray* fChambers; //! Array of AliMUONCheckItem.
+
+ ClassDef(AliMUON2DStoreValidator,1) // Validator of 2DStore
+};
+
+#endif
--- /dev/null
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* *
+* Author: The ALICE Off-line Project. *
+* Contributors are mentioned in the code where appropriate. *
+* *
+* Permission to use, copy, modify and distribute this software and its *
+* documentation strictly for non-commercial purposes is hereby granted *
+* without fee, provided that the above copyright notice appears in all *
+* copies and that both the copyright notice and this permission notice *
+* appear in the supporting documentation. The authors make no claims *
+* about the suitability of this software for any purpose. It is *
+* provided "as is" without express or implied warranty. *
+**************************************************************************/
+
+// $Id$
+
+#include "AliMUONCheckItem.h"
+
+#include "AliLog.h"
+#include "AliMpExMap.h"
+#include "Riostream.h"
+#include "AliMUONCheckItemIterator.h"
+
+/// \class AliMUONCheckItem
+///
+/// A structure used to gather information at different levels (ch,manu,de,chamber)
+///
+/// Used by AliMUON2DStoreValidator to present results in a concise way
+///
+///
+/// \author Laurent Aphecetche
+
+/// \cond CLASSIMP
+ClassImp(AliMUONCheckItem)
+/// \endcond
+
+//_____________________________________________________________________________
+AliMUONCheckItem::AliMUONCheckItem(Int_t id, Int_t maxNumber, const char* name) :
+TNamed(name,name),
+fID(id),
+fDead(-1),
+fMaximum(maxNumber),
+fMissing(new AliMpExMap(kTRUE))
+{
+ /// ctor. id is the number of that item, maxNumber is the maximum number
+ /// of sub-item it can contains, and name is a label, e.g. de, chamber, manu.
+ /// Note that name="manu" has a special influence on the IsDead() method.
+
+ fMissing->SetSize(fMaximum);
+ AliDebug(1,Form("ID %d maxNumber %d name %s",id,maxNumber,name));
+}
+
+//_____________________________________________________________________________
+AliMUONCheckItem::~AliMUONCheckItem()
+{
+ /// dtor
+ delete fMissing;
+}
+
+//_____________________________________________________________________________
+Bool_t AliMUONCheckItem::AddItem(Int_t id, TObject* item)
+{
+ /// Add an item, if possible.
+
+ if ( IsFull() )
+ {
+ AliError("I'm already full!");
+ return kFALSE;
+ }
+
+ TObject* test = GetItem(id);
+ if (test)
+ {
+ AliError(Form("id %d is already there !",id));
+ return kFALSE;
+ }
+ else
+ {
+ fMissing->Add(id,item);
+ fDead=-1;
+ }
+ return kTRUE;
+}
+
+//_____________________________________________________________________________
+void
+AliMUONCheckItem::ComputeDead() const
+{
+ /// Decide whether this item is completely dead, which is determined by
+ /// the fact that all its sub-items are dead, or for name="manu", by
+ /// the fact that all channels are missing, i.e. IsFull()==kTRUE
+
+ TString name(GetName());
+ name.ToLower();
+
+ if ( name.Contains("manu") )
+ {
+ if ( IsFull() )
+ {
+ fDead=1;
+ }
+ else
+ {
+ fDead=0;
+ }
+ }
+ else
+ {
+ AliMUONCheckItemIterator it(*this);
+ AliMUONCheckItem* item;
+ it.First();
+ Int_t ndead(0);
+ fDead=0;
+ while ( ( item = dynamic_cast<AliMUONCheckItem*>(it.Next()) ) )
+ {
+ if ( item->IsDead() ) ++ndead;
+ }
+ if ( ndead == fMaximum ) fDead = 1;
+ }
+}
+
+//_____________________________________________________________________________
+TObject*
+AliMUONCheckItem::GetItem(Int_t id) const
+{
+ /// Return item of a given id
+ return fMissing->GetValue(id);
+}
+
+//_____________________________________________________________________________
+Bool_t
+AliMUONCheckItem::IsDead() const
+{
+ /// Return (and compute it first if not done already) dead status
+ if ( fDead == -1 )
+ {
+ ComputeDead();
+ }
+ return (fDead==1);
+}
+
+//_____________________________________________________________________________
+Bool_t
+AliMUONCheckItem::IsFull() const
+{
+ /// Whether we have as many sub-items as possible
+ return (fMissing->GetSize() == fMaximum);
+}
+
+//_____________________________________________________________________________
+void
+AliMUONCheckItem::Print(Option_t* opt) const
+{
+ /// output to screen
+ cout << Form("<AliMUONCheckItem> %s ID %d has %d items over %d max. Dead %d",
+ GetName(),fID,fMissing->GetSize(),fMaximum,IsDead()) << endl;
+ TString sopt(opt);
+ sopt.ToLower();
+ if (sopt.Contains("all") )
+ {
+ TObject* object(0x0);
+
+ AliMUONCheckItemIterator it(*this);
+
+ it.First();
+
+ while ( ( object = it.Next() ) )
+ {
+ object->Print(opt);
+ }
+ }
+}
--- /dev/null
+#ifndef ALIMUONCHECKITEM_H
+#define ALIMUONCHECKITEM_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* See cxx source for full Copyright notice */
+
+// $Id$
+
+/// \ingroup shuttle
+/// \class AliMUONCheckItem
+/// \brief A structure used to gather information at different levels (ch,manu,de,chamber)
+///
+/// \author Laurent Aphecetche
+
+#ifndef ROOT_TNamed
+# include "TNamed.h"
+#endif
+
+class AliMpExMap;
+class TExMapIter;
+class AliMUONCheckItemIterator;
+
+class AliMUONCheckItem : public TNamed
+{
+ friend class AliMUONCheckItemIterator;
+
+public:
+
+ AliMUONCheckItem(Int_t id, Int_t maxNumber, const char* name);
+ virtual ~AliMUONCheckItem();
+
+ Int_t GetID() const { return fID; }
+
+ TObject* GetItem(Int_t id) const;
+ Bool_t AddItem(Int_t id, TObject* item);
+
+ Bool_t IsFull() const;
+ Bool_t IsDead() const;
+
+ void Print(Option_t* opt="") const;
+
+private:
+ AliMUONCheckItem(const AliMUONCheckItem&);
+ AliMUONCheckItem& operator=(const AliMUONCheckItem&);
+ void ComputeDead() const;
+
+private:
+ Int_t fID; //!< identifier of this item
+ mutable Int_t fDead; //!< whether this object is completely dead
+ Int_t fMaximum; //!< maximum number of sub-items possible within this item
+ AliMpExMap* fMissing; //!< pointers to the sub-items
+
+ ClassDef(AliMUONCheckItem,1) // A composite object
+};
+
+#endif
--- /dev/null
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* *
+* Author: The ALICE Off-line Project. *
+* Contributors are mentioned in the code where appropriate. *
+* *
+* Permission to use, copy, modify and distribute this software and its *
+* documentation strictly for non-commercial purposes is hereby granted *
+* without fee, provided that the above copyright notice appears in all *
+* copies and that both the copyright notice and this permission notice *
+* appear in the supporting documentation. The authors make no claims *
+* about the suitability of this software for any purpose. It is *
+* provided "as is" without express or implied warranty. *
+**************************************************************************/
+
+// $Id$
+
+#include "AliMUONCheckItemIterator.h"
+#include "TExMap.h"
+#include "AliMpExMap.h"
+#include "AliMUONCheckItem.h"
+
+/// \class AliMUONCheckItemIterator
+///
+/// Iterator on AliMUONCheckItem objects
+///
+///
+/// \author Laurent Aphecetche
+
+/// \cond CLASSIMP
+ClassImp(AliMUONCheckItemIterator)
+/// \endcond
+
+//_____________________________________________________________________________
+AliMUONCheckItemIterator::AliMUONCheckItemIterator() : TObject(), fIter(0x0)
+{
+ /// default ctor
+}
+
+//_____________________________________________________________________________
+AliMUONCheckItemIterator::AliMUONCheckItemIterator(const AliMUONCheckItem& item)
+: TObject(),
+fIter(0x0)
+{
+ /// ctor
+ AliMpExMap* m = item.fMissing;
+ fIter = new TExMapIter(m->GetIterator());
+}
+
+//_____________________________________________________________________________
+AliMUONCheckItemIterator::~AliMUONCheckItemIterator()
+{
+ /// dtor
+ delete fIter;
+}
+
+//_____________________________________________________________________________
+void
+AliMUONCheckItemIterator::First()
+{
+ /// Rewind the iterator
+ if ( fIter) fIter->Reset();
+}
+
+//_____________________________________________________________________________
+TObject*
+AliMUONCheckItemIterator::Next()
+{
+ /// Advance one object. Return 0 if ended.
+ if (!fIter) return 0x0;
+ Long_t key, value;
+ Bool_t ok = fIter->Next(key,value);
+ if (ok)
+ {
+ return reinterpret_cast<TObject*>(value);
+ }
+ else
+ {
+ return 0x0;
+ }
+}
--- /dev/null
+#ifndef ALIMUONCHECKITEMITERATOR_H
+#define ALIMUONCHECKITEMITERATOR_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* See cxx source for full Copyright notice */
+
+// $Id$
+
+/// \ingroup shuttle
+/// \class AliMUONCheckItemIterator
+/// \brief Iterator on CheckItem
+///
+/// \author Laurent Aphecetche
+
+#ifndef ROOT_TObject
+# include "TObject.h"
+#endif
+
+class AliMUONCheckItem;
+class TExMapIter;
+
+class AliMUONCheckItemIterator : public TObject
+{
+public:
+ AliMUONCheckItemIterator();
+ AliMUONCheckItemIterator(const AliMUONCheckItem& object);
+ virtual ~AliMUONCheckItemIterator();
+
+ void First();
+ TObject* Next();
+
+private:
+ AliMUONCheckItemIterator(const AliMUONCheckItemIterator&);
+ AliMUONCheckItemIterator& operator=(const AliMUONCheckItemIterator&);
+
+private:
+ TExMapIter* fIter; //!< the actual iterator doing the job
+
+ ClassDef(AliMUONCheckItemIterator,1) // Iterator for AliMUONCheckItem objects
+};
+
+#endif
--- /dev/null
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* *
+* Author: The ALICE Off-line Project. *
+* Contributors are mentioned in the code where appropriate. *
+* *
+* Permission to use, copy, modify and distribute this software and its *
+* documentation strictly for non-commercial purposes is hereby granted *
+* without fee, provided that the above copyright notice appears in all *
+* copies and that both the copyright notice and this permission notice *
+* appear in the supporting documentation. The authors make no claims *
+* about the suitability of this software for any purpose. It is *
+* provided "as is" without express or implied warranty. *
+**************************************************************************/
+
+// $Id$
+
+#include "AliMUONObjectPair.h"
+
+/// \class AliMUONObjectPair
+///
+/// The equivalent of a std::pair<TObject*,TObject*> ;-)
+///
+/// What else can be said ? That if we'd been using STL, that class
+/// would not be there, thus saving some octets ? No comment.
+///
+/// Well, in fact, there *is* a difference wrt to std::pair : here
+/// we decide on the ownership of the first and/or second object...
+///
+/// \author Laurent Aphecetche
+
+/// \cond CLASSIMP
+ClassImp(AliMUONObjectPair)
+/// \endcond
+
+//_____________________________________________________________________________
+AliMUONObjectPair::AliMUONObjectPair()
+: TObject(),
+fFirst(0x0),
+fSecond(0x0),
+fIsOwnerOfFirst(kTRUE),
+fIsOwnerOfSecond(kTRUE)
+{
+ /// ctor
+}
+
+//_____________________________________________________________________________
+AliMUONObjectPair::AliMUONObjectPair(TObject* first,
+ TObject* second,
+ Bool_t isOwnerOfFirst,
+ Bool_t isOwnerOfSecond)
+: TObject(),
+fFirst(first),
+fSecond(second),
+fIsOwnerOfFirst(isOwnerOfFirst),
+fIsOwnerOfSecond(isOwnerOfSecond)
+{
+ /// ctor
+}
+
+//_____________________________________________________________________________
+AliMUONObjectPair::AliMUONObjectPair(const AliMUONObjectPair& other)
+: TObject(other),
+fFirst(0x0),
+fSecond(0x0),
+fIsOwnerOfFirst(kTRUE),
+fIsOwnerOfSecond(kTRUE)
+{
+ /// copy ctor
+ other.Copy(*this);
+}
+
+//_____________________________________________________________________________
+AliMUONObjectPair&
+AliMUONObjectPair::operator=(const AliMUONObjectPair& other)
+{
+ /// assignement operator
+ AliMUONObjectPair pair(other);
+ pair.Copy(*this);
+ return *this;
+}
+
+//_____________________________________________________________________________
+AliMUONObjectPair::~AliMUONObjectPair()
+{
+ /// dtor
+ if ( fIsOwnerOfFirst ) delete fFirst;
+ if ( fIsOwnerOfSecond ) delete fSecond;
+}
+
+//_____________________________________________________________________________
+void
+AliMUONObjectPair::Copy(TObject& other) const
+{
+ /// Copy this to other (used by copy ctor and operator=)
+
+ TObject::Copy(other);
+ AliMUONObjectPair& pair = (AliMUONObjectPair&)(other);
+ pair.fIsOwnerOfFirst = fIsOwnerOfFirst;
+ pair.fIsOwnerOfSecond = fIsOwnerOfSecond;
+ if ( fIsOwnerOfFirst )
+ {
+ pair.fFirst = fFirst->Clone();
+ }
+ else
+ {
+ pair.fFirst = fFirst;
+ }
+ if ( fIsOwnerOfSecond )
+ {
+ pair.fSecond = fSecond->Clone();
+ }
+ else
+ {
+ pair.fSecond = fSecond;
+ }
+}
--- /dev/null
+#ifndef ALIMUONOBJECTPAIR_H
+#define ALIMUONOBJECTPAIR_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* See cxx source for full Copyright notice */
+
+// $Id$
+
+/// \ingroup base
+/// \class AliMUONObjectPair
+/// \brief The equivalent of a std::pair<TObject*,TObject*> ;-)
+///
+// Author Laurent Aphecetche
+
+#ifndef ROOT_TObject
+# include "TObject.h"
+#endif
+
+class AliMUONObjectPair : public TObject
+{
+public:
+ AliMUONObjectPair();
+ AliMUONObjectPair(TObject* first,
+ TObject* second,
+ Bool_t isOwnerOfFirst=kTRUE,
+ Bool_t isOwnerOfSecond=kFALSE);
+ AliMUONObjectPair(const AliMUONObjectPair& other);
+ AliMUONObjectPair& operator=(const AliMUONObjectPair& other);
+
+ virtual ~AliMUONObjectPair();
+
+ TObject* First() const { return fFirst; }
+ TObject* Second() const { return fSecond; }
+
+ TObject* Key() const { return fFirst; }
+ TObject* Value() const { return fSecond; }
+
+ virtual void Copy(TObject& other) const;
+
+private:
+
+ TObject* fFirst; ///< first element of the pair
+ TObject* fSecond; ///< second element of the pair
+ Bool_t fIsOwnerOfFirst; ///< whether we own the first element
+ Bool_t fIsOwnerOfSecond; ///<whether we own the second element
+
+ ClassDef(AliMUONObjectPair,1) // A pair of TObject*
+};
+
+#endif
--- /dev/null
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* *
+* Author: The ALICE Off-line Project. *
+* Contributors are mentioned in the code where appropriate. *
+* *
+* Permission to use, copy, modify and distribute this software and its *
+* documentation strictly for non-commercial purposes is hereby granted *
+* without fee, provided that the above copyright notice appears in all *
+* copies and that both the copyright notice and this permission notice *
+* appear in the supporting documentation. The authors make no claims *
+* about the suitability of this software for any purpose. It is *
+* provided "as is" without express or implied warranty. *
+**************************************************************************/
+
+// $Id$
+
+#include "AliMUONPedestalEventGenerator.h"
+
+#include "AliDAQ.h"
+#include "AliHeader.h"
+#include "AliLog.h"
+#include "AliMUONCalibrationData.h"
+#include "AliMUONData.h"
+#include "AliMUONDigit.h"
+#include "AliMUONRawWriter.h"
+#include "AliMUONVCalibParam.h"
+#include "AliMpIntPair.h"
+#include "AliMpManuList.h"
+#include "AliRunLoader.h"
+
+#include "TClonesArray.h"
+#include "TRandom.h"
+#include "TStopwatch.h"
+#include "TSystem.h"
+#include "TMath.h"
+
+///
+/// \class AliMUONPedestalEventGenerator
+///
+/// Generate simulated pedestal events for MUON TRK, to be able to e.g. test
+/// online calibration routines.
+///
+/// The pedestals themselves are taken from the CDB. What we get from the CDB
+/// is, per channel, the mean and the sigma of the pedestal. We then use
+/// those informations to randomly get the pedestals for each channel, for
+/// each event (picking in a gaus(mean,sigma)).
+///
+/// Output can be just digits, or digits + raw (ddl), or digits + raw (ddl)
+/// + raw (date files, one per LDC), depending of ctor and MakeDDL() method.
+///
+/// \author L. Aphecetche
+///
+
+/// \cond CLASSIMP
+ClassImp(AliMUONPedestalEventGenerator)
+/// \endcond
+
+Int_t AliMUONPedestalEventGenerator::fgCounter(0);
+
+//_____________________________________________________________________________
+AliMUONPedestalEventGenerator::AliMUONPedestalEventGenerator(Int_t runNumber,
+ Int_t nevents,
+ const char* filename)
+: TTask("AliMUONPedestalEventGenerator","Generate fake pedestal events"),
+fManuList(AliMpManuList::ManuList()),
+fCalibrationData(new AliMUONCalibrationData(runNumber)),
+fDateFileName(filename),
+fGAliceFileName("galice.root"),
+fMakeDDL(kTRUE)
+{
+ /// Will generate pedestals according to (mean,sigma)s found in CDB
+ /// for run runNumber.
+ /// Will generate nevents events
+ /// If filename is != "", it will be the basename of the output LDC files
+ ///
+ if (!gSystem->IsAbsoluteFileName(fGAliceFileName))
+ {
+ char* absFileName = gSystem->ConcatFileName(gSystem->WorkingDirectory(),
+ fGAliceFileName);
+ fGAliceFileName = absFileName;
+ delete[] absFileName;
+ }
+
+ AliRunLoader* runLoader = LoadRun("recreate");
+
+ runLoader->SetNumberOfEventsPerFile(nevents);
+
+ if (!runLoader)
+ {
+ AliError("Could not create RunLoader");
+ return;
+ }
+
+ AliConfig::Instance()
+ ->CreateDetectorFolders(runLoader->GetEventFolder(),
+ "MUON", "MUON");
+
+ AliLoader* loader = new AliLoader("MUON",runLoader->GetEventFolder());
+
+ runLoader->AddLoader(loader);
+
+ // Initialize event headers.
+ runLoader->MakeTree("E");
+ for ( Int_t iEvent = 0; iEvent < nevents; ++iEvent )
+ {
+ runLoader->SetEventNumber(iEvent);
+ runLoader->GetHeader()->Reset(runNumber,iEvent);
+ runLoader->TreeE()->Fill();
+ }
+ runLoader->WriteHeader("OVERWRITE");
+ runLoader->CdGAFile();
+ runLoader->Write(0, TObject::kOverwrite);
+
+ assert(runLoader->GetNumberOfEvents()==nevents);
+ assert(runLoader->GetHeader()->GetRun()==runNumber);
+
+ delete runLoader;
+}
+
+
+//_____________________________________________________________________________
+AliMUONPedestalEventGenerator::~AliMUONPedestalEventGenerator()
+{
+ /// dtor
+ delete fManuList;
+ delete fCalibrationData;
+ AliInfo(Form("make a digit counter %d",fgCounter));
+}
+
+//_____________________________________________________________________________
+Bool_t
+AliMUONPedestalEventGenerator::ConvertRawFilesToDate()
+{
+ /// convert raw data DDL files to DATE files with the program "dateStream".
+ /// we make one file per LDC
+
+ const Int_t kIDet = AliDAQ::DetectorID("MUONTRK");
+
+ const Int_t kNLDCs = TMath::CeilNint(AliDAQ::NumberOfLdcs(kIDet));
+
+ char* path = gSystem->Which(gSystem->Getenv("PATH"), "dateStream");
+ if (!path)
+ {
+ AliError("the program dateStream was not found");
+ return kFALSE;
+ }
+
+ delete[] path;
+
+ AliRunLoader* runLoader = LoadRun("read");
+ if (!runLoader) return kFALSE;
+
+ AliInfo(Form("converting raw data DDL files to DATE files %s", fDateFileName.Data()));
+ FILE** pipe = new FILE*[kNLDCs];
+
+ for ( Int_t iFile = 0; iFile < kNLDCs; ++iFile)
+ {
+ char command[256];
+ // Note the option -s. It is used in order to avoid
+ // the generation of SOR/EOR events.
+ sprintf(command, "dateStream -s -D -o %s.LDC%d -# %d -C",
+ fDateFileName.Data(), iFile, runLoader->GetNumberOfEvents());
+ pipe[iFile] = gSystem->OpenPipe(command, "w");
+ }
+
+ for (Int_t iEvent = 0; iEvent < runLoader->GetNumberOfEvents(); ++iEvent)
+ {
+ Float_t ldc = 0;
+ Int_t prevLDC = -1;
+
+ for (Int_t iDDL = 0; iDDL < AliDAQ::NumberOfDdls(kIDet); ++iDDL)
+ {
+ Int_t ddlID = AliDAQ::DdlID(kIDet,iDDL);
+ Int_t ldcID = Int_t(ldc + 0.0001);
+ ldc += AliDAQ::NumberOfLdcs(kIDet) / AliDAQ::NumberOfDdls(kIDet);
+
+ char rawFileName[256];
+ sprintf(rawFileName, "raw%d/%s",
+ iEvent, AliDAQ::DdlFileName(kIDet,iDDL));
+
+ // check existence and size of raw data file
+ FILE* file = fopen(rawFileName, "rb");
+ if (!file) continue;
+ fseek(file, 0, SEEK_END);
+ unsigned long size = ftell(file);
+ fclose(file);
+ if (!size) continue;
+
+ if (ldcID != prevLDC) {
+ fprintf(pipe[ldcID], " LDC Id %d\n", ldcID);
+ prevLDC = ldcID;
+ }
+ fprintf(pipe[ldcID], " Equipment Id %d Payload %s\n", ddlID, rawFileName);
+ }
+ }
+
+ Int_t result(0);
+
+ for ( Int_t iFile = 0; iFile < kNLDCs; ++iFile)
+ {
+ result += gSystem->ClosePipe(pipe[iFile]);
+ }
+
+ delete [] pipe;
+ delete runLoader;
+ return (result == 0);
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPedestalEventGenerator::Exec(Option_t*)
+{
+ /// Main steering method
+
+ TStopwatch timer;
+ timer.Start(kTRUE);
+
+ TStopwatch writeTimer;
+ writeTimer.Start(kTRUE); writeTimer.Stop();
+ TStopwatch fillTimer;
+ fillTimer.Start(kTRUE); fillTimer.Stop();
+ TStopwatch resetTimer;
+ resetTimer.Start(kTRUE); resetTimer.Stop();
+ TStopwatch getEventTimer;
+ getEventTimer.Start(kTRUE); getEventTimer.Stop();
+ TStopwatch branchTimer;
+ branchTimer.Start(kTRUE); branchTimer.Stop();
+ TStopwatch generateDigitsTimer;
+ generateDigitsTimer.Start(kTRUE); generateDigitsTimer.Stop();
+ TStopwatch digits2RawTimer;
+ digits2RawTimer.Start(kTRUE); digits2RawTimer.Stop();
+ TStopwatch convertRawFilesToDateTimer;
+ convertRawFilesToDateTimer.Start(kTRUE); convertRawFilesToDateTimer.Stop();
+ TStopwatch getTimer;
+
+ getTimer.Start(kTRUE);
+ AliMUONData* data = GetDataAccess("update");
+ AliRunLoader* runLoader = data->GetLoader()->GetRunLoader();
+ getTimer.Stop();
+
+ for ( Int_t i = 0; i < runLoader->GetNumberOfEvents(); ++i )
+ {
+ getEventTimer.Start(kFALSE);
+ runLoader->GetEvent(i);
+ getEventTimer.Stop();
+
+ branchTimer.Start(kFALSE);
+ if ( data->TreeD() == 0x0 )
+ {
+ AliDebug(1,"Calling MakeDigitsContainer");
+ data->GetLoader()->MakeDigitsContainer();
+ }
+ data->MakeBranch("D,GLT");
+ data->SetTreeAddress("D,GLT");
+ branchTimer.Stop();
+
+ generateDigitsTimer.Start(kFALSE);
+ GenerateDigits(data);
+ generateDigitsTimer.Stop();
+
+ fillTimer.Start(kTRUE);
+ // Fill the output treeD
+ data->Fill("D,GLT");
+ fillTimer.Stop();
+
+ // Write to the output tree(D).
+ // Please note that as GlobalTrigger, LocalTrigger and Digits are in the same
+ // tree (=TreeD) in different branches, this WriteDigits in fact writes all of
+ // the 3 branches.
+
+ writeTimer.Start(kFALSE);
+ data->GetLoader()->WriteDigits("OVERWRITE");
+ writeTimer.Stop();
+
+ // Finally, we clean up after ourselves.
+ resetTimer.Start(kTRUE);
+ data->ResetDigits();
+ data->ResetTrigger();
+ data->GetLoader()->UnloadDigits();
+ resetTimer.Stop();
+ }
+
+ TStopwatch endTimer;
+ endTimer.Start(kTRUE);
+ runLoader->WriteRunLoader("OVERWRITE");
+ delete data;
+ delete runLoader;
+ endTimer.Stop();
+
+ if ( fMakeDDL )
+ {
+ // Now convert the digits.root file(s) to DDL files
+ digits2RawTimer.Start(kFALSE);
+ Digits2Raw();
+ digits2RawTimer.Stop();
+ }
+
+ // Finally, if instructed to do so, convert DDL files to DATE file(s)
+ if ( fMakeDDL && fDateFileName.Length() > 0 )
+ {
+ convertRawFilesToDateTimer.Start(kFALSE);
+ AliDebug(1,"Converting to DATE file(s)");
+
+ Bool_t dateOutput = ConvertRawFilesToDate();
+ convertRawFilesToDateTimer.Stop();
+ if (!dateOutput)
+ {
+ AliError("DATE output failed. Aborting.");
+ return;
+ }
+ }
+
+ AliInfo(Form("Execution time Exec : R:%.2fs C:%.2fs",
+ timer.RealTime(),timer.CpuTime()));
+
+ AliInfo(Form(" Execution time branch : R:%.2fs C:%.2fs",
+ branchTimer.RealTime(),branchTimer.CpuTime()));
+ AliInfo(Form(" Execution time getEvent : R:%.2fs C:%.2fs",
+ getEventTimer.RealTime(),getEventTimer.CpuTime()));
+ AliInfo(Form(" Execution time fill digits : R:%.2fs C:%.2fs",
+ fillTimer.RealTime(),fillTimer.CpuTime()));
+ AliInfo(Form(" Execution time write digits : R:%.2fs C:%.2fs",
+ writeTimer.RealTime(),writeTimer.CpuTime()));
+ AliInfo(Form(" Execution time reset digits : R:%.2fs C:%.2fs",
+ resetTimer.RealTime(),resetTimer.CpuTime()));
+ AliInfo(Form(" Execution time for GenerateDigits : R:%.2fs C:%.2fs",
+ generateDigitsTimer.RealTime(),generateDigitsTimer.CpuTime()));
+ AliInfo(Form(" Execution time for Digits2Raw : R:%.2fs C:%.2fs",
+ digits2RawTimer.RealTime(),digits2RawTimer.CpuTime()));
+ AliInfo(Form(" Execution time for ConvertRawFilesToDate : R:%.2fs C:%.2fs",
+ convertRawFilesToDateTimer.RealTime(),convertRawFilesToDateTimer.CpuTime()));
+ AliInfo(Form(" Execution time for get : R:%.2fs C:%.2fs",
+ getTimer.RealTime(),getTimer.CpuTime()));
+ AliInfo(Form(" Execution time for end : R:%.2fs C:%.2fs",
+ endTimer.RealTime(),endTimer.CpuTime()));
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPedestalEventGenerator::Digits2Raw()
+{
+ /// Converts digits (from MUON.Digits.root file) to Raw DDL ascii files.
+
+ AliMUONData* data = GetDataAccess("read");
+ AliRunLoader* runLoader = data->GetLoader()->GetRunLoader();
+ AliDebug(1,Form("runLoader=%p",runLoader));
+
+ AliMUONRawWriter rawWriter(data);
+
+ // Generate RAW data from the digits
+ // Be carefull to create&change to the correct directory first...
+
+ TString baseDir = gSystem->WorkingDirectory();
+
+ for ( Int_t i = 0; i < runLoader->GetNumberOfEvents(); ++i )
+ {
+ runLoader->GetEvent(i);
+
+ AliDebug(1,Form("processing event %d", i));
+
+ char dirName[256];
+ sprintf(dirName, "raw%d", i);
+ gSystem->MakeDirectory(dirName);
+ if (!gSystem->ChangeDirectory(dirName))
+ {
+ AliError(Form("couldn't change to directory %s", dirName));
+ return;
+ }
+
+ rawWriter.Digits2Raw();
+
+ gSystem->ChangeDirectory(baseDir);
+ }
+
+ delete data;
+ delete runLoader;
+
+ AliDebug(1,Form("DDL files written successfully"));
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPedestalEventGenerator::GenerateDigits(AliMUONData* data)
+{
+ /// Generate digits (where ADC is set to pedestal value) for all MUON TRK
+ /// and for 1 event.
+
+ TIter next(fManuList);
+ AliMpIntPair* p;
+ Int_t ngenerated(0);
+
+ while ( ( p = static_cast<AliMpIntPair*>(next())) )
+ {
+ Int_t detElemId = p->GetFirst();
+
+ Int_t chamber = detElemId/100-1;
+
+ TClonesArray* pdigits = data->Digits(chamber);
+ if (!pdigits)
+ {
+ AliError(Form("No digits for chamber %d",1));
+ continue;
+ }
+ TClonesArray& digits = *pdigits;
+
+ Int_t manuId = p->GetSecond();
+
+ AliMUONVCalibParam* pedestals = fCalibrationData->Pedestals(detElemId,manuId);
+ if (!pedestals)
+ {
+ AliError(Form("Could not find pedestals for (DE,MANU)=(%d,%d)",detElemId,
+ manuId));
+ return;
+ }
+ for ( Int_t manuChannel = 0; manuChannel < pedestals->Size(); ++manuChannel )
+ {
+ Float_t mean = pedestals->ValueAsFloat(manuChannel,0);
+ if (mean == AliMUONVCalibParam::InvalidFloatValue())
+ {
+ // This is a poor's man way of knowing if that channel really exists.
+ // Better and safer way (but much slower too) would be to check pad existence
+ // using AliMpVSegmentation::PadByLocation(AliMpIntPair(manuId,manuChannel))
+ continue;
+ }
+ else
+ {
+ Float_t sigma = pedestals->ValueAsFloat(manuChannel,1);
+ AliMUONDigit d;
+ Float_t ped = gRandom->Gaus(mean,sigma);
+ Int_t pedADC = TMath::FloorNint(ped);
+ d.SetElectronics(manuId, manuChannel);
+ d.SetADC(pedADC);
+ d.SetSignal(ped);
+ d.SetDetElemId(detElemId);
+ // we do not set the remaining parts of the digit, as in principle
+ // this is all we need : manuId, manuChannel and ADC, as far as
+ // real data is concerned.
+ new (digits[digits.GetLast()+1]) AliMUONDigit(d);
+ ++fgCounter;
+ ++ngenerated;
+ }
+ }
+ }
+ AliDebug(1,Form("ngenerated=%d",ngenerated));
+}
+
+//_____________________________________________________________________________
+AliMUONData*
+AliMUONPedestalEventGenerator::GetDataAccess(const char* mode)
+{
+ /// Get the pointer to AliMUONData object
+ AliRunLoader* runLoader = LoadRun(mode);
+ if (!runLoader)
+ {
+ AliError("Could not get RunLoader");
+ return 0x0;
+ }
+ AliLoader* loader = static_cast<AliLoader*>(runLoader->GetLoader("MUONLoader"));
+ if (!loader)
+ {
+ AliError("Could not get MuonLoader");
+ return 0x0;
+ }
+
+ return new AliMUONData(loader,"MUON","MUONData");
+}
+
+//_____________________________________________________________________________
+AliRunLoader*
+AliMUONPedestalEventGenerator::LoadRun(const char* mode)
+{
+ /// Get access to AliRunLoader object
+ while (AliRunLoader::GetRunLoader())
+ {
+ AliDebug(1,Form("Deleting AliRunLoader %p",AliRunLoader::GetRunLoader()));
+ delete AliRunLoader::GetRunLoader();
+ }
+
+ AliRunLoader* runLoader =
+ AliRunLoader::Open(fGAliceFileName,AliConfig::GetDefaultEventFolderName(),
+ mode);
+
+ AliDebug(1,Form("AliRunLoader(%s)=%p",mode,runLoader));
+
+ if (!runLoader)
+ {
+ AliError("No run loader found in file galice.root");
+ }
+ return runLoader;
+}
--- /dev/null
+#ifndef ALIMUONPEDESTALEVENTGENERATOR_H
+#define ALIMUONPEDESTALEVENTGENERATOR_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* See cxx source for full Copyright notice */
+
+// $Id$
+
+/// \ingroup shuttle
+/// \class AliMUONPedestalEventGenerator
+/// \brief Generate pedestal events (only for tracker).
+///
+/// \author Laurent Aphecetche
+
+#ifndef ROOT_TTask
+# include "TTask.h"
+#endif
+#ifndef ROOT_TString
+# include "TString.h"
+#endif
+
+class AliMUONCalibrationData;
+class AliMUONData;
+class TList;
+class AliRunLoader;
+
+class AliMUONPedestalEventGenerator : public TTask
+{
+public:
+ AliMUONPedestalEventGenerator(Int_t runNumber, Int_t nevents, const char* dateFileName);
+ virtual ~AliMUONPedestalEventGenerator();
+
+ void Exec(Option_t* option);
+
+ void MakeDDL(Bool_t value) { fMakeDDL = value; }
+
+private:
+ AliMUONPedestalEventGenerator(const AliMUONPedestalEventGenerator&);
+ AliMUONPedestalEventGenerator& operator=(const AliMUONPedestalEventGenerator&);
+ Bool_t ConvertRawFilesToDate();
+ void GenerateDigits(AliMUONData* data);
+ AliMUONData* GetDataAccess(const char* mode);
+ AliRunLoader* LoadRun(const char* mode);
+ void Digits2Raw();
+
+private:
+ TList* fManuList; //! list of (de,manu) pairs
+ AliMUONCalibrationData* fCalibrationData; //! access to pedestal CDB
+ TString fDateFileName; //! basefilename of the DATE output file
+ TString fGAliceFileName; //! absolute path to galice.root file
+ Bool_t fMakeDDL; //! whether to generate DDL ascii files or not
+ static Int_t fgCounter; //!
+
+ ClassDef(AliMUONPedestalEventGenerator,1) // Random generator of pedestal events for MUON TRK
+};
+
+#endif
--- /dev/null
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* *
+* Author: The ALICE Off-line Project. *
+* Contributors are mentioned in the code where appropriate. *
+* *
+* Permission to use, copy, modify and distribute this software and its *
+* documentation strictly for non-commercial purposes is hereby granted *
+* without fee, provided that the above copyright notice appears in all *
+* copies and that both the copyright notice and this permission notice *
+* appear in the supporting documentation. The authors make no claims *
+* about the suitability of this software for any purpose. It is *
+* provided "as is" without express or implied warranty. *
+**************************************************************************/
+
+// $Id$
+
+#include "AliMUONPedestalSubprocessor.h"
+
+#include "AliCDBMetaData.h"
+#include "AliLog.h"
+#include "AliMUON2DMap.h"
+#include "AliMUON2DStoreValidator.h"
+#include "AliMUONCalibParam2F.h"
+#include "Riostream.h"
+#include "TObjString.h"
+#include "TSystem.h"
+#include <sstream>
+#include "AliMUONVDataIterator.h"
+#include "AliMUONConstants.h"
+#include "AliMUONObjectPair.h"
+#include "AliMpBusPatch.h"
+#include "AliMUONPreprocessor.h"
+
+///
+/// \class AliMUONPedestalSubprocessor
+///
+/// Implementation of AliMUONVSubprocessor class to deal with MUON TRK pedestals.
+///
+/// Pedestals are read in from an ascii file, with the format : \n
+///---------------------------------------------------------------------------\n
+/// BUS_PATCH MANU_ADDR CHANNEL MEAN SIGMA \n
+///---------------------------------------------------------------------------\n
+///
+/// \author L. Aphecetche
+///
+
+/// \cond CLASSIMP
+ClassImp(AliMUONPedestalSubprocessor)
+/// \endcond
+
+//_____________________________________________________________________________
+AliMUONPedestalSubprocessor::AliMUONPedestalSubprocessor(AliMUONPreprocessor* master)
+: AliMUONVSubprocessor(master,
+ "Pedestals",
+ "Upload MUON Tracker pedestals to OCDB"),
+fPedestals(0x0)
+{
+ // default ctor
+}
+
+//_____________________________________________________________________________
+AliMUONPedestalSubprocessor::~AliMUONPedestalSubprocessor()
+{
+ // dtor
+ delete fPedestals;
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPedestalSubprocessor::Initialize(Int_t run, UInt_t startTime, UInt_t endTime)
+{
+ /// When starting a new run, reads in the pedestals ASCII files.
+
+ const Int_t kSystem = AliMUONPreprocessor::kDAQ;
+ const char* kId = "PEDESTALS";
+
+ delete fPedestals;
+ fPedestals = new AliMUON2DMap(kTRUE);
+
+ AliInfo(Form("Reading pedestal files for Run %d startTime %ld endTime %ld",
+ run,startTime,endTime));
+
+ TList* sources = Master()->GetFileSources(kSystem,kId);
+ TIter next(sources);
+ TObjString* o(0x0);
+ while ( ( o = static_cast<TObjString*>(next()) ) )
+ {
+ TString fileName(Master()->GetFile(kSystem,kId,o->GetName()));
+ Bool_t ok = ReadFile(fileName.Data());
+ if (!ok)
+ {
+ AliError(Form("Could not read file %s",fileName.Data()));
+ }
+ }
+ delete sources;
+}
+
+//_____________________________________________________________________________
+UInt_t
+AliMUONPedestalSubprocessor::Process(TMap* /*dcsAliasMap*/)
+{
+ // Store the pedestals into the CDB
+
+ if (!fPedestals) return 0;
+
+ AliInfo("Validating pedestals");
+ AliMUON2DStoreValidator validator;
+ TObjArray* missing =
+ validator.Validate(*fPedestals,AliMUONCalibParam2F::InvalidFloatValue());
+
+ if (missing)
+ {
+ validator.Report(*missing);
+// AliError("Will not write into CDB as some pieces are missing...");
+// return 0;
+ }
+
+ AliInfo("Storing pedestals");
+
+ AliCDBMetaData metaData;
+ metaData.SetBeamPeriod(0);
+ metaData.SetResponsible("MUON TRK");
+ metaData.SetComment("Computed by AliMUONPedestalSubprocessor $Id$");
+
+ UInt_t result = Master()->Store("Calib", "Pedestals", fPedestals, &metaData, 0, 0);
+
+ return result;
+}
+
+//_____________________________________________________________________________
+Bool_t
+AliMUONPedestalSubprocessor::ReadFile(const char* filename)
+{
+ // Read the pedestals from an ASCII file.
+ // Format of that file is one line per channel :
+ //---------------------------------------------------------------------------
+ // BUS_PATCH MANU_ADDR CHANNEL MEAN SIGMA
+ //---------------------------------------------------------------------------
+ //
+ // Return kFALSE if reading was not successfull.
+ //
+
+ AliInfo(Form("Reading %s",filename));
+
+ std::ifstream in(gSystem->ExpandPathName(filename));
+ if (!in.good()) return kFALSE;
+
+ char line[80];
+ Int_t busPatchID, manuID, manuChannel;
+ Float_t pedMean, pedSigma;
+ AliMpBusPatch busPatch;
+ busPatch.ReadBusPatchFile();
+ static const Int_t kNchannels(64);
+ static Bool_t replace(kFALSE);
+
+ while ( in.getline(line,80) )
+ {
+ if ( line[0] == '/' && line[1] == '/' ) continue;
+ std::istringstream sin(line);
+ sin >> busPatchID >> manuID >> manuChannel >> pedMean >> pedSigma;
+ Int_t detElemID = busPatch.GetDEfromBus(busPatchID);
+ AliDebug(3,Form("BUSPATCH %3d DETELEMID %4d MANU %3d CH %3d MEAN %7.2f SIGMA %7.2f",
+ busPatchID,detElemID,manuID,manuChannel,pedMean,pedSigma));
+
+ AliMUONVCalibParam* ped =
+ static_cast<AliMUONVCalibParam*>(fPedestals->Get(detElemID,manuID));
+
+ if (!ped)
+ {
+ ped = new AliMUONCalibParam2F(kNchannels,AliMUONCalibParam2F::InvalidFloatValue());
+ fPedestals->Set(detElemID,manuID,ped,replace);
+ }
+ ped->SetValueAsFloat(manuChannel,0,pedMean);
+ ped->SetValueAsFloat(manuChannel,1,pedSigma);
+ }
+ in.close();
+ return kTRUE;
+}
+
+
+//_____________________________________________________________________________
+void
+AliMUONPedestalSubprocessor::Print(Option_t* opt) const
+{
+ /// ouput to screen
+ AliMUONVDataIterator* it = fPedestals->Iterator();
+ AliMUONObjectPair* p;
+
+ while ( ( p = static_cast<AliMUONObjectPair*>(it->Next() ) ) )
+ {
+ AliMUONVCalibParam* value = static_cast<AliMUONVCalibParam*>(p->Value());
+ value->Print(opt);
+ }
+}
--- /dev/null
+#ifndef ALIMUONPEDESTALSUBPROCESSOR_H
+#define ALIMUONPEDESTALSUBPROCESSOR_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* See cxx source for full Copyright notice */
+
+// $Id$
+
+/// \ingroup shuttle
+/// \class AliMUONPedestalSubprocessor
+/// \brief Implementation of AliMUONVSubprocessor for MUON TRK pedestals
+///
+/// \author Laurent Aphecetche
+
+#ifndef ALIMUONVSUBPROCESSOR_H
+# include "AliMUONVSubprocessor.h"
+#endif
+
+class AliMUONV2DStore;
+class TObjArray;
+
+class AliMUONPedestalSubprocessor : public AliMUONVSubprocessor
+{
+public:
+ AliMUONPedestalSubprocessor(AliMUONPreprocessor* master);
+ virtual ~AliMUONPedestalSubprocessor();
+
+ void Initialize(Int_t run, UInt_t startTime, UInt_t endTime);
+ UInt_t Process(TMap* dcsAliasMap);
+ void Print(Option_t* opt="") const;
+
+private:
+ AliMUONPedestalSubprocessor(const AliMUONPedestalSubprocessor&);
+ AliMUONPedestalSubprocessor& operator=(const AliMUONPedestalSubprocessor&);
+
+ Bool_t ReadFile(const char* filename);
+ void ReportMissing(const TObjArray& chambers);
+
+private:
+ AliMUONV2DStore* fPedestals; //! Pedestals for the MUON TRK
+
+ ClassDef(AliMUONPedestalSubprocessor,1) // A shuttle preprocessor for MUON TRK pedetals
+};
+
+#endif
--- /dev/null
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* *
+* Author: The ALICE Off-line Project. *
+* Contributors are mentioned in the code where appropriate. *
+* *
+* Permission to use, copy, modify and distribute this software and its *
+* documentation strictly for non-commercial purposes is hereby granted *
+* without fee, provided that the above copyright notice appears in all *
+* copies and that both the copyright notice and this permission notice *
+* appear in the supporting documentation. The authors make no claims *
+* about the suitability of this software for any purpose. It is *
+* provided "as is" without express or implied warranty. *
+**************************************************************************/
+
+// $Id$
+
+#include "AliMUONPreprocessor.h"
+#include "TObjArray.h"
+#include "AliMUONPedestalSubprocessor.h"
+#include "Riostream.h"
+
+/// \class AliMUONPreprocessor
+///
+/// Shuttle preprocessor for MUON subsystems (TRK and TRG)
+///
+/// It's simply a manager class that deals with a list of sub-tasks
+/// (of type AliMUONVSubprocessor).
+///
+/// \author Laurent Aphecetche
+
+/// \cond CLASSIMP
+ClassImp(AliMUONPreprocessor)
+/// \endcond
+
+//_____________________________________________________________________________
+AliMUONPreprocessor::AliMUONPreprocessor(const char* detector,
+ AliShuttleInterface* shuttle)
+: AliPreprocessor(detector,shuttle), fSubprocessors(new TObjArray[kLast])
+{
+ /// ctor. Builds the list of subtasks
+ ///
+ /// \todo FIXME: should test detector wrt to tracker or trigger to
+ /// instantiate the correct list of subtasks, which should be :
+ /// Tracker :
+ /// pedestals
+ /// gains
+ /// deadchannels
+ /// gms
+ ///
+ /// Trigger :
+ /// masks
+ /// lut
+ ///
+ fSubprocessors->AddAt(new AliMUONPedestalSubprocessor(this),kPedestal);
+}
+
+//_____________________________________________________________________________
+AliMUONPreprocessor::~AliMUONPreprocessor()
+{
+ /// dtor
+ delete fSubprocessors;
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPreprocessor::Initialize(Int_t run, UInt_t startTime, UInt_t endTime)
+{
+ /// loop over subtasks and initialize them
+ for ( Int_t i = 0; i <= fSubprocessors->GetLast(); ++i )
+ {
+ Subprocessor(i)->Initialize(run,startTime,endTime);
+ }
+}
+
+//_____________________________________________________________________________
+UInt_t
+AliMUONPreprocessor::Process(TMap* dcsAliasMap)
+{
+ /// loop over subtasks to make them work
+ UInt_t rv(0);
+
+ for ( Int_t i = 0; i <= fSubprocessors->GetLast(); ++i )
+ {
+ rv += Subprocessor(i)->Process(dcsAliasMap);
+ }
+ return rv;
+}
+
+//_____________________________________________________________________________
+void
+AliMUONPreprocessor::Print(Option_t* opt) const
+{
+ /// output to screen
+ cout << "<AliMUONPreprocessor> subprocessors :" << endl;
+ for ( Int_t i=0; i <= fSubprocessors->GetLast(); ++i )
+ {
+ Subprocessor(i)->Print(opt);
+ }
+}
+
+//_____________________________________________________________________________
+AliMUONVSubprocessor*
+AliMUONPreprocessor::Subprocessor(Int_t i) const
+{
+ /// return i-th subprocessor
+ if ( i >= 0 && i <= fSubprocessors->GetLast() )
+ {
+ return static_cast<AliMUONVSubprocessor*>(fSubprocessors->At(i));
+ }
+ return 0x0;
+}
--- /dev/null
+#ifndef ALIMUONPREPROCESSOR_H
+#define ALIMUONPREPROCESSOR_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* See cxx source for full Copyright notice */
+
+// $Id$
+
+/// \ingroup shuttle
+/// \class AliMUONPreprocessor
+/// \brief Shuttle preprocessor for MUON subsystems (TRK and TRG)
+///
+/// \author Laurent Aphecetche
+
+#ifndef ALI_PREPROCESSOR_H
+# include "AliPreprocessor.h"
+#endif
+
+class AliMUONVSubprocessor;
+class TObjArray;
+
+class AliMUONPreprocessor : public AliPreprocessor
+{
+public:
+ AliMUONPreprocessor(const char* detector, AliShuttleInterface* shuttle);
+ virtual ~AliMUONPreprocessor();
+
+ virtual void Initialize(Int_t run, UInt_t startTime, UInt_t endTime);
+ virtual UInt_t Process(TMap* dcsAliasMap);
+ virtual void Print(Option_t* opt="") const;
+
+ TList* GetFileSources(Int_t system, const char* id)
+ { return AliPreprocessor::GetFileSources(system,id); }
+
+ UInt_t Store(const char* pathLevel2, const char* pathLevel3, TObject* object,
+ AliCDBMetaData* metaData,
+ Int_t validityStart = 0, Bool_t validityInfinite = kFALSE)
+ {
+ return AliPreprocessor::Store(pathLevel2,pathLevel3,object,metaData,
+ validityStart,validityInfinite);
+ }
+
+ const char* GetFile(Int_t system, const char* id, const char* source)
+ {
+ return AliPreprocessor::GetFile(system,id,source);
+ }
+
+private:
+ enum ESubprocessors { kPedestal=0, kLast };
+
+ AliMUONPreprocessor(const AliMUONPreprocessor& rhs);
+ AliMUONPreprocessor& operator=(const AliMUONPreprocessor& rhs);
+
+ AliMUONVSubprocessor* Subprocessor(Int_t i) const;
+
+private:
+ TObjArray* fSubprocessors; ///!< sub processors to execute
+
+ ClassDef(AliMUONPreprocessor,1) // MUON Shuttle preprocessor
+};
+
+#endif
--- /dev/null
+/**************************************************************************
+* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* *
+* Author: The ALICE Off-line Project. *
+* Contributors are mentioned in the code where appropriate. *
+* *
+* Permission to use, copy, modify and distribute this software and its *
+* documentation strictly for non-commercial purposes is hereby granted *
+* without fee, provided that the above copyright notice appears in all *
+* copies and that both the copyright notice and this permission notice *
+* appear in the supporting documentation. The authors make no claims *
+* about the suitability of this software for any purpose. It is *
+* provided "as is" without express or implied warranty. *
+**************************************************************************/
+
+// $Id$
+
+#include "AliMUONVSubprocessor.h"
+
+/// \class AliMUONVSubprocessor
+///
+/// Base class for a shuttle sub-task for MUON (either TRK or TRG)
+///
+/// It allows to organize more cleanly the various calibration tasks
+/// to be performed within the MUON shuttle's preprocessors
+///
+/// \author Laurent Aphecetche
+///
+
+/// \cond CLASSIMP
+ClassImp(AliMUONVSubprocessor)
+/// \endcond
+
+//_____________________________________________________________________________
+AliMUONVSubprocessor::AliMUONVSubprocessor(AliMUONPreprocessor* master,
+ const char* name,
+ const char* title)
+: TNamed(name,title), fMaster(master)
+{
+ /// ctor
+}
+
+//_____________________________________________________________________________
+AliMUONVSubprocessor::~AliMUONVSubprocessor()
+{
+ /// dtor
+}
+
+//_____________________________________________________________________________
+void
+AliMUONVSubprocessor::Initialize(Int_t /*run*/,
+ UInt_t /*startTime*/,
+ UInt_t /*endTime*/)
+{
+ /// optional
+}
+
--- /dev/null
+#ifndef ALIMUONVSUBPROCESSOR_H
+#define ALIMUONVSUBPROCESSOR_H
+
+/* Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+* See cxx source for full Copyright notice */
+
+// $Id$
+
+/// \ingroup shuttle
+/// \class AliMUONVSubprocessor
+/// \brief Base class for a shuttle sub-task for MUON (either TRK or TRG)
+///
+/// \author Laurent Aphecetche
+
+#ifndef ROOT_TNamed
+# include "TNamed.h"
+#endif
+
+class TMap;
+class AliMUONPreprocessor;
+
+class AliMUONVSubprocessor : public TNamed
+{
+public:
+ AliMUONVSubprocessor(AliMUONPreprocessor* master,
+ const char* name="", const char* title="");
+ virtual ~AliMUONVSubprocessor();
+
+ virtual void Initialize(Int_t run, UInt_t startTime, UInt_t endTime);
+ virtual UInt_t Process(TMap* dcsAliasMap) = 0;
+
+protected:
+ AliMUONPreprocessor* Master() const { return fMaster; }
+
+ AliMUONVSubprocessor();
+ AliMUONVSubprocessor(const AliMUONVSubprocessor&);
+ AliMUONVSubprocessor& operator=(const AliMUONVSubprocessor&);
+
+private:
+ AliMUONPreprocessor* fMaster; ///< Pointer to our master
+
+ ClassDef(AliMUONVSubprocessor,1) // Base class of MUON shuttle sub(pre)processors
+};
+
+#endif
--- /dev/null
+#ifdef __CINT__
+
+#pragma link C++ class AliMUON2DStoreValidator+;
+#pragma link C++ class AliMUONPreprocessor+;
+#pragma link C++ class AliMUONVSubprocessor+;
+#pragma link C++ class AliMUONPedestalSubprocessor+;
+#pragma link C++ class AliMUONPedestalEventGenerator+;
+#pragma link C++ class AliMUONCheckItem+;
+#pragma link C++ class AliMUONCheckItemIterator+;
+
+#endif
--- /dev/null
+/**************************************************************************
+ * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
+ * *
+ * Author: The ALICE Off-line Project. *
+ * Contributors are mentioned in the code where appropriate. *
+ * *
+ * Permission to use, copy, modify and distribute this software and its *
+ * documentation strictly for non-commercial purposes is hereby granted *
+ * without fee, provided that the above copyright notice appears in all *
+ * copies and that both the copyright notice and this permission notice *
+ * appear in the supporting documentation. The authors make no claims *
+ * about the suitability of this software for any purpose. It is *
+ * provided "as is" without express or implied warranty. *
+ **************************************************************************/
+
+/* $Id$ */
+
+#if !defined(__CINT__) || defined(__MAKECINT__)
+
+// This macro runs the test preprocessor
+// It uses AliTestShuttle to simulate a full Shuttle process
+
+// The input data is created in the functions
+// CreateDCSAliasMap() creates input that would in the same way come from DCS
+// ReadDCSAliasMap() reads from a file
+// CreateInputFilesMap() creates a list of local files, that can be accessed by the shuttle
+//
+// According to SHUTTLE/TestShuttle/TestPreprocessor.C
+// By Laurent Aphecetche, SUBATECH Nantes
+
+#include "AliCDBManager.h"
+#include "AliShuttleInterface.h"
+#include "AliCDBId.h"
+#include "AliTestShuttle.h"
+#include "TMap.h"
+#include "Riostream.h"
+#include "TSystem.h"
+#include "AliMpExMap.h"
+#include "TMap.h"
+#include "TString.h"
+#include "TObjArray.h"
+#include "AliMpHelper.h"
+#include "AliDCSValue.h"
+#include "TObjString.h"
+#include "TRandom.h"
+#include "AliMUONPreprocessor.h"
+#include "AliCDBEntry.h"
+#endif
+
+void TestMUONPreprocessor()
+{
+ // load library
+ gSystem->Load("../SHUTTLE/TestShuttle/libTestShuttle.so");
+
+ // initialize location of CDB
+ AliCDBManager::Instance()->SetDefaultStorage("local://$ALICE_ROOT/SHUTTLE/TestShuttle/TestCDB");
+
+ // create AliTestShuttle instance
+ // The parameters are run, startTime, endTime
+ AliTestShuttle* shuttle = new AliTestShuttle(800, 0, 1);
+
+ // TODO(1)
+ //
+ // The shuttle can read DCS data, if the preprocessor should be tested to process DCS data,
+ // some fake data has to be created.
+ //
+ // The "fake" input data can be taken using either (a) or (b):
+ // (a) data from a file: Use ReadDCSAliasMap()
+ // the format of the file is explained in ReadDCSAliasMap()
+ // To use it uncomment the following line:
+ //
+// TMap* dcsAliasMap = ReadDCSAliasMap();
+ //
+ // (b) generated in this macro: Use CreateDCSAliasMap() and its documentation
+ // To use it uncomment the following line:
+ //
+// TMap* dcsAliasMap = CreateDCSAliasMap();
+
+ // now give the alias map to the shuttle
+ // shuttle->SetDCSInput(dcsAliasMap);
+
+ // TODO(2)
+ //
+ // The shuttle can also process files that originate from DCS, DAQ and HLT.
+ // To test it, we provide some local files and locations where these would be found when
+ // the online machinery would be there.
+ // In real life this functions would be produces by the sub-detectors
+ // calibration programs in DCS, DAQ or HLT. These files can then be retrieved using the Shuttle.
+ //
+ // Files are added with the function AliTestShuttle::AddInputFile. The syntax is:
+ // AddInputFile(<system>, <detector>, <id>, <source>, <local-file>)
+ // In this example we add a file originating from the GDC with the id PEDESTALS
+ // Three files originating from different LDCs but with the same id are also added
+// shuttle->AddInputFile(AliTestShuttle::kDAQ, "DET", "PEDESTALS", "GDC", "file1.root");
+// shuttle->AddInputFile(AliTestShuttle::kDAQ, "DET", "DRIFTVELOCITY", "LDC0", "file2a.root");
+// shuttle->AddInputFile(AliTestShuttle::kDAQ, "DET", "DRIFTVELOCITY", "LDC1", "file2b.root");
+// shuttle->AddInputFile(AliTestShuttle::kDAQ, "DET", "DRIFTVELOCITY", "LDC2", "file2b.root");
+
+ shuttle->AddInputFile(AliTestShuttle::kDAQ,"MUON","PEDESTALS","LDC0","$ALICE_ROOT/MUON/data/LDC0.ped");
+ shuttle->AddInputFile(AliTestShuttle::kDAQ,"MUON","PEDESTALS","LDC1","$ALICE_ROOT/MUON/data/LDC1.ped");
+ shuttle->AddInputFile(AliTestShuttle::kDAQ,"MUON","PEDESTALS","LDC2","$ALICE_ROOT/MUON/data/LDC2.ped");
+ shuttle->AddInputFile(AliTestShuttle::kDAQ,"MUON","PEDESTALS","LDC3","$ALICE_ROOT/MUON/data/LDC3.ped");
+
+ // TODO(3)
+ // Create the preprocessor that should be tested, it registers itself automatically to the shuttle
+// AliPreprocessor* pp = new AliTestPreprocessor("DET", shuttle);
+ new AliMUONPreprocessor("MUON",shuttle);
+
+ shuttle->Print();
+
+ // Test the preprocessor
+ shuttle->Process();
+
+ // TODO(4)
+ // In the preprocessor AliShuttleInterface::Store should be called to put the final
+ // data to the CDB. To check if all went fine have a look at the files produced in
+ // $ALICE_ROOT/SHUTTLE/TestShuttle/TestCDB/<detector>/SHUTTLE/Data
+ //
+ // Check the file which should have been created
+// AliCDBEntry* entry = AliCDBManager::Instance()->Get("DET/SHUTTLE/Data", 7);
+// if (!entry)
+// {
+// printf("The file is not there. Something went wrong.\n");
+// return;
+// }
+//
+// AliTestDataDCS* output = dynamic_cast<AliTestDataDCS*> (entry->GetObject());
+// // If everything went fine, draw the result
+// if (output)
+// output->Draw();
+}
--- /dev/null
+# $Id$
+
+SRCS:= \
+AliMUONPreprocessor.cxx \
+AliMUONVSubprocessor.cxx \
+AliMUONPedestalSubprocessor.cxx \
+AliMUON2DStoreValidator.cxx \
+AliMUONPedestalEventGenerator.cxx \
+AliMUONCheckItem.cxx \
+AliMUONCheckItemIterator.cxx
+
+HDRS:= $(SRCS:.cxx=.h)
+
+DHDR:= MUONshuttleLinkDef.h
+
+EINCLUDE := MUON/mapping
+
+