Back to home page

Project CMSSW displayed by LXR

 
 

    


File indexing completed on 2024-10-04 22:55:03

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       if (iReadLine < nSupercrystalXBins) {  // EE- reading
0558         if (read - 1 != nSupercrystalYBins) {
0559           cerr << "Error: line " << line << " of file " << srfFilename << " has incorrect length"
0560                << " (" << read - 1 << " instead of " << nSupercrystalYBins << ")" << endl;
0561           exit(EXIT_FAILURE);
0562         }
0563         for (int iY = 0; iY < nSupercrystalYBins; ++iY) {
0564           endcapSrFlags[0][iXm][iY] = buffer[iY];
0565         }
0566         ++iXm;
0567       } else if (iReadLine < nSupercrystalYBins + nBarrelTTInEta) {  // EB
0568                                                                      // reading
0569         if (read - 1 != nTTInPhi) {
0570           cerr << "Error: line " << line << " of file " << srfFilename << " has incorrect length"
0571                << " (" << read - 1 << " instead of " << nTTInPhi << ")" << endl;
0572           exit(EXIT_FAILURE);
0573         }
0574         for (int iPhi = 0; iPhi < nTTInPhi; ++iPhi) {
0575           barrelSrFlags[iEta][iPhi] = buffer[iPhi];
0576         }
0577         ++iEta;
0578       } else if (iReadLine < 2 * nSupercrystalXBins + nBarrelTTInEta) {  // EE+ reading
0579         if (read - 1 != nSupercrystalYBins) {
0580           cerr << "Error: line " << line << " of file " << srfFilename << " has incorrect length"
0581                << " (" << read - 1 << " instead of " << nSupercrystalYBins << ")" << endl;
0582           exit(EXIT_FAILURE);
0583         }
0584         for (int iY = 0; iY < nSupercrystalYBins; ++iY) {
0585           endcapSrFlags[1][iXp][iY] = buffer[iY];
0586         }
0587         ++iXp;
0588       }
0589       ++iReadLine;
0590     }  // not a comment or empty line
0591   }
0592   // returns 0 if all TT were read:
0593   return (iReadLine == nReadLine) ? true : false;
0594 }
0595 
0596 // void writeEventHeader(ofstream& f, int iEvent, int nPhi){
0597 //   //event header:
0598 //   stringstream header;
0599 //   header.str("");
0600 //   header << " event " << iEvent << " ";
0601 //   f << "+";
0602 //   for(int iPhi = 0; iPhi < nPhi; ++iPhi){
0603 //     if(iPhi == (int)(nPhi-header.str().size())/2){
0604 //       f << header.str();
0605 //       iPhi += header.str().size()-1;
0606 //     } else{
0607 //       f << "-";
0608 //     }
0609 //   }
0610 //   f << "+\n";
0611 // }
0612 
0613 // void writeEventTrailer(ofstream& f, int nPhi){
0614 //   f << "+";
0615 //   for(int iPhi = 0; iPhi < nPhi; ++iPhi) f << "-";
0616 //   f << "+\n";
0617 // }
0618 
0619 void writeABTTFFileHeader(ofstream &f, int abNum) {
0620   time_t t;
0621   time(&t);
0622   const char *date = ctime(&t);
0623   f << "# TTF flag map covered by AB " << abNum + 1
0624     << "\n#\n"
0625        "# Generated on : "
0626     << date
0627     << "#\n"
0628        "# +---> Phi          "
0629     << srpFlagMarker[0]
0630     << ": 000 (low interest)\n"
0631        "# |                  "
0632     << srpFlagMarker[1]
0633     << ": 001 (single)\n"
0634        "# |                  "
0635     << srpFlagMarker[2]
0636     << ": 010 (neighbour)\n"
0637        "# V |Eta|            "
0638     << srpFlagMarker[3]
0639     << ": 011 (center)\n"
0640        "#\n";
0641 }
0642 
0643 void writeABSRFFileHeader(ofstream &f, int abNum) {
0644   time_t t;
0645   time(&t);
0646   const char *date = ctime(&t);
0647   const char *xLabel;
0648   const char *yLabel;
0649   if (abNum < 3 || abNum > 8) {  // endcap
0650     xLabel = "Y  ";
0651     yLabel = "X    ";
0652   } else {  // barrel
0653     xLabel = "Phi";
0654     yLabel = "|Eta|";
0655   }
0656   f << "# SRF flag map covered by AB " << abNum + 1
0657     << "\n#\n"
0658        "# Generated on : "
0659     << date
0660     << "#\n"
0661        "# +---> "
0662     << xLabel << "          " << roFlagMarker[0]
0663     << ": 000 (suppress)\n"
0664        "# |                  "
0665     << roFlagMarker[1]
0666     << ": 010 (SR Threshold 2)\n"
0667        "# |                  "
0668     << roFlagMarker[2]
0669     << ": 001 (SR Threshold 1)\n"
0670        "# V "
0671     << yLabel << "            " << roFlagMarker[3]
0672     << ": 011 (Full readout)\n"
0673        "#\n"
0674        "# action table (when forced):\n"
0675        "# LI-> "
0676     << roFlagMarker[actions[0]] << " (" << roFlagMarker[actions[4]] << ")"
0677     << "\n"
0678        "# S -> "
0679     << roFlagMarker[actions[1]] << " (" << roFlagMarker[actions[5]] << ")"
0680     << "\n"
0681        "# N -> "
0682     << roFlagMarker[actions[2]] << " (" << roFlagMarker[actions[6]] << ")"
0683     << "\n"
0684        "# C -> "
0685     << roFlagMarker[actions[3]] << " (" << roFlagMarker[actions[7]] << ")"
0686     << "\n";
0687 }
0688 
0689 void writeABIOFileHeader(ofstream &f, int abNum) {
0690   time_t t;
0691   time(&t);
0692   const char *date = ctime(&t);
0693   f << "# AB " << abNum + 1
0694     << " I/O \n#\n"
0695        "# Generated on : "
0696     << date
0697     << "#\n"
0698        "# "
0699     << srpFlagMarker[0] << ": 000 (low interest)   " << tccFlagMarker[0] << ": 000 (low interest)   " << roFlagMarker[0]
0700     << ": 000 (suppress)\n"
0701        "# "
0702     << srpFlagMarker[1] << ": 001 (single)         " << tccFlagMarker[1] << ": 001 (mid interest)   " << roFlagMarker[1]
0703     << ": 010 (SR Threshold 2)\n"
0704        "# "
0705     << srpFlagMarker[2] << ": 010 (neighbour)      " << tccFlagMarker[2] << ": 010 (not valid)      " << roFlagMarker[2]
0706     << ": 001 (SR Threshold 1)\n"
0707        "# "
0708     << srpFlagMarker[3] << ": 011 (center)         " << tccFlagMarker[3] << ": 011 (high interest)  " << roFlagMarker[3]
0709     << ": 011 (Full readout)\n"
0710        "#\n"
0711        "# action table (when forced):\n"
0712        "# LI-> "
0713     << roFlagMarker[actions[0]] << " (" << roFlagMarker[actions[4]] << ")"
0714     << "\n"
0715        "# S -> "
0716     << roFlagMarker[actions[1]] << " (" << roFlagMarker[actions[5]] << ")"
0717     << "\n"
0718        "# N -> "
0719     << roFlagMarker[actions[2]] << " (" << roFlagMarker[actions[6]] << ")"
0720     << "\n"
0721        "# C -> "
0722     << roFlagMarker[actions[3]] << " (" << roFlagMarker[actions[7]] << ")"
0723     << "\n"
0724        "#\n";
0725 }
0726 
0727 string getFlagStream(const char flags[nTTInEta][nTTInPhi], int iEtaMin, int iEtaMax, int iPhiMin, int iPhiMax) {
0728   assert(0 <= iEtaMin && iEtaMin <= iEtaMax && iEtaMax < nTTInEta);
0729   if (iEtaMin <= nTTInEta / 2 && iEtaMax > nTTInEta) {
0730     cerr << "Implementation Errror:" << __FILE__ << ":" << __LINE__
0731          << ": A flag stream cannot covers parts of both half-ECAL!" << endl;
0732     exit(EXIT_FAILURE);
0733   }
0734 
0735   bool zPos = (iEtaMin >= nTTInEta / 2);
0736 
0737   stringstream buffer;
0738   buffer.str("");
0739   for (int jEta = 0; jEta <= iEtaMax - iEtaMin; ++jEta) {
0740     // loops on iEta in |eta| increasing order:
0741     int iEta;
0742     if (zPos) {
0743       iEta = iEtaMin + jEta;
0744     } else {
0745       iEta = iEtaMax - jEta;
0746     }
0747 
0748     for (int iPhi = mod(iPhiMin, nTTInPhi); mod(iPhiMax + 1 - iPhi, nTTInPhi) != 0; iPhi = mod(++iPhi, nTTInPhi)) {
0749       buffer << flags[iEta][iPhi];
0750     }
0751   }
0752 
0753   return buffer.str();
0754 }
0755 
0756 string getABTCCInputStream(const char tccFlags[nTTInEta][nTTInPhi], int iABEta, int iABPhi, int iTCCCh) {
0757   // gets eta bounds for this tcc channel:
0758   int iTCCEta;
0759   if (iABEta == 1 || iABEta == 2) {  // barrel
0760     if (iTCCCh > 5)
0761       return "";  // only 6 TCCs per AB for barrel
0762     iTCCEta = 1 + iABEta;
0763   } else {              // endcap
0764     if (iABEta == 0) {  // EE-
0765       iTCCEta = (iTCCCh < 6) ? 1 : 0;
0766     } else {  // EE+
0767       iTCCEta = (iTCCCh < 6) ? 4 : 5;
0768     }
0769   }
0770   int iEtaMin = iTCCEtaBounds[iTCCEta];
0771   int iEtaMax = iTCCEtaBounds[iTCCEta + 1] - 1;
0772 
0773   // gets phi bounds:
0774   int iPhiMin;
0775   int iPhiMax;
0776   getABTTPhiBounds(iABPhi, iPhiMin, iPhiMax);
0777   // phi is increasing with TTC channel number
0778   // a TTC covers a 4TT-wide phi-sector
0779   //=>iPhiMin(iTTCCh) = iPhiMin(AB) + 4*iTTCCh for iTCCCh<6
0780   iPhiMin += 4 * (iTCCCh % 6);
0781   iPhiMax = iPhiMin + 4 - 1;
0782 
0783   return getFlagStream(tccFlags, iEtaMin, iEtaMax, iPhiMin, iPhiMax);
0784 }
0785 
0786 string getABABOutputStream(const char tccFlags[nTTInEta][nTTInPhi], int iABEta, int iABPhi, int iABCh) {
0787   stringstream buffer;
0788   buffer.str("");
0789   bool barrel = (iABEta == 1 || iABEta == 2);  // true for barrel, false for endcap
0790   switch (iABCh) {
0791     case 0:
0792       // to AB ch #0 are sent the 16 1st TCC flags received on TCC input Ch. 0
0793       buffer << getABTCCInputStream(tccFlags, iABEta, iABPhi, 0).substr(0, 16);
0794       break;
0795     case 1:
0796       // to AB ch #1 are sent the 16 1st TCC flags received on TCC input Ch. 0 to
0797       // 5:
0798       for (int iTCCCh = 0; iTCCCh < 6; ++iTCCCh) {
0799         buffer << getABTCCInputStream(tccFlags, iABEta, iABPhi, iTCCCh).substr(0, 16);
0800       }
0801       break;
0802     case 2:
0803       // to AB ch #2 are sent the 16 1st TCC flags received on TCC input Ch. 5:
0804       buffer << getABTCCInputStream(tccFlags, iABEta, iABPhi, 5).substr(0, 16);
0805       break;
0806     case 3:
0807       // to AB ch #3 are sent TCC flags received on TCC input Ch. 0 and 6:
0808       buffer << getABTCCInputStream(tccFlags, iABEta, iABPhi, 0);
0809       buffer << getABTCCInputStream(tccFlags, iABEta, iABPhi, 6);
0810       break;
0811     case 4:
0812       // to AB ch #4 are sent TCC flags received on TCC input Ch 5 and 11:
0813       buffer << getABTCCInputStream(tccFlags, iABEta, iABPhi, 5);
0814       buffer << getABTCCInputStream(tccFlags, iABEta, iABPhi, 11);
0815       break;
0816     case 5:
0817       // for endcaps AB output ch 5 is not used.
0818       // for barrel, to AB ch #5 are sent the 16 last TCC flags received on TCC
0819       // input Ch. 0:
0820       if (barrel) {  // in barrel
0821         string s = getABTCCInputStream(tccFlags, iABEta, iABPhi, 0);
0822         assert(s.size() >= 16);
0823         buffer << s.substr(s.size() - 16, 16);
0824       }
0825       break;
0826     case 6:
0827       // for endcaps AB output ch 6 is not used.
0828       // for barrel, to AB ch #6 are sent the 16 last TCC flags received on TCC
0829       // input Ch. 0 to 5:
0830       if (barrel) {  // in barrel
0831         for (int iTCCCh = 0; iTCCCh < 6; ++iTCCCh) {
0832           string s = getABTCCInputStream(tccFlags, iABEta, iABPhi, iTCCCh);
0833           buffer << s.substr(s.size() - 16, 16);
0834         }
0835       }
0836       break;
0837     case 7:
0838       // for endcaps AB output ch 7 is not used.
0839       // for barrel, to AB ch #7 are sent the 16 last TCC flags received on TCC
0840       // input Ch. 5:
0841       if (barrel) {  // in barrel
0842         string s = getABTCCInputStream(tccFlags, iABEta, iABPhi, 5);
0843         assert(s.size() >= 16);
0844         buffer << s.substr(s.size() - 16, 16);
0845       }
0846       break;
0847     default:
0848       assert(false);
0849   }
0850   return buffer.str();
0851 }
0852 
0853 string getABABInputStream(const char tccFlags[nTTInEta][nTTInPhi], int iABEta, int iABPhi, int iABCh) {
0854   int iAB = abNum(iABEta, iABPhi);
0855   int iOtherAB;    // AB which this channel is connected to
0856   int iOtherABCh;  // ch # on the other side of the AB-AB link
0857   abConnect(iAB, iABCh, iOtherAB, iOtherABCh);
0858   int iOtherABEta = iOtherAB / 3;
0859   int iOtherABPhi = iOtherAB % 3;
0860   return getABABOutputStream(tccFlags, iOtherABEta, iOtherABPhi, iOtherABCh);
0861 }
0862 
0863 void getABTTPhiBounds(int iABPhi, int &iTTPhiMin, int &iTTPhiMax) {
0864   iTTPhiMin = mod(-6 + iABPhi * nTTInABAlongPhi, nTTInPhi);
0865   iTTPhiMax = mod(iTTPhiMin + nTTInABAlongPhi - 1, nTTInPhi);
0866 }
0867 
0868 void abConnect(int iAB, int iABCh, int &iOtherAB, int &iOtherABCh) {
0869   static bool firstCall = true;
0870   static int xconnectMap[nAB][nABABCh][2];
0871   if (firstCall) {
0872     FILE *f = fopen(xconnectFilename, "r");
0873     if (f == nullptr) {
0874       cerr << "Error. Failed to open xconnect definition file," << xconnectFilename << endl;
0875       exit(EXIT_FAILURE);
0876     }
0877     // skips two first lines:
0878     for (int i = 0; i < 2; ++i) {
0879       int c;
0880       while ((c = getc(f)) != '\n' && c >= 0)
0881         ;
0882     }
0883     int ilink = 0;
0884     while (!feof(f)) {
0885       int abIn;
0886       int pinIn;
0887       int abOut;
0888       int pinOut;
0889       if (4 == fscanf(f, "%d\t%d\t%d\t%d", &abIn, &pinIn, &abOut, &pinOut)) {
0890         xconnectMap[abIn][pinIn][0] = abOut;
0891         xconnectMap[abIn][pinIn][1] = pinOut;
0892         ++ilink;
0893       }
0894     }
0895     if (ilink != nAB * nABABCh) {
0896       cerr << "Error cross-connect definition file " << xconnectFilename
0897            << " contains an unexpected number of link definition." << endl;
0898       exit(EXIT_FAILURE);
0899     }
0900     firstCall = false;
0901   }
0902 
0903   iOtherAB = xconnectMap[iAB][iABCh][0];
0904   iOtherABCh = xconnectMap[iAB][iABCh][1];
0905 }
0906 
0907 string getABDCCOutputStream(const char barrelSrFlags[nBarrelTTInEta][nTTInPhi],
0908                             const char endcapSrFlags[nEndcaps][nSupercrystalXBins][nSupercrystalYBins],
0909                             int iABEta,
0910                             int iABPhi,
0911                             int iDCCCh) {
0912   bool barrel = (iABEta == 1 || iABEta == 2);
0913   if (barrel) {
0914     // same as TCC with same ch number but with TCC flags replaced by SRP flags:
0915     string stream = getABTCCInputStream(barrelSrFlags - nEndcapTTInEta, iABEta, iABPhi, iDCCCh);
0916     // converts srp flags to readout flags:
0917     for (size_t i = 0; i < stream.size(); ++i) {
0918       stream[i] = srp2roFlags[(int)stream[i]];
0919     }
0920     return stream;
0921   } else {             // endcap
0922     if (iDCCCh < 3) {  // used DCC output channel
0923       // endcap index:
0924       int iEE = (iABEta == 0) ? 0 : 1;
0925       stringstream buffer("");
0926       // 3 DCC per AB and AB DCC output channel in
0927       // increasing DCC phi position:
0928       int iDCCPhi = iABPhi * 3 + iDCCCh;
0929       for (size_t iSC = 0; iSC < ecalDccSC[iEE][iDCCPhi].size(); ++iSC) {
0930         pair<int, int> sc = ecalDccSC[iEE][iDCCPhi][iSC];
0931         buffer << srp2roFlags[(int)endcapSrFlags[iEE][sc.first][sc.second]];
0932       }
0933       return buffer.str();
0934     } else {  // unused output channel
0935       return "";
0936     }
0937   }
0938 }