Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-04-06 12:29:23

0001 // -*- Mode: C++; c-basic-offset: 2; indent-tabs-mode: t; tab-width: 8; -*-
0002 
0003 /** \file
0004  * GenABIO is a standalone program to produce individual SRP card trigger tower
0005  * and selective readout action flags from TTF.txt and SRF.txt global flag
0006  * files.
0007  * Run 'GenABIO -h' for usage.
0008  */
0009 
0010 #include <cassert>
0011 #include <cstdlib>
0012 #include <cstring>
0013 #include <fstream>
0014 #include <iostream>
0015 #include <sstream>
0016 #include <vector>
0017 
0018 #include "ecalDccMap.h"
0019 
0020 #if !defined(__linux__) && !(defined(__APPLE__) && __DARWIN_C_LEVEL >= 200809L)
0021 #include <errno.h>
0022 /* getline implementation is copied from glibc. */
0023 
0024 #ifndef SIZE_MAX
0025 #define SIZE_MAX ((size_t)-1)
0026 #endif
0027 #ifndef SSIZE_MAX
0028 #define SSIZE_MAX ((ssize_t)(SIZE_MAX / 2))
0029 #endif
0030 namespace {
0031   ssize_t getline(char **lineptr, size_t *n, FILE *fp) {
0032     ssize_t result;
0033     size_t cur_len = 0;
0034 
0035     if (lineptr == NULL || n == NULL || fp == NULL) {
0036       errno = EINVAL;
0037       return -1;
0038     }
0039 
0040     if (*lineptr == NULL || *n == 0) {
0041       *n = 120;
0042       *lineptr = (char *)malloc(*n);
0043       if (*lineptr == NULL) {
0044         result = -1;
0045         goto end;
0046       }
0047     }
0048 
0049     for (;;) {
0050       int i;
0051 
0052       i = getc(fp);
0053       if (i == EOF) {
0054         result = -1;
0055         break;
0056       }
0057 
0058       /* Make enough space for len+1 (for final NUL) bytes.  */
0059       if (cur_len + 1 >= *n) {
0060         size_t needed_max = SSIZE_MAX < SIZE_MAX ? (size_t)SSIZE_MAX + 1 : SIZE_MAX;
0061         size_t needed = 2 * *n + 1; /* Be generous. */
0062         char *new_lineptr;
0063 
0064         if (needed_max < needed)
0065           needed = needed_max;
0066         if (cur_len + 1 >= needed) {
0067           result = -1;
0068           goto end;
0069         }
0070 
0071         new_lineptr = (char *)realloc(*lineptr, needed);
0072         if (new_lineptr == NULL) {
0073           result = -1;
0074           goto end;
0075         }
0076 
0077         *lineptr = new_lineptr;
0078         *n = needed;
0079       }
0080 
0081       (*lineptr)[cur_len] = i;
0082       cur_len++;
0083 
0084       if (i == '\n')
0085         break;
0086     }
0087     (*lineptr)[cur_len] = '\0';
0088     result = cur_len ? (ssize_t)cur_len : result;
0089 
0090   end:
0091     return result;
0092   }
0093 }  // namespace
0094 #endif
0095 
0096 using namespace std;
0097 
0098 /** Range of the x-index of endcap crystals (xman-xmin+1).
0099  */
0100 const static int nEndcapXBins = 100;
0101 /** Range of the y-index of endcap crystals (yman-ymin+1).
0102  */
0103 const static int nEndcapYBins = 100;
0104 /** Edge size of a supercrystal. A supercrystal is a tower of 5x5 crystals.
0105  */
0106 const static int supercrystalEdge = 5;
0107 /** Range of endcap supercrystal x-index (xmax-xmin+1)
0108  */
0109 const static int nSupercrystalXBins = nEndcapXBins / supercrystalEdge;
0110 /** Range of endcap supercrystal y-index (ymay-ymin+1)
0111  */
0112 const static int nSupercrystalYBins = nEndcapYBins / supercrystalEdge;
0113 /** Number of endcap, obviously tow
0114  */
0115 const static int nEndcaps = 2;
0116 /** Number of trigger towers along eta in one endcap
0117  */
0118 const static int nEndcapTTInEta = 11;
0119 /** Number of barrel trigger towers along eta
0120  */
0121 const static int nBarrelTTInEta = 34;
0122 /** Number of trigger towers along eta for the whole ECAL
0123  */
0124 const static int nTTInEta = 2 * nEndcapTTInEta + nBarrelTTInEta;
0125 /** Number of trigger towers in an eta ring
0126  */
0127 const static int nTTInPhi = 72;
0128 /** Number of ABs in a phi-sector
0129  */
0130 const int nABInEta = 4;
0131 /** Number of ABs in an eta slice
0132  */
0133 const int nABInPhi = 3;
0134 /** Number of DCCs in an endcap
0135  */
0136 const int nDCCEE = 9;
0137 const int nABABCh = 8;    // nbr of AB input/output ch. on an AB
0138 const int nABTCCCh = 12;  // nbr of TCC inputs on an AB
0139 const int nDCCCh = 12;    // nbr of DCC outputs on an AB
0140 const int nTCCInEta = 6;  // nbr of TCC bins along eta
0141 const int nAB = nABInPhi * nABInEta;
0142 const int nTTInABAlongPhi = nTTInPhi / nABInPhi;
0143 const int iTTEtaMin[nABInEta] = {0, 11, 28, 45};
0144 const int iTTEtaMax[nABInEta] = {10, 27, 44, 55};
0145 const int iTTEtaSign[nABInEta] = {-1, -1, 1, 1};
0146 
0147 // Eta bounds for TCC partionning
0148 // a TCC covers from iTCCEtaBounds[iTCCEta] included to
0149 // iTCCEtaBounds[iTCCEta+1] excluded.
0150 const int iTCCEtaBounds[nTCCInEta + 1] = {0, 7, 11, 28, 45, 49, 56};
0151 
0152 const char *abTTFFilePrefix = "TTF_AB";
0153 const char *abTTFFilePostfix = ".txt";
0154 const char *abSRFFilePrefix = "AF_AB";
0155 const char *abSRFFilePostfix = ".txt";
0156 const char *abIOFilePrefix = "IO_AB";
0157 const char *abIOFilePostfix = ".txt";
0158 
0159 const char *srfFilename = "SRF.txt";
0160 const char *ttfFilename = "TTF.txt";
0161 const char *xconnectFilename = "xconnect_universal.txt";
0162 
0163 const char srpFlagMarker[] = {'.', 'S', 'N', 'C', '4', '5', '6', '7'};
0164 const char tccFlagMarker[] = {'.', 'S', '?', 'C', '4', '5', '6', '7'};
0165 
0166 char srp2roFlags[128];
0167 
0168 typedef enum { suppress = 0, sr2, sr1, full, fsuppress, fsr2, fsr1, ffull } roAction_t;
0169 char roFlagMarker[] = {
0170     /*suppress*/ '.',
0171     /*sr1*/ 'z',
0172     /*sr1*/ 'Z',
0173     /*full*/ 'F',
0174     /*fsuppress*/ '4',
0175     /*fsr2*/ '5',
0176     /*fsr1*/ '6',
0177     /*ffull*/ '7'};
0178 
0179 const int nactions = 8;
0180 // can be overwritten according by cmd line arguments
0181 roAction_t actions[nactions] = {
0182     /*LI->*/ sr2,
0183     /*S->*/ full,
0184     /*N->*/ full,
0185     /*C->*/ full,
0186     /*fLI->*/ sr2,
0187     /*fS->*/ sr2,
0188     /*fN->*/ sr2,
0189     /*fC->*/ sr2};
0190 
0191 // list of SC deserves by an endcap DCC [0(EE-)|1(EE+)][iDCCPhi]
0192 vector<pair<int, int>> ecalDccSC[nEndcaps][nDCCEE];
0193 
0194 void fillABTTFFiles(const char ttFlags[nTTInEta][nTTInPhi], ofstream files[]);
0195 void fillABSRPFiles(const char barrelSrFlags[nBarrelTTInEta][nTTInPhi],
0196                     const char endcapSrFlags[nEndcaps][nSupercrystalXBins][nSupercrystalYBins],
0197                     ofstream files[]);
0198 void fillABIOFiles(const char ttFlags[nTTInEta][nTTInPhi],
0199                    const char barrelSrFlags[nBarrelTTInEta][nTTInPhi],
0200                    const char endcapSrFlags[nEndcaps][nSupercrystalXBins][nSupercrystalYBins],
0201                    ofstream files[]);
0202 inline int abNum(int iABEta, int iABPhi) { return 3 * iABEta + iABPhi; }
0203 
0204 bool readTTF(FILE *file, char ttFlags[nTTInEta][nTTInPhi]);
0205 bool readSRF(FILE *file,
0206              char barrelSrFlags[nBarrelTTInEta][nTTInPhi],
0207              char endcapSrFlags[nEndcaps][nSupercrystalXBins][nSupercrystalYBins]);
0208 
0209 void writeABTTFFileHeader(ofstream &f, int abNum);
0210 void writeABSRFFileHeader(ofstream &f, int abNum);
0211 void writeABIOFileHeader(ofstream &f, int abNum);
0212 string getFlagStream(char flags[nTTInEta][nTTInPhi], int iEtaMin, int iEtaMax, int iPhiMin, int iPhiMax);
0213 string getABTCCInputStream(const char tccFlags[nTTInEta][nTTInPhi], int iABEta, int iABPhi, int iTCCCh);
0214 void getABTTPhiBounds(int iABPhi, int &iTTPhiMin, int &iTTPhiMax);
0215 string getABABOutputStream(const char tccFlags[nTTInEta][nTTInPhi], int iABEta, int iABPhi, int iABCh);
0216 string getABABInputStream(const char tccFlags[nTTInEta][nTTInPhi], int iABEta, int iABPhi, int iABCh);
0217 string getABDCCOutputStream(const char barrelSrFlags[nBarrelTTInEta][nTTInPhi],
0218                             const char endcapSrFlags[nEndcaps][nSupercrystalXBins][nSupercrystalYBins],
0219                             int iABEta,
0220                             int iABPhi,
0221                             int DCCCh);
0222 void abConnect(int iAB, int iABCh, int &iOtherAB, int &iOtherABCh);
0223 
0224 int iEvent = 0;
0225 
0226 int theAB = -1;
0227 
0228 int main(int argc, char *argv[]) {
0229   char barrelSrFlags[nBarrelTTInEta][nTTInPhi];
0230   char endcapSrFlags[nEndcaps][nEndcapXBins / 5][nEndcapYBins / 5];
0231   char ttFlags[nTTInEta][nTTInPhi];
0232   ofstream abTTFFiles[nAB];
0233   ofstream abSRFFiles[nAB];
0234   ofstream abIOFiles[nAB];
0235 
0236   int iarg = 0;
0237   while (++iarg < argc) {
0238     if (strcmp(argv[iarg], "-h") == 0 || strcmp(argv[iarg], "--help") == 0) {
0239       cout << "Usage: GenABIO [OPTIONS]\n\n"
0240               "Produces TT and SR flag files for each SRP board from TTF.txt "
0241               "and "
0242               "SRF.txt global flag files. Requires the SRP cross-connect "
0243               "description"
0244               " description file (xconnect_universal.txt). TTF.txt, SRF.txt and "
0245               "xconnect_universal.txt must be in the directory the command is "
0246               "launched.\n\n"
0247               "OPTIONS:\n"
0248               "  -A, --actions IJKLMNOP. IJKLMNOP I..P integers from 0 to 7.\n"
0249               "                I: action flag for low interest RUs\n"
0250               "                J: action flag for single RUs\n"
0251               "                K: action flag for neighbour RUs\n"
0252               "                L: action flag for centers RUs\n"
0253               "                M: action flag for forced low interest RUs\n"
0254               "                N: action flag for forced single RUs\n"
0255               "                O: action flag for forced neighbour RUs\n"
0256               "                P: action flag for forced centers RUs\n\n"
0257               " -h, --help display this help\n"
0258               " -a n, --ab n specifies indices of the AB whose file must be "
0259               "produced. The ab number runs from 1 to 12. Use -1 to produce "
0260               "files "
0261               "for every AB\n\n";
0262 
0263       return 0;
0264     }
0265 
0266     if (!strcmp(argv[iarg], "-A") || !strcmp(argv[iarg], "-A")) {  // actions
0267       if (++iarg >= argc) {
0268         cout << "Option error. Try -h\n";
0269         return 1;
0270       }
0271       for (int i = 0; i < 8; ++i) {
0272         int act = argv[iarg][i] - '0';
0273         if (act < 0 || act >= nactions) {
0274           cout << "Error. Action argument is invalid.\n";
0275           return 1;
0276         } else {
0277           actions[i] = (roAction_t)act;
0278         }
0279       }
0280       continue;
0281     }
0282     if (!strcmp(argv[iarg], "-a") || !strcmp(argv[iarg], "--ab")) {
0283       if (++iarg >= argc) {
0284         cout << "Option error. Try -h\n";
0285         return 1;
0286       }
0287       theAB = strtoul(argv[iarg], nullptr, 0);
0288       if (theAB >= 0)
0289         --theAB;
0290       if (theAB < -1 || theAB > 11) {
0291         cout << "AB number is incorrect. Try -h option to get help.\n";
0292       }
0293       continue;
0294     }
0295   }
0296 
0297   for (size_t i = 0; i < sizeof(srp2roFlags) / sizeof(srp2roFlags[0]); srp2roFlags[i++] = '?')
0298     ;
0299   for (size_t i = 0; i < sizeof(actions) / sizeof(actions[0]); ++i) {
0300     srp2roFlags[(int)srpFlagMarker[i]] = roFlagMarker[actions[i]];
0301   }
0302 
0303   for (int iEE = 0; iEE < nEndcaps; ++iEE) {
0304     for (int iY = 0; iY < nSupercrystalXBins; ++iY) {
0305       for (int iX = 0; iX < nSupercrystalYBins; ++iX) {
0306         int iDCCPhi = dccPhiIndexOfRU(iEE == 0 ? 0 : 2, iX, iY);
0307         if (iDCCPhi >= 0) {  // SC exists
0308           ecalDccSC[iEE][iDCCPhi].push_back(pair<int, int>(iX, iY));
0309         }
0310       }
0311     }
0312   }
0313 
0314   stringstream s;
0315   for (int iAB = 0; iAB < nAB; ++iAB) {
0316     if (theAB != -1 && theAB != iAB)
0317       continue;
0318     s.str("");
0319     s << abTTFFilePrefix << (iAB < 9 ? "0" : "") << iAB + 1 << abTTFFilePostfix;
0320     abTTFFiles[iAB].open(s.str().c_str(), ios::out);
0321     writeABTTFFileHeader(abTTFFiles[iAB], iAB);
0322     s.str("");
0323     s << abSRFFilePrefix << (iAB < 9 ? "0" : "") << iAB + 1 << abSRFFilePostfix;
0324     abSRFFiles[iAB].open(s.str().c_str(), ios::out);
0325     writeABSRFFileHeader(abSRFFiles[iAB], iAB);
0326     s.str("");
0327     s << abIOFilePrefix << (iAB < 9 ? "0" : "") << iAB + 1 << abIOFilePostfix;
0328     abIOFiles[iAB].open(s.str().c_str(), ios::out);
0329     writeABIOFileHeader(abIOFiles[iAB], iAB);
0330   }
0331 
0332   FILE *srfFile = fopen(srfFilename, "r");
0333   if (srfFile == nullptr) {
0334     cerr << "Failed to open SRF file, " << srfFilename << endl;
0335     exit(EXIT_FAILURE);
0336   }
0337 
0338   FILE *ttfFile = fopen(ttfFilename, "r");
0339   if (ttfFile == nullptr) {
0340     cerr << "Failed to open TTF file, " << ttfFilename << endl;
0341     exit(EXIT_FAILURE);
0342   }
0343 
0344   iEvent = 0;
0345   while (readSRF(srfFile, barrelSrFlags, endcapSrFlags) && readTTF(ttfFile, ttFlags)) {
0346     if (iEvent % 100 == 0) {
0347       cout << "Event " << iEvent << endl;
0348     }
0349     fillABTTFFiles(ttFlags, abTTFFiles);
0350     fillABSRPFiles(barrelSrFlags, endcapSrFlags, abSRFFiles);
0351     fillABIOFiles(ttFlags, barrelSrFlags, endcapSrFlags, abIOFiles);
0352     ++iEvent;
0353   }
0354 
0355   return 0;
0356 }
0357 
0358 /** Produces one file per AB. Each file contains the TT flags
0359  * the AB receives from its inputs.
0360  */
0361 void fillABTTFFiles(const char ttFlags[nTTInEta][nTTInPhi], ofstream files[]) {
0362   for (int iABEta = 0; iABEta < nABInEta; ++iABEta) {
0363     for (int iABPhi = 0; iABPhi < nABInPhi; ++iABPhi) {
0364       int iAB = abNum(iABEta, iABPhi);
0365       int iTTPhiMin;
0366       int iTTPhiMax;
0367       getABTTPhiBounds(iABPhi, iTTPhiMin, iTTPhiMax);
0368       //      writeEventHeader(files[iAB], iEvent, nTTInABAlongPhi);
0369       files[iAB] << "# Event " << iEvent << "\n";
0370 
0371       for (int i = 0; i <= iTTEtaMax[iABEta] - iTTEtaMin[iABEta]; ++i) {
0372         int iTTEta;
0373         if (iTTEtaSign[iABEta] > 0) {
0374           iTTEta = iTTEtaMin[iABEta] + i;
0375         } else {
0376           iTTEta = iTTEtaMax[iABEta] - i;
0377         }
0378         for (int iTTPhi = iTTPhiMin; mod(iTTPhiMax - iTTPhi, nTTInPhi) < nTTInABAlongPhi;
0379              iTTPhi = mod(++iTTPhi, nTTInPhi)) {
0380           files[iAB] << ttFlags[iTTEta][iTTPhi];
0381         }
0382         files[iAB] << "\n";
0383       }
0384       files[iAB] << "#\n";
0385       // writeEventTrailer(files[iAB], nTTInABAlongPhi);
0386     }
0387   }
0388 }
0389 
0390 void fillABSRPFiles(const char barrelSrFlags[nBarrelTTInEta][nTTInPhi],
0391                     const char endcapSrFlags[nEndcaps][nSupercrystalXBins][nSupercrystalYBins],
0392                     ofstream files[]) {
0393   // event headers:
0394   for (int iAB = 0; iAB < nAB; ++iAB) {
0395     files[iAB] << "# Event " << iEvent << "\n";
0396   }
0397 
0398   bool lineAppended[nAB];
0399   for (int i = 0; i < nAB; lineAppended[i++] = false) /*empty*/
0400     ;
0401 
0402   // EE:
0403   for (int iEE = 0; iEE < nEndcaps; ++iEE) {
0404     for (int iX = 0; iX < nSupercrystalXBins; ++iX) {
0405       for (int iY = 0; iY < nSupercrystalYBins; ++iY) {
0406         //        int iDCC = dccIndex(iEE==0?0:2,iX*5,iY*5);
0407         int iDCC = dccIndexOfRU(iEE == 0 ? 0 : 2, iX, iY);
0408         if (iDCC >= 0) {
0409           int iAB = abOfDcc(iDCC);
0410           if (!lineAppended[iAB]) {
0411             for (int i = 0; i < iY; ++i)
0412               files[iAB] << ' ';
0413           }
0414           files[iAB] << srp2roFlags[(int)endcapSrFlags[iEE][iX][iY]];
0415           lineAppended[iAB] = true;
0416         }
0417       }  // next iY
0418       for (int iFile = 0; iFile < nAB; ++iFile) {
0419         if (lineAppended[iFile]) {
0420           files[iFile] << "\n";
0421           lineAppended[iFile] = false;
0422         }
0423       }
0424     }  // next iX
0425   }
0426 
0427   // EB:
0428   for (int iABEta = 1; iABEta < 3; ++iABEta) {
0429     for (int iABPhi = 0; iABPhi < nABInPhi; ++iABPhi) {
0430       int iAB = abNum(iABEta, iABPhi);
0431       int iTTPhiMin;
0432       int iTTPhiMax;
0433       getABTTPhiBounds(iABPhi, iTTPhiMin, iTTPhiMax);
0434       // writeEventHeader(files[iAB], iEvent, nTTInABAlongPhi);
0435       for (int i = 0; i <= iTTEtaMax[iABEta] - iTTEtaMin[iABEta]; ++i) {
0436         int iTTEta;
0437         if (iTTEtaSign[iABEta] > 0) {
0438           iTTEta = iTTEtaMin[iABEta] + i;
0439         } else {
0440           iTTEta = iTTEtaMax[iABEta] - i;
0441         }
0442         for (int iTTPhi = iTTPhiMin; mod(iTTPhiMax - iTTPhi, nTTInPhi) < nTTInABAlongPhi;
0443              iTTPhi = mod(++iTTPhi, nTTInPhi)) {
0444           files[iAB] << srp2roFlags[(int)barrelSrFlags[iTTEta - nEndcapTTInEta][iTTPhi]];
0445         }
0446         files[iAB] << "\n";
0447       }
0448       //      writeEventTrailer(files[iAB], nTTInABAlongPhi);
0449       files[iAB] << "#\n";
0450     }
0451   }
0452 
0453   // file trailers
0454   for (int iAB = 0; iAB < nAB; ++iAB) {
0455     files[iAB] << "#\n";
0456   }
0457 }
0458 
0459 void fillABIOFiles(const char ttFlags[nTTInEta][nTTInPhi],
0460                    const char barrelSrFlags[nBarrelTTInEta][nTTInPhi],
0461                    const char endcapSrFlags[nEndcaps][nSupercrystalXBins][nSupercrystalYBins],
0462                    ofstream files[]) {
0463   for (int iABEta = 0; iABEta < nABInEta; ++iABEta) {
0464     for (int iABPhi = 0; iABPhi < nABInPhi; ++iABPhi) {
0465       int iAB = abNum(iABEta, iABPhi);
0466       //      writeABIOFileHeader(files[iAB], iAB);
0467       files[iAB] << "# Event " << iEvent << "\n";
0468       // TCC inputs:
0469       for (int iTCC = 0; iTCC < nABTCCCh; ++iTCC) {
0470         files[iAB] << "ITCC" << iTCC + 1 << ":" << getABTCCInputStream(ttFlags, iABEta, iABPhi, iTCC) << "\n";
0471       }
0472       // AB inputs:
0473       for (int iABCh = 0; iABCh < nABABCh; ++iABCh) {
0474         files[iAB] << "IAB" << iABCh + 1 << ":" << getABABInputStream(ttFlags, iABEta, iABPhi, iABCh) << "\n";
0475       }
0476       // AB outputs:
0477       for (int iABCh = 0; iABCh < nABABCh; ++iABCh) {
0478         files[iAB] << "OAB" << iABCh + 1 << ":" << getABABOutputStream(ttFlags, iABEta, iABPhi, iABCh) << "\n";
0479       }
0480       // DCC output:
0481       for (int iDCCCh = 0; iDCCCh < nDCCCh; ++iDCCCh) {
0482         files[iAB] << "ODCC";
0483         files[iAB] << (iDCCCh <= 8 ? "0" : "") << iDCCCh + 1 << ":"
0484                    << getABDCCOutputStream(barrelSrFlags, endcapSrFlags, iABEta, iABPhi, iDCCCh) << "\n";
0485       }
0486       files[iAB] << "#\n";
0487     }
0488   }
0489 }
0490 
0491 /*
0492   stringstream filename;
0493   filename.str("");
0494   filename << abTTFFilePrefix << abNum(iABEta, iABPhi) <<abTTFFilePostfix;
0495   ofstream file(filename.str(), ios::ate);
0496 
0497 */
0498 
0499 bool readTTF(FILE *f, char ttFlags[nTTInEta][nTTInPhi]) {
0500   char *buffer = nullptr;
0501   size_t bufferSize = 0;
0502   int read;
0503   if (f == nullptr)
0504     exit(EXIT_FAILURE);
0505   int line = 0;
0506   int iEta = 0;
0507   while (iEta < nTTInEta && (read = getline(&buffer, &bufferSize, f)) != -1) {
0508     ++line;
0509     char *pos = buffer;
0510     while (*pos == ' ' || *pos == '\t')
0511       ++pos;                            // skip spaces
0512     if (*pos != '#' && *pos != '\n') {  // not a comment line nor an empty line
0513       if (read - 1 != nTTInPhi) {
0514         cerr << "Error: line " << line << " of file " << ttfFilename
0515              << " has incorrect length"
0516              //             << " (" << read-1 << " instead of " << nTTInPhi <<
0517              //             ")"
0518              << endl;
0519         exit(EXIT_FAILURE);
0520       }
0521       for (int iPhi = 0; iPhi < nTTInPhi; ++iPhi) {
0522         ttFlags[iEta][iPhi] = buffer[iPhi];
0523         //         if(ttFlags[iEta][iPhi]!='.'){
0524         //           cout << __FILE__ << ":" << __LINE__ << ": "
0525         //                << iEta << "," << iPhi
0526         //                << " " << ttFlags[iEta][iPhi] << "\n";
0527         //         }
0528       }
0529       ++iEta;
0530     }
0531   }
0532   // returns true if all TT were read (not at end of file)
0533   return (iEta == nTTInEta) ? true : false;
0534 }
0535 
0536 bool readSRF(FILE *f,
0537              char barrelSrFlags[nBarrelTTInEta][nTTInPhi],
0538              char endcapSrFlags[nEndcaps][nSupercrystalXBins][nSupercrystalYBins]) {
0539   char *buffer = nullptr;
0540   size_t bufferSize = 0;
0541   int read;
0542   if (f == nullptr)
0543     exit(EXIT_FAILURE);
0544   int line = 0;
0545   int iEta = 0;
0546   int iXm = 0;
0547   int iXp = 0;
0548   int iReadLine = 0;  // number of read line, comment lines excluded
0549   // number of non-comment lines to read:
0550   const int nReadLine = nBarrelTTInEta + nEndcaps * nSupercrystalXBins;
0551   while (iReadLine < nReadLine && (read = getline(&buffer, &bufferSize, f)) != -1) {
0552     ++line;
0553     char *pos = buffer;
0554     while (*pos == ' ' || *pos == '\t')
0555       ++pos;                            // skip spaces
0556     if (*pos != '#' && *pos != '\n') {  // not a comment line nor an empty line
0557       // go back to beginning of line:
0558       pos = buffer;
0559       if (iReadLine < nSupercrystalXBins) {  // EE- reading
0560         if (read - 1 != nSupercrystalYBins) {
0561           cerr << "Error: line " << line << " of file " << srfFilename << " has incorrect length"
0562                << " (" << read - 1 << " instead of " << nSupercrystalYBins << ")" << endl;
0563           exit(EXIT_FAILURE);
0564         }
0565         for (int iY = 0; iY < nSupercrystalYBins; ++iY) {
0566           endcapSrFlags[0][iXm][iY] = buffer[iY];
0567         }
0568         ++iXm;
0569       } else if (iReadLine < nSupercrystalYBins + nBarrelTTInEta) {  // EB
0570                                                                      // reading
0571         if (read - 1 != nTTInPhi) {
0572           cerr << "Error: line " << line << " of file " << srfFilename << " has incorrect length"
0573                << " (" << read - 1 << " instead of " << nTTInPhi << ")" << endl;
0574           exit(EXIT_FAILURE);
0575         }
0576         for (int iPhi = 0; iPhi < nTTInPhi; ++iPhi) {
0577           barrelSrFlags[iEta][iPhi] = buffer[iPhi];
0578         }
0579         ++iEta;
0580       } else if (iReadLine < 2 * nSupercrystalXBins + nBarrelTTInEta) {  // EE+ reading
0581         if (read - 1 != nSupercrystalYBins) {
0582           cerr << "Error: line " << line << " of file " << srfFilename << " has incorrect length"
0583                << " (" << read - 1 << " instead of " << nSupercrystalYBins << ")" << endl;
0584           exit(EXIT_FAILURE);
0585         }
0586         for (int iY = 0; iY < nSupercrystalYBins; ++iY) {
0587           endcapSrFlags[1][iXp][iY] = buffer[iY];
0588         }
0589         ++iXp;
0590       }
0591       ++iReadLine;
0592     }  // not a comment or empty line
0593   }
0594   // returns 0 if all TT were read:
0595   return (iReadLine == nReadLine) ? true : false;
0596 }
0597 
0598 // void writeEventHeader(ofstream& f, int iEvent, int nPhi){
0599 //   //event header:
0600 //   stringstream header;
0601 //   header.str("");
0602 //   header << " event " << iEvent << " ";
0603 //   f << "+";
0604 //   for(int iPhi = 0; iPhi < nPhi; ++iPhi){
0605 //     if(iPhi == (int)(nPhi-header.str().size())/2){
0606 //       f << header.str();
0607 //       iPhi += header.str().size()-1;
0608 //     } else{
0609 //       f << "-";
0610 //     }
0611 //   }
0612 //   f << "+\n";
0613 // }
0614 
0615 // void writeEventTrailer(ofstream& f, int nPhi){
0616 //   f << "+";
0617 //   for(int iPhi = 0; iPhi < nPhi; ++iPhi) f << "-";
0618 //   f << "+\n";
0619 // }
0620 
0621 void writeABTTFFileHeader(ofstream &f, int abNum) {
0622   time_t t;
0623   time(&t);
0624   const char *date = ctime(&t);
0625   f << "# TTF flag map covered by AB " << abNum + 1
0626     << "\n#\n"
0627        "# Generated on : "
0628     << date
0629     << "#\n"
0630        "# +---> Phi          "
0631     << srpFlagMarker[0]
0632     << ": 000 (low interest)\n"
0633        "# |                  "
0634     << srpFlagMarker[1]
0635     << ": 001 (single)\n"
0636        "# |                  "
0637     << srpFlagMarker[2]
0638     << ": 010 (neighbour)\n"
0639        "# V |Eta|            "
0640     << srpFlagMarker[3]
0641     << ": 011 (center)\n"
0642        "#\n";
0643 }
0644 
0645 void writeABSRFFileHeader(ofstream &f, int abNum) {
0646   time_t t;
0647   time(&t);
0648   const char *date = ctime(&t);
0649   const char *xLabel;
0650   const char *yLabel;
0651   if (abNum < 3 || abNum > 8) {  // endcap
0652     xLabel = "Y  ";
0653     yLabel = "X    ";
0654   } else {  // barrel
0655     xLabel = "Phi";
0656     yLabel = "|Eta|";
0657   }
0658   f << "# SRF flag map covered by AB " << abNum + 1
0659     << "\n#\n"
0660        "# Generated on : "
0661     << date
0662     << "#\n"
0663        "# +---> "
0664     << xLabel << "          " << roFlagMarker[0]
0665     << ": 000 (suppress)\n"
0666        "# |                  "
0667     << roFlagMarker[1]
0668     << ": 010 (SR Threshold 2)\n"
0669        "# |                  "
0670     << roFlagMarker[2]
0671     << ": 001 (SR Threshold 1)\n"
0672        "# V "
0673     << yLabel << "            " << roFlagMarker[3]
0674     << ": 011 (Full readout)\n"
0675        "#\n"
0676        "# action table (when forced):\n"
0677        "# LI-> "
0678     << roFlagMarker[actions[0]] << " (" << roFlagMarker[actions[4]] << ")"
0679     << "\n"
0680        "# S -> "
0681     << roFlagMarker[actions[1]] << " (" << roFlagMarker[actions[5]] << ")"
0682     << "\n"
0683        "# N -> "
0684     << roFlagMarker[actions[2]] << " (" << roFlagMarker[actions[6]] << ")"
0685     << "\n"
0686        "# C -> "
0687     << roFlagMarker[actions[3]] << " (" << roFlagMarker[actions[7]] << ")"
0688     << "\n";
0689 }
0690 
0691 void writeABIOFileHeader(ofstream &f, int abNum) {
0692   time_t t;
0693   time(&t);
0694   const char *date = ctime(&t);
0695   f << "# AB " << abNum + 1
0696     << " I/O \n#\n"
0697        "# Generated on : "
0698     << date
0699     << "#\n"
0700        "# "
0701     << srpFlagMarker[0] << ": 000 (low interest)   " << tccFlagMarker[0] << ": 000 (low interest)   " << roFlagMarker[0]
0702     << ": 000 (suppress)\n"
0703        "# "
0704     << srpFlagMarker[1] << ": 001 (single)         " << tccFlagMarker[1] << ": 001 (mid interest)   " << roFlagMarker[1]
0705     << ": 010 (SR Threshold 2)\n"
0706        "# "
0707     << srpFlagMarker[2] << ": 010 (neighbour)      " << tccFlagMarker[2] << ": 010 (not valid)      " << roFlagMarker[2]
0708     << ": 001 (SR Threshold 1)\n"
0709        "# "
0710     << srpFlagMarker[3] << ": 011 (center)         " << tccFlagMarker[3] << ": 011 (high interest)  " << roFlagMarker[3]
0711     << ": 011 (Full readout)\n"
0712        "#\n"
0713        "# action table (when forced):\n"
0714        "# LI-> "
0715     << roFlagMarker[actions[0]] << " (" << roFlagMarker[actions[4]] << ")"
0716     << "\n"
0717        "# S -> "
0718     << roFlagMarker[actions[1]] << " (" << roFlagMarker[actions[5]] << ")"
0719     << "\n"
0720        "# N -> "
0721     << roFlagMarker[actions[2]] << " (" << roFlagMarker[actions[6]] << ")"
0722     << "\n"
0723        "# C -> "
0724     << roFlagMarker[actions[3]] << " (" << roFlagMarker[actions[7]] << ")"
0725     << "\n"
0726        "#\n";
0727 }
0728 
0729 string getFlagStream(const char flags[nTTInEta][nTTInPhi], int iEtaMin, int iEtaMax, int iPhiMin, int iPhiMax) {
0730   assert(0 <= iEtaMin && iEtaMin <= iEtaMax && iEtaMax < nTTInEta);
0731   if (iEtaMin <= nTTInEta / 2 && iEtaMax > nTTInEta) {
0732     cerr << "Implementation Errror:" << __FILE__ << ":" << __LINE__
0733          << ": A flag stream cannot covers parts of both half-ECAL!" << endl;
0734     exit(EXIT_FAILURE);
0735   }
0736 
0737   bool zPos = (iEtaMin >= nTTInEta / 2);
0738 
0739   stringstream buffer;
0740   buffer.str("");
0741   for (int jEta = 0; jEta <= iEtaMax - iEtaMin; ++jEta) {
0742     // loops on iEta in |eta| increasing order:
0743     int iEta;
0744     if (zPos) {
0745       iEta = iEtaMin + jEta;
0746     } else {
0747       iEta = iEtaMax - jEta;
0748     }
0749 
0750     for (int iPhi = mod(iPhiMin, nTTInPhi); mod(iPhiMax + 1 - iPhi, nTTInPhi) != 0; iPhi = mod(++iPhi, nTTInPhi)) {
0751       buffer << flags[iEta][iPhi];
0752     }
0753   }
0754 
0755   return buffer.str();
0756 }
0757 
0758 string getABTCCInputStream(const char tccFlags[nTTInEta][nTTInPhi], int iABEta, int iABPhi, int iTCCCh) {
0759   // gets eta bounds for this tcc channel:
0760   int iTCCEta;
0761   if (iABEta == 1 || iABEta == 2) {  // barrel
0762     if (iTCCCh > 5)
0763       return "";  // only 6 TCCs per AB for barrel
0764     iTCCEta = 1 + iABEta;
0765   } else {              // endcap
0766     if (iABEta == 0) {  // EE-
0767       iTCCEta = (iTCCCh < 6) ? 1 : 0;
0768     } else {  // EE+
0769       iTCCEta = (iTCCCh < 6) ? 4 : 5;
0770     }
0771   }
0772   int iEtaMin = iTCCEtaBounds[iTCCEta];
0773   int iEtaMax = iTCCEtaBounds[iTCCEta + 1] - 1;
0774 
0775   // gets phi bounds:
0776   int iPhiMin;
0777   int iPhiMax;
0778   getABTTPhiBounds(iABPhi, iPhiMin, iPhiMax);
0779   // phi is increasing with TTC channel number
0780   // a TTC covers a 4TT-wide phi-sector
0781   //=>iPhiMin(iTTCCh) = iPhiMin(AB) + 4*iTTCCh for iTCCCh<6
0782   iPhiMin += 4 * (iTCCCh % 6);
0783   iPhiMax = iPhiMin + 4 - 1;
0784 
0785   return getFlagStream(tccFlags, iEtaMin, iEtaMax, iPhiMin, iPhiMax);
0786 }
0787 
0788 string getABABOutputStream(const char tccFlags[nTTInEta][nTTInPhi], int iABEta, int iABPhi, int iABCh) {
0789   stringstream buffer;
0790   buffer.str("");
0791   bool barrel = (iABEta == 1 || iABEta == 2);  // true for barrel, false for endcap
0792   switch (iABCh) {
0793     case 0:
0794       // to AB ch #0 are sent the 16 1st TCC flags received on TCC input Ch. 0
0795       buffer << getABTCCInputStream(tccFlags, iABEta, iABPhi, 0).substr(0, 16);
0796       break;
0797     case 1:
0798       // to AB ch #1 are sent the 16 1st TCC flags received on TCC input Ch. 0 to
0799       // 5:
0800       for (int iTCCCh = 0; iTCCCh < 6; ++iTCCCh) {
0801         buffer << getABTCCInputStream(tccFlags, iABEta, iABPhi, iTCCCh).substr(0, 16);
0802       }
0803       break;
0804     case 2:
0805       // to AB ch #2 are sent the 16 1st TCC flags received on TCC input Ch. 5:
0806       buffer << getABTCCInputStream(tccFlags, iABEta, iABPhi, 5).substr(0, 16);
0807       break;
0808     case 3:
0809       // to AB ch #3 are sent TCC flags received on TCC input Ch. 0 and 6:
0810       buffer << getABTCCInputStream(tccFlags, iABEta, iABPhi, 0);
0811       buffer << getABTCCInputStream(tccFlags, iABEta, iABPhi, 6);
0812       break;
0813     case 4:
0814       // to AB ch #4 are sent TCC flags received on TCC input Ch 5 and 11:
0815       buffer << getABTCCInputStream(tccFlags, iABEta, iABPhi, 5);
0816       buffer << getABTCCInputStream(tccFlags, iABEta, iABPhi, 11);
0817       break;
0818     case 5:
0819       // for endcaps AB output ch 5 is not used.
0820       // for barrel, to AB ch #5 are sent the 16 last TCC flags received on TCC
0821       // input Ch. 0:
0822       if (barrel) {  // in barrel
0823         string s = getABTCCInputStream(tccFlags, iABEta, iABPhi, 0);
0824         assert(s.size() >= 16);
0825         buffer << s.substr(s.size() - 16, 16);
0826       }
0827       break;
0828     case 6:
0829       // for endcaps AB output ch 6 is not used.
0830       // for barrel, to AB ch #6 are sent the 16 last TCC flags received on TCC
0831       // input Ch. 0 to 5:
0832       if (barrel) {  // in barrel
0833         for (int iTCCCh = 0; iTCCCh < 6; ++iTCCCh) {
0834           string s = getABTCCInputStream(tccFlags, iABEta, iABPhi, iTCCCh);
0835           buffer << s.substr(s.size() - 16, 16);
0836         }
0837       }
0838       break;
0839     case 7:
0840       // for endcaps AB output ch 7 is not used.
0841       // for barrel, to AB ch #7 are sent the 16 last TCC flags received on TCC
0842       // input Ch. 5:
0843       if (barrel) {  // in barrel
0844         string s = getABTCCInputStream(tccFlags, iABEta, iABPhi, 5);
0845         assert(s.size() >= 16);
0846         buffer << s.substr(s.size() - 16, 16);
0847       }
0848       break;
0849     default:
0850       assert(false);
0851   }
0852   return buffer.str();
0853 }
0854 
0855 string getABABInputStream(const char tccFlags[nTTInEta][nTTInPhi], int iABEta, int iABPhi, int iABCh) {
0856   int iAB = abNum(iABEta, iABPhi);
0857   int iOtherAB;    // AB which this channel is connected to
0858   int iOtherABCh;  // ch # on the other side of the AB-AB link
0859   abConnect(iAB, iABCh, iOtherAB, iOtherABCh);
0860   int iOtherABEta = iOtherAB / 3;
0861   int iOtherABPhi = iOtherAB % 3;
0862   return getABABOutputStream(tccFlags, iOtherABEta, iOtherABPhi, iOtherABCh);
0863 }
0864 
0865 void getABTTPhiBounds(int iABPhi, int &iTTPhiMin, int &iTTPhiMax) {
0866   iTTPhiMin = mod(-6 + iABPhi * nTTInABAlongPhi, nTTInPhi);
0867   iTTPhiMax = mod(iTTPhiMin + nTTInABAlongPhi - 1, nTTInPhi);
0868 }
0869 
0870 void abConnect(int iAB, int iABCh, int &iOtherAB, int &iOtherABCh) {
0871   static bool firstCall = true;
0872   static int xconnectMap[nAB][nABABCh][2];
0873   if (firstCall) {
0874     FILE *f = fopen(xconnectFilename, "r");
0875     if (f == nullptr) {
0876       cerr << "Error. Failed to open xconnect definition file," << xconnectFilename << endl;
0877       exit(EXIT_FAILURE);
0878     }
0879     // skips two first lines:
0880     for (int i = 0; i < 2; ++i) {
0881       int c;
0882       while ((c = getc(f)) != '\n' && c >= 0)
0883         ;
0884     }
0885     int ilink = 0;
0886     while (!feof(f)) {
0887       int abIn;
0888       int pinIn;
0889       int abOut;
0890       int pinOut;
0891       if (4 == fscanf(f, "%d\t%d\t%d\t%d", &abIn, &pinIn, &abOut, &pinOut)) {
0892         xconnectMap[abIn][pinIn][0] = abOut;
0893         xconnectMap[abIn][pinIn][1] = pinOut;
0894         ++ilink;
0895       }
0896     }
0897     if (ilink != nAB * nABABCh) {
0898       cerr << "Error cross-connect definition file " << xconnectFilename
0899            << " contains an unexpected number of link definition." << endl;
0900       exit(EXIT_FAILURE);
0901     }
0902     firstCall = false;
0903   }
0904 
0905   iOtherAB = xconnectMap[iAB][iABCh][0];
0906   iOtherABCh = xconnectMap[iAB][iABCh][1];
0907 }
0908 
0909 string getABDCCOutputStream(const char barrelSrFlags[nBarrelTTInEta][nTTInPhi],
0910                             const char endcapSrFlags[nEndcaps][nSupercrystalXBins][nSupercrystalYBins],
0911                             int iABEta,
0912                             int iABPhi,
0913                             int iDCCCh) {
0914   bool barrel = (iABEta == 1 || iABEta == 2);
0915   if (barrel) {
0916     // same as TCC with same ch number but with TCC flags replaced by SRP flags:
0917     string stream = getABTCCInputStream(barrelSrFlags - nEndcapTTInEta, iABEta, iABPhi, iDCCCh);
0918     // converts srp flags to readout flags:
0919     for (size_t i = 0; i < stream.size(); ++i) {
0920       stream[i] = srp2roFlags[(int)stream[i]];
0921     }
0922     return stream;
0923   } else {             // endcap
0924     if (iDCCCh < 3) {  // used DCC output channel
0925       // endcap index:
0926       int iEE = (iABEta == 0) ? 0 : 1;
0927       stringstream buffer("");
0928       // 3 DCC per AB and AB DCC output channel in
0929       // increasing DCC phi position:
0930       int iDCCPhi = iABPhi * 3 + iDCCCh;
0931       for (size_t iSC = 0; iSC < ecalDccSC[iEE][iDCCPhi].size(); ++iSC) {
0932         pair<int, int> sc = ecalDccSC[iEE][iDCCPhi][iSC];
0933         buffer << srp2roFlags[(int)endcapSrFlags[iEE][sc.first][sc.second]];
0934       }
0935       return buffer.str();
0936     } else {  // unused output channel
0937       return "";
0938     }
0939   }
0940 }