/************************************************************************** * 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$ */ /////////////////////////////////////////////////////////////////////// // ITS geometry manipulation routines. // // Created April 15 1999. // // version: 0.0.0 // // By: Bjorn S. Nilsen // // version: 0.0.1 // // Updated May 27 1999. // // Added Cylindrical random and global based changes. // // Added function PrintComparison. // // Modified and added functions Feb. 7 2006 // /////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// // The local coordinate system by, default, is show in the following // figures. Also shown are the ladder numbering scheme. //Begin_Html /*

This shows the relative geometry differences between the ALICE Global coordinate system and the local detector coordinate system.




This shows the front view of the SPDs and the orientation of the local pixel coordinate system. Note that the inner pixel layer has its y coordinate in the opposite direction from all of the other layers.




This shows the front view of the SDDs and the orientation of the local pixel coordinate system.




This shows the front view of the SSDs and the orientation of the local pixel coordinate system.

*/
//End_Html
//
////////////////////////////////////////////////////////////////////////

////////////////////////////////////////////////////////////////////////
//
// version: 0
// Written by Bjorn S. Nilsen
//
// Data Members:
//
// TString    fVersion 
//     Transformation version.
// Int_t      fTrans
//     Flag to keep track of which transformation 
// Int_t      fNmodules
//      The total number of modules
// Int_t fNlayers
//     The number of ITS layers for this geometry. By default this
//  is 6, but can be modified by the creator function if there are
// more layers defined.
//
// TArrayI fNlad
//     A pointer to an array fNlayers long containing the number of 
// ladders for each layer. This array is typically created and filled 
// by the AliITSgeom creator function.
//
// TArrayI fNdet
//     A pointer to an array fNlayers long containing the number of
// active detector volumes for each ladder. This array is typically
// created and filled by the AliITSgeom creator function.
//
// TObjArray fGm containing objects of type AliITSgeomMatrix
//     A pointer to an array of AliITSgeomMatrix classes. One element 
// per module (detector) in the ITS. AliITSgeomMatrix basicly contains
// all of the necessary information about the detector and it's coordinate
// transformations.
//
// TObjArray fShape containting objects of type AliITSgeom
//     A pointer to an array of TObjects containing the detailed shape
// information for each type of detector used in the ITS. For example
// I have created AliITSgeomSPD, AliITSgeomSDD, and 
// AliITSsegmenttionSSD as example structures, derived from TObjects, 
// to hold the detector information. I would recommend that one element 
// in each of these structures, that which describes the shape of the 
// active volume, be one of the ROOT classes derived from TShape. In this 
// way it would be easy to have the display program display the correct 
// active ITS volumes. See the example classes AliITSgeomSPD, 
// AliITSgeomSDD, and AliITSgeomSSD for a more detailed 
// example.
////////////////////////////////////////////////////////////////////////
#include 
#include 

#include 
#include 
#include 

#include "AliITSgeomSPD.h"
#include "AliITSgeomSDD.h"
#include "AliITSgeomSSD.h"
#include "AliITSgeom.h"
#include "AliLog.h"

ClassImp(AliITSgeom)

//______________________________________________________________________
AliITSgeom::AliITSgeom():
TObject(),
fVersion("GEANT"),// Transformation version.
fTrans(0),       // Flag to keep track of which transformation 
fNmodules(0),    // The total number of modules
fNlayers(0),     // The number of layers.
fNlad(),         //[] Array of the number of ladders/layer(layer)
fNdet(),         //[] Array of the number of detector/ladder(layer)
fGm(0,0),        // Structure of translation. and rotation.
fShape(0,0)      // Array of shapes and detector information.
{
    //     The default constructor for the AliITSgeom class. It, by default,
    // sets fNlayers to zero and zeros all pointers.
    // Do not allocate anything zero everything.
    // Inputs:
    //    none.
    // Outputs:
    //    none.
    // Return:
    //    a zeroed AliITSgeom object.

    fGm.SetOwner(kTRUE);
    fShape.SetOwner(kTRUE);
    return;
}

//______________________________________________________________________
AliITSgeom::AliITSgeom(Int_t itype,Int_t nlayers,const Int_t *nlads,
                       const Int_t *ndets,Int_t mods):
