-/**************************************************************************
- * Copyright(c) 2007-2009, 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$ */
-//-----------------------------------------------------------------------------
-/// class AliITSAlignMille2Module
-/// Alignment class for the ALICE ITS detector
-///
-/// This class is used by AliITSAlignMille to build custom supermodules
-/// made of ITS sensitive modules. These supermodules are then aligned
-///
-/// Custom supermodules must have VolumeID > 14335
-///
-/// \author M. Lunardon
-//-----------------------------------------------------------------------------
-
-#include <TGeoManager.h>
-#include <TGeoMatrix.h>
-
-#include "AliITSAlignMille2Module.h"
-#include "AliITSgeomTGeo.h"
-#include "AliGeomManager.h"
-#include "AliAlignObjParams.h"
-#include "AliLog.h"
-#include "AliITSAlignMille2.h"
-
-/// \cond CLASSIMP
-ClassImp(AliITSAlignMille2Module)
-/// \endcond
-
-#define CORHW_
-
-AliAlignObjParams AliITSAlignMille2Module::fgTempAlignObj;
-
-//-------------------------------------------------------------
-AliITSAlignMille2Module::AliITSAlignMille2Module() :
- TNamed(),
- fNSensVol(0),
- fIndex(-1),
- fVolumeID(0),
- fNProcPoints(0),
- fSensVolIndex(0),
- fSensVolVolumeID(0),
- fMatrix(NULL),
- fSensVolMatrix(NULL),
- fSensVolModifMatrix(NULL),
- fParent(NULL)
-{
- /// void constructor
- fMatrix = new TGeoHMatrix;
- fSensVolMatrix = new TGeoHMatrix;
- fSensVolModifMatrix = new TGeoHMatrix;
- fSensVolIndex.Set(1);
- fSensVolVolumeID.Set(1);
- fSigmaFactor[0]=fSigmaFactor[1]=fSigmaFactor[2]=1.0;
-}
-
-//-------------------------------------------------------------
-AliITSAlignMille2Module::AliITSAlignMille2Module(Int_t index,UShort_t volid,char* symname,TGeoHMatrix *m,Int_t nsv,UShort_t *volidsv) :
- TNamed(),
- fNSensVol(0),
- fIndex(-1),
- fVolumeID(0),
- fNProcPoints(0),
- fSensVolIndex(0),
- fSensVolVolumeID(0),
- fMatrix(NULL),
- fSensVolMatrix(NULL),
- fSensVolModifMatrix(NULL),
- fParent(NULL)
-{
- /// void constructor
- fMatrix = new TGeoHMatrix;
- fSensVolMatrix = new TGeoHMatrix;
- fSensVolModifMatrix = new TGeoHMatrix;
- fSigmaFactor[0]=fSigmaFactor[1]=fSigmaFactor[2]=1.0;
- if (Set(index,volid,symname,m,nsv,volidsv)) {
- AliInfo("Error in AliITSAlignMille2Module::Set() - initializing void supermodule...");
- }
-}
-
-//-------------------------------------------------------------
-AliITSAlignMille2Module::AliITSAlignMille2Module(UShort_t volid) :
- TNamed(),
- fNSensVol(0),
- fIndex(-1),
- fVolumeID(0),
- fNProcPoints(0),
- fSensVolIndex(0),
- fSensVolVolumeID(0),
- fMatrix(NULL),
- fSensVolMatrix(NULL),
- fSensVolModifMatrix(NULL),
- fParent(NULL)
-{
- /// simple constructor building a supermodule from a single sensitive volume
- fMatrix = new TGeoHMatrix;
- fSensVolMatrix = new TGeoHMatrix;
- fSensVolModifMatrix = new TGeoHMatrix;
- // temporary align object, just use the rotation...
- fSensVolIndex.Set(1);
- fSensVolVolumeID.Set(1);
- fSigmaFactor[0]=fSigmaFactor[1]=fSigmaFactor[2]=1.0;
- //
- fIndex = GetIndexFromVolumeID(volid);
- if (fIndex>=0 && gGeoManager) { // good sensitive module and geometry loaded
- SetName(AliGeomManager::SymName(volid));
- fVolumeID = volid;
- AddSensitiveVolume(volid);
- if (SensVolMatrix(volid, fMatrix))
- AliInfo("Matrix not defined");
- }
- else {
- AliInfo("Wrong VolumeID or Geometry not loaded - initializing void supermodule...");
- }
-}
-
-
-//_____________________________________________________________________________
-AliITSAlignMille2Module::AliITSAlignMille2Module(const AliITSAlignMille2Module &m) :
- TNamed(m),
- fNSensVol(m.fNSensVol),
- fIndex(m.fIndex),
- fVolumeID(m.fVolumeID),
- fNProcPoints(0),
- fSensVolIndex(m.fSensVolIndex),
- fSensVolVolumeID(m.fSensVolVolumeID),
- fMatrix(new TGeoHMatrix(*m.GetMatrix())),
- fSensVolMatrix(new TGeoHMatrix),
- fSensVolModifMatrix(new TGeoHMatrix),
- fParent(m.fParent)
-{
- // Copy constructor
- fSensVolIndex = m.fSensVolIndex;
- fSensVolVolumeID = m.fSensVolVolumeID;
- for (int i=3;i--;) fSigmaFactor[i] = m.fSigmaFactor[i];
-}
-
-//_____________________________________________________________________________
-AliITSAlignMille2Module& AliITSAlignMille2Module::operator=(const AliITSAlignMille2Module &m)
-{
- // operator =
- //
- if(this==&m) return *this;
- ((TNamed *)this)->operator=(m);
- //
- fNSensVol=m.fNSensVol;
- fIndex=m.fIndex;
- fVolumeID=m.fVolumeID;
- for (int i=3;i--;) fSigmaFactor[i] = m.fSigmaFactor[i];
- if (fMatrix) delete fMatrix;
- fMatrix=new TGeoHMatrix(*m.GetMatrix());
- fSensVolIndex = m.fSensVolIndex;
- fSensVolVolumeID = m.fSensVolVolumeID;
- fParent = m.fParent;
- return *this;
-}
-
-
-//-------------------------------------------------------------
-AliITSAlignMille2Module::~AliITSAlignMille2Module() {
- /// Destructor
- delete fMatrix;
- delete fSensVolMatrix;
- delete fSensVolModifMatrix;
-}
-
-//-------------------------------------------------------------
-Int_t AliITSAlignMille2Module::Set(Int_t index, UShort_t volid, char* symname, TGeoHMatrix *m, Int_t nsv, UShort_t *volidsv)
-{
- // initialize a custom supermodule
- // index, volid, symname and matrix must be given
- // if (volidsv) add nsv sensitive volumes to the supermodules
- // return 0 if success
-
- if (index<2198) {
- AliInfo("Index must be >= 2198");
- return -1;
- }
- if (volid<14336) {
- AliInfo("VolumeID must be >= 14336");
- return -2;
- }
-
- if (!symname) return -3;
- for (Int_t i=0; i<2198; i++) {
- if (!strcmp(symname,AliITSgeomTGeo::GetSymName(i))) {
- AliInfo("Symname already used by a Sensitive Volume");
- return -3;
- }
- }
-
- if (!m) return -4;
-
- // can initialize needed stuffs
- fIndex = index;
- fVolumeID = volid;
- SetName(symname);
- //
- (*fMatrix) = (*m);
- //
- fSensVolIndex.Set(nsv);
- fSensVolVolumeID.Set(nsv);
- // add sensitive volumes
- for (Int_t i=0; i<nsv; i++) AddSensitiveVolume(volidsv[i]);
-
- return 0;
-}
-
-//-------------------------------------------------------------
-Int_t AliITSAlignMille2Module::GetIndexFromVolumeID(UShort_t voluid) {
- /// index from volume ID
- AliGeomManager::ELayerID lay = AliGeomManager::VolUIDToLayer(voluid);
- if (lay<1|| lay>6) return -1;
- Int_t idx=Int_t(voluid)-2048*lay;
- if (idx>=AliGeomManager::LayerSize(lay)) return -1;
- for (Int_t ilay=1; ilay<lay; ilay++)
- idx += AliGeomManager::LayerSize(ilay);
- return idx;
-}
-
-//-------------------------------------------------------------
-void AliITSAlignMille2Module::AddSensitiveVolume(UShort_t voluid)
-{
- /// add a sensitive volume to this supermodule
- if (GetIndexFromVolumeID(voluid)<0) return; // bad volid
- //
- // in principle, the correct size of fSensVol... arrays was set outside but check anyway
- if (fSensVolVolumeID.GetSize()<fNSensVol) {
- fSensVolVolumeID.Set(fNSensVol+1);
- fSensVolIndex.Set(fNSensVol+1);
- }
- //
- fSensVolVolumeID[fNSensVol] = Short_t(voluid);
- fSensVolIndex[fNSensVol] = GetIndexFromVolumeID(voluid);
- fNSensVol++;
-}
-
-//-------------------------------------------------------------
-void AliITSAlignMille2Module::DelSensitiveVolume(Int_t at)
-{
- // Suppress sensor at position "at"
- // in fact we are swapping with the last valid one
- int lastValid = --fNSensVol;
- int tmpv = fSensVolIndex[at];
- fSensVolIndex[at] = fSensVolIndex[lastValid];
- tmpv = fSensVolVolumeID[at];
- fSensVolVolumeID[at] = fSensVolVolumeID[lastValid];
- fSensVolVolumeID[lastValid] = tmpv;
- //
-}
-
-//-------------------------------------------------------------
-Bool_t AliITSAlignMille2Module::IsIn(UShort_t voluid) const
-{
- /// check if voluid is defined
- if (!voluid) return kFALSE; // only positive voluid are accepted
- for (Int_t i=0; i<fNSensVol; i++) if (UShort_t(fSensVolVolumeID[i])==voluid) return kTRUE;
- return kFALSE;
-}
-
-//-------------------------------------------------------------
-Bool_t AliITSAlignMille2Module::BelongsTo(AliITSAlignMille2Module* parent) const
-{
- /// check if parent contains the sensors of this volume
- if (fNSensVol<1 || fNSensVol>=parent->GetNSensitiveVolumes()) return kFALSE;
- return parent->IsIn( fSensVolVolumeID[0] );
-}
-
-//-------------------------------------------------------------
-TGeoHMatrix *AliITSAlignMille2Module::GetSensitiveVolumeModifiedMatrix(UShort_t voluid, Double_t *delta,Bool_t local)
-{
- // modify the original TGeoHMatrix of the sensitive module 'voluid' according
- // with a delta transform. applied to the supermodule matrix
- // return NULL if error
-
- if (!IsIn(voluid)) return NULL;
- if (!gGeoManager) return NULL;
-
- // prepare the TGeoHMatrix
- Double_t tr[3],ang[3];
- tr[0]=delta[0]; // in centimeter
- tr[1]=delta[1];
- tr[2]=delta[2];
- ang[0]=delta[3]; // psi (X) in deg
- ang[1]=delta[4]; // theta (Y)
- ang[2]=delta[5]; // phi (Z)
- //
- fgTempAlignObj.SetRotation(ang[0],ang[1],ang[2]);
- fgTempAlignObj.SetTranslation(tr[0],tr[1],tr[2]);
- AliDebug(3,Form("Delta angles: psi=%f theta=%f phi=%f",ang[0],ang[1],ang[2]));
- TGeoHMatrix hm;
- fgTempAlignObj.GetMatrix(hm);
- //printf("\n0: delta matrix\n");hm.Print();
-
- // 1) start setting fSensVolModif = fSensVol
- if (SensVolMatrix(voluid, fSensVolModifMatrix)) return NULL;
- //
- if (local) {
- // 2) set fSensVolModif = SensVolRel
- fSensVolModifMatrix->MultiplyLeft( &fMatrix->Inverse() );
- // 3) multiply left by delta
- fSensVolModifMatrix->MultiplyLeft( &hm );
- // 4) multiply left by fMatrix
- fSensVolModifMatrix->MultiplyLeft( fMatrix );
- }
- else fSensVolModifMatrix->MultiplyLeft( &hm );
- //
- return fSensVolModifMatrix;
-}
-
-//-------------------------------------------------------------
-AliAlignObjParams *AliITSAlignMille2Module::GetSensitiveVolumeMisalignment(UShort_t voluid, Double_t *deltalocal)
-{
- // calculate misalignment of sens.vol. 'voluid' according with a displacement 'deltalocal'
- // of the mother volume. The misalignment is returned as AliAlignObjParams object
-
- if (!IsIn(voluid)) return NULL;
- if (!gGeoManager) return NULL;
-
- // prepare the TGeoHMatrix
- Double_t tr[3],ang[3];
- tr[0]=deltalocal[0]; // in centimeter
- tr[1]=deltalocal[1];
- tr[2]=deltalocal[2];
- ang[0]=deltalocal[3]; // psi (X) in deg
- ang[1]=deltalocal[4]; // theta (Y)
- ang[2]=deltalocal[5]; // phi (Z)
- //
- fgTempAlignObj.SetRotation(ang[0],ang[1],ang[2]);
- fgTempAlignObj.SetTranslation(tr[0],tr[1],tr[2]);
- AliDebug(3,Form("Delta angles: psi=%f theta=%f phi=%f",ang[0],ang[1],ang[2]));
- //
- return GetSensitiveVolumeMisalignment(voluid,&fgTempAlignObj);
-}
-
-//-------------------------------------------------------------
-AliAlignObjParams *AliITSAlignMille2Module::GetSensitiveVolumeMisalignment(UShort_t voluid, AliAlignObjParams *a)
-{
- // return the misalignment of the sens. vol. 'voluid' corresponding with
- // a misalignment 'a' in the mother volume
- // return NULL if error
-
- // Gsv = Gg * Gg-1 * Gsv -> Lsv,g = Gg-1 * Gsv
- // G'sv = Gg * Dg * Lsv,g === Gsv * Dsv
- // Gg * Dg * Gg-1 * Gsv = Gsv * Gsv-1 * Gg * Dg * Gg-1 * Gsv
- //
- // => Dsv = (Gsv-1 * Gg * Dg * Gg-1 * Gsv)
- //
-
- if (!IsIn(voluid)) return NULL;
- if (!gGeoManager) return NULL;
-
- //a->Print("");
-
- // prepare the Delta matrix Dg
- TGeoHMatrix dg;
- a->GetMatrix(dg);
- //dg.Print();
-
- // 1) start setting fSensVolModif = Gsv
- if (SensVolMatrix(voluid, fSensVolModifMatrix)) return NULL;
- //printf("\n1: modif=orig del sensvol\n");fSensVolModifMatrix->Print();
-
- // 2) set fSensVolModif = Gg-1 * Gsv
- fSensVolModifMatrix->MultiplyLeft( &fMatrix->Inverse() );
- //printf("\n2: modif=relative del sensvol\n");fSensVolModifMatrix->Print();
-
- // 3) set fSensVolModif = Dg * Gg-1 * Gsv
- fSensVolModifMatrix->MultiplyLeft( &dg );
- //printf("\n3: modif= delta*relative\n");fSensVolModifMatrix->Print();
-
- // 4) set fSensVolModif = Gg * Dg * Gg-1 * Gsv
- fSensVolModifMatrix->MultiplyLeft( fMatrix );
- //printf("\n4: modif=quasi,manca il Gsv-1...\n");fSensVolModifMatrix->Print();
-
- // 5) set fSensVolModif = Gsv-1 * Gg * Dg * Gg-1 * Gsv
- if (SensVolMatrix(voluid, &dg)) return NULL;
- fSensVolModifMatrix->MultiplyLeft( &dg.Inverse() );
- //printf("\n5: modif=finale\n");fSensVolModifMatrix->Print();
- //
- // >> RS
- // 6) mo' fSensVolModif dovrebbe essere la Dsv(loc) t.c. G'sv = Gsv*Dsv(loc)
- // per trasformarla in Dsv(loc rispetto al Gsv0, non modificato) dovrebbe essere:
- // Dsv(loc) -> Dpre * Dsv(loc) * Dpre-1
- //TGeoHMatrix dpre; // dpre = Gsv0-1*Gsv
- //if (SensVolOrigGlobalMatrix(voluid, &dg)) return NULL;
- //if (SensVolMatrix(voluid, &dpre)) return NULL;
- //dpre.MultiplyLeft( &dg.Inverse() );
- //fSensVolModifMatrix->Multiply( &dpre.Inverse() );
- //fSensVolModifMatrix->MultiplyLeft( &dpre );
- // direi che NON FUNZIONA!!!!
-
- // << RS
-
- // reset align object (may not be needed...)
- fgTempAlignObj.SetVolUID(0);
- fgTempAlignObj.SetSymName("");
- fgTempAlignObj.SetTranslation(0,0,0);
- fgTempAlignObj.SetRotation(0,0,0);
- //
- // >> RS
-#ifdef CORHW_
- // correction for SPD y-shift
- if (voluid>=2048 && voluid<4256) {
- TGeoHMatrix deltay;
- double dy[3]={0.,0.0081,0.};
- deltay.SetTranslation(dy);
- fSensVolModifMatrix->MultiplyLeft( &deltay );
- fSensVolModifMatrix->Multiply( &deltay.Inverse() );
- }
-#endif
- // << RS
- if (!fgTempAlignObj.SetMatrix(*fSensVolModifMatrix)) return NULL;
- fgTempAlignObj.SetVolUID(voluid);
- fgTempAlignObj.SetSymName(AliGeomManager::SymName(voluid));
- //
- return &fgTempAlignObj;
-}
-
-// >> RS
-//-------------------------------------------------------------
-AliAlignObjParams *AliITSAlignMille2Module::GetSensitiveVolumeTotalMisalignment(UShort_t voluid, Double_t *deltalocal)
-{
- // calculate misalignment of sens.vol. 'voluid' according with a displacement 'deltalocal'
- // of the mother volume. The misalignment is returned as AliAlignObjParams object including
- // the (evenctual) prealignment => no merging needed
-
- if (!IsIn(voluid)) return NULL;
- if (!gGeoManager) return NULL;
-
- // prepare the TGeoHMatrix
- Double_t tr[3],ang[3];
- tr[0]=deltalocal[0]; // in centimeter
- tr[1]=deltalocal[1];
- tr[2]=deltalocal[2];
- ang[0]=deltalocal[3]; // psi (X) in deg
- ang[1]=deltalocal[4]; // theta (Y)
- ang[2]=deltalocal[5]; // phi (Z)
-
- // reset align object (may not be needed...)
- fgTempAlignObj.SetVolUID(0);
- fgTempAlignObj.SetSymName("");
- fgTempAlignObj.SetRotation(ang[0],ang[1],ang[2]);
- fgTempAlignObj.SetTranslation(tr[0],tr[1],tr[2]);
- AliDebug(3,Form("Delta angles: psi=%f theta=%f phi=%f",ang[0],ang[1],ang[2]));
-
- // Gsv = Gg * Gg-1 * Gsv -> Lsv,g = Gg-1 * Gsv
- // G'sv = Gg * Dg * Lsv,g === DGsv * Gsv
- //
- // => Dsv = (G0sv-1 * Gg * Dg * Gg-1 * GMsv) //
- //
-
- // prepare the Delta matrix Dg
- TGeoHMatrix dg;
- fgTempAlignObj.GetMatrix(dg);
- //dg.Print();
-
- // 1) start setting fSensVolModif = Gsv
- if (SensVolMatrix(voluid, fSensVolModifMatrix)) return NULL;
- //printf("\n1: modif=orig del sensvol\n");fSensVolModifMatrix->Print();
-
- // 2) set fSensVolModif = Gg-1 * Gsv
- fSensVolModifMatrix->MultiplyLeft( &fMatrix->Inverse() );
- //printf("\n2: modif=relative del sensvol\n");fSensVolModifMatrix->Print();
-
- // 3) set fSensVolModif = Dg * Gg-1 * Gsv
- fSensVolModifMatrix->MultiplyLeft( &dg );
- //printf("\n3: modif= delta*relative\n");fSensVolModifMatrix->Print();
-
- // 4) set fSensVolModif = Gg * Dg * Gg-1 * Gsv
- fSensVolModifMatrix->MultiplyLeft( fMatrix );
- //printf("\n4: modif=quasi,manca il Gsv-1...\n");fSensVolModifMatrix->Print();
-
- // 5) set fSensVolModif = G0sv-1 * Gg * Dg * Gg-1 * Gsv
- // qui usa l'orig anziche' la prealigned...
- if (SensVolOrigGlobalMatrix(voluid, &dg)) return NULL;
- fSensVolModifMatrix->MultiplyLeft( &dg.Inverse() );
- //printf("\n5: modif=finale\n");fSensVolModifMatrix->Print();
-
- // reset align object (may not be needed...)
- fgTempAlignObj.SetVolUID(0);
- fgTempAlignObj.SetSymName("");
- fgTempAlignObj.SetTranslation(0,0,0);
- fgTempAlignObj.SetRotation(0,0,0);
-
-#ifdef CORHW_
- // correction for SPD y-shift
- if (voluid>=2048 && voluid<4256) {
- TGeoHMatrix deltay;
- double dy[3]={0.,0.0081,0.};
- deltay.SetTranslation(dy);
- fSensVolModifMatrix->MultiplyLeft( &deltay );
- fSensVolModifMatrix->Multiply( &deltay.Inverse() );
- }
-#endif
- if (!fgTempAlignObj.SetMatrix(*fSensVolModifMatrix)) return NULL;
- fgTempAlignObj.SetVolUID(voluid);
- fgTempAlignObj.SetSymName(AliGeomManager::SymName(voluid));
-
-
- //fgTempAlignObj.Print("");
-
- return &fgTempAlignObj;
-}
-//-------------------------------------------------------------
-
-//-------------------------------------------------------------
-AliAlignObjParams *AliITSAlignMille2Module::GetSensitiveVolumeGlobalMisalignment(UShort_t voluid, Double_t *deltalocal)
-{
- // calculate misalignment of sens.vol. 'voluid' according with a displacement 'deltalocal'
- // of the mother volume. The misalignment is returned as AliAlignObjParams object
-
- if (!IsIn(voluid)) return NULL;
- if (!gGeoManager) return NULL;
-
- // prepare the TGeoHMatrix
- Double_t tr[3],ang[3];
- tr[0]=deltalocal[0]; // in centimeter
- tr[1]=deltalocal[1];
- tr[2]=deltalocal[2];
- ang[0]=deltalocal[3]; // psi (X) in deg
- ang[1]=deltalocal[4]; // theta (Y)
- ang[2]=deltalocal[5]; // phi (Z)
-
- // reset align object (may not be needed...)
- fgTempAlignObj.SetTranslation(0,0,0);
- fgTempAlignObj.SetRotation(0,0,0);
-
- fgTempAlignObj.SetRotation(ang[0],ang[1],ang[2]);
- fgTempAlignObj.SetTranslation(tr[0],tr[1],tr[2]);
- AliDebug(3,Form("Delta angles: psi=%f theta=%f phi=%f",ang[0],ang[1],ang[2]));
-
- // Gsv = Gg * Gg-1 * Gsv -> Lsv,g = Gg-1 * Gsv
- // G'sv = Gg * Dg * Lsv,g === DGsv * Gsv
- //
- // => DGsv = (Gg * Dg * Gg-1)
- //
-
- // prepare the Delta matrix Dg
- TGeoHMatrix dg;
- fgTempAlignObj.GetMatrix(dg);
- //dg.Print();
-
- dg.MultiplyLeft( fMatrix );
- dg.Multiply( &fMatrix->Inverse() );
-
- // reset align object (may not be needed...)
- fgTempAlignObj.SetTranslation(0,0,0);
- fgTempAlignObj.SetRotation(0,0,0);
-
- fgTempAlignObj.SetVolUID(voluid);
- fgTempAlignObj.SetSymName(AliGeomManager::SymName(voluid));
-
- if (!fgTempAlignObj.SetMatrix(dg)) return NULL;
-
- //fgTempAlignObj.Print("");
-
- return &fgTempAlignObj;
-}
-// << RS
-
-//-------------------------------------------------------------
-TGeoHMatrix *AliITSAlignMille2Module::GetSensitiveVolumeMatrix(UShort_t voluid)
-{
- // return TGeoHMatrix of the sens.vol. 'voluid' in the current geometry
- if (SensVolMatrix(voluid,fSensVolMatrix)) return NULL;
- return fSensVolMatrix;
-}
-
-//-------------------------------------------------------------
-TGeoHMatrix *AliITSAlignMille2Module::GetSensitiveVolumeOrigGlobalMatrix(UShort_t voluid)
-{
- // return original ideal position (from AliGeomManager::GetOrigGlobalMatrix())
- if (SensVolOrigGlobalMatrix(voluid,fSensVolMatrix)) return NULL;
- return fSensVolMatrix;
-}
-//-------------------------------------------------------------
-Int_t AliITSAlignMille2Module::SensVolMatrix(UShort_t volid, TGeoHMatrix *m)
-{
- // set matrix for sensitive modules (SPD corrected)
- // return 0 if success
- Double_t rot[9];
- Int_t idx=GetIndexFromVolumeID(volid);
- if (idx<0) return -1;
- if (!AliITSgeomTGeo::GetRotation(idx,rot)) return -2;
- m->SetRotation(rot);
- Double_t oLoc[3]={0,0,0};
- Double_t oGlo[3]={0,0,0};
- if (!AliITSgeomTGeo::LocalToGlobal(idx,oLoc,oGlo)) return -3;
- m->SetTranslation(oGlo);
- return 0;
-}
-
-//-------------------------------------------------------------
-Int_t AliITSAlignMille2Module::SensVolOrigGlobalMatrix(UShort_t volid, TGeoHMatrix *m)
-{
- // set original global matrix for sensitive modules (SPD corrected)
- // return 0 if success
- Int_t idx=GetIndexFromVolumeID(volid);
- if (idx<0) return -1;
- TGeoHMatrix mo;
- if (!AliGeomManager::GetOrigGlobalMatrix(AliGeomManager::SymName(volid),mo)) (*m)=mo;
-
-#ifdef CORHW_
- // SPD y-shift by 81 mu
- if (volid<5000) {
- Double_t oLoc[3]={0.0,0.0081,0.0};
- Double_t oGlo[3]={0,0,0};
- m->LocalToMaster(oLoc,oGlo);
- m->SetTranslation(oGlo);
- }
-#endif
- return 0;
-}
-
-//-------------------------------------------------------------
-UShort_t AliITSAlignMille2Module::GetVolumeIDFromSymname(const Char_t *symname) {
- /// volume ID from symname
- if (!symname) return 0;
-
- for (UShort_t voluid=2000; voluid<13300; voluid++) {
- Int_t modId;
- AliGeomManager::ELayerID layerId = AliGeomManager::VolUIDToLayer(voluid,modId);
- if (layerId>0 && layerId<7 && modId>=0 && modId<AliGeomManager::LayerSize(layerId)) {
- if (!strcmp(symname,AliGeomManager::SymName(layerId,modId))) return voluid;
- }
- }
-
- return 0;
-}
-
-//-------------------------------------------------------------
-UShort_t AliITSAlignMille2Module::GetVolumeIDFromIndex(Int_t index) {
- /// volume ID from index
- if (index<0 || index>2197) return 0;
- return GetVolumeIDFromSymname(AliITSgeomTGeo::GetSymName(index));
-}
-
-//-------------------------------------------------------------
-void AliITSAlignMille2Module::Print(Option_t*) const
-{
- ///
- printf("*** ITS SuperModule for AliITSAlignMille ***\n");
- printf("symname : %s\n",GetName());
- printf("parent : %s\n",fParent ? fParent->GetName() : "N/A");
- printf("volumeID : %4d | index : %4d\n",fVolumeID,fIndex);
- printf("Factors : X=%.2f Y=%.2f Z=%.2f | DOF: Tx:%d Ty:%d Tz:%d Phi:%d Theta:%d Psi:%d\n",
- fSigmaFactor[0],fSigmaFactor[1],fSigmaFactor[2],
- IsFreeDOF(AliITSAlignMille2::kDOFTX),IsFreeDOF(AliITSAlignMille2::kDOFTY),
- IsFreeDOF(AliITSAlignMille2::kDOFTZ),IsFreeDOF(AliITSAlignMille2::kDOFPH),
- IsFreeDOF(AliITSAlignMille2::kDOFTH),IsFreeDOF(AliITSAlignMille2::kDOFPS));
- fMatrix->Print();
- printf("%4d Sensitive volumes | %6d Processed Points\n",fNSensVol,fNProcPoints);
- for (Int_t i=0; i<fNSensVol; i++) printf(" voluid[%d] = %d\n",i,UShort_t(fSensVolVolumeID[i]));
-}
-
-//-------------------------------------------------------------
-Bool_t AliITSAlignMille2Module::IsAlignable() const
-{
- TGeoManager* geoManager = AliGeomManager::GetGeometry();
- if (!geoManager) {
- AliInfo("Couldn't initialize geometry");
- return kFALSE;
- }
- return geoManager->GetAlignableEntry(GetName())!=0;
-}
-
-//-------------------------------------------------------------
-void AliITSAlignMille2Module::GetLocalMatrix(TGeoHMatrix &mat) const
-{
- // return the local matrix for transformation to its parent
- mat = *fMatrix;
- if (fParent) mat.MultiplyLeft( &fParent->GetMatrix()->Inverse() );
-}
+/************************************************************************** \r
+ * Copyright(c) 2007-2009, ALICE Experiment at CERN, All rights reserved. * \r
+ * * \r
+ * Author: The ALICE Off-line Project. * \r
+ * Contributors are mentioned in the code where appropriate. * \r
+ * * \r
+ * Permission to use, copy, modify and distribute this software and its * \r
+ * documentation strictly for non-commercial purposes is hereby granted * \r
+ * without fee, provided that the above copyright notice appears in all * \r
+ * copies and that both the copyright notice and this permission notice * \r
+ * appear in the supporting documentation. The authors make no claims * \r
+ * about the suitability of this software for any purpose. It is * \r
+ * provided "as is" without express or implied warranty. * \r
+ **************************************************************************/ \r
+ \r
+/* $Id$ */ \r
+//----------------------------------------------------------------------------- \r
+/// \class AliITSAlignMille2Module\r
+/// Alignment class for the ALICE ITS detector \r
+/// \r
+/// This class is used by AliITSAlignMille to build custom supermodules \r
+/// made of ITS sensitive modules. These supermodules are then aligned\r
+/// \r
+/// Custom supermodules must have VolumeID > 14335\r
+///\r
+/// \author M. Lunardon \r
+//----------------------------------------------------------------------------- \r
+ \r
+#include <TGeoManager.h> \r
+#include <TGeoMatrix.h> \r
+ \r
+#include "AliITSAlignMille2Module.h" \r
+#include "AliITSgeomTGeo.h" \r
+#include "AliGeomManager.h" \r
+#include "AliAlignObjParams.h" \r
+#include "AliLog.h" \r
+#include "AliITSAlignMille2.h"\r
+ \r
+/// \cond CLASSIMP \r
+ClassImp(AliITSAlignMille2Module) \r
+/// \endcond \r
+\r
+#define CORHW_\r
+\r
+AliAlignObjParams AliITSAlignMille2Module::fgTempAlignObj;\r
+const Float_t AliITSAlignMille2Module::fgkDummyConstraint = 1.E3;\r
+ \r
+//-------------------------------------------------------------\r
+AliITSAlignMille2Module::AliITSAlignMille2Module() : \r
+ TNamed(), \r
+ fNSensVol(0), \r
+ fIndex(-1), \r
+ fDetType(-1),\r
+ fVolumeID(0),\r
+ fNParTot(0),\r
+ fNParFree(0),\r
+ fParOffs(0),\r
+ fNProcPoints(0),\r
+ fParVals(0),\r
+ fParErrs(0),\r
+ fParCstr(0),\r
+ fSensVolIndex(0),\r
+ fSensVolVolumeID(0),\r
+ fMatrix(NULL),\r
+ fSensVolMatrix(NULL),\r
+ fSensVolModifMatrix(NULL),\r
+ fParent(NULL),\r
+ fChildren(0)\r
+{ \r
+ /// void constructor \r
+ fMatrix = new TGeoHMatrix; \r
+ fSensVolMatrix = new TGeoHMatrix; \r
+ fSensVolModifMatrix = new TGeoHMatrix; \r
+ fSensVolIndex.Set(1);\r
+ fSensVolVolumeID.Set(1);\r
+ fSigmaFactor[0]=fSigmaFactor[1]=fSigmaFactor[2]=1.0;\r
+} \r
+\r
+//-------------------------------------------------------------\r
+AliITSAlignMille2Module::AliITSAlignMille2Module(Int_t index, UShort_t volid, const char* symname,\r
+ const TGeoHMatrix *m, Int_t nsv, const UShort_t *volidsv) : \r
+ TNamed(), \r
+ fNSensVol(0), \r
+ fIndex(-1), \r
+ fDetType(-1), \r
+ fVolumeID(0),\r
+ fNParTot(0),\r
+ fNParFree(0),\r
+ fParOffs(kMaxParGeom),\r
+ fNProcPoints(0),\r
+ fParVals(0),\r
+ fParErrs(0),\r
+ fParCstr(0),\r
+ fSensVolIndex(0),\r
+ fSensVolVolumeID(0), \r
+ fMatrix(NULL),\r
+ fSensVolMatrix(NULL),\r
+ fSensVolModifMatrix(NULL),\r
+ fParent(NULL),\r
+ fChildren(0)\r
+{ \r
+ /// void constructor \r
+ fMatrix = new TGeoHMatrix; \r
+ fSensVolMatrix = new TGeoHMatrix; \r
+ fSensVolModifMatrix = new TGeoHMatrix; \r
+ fSigmaFactor[0]=fSigmaFactor[1]=fSigmaFactor[2]=1.0;\r
+ for (int i=kMaxParGeom;i--;) fParOffs[i] = -1;\r
+ if (Set(index,volid,symname,m,nsv,volidsv)) {\r
+ AliInfo("Error in AliITSAlignMille2Module::Set() - initializing void supermodule...");\r
+ }\r
+ AssignDetType();\r
+} \r
+\r
+//-------------------------------------------------------------\r
+AliITSAlignMille2Module::AliITSAlignMille2Module(UShort_t volid) : \r
+ TNamed(), \r
+ fNSensVol(0), \r
+ fIndex(-1), \r
+ fDetType(-1),\r
+ fVolumeID(0),\r
+ fNParTot(0),\r
+ fNParFree(0),\r
+ fParOffs(kMaxParGeom),\r
+ fNProcPoints(0),\r
+ fParVals(0),\r
+ fParErrs(0),\r
+ fParCstr(0), \r
+ fSensVolIndex(0),\r
+ fSensVolVolumeID(0),\r
+ fMatrix(NULL),\r
+ fSensVolMatrix(NULL),\r
+ fSensVolModifMatrix(NULL),\r
+ fParent(NULL),\r
+ fChildren(0)\r
+{ \r
+ /// simple constructor building a supermodule from a single sensitive volume \r
+ fMatrix = new TGeoHMatrix; \r
+ fSensVolMatrix = new TGeoHMatrix; \r
+ fSensVolModifMatrix = new TGeoHMatrix; \r
+ // temporary align object, just use the rotation...\r
+ fSensVolIndex.Set(1);\r
+ fSensVolVolumeID.Set(1);\r
+ fSigmaFactor[0]=fSigmaFactor[1]=fSigmaFactor[2]=1.0;\r
+ for (int i=kMaxParGeom;i--;) fParOffs[i] = -1;\r
+ //\r
+ fIndex = GetIndexFromVolumeID(volid); \r
+ if (fIndex>=0 && gGeoManager) { // good sensitive module and geometry loaded\r
+ SetName(AliGeomManager::SymName(volid));\r
+ fVolumeID = volid;\r
+ AddSensitiveVolume(volid);\r
+ SetSensorsProvided(kTRUE);\r
+ if (SensVolMatrix(volid, fMatrix))\r
+ AliInfo("Matrix not defined");\r
+ }\r
+ else {\r
+ AliInfo("Wrong VolumeID or Geometry not loaded - initializing void supermodule...");\r
+ }\r
+ AssignDetType();\r
+} \r
+\r
+\r
+//_____________________________________________________________________________\r
+AliITSAlignMille2Module::AliITSAlignMille2Module(const AliITSAlignMille2Module &m) :\r
+ TNamed(m),\r
+ fNSensVol(m.fNSensVol),\r
+ fIndex(m.fIndex), \r
+ fDetType(m.fDetType),\r
+ fVolumeID(m.fVolumeID),\r
+ fNParTot(m.fNParTot),\r
+ fNParFree(m.fNParFree),\r
+ fParOffs(m.fNParTot),\r
+ fNProcPoints(0),\r
+ fParVals(0),\r
+ fParErrs(0),\r
+ fParCstr(0), \r
+ fSensVolIndex(m.fSensVolIndex),\r
+ fSensVolVolumeID(m.fSensVolVolumeID),\r
+ fMatrix(new TGeoHMatrix(*m.GetMatrix())),\r
+ fSensVolMatrix(new TGeoHMatrix),\r
+ fSensVolModifMatrix(new TGeoHMatrix),\r
+ fParent(m.fParent),\r
+ fChildren(0)\r
+{\r
+ // Copy constructor\r
+ fSensVolIndex = m.fSensVolIndex;\r
+ fSensVolVolumeID = m.fSensVolVolumeID;\r
+ for (int i=m.fNParTot;i--;) fParOffs[i] = m.fParOffs[i];\r
+ for (int i=3;i--;) fSigmaFactor[i] = m.fSigmaFactor[i];\r
+ if (fNParTot) {\r
+ fParVals = new Float_t[fNParTot];\r
+ fParErrs = new Float_t[fNParTot];\r
+ fParCstr = new Float_t[fNParTot];\r
+ for (int i=fNParTot;i--;) {\r
+ fParVals[i] = m.fParVals[i];\r
+ fParErrs[i] = m.fParErrs[i];\r
+ fParCstr[i] = m.fParCstr[i];\r
+ }\r
+ }\r
+}\r
+\r
+//_____________________________________________________________________________\r
+AliITSAlignMille2Module& AliITSAlignMille2Module::operator=(const AliITSAlignMille2Module &m) \r
+{\r
+ // operator =\r
+ //\r
+ if(this==&m) return *this;\r
+ ((TNamed *)this)->operator=(m);\r
+ //\r
+ fNSensVol=m.fNSensVol;\r
+ fIndex=m.fIndex;\r
+ fDetType = m.fDetType;\r
+ fVolumeID=m.fVolumeID;\r
+ fNParTot = m.fNParTot;\r
+ fNParFree = m.fNParFree;\r
+ delete[] fParVals; fParVals = 0;\r
+ delete[] fParErrs; fParErrs = 0;\r
+ delete[] fParCstr; fParCstr = 0;\r
+ //\r
+ if (fNParTot) {\r
+ fParVals = new Float_t[fNParTot];\r
+ fParErrs = new Float_t[fNParTot];\r
+ for (int i=m.GetNParTot();i--;) {\r
+ fParVals[i] = m.fParVals[i];\r
+ fParErrs[i] = m.fParErrs[i];\r
+ fParCstr[i] = m.fParCstr[i];\r
+ }\r
+ }\r
+ //\r
+ fParOffs.Set(fNParTot);\r
+ for (int i=0;i<fNParTot;i++) fParOffs[i] = m.fParOffs[i];\r
+ for (int i=3;i--;) fSigmaFactor[i] = m.fSigmaFactor[i];\r
+ if (fMatrix) delete fMatrix;\r
+ fMatrix=new TGeoHMatrix(*m.GetMatrix());\r
+ fSensVolIndex = m.fSensVolIndex;\r
+ fSensVolVolumeID = m.fSensVolVolumeID;\r
+ fParent = m.fParent;\r
+ fChildren.Clear();\r
+ for (int i=0;i<m.GetNChildren();i++) fChildren.Add(m.GetChild(i));\r
+ return *this;\r
+}\r
+\r
+\r
+//-------------------------------------------------------------\r
+AliITSAlignMille2Module::~AliITSAlignMille2Module() { \r
+ /// Destructor \r
+ delete fMatrix; \r
+ delete fSensVolMatrix; \r
+ delete fSensVolModifMatrix; \r
+ delete[] fParVals;\r
+ delete[] fParErrs;\r
+ delete[] fParCstr;\r
+ fChildren.Clear();\r
+} \r
+\r
+//-------------------------------------------------------------\r
+Int_t AliITSAlignMille2Module::Set(Int_t index, UShort_t volid, const char* symname, \r
+ const TGeoHMatrix *m, Int_t nsv, const UShort_t *volidsv) \r
+{\r
+ // initialize a custom supermodule\r
+ // index, volid, symname and matrix must be given\r
+ // if (volidsv) add nsv sensitive volumes to the supermodules\r
+ // return 0 if success\r
+\r
+ if (index<2198) {\r
+ AliInfo("Index must be >= 2198");\r
+ return -1;\r
+ }\r
+ if (volid<14336) {\r
+ AliInfo("VolumeID must be >= 14336");\r
+ return -2;\r
+ }\r
+ \r
+ if (!symname) return -3;\r
+ for (Int_t i=0; i<2198; i++) {\r
+ if (!strcmp(symname,AliITSgeomTGeo::GetSymName(i))) {\r
+ AliInfo("Symname already used by a Sensitive Volume");\r
+ return -3;\r
+ }\r
+ }\r
+ \r
+ if (!m) return -4;\r
+\r
+ // can initialize needed stuffs\r
+ fIndex = index;\r
+ fVolumeID = volid;\r
+ SetName(symname);\r
+ //\r
+ (*fMatrix) = (*m);\r
+ //\r
+ fSensVolIndex.Set(nsv);\r
+ fSensVolVolumeID.Set(nsv);\r
+ // add sensitive volumes\r
+ for (Int_t i=0; i<nsv; i++) AddSensitiveVolume(volidsv[i]);\r
+\r
+ return 0;\r
+}\r
+\r
+//-------------------------------------------------------------\r
+void AliITSAlignMille2Module::SetFreeDOF(Int_t dof,Double_t cstr)\r
+{\r
+ if (cstr>0) fParCstr[dof] = fgkDummyConstraint+1.; // the parameter is free and unconstrained\r
+ else if (cstr<0) fParCstr[dof] = -cstr; // the parameter is free but constrained\r
+ else fParCstr[dof] = 0; // fixed parameter\r
+}\r
+\r
+//-------------------------------------------------------------\r
+Bool_t AliITSAlignMille2Module::IsSensor(UShort_t voluid) \r
+{\r
+ // Does this volid correspond to sensor ?\r
+ AliGeomManager::ELayerID layId = AliGeomManager::VolUIDToLayerSafe(voluid);\r
+ if (layId>0 && layId<7) {\r
+ Int_t mId = Int_t(voluid & 0x7ff);\r
+ if( mId>=0 && mId<AliGeomManager::LayerSize(layId)) return kTRUE;\r
+ }\r
+ return kFALSE;\r
+}\r
+\r
+//-------------------------------------------------------------\r
+Int_t AliITSAlignMille2Module::GetIndexFromVolumeID(UShort_t voluid) {\r
+ /// index from volume ID\r
+ AliGeomManager::ELayerID lay = AliGeomManager::VolUIDToLayer(voluid);\r
+ if (lay<1|| lay>6) return -1;\r
+ Int_t idx=Int_t(voluid)-2048*lay;\r
+ if (idx>=AliGeomManager::LayerSize(lay)) return -1;\r
+ for (Int_t ilay=1; ilay<lay; ilay++) \r
+ idx += AliGeomManager::LayerSize(ilay);\r
+ return idx;\r
+}\r
+\r
+//-------------------------------------------------------------\r
+void AliITSAlignMille2Module::AddSensitiveVolume(UShort_t voluid)\r
+{\r
+ /// add a sensitive volume to this supermodule\r
+ if (GetIndexFromVolumeID(voluid)<0) return; // bad volid\r
+ //\r
+ // in principle, the correct size of fSensVol... arrays was set outside but check anyway\r
+ if (fSensVolVolumeID.GetSize()<fNSensVol+1) {\r
+ fSensVolVolumeID.Set(fNSensVol+1);\r
+ fSensVolIndex.Set(fNSensVol+1);\r
+ }\r
+ //\r
+ fSensVolVolumeID[fNSensVol] = Short_t(voluid);\r
+ fSensVolIndex[fNSensVol] = GetIndexFromVolumeID(voluid);\r
+ fNSensVol++;\r
+}\r
+\r
+//-------------------------------------------------------------\r
+void AliITSAlignMille2Module::DelSensitiveVolume(Int_t at)\r
+{\r
+ // Suppress sensor at position "at"\r
+ // in fact we are swapping with the last valid one \r
+ int lastValid = --fNSensVol;\r
+ int tmpv = fSensVolIndex[at];\r
+ fSensVolIndex[at] = fSensVolIndex[lastValid];\r
+ tmpv = fSensVolVolumeID[at];\r
+ fSensVolVolumeID[at] = fSensVolVolumeID[lastValid];\r
+ fSensVolVolumeID[lastValid] = tmpv;\r
+ //\r
+}\r
+\r
+//-------------------------------------------------------------\r
+Bool_t AliITSAlignMille2Module::IsIn(UShort_t voluid) const \r
+{\r
+ /// check if voluid is defined\r
+ if (!voluid) return kFALSE; // only positive voluid are accepted\r
+ for (Int_t i=0; i<fNSensVol; i++) if (UShort_t(fSensVolVolumeID[i])==voluid) return kTRUE;\r
+ return kFALSE;\r
+}\r
+\r
+//-------------------------------------------------------------\r
+Bool_t AliITSAlignMille2Module::BelongsTo(AliITSAlignMille2Module* parent) const\r
+{\r
+ /// check if parent contains the sensors of this volume\r
+ if (fNSensVol<1 || fNSensVol>=parent->GetNSensitiveVolumes()) return kFALSE;\r
+ return parent->IsIn( fSensVolVolumeID[0] );\r
+}\r
+\r
+//-------------------------------------------------------------\r
+TGeoHMatrix *AliITSAlignMille2Module::GetSensitiveVolumeModifiedMatrix(UShort_t voluid, Double_t *delta,Bool_t local)\r
+{\r
+ // modify the original TGeoHMatrix of the sensitive module 'voluid' according\r
+ // with a delta transform. applied to the supermodule matrix\r
+ // return NULL if error\r
+\r
+ if (!IsIn(voluid)) return NULL;\r
+ if (!gGeoManager) return NULL;\r
+\r
+ // prepare the TGeoHMatrix\r
+ Double_t tr[3],ang[3];\r
+ tr[0]=delta[0]; // in centimeter\r
+ tr[1]=delta[1]; \r
+ tr[2]=delta[2];\r
+ ang[0]=delta[3]; // psi (X) in deg\r
+ ang[1]=delta[4]; // theta (Y)\r
+ ang[2]=delta[5]; // phi (Z)\r
+ //\r
+ fgTempAlignObj.SetRotation(ang[0],ang[1],ang[2]);\r
+ fgTempAlignObj.SetTranslation(tr[0],tr[1],tr[2]);\r
+ AliDebug(3,Form("Delta angles: psi=%f theta=%f phi=%f",ang[0],ang[1],ang[2]));\r
+ TGeoHMatrix hm;\r
+ fgTempAlignObj.GetMatrix(hm);\r
+ //printf("\n0: delta matrix\n");hm.Print();\r
+\r
+ // 1) start setting fSensVolModif = fSensVol\r
+ if (SensVolMatrix(voluid, fSensVolModifMatrix)) return NULL;\r
+ //\r
+ if (local) {\r
+ // 2) set fSensVolModif = SensVolRel\r
+ fSensVolModifMatrix->MultiplyLeft( &fMatrix->Inverse() );\r
+ // 3) multiply left by delta\r
+ fSensVolModifMatrix->MultiplyLeft( &hm );\r
+ // 4) multiply left by fMatrix\r
+ fSensVolModifMatrix->MultiplyLeft( fMatrix );\r
+ }\r
+ else fSensVolModifMatrix->MultiplyLeft( &hm );\r
+ //\r
+ return fSensVolModifMatrix;\r
+}\r
+\r
+//-------------------------------------------------------------\r
+AliAlignObjParams *AliITSAlignMille2Module::GetSensitiveVolumeMisalignment(UShort_t voluid, Double_t *deltalocal)\r
+{\r
+ // calculate misalignment of sens.vol. 'voluid' according with a displacement 'deltalocal'\r
+ // of the mother volume. The misalignment is returned as AliAlignObjParams object\r
+\r
+ if (!IsIn(voluid)) return NULL;\r
+ if (!gGeoManager) return NULL;\r
+ \r
+ // prepare the TGeoHMatrix\r
+ Double_t tr[3],ang[3];\r
+ tr[0]=deltalocal[0]; // in centimeter\r
+ tr[1]=deltalocal[1]; \r
+ tr[2]=deltalocal[2];\r
+ ang[0]=deltalocal[3]; // psi (X) in deg\r
+ ang[1]=deltalocal[4]; // theta (Y)\r
+ ang[2]=deltalocal[5]; // phi (Z)\r
+ //\r
+ fgTempAlignObj.SetRotation(ang[0],ang[1],ang[2]);\r
+ fgTempAlignObj.SetTranslation(tr[0],tr[1],tr[2]);\r
+ AliDebug(3,Form("Delta angles: psi=%f theta=%f phi=%f",ang[0],ang[1],ang[2]));\r
+ //\r
+ return GetSensitiveVolumeMisalignment(voluid,&fgTempAlignObj);\r
+}\r
+\r
+//-------------------------------------------------------------\r
+AliAlignObjParams *AliITSAlignMille2Module::GetSensitiveVolumeMisalignment(UShort_t voluid, AliAlignObjParams *a)\r
+{\r
+ // return the misalignment of the sens. vol. 'voluid' corresponding with \r
+ // a misalignment 'a' in the mother volume\r
+ // return NULL if error\r
+\r
+ // Gsv = Gg * Gg-1 * Gsv -> Lsv,g = Gg-1 * Gsv\r
+ // G'sv = Gg * Dg * Lsv,g === Gsv * Dsv\r
+ // Gg * Dg * Gg-1 * Gsv = Gsv * Gsv-1 * Gg * Dg * Gg-1 * Gsv\r
+ //\r
+ // => Dsv = (Gsv-1 * Gg * Dg * Gg-1 * Gsv)\r
+ //\r
+\r
+ if (!IsIn(voluid)) return NULL;\r
+ if (!gGeoManager) return NULL;\r
+\r
+ //a->Print("");\r
+\r
+ // prepare the Delta matrix Dg\r
+ TGeoHMatrix dg;\r
+ a->GetMatrix(dg);\r
+ //dg.Print();\r
+\r
+ // 1) start setting fSensVolModif = Gsv\r
+ if (SensVolMatrix(voluid, fSensVolModifMatrix)) return NULL;\r
+ //printf("\n1: modif=orig del sensvol\n");fSensVolModifMatrix->Print();\r
+\r
+ // 2) set fSensVolModif = Gg-1 * Gsv\r
+ fSensVolModifMatrix->MultiplyLeft( &fMatrix->Inverse() );\r
+ //printf("\n2: modif=relative del sensvol\n");fSensVolModifMatrix->Print();\r
+ \r
+ // 3) set fSensVolModif = Dg * Gg-1 * Gsv\r
+ fSensVolModifMatrix->MultiplyLeft( &dg );\r
+ //printf("\n3: modif= delta*relative\n");fSensVolModifMatrix->Print();\r
+ \r
+ // 4) set fSensVolModif = Gg * Dg * Gg-1 * Gsv\r
+ fSensVolModifMatrix->MultiplyLeft( fMatrix );\r
+ //printf("\n4: modif=quasi,manca il Gsv-1...\n");fSensVolModifMatrix->Print();\r
+\r
+ // 5) set fSensVolModif = Gsv-1 * Gg * Dg * Gg-1 * Gsv\r
+ if (SensVolMatrix(voluid, &dg)) return NULL;\r
+ fSensVolModifMatrix->MultiplyLeft( &dg.Inverse() );\r
+ //printf("\n5: modif=finale\n");fSensVolModifMatrix->Print();\r
+ //\r
+ // >> RS\r
+ // 6) mo' fSensVolModif dovrebbe essere la Dsv(loc) t.c. G'sv = Gsv*Dsv(loc)\r
+ // per trasformarla in Dsv(loc rispetto al Gsv0, non modificato) dovrebbe essere:\r
+ // Dsv(loc) -> Dpre * Dsv(loc) * Dpre-1\r
+ //TGeoHMatrix dpre; // dpre = Gsv0-1*Gsv\r
+ //if (SensVolOrigGlobalMatrix(voluid, &dg)) return NULL;\r
+ //if (SensVolMatrix(voluid, &dpre)) return NULL;\r
+ //dpre.MultiplyLeft( &dg.Inverse() );\r
+ //fSensVolModifMatrix->Multiply( &dpre.Inverse() );\r
+ //fSensVolModifMatrix->MultiplyLeft( &dpre );\r
+ // direi che NON FUNZIONA!!!! \r
+\r
+ // << RS\r
+\r
+ // reset align object (may not be needed...)\r
+ fgTempAlignObj.SetVolUID(0);\r
+ fgTempAlignObj.SetSymName("");\r
+ fgTempAlignObj.SetTranslation(0,0,0);\r
+ fgTempAlignObj.SetRotation(0,0,0);\r
+ //\r
+ // >> RS\r
+#ifdef CORHW_\r
+ // correction for SPD y-shift\r
+ if (voluid>=2048 && voluid<4256) {\r
+ TGeoHMatrix deltay;\r
+ double dy[3]={0.,0.0081,0.};\r
+ deltay.SetTranslation(dy);\r
+ fSensVolModifMatrix->MultiplyLeft( &deltay );\r
+ fSensVolModifMatrix->Multiply( &deltay.Inverse() );\r
+ }\r
+#endif\r
+ // << RS\r
+ if (!fgTempAlignObj.SetMatrix(*fSensVolModifMatrix)) return NULL;\r
+ fgTempAlignObj.SetVolUID(voluid);\r
+ fgTempAlignObj.SetSymName(AliGeomManager::SymName(voluid));\r
+ //\r
+ return &fgTempAlignObj;\r
+}\r
+\r
+// >> RS\r
+//-------------------------------------------------------------\r
+AliAlignObjParams *AliITSAlignMille2Module::GetSensitiveVolumeTotalMisalignment(UShort_t voluid, Double_t *deltalocal)\r
+{\r
+ // calculate misalignment of sens.vol. 'voluid' according with a displacement 'deltalocal'\r
+ // of the mother volume. The misalignment is returned as AliAlignObjParams object including\r
+ // the (evenctual) prealignment => no merging needed\r
+\r
+ if (!IsIn(voluid)) return NULL;\r
+ if (!gGeoManager) return NULL;\r
+ \r
+ // prepare the TGeoHMatrix\r
+ Double_t tr[3],ang[3];\r
+ tr[0]=deltalocal[0]; // in centimeter\r
+ tr[1]=deltalocal[1]; \r
+ tr[2]=deltalocal[2];\r
+ ang[0]=deltalocal[3]; // psi (X) in deg\r
+ ang[1]=deltalocal[4]; // theta (Y)\r
+ ang[2]=deltalocal[5]; // phi (Z)\r
+\r
+ // reset align object (may not be needed...)\r
+ fgTempAlignObj.SetVolUID(0);\r
+ fgTempAlignObj.SetSymName("");\r
+ fgTempAlignObj.SetRotation(ang[0],ang[1],ang[2]);\r
+ fgTempAlignObj.SetTranslation(tr[0],tr[1],tr[2]);\r
+ AliDebug(3,Form("Delta angles: psi=%f theta=%f phi=%f",ang[0],ang[1],ang[2]));\r
+\r
+ // Gsv = Gg * Gg-1 * Gsv -> Lsv,g = Gg-1 * Gsv\r
+ // G'sv = Gg * Dg * Lsv,g === DGsv * Gsv \r
+ //\r
+ // => Dsv = (G0sv-1 * Gg * Dg * Gg-1 * GMsv) //\r
+ //\r
+\r
+ // prepare the Delta matrix Dg\r
+ TGeoHMatrix dg;\r
+ fgTempAlignObj.GetMatrix(dg);\r
+ //dg.Print();\r
+\r
+ // 1) start setting fSensVolModif = Gsv\r
+ if (SensVolMatrix(voluid, fSensVolModifMatrix)) return NULL;\r
+ //printf("\n1: modif=orig del sensvol\n");fSensVolModifMatrix->Print();\r
+\r
+ // 2) set fSensVolModif = Gg-1 * Gsv\r
+ fSensVolModifMatrix->MultiplyLeft( &fMatrix->Inverse() );\r
+ //printf("\n2: modif=relative del sensvol\n");fSensVolModifMatrix->Print();\r
+ \r
+ // 3) set fSensVolModif = Dg * Gg-1 * Gsv\r
+ fSensVolModifMatrix->MultiplyLeft( &dg );\r
+ //printf("\n3: modif= delta*relative\n");fSensVolModifMatrix->Print();\r
+ \r
+ // 4) set fSensVolModif = Gg * Dg * Gg-1 * Gsv\r
+ fSensVolModifMatrix->MultiplyLeft( fMatrix );\r
+ //printf("\n4: modif=quasi,manca il Gsv-1...\n");fSensVolModifMatrix->Print();\r
+\r
+ // 5) set fSensVolModif = G0sv-1 * Gg * Dg * Gg-1 * Gsv\r
+ // qui usa l'orig anziche' la prealigned...\r
+ if (SensVolOrigGlobalMatrix(voluid, &dg)) return NULL;\r
+ fSensVolModifMatrix->MultiplyLeft( &dg.Inverse() );\r
+ //printf("\n5: modif=finale\n");fSensVolModifMatrix->Print();\r
+\r
+ // reset align object (may not be needed...)\r
+ fgTempAlignObj.SetVolUID(0);\r
+ fgTempAlignObj.SetSymName("");\r
+ fgTempAlignObj.SetTranslation(0,0,0);\r
+ fgTempAlignObj.SetRotation(0,0,0);\r
+\r
+#ifdef CORHW_\r
+ // correction for SPD y-shift\r
+ if (voluid>=2048 && voluid<4256) {\r
+ TGeoHMatrix deltay;\r
+ double dy[3]={0.,0.0081,0.};\r
+ deltay.SetTranslation(dy);\r
+ fSensVolModifMatrix->MultiplyLeft( &deltay );\r
+ fSensVolModifMatrix->Multiply( &deltay.Inverse() );\r
+ }\r
+#endif\r
+ if (!fgTempAlignObj.SetMatrix(*fSensVolModifMatrix)) return NULL;\r
+ fgTempAlignObj.SetVolUID(voluid);\r
+ fgTempAlignObj.SetSymName(AliGeomManager::SymName(voluid));\r
+\r
+ \r
+ //fgTempAlignObj.Print("");\r
+\r
+ return &fgTempAlignObj;\r
+}\r
+//-------------------------------------------------------------\r
+\r
+//-------------------------------------------------------------\r
+AliAlignObjParams *AliITSAlignMille2Module::GetSensitiveVolumeGlobalMisalignment(UShort_t voluid, Double_t *deltalocal)\r
+{\r
+ // calculate misalignment of sens.vol. 'voluid' according with a displacement 'deltalocal'\r
+ // of the mother volume. The misalignment is returned as AliAlignObjParams object\r
+\r
+ if (!IsIn(voluid)) return NULL;\r
+ if (!gGeoManager) return NULL;\r
+ \r
+ // prepare the TGeoHMatrix\r
+ Double_t tr[3],ang[3];\r
+ tr[0]=deltalocal[0]; // in centimeter\r
+ tr[1]=deltalocal[1]; \r
+ tr[2]=deltalocal[2];\r
+ ang[0]=deltalocal[3]; // psi (X) in deg\r
+ ang[1]=deltalocal[4]; // theta (Y)\r
+ ang[2]=deltalocal[5]; // phi (Z)\r
+\r
+ // reset align object (may not be needed...)\r
+ fgTempAlignObj.SetTranslation(0,0,0);\r
+ fgTempAlignObj.SetRotation(0,0,0);\r
+\r
+ fgTempAlignObj.SetRotation(ang[0],ang[1],ang[2]);\r
+ fgTempAlignObj.SetTranslation(tr[0],tr[1],tr[2]);\r
+ AliDebug(3,Form("Delta angles: psi=%f theta=%f phi=%f",ang[0],ang[1],ang[2]));\r
+\r
+ // Gsv = Gg * Gg-1 * Gsv -> Lsv,g = Gg-1 * Gsv\r
+ // G'sv = Gg * Dg * Lsv,g === DGsv * Gsv \r
+ //\r
+ // => DGsv = (Gg * Dg * Gg-1)\r
+ //\r
+\r
+ // prepare the Delta matrix Dg\r
+ TGeoHMatrix dg;\r
+ fgTempAlignObj.GetMatrix(dg);\r
+ //dg.Print();\r
+\r
+ dg.MultiplyLeft( fMatrix );\r
+ dg.Multiply( &fMatrix->Inverse() );\r
+\r
+ // reset align object (may not be needed...)\r
+ fgTempAlignObj.SetTranslation(0,0,0);\r
+ fgTempAlignObj.SetRotation(0,0,0);\r
+\r
+ fgTempAlignObj.SetVolUID(voluid);\r
+ fgTempAlignObj.SetSymName(AliGeomManager::SymName(voluid));\r
+\r
+ if (!fgTempAlignObj.SetMatrix(dg)) return NULL;\r
+ \r
+ //fgTempAlignObj.Print("");\r
+\r
+ return &fgTempAlignObj;\r
+}\r
+// << RS\r
+\r
+//-------------------------------------------------------------\r
+TGeoHMatrix *AliITSAlignMille2Module::GetSensitiveVolumeMatrix(UShort_t voluid)\r
+{\r
+ // return TGeoHMatrix of the sens.vol. 'voluid' in the current geometry\r
+ if (SensVolMatrix(voluid,fSensVolMatrix)) return NULL;\r
+ return fSensVolMatrix;\r
+}\r
+\r
+//-------------------------------------------------------------\r
+TGeoHMatrix *AliITSAlignMille2Module::GetSensitiveVolumeOrigGlobalMatrix(UShort_t voluid)\r
+{\r
+ // return original ideal position (from AliGeomManager::GetOrigGlobalMatrix())\r
+ if (SensVolOrigGlobalMatrix(voluid,fSensVolMatrix)) return NULL;\r
+ return fSensVolMatrix;\r
+}\r
+//-------------------------------------------------------------\r
+Int_t AliITSAlignMille2Module::SensVolMatrix(UShort_t volid, TGeoHMatrix *m) \r
+{\r
+ // set matrix for sensitive modules (SPD corrected)\r
+ // return 0 if success\r
+ Double_t rot[9];\r
+ Int_t idx=GetIndexFromVolumeID(volid);\r
+ if (idx<0) return -1;\r
+ if (!AliITSgeomTGeo::GetRotation(idx,rot)) return -2;\r
+ m->SetRotation(rot);\r
+ Double_t oLoc[3]={0,0,0};\r
+ Double_t oGlo[3]={0,0,0};\r
+ if (!AliITSgeomTGeo::LocalToGlobal(idx,oLoc,oGlo)) return -3;\r
+ m->SetTranslation(oGlo);\r
+ return 0;\r
+}\r
+\r
+//-------------------------------------------------------------\r
+Int_t AliITSAlignMille2Module::SensVolOrigGlobalMatrix(UShort_t volid, TGeoHMatrix *m) \r
+{\r
+ // set original global matrix for sensitive modules (SPD corrected)\r
+ // return 0 if success\r
+ Int_t idx=GetIndexFromVolumeID(volid);\r
+ if (idx<0) return -1;\r
+ TGeoHMatrix mo;\r
+ if (!AliGeomManager::GetOrigGlobalMatrix(AliGeomManager::SymName(volid),mo)) return -1;\r
+ (*m)=mo;\r
+ //\r
+#ifdef CORHW_\r
+ // SPD y-shift by 81 mu\r
+ if (volid<5000) { \r
+ Double_t oLoc[3]={0.0,0.0081,0.0};\r
+ Double_t oGlo[3]={0,0,0};\r
+ m->LocalToMaster(oLoc,oGlo);\r
+ m->SetTranslation(oGlo);\r
+ }\r
+#endif\r
+ return 0;\r
+}\r
+\r
+//-------------------------------------------------------------\r
+UShort_t AliITSAlignMille2Module::GetVolumeIDFromSymname(const Char_t *symname) {\r
+ /// volume ID from symname\r
+ if (!symname) return 0;\r
+\r
+ for (UShort_t voluid=2000; voluid<13300; voluid++) {\r
+ Int_t modId;\r
+ AliGeomManager::ELayerID layerId = AliGeomManager::VolUIDToLayer(voluid,modId);\r
+ if (layerId>0 && layerId<7 && modId>=0 && modId<AliGeomManager::LayerSize(layerId)) {\r
+ if (!strcmp(symname,AliGeomManager::SymName(layerId,modId))) return voluid;\r
+ }\r
+ }\r
+\r
+ return 0;\r
+}\r
+\r
+//-------------------------------------------------------------\r
+UShort_t AliITSAlignMille2Module::GetVolumeIDFromIndex(Int_t index) {\r
+ /// volume ID from index\r
+ if (index<0 || index>2197) return 0;\r
+ return GetVolumeIDFromSymname(AliITSgeomTGeo::GetSymName(index));\r
+}\r
+\r
+//-------------------------------------------------------------\r
+void AliITSAlignMille2Module::Print(Option_t*) const \r
+{\r
+ //\r
+ const char* typeName[] = {"SPD","SDD","SSD"};\r
+ printf("*** ITS SuperModule for AliITSAlignMille ***\n");\r
+ printf("symname : %s (type: %s)\n",GetName(),fDetType<0 ? "N/A":typeName[fDetType]);\r
+ printf("parent : %s | %d children\n",fParent ? fParent->GetName() : "N/A",GetNChildren());\r
+ printf("volumeID : %4d | index : %4d | Geom.Params are %s\n",fVolumeID,fIndex,\r
+ GeomParamsGlobal() ? "Global":"Local");\r
+ printf("Factors : X=%.2f Y=%.2f Z=%.2f\n"\r
+ "DOF: %cTx:%5d| %cTy:%5d| %cTz:%5d| %cPsi:%5d| %cTheta:%5d| %cPhi:%5d|",\r
+ fSigmaFactor[0],fSigmaFactor[1],fSigmaFactor[2],\r
+ IsFreeDOF(kDOFTX) ? '+':'-',fParOffs[kDOFTX],IsFreeDOF(kDOFTY) ? '+':'-',fParOffs[kDOFTY],\r
+ IsFreeDOF(kDOFTZ) ? '+':'-',fParOffs[kDOFTZ],IsFreeDOF(kDOFPS) ? '+':'-',fParOffs[kDOFPS],\r
+ IsFreeDOF(kDOFTH) ? '+':'-',fParOffs[kDOFTH],IsFreeDOF(kDOFPH) ? '+':'-',fParOffs[kDOFPH]);\r
+ if (IsSDD()) printf("%cT0:%5d| %cDV:%5d|",IsFreeDOF(kDOFT0)?'+':'-',fParOffs[kDOFT0],\r
+ IsFreeDOF(kDOFDV)?'+':'-',fParOffs[kDOFDV]);\r
+ printf("\n");\r
+ fMatrix->Print();\r
+ printf("%4d Sensitive volumes | %6d Processed Points\n",fNSensVol,fNProcPoints);\r
+ for (Int_t i=0; i<fNSensVol; i++) printf(" voluid[%d] = %d\n",i,UShort_t(fSensVolVolumeID[i]));\r
+}\r
+\r
+//-------------------------------------------------------------\r
+Bool_t AliITSAlignMille2Module::IsAlignable() const\r
+{\r
+ TGeoManager* geoManager = AliGeomManager::GetGeometry();\r
+ if (!geoManager) {\r
+ AliInfo("Couldn't initialize geometry");\r
+ return kFALSE;\r
+ }\r
+ return geoManager->GetAlignableEntry(GetName())!=0;\r
+}\r
+\r
+//-------------------------------------------------------------\r
+void AliITSAlignMille2Module::GetLocalMatrix(TGeoHMatrix &mat) const\r
+{\r
+ // return the local matrix for transformation to its parent\r
+ mat = *fMatrix;\r
+ if (fParent) mat.MultiplyLeft( &fParent->GetMatrix()->Inverse() );\r
+}\r
+\r
+//-------------------------------------------------------------\r
+void AliITSAlignMille2Module::AssignDetType()\r
+{\r
+ TString tp = GetName();\r
+ if (tp.Contains("SPD",TString::kIgnoreCase)) fDetType = kSPD;\r
+ else if (tp.Contains("SDD",TString::kIgnoreCase)) fDetType = kSDD;\r
+ else if (tp.Contains("SSD",TString::kIgnoreCase)) fDetType = kSSD;\r
+ else fDetType = -1;\r
+ fNParTot = IsSDD() ? 8:6;\r
+ fNParFree = 0;\r
+ fParVals = new Float_t[fNParTot];\r
+ fParErrs = new Float_t[fNParTot]; \r
+ fParCstr = new Float_t[fNParTot]; \r
+ if (fParOffs.GetSize()<fNParTot) fParOffs.Set(fNParTot);\r
+ for (int i=fNParTot;i--;) {\r
+ fParVals[i] = fParErrs[i] = 0.; \r
+ fParCstr[i] = 0.;\r
+ fParOffs[i] = -1;\r
+ }\r
+}\r
+\r
+//-------------------------------------------------------------\r
+void AliITSAlignMille2Module::EvaluateDOF()\r
+{\r
+ fNParFree = 0;\r
+ for (int i=fNParTot;i--;) if (IsFreeDOF(i)) fNParFree++;\r
+}\r
+\r
+//-------------------------------------------------------------\r
+void AliITSAlignMille2Module::GetSensVolGlobalParams(UShort_t volid,Double_t *t, Double_t *r)\r
+{\r
+ // return global parameters of the sensor volid\r
+ for (int i=3;i--;) t[i] = r[i] = 0.;\r
+ if (SensVolMatrix(volid,fSensVolMatrix)) return; \r
+ fgTempAlignObj.SetMatrix(*fSensVolMatrix);\r
+ fgTempAlignObj.GetPars(t,r);\r
+}\r
+\r
+//-------------------------------------------------------------\r
+void AliITSAlignMille2Module::GetSensVolLocalParams(UShort_t volid,Double_t *t, Double_t *r)\r
+{\r
+ // return parameters of the sensor volid in the current module\r
+ for (int i=3;i--;) t[i] = r[i] = 0.;\r
+ if (SensVolMatrix(volid,fSensVolMatrix)) return; \r
+ fSensVolMatrix->MultiplyLeft( &fMatrix->Inverse() );\r
+ fgTempAlignObj.SetMatrix(*fSensVolMatrix);\r
+ fgTempAlignObj.GetPars(t,r);\r
+}\r
+\r
+//-------------------------------------------------------------\r
+void AliITSAlignMille2Module::GetSensVolGlobalParams(UShort_t volid,Double_t* loct,Double_t* locr,Double_t *t, Double_t *r)\r
+{\r
+ // return global parameters of the sensor volid modified by the localDelta params\r
+ for (int i=3;i--;) t[i] = r[i] = 0.;\r
+ if (SensVolMatrix(volid,fSensVolMatrix)) return; \r
+ fgTempAlignObj.SetTranslation(loct[0],loct[1],loct[2]);\r
+ fgTempAlignObj.SetRotation(locr[0],locr[1],locr[2]);\r
+ //\r
+ fgTempAlignObj.GetMatrix(*fSensVolModifMatrix); // obtain local delta\r
+ fSensVolModifMatrix->MultiplyLeft( fSensVolMatrix ); // obtain global delta\r
+ fgTempAlignObj.SetMatrix(*fSensVolModifMatrix);\r
+ fgTempAlignObj.GetPars(t,r); // obtain global params\r
+}\r
+\r
+//-------------------------------------------------------------\r
+void AliITSAlignMille2Module::GetSensVolLocalParams(UShort_t volid,Double_t* loct,Double_t* locr,Double_t *t, Double_t *r)\r
+{\r
+ // return parameters of the sensor volid (modified by the localDelta params) in the current volume\r
+ for (int i=3;i--;) t[i] = r[i] = 0.;\r
+ if (SensVolMatrix(volid,fSensVolMatrix)) return; \r
+ fgTempAlignObj.SetTranslation(loct[0],loct[1],loct[2]);\r
+ fgTempAlignObj.SetRotation(locr[0],locr[1],locr[2]);\r
+ //\r
+ fgTempAlignObj.GetMatrix(*fSensVolModifMatrix); // obtain local delta\r
+ fSensVolModifMatrix->MultiplyLeft( fSensVolMatrix ); // obtain global delta\r
+ fSensVolModifMatrix->MultiplyLeft( &fMatrix->Inverse() ); // obtain delta in current volume\r
+ fgTempAlignObj.SetMatrix(*fSensVolModifMatrix);\r
+ fgTempAlignObj.GetPars(t,r); // obtain params\r
+}\r
+\r
+//-------------------------------------------------------------\r
+void AliITSAlignMille2Module::SetParVals(Double_t *vl,Int_t npar)\r
+{\r
+ for (int i=TMath::Min(npar,(Int_t)fNParTot);i--;) fParVals[i] = vl[i];\r
+}\r
+\r
+//-------------------------------------------------------------\r
+void AliITSAlignMille2Module::GetGeomParamsGlo(Double_t *pars)\r
+{\r
+ // recompute parameters from local to global frame\r
+ //\r
+ // is there anything to do?\r
+ if (GeomParamsGlobal()) {for (int i=kMaxParGeom;i--;) pars[i] = fParVals[i]; return;}\r
+ //\r
+ // IMPORTANT: It is assumed that the parents params are defined in a same way (local or global)\r
+ // as for the current module. Since in the mp2 the modules are stored from parents to children,\r
+ // it is safe to call this method in loop staring from the lowest level child, i.e. from the end\r
+ // of the modules array.\r
+ //\r
+ // DeltaGlobal = (ModifParents)*DeltaLocal*(ModifParents)^-1 \r
+ //\r
+ *fSensVolMatrix = *fMatrix; // current global matrix\r
+ AliITSAlignMille2Module* parent = GetParent();\r
+ while (parent) {\r
+ if (parent->GeomParamsGlobal()) {\r
+ AliError("Cannot convert params to Global when the parents are already Global\n");\r
+ for (int i=kMaxParGeom;i--;) pars[i] = 0;\r
+ return;\r
+ }\r
+ fSensVolMatrix->MultiplyLeft( &parent->GetMatrix()->Inverse() ); // Local Matrix\r
+ Float_t *parpar = parent->GetParVals();\r
+ fgTempAlignObj.SetTranslation(parpar[0],parpar[1],parpar[2]);\r
+ fgTempAlignObj.SetRotation(parpar[3],parpar[4],parpar[5]);\r
+ fgTempAlignObj.GetMatrix(*fSensVolModifMatrix);\r
+ fSensVolMatrix->MultiplyLeft(fSensVolModifMatrix);\r
+ fSensVolMatrix->MultiplyLeft(parent->GetMatrix()); // global matrix after parents modifications\r
+ parent = parent->GetParent();\r
+ }\r
+ //\r
+ fgTempAlignObj.SetTranslation(fParVals[0],fParVals[1],fParVals[2]);\r
+ fgTempAlignObj.SetRotation(fParVals[3],fParVals[4],fParVals[5]);\r
+ fgTempAlignObj.GetMatrix(*fSensVolModifMatrix); // local delta matrix\r
+ fSensVolModifMatrix->Multiply( &fSensVolMatrix->Inverse() );\r
+ fSensVolModifMatrix->MultiplyLeft( fSensVolMatrix );\r
+ fgTempAlignObj.SetMatrix( *fSensVolModifMatrix ); // global delta matrix\r
+ fgTempAlignObj.GetPars(pars,pars+3);\r
+ //\r
+}\r
+\r
+//-------------------------------------------------------------\r
+void AliITSAlignMille2Module::GetGeomParamsLoc(Double_t *pars)\r
+{\r
+ // recompute parameters from global to local frame\r
+ //\r
+ // is there anything to do?\r
+ if (!GeomParamsGlobal()) {for (int i=kMaxParGeom;i--;) pars[i] = fParVals[i]; return;}\r
+ //\r
+ // IMPORTANT: It is assumed that the parents params are defined in a same way (local or global)\r
+ // as for the current module. Since in the mp2 the modules are stored from parents to children,\r
+ // it is safe to call this method in loop staring from the lowest level child, i.e. from the end\r
+ // of the modules array.\r
+ //\r
+ // DeltaLocal = (DeltaParents*GlobalMat)^-1*DeltaGlobal*(DeltaParents*GlobalMat)\r
+ //\r
+ AliITSAlignMille2Module* parent = GetParent();\r
+ fgTempAlignObj.SetTranslation(0.,0.,0.);\r
+ fgTempAlignObj.SetRotation(0.,0.,0.);\r
+ fgTempAlignObj.GetMatrix(*fSensVolMatrix); // get no-shift matrix\r
+ //\r
+ while (parent) { // accumulate the product of parents global modifications\r
+ if (!parent->GeomParamsGlobal()) {\r
+ AliError("Cannot convert params to Local when the parents are already Local\n");\r
+ for (int i=kMaxParGeom;i--;) pars[i] = 0;\r
+ return;\r
+ }\r
+ Float_t *parpar = parent->GetParVals();\r
+ fgTempAlignObj.SetTranslation(parpar[0],parpar[1],parpar[2]);\r
+ fgTempAlignObj.SetRotation(parpar[3],parpar[4],parpar[5]);\r
+ fgTempAlignObj.GetMatrix(*fSensVolModifMatrix);\r
+ fSensVolMatrix->Multiply(fSensVolModifMatrix); \r
+ parent = parent->GetParent();\r
+ }\r
+ // global matrix after parents modifications\r
+ fSensVolMatrix->Multiply(fMatrix);\r
+ //\r
+ fgTempAlignObj.SetTranslation(fParVals[0],fParVals[1],fParVals[2]);\r
+ fgTempAlignObj.SetRotation(fParVals[3],fParVals[4],fParVals[5]);\r
+ fgTempAlignObj.GetMatrix(*fSensVolModifMatrix); // global delta matrix\r
+ fSensVolModifMatrix->MultiplyLeft( &fSensVolMatrix->Inverse() );\r
+ fSensVolModifMatrix->Multiply( fSensVolMatrix );\r
+ fgTempAlignObj.SetMatrix( *fSensVolModifMatrix ); // local delta matrix\r
+ fgTempAlignObj.GetPars(pars,pars+3);\r
+ //\r
+}\r
+\r
+\r
+//-------------------------------------------------------------\r
+void AliITSAlignMille2Module::CalcDerivDPosDPar(Int_t sensVol,const Double_t* pl, Double_t *deriv)\r
+{\r
+ // calculate jacobian of the global position vs Parameters (dPos/dParam) \r
+ // for the point in the sensor sensVol\r
+ const double kDel = 0.01;\r
+ double pos0[3],pos1[3],pos2[3],pos3[3];\r
+ double delta[kMaxParGeom];\r
+ //\r
+ for (int ip=kMaxParGeom;ip--;) delta[ip] = 0;\r
+ //\r
+ for (int ip=kMaxParGeom;ip--;) {\r
+ //\r
+ delta[ip] -= kDel;\r
+ GetSensitiveVolumeModifiedMatrix(sensVol,delta,!GeomParamsGlobal())->LocalToMaster(pl,pos0); \r
+ delta[ip] += kDel/2;\r
+ GetSensitiveVolumeModifiedMatrix(sensVol,delta,!GeomParamsGlobal())->LocalToMaster(pl,pos1); \r
+ delta[ip] += kDel;\r
+ GetSensitiveVolumeModifiedMatrix(sensVol,delta,!GeomParamsGlobal())->LocalToMaster(pl,pos2); \r
+ delta[ip] += kDel/2;\r
+ GetSensitiveVolumeModifiedMatrix(sensVol,delta,!GeomParamsGlobal())->LocalToMaster(pl,pos3); \r
+ //\r
+ delta[ip] = 0;\r
+ double *curd = deriv + ip*3;\r
+ for (int i=3;i--;) curd[i] = (8.*(pos2[i]-pos1[i]) - (pos3[i]-pos0[i]))/6./kDel;\r
+ }\r
+ //\r
+}\r
+\r
+//-------------------------------------------------------------\r
+void AliITSAlignMille2Module::CalcDerivGloLoc(Int_t idx,Double_t *deriv)\r
+{\r
+ // calculate derivative of global params vs local param idx: deriv[j] = dParGlo[j]/dParLoc[idx]\r
+ Double_t lpar[kMaxParGeom];\r
+ for (int i=kMaxParGeom;i--;) lpar[i] = 0.;\r
+ // using f(x+h),f(x-h),f(x+h/2),f(x-h2)...\r
+ Double_t par1[kMaxParGeom]; // f(x-h)\r
+ Double_t par2[kMaxParGeom]; // f(x-h/2)\r
+ Double_t par3[kMaxParGeom]; // f(x+h/2)\r
+ Double_t par4[kMaxParGeom]; // f(x+h)\r
+ //\r
+ const Double_t dpar = 1e-3;\r
+ //\r
+ // first values\r
+ lpar[idx] -= dpar;\r
+ GetGlobalParams(lpar,lpar+3, par1,par1+3);\r
+ //\r
+ // second values\r
+ lpar[idx] += dpar/2;\r
+ GetGlobalParams(lpar,lpar+3, par2,par2+3);\r
+ //\r
+ // third values\r
+ lpar[idx] += dpar;\r
+ GetGlobalParams(lpar,lpar+3, par3,par3+3);\r
+ //\r
+ // fourth values\r
+ lpar[idx] += dpar/2;\r
+ GetGlobalParams(lpar,lpar+3, par4,par4+3);\r
+ //\r
+ Double_t h2 = 1./(2.*dpar);\r
+ for (int i=kMaxParGeom;i--;) {\r
+ Double_t d0 = par4[i]-par1[i];\r
+ Double_t d2 = 2.*(par3[i]-par2[i]);\r
+ deriv[i] = h2*(4*d2 - d0)/3.;\r
+ if (TMath::Abs(deriv[i]) < 1.0e-9) deriv[i] = 0.0;\r
+ }\r
+ //\r
+}\r
+\r
+//-------------------------------------------------------------\r
+void AliITSAlignMille2Module::CalcDerivLocGlo(Double_t *deriv)\r
+{\r
+ // calculate derivative of local params vs global params: deriv[i][j] = dParLoc[i]/dParGlo[j]\r
+ Double_t gpar[kMaxParGeom];\r
+ for (int i=kMaxParGeom;i--;) gpar[i] = 0.;\r
+ // using f(x+h),f(x-h),f(x+h/2),f(x-h2)...\r
+ Double_t par1[kMaxParGeom]; // f(x-h)\r
+ Double_t par2[kMaxParGeom]; // f(x-h/2)\r
+ Double_t par3[kMaxParGeom]; // f(x+h/2)\r
+ Double_t par4[kMaxParGeom]; // f(x+h)\r
+ //\r
+ const Double_t dpar = 1e-3;\r
+ //\r
+ for (int ig=kMaxParGeom;ig--;) {\r
+ // first values\r
+ gpar[ig] -= dpar;\r
+ GetLocalParams(gpar,gpar+3, par1,par1+3);\r
+ //\r
+ // second values\r
+ gpar[ig] += dpar/2;\r
+ GetLocalParams(gpar,gpar+3, par2,par2+3);\r
+ //\r
+ // third values\r
+ gpar[ig] += dpar;\r
+ GetLocalParams(gpar,gpar+3, par3,par3+3);\r
+ //\r
+ // fourth values\r
+ gpar[ig] += dpar/2;\r
+ GetLocalParams(gpar,gpar+3, par4,par4+3);\r
+ //\r
+ Double_t h2 = 1./(2.*dpar);\r
+ for (int i=kMaxParGeom;i--;) {\r
+ Double_t d0 = par4[i]-par1[i];\r
+ Double_t d2 = 2.*(par3[i]-par2[i]);\r
+ int idig = i*kMaxParGeom + ig;\r
+ deriv[idig] = h2*(4*d2 - d0)/3.;\r
+ if (TMath::Abs(deriv[idig]) < 1.0e-9) deriv[idig] = 0.0;\r
+ }\r
+ }\r
+ //\r
+}\r
+\r
+//________________________________________________________________________________________________________\r
+void AliITSAlignMille2Module::CalcDerivGloLoc(Int_t sensVol,Int_t paridx,Double_t* derivative)\r
+{\r
+ /// calculate numerically the derivatives of global params vs local param paridx for sensor sensVol: dPglob/dPloc_paridx\r
+ //\r
+ Double_t lpar[kMaxParGeom];\r
+ for (int i=kMaxParGeom;i--;) lpar[i] = 0.;\r
+ // using f(x+h),f(x-h),f(x+h/2),f(x-h2)...\r
+ Double_t par1[kMaxParGeom]; // f(x-h)\r
+ Double_t par2[kMaxParGeom]; // f(x-h/2)\r
+ Double_t par3[kMaxParGeom]; // f(x+h/2)\r
+ Double_t par4[kMaxParGeom]; // f(x+h)\r
+ //\r
+ const Double_t dpar = 1e-3;\r
+ //\r
+ // first values\r
+ lpar[paridx] -= dpar;\r
+ GetSensVolGlobalParams(sensVol,lpar,lpar+3, par1,par1+3);\r
+ //\r
+ // second values\r
+ lpar[paridx] += dpar/2;\r
+ GetSensVolGlobalParams(sensVol,lpar,lpar+3, par2,par2+3);\r
+ //\r
+ // third values\r
+ lpar[paridx] += dpar;\r
+ GetSensVolGlobalParams(sensVol,lpar,lpar+3, par3,par3+3);\r
+ //\r
+ // fourth values\r
+ lpar[paridx] += dpar/2;\r
+ GetSensVolGlobalParams(sensVol,lpar,lpar+3, par4,par4+3);\r
+ //\r
+ Double_t h2 = 1./(2.*dpar);\r
+ for (int i=kMaxParGeom;i--;) {\r
+ Double_t d0 = par4[i]-par1[i];\r
+ Double_t d2 = 2.*(par3[i]-par2[i]);\r
+ derivative[i] = h2*(4*d2 - d0)/3.;\r
+ if (TMath::Abs(derivative[i]) < 1.0e-9) derivative[i] = 0.0;\r
+ }\r
+ //\r
+}\r
+\r
+//________________________________________________________________________________________________________\r
+void AliITSAlignMille2Module::CalcDerivCurLoc(Int_t sensVol,Int_t paridx,Double_t* derivative) \r
+{\r
+ /// calculate numerically the derivatives of sensor params in the current volume vs sensor local param paridx\r
+ //\r
+ Double_t lpar[kMaxParGeom];\r
+ for (int i=kMaxParGeom;i--;) lpar[i] = 0.;\r
+ // using f(x+h),f(x-h),f(x+h/2),f(x-h2)...\r
+ Double_t par1[kMaxParGeom]; // f(x-h)\r
+ Double_t par2[kMaxParGeom]; // f(x-h/2)\r
+ Double_t par3[kMaxParGeom]; // f(x+h/2)\r
+ Double_t par4[kMaxParGeom]; // f(x+h)\r
+ //\r
+ const Double_t dpar = 1e-3;\r
+ //\r
+ // first values\r
+ lpar[paridx] -= dpar;\r
+ GetSensVolLocalParams(sensVol,lpar,lpar+3, par1,par1+3);\r
+ //\r
+ // second values\r
+ lpar[paridx] += dpar/2;\r
+ GetSensVolLocalParams(sensVol,lpar,lpar+3, par2,par2+3);\r
+ //\r
+ // third values\r
+ lpar[paridx] += dpar;\r
+ GetSensVolLocalParams(sensVol,lpar,lpar+3, par3,par3+3);\r
+ //\r
+ // fourth values\r
+ lpar[paridx] += dpar/2;\r
+ GetSensVolLocalParams(sensVol,lpar,lpar+3, par4,par4+3);\r
+ //\r
+ Double_t h2 = 1./(2.*dpar);\r
+ for (int i=kMaxParGeom;i--;) {\r
+ Double_t d0 = par4[i]-par1[i];\r
+ Double_t d2 = 2.*(par3[i]-par2[i]);\r
+ derivative[i] = h2*(4*d2 - d0)/3.;\r
+ if (TMath::Abs(derivative[i]) < 1.0e-9) derivative[i] = 0.0;\r
+ }\r
+ //\r
+}\r
+\r
+\r
+//-------------------------------------------------------------\r
+void AliITSAlignMille2Module::GetGlobalParams(Double_t *t, Double_t *r)\r
+{\r
+ // global parameters of the module\r
+ fgTempAlignObj.SetMatrix( *fMatrix );\r
+ fgTempAlignObj.GetPars(t,r);\r
+}\r
+\r
+//-------------------------------------------------------------\r
+void AliITSAlignMille2Module::GetGlobalParams(const Double_t* loct, const Double_t* locr, Double_t *t, Double_t *r)\r
+{\r
+ // global parameters of the module after the modification by local loct,locr\r
+ fgTempAlignObj.SetTranslation(loct[0],loct[1],loct[2]);\r
+ fgTempAlignObj.SetRotation(locr[0],locr[1],locr[2]);\r
+ fgTempAlignObj.GetMatrix(*fSensVolModifMatrix); \r
+ *fSensVolMatrix = *fMatrix;\r
+ fSensVolMatrix->Multiply(fSensVolModifMatrix);\r
+ fgTempAlignObj.SetMatrix(*fSensVolMatrix);\r
+ fgTempAlignObj.GetPars(t,r);\r
+}\r
+\r
+//-------------------------------------------------------------\r
+void AliITSAlignMille2Module::GetLocalParams(const Double_t* glot, const Double_t* glor, Double_t *t, Double_t *r)\r
+{\r
+ // obtain local delta parameters from global delta params\r
+ fgTempAlignObj.SetTranslation(glot[0],glot[1],glot[2]);\r
+ fgTempAlignObj.SetRotation(glor[0],glor[1],glor[2]);\r
+ fgTempAlignObj.GetMatrix(*fSensVolMatrix); \r
+ fSensVolMatrix->Multiply( fMatrix );\r
+ fSensVolMatrix->MultiplyLeft( &fMatrix->Inverse() );\r
+ fgTempAlignObj.SetMatrix(*fSensVolMatrix);\r
+ fgTempAlignObj.GetPars(t,r);\r
+}\r