#include "Mapping.h" //=========================================================================== Mapping::Mapping(){ // // Constructor. Read one file per rcu // fLogger = Logger::getInstance(); fDZ = 249.7; // max driftlength fDR = 246.6; // max radius to outermost padrow of OROC fVelocity = 2.57563; // [cm/microsec] // 249.7/88; fOffset = 1 /*[microsec]*/ * fVelocity; // [cm] fTimeBinLength = 0.1; // 100 nanosec // IROC fCenterPad[0] = new uint32_t[63]; fNPads[0] = new uint32_t[63]; for (uint32_t irow=0; irow<63; irow++) { fNPads[0][irow] = (irow==0) ? 68 : 2 *(int)(float(irow)/3. + 33.67); fCenterPad[0][irow] = 140; } // OROC fCenterPad[1] = new uint32_t[96]; fNPads[1] = new uint32_t[96]; for (uint32_t irow=0; irow<96; irow++) { uint32_t npads = (irow<64) ? 2*(uint32_t)(10.*tan(10*1.74532925199432955e-02)/6.*irow + 37.75): 2*(uint32_t)(15.*tan(10*1.74532925199432955e-02)/6.*(irow-64) + 56.66); fNPads[1][irow] = npads; fCenterPad[1][irow] = 140; } // fRCUCount = 6; fRCUs = new RCUMapping[fRCUCount]; //clear for ( uint32_t i = 0; i < 240; i++) fPadsPerRow[i] = 0; // Do the mapping for ( uint32_t rcu = 0; rcu < fRCUCount; ++rcu) { ReadRCU(rcu); CreateInvMapping(rcu); } } //=========================================================================== Mapping::~Mapping() { // // Destructor // for ( uint32_t rcu = 0; rcu < fRCUCount; ++rcu) { delete [] fRCUs[rcu].fMapping; delete [] fRCUs[rcu].fInvMapping; } delete [] fRCUs; delete [] fNPads[0]; delete [] fNPads[1]; delete [] fCenterPad[0]; delete [] fCenterPad[1]; } //=========================================================================== void Mapping::ReadRCU(uint32_t rcu) { // // read one rcu-file // fRCUs[rcu].fMinPadRow = 0x7fffffff; fRCUs[rcu].fMaxPadRow = 0; fRCUs[rcu].fMaxPad = 0; ifstream *ifs; char fileName[256]; char desc[256]; uint32_t fNumberOfChannels; // determine path and filename #ifdef TPC_PADMAPPING_PATH string path(TPC_PADMAPPING_PATH); sprintf(fileName, "%s/Patch%i.data", path.c_str(), rcu); #else sprintf(desc, "Mapping::ReadRCU(): TPC_PADMAPPING_PATH not defined. Trying path: ../Mapping/PatchX.data"); fLogger->appendWarning(desc); sprintf(fileName, "../Mapping/Patch%i.data", rcu); #endif ifs = new ifstream(fileName); if ( !*ifs ) { sprintf(desc, "Mapping::ReadRCU(): Failed to open file %s", fileName); fLogger->appendError(desc); throw TpcException( (string) desc); return; } // number of pads if ( !(*ifs >> fNumberOfChannels)) { sprintf(desc, "Mapping::ReadRCU(): Bad file format in file %s", fileName); fLogger->appendError(desc); throw TpcException( (string) desc); return; } // maximum hardware address if ( !(*ifs >> fRCUs[rcu].fMaxHWAddress)) { sprintf(desc, "Mapping::ReadRCU(): Bad file format in file %s", fileName); fLogger->appendError(desc); throw TpcException( (string) desc); return; } fRCUs[rcu].fMapping = new int16_t[fRCUs[rcu].fMaxHWAddress * 2 + 2]; for ( uint32_t i = 0; i <= fRCUs[rcu].fMaxHWAddress * 2; i++) fRCUs[rcu].fMapping[i] = -1; uint32_t padrow, pad; int32_t hwAddress; for ( uint32_t i = 0; i < fNumberOfChannels; i++) { // read out padrow and pad for hwAddress if ( (!(*ifs >> hwAddress)) || (hwAddress > (int)fRCUs[rcu].fMaxHWAddress) ) { sprintf(desc, "Mapping::ReadRCU(): Bad file format in file %s", fileName); fLogger->appendError(desc); throw TpcException( (string) desc); } if ( ( !(*ifs >> padrow) ) || ( !(*ifs >> pad)) ) { sprintf(desc, "Mapping::ReadRCU(): Bad file format in file %s", fileName); fLogger->appendError(desc); throw TpcException( (string) desc); } //cout << hwAddress << ", " << padrow << ", " << pad << endl; fRCUs[rcu].fMapping[hwAddress * 2 ] = padrow; fRCUs[rcu].fMapping[hwAddress * 2 + 1] = pad; if (padrow > fRCUs[rcu].fMaxPadRow) fRCUs[rcu].fMaxPadRow = padrow; if (padrow < fRCUs[rcu].fMinPadRow) fRCUs[rcu].fMinPadRow = padrow; if (pad > fRCUs[rcu].fMaxPad ) fRCUs[rcu].fMaxPad = pad; // count pads per row if ( GetPadsPerRow(fRCUs[rcu].fMapping[hwAddress * 2], rcu) < fRCUs[rcu].fMapping[hwAddress * 2 + 1] ) SetPadsPerRow(fRCUs[rcu].fMapping[hwAddress * 2], rcu, fRCUs[rcu].fMapping[hwAddress * 2 + 1]); // find center pad in this row if ( (rcu < 2) && (hwAddress>=0x800) && (pad 1) && (hwAddress>=0x800) && (padclose(); delete ifs; return; } //=========================================================================== void Mapping::CreateInvMapping(uint32_t rcu) { // Create the inverse mapping if (!fRCUs[rcu].fMapping) { char desc[256]; sprintf(desc, "Mapping::CreateInvMapping(): Mapping array not correctly initalized for rcu %d", rcu); fLogger->appendError(desc); throw TpcException( (string) desc); return; } /* cout << "rcu " << rcu << " covers padrows " << fRCUs[rcu].fMinPadRow << " to " << fRCUs[rcu].fMaxPadRow << ", maxpad is " << fRCUs[rcu].fMaxPad << endl; */ uint32_t nRows = fRCUs[rcu].fMaxPadRow - fRCUs[rcu].fMinPadRow + 1; uint32_t nPads = fRCUs[rcu].fMaxPad + 1; uint32_t invMappingSize = nRows*nPads; fRCUs[rcu].fInvMapping = new int16_t[invMappingSize]; // clear arrays for (uint32_t i = 0; i <= (fRCUs[rcu].fMaxPadRow - fRCUs[rcu].fMinPadRow); i++) { for (uint32_t j = 0; j <= fRCUs[rcu].fMaxPad; j++) fRCUs[rcu].fInvMapping[nPads*i+j] = -1; } for ( uint32_t i = 0; i <= fRCUs[rcu].fMaxHWAddress; i++) { int16_t padrow = fRCUs[rcu].fMapping[2*i]; int16_t pad = fRCUs[rcu].fMapping[2*i+1]; //if ((padrow == 30) && (pad == 40)) cout << rcu << endl; if (padrow != -1 && pad != -1) fRCUs[rcu].fInvMapping[nPads*(padrow-fRCUs[rcu].fMinPadRow)+pad] = i; } return ; } //=========================================================================== uint32_t Mapping::GetNPads(uint32_t row, uint32_t rcu) { // get number of pads in this padrow. return ((rcu < 2) ? fNPads[0][row] /*IROC*/ : fNPads[1][row] /*OROC*/ ); } //=========================================================================== uint32_t Mapping::GetCenterPad(uint32_t row, uint32_t rcu) { // get first pad in branch b in this padrow return ((rcu < 2) ? fCenterPad[0][row] /*IROC*/ : fCenterPad[1][row] /*OROC*/ ); } //=========================================================================== int32_t Mapping::GetRocFromPatch(uint32_t side, uint32_t sector, uint32_t patch) { // Get Roc (0 ... 71) from side (0, 1), sector (0 ... 17) and patch (0 ... 5) if ( side > 1 ) { char desc[256]; sprintf(desc, "Mapping::GetRocFromPatch(): Side outside range: %d", side); fLogger->appendError(desc); return -1; } if ( sector > 17 ) { char desc[256]; sprintf(desc, "Mapping::GetRocFromPatch(): Sector outside range: %d", sector); fLogger->appendError(desc); return -1; } if ( patch > 5 ) { char desc[256]; sprintf(desc, "Mapping::GetRocFromPatch(): Rcu outside range: %d", patch); fLogger->appendError(desc); return -1; } if ( patch < 2 ) return side*18+sector; // IROC else return 36+side*18+sector; // OROC } //=========================================================================== int32_t Mapping::GetDDLfromPatch(uint32_t side, uint32_t sector, uint32_t patch) { // Get the DDL Number [0,..,215] from the geographic position // int32_t roc = GetRocFromPatch(side, sector, patch); int32_t ddl = -1; if (roc>=0) { if (patch < 2) // IROC ddl = roc*2 + patch; else // OROC ddl = (roc-36)*4 + 36*2 + (patch-2); } return ddl; } //=========================================================================== int32_t Mapping::GetHWAddress(uint32_t padrow, uint32_t pad, uint32_t rcu) { // Get the content of the inverse mapping array // return -1 in case there is no hardware adress defined for these pad-row and pad if (padrow < fRCUs[rcu].fMinPadRow || padrow > fRCUs[rcu].fMaxPadRow) { char desc[256]; sprintf(desc, "Mapping::GetHWAddress(): Padrow index (%d) for rcu %d outside range (%d..%d)!", padrow, rcu, fRCUs[rcu].fMinPadRow, fRCUs[rcu].fMaxPadRow); fLogger->appendError(desc); return -1; } if (pad > fRCUs[rcu].fMaxPad) { char desc[256]; sprintf(desc, "Mapping::GetHWAddress(): Pad index (%d) for rcu %d outside range (0..%d)!", pad, rcu, fRCUs[rcu].fMaxPad); fLogger->appendError(desc); return -1; } int32_t hwAddress = fRCUs[rcu].fInvMapping[(fRCUs[rcu].fMaxPad+1)*(padrow-fRCUs[rcu].fMinPadRow)+pad]; if (hwAddress == -1) { // This is often output for padrows which are shared between 2 RCUs char desc[256]; sprintf(desc, "Mapping::GetHWAddress(): Hardware adress is not defined for rcu %d, padrow %d, pad %d!!", rcu, padrow, pad); fLogger->appendDebug(desc); sprintf(desc, "Mapping::GetHWAddress(): This warning is ok for a some padrows."); fLogger->appendDebug(desc); } return hwAddress; } //=========================================================================== int32_t Mapping::DecodedHWAddressBranch(int32_t hwAddress) { // Get branch index (0, 1) from hardware address if ( hwAddress < 0 ) return -1; return ((hwAddress>>11)&ci01BitOn); } //=========================================================================== int32_t Mapping::DecodedHWAddressFECaddr(int32_t hwAddress) { // Get FEC index (0 ... 12) from hardware address if ( hwAddress < 0 ) return -1; return ((hwAddress>>7)&ci04BitOn); } //=========================================================================== int32_t Mapping::DecodedHWAddressChipaddr(int32_t hwAddress) { // Get ALTRO index (0 ... 7) from hardware address if ( hwAddress < 0 ) return -1; return ((hwAddress>>4)&ci03BitOn); } //=========================================================================== int32_t Mapping::DecodedHWAddressChanneladdr(int32_t hwAddress) { // Get channel index (0 ... 15) from hardware address if ( hwAddress < 0 ) return -1; return ((hwAddress&ci04BitOn)); } //=========================================================================== int16_t Mapping::GetPadRow(int32_t hwAddress, uint32_t rcu) { // // Get PadRow from hwAdress // if ( hwAddress > (int)fRCUs[rcu].fMaxHWAddress) return -1; else return fRCUs[rcu].fMapping[2 * hwAddress]; } //=========================================================================== int16_t Mapping::GetPad(int32_t hwAddress, uint32_t rcu) { // // Get Pad from hwAdress // if ( hwAddress > (int)fRCUs[rcu].fMaxHWAddress) { char desc[256]; sprintf(desc, "Mapping::GetPad(): Invalid hardwareAdress (%d)!", hwAddress); fLogger->appendError(desc); return -1; } else { return fRCUs[rcu].fMapping[2*hwAddress + 1]; } } //=========================================================================== uint32_t Mapping::codeAddress(uint32_t Branch, uint32_t FEC, uint32_t chip, uint32_t channel) { // // Convert Branch, FEC, altro and channel into a hwAddress // return ((Branch&1)<<11) + ((FEC&0xf)<<7) + ((chip&0x7)<<4) + (channel&0xf); } //=========================================================================== int16_t Mapping::GetPadRow2(uint32_t Branch, uint32_t FEC, uint32_t chip, uint32_t channel, uint32_t rcu) { // // chip = altro // return GetPadRow(codeAddress(Branch, FEC, chip, channel), rcu); } //=========================================================================== int16_t Mapping::GetPad2(uint32_t Branch, uint32_t FEC, uint32_t chip, uint32_t channel, uint32_t rcu) { // // // return GetPad(codeAddress(Branch, FEC, chip, channel), rcu); } //=========================================================================== int16_t Mapping::GetPadsPerRow(uint32_t Row, uint32_t rcu) { // // Return the number of pads in a row // if ( rcu < 2) return fPadsPerRow[Row]; else return fPadsPerRow[Row+100]; } //=========================================================================== void Mapping::SetPadsPerRow(uint32_t Row, uint32_t rcu, int16_t PadCount) { // // set the count of pads in a row // if ( rcu < 2) fPadsPerRow[Row] = PadCount; else fPadsPerRow[Row+100] = PadCount; } //=========================================================================== int32_t Mapping::GetMaxHWAddress(uint32_t rcu) { // // get the maximum hwAdress // if ( rcu < fRCUCount) return (int)(fRCUs[rcu].fMaxHWAddress); else return -1; } //=========================================================================== float Mapping::GetRadialDistance(int32_t hwAddress, uint32_t rcu) { // // calculates the radial distance of a pad [cm] // the radial distance consists of two parameters // > z-distance // > r-distance // radial distance ^ 2 = z^2 + r^2 uint32_t Pad; // which padindex/padrow uint32_t PadRow; Pad = GetPad(hwAddress, rcu); PadRow = GetPadRow(hwAddress, rcu); // z-distance = PadWidth * (PadIndex - PadsPerRow/2) float PadWidth; if ( rcu < 2 ) // IROC PadWidth = 0.4; // 4 mm else // OROC PadWidth = 0.6; // 6 mm float distz = PadWidth * ((float)Pad - ((float)GetPadsPerRow(PadRow, rcu))/2 + 0.5); // cm // r-distance = OffsetR + PadRow * PadHeight float OffsetR; float PadHeight; float PadHeight2; float distr; if ( rcu < 2 ) { // IROC OffsetR = 84.85; // cm PadHeight = 0.75; // cm distr = OffsetR + ((float)PadRow + 0.5) * PadHeight; } else { // OROC // there are two different padheights in these rcus, // depending on the padrow OffsetR = 134.6; // cm PadHeight = 1; // cm PadHeight2 = 1.5; // cm if ( PadRow > 63) { distr = OffsetR + (float)64 * PadHeight + ((float)PadRow - 64 + 0.5) * PadHeight2; } else { distr = OffsetR + ((float)PadRow + 0.5) * PadHeight; } } // calc distance (see above) return (sqrt(distz*distz + distr*distr)); } //=========================================================================== float Mapping::GetMaxRadialDistance(uint32_t Branch, uint32_t FEC, uint32_t chip, uint32_t rcu) { // // determines the highest radial distance of an altro [cm] // by checking every channel of this altro // float maxdist = 0; float curdist; // for each channel for ( uint32_t i = 0; i<16; i++ ) { curdist = GetRadialDistance(codeAddress(Branch, FEC, chip, i), rcu); if ( curdist > maxdist) maxdist = curdist; // store max. value } return maxdist; } //=========================================================================== float Mapping::GetMinDriftTime(float RadDist) { // calculates the minimal allowed drift time for a (max.) // rad. distance, given the velocity. // constants: min. beam direction defined by driftlength in z and r // of the outer field cage // units of RadDist and Velocity must match! // drifttime = driftway / velocity // driftway = fDZ - (fDZ / fDR * raddist) float fTime = (fDZ - (fDZ/fDR * RadDist) - fOffset) / fVelocity; if ( fTime < 0) return 0; else return fTime / fTimeBinLength; } //=========================================================================== void Mapping::SetOffset(float offset) { // // Set an horizontal offset from interaction point (on the beam axis) // Offset is [cm] // if ( offset < 0) { char desc[256]; sprintf(desc, "Mapping::SetOffset(): Negative offset for data acquisition start: %f", offset); fLogger->appendWarning(desc); } fOffset = offset; } //=========================================================================== void Mapping::SetTimeBinLength(float tLength) { // [microsec] if ( tLength <= 0 ) { char desc[256]; sprintf(desc, "Mapping::SetOffset(): Negative or zero TimeBinLength: %f", tLength); fLogger->appendWarning(desc); } fTimeBinLength = tLength; }