TObject(),
fVersion("GEANT"),    // Transformation version.
fTrans(itype),       // Flag to keep track of which transformation 
fNmodules(mods),     // The total number of modules
fNlayers(nlayers),   // The number of layers.
fNlad(nlayers,nlads),//[] Array of the number of ladders/layer(layer)
fNdet(nlayers,ndets),//[] Array of the number of detector/ladder(layer)
fGm(mods,0),         // Structure of translation. and rotation.
fShape(5,0)          // Array of shapes and detector information.
{
    //     A simple constructor to set basic geometry class variables
    // Inputs:
    //      Int_t itype   the type of transformation kept.
    //                    bit 0 => Standard GEANT
    //                    bit 1 => ITS tracking
    //                    bit 2 => A change in the coordinate system 
    //                    has been made. others are still to be defined 
    //                    as needed.
    //      Int_t nlayers The number of ITS layers also set the size of 
    //                    the arrays
    //      Int_t *nlads  an array of the number of ladders for each 
    //                    layer. This array must be nlayers long.
    //      Int_t *ndets  an array of the number of detectors per ladder
    //                    for each layer. This array must be nlayers long.
    //      Int_t mods    The number of modules. Typically the sum of all the 
    //                    detectors on every layer and ladder.
    // Outputs:
    //     none
    // Return:
    //     A properly inilized AliITSgeom object.

    fGm.SetOwner(kTRUE);
    fShape.SetOwner(kTRUE);
    return;
}
//______________________________________________________________________
void AliITSgeom::Init(Int_t itype,Int_t nlayers,const Int_t *nlads,
                      const Int_t *ndets,Int_t mods){
    //     A simple Inilizer to set basic geometry class variables
    // Inputs:
    //      Int_t itype   the type of transformation kept.
    //                    bit 0 => Standard GEANT
    //                    bit 1 => ITS tracking
    //                    bit 2 => A change in the coordinate system 
    //                    has been made. others are still to be defined 
    //                    as needed.
    //      Int_t nlayers The number of ITS layers also set the size of 
    //                    the arrays
    //      Int_t *nlads  an array of the number of ladders for each 
    //                    layer. This array must be nlayers long.
    //      Int_t *ndets  an array of the number of detectors per ladder 
    //                    for each layer. This array must be nlayers long.
    //      Int_t mods    The number of modules. Typically the sum of all the 
    //                    detectors on every layer and ladder.
    // Outputs:
    //     none
    // Return:
    //     A properly inilized AliITSgeom object.

    fVersion  = "GEANT";     // Transformation version.
    fTrans    = itype;       // Flag to keep track of which transformation 
    fNmodules = mods;        // The total number of modules
    fNlayers  = nlayers;     // The number of layers.
    fNlad.Set(nlayers,nlads);//[] Array of the number of ladders/layer(layer)
    fNdet.Set(nlayers,ndets);//[] Array of the number of detector/ladder(layer)
    fGm.Clear();
    fGm.Expand(mods);        // Structure of translation. and rotation.
    fGm.SetOwner(kTRUE);
    fShape.Clear();
    fShape.Expand(5);         // Array of shapes and detector information.
    fShape.SetOwner(kTRUE);
    return;
}
//______________________________________________________________________
void AliITSgeom::CreateMatrix(Int_t mod,Int_t lay,Int_t lad,Int_t det,
                              AliITSDetector idet,const Double_t tran[3],
                              const Double_t rot[10]){
    // Given the translation vector tran[3] and the rotation matrix rot[1],
    // this function creates and adds to the TObject Array fGm the
    // AliITSgeomMatrix object.
    // The rot[10] matrix is set up like:
    /*   / rot[0]  rot[1]  rot[2] \
    //  |  rot[3]  rot[4]  rot[5]  |
    //   \ rot[6]  rot[7]  rot[8] /  if(rot[9]!=0) then the Identity matrix
    // is used regardless of the values in rot[0]-rot[8].
    */
    // Inputs:
    //    Int_t           mod     The module number. The location in TObjArray
    //    Int_t           lay     The layer where this module is
    //    Int_t           lad     On which ladder this module is
    //    Int_t           det     Which detector on this ladder this module is
    //    AliITSDetector idet     The type of detector see AliITSgeom.h
    //    Double_t       tran[3]  The translation vector
    //    Double_t       rot[10]  The rotation matrix.
    // Outputs:
    //    none
    // Return:
    //    none.
    Int_t id[3];
    Double_t r[3][3] = {{1.0,0.0,0.0},{0.0,1.0,0.0},{0.0,0.0,1.0}};

    if(mod<0||mod>=fGm.GetSize()){ 
	Error("CreateMatrix","mod=%d is out of bounds max value=%d",mod,
	      fGm.GetSize());
	return;
    } // end if
    delete fGm.At(mod);
    id[0] = lay; id[1] = lad; id[2] = det;
    if(rot[9]!=0.0) { // null rotation
        r[0][0] = rot[0]; r[0][1] = rot[1]; r[0][2] = rot[2];
        r[1][0] = rot[3]; r[1][1] = rot[4]; r[1][2] = rot[5];
        r[2][0] = rot[6]; r[2][1] = rot[7]; r[2][2] = rot[8];
    } // end if
    fGm.AddAt(new AliITSgeomMatrix(idet,id,r,tran),mod);
}
//______________________________________________________________________
AliITSgeom::~AliITSgeom(){
    //     The destructor for the AliITSgeom class. If the arrays fNlad,
    // fNdet, or fGm have had memory allocated to them, there pointer values
    // are non zero, then this memory space is freed and they are set
    // to zero. In addition, fNlayers is set to zero. The destruction of
    // TObjArray fShape is, by default, handled by the TObjArray destructor.
    // Inputs:
    //    none.
    // Outputs:
    //    none.
    // Return:
    //    none.

    return;
}
//______________________________________________________________________
void AliITSgeom::ReadNewFile(const char *filename){
    // It is generally preferred to define the geometry in AliITSgeom
    // directly from the GEANT geometry, see AliITSvPPRasymm.cxx for
    // and example. Under some circumstances this may not be possible.
    // This function will read in a formatted file for all of the
    // information needed to define the geometry in AliITSgeom.
    // Unlike the older file format, this file may contain comments
    // and the order of the data does not need to be completely
    // respected. A file can be created using the function WriteNewFile
    // defined below.
    // Inputs:
    //    const char *filename The file name of the file to be read in.
    // Outputs:
    //     none
    // Return:
    //     none.
    Int_t ncmd=9;
    const char *cmda[]={"Version"        ,"fTrans"  ,"fNmodules",
	                "fNlayers"       ,"fNladers","fNdetectors",
	                "fNDetectorTypes","fShape"  ,"Matrix"};
    Int_t i,j,lNdetTypes,ldet;
    char cmd[20],c;
    AliITSgeomMatrix *m=0;
    ifstream *fp=0;
    char *filtmp=0;
    Bool_t arrayGm = kFALSE, arrayShape = kFALSE;

    filtmp = gSystem->ExpandPathName(filename);
    AliInfo(Form("Reading New .det file %s",filtmp));
    fp = new ifstream(filtmp,ios::in);  // open file to write
    while(fp->get(c)!=NULL){ // for ever loop
        if(c==' ') continue; // remove blanks
        if(c=='\n') continue;
        if(c=='#' || c=='!') {while(fp->get(c)) if(c=='\n') break; continue;}
        if(c=='/'){
            fp->get(c);{
                if(c=='/') {while(fp->get(c)) if(c=='\n') break; continue;}
                if(c=='*'){
                  NotYet:
                    while(fp->get(c)) if(c=='*') break;
                    fp->get(c);{
                        if(c=='/') continue;
                        goto NotYet;
                    } //
                } // end if c=='*'
            } // end if second /
        } // end if first /
        fp->putback(c);
        *fp >> cmd;
        for(i=0;ipeek())) fp->get(); // skip spaces
	    if(isdigit(fp->peek())){ // new TString
		*fp >> j;
		fVersion.Resize(j);
		for(j=0;j> fVersion[j];
	    }else{
		fVersion.Resize(20);
		for(j=0;isprint(fp->peek())&&j<20;j++) *fp >> fVersion[j];
	    } // end if isdigit
            break;
        case 1:  // fTrans
            *fp >> fTrans;
            break;
        case 2:  // fNModules
            *fp >> fNmodules;
            fGm.Clear();
            fGm.Expand(fNmodules);
            fGm.SetOwner(kTRUE);
            arrayGm = kTRUE;
            break;
        case 3:  // fNlayers
            *fp >> fNlayers;
            fNlad.Set(fNlayers);
            fNdet.Set(fNlayers);
            break;
        case 4:  // fNladers
            for(j=0;j> fNlad[j];
            break;
        case 5:  // fNdetectors
            for(j=0;j> fNdet[j];
            break;
        case 6:  // fNDetectorTypes
            *fp >> lNdetTypes;
            fShape.Clear();
            fShape.Expand(lNdetTypes);
            fShape.SetOwner(kTRUE);
            arrayShape = kTRUE;
            break;
        case 7:  // fShape
            *fp >> ldet;
            if(!arrayShape) fShape.Expand(5);
            fShape.SetOwner(kTRUE);
            switch (ldet){
            case kSPD :{
                AliITSgeomSPD *spd = new AliITSgeomSPD();
                *fp >> *spd;
                ReSetShape(ldet,spd);
            } break;
            case kSDD : case kSDDp:{
                AliITSgeomSDD *sdd = new AliITSgeomSDD();
                *fp >> *sdd;
                ReSetShape(ldet,sdd);
            }break;
            case kSSD : case kSSDp :{
                AliITSgeomSSD *ssd = new AliITSgeomSSD();
                *fp >> *ssd;
                ReSetShape(ldet,ssd);
            }break;
            default:{
                AliError(Form("Unknown fShape type number=%d c=%c",ldet,c));
                while(fp->get(c)) if(c=='\n') break; // skip to end of line.
            }break;
            } // end switch
            break;
        case 8:  // Matrix
            *fp >> ldet;
            if(!arrayGm){
                fGm.Clear();
                fGm.Expand(2270);
                arrayGm = kTRUE;
            } // end if
	    if(ldet<0||ldet>=fGm.GetSize()){
		Error("ReadNewFile","ldet<0||ldet>=fGm.GetSize()=%d",
		      ldet,fGm.GetSize());
		return;
	    } // end if
            delete fGm.At(ldet);
            fGm.AddAt((TObject*)new AliITSgeomMatrix(),ldet);
            m = (AliITSgeomMatrix*) fGm.At(ldet);
            *fp >> *m;
            m = 0;
            break;
        default:
            AliError(Form("ReadNewFile","Data line i=%d c=%c",i,c));
            while(fp->get(c)) if(c=='\n') break; // skip this line
            break;
        } // end switch i
    } // end while
    delete fp;

    return;
}
//______________________________________________________________________
void AliITSgeom::WriteNewFile(const char *filename)const{
    // Writes AliITSgeom, AliITSgeomMatrix, and the defined 
    // AliITSgeomS*D classes to a file in a format that 
    // is more readable and commendable.
    // Inputs:
    //     const char *filename The file name of the file to be write to.
    // Outputs:
    //     none
    // Return:
    //     none
    ofstream *fp;
    Int_t i;
    char *filtmp;

    filtmp = gSystem->ExpandPathName(filename);
    fp = new ofstream(filtmp,ios::out);  // open file to write
    *fp << "//Comment lines begin with two //, one #, or one !" << endl;
    *fp << "#Blank lines are skipped including /* and */ sections." << endl;
    *fp << "!and, in principle the order of the lines is not important" <ExpandPathName(filename);
    Info("AliITSgeom","reading old .det file %s",filtmp);
    fVersion="GEANT5";
    pf = fopen(filtmp,"r");

    fNlayers = 6; // set default number of ladders
  TryAgain:
    fNlad.Set(fNlayers);
    fNdet.Set(fNlayers);
    fNmodules = 0;
    // find the number of ladders and detectors in this geometry.
    for(i=0;ilm) lm = l;
        if(l<1 || l>fNlayers) {
            printf("error in file %s layer=%d min. is 1 max is %d"
                   " Trying new format\n",filename,l,fNlayers);
            fclose(pf);
            ReadNewFile(filename);
            return;
            //continue;
        }// end if l
        fNmodules++;
        if(l<=fNlayers&&fNlad[l-1]fNlayers){
        fNlayers = lm;
        goto TryAgain;
    } // end if lm>fNlayers
    // counted the number of ladders and detectors now allocate space.
    fGm.Expand(fNmodules);
    fGm.SetOwner(kTRUE);
    fShape.SetOwner(kTRUE);

    // Set up Shapes for a default configuration of 6 layers.
    fTrans   = 0; // standard GEANT global/local coordinate system.
    // prepare to read in transforms
    lm = 0; // reuse lm as counter of modules.
    rewind(pf); // start over reading file
    while(fgets(buf,200,pf)!=NULL){ // for ever loop
        for(i=0;i<200;i++)if(buf[i]!=' '){ // remove blank spaces.
            buff = &(buf[i]);
            break;
        } // end for i
        // remove blank lines and comments.
        if(buff[0]=='\n'||buff[0]=='#'||buff[0]=='!'||
           (buff[0]=='/'&&buff[1]=='/')) continue;
        x = y = z = o = p = q = r = s = t = 0.0;
        sscanf(buff,"%d %d %d %f %f %f %f %f %f %f %f %f",
               &l,&a,&d,&x,&y,&z,&o,&p,&q,&r,&s,&t);
        if(l<1 || l>fNlayers) {
            Warning("AliITSgeom","error in file %s layer=%d"
                    " min. is 1 max is %d",filename,l,fNlayers);
            continue;
        }// end if l
        id[0] = l;id[1] = a;id[2] = d;
        tran[0] = tran[1] = tran[2]  = 0.0;
        tran[0] = (Double_t)x;tran[1] = (Double_t)y;tran[2] = (Double_t)z;
        rot6[0] = rot6[1] = rot6[2] = rot6[3] = rot6[4] = rot6[5] =0.0;
        rot6[0] = (Double_t)o;rot6[1] = (Double_t)p;rot6[2] = (Double_t)q;
        rot6[3] = (Double_t)r;rot6[4] = (Double_t)s;rot6[5] = (Double_t)t;
	if(lm<0||lm>=fGm.GetSize()){
	    Error("AliITSgeom(filename)","lm<0||lm>=fGm.GetSize()=%d",
		  lm,fGm.GetSize());
	    return;
	} // end if
        switch (l){
        case 1: case 2: // layer 1 or2 SPD
            fGm.AddAt(new AliITSgeomMatrix(rot6,kSPD,id,tran),lm++);
            break;
        case 3: case 4: // layer 3 or 4 SDD
            fGm.AddAt(new AliITSgeomMatrix(rot6,kSDD,id,tran),lm++);
            break;
        case 5: case 6: // layer 5 or 6 SSD
            fGm.AddAt(new AliITSgeomMatrix(rot6,kSSD,id,tran),lm++);
            break;
        } // end switch
    } // end while ever loop
    fclose(pf);
}
//______________________________________________________________________
AliITSgeom::AliITSgeom(const AliITSgeom &source) : 
TObject(source),
fVersion(source.fVersion), // Transformation version.
fTrans(source.fTrans),   // Flag to keep track of which transformation
fNmodules(source.fNmodules),// The total number of modules
fNlayers(source.fNlayers), // The number of layers.
fNlad(source.fNlad),    // Array of the number of ladders/layer(layer)
fNdet(source.fNdet),    // Array of the number of detector/ladder(layer)
fGm(source.fGm.GetSize(),source.fGm.LowerBound()),// Structure of 
                                                  // translation and rotation.
fShape(source.fShape.GetSize(),source.fShape.LowerBound())// Array of shapes 
                                                   // and detector information.
{
    //     The copy constructor for the AliITSgeom class. It calls the
    // = operator function. See the = operator function for more details.
    // Inputs:
    //     AliITSgeom &source  The AliITSgeom class with which to make this
    //                         a copy of.
    // Outputs:
    //     none.
    // Return:
    //     none.
    Int_t i,n;

    n = source.fGm.GetLast()+1;
    for(i=source.fGm.LowerBound();ifGm.Clear();
    this->fShape.Clear();

    this->fVersion  = source.fVersion;
    this->fTrans    = source.fTrans;
    this->fNmodules = source.fNmodules;
    this->fNlayers  = source.fNlayers;
    this->fNlad     = source.fNlad;
    this->fNdet     = source.fNdet;
    this->fGm.Expand(this->fNmodules);
    for(i=source.fGm.LowerBound();ifShape.Expand(source.fShape.GetEntriesFast());
    for(i=source.fShape.LowerBound();i=fNmodules) return -1;
    GetGeomMatrix(i)->GetIndex(id);
    if(id[0]==lay&&id[1]==lad&&id[2]==det) return i;
    // Array of modules fGm is not in expected order. Search for this index
    for(i=0;iGetIndex(id);
        if(id[0]==lay&&id[1]==lad&&id[2]==det) return i;
    } // end for i
    // This layer ladder and detector combination does not exist return -1.
    return -1;
}
//______________________________________________________________________
void AliITSgeom::GetModuleId(Int_t index,Int_t &lay,Int_t &lad,Int_t &det)
const{
    //      This routine computes the layer, ladder and detector number 
    // given the module index number. The number of ladders and detectors
    // per layer is determined when this geometry package is constructed,
    // see AliITSgeom(const char *filename) for specifics.
    // Inputs:
    //     Int_t index  The module index number, starting from zero.
    // Outputs:
    //     Int_t lay    The layer number. Starting from 1.
    //     Int_t lad    The ladder number. Starting from 1.
    //     Int_t det    The detector number. Starting from 1.
    // Return:
    //     none.
    Int_t id[3];
    AliITSgeomMatrix *g = GetGeomMatrix(index);

    if (g == 0x0){
        Error("GetModuleId","Can not get GeoMatrix for index = %d",index);
        lay = -1; lad = -1; det = -1;
    }else{
        g->GetIndex(id);
        lay = id[0]; lad = id[1]; det = id[2];
    }// End if
    return;
    // The old way kept for posterity.
/*
    Int_t i,j,k;
    j = 0;
    for(k=0;kindex)break;
    } // end for k
    lay = k+1;
    i = index -j + fNdet[k]*fNlad[k];
    j = 0;
    for(k=0;ki)break;
    } // end for k
    lad = k+1;
    det = 1+i-fNdet[lay-1]*k;
    return;
*/
}
//______________________________________________________________________
Int_t AliITSgeom::GetNDetTypes(Int_t &max)const{
    // Finds and returns the number of detector types used and the
    // maximum detector type value. Only counts id >=0 (no undefined
    // values. See AliITSgeom.h for list of AliITSDetecor enumerated types.
    // Inputs:
    //    none.
    // Outputs:
    //    The maximum detector type used
    // Return:
    //    The number of detector types used
    Int_t i,*n,id;

    max = -1;
    for(i=0;imax) max=id;
    } // end for i
    n = new Int_t[max+1];
    for(i=0;i-1)n[id]++; // note id=-1 => undefined.
    } // end for i
    id = 0;
    for(i=0;i=0 (no undefined
    // values. See AliITSgeom.h for list of AliITSDetecor enumerated types.
    // Inputs:
    //    none.
    // Outputs:
    //    The maximum detector type used
    // Return:
    //    The number of detector types used
    Int_t i,j,*n,id,max;

    max = -1;
    for(i=0;imax) max=id;
    } // end for i
    n = new Int_t[max+1];
    for(i=0;i-1)n[id]++; // note id=-1 => undefined.
    } // end for i
    id = 0;
    for(i=0;i<=max;i++) if(n[i]!=0) id++;
    maxs.Set(id);
    j = 0;
    for(i=0;i<=max;i++) if(n[i]!=0){
        maxs[j] = n[i];
        types[j++] = (AliITSDetector) i;
    } // end for i/end if
    delete[] n;
    return id;
}
//______________________________________________________________________
Int_t AliITSgeom::GetStartDet(Int_t dtype)const{
    // returns the starting module index value for a give type of detector id.
    // This assumes that the detector types are different on different layers
    // and that they are not mixed up.
    // Inputs:
    //    Int_t dtype A detector type number. 0 for SPD, 1 for SDD, 
    //                and 2 for SSD.
    // Outputs:
    //    none.
    // Return:
    //    the module index for the first occurrence of that detector type.

    switch(dtype){
    case 0:
        return GetModuleIndex(1,1,1);
        break;
    case 1:
        return GetModuleIndex(3,1,1);
        break;
    case 2:
        return GetModuleIndex(5,1,1);
        break;
    default:
        Warning("GetStartDet","undefined detector type %d",dtype);
        return 0;
    } // end switch

    Warning("GetStartDet","undefined detector type %d",dtype);
    return 0;
}
//______________________________________________________________________
Int_t AliITSgeom::GetLastDet(Int_t dtype)const{
    // returns the last module index value for a give type of detector id.
    // This assumes that the detector types are different on different layers
    // and that they are not mixed up.
    // Inputs:
    //     Int_t dtype A detector type number. 0 for SPD, 1 for SDD, 
    //                 and 2 for SSD.
    // Outputs:
    // Return:
    //     the module index for the last occurrence of that detector type.

    switch((AliITSDetector)dtype){
    case kSPD:
        return GetModuleIndex(3,1,1)-1;
        break;
    case kSDD:
        return GetModuleIndex(5,1,1)-1;
        break;
    case kSSD:
        return GetIndexMax()-1;
        break;
    case kSSDp: case kSDDp: case kND:
    default:
        Warning("GetLastDet","undefined detector type %d",dtype);
        return 0;
    } // end switch

    Warning("GetLastDet","undefined detector type %d",dtype);
    return 0;
}
//______________________________________________________________________
Bool_t AliITSgeom::IsInside(Int_t module,Double_t point[3])const{
    // Determins if the give point is inside of the module as defined
    // by this set of coordinate transforms.
    // Inputs:
    //    Int_t    module    The module to be checked
    //    Double_t point[3]  A 3 vector global point
    // Outputs:
    //    none.
    // Return:
    //    kTRUE if point is inside of module, kFALSE otherwise.
    Double_t l[3],dx,dy,dz;
    AliITSDetector idet = (AliITSDetector)(this->GetGeomMatrix(module)->
                                           GetDetectorIndex());

    this->GtoL(module,point,l);
    switch(idet){
    case kSPD:{
        AliITSgeomSPD *spd = (AliITSgeomSPD*)(fShape.At((Int_t)idet));
        dx = spd->GetDx();
        dy = spd->GetDy();
        dz = spd->GetDz();}
        break;
    case kSDD: case kSDDp:{
        AliITSgeomSDD *sdd = (AliITSgeomSDD*)(fShape.At((Int_t)idet));
        dx = sdd->GetDx();
        dy = sdd->GetDy();
        dz = sdd->GetDz();}
        break;
    case kSSD: case kSSDp:{
        AliITSgeomSSD *ssd = (AliITSgeomSSD*)(fShape.At((Int_t)idet));
        dx = ssd->GetDx();
        dy = ssd->GetDy();
        dz = ssd->GetDz();}
        break;
    default: // Detector not defined.
        return kFALSE;
        break;
    }// end switch
    if(TMath::Abs(l[0])>dx) return kFALSE;
    if(TMath::Abs(l[2])>dz) return kFALSE;
    if(TMath::Abs(l[1])>dy) return kFALSE;
    return kTRUE;
}
//______________________________________________________________________
void AliITSgeom::PrintComparison(FILE *fp,AliITSgeom *other)const{
    //     This function was primarily created for diagnostic reasons. It
    // print to a file pointed to by the file pointer fp the difference
    // between two AliITSgeom classes. The format of the file is basically,
    // define d? to be the difference between the same element of the two
    // classes. For example dfrx = this->GetGeomMatrix(i)->frx 
    // - other->GetGeomMatrix(i)->frx.
    // if(at least one of dfx0, dfy0, dfz0,dfrx,dfry,dfrz are non zero) then
    // print layer ladder detector dfx0 dfy0 dfz0 dfrx dfry dfrz
    // if(at least one of the 9 elements of dfr[] are non zero) then print
    // layer ladder detector dfr[0] dfr[1] dfr[2]
    //                       dfr[3] dfr[4] dfr[5]
    //                       dfr[6] dfr[7] dfr[8]
    // Only non zero values are printed to save space. The differences are
    // typical written to a file because there are usually a lot of numbers
    // printed out and it is usually easier to read them in some nice editor
    // rather than zooming quickly past you on a screen. fprintf is used to
    // do the printing. The fShapeIndex difference is not printed at this time.
    // Inputs:
    //    FILE *fp           A file pointer to an opened file for writing 
    //                       in which the results of the comparison will 
    //                       be written.
    //    AliITSgeom *other  The other AliITSgeom class to which this one is
    //                       being compared.
    // Outputs:
    //    none.
    // Return:
    //    none.
    Int_t    i,j,idt[3],ido[3];
    Double_t tt[3],to[3];  // translation
    Double_t rt[3],ro[3];  // phi in radians
    Double_t mt[3][3],mo[3][3]; // matrices
    AliITSgeomMatrix *gt,*go;
    Bool_t   t;

    for(i=0;ifNmodules;i++){
        gt  =  this->GetGeomMatrix(i);
        go  = other->GetGeomMatrix(i);
        gt->GetIndex(idt);
        go->GetIndex(ido);
        t = kFALSE;
        for(i=0;i<3;i++) t = t&&idt[i]!=ido[i];
        if(t) fprintf(fp,"%4.4d %1.1d %2.2d %2.2d %1.1d %2.2d %2.2d\n",i,
                      idt[0],idt[1],idt[2],ido[0],ido[1],ido[2]);
        gt->GetTranslation(tt);
        go->GetTranslation(to);
        gt->GetAngles(rt);
        go->GetAngles(ro);
        t = kFALSE;
        for(i=0;i<3;i++) t = t&&tt[i]!=to[i];
        if(t) fprintf(fp,"%1.1d %2.2d %2.2d dTrans=%f %f %f drot=%f %f %f\n",
                      idt[0],idt[1],idt[2],
                      tt[0]-to[0],tt[1]-to[1],tt[2]-to[2],
                      rt[0]-ro[0],rt[1]-ro[1],rt[2]-ro[2]);
        t = kFALSE;
        gt->GetMatrix(mt);
        go->GetMatrix(mo);
        for(i=0;i<3;i++)for(j=0;j<3;j++)  t = mt[i][j] != mo[i][j];
        if(t){
            fprintf(fp,"%1.1d %2.2d %2.2d dfr= %e %e %e\n",
                    idt[0],idt[1],idt[2],
                    mt[0][0]-mo[0][0],mt[0][1]-mo[0][1],mt[0][2]-mo[0][2]);
            fprintf(fp,"        dfr= %e %e %e\n",
                    mt[1][0]-mo[1][0],mt[1][1]-mo[1][1],mt[1][2]-mo[1][2]);
            fprintf(fp,"        dfr= %e %e %e\n",
                    mt[2][0]-mo[2][0],mt[2][1]-mo[2][1],mt[2][2]-mo[2][2]);
        } // end if t
    } // end for i
    return;
}
//______________________________________________________________________
void AliITSgeom::PrintData(FILE *fp,Int_t lay,Int_t lad,Int_t det)const{
    //     This function prints out the coordinate transformations for
    // the particular detector defined by layer, ladder, and detector
    // to the file pointed to by the File pointer fp. fprintf statements
    // are used to print out the numbers. The format is
    // layer ladder detector Trans= fx0 fy0 fz0 rot= frx fry frz 
    // Shape=fShapeIndex
    //                         dfr= fr[0] fr[1] fr[2]
    //                         dfr= fr[3] fr[4] fr[5]
    //                         dfr= fr[6] fr[7] fr[8]
    // By indicating which detector, some control over the information 
    // is given to the user. The output it written to the file pointed
    // to by the file pointer fp. This can be set to stdout if you want.
    // Inputs:
    //     FILE *fp           A file pointer to an opened file for 
    //                        writing in which the results of the 
    //                        comparison will be written.
    //     Int_t lay          The layer number. Starting from 1.
    //     Int_t lad          The ladder number. Starting from 1.
    //     Int_t det          The detector number. Starting from 1.
    // Outputs:
    //     none
    // Return:
    //     none.
    AliITSgeomMatrix *gt;
    Double_t t[3],r[3],m[3][3];

    gt = this->GetGeomMatrix(GetModuleIndex(lay,lad,det));
    gt->GetTranslation(t);
    gt->GetAngles(r);
    fprintf(fp,"%1.1d %2.2d %2.2d Trans=%f %f %f rot=%f %f %f Shape=%d\n",
            lay,lad,det,t[0],t[1],t[2],r[0],r[1],r[2],
            gt->GetDetectorIndex());
    gt->GetMatrix(m);
    fprintf(fp,"        dfr= %e %e %e\n",m[0][0],m[0][1],m[0][2]);
    fprintf(fp,"        dfr= %e %e %e\n",m[1][0],m[1][1],m[1][2]);
    fprintf(fp,"        dfr= %e %e %e\n",m[2][0],m[2][1],m[2][2]);
    return;
}
//______________________________________________________________________
void AliITSgeom::PrintGeom(ostream *wb)const{
    //     Stream out an object of class AliITSgeom to standard output.
    // Intputs:
    //     ofstream *wb    The output streaming buffer.
    // Outputs:
    //     none.
    // Return:
    //     none.
    Int_t i,nshapes;

    wb->setf(ios::scientific);
    *wb << fTrans << " ";
    *wb << fNmodules << " ";
    *wb << fNlayers << " ";
    for(i=0;i> fTrans >> fNmodules >> fNlayers;
    fNlad.Set(fNlayers);
    fNdet.Set(fNlayers);
    for(i=0;i> fNlad[i];
    for(i=0;i> fNdet[i];
    fGm.Expand(fNmodules);
    fGm.SetOwner(kTRUE);
    for(i=0;i=fGm.GetSize()){
	    Error("ReadGeom","i<0||i>=fGm.GetSize()=%d",
		  i,fGm.GetSize());
	    return;
	} // end if
        fGm.AddAt(new AliITSgeomMatrix,i);
        *rb >> *(GetGeomMatrix(i));
    } // end for i
    *rb >> i;
    fShape.Expand(i);
    fShape.SetOwner(kTRUE);
    for(i=0;i> j;
        switch (j){
        case kSPD:{
            AliITSgeomSPD *s = new AliITSgeomSPD();
            *rb >> *s;
            fShape.AddAt(s,kSPD);}
            break;
        case kSDD:{
            AliITSgeomSDD *s = new AliITSgeomSDD();
            *rb >> *s;
            fShape.AddAt(s,kSDD);}
            break;
        case kSSD:{
            AliITSgeomSSD *s = new AliITSgeomSSD();
            *rb >> *s;
            fShape.AddAt(s,kSSD);}
            break;
        case kSSDp:{
            AliITSgeomSSD *s = new AliITSgeomSSD();
            *rb >> *s;
            fShape.AddAt(s,kSSDp);}
            break;
        case kSDDp:{
            AliITSgeomSDD *s = new AliITSgeomSDD();
            *rb >> *s;
            fShape.AddAt(s,kSDDp);}
            break;
        } // end  switch
    } //  end for i
    return;
}
//______________________________________________________________________
//     The following routines modify the transformation of "this"
// geometry transformations in a number of different ways.
//______________________________________________________________________
void AliITSgeom::GlobalChange(const Float_t *tran,const Float_t *rot){
    //     This function performs a Cartesian translation and rotation of
    // the full ITS from its default position by an amount determined by
    // the three element arrays tran and rot. If every element
    // of tran and rot are zero then there is no change made
    // the geometry. The change is global in that the exact same translation
    // and rotation is done to every detector element in the exact same way.
    // The units of the translation are those of the Monte Carlo, usually cm,
    // and those of the rotation are in radians. The elements of tran
    // are tran[0] = x, tran[1] = y, and tran[2] = z.
    // The elements of rot are rot[0] = rx, rot[1] = ry, and
    // rot[2] = rz. A change in x will move the hole ITS in the ALICE
    // global x direction, the same for a change in y. A change in z will
    // result in a translation of the ITS as a hole up or down the beam line.
    // A change in the angles will result in the inclination of the ITS with
    // respect to the beam line, except for an effective rotation about the
    // beam axis which will just rotate the ITS as a hole about the beam axis.
    // Intputs:
    //     Float_t *tran   A 3 element array representing the global 
    //                     translations. the elements are x,y,z in cm.
    //     Float_t *rot    A 3 element array representing the global rotation
    //                     angles about the three axis x,y,z in radians
    // Outputs:
    //     none.
    // Return:
    //     none.
    Int_t    i,j;
    Double_t t[3],r[3];
    AliITSgeomMatrix *g;

    fTrans = (fTrans && 0xfffd) + 2;  // set bit 1 true.
    for(i=0;iGetGeomMatrix(i);
        g->GetTranslation(t);
        g->GetAngles(r);
        for(j=0;j<3;j++){
            t[j] += tran[j];
            r[j] += rot[j];
        } // end for j
        g->SetTranslation(t);
        g->SetAngles(r);
    } // end for i
    return;
}
//______________________________________________________________________
void AliITSgeom::GlobalCylindericalChange(const Float_t *tran,
					  const Float_t *rot){
    //     This function performs a cylindrical translation and rotation of
    // each ITS element by a fixed about in radius, rphi, and z from its
    // default position by an amount determined by the three element arrays
    // tran and rot. If every element of tran and
    // rot are zero then there is no change made the geometry. The
    // change is global in that the exact same distance change in translation
    // and rotation is done to every detector element in the exact same way.
    // The units of the translation are those of the Monte Carlo, usually cm,
    // and those of the rotation are in radians. The elements of tran
    // are tran[0] = r, tran[1] = rphi, and tran[2] = z.
    // The elements of rot are rot[0] = rx, rot[1] = ry, and
    // rot[2] = rz. A change in r will results in the increase of the
    // radius of each layer by the same about. A change in rphi will results in
    // the rotation of each layer by a different angle but by the same
    // circumferential distance. A change in z will result in a translation
    // of the ITS as a hole up or down the beam line. A change in the angles
    // will result in the inclination of the ITS with respect to the beam
    // line, except for an effective rotation about the beam axis which will
    // just rotate the ITS as a hole about the beam axis.
    // Intputs:
    //     Float_t *tran   A 3 element array representing the global 
    //                     translations. the elements are r,theta,z in 
    //                     cm/radians.
    //     Float_t *rot    A 3 element array representing the global rotation
    //                     angles about the three axis x,y,z in radians
    // Outputs:
    //     none.
    // Return:
    //     none.
    Int_t    i,j;
    Double_t t[3],ro[3],r,r0,phi,rphi;
    AliITSgeomMatrix *g;

    fTrans = (fTrans && 0xfffd) + 2;  // set bit 1 true.
    for(i=0;iGetGeomMatrix(i);
        g->GetTranslation(t);
        g->GetAngles(ro);
        r = r0= TMath::Hypot(t[1],t[0]);
        phi   = TMath::ATan2(t[1],t[0]);
        rphi  = r0*phi;
        r    += tran[0];
        rphi += tran[1];
        phi   = rphi/r0;
        t[0]  = r*TMath::Cos(phi);
        t[1]  = r*TMath::Sin(phi);
        t[2] += tran[2];
        for(j=0;j<3;j++){
            ro[j] += rot[j];
        } // end for j
        g->SetTranslation(t);
        g->SetAngles(ro);
    } // end for i
    return;
}
//______________________________________________________________________
void AliITSgeom::RandomChange(const Float_t *stran,const Float_t *srot){
    //     This function performs a Gaussian random displacement and/or
    // rotation about the present global position of each active
    // volume/detector of the ITS. The sigma of the random displacement
    // is determined by the three element array stran, for the
    // x y and z translations, and the three element array srot,
    // for the three rotation about the axis x y and z.
    // Intputs:
    //     Float_t *stran  A 3 element array representing the global 
    //                     translations variances. The elements are x,
    //                     y,z in cm.
    //     Float_t *srot   A 3 element array representing the global rotation
    //                     angles variances about the three axis x,y,z in 
    //                     radians.
    // Outputs:
    //     none.
    // Return:
    //     none.
    Int_t    i,j;
    Double_t t[3],r[3];
    AliITSgeomMatrix *g;

    fTrans = (fTrans && 0xfffd) + 2;  // set bit 1 true.
    for(i=0;iGetGeomMatrix(i);
        g->GetTranslation(t);
        g->GetAngles(r);
        for(j=0;j<3;j++){
            t[j] += gRandom->Gaus(0.0,stran[j]);
            r[j] += gRandom->Gaus(0.0, srot[j]);
        } // end for j
        g->SetTranslation(t);
        g->SetAngles(r);
    } // end for i
    return;
}
//______________________________________________________________________
void AliITSgeom::RandomCylindericalChange(const Float_t *stran,
					  const Float_t *srot){
    //     This function performs a Gaussian random displacement and/or
    // rotation about the present global position of each active
    // volume/detector of the ITS. The sigma of the random displacement
    // is determined by the three element array stran, for the
    // r rphi and z translations, and the three element array srot,
    // for the three rotation about the axis x y and z. This random change
    // in detector position allow for the simulation of a random uncertainty
    // in the detector positions of the ITS.
    // Intputs:
    //     Float_t *stran  A 3 element array representing the global 
    //                     translations variances. The elements are r,
    //                     theta,z in cm/radians.
    //     Float_t *srot   A 3 element array representing the global rotation
    //                     angles variances about the three axis x,y,z in 
    //                     radians.
    // Outputs:
    //     none.
    // Return:
    //     none.
    Int_t    i,j;
    Double_t t[3],ro[3],r,r0,phi,rphi;
    TRandom ran;
    AliITSgeomMatrix *g;

    fTrans = (fTrans && 0xfffd) + 2;  // set bit 1 true.
    for(i=0;iGetGeomMatrix(i);
        g->GetTranslation(t);
        g->GetAngles(ro);
        r = r0= TMath::Hypot(t[1],t[0]);
        phi   = TMath::ATan2(t[1],t[0]);
        rphi  = r0*phi;
        r    += ran.Gaus(0.0,stran[0]);
        rphi += ran.Gaus(0.0,stran[1]);
        phi   = rphi/r0;
        t[0]  = r*TMath::Cos(phi);
        t[1]  = r*TMath::Sin(phi);
        t[2] += ran.Gaus(0.0,stran[2]);
        for(j=0;j<3;j++){
            ro[j] += ran.Gaus(0.0, srot[j]);
        } // end for j
        g->SetTranslation(t);
        g->SetAngles(ro);
    } // end for i
    return;
}
//______________________________________________________________________
void AliITSgeom::GeantToTracking(const AliITSgeom &source){
    //     Copy the geometry data but change it to go between the ALICE
    // Global coordinate system to that used by the ITS tracking. A slightly
    // different coordinate system is used when tracking. This coordinate 
    // system is only relevant when the geometry represents the cylindrical
    // ALICE ITS geometry. For tracking the Z axis is left alone but X-> -Y
    // and Y-> X such that X always points out of the ITS cylinder for every
    // layer including layer 1 (where the detectors are mounted upside down).
    //Begin_Html
    /*
      
    */
    //End_Html
    // Input:
    //     AliITSgeom &source  The AliITSgeom class with which to make this
    //                         a copy of.
    // Output:
    //     none.
    // Return:
    //     none.
    Int_t    i,j,k,l,id[3];
    Double_t r0[3][3],r1[3][3];
    Double_t a0[3][3] = {{0.,+1.,0.},{-1.,0.,0.},{0.,0.,+1.}};
    Double_t a1[3][3] = {{0.,-1.,0.},{+1.,0.,0.},{0.,0.,+1.}};

    *this = source;  // copy everything
    for(i=0;iGetIndex(id);
        GetGeomMatrix(i)->GetMatrix(r0);
        if(id[0]==1){ // Layer 1 is treated different from the others.
            for(j=0;j<3;j++) for(k=0;k<3;k++){
                r1[j][k] = 0.;
                for(l=0;l<3;l++) r1[j][k] += a0[j][l]*r0[l][k];
            } // end for j,k
        }else{
            for(j=0;j<3;j++) for(k=0;k<3;k++){
                r1[j][k] = 0.;
                for(l=0;l<3;l++) r1[j][k] += a1[j][l]*r0[l][k];
            } // end for j,k
        } // end if
        GetGeomMatrix(i)->SetMatrix(r1);
    } // end for i
    this->fTrans = (this->fTrans && 0xfffe) + 1;  // set bit 0 true.
    return;
}
//______________________________________________________________________
Int_t AliITSgeom::GetNearest(const Double_t g[3],Int_t lay)const{
    //      Finds the Detector (Module) that is nearest the point g [cm] in
    // ALICE Global coordinates. If layer !=0 then the search is restricted
    // to Detectors (Modules) in that particular layer.
    // Inputs:
    //     Double_t g[3]  The ALICE Cartesian global coordinate from which the
    //                    distance is to be calculated with.
    //     Int_t lay      The layer to restrict the search to. If layer=0 then
    //                    all layers are searched. Default is lay=0.
    // Output:
    //     none.
    // Return:
    //     The module number representing the nearest module.
    Int_t    i,l,a,e,in=0;
    Double_t d,dn=1.0e10;
    Bool_t   t=lay!=0; // skip if lay = 0 default value check all layers.

    for(i=0;iDistance2(g))Distance2(g);
            if(da;e--){dn[e] = dn[e-1];in[e] = in[e-1];}
                dn[a] = d; in[a] = i;
            } // end if dGetDx();
		dl[1] = ((AliITSgeomSPD*)GetShape(idet))->GetDy();
		dl[2] = ((AliITSgeomSPD*)GetShape(idet))->GetDz();
	    } break;
	    case kSDD: case kSDDp:{
		dl[0] = ((AliITSgeomSDD*)GetShape(idet))->GetDx();
		dl[1] = ((AliITSgeomSDD*)GetShape(idet))->GetDy();
		dl[2] = ((AliITSgeomSDD*)GetShape(idet))->GetDz();
	    } break;
	    case kSSD: case kSSDp:{
		dl[0] = ((AliITSgeomSSD*)GetShape(idet))->GetDx();
		dl[1] = ((AliITSgeomSSD*)GetShape(idet))->GetDy();
		dl[2] = ((AliITSgeomSSD*)GetShape(idet))->GetDz();
	    } break;
	    case kND:{
		Warning("GetAverageRadiusOfLayer",
			"idet=kND undefined detector type");
		continue;
	    }break;
	    default:{
		Warning("GetAverageRadiusOfLayer",
			"idet=%d not a defined value",(Int_t)idet);
		continue;
	    }break;
	    }// end switch.
        } // end of
        n++;
        GetTransCyln(i,t);
        rp = t[0];
        r += rp;
        if(rmin>rp) rmin = rp;
        if(rmax3) l[2] = -dl[2];
            LtoG(i,l,t);
            rp = TMath::Sqrt(t[0]*t[0]+t[1]*t[1]);
            if(rmin>rp) rmin = rp;
            if(rmax>(istream &is,AliITSgeom &r){
    // Standard input streaming function.
    // Inputs:
    //   istream    is  The input stream
    //   AliITSgeom p   The AliITSgeom class to be filled from this 
    //                  input stream
    // Outputs:
    //   none.
    // Return:
    //   The input stream

    r.ReadGeom(&is);
    return is;
}
//----------------------------------------------------------------------