Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:10:36

0001 #include<string>
0002 //#include<vector>
0003 #include <sstream>
0004 std::string IntToString(int num)
0005  {
0006    std::ostringstream myStream; //creates an ostringstream object
0007    myStream << num << std::flush;
0008 
0009   /*
0010    * outputs the number into the string stream and then flushes
0011    * the buffer (makes sure the output is put into the stream)
0012    */
0013 
0014    return(myStream.str()); //returns the string form of the stringstream object
0015  }
0016 
0017 // 
0018 // File H4Geom.cxx
0019 //
0020 /*! \class H4Geom
0021  * \brief A helper class with geometry information of the super module
0022  *
0023  * Author: Giovanni Franzoni
0024  * Crystal numbering schemes during automn 2004 (SM10):
0025  * - <b>Conventions</b>
0026  *   SM Crystal Number range is [1, 1700]
0027  *   SM Tower Number range is [1, 68]
0028  *   eta range is [0, 84]
0029  *   phi range is [0, 19]
0030  * - <b>Crystal Number in Readout-Order</b>
0031  *   Crystal numbering in readout order is very similar to 2003 with two
0032  *   different orders according to the LVRB position (right or left) on the
0033  *   trigger tower.
0034  *   \verbatim
0035  *                  <- eta
0036  *   +--+--+--+--+--+      +--+--+--+--+--+
0037  *   | 4| 5|14|15|24|      |20|19|10| 9| 0|
0038  *   +--+--+--+--+--+      +--+--+--+--+--+
0039  *   | 3| 6|13|16|23|      |21|18|11| 8| 1|
0040  *   +--+--+--+--+--+      +--+--+--+--+--+  ||
0041  *   | 2| 7|12|17|22|      |22|17|12| 7| 2|  || phi
0042  *   +--+--+--+--+--+      +--+--+--+--+--+  \/
0043  *   | 1| 8|11|18|21|      |23|16|12| 6| 3| 
0044  *   +--+--+--+--+--+      +--+--+--+--+--+
0045  *   | 0| 9|10|19|20|      |24|15|14| 5| 4| 
0046  *   +--+--+--+--+--+      +--+--+--+--+--+
0047  *      left tower            right tower
0048  *   \endverbatim
0049  *   In order to know if a trigger tower (from 1 -> 68) is right or left, the
0050  *   following logic can be applied:
0051  *     if ((smTower - 1)/4 < 3 || ((smTower - 1)/4 - 3)%4 >= 2)         
0052  *       left tower
0053  *     else
0054  *       right tower
0055  * - <b>Super Module Crystal Number</b> 
0056  *   Organization of crystals in the lines of a supermodule has been changed
0057  *   in 2004:
0058  *   \verbatim
0059  *(i = 84, j = 0)          <- eta               (i = 0, j = 0)
0060  *      +----+----+     +----+----+----+----+----+----+
0061  *      |1681|1661| ... | 101|  81|  61|  41|  21|   1|
0062  *      +----+----+     +----+----+----+----+----+----+
0063  *      |1682|1662| ... | 102|  82|  62|  42|  22|   2|
0064  *      +----+----+     +----+----+----+----+----+----+  
0065  *      ...                                              ||      |
0066  *      +----+----+     +----+----+----+----+----+----+  || phi  |
0067  *      |1698|1678| ... | 118|  98|  78|  58|  38|  18|  \/      |t
0068  *      +----+----+     +----+----+----+----+----+----+          |o
0069  *      |1699|1679| ... | 119|  99|  79|  59|  39|  19|          |w
0070  *      +----+----+     +----+----+----+----+----+----+          |e
0071  *      |1700|1680| ... | 120| 100|  80|  60|  40|  20|          |r
0072  *      +----+----+     +----+----+----+----+----+----+          |
0073  *(i = 84, j = 19)                              (i = 0, j = 19)  
0074  *                           --------- tower ----------
0075  *   \endverbatim
0076  *   smCrystalNumber is obtained from i and j:
0077  *     smCrystalNumber = i*5*4 + j + 1
0078  *   conversly:
0079  *     i = (smCrystalNumber - 1)/(5*4)
0080  *     j = (smCrystalNumber - 1)%(5*4)
0081  *
0082  *   the logic to determine i and j from smTower and crystal readout number is:
0083  *     if (tower is left)
0084  *       i = (smTower - 1)/4 * 5 + (24 - crystal)/5
0085  *     else
0086  *       i = (smTower - 1)/4 * 5 + crystal/5
0087  *     if (tower is left && (crystal/5)%2 = 0 || 
0088  *         tower is right && (crystal/5)%2 = 1)
0089  *       j = (smTower - 1)%4 * 5 + 4 - crystal%5
0090  *     else
0091  *       j = (smTower - 1)%4 * 5 + crystal%5
0092  *   conversly
0093  *     smTower = i/5 * 4 + j/5 + 1
0094  *     if (tower is left)
0095  *       if ((i%5)%2 = 0)
0096  *         crystal = (4 - i%5)*5 + 4 - j%5
0097  *       else
0098  *         crystal = (4 - i%5)*5 + j%5
0099  *     else
0100  *       if ((i%5)%2 = 0)
0101  *         crystal = i%5 * 5 + j%5
0102  *       else
0103  *         crystal = i%5 * 5 + 4 - j%5 
0104  *
0105  *
0106  * Crystal numbering schemes in 2003:
0107  * - <b>Crystal Number in Readout-Order</b>
0108  *   The data on the RRF files contain the crystal information in
0109  *   readout order. The physical position of the crystals in readout
0110  *   order depends then on the VFE-Module and Tower-Number. There
0111  *   exist two different kinds of towers, one where the low voltage
0112  *   board sits on the left side, and one where the board sits on the
0113  *   right side. The following scheme shows the position in eta and
0114  *   phi of the crystals given their readout crystal number: 
0115  *   \verbatim
0116  *                  <- eta
0117  *   +--+--+--+--+--+      +--+--+--+--+--+
0118  *   | 4| 5|14|15|24|      |20|19|10| 9| 0|
0119  *   +--+--+--+--+--+      +--+--+--+--+--+
0120  *   | 3| 6|13|16|23|      |21|18|11| 8| 1|
0121  *   +--+--+--+--+--+      +--+--+--+--+--+  ^
0122  *   | 2| 7|12|17|22|      |22|17|12| 7| 2|  | phi
0123  *   +--+--+--+--+--+      +--+--+--+--+--+  |
0124  *   | 1| 8|11|18|21|      |23|16|12| 6| 3| 
0125  *   +--+--+--+--+--+      +--+--+--+--+--+
0126  *   | 0| 9|10|19|20|      |24|15|14| 5| 4| 
0127  *   +--+--+--+--+--+      +--+--+--+--+--+
0128  *      left tower            right tower
0129  *   \endverbatim
0130  *   <b>If in this documentation a crystal number is mentioned, then by
0131  *   default, the readout number is meant. </b>
0132  * - <b>Super Module Crystal Number</b> 
0133  *   Organization of crystals in the lines of a supermodule:
0134  *   \verbatim
0135  *                 <- eta
0136  *      +----+----+     +----+----+----+----+----+----+
0137  *      |1699|1698| ... |1620|1919|1618|1617|1616|1615|
0138  *      +----+----+     +----+----+----+----+----+----+
0139  *      |1614|1613| ... |1535|1534|1533|1532|1531|1530|
0140  *      +----+----+     +----+----+----+----+----+----+  ^
0141  *      ...                                              | phi  |
0142  *      +----+----+     +----+----+----+----+----+----+  |      |
0143  *      | 254| 253| ... | 175| 174| 173| 172| 171| 170|         |t
0144  *      +----+----+     +----+----+----+----+----+----+         |o
0145  *      | 169| 168| ... |  90|  89|  88|  87|  86|  85|         |w
0146  *      +----+----+     +----+----+----+----+----+----+         |e
0147  *      |  84|  83| ... |   5|   4|   3|   2|   1|   0|         |r
0148  *      +----+----+     +----+----+----+----+----+----+         |
0149  *
0150  *                           --------- tower ----------
0151  *   \endverbatim
0152  *   The above numbering scheme schows the numbers of a crystal in the
0153  *   super module (SM). The sm-crystal-number allows to uniquely
0154  *   identify the crystal in the H4 test-beams since only one SM is put
0155  *   into the beam at a time. The sm-crystal-number allows navigation
0156  *   across the boarders of the towers and is used on the ERF level by
0157  *   void H4RecEnergy::getCrystal(H4RecXtal * oneXtal, int smCrystal).
0158  * - <b>Crystal Number in Geometrical Order</b>
0159  *   The geometrical crystal number within a tower reflects the
0160  *   physical position of a crystal and is therefore used on the ERF
0161  *   level where higher level information is of interest. The
0162  *   geometrical ordering counts crystals as:
0163  *   \verbatim
0164  *        <- eta
0165  *   +--+--+--+--+--+
0166  *   |24|19|14| 9| 4|
0167  *   +--+--+--+--+--+
0168  *   |23|18|13| 8| 3|  ^
0169  *   +--+--+--+--+--+  | phi
0170  *   |22|17|12| 7| 2|  |
0171  *   +--+--+--+--+--+ 
0172  *   |21|16|11| 6| 1| 
0173  *   +--+--+--+--+--+ 
0174  *   |20|15|10| 5| 0| 
0175  *   +--+--+--+--+--+ 
0176  *   \endverbatim
0177  *   This numbering scheme is offered by 
0178  *   void H4RecEnergy::getTower(int towerNb, H4RecXtal * tower[])
0179  *
0180  * The H4Geom class is providing methods to convert these numbers into
0181  * each other.
0182 */
0183 
0184 #include "./Geom.h"
0185 #include <iostream>
0186 
0187 using namespace std;
0188 
0189 const int H4Geom::crystalChannelMap[5][5] = {
0190   { 4, 5, 14, 15, 24},
0191   { 3, 6, 13, 16, 23},
0192   { 2, 7, 12, 17, 22},
0193   { 1, 8, 11, 18, 21},
0194   { 0, 9, 10, 19, 20}
0195 };
0196 
0197 const int H4Geom::crystalMap[25] = {
0198   340, 255, 170,  85,   0,
0199     1,  86, 171, 256, 341,
0200   342, 257, 172,  87,   2,
0201     3,  88, 173, 258, 343,
0202   344, 259, 174,  89,   4
0203 };
0204 const int H4Geom::WhichHalf[69] = {
0205   0, // TT 0 does not exist 
0206   1,1,1,1,
0207   2,2,1,1,
0208   2,2,1,1,
0209   2,2,1,1,
0210   2,2,1,1,
0211   2,2,1,1,
0212   2,2,1,1,
0213   2,2,1,1,
0214   2,2,1,1,
0215   2,2,1,1,
0216   2,2,1,1,
0217   2,2,1,1,
0218   2,2,1,1,
0219   2,2,1,1,
0220   2,2,1,1,
0221   2,2,1,1,
0222   2,2,1,1};
0223 
0224 
0225 H4Geom::GeomPeriod_t H4Geom::geometry_ = H4Geom::Undef;
0226 
0227 // initializes geometry since we always use Automn2004
0228 // (previously done in init() )
0229 H4Geom::H4Geom()
0230 { 
0231   GeomPeriod_t ForEcalMonitoring;    ForEcalMonitoring = Automn2004;
0232   H4Geom::SetGeomPeriod(ForEcalMonitoring);
0233 }
0234 
0235 //! does nothing
0236 H4Geom::~H4Geom()
0237 { }
0238 
0239 //! Initialize geometry with config file
0240 bool H4Geom::init()
0241 {
0242   //   if (gConfigParser->isDefined("Geometry::Period"))
0243   //     geometry_ = H4Geom::GeomPeriod_t(gConfigParser->
0244   //                     readIntOption("Geometry::Period"));
0245   //   else
0246   //     return false;
0247   
0248   // initialization of period moved to constructor, since we always use Automn2004
0249   //   GeomPeriod_t ForEcalMonitoring;    ForEcalMonitoring = Automn2004;
0250   //   H4Geom::SetGeomPeriod(ForEcalMonitoring);
0251   return true;
0252 }
0253 
0254 //! Retuns the crystal number in the super module for a given
0255 //! tower number in the super module and crystal number in the tower
0256 int H4Geom::getSMCrystalNumber(int tower, int crystal) const 
0257 {
0258   if (!IsGeomPeriodDefined()) 
0259     {cout << "[H4Geom] geometry period not defined, aborting.\t (should be  ForEcalMonitoring = Automn2004;)" << endl;
0260       abort();}
0261 
0262   if (geometry_ == H4Geom::Spring2004) {
0263     int smCrystalNbr = 0;
0264     if ((crystal/5)%2 == 0)
0265       smCrystalNbr = kCrystalsPerTower - 
0266     int(crystal/kCardsPerTower)*kChannelsPerCard - 
0267     crystal%kChannelsPerCard + (tower - 1)*kCrystalsPerTower;
0268     else
0269       smCrystalNbr = kCrystalsPerTower + 1 - 
0270     (int(crystal/kCardsPerTower) + 1)*kChannelsPerCard + 
0271     crystal%kChannelsPerCard + (tower - 1)*kCrystalsPerTower;
0272     return smCrystalNbr;
0273   } else if (geometry_ == H4Geom::Automn2004) {
0274     int eta = (tower - 1)/kTowersInPhi*kCardsPerTower;
0275     int phi = (tower - 1)%kTowersInPhi*kChannelsPerCard;
0276     if (rightTower(tower))
0277       eta += crystal/kCardsPerTower;
0278     else
0279       eta += (kCrystalsPerTower - 1 - crystal)/kCardsPerTower;
0280     if (rightTower(tower) && (crystal/kCardsPerTower)%2 == 1 ||
0281     !rightTower(tower) && (crystal/kCardsPerTower)%2 == 0)
0282       phi += (kChannelsPerCard - 1 - crystal%kChannelsPerCard);
0283     else
0284       phi += crystal%kChannelsPerCard;
0285     return eta*kChannelsPerCard*kTowersInPhi + phi + 1;
0286   } else {
0287     int towerId = tower - 1;
0288     int line = towerId%4;
0289     int column = towerId/4;
0290     int lowerRight = 5*line*85 + column*5;
0291     if (rightTower(tower))
0292       return lowerRight+crystalMap[crystal];
0293     else
0294       return lowerRight+crystalMap[24-crystal];
0295   }
0296 }
0297 
0298 
0299 //! Retuns the crystal number in the super module for a given
0300 //! tower number in the super module and crystal number in the tower
0301 int H4Geom::getSMCrystalNumber(int tower, int strip_id, int crystal_id) const {
0302   if (
0303       !(0< strip_id && strip_id <6
0304     && 0< crystal_id && crystal_id <6)
0305       )    {
0306     cout << "[H4geom] invalid strip_id or crystal_id; ";
0307     cout << "strip= "<<strip_id << " crystal_id= " << crystal_id << endl ;
0308     //    abort();
0309     return -1;
0310   }
0311   else
0312     {
0313       //      cout << "[H4Geom][getSMCrystalNumber] doing nothing for now" << endl;
0314       //       strip_id and crystal_id --> {1,2,3,4,5}
0315       //       crystal_id = 5 - crystal_id + 1;
0316       //       int  crystalInTower = 5*(strip_id-1) + crystal_id-1 ;
0317       int  crystalInTower = 5*(strip_id-1) + crystal_id -1;
0318       //      cout << "[H4geom][debug] crystalInTower is: " << crystalInTower << endl;
0319       return 
0320     H4Geom::getSMCrystalNumber(tower, crystalInTower); // should be ok for TT right
0321     }
0322 }
0323 
0324 
0325 //! Retuns the crystal number in the super module for a given
0326 //! tower number in the super module and crystal number in the tower
0327 void H4Geom::getTowerStripChannelNumber(int& tower, int& strip_id, int& crystal_id, int sm_num) const {
0328   int CryNum;
0329   getTowerCrystalNumber(tower,CryNum,sm_num);
0330   strip_id   = CryNum/5 + 1;
0331   crystal_id = CryNum%5 + 1;
0332 }
0333 
0334 
0335 
0336 
0337 //! Returns the crystal number in a tower for a given
0338 //! crystal number in the super module
0339 void H4Geom::getTowerCrystalNumber(int &tower, int &crystal, int smCrystal) const 
0340 {
0341   if (!IsGeomPeriodDefined()) 
0342     {cout << "[H4Geom] geometry period not defined, aborting.\t (should be  ForEcalMonitoring = Automn2004;)" << endl;
0343       abort();}
0344   if (geometry_ == H4Geom::Spring2004) {
0345     // We do not know where the supercrystal is...
0346     tower = (smCrystal - 1)/kCrystalsPerTower + 1; 
0347     smCrystal -= (tower - 1)*kCrystalsPerTower;
0348     if (((smCrystal - 1)/kCardsPerTower)%2 == 0)
0349       crystal = (kCardsPerTower - 
0350          int((smCrystal - 1)/kCardsPerTower))*kCardsPerTower - 
0351                 (smCrystal - 1)%kCardsPerTower - 1;
0352     else
0353       crystal = (kCardsPerTower - 1 - 
0354          int((smCrystal - 1)/kCardsPerTower))*kCardsPerTower + 
0355                 (smCrystal - 1)%kCardsPerTower;
0356     return;
0357   } else if (geometry_ == H4Geom::Automn2004) {
0358     int eta = (smCrystal - 1)/(kChannelsPerCard*kTowersInPhi);
0359     int phi = (smCrystal - 1)%(kChannelsPerCard*kTowersInPhi);
0360     tower = eta/kCardsPerTower*kTowersInPhi + phi/kChannelsPerCard + 1;
0361     if (rightTower(tower)) {
0362       crystal = (eta%kCardsPerTower)*kChannelsPerCard;
0363       if ((eta%kChannelsPerCard)%2 == 0)
0364     crystal += phi%kChannelsPerCard;
0365       else
0366     crystal += kChannelsPerCard - 1 - phi%kChannelsPerCard;
0367     } else {
0368       crystal = (kCardsPerTower - 1 - eta%kCardsPerTower)*kChannelsPerCard;
0369       if ((eta%kChannelsPerCard)%2 == 0)
0370     crystal += kChannelsPerCard - 1 - phi%kChannelsPerCard;
0371       else
0372     crystal += phi%kChannelsPerCard;
0373     }
0374   } else {
0375     int line = smCrystal/85;
0376     int cInLine = smCrystal%85;
0377     
0378     tower= 1 + (cInLine/5) * 4 + line/5; // tower number in SM
0379     crystal = crystalChannelMap[line%5][cInLine%5];
0380     if (leftTower(tower)) crystal = 24-crystal ;
0381   }
0382   return;
0383 }
0384 
0385 
0386 //! Returns the crystal number (readout order) in a tower 
0387 //! for a given position in the tower (crystalNbGeom=0 is the 
0388 //! lower-right corner and crystalNbGeom=24 is the upper-left corner,
0389 //! see scheme in H4Geom::getTower)
0390 int H4Geom::getTowerCrystalNumber(int smTowerNb, int crystalNbGeom) const
0391 {
0392   if (crystalNbGeom < 0 || crystalNbGeom >= kCrystalsPerTower) return -1 ;
0393   int column = crystalNbGeom/kCardsPerTower;
0394   int line = crystalNbGeom%kChannelsPerCard;
0395   int crystal = crystalChannelMap[line][column];
0396   if (leftTower(smTowerNb)) crystal = kCrystalsPerTower - 1 - crystal;
0397   return crystal;
0398 }
0399 
0400 
0401 //! Returns the crystal coordinates (eta, phi index) for a given
0402 //! crystal number in the super module
0403 void H4Geom::getCrystalCoord(int &eta, int &phi, int smCrystal) const
0404 {
0405   if (geometry_ == H4Geom::Spring2004) {
0406     eta = (smCrystal - 1)/kChannelsPerCard; // arbitrary units
0407     phi = kChannelsPerCard - 1 - 
0408       ((smCrystal - 1)%kCrystalsPerTower)%kChannelsPerCard;
0409   } else if (geometry_ == H4Geom::Automn2004) {
0410     eta = (smCrystal - 1)/(kChannelsPerCard*kTowersInPhi);
0411     phi = (smCrystal - 1)%(kChannelsPerCard*kTowersInPhi);
0412   } else {
0413     eta = smCrystal%kCrystalsInEta;
0414     phi = smCrystal/kCrystalsInEta;
0415   }
0416 }
0417 
0418 
0419 //! Retuns the crystal number in the super module for given coordinates
0420 int H4Geom::getSMCrystalFromCoord(int eta, int phi) const
0421 {
0422   if (geometry_ == H4Geom::Spring2004) {
0423     if (eta >= 9 || eta < 0 || phi >= 4 || phi < 0) 
0424       return -1; // Only two supercrystals
0425     return eta*kCardsPerTower + (kChannelsPerCard - phi);
0426   }
0427   if (eta < 0 || eta >= kCrystalsInEta || phi < 0 || phi >= kCrystalsInPhi) 
0428     return -1; // non real smCrystal
0429   else {
0430     if (geometry_ == H4Geom::Automn2004)
0431       return eta*kChannelsPerCard*kTowersInPhi + phi + 1;
0432     else
0433       return eta + kCrystalsInEta*phi;
0434   }
0435 }
0436 
0437 
0438 //! Returns left neighbour of a sm crystal.
0439 //! Input and output are crystal numbers in the super module.
0440 //! A negative output means outside of the supermodule.
0441 int H4Geom::getLeft(int smCrystal) const
0442 {
0443   if (!IsGeomPeriodDefined()) 
0444     {cout << "[H4Geom] geometry period not defined, aborting.\t (should be  ForEcalMonitoring = Automn2004;)" << endl;
0445       abort();}
0446   if (geometry_ == H4Geom::Spring2004) {
0447     smCrystal += kChannelsPerCard;
0448     if (smCrystal > 2*kCrystalsPerTower || smCrystal < 1) return -1;
0449     return smCrystal;
0450   } else if (geometry_ == H4Geom::Automn2004) {
0451     smCrystal += kCrystalsInPhi;
0452     if (smCrystal > kCrystals) return -1;
0453     return smCrystal;
0454   } else {
0455     smCrystal++;
0456     if (!(smCrystal % kCrystalsInEta)) return -1;
0457     if (smCrystal >= kCrystals || smCrystal < 0) return -1;
0458     return smCrystal;
0459   }
0460 }
0461 
0462 
0463 //! Returns right neighbour of a sm crystal.
0464 //! Input and output are crystal numbers in the super module.
0465 //! A negative output means outside of the supermodule.
0466 int H4Geom::getRight(int smCrystal) const
0467 {
0468   if (!IsGeomPeriodDefined()) 
0469     {cout << "[H4Geom] geometry period not defined, aborting.\t (should be  ForEcalMonitoring = Automn2004;)" << endl;
0470       abort();}
0471   if (geometry_ == H4Geom::Spring2004) {
0472     smCrystal -= kChannelsPerCard;
0473     if (smCrystal > 2*kCrystalsPerTower || smCrystal < 1) return -1;
0474     return smCrystal;
0475   } else if (geometry_ == H4Geom::Automn2004) {
0476     smCrystal -= kCrystalsInPhi;
0477     if (smCrystal < 0) return -1;
0478     return smCrystal;
0479   } else {
0480     smCrystal--;
0481     if (smCrystal % kCrystalsInEta == kCrystalsInEta - 1) return -1;
0482     if (smCrystal >= kCrystals || smCrystal < 0) return -1;
0483     return smCrystal;
0484   }
0485 }
0486 
0487 
0488 //! Returns upper neighbour of a sm crystal.
0489 //! Input and output are crystal numbers in the super module.
0490 //! A negative output means outside of the supermodule.
0491 int H4Geom::getUpper(int smCrystal) const{
0492   if (!IsGeomPeriodDefined()) 
0493     {cout << "[H4Geom] geometry period not defined, aborting.\t (should be  ForEcalMonitoring = Automn2004;)" << endl;
0494       abort();}
0495   if (geometry_ == H4Geom::Spring2004) {
0496     smCrystal--;
0497     if (smCrystal > 2*kCrystalsPerTower || smCrystal < 1) return -1;
0498     return smCrystal;
0499   } else if (geometry_ == H4Geom::Automn2004) {
0500     if ((smCrystal - 1)%kCrystalsInPhi == 0) return -1; // phi = 0
0501     smCrystal--;
0502     return smCrystal;
0503   } else {
0504     smCrystal += kCrystalsInEta;
0505     if (smCrystal >= kCrystals || smCrystal < 0) return -1;
0506     return smCrystal;
0507   }
0508 }
0509 
0510 
0511 //! Returns lower neighbour of a sm crystal.
0512 //! Input and output are crystal numbers in the super module.
0513 //! A negative output means outside of the supermodule.
0514 int H4Geom::getLower(int smCrystal) const
0515 {
0516   if (!IsGeomPeriodDefined()) 
0517     {cout << "[H4Geom] geometry period not defined, aborting.\t (should be  ForEcalMonitoring = Automn2004;)" << endl;
0518       abort();}
0519   if (geometry_ == H4Geom::Spring2004) {
0520     smCrystal ++;
0521     if (smCrystal > 2*kCrystalsPerTower || smCrystal < 1) return -1;
0522     return smCrystal;
0523   } else if (geometry_ == H4Geom::Automn2004) {
0524     if (smCrystal%kCrystalsInPhi == 0) return -1; // phi = 19
0525     smCrystal++;
0526     return smCrystal;
0527   } else {
0528     smCrystal -= kCrystalsInEta;
0529     if (smCrystal >= kCrystals || smCrystal < 0) return -1;
0530     return smCrystal;
0531   }
0532 }
0533 
0534 
0535 //! Returns left neighbour of a crystal referenced by its coordinates.
0536 //! New coordonates overwrite the old ones. No check is done to see
0537 //! if it corresponds to a real crystal. To be used with caution. 
0538 void H4Geom::mvLeft(int &eta, int &phi) const
0539 {
0540   if (eta >= kCrystalsInEta)
0541     std::cout << "H4Geom::mvLeft: eta is too large " << eta << std::endl;
0542   eta++;
0543 }
0544 
0545 //! Returns right neighbour of a crystal referenced by its coordinates.
0546 //! New coordonates overwrite the old ones. No check is done to see
0547 //! if it corresponds to a real crystal. To be used with caution. 
0548 void H4Geom::mvRight(int &eta, int &phi) const
0549 {
0550   if (eta < 0)
0551     std::cout << "H4Geom::mvRight: eta is too small " << eta << std::endl;
0552   eta--;
0553 }
0554 
0555 //! Returns upper neighbour of a crystal referenced by its coordinates.
0556 //! New coordonates overwrite the old ones. No check is done to see
0557 //! if it corresponds to a real crystal. To be used with caution. 
0558 void H4Geom::mvUp(int &eta, int &phi) const
0559 {
0560   if (phi >= kCrystalsInPhi)
0561     std::cout << "H4Geom::mvUp: phi is too large " << phi << std::endl;
0562   phi++;
0563 }
0564 
0565 
0566 //! Returns lower neighbour of a crystal referenced by its coordinates.
0567 //! New coordonates overwrite the old ones. No check is done to see
0568 //! if it corresponds to a real crystal. To be used with caution. 
0569 void H4Geom::mvDown(int &eta, int &phi) const
0570 {
0571   if (phi < 0)
0572     std::cout << "H4Geom::mvDown: phi is too small " << phi << std::endl;
0573   phi--;
0574 }
0575 
0576 
0577 //! Returns the 25 crystals of tower towerNb in the super module.
0578 //! Output are crystal numbers in the super module.
0579 //! By default, the order in the output array (tower) corresponds to
0580 //! geometric order (index 0 is lower-right corner).
0581 //! if order=readout, the order in the output array (tower) 
0582 //! corresponds to the readout scheme (depends on the kind of tower)
0583 /**
0584  * the geometric order is defined by:
0585  * \verbatim
0586  *  +--+--+--+--+--+
0587  *  |24|19|14| 9| 4|
0588  *  +--+--+--+--+--+
0589  *  |23|18|13| 8| 3|
0590  *  +--+--+--+--+--+  
0591  *  |22|17|12| 7| 2| 
0592  *  +--+--+--+--+--+ 
0593  *  |21|16|11| 6| 1| 
0594  *  +--+--+--+--+--+ 
0595  *  |20|15|10| 5| 0| 
0596  *  +--+--+--+--+--+ 
0597  * \endverbatim
0598  */ 
0599 void H4Geom::getTower(int * tower, int towerNb, std::string order) const 
0600 {
0601   if (!IsGeomPeriodDefined()) 
0602     {cout << "[H4Geom] geometry period not defined, aborting.\t (should be  ForEcalMonitoring = Automn2004;)" << endl;
0603       abort();}
0604   if (order == "readout") {
0605     for (int crystalNb = 0; crystalNb < kCrystalsPerTower; crystalNb++)
0606       tower[crystalNb] = getSMCrystalNumber(towerNb, crystalNb);
0607   } else {
0608     int towerId = towerNb - 1;
0609     int line = towerId%kTowersInPhi;
0610     int column = towerId/kTowersInPhi;
0611     if (geometry_ == H4Geom::Automn2004) {
0612       int smLowerRight = column*kCardsPerTower*kCrystalsInPhi + 
0613                      (line + 1)*kChannelsPerCard;
0614       for (int i = 0; i < kCrystalsPerTower; i++)
0615     tower[i] = smLowerRight - i%kChannelsPerCard + 
0616                    i/kChannelsPerCard*kCrystalsInPhi;
0617     } else {
0618       int smLowerRight = kChannelsPerCard*line*kCrystalsInEta + 
0619                      column*kCardsPerTower;
0620       for (int i = 0; i < kCrystalsPerTower; i++)
0621     tower[i] = i%kChannelsPerCard * kCrystalsInEta + 
0622                i/kChannelsPerCard + smLowerRight;
0623     }
0624   }
0625   return;
0626 }
0627 
0628 
0629 //! Returns the 5 crystals belonging to the same VFE board as smCrystal.
0630 //! Input and output are crystal numbers in the super module.
0631 //! By default, the order in the output array (VFE) corresponds to
0632 //! The geometric order (index 0 is lower-right corner).
0633 //! if order=readout, the order in the output array (VFE) 
0634 //! corresponds to the readout scheme (depends on the kind of tower)
0635 /**
0636  * the geometric order is defined by:
0637  * \verbatim
0638  *  +-+
0639  *  |4|
0640  *  +-+
0641  *  |3|
0642  *  +-+  
0643  *  |2| 
0644  *  +-+ 
0645  *  |1| 
0646  *  +-+ 
0647  *  |0| 
0648  *  +-+ 
0649  * \endverbatim
0650  */ 
0651 void H4Geom::getVFE(int * VFE, int smCrystal, std::string order) const 
0652 {
0653   int towerNb, crystalNb;
0654   getTowerCrystalNumber(towerNb, crystalNb, smCrystal);
0655   int VFEnb = crystalNb/kChannelsPerCard;
0656   if (order == "readout") {
0657     for (crystalNb = 0; crystalNb < kChannelsPerCard; crystalNb++) 
0658       VFE[crystalNb] = getSMCrystalNumber(towerNb, 
0659                       kChannelsPerCard*VFEnb+crystalNb);
0660   } else {
0661     int eta, phi;
0662     getCrystalCoord(eta, phi, smCrystal);
0663     int smLower = eta+85*5*(phi/5); 
0664     for (int i = 0; i < 5; i++)
0665       VFE[i] =  i*85 + smLower;
0666   }  
0667 }
0668 
0669 //! Returns sm crystal numbers for crystals in a window of
0670 //! size widthxheight centered around a given smCrystal.
0671 //! width and height must be odd.
0672 //! The order in the output array (window) is defined 
0673 //! by the geometric order (index 0 is lower-right corner).
0674 /**
0675  * the geometric order is defined by:
0676  * \verbatim
0677  *         width (w)
0678  * <--------------------->
0679  * +---------------------+   -
0680  * | h*w . . . . .  .   h|   |
0681  * | .              .   .|   |
0682  * | .              .   .|   | h
0683  * | .              .   .|   | e
0684  * | . . . . x . .  .   .|   | i (h)
0685  * | .              .   .|   | g
0686  * | .              .   .|   | h
0687  * | .              .   .|   | t
0688  * | .              .   1|   | 
0689  * | . . . . . . . h+1  0|   |
0690  * +---------------------+   -
0691  *
0692  *    x: central crystal     
0693  * \endverbatim
0694  */
0695 void H4Geom::getWindow(int * window, int smCrystal, int width, int height) const
0696 {
0697   if (width <= 0 || width%2 == 0) {
0698     std::cout << "H4Geom::getWindow, width should be >0 and odd!" << std::endl;
0699     return;
0700   }
0701   if (height <= 0 || height%2 == 0) {
0702     std::cout << "H4Geom::getWindow, height should be >0 and odd!" 
0703           << std::endl;
0704     return;
0705   }
0706   int eta, phi;
0707   getCrystalCoord(eta, phi, smCrystal);
0708   // get lower-right corner
0709   int eta0 = eta - (width - 1)/2;
0710   int phi0 = phi - (height - 1)/2;
0711   int index = 0;
0712   eta = eta0;
0713   phi = phi0;
0714   for (int i = 0; i < width; i++) {
0715     for (int j = 0; j < height; j++) {
0716       window[index] = getSMCrystalFromCoord(eta, phi);
0717       phi++;
0718       index++;
0719     }
0720     eta++;
0721     phi = phi0;
0722   }
0723 }
0724 
0725 
0726 //! Tests if low voltage board is on the right size of the tower.
0727 //! Readout scheme depends on that.
0728 /**
0729  * the readout order for a "right-tower" is defined by:
0730  * \verbatim
0731  *  +--+--+--+--+--+
0732  *  |20|19|10| 9| 0|
0733  *  +--+--+--+--+--+
0734  *  |21|18|11| 8| 1|
0735  *  +--+--+--+--+--+  
0736  *  |22|17|12| 7| 2| 
0737  *  +--+--+--+--+--+ 
0738  *  |23|16|12| 6| 3| 
0739  *  +--+--+--+--+--+ 
0740  *  |24|15|14| 5| 4| 
0741  *  +--+--+--+--+--+ 
0742  * \endverbatim
0743  */ 
0744 bool H4Geom::rightTower(int tower) const 
0745 {
0746   if (!IsGeomPeriodDefined()) 
0747     {cout << "[H4Geom] geometry period not defined, aborting.\t (should be  ForEcalMonitoring = Automn2004;)" << endl;
0748       abort();}
0749   if (geometry_ == H4Geom::Automn2004) {
0750     if ((tower - 1)/kTowersInPhi < 3 ||
0751     ((tower - 1)/kTowersInPhi - 3)%4 >= 2)
0752       return false;
0753     else
0754       return true;
0755   }
0756   if ((tower>12 && tower<21) || (tower>28 && tower<37) ||
0757       (tower>44 && tower<53) || (tower>60 && tower<69))
0758     return true;
0759   else
0760     return false;
0761 }
0762 
0763 //! Tests if low voltage board is on the left size of the tower.
0764 //! Readout scheme depends on that.
0765 /**
0766  * the readout order for a "left-tower" is defined by:
0767  * \verbatim
0768  *  +--+--+--+--+--+
0769  *  | 4| 5|14|15|24|
0770  *  +--+--+--+--+--+
0771  *  | 3| 6|13|16|23|
0772  *  +--+--+--+--+--+  
0773  *  | 2| 7|12|17|22| 
0774  *  +--+--+--+--+--+ 
0775  *  | 1| 8|11|18|21| 
0776  *  +--+--+--+--+--+ 
0777  *  | 0| 9|10|19|20| 
0778  *  +--+--+--+--+--+ 
0779  * \endverbatim
0780  */ 
0781 bool H4Geom::leftTower(int tower) const
0782 {
0783   return !rightTower(tower);
0784 }
0785 
0786 void H4Geom::SetGeomPeriod(GeomPeriod_t geometry)
0787 {
0788   geometry_ = geometry;
0789 }
0790 
0791 bool H4Geom::IsGeomPeriodDefined() const {
0792   if (geometry_ == H4Geom::Undef) {
0793     std::cout << "Class H4Geom : geometry is not defined. You should call in"
0794           << " your program H4Geom::init (and fill the [Geometry] section"
0795           << " of your config file) or call H4Geom::SetGeomPeriod." 
0796           << std::endl;
0797     return false;
0798   }
0799   return true;
0800 }
0801 
0802 int H4Geom::getHalf (int TT){
0803   if(TT < 1 || TT >68){cout <<"TT num out of range: "<<TT<<endl; return 0;}
0804   return WhichHalf[TT];
0805 }