Skip to content
Snippets Groups Projects
merge_maps.py 6.84 KiB
Newer Older
# -*- coding: utf-8 -*-

from __future__ import division, print_function

import copy
from pprint import pprint
slotKWs = [
    'REFCHAN',
    'REFINDEX',
]

skipKws = [
    'MASK',
    'NSUBADD',
    'BSUB',
]


class Detector:
    def __init__(self):
        self.ID = -1
        self.comment = ''
        self.rocs = [Roc()]

    def __str__(self):
        string = 'DETECTOR={0.ID}'.format(self)
        if self.comment != '':
            string += '  ! {0.comment}'.format(self)

        return string


class Roc:
    def __init__(self):
        self.ID = -1
        self.comment = ''
        self.slots = [Slot()]

    def __str__(self):
        string = 'ROC={0.ID}'.format(self)
        if self.comment != '':
            string += '  ! {0.comment}'.format(self)

        return string


class Slot:
    def __init__(self):
        self.ID = -1
        self.comment = ''
Jure Bericic's avatar
Jure Bericic committed
        self.KWs = {}
        self.channels = []

Jure Bericic's avatar
Jure Bericic committed
        for kw in slotKWs:
            self.KWs[kw] = -1

    def __str__(self):
        string = 'SLOT={0.ID}'.format(self)
        if self.comment != '':
            string += '  ! {0.comment}'.format(self)
        string += '\n'
        for k, v in self.KWs.items():
            if v > -1:
                string += '{}={}\n'.format(k, v)

        return string


class Channel:
    def __init__(self, ID, plane, bar, signal=-1, comment=''):
        self.ID = ID
        self.plane = plane
        self.bar = bar
        self.signal = signal
        self.comment = comment

    def __str__(self):
        string = '{0.ID:>4},{0.plane:>4},{0.bar:>4}'.format(self)
        if self.signal >= 0:
            string += ',{0.signal:>4}'.format(self)
        if self.comment:
            string += '  ! {0.comment}'.format(self)

        return string


Jure Bericic's avatar
Jure Bericic committed
if (len(sys.argv) != 3 or sys.argv[1] == '-h'):
    print('Call as:')
    print('  merge_maps.py merge_list.txt outfile.map')
    sys.exit()


listName = sys.argv[1]
mergedName = sys.argv[2]


# Get map files to merge.
with open(listName, 'r') as fi:
    fileNames = [
        l.strip() for l in fi
        if not l.isspace() and not l.startswith('#')
    ]


header = {
    "KWs": [],
    "IDs": [],
    "signals": [],
}
detectors = []


for fileName in fileNames:
    # Track detector IDs in current file.
    currentIDs = []
    detectors.append(Detector())

    with open(fileName, 'r') as fi:
        for line in fi:
            # Skip empty lines.
            if line.isspace():
                continue

            line = line.strip()

            # Check if comment line.
            if line.startswith('!'):
                # Check if header line.
                # eg: ! HCAL_ID=4   ADC
                i = line.find('_ID=')
                if i == -1:
                    continue

                KW =  line[1:i].strip()
                ID = line[i+4:].split()[0].strip()
                signal = ','.join(line[i+4:].replace('::', '').split()[1:])

                if KW in header['KWs']:
                    print('Detector keyword `{}` already present!'.format(KW))
                    sys.exit(1)
                if ID in header['IDs']:
                    print('Detector ID `{}` already present!'.format(ID))
                    sys.exit(1)

                header['KWs'].append(KW)
                header['IDs'].append(ID)
                header['signals'].append(signal)
                currentIDs.append(ID)
                continue

            # Get comments.
            i = line.find('!')
            if i > -1:
                comment = line[i+1:].strip()
                line = ''.join(line[:i].split())
            else:
                line = ''.join(line.split())
                comment = ''

            # Check if there is keyword.
            i = line.find('=')
            if i > -1:
                command = line[:i].upper()
                ID = line[i+1:]
                if command == 'DETECTOR':
                    if detectors[-1].ID > 0:
                        detectors.append(Detector())
                    if ID not in currentIDs:
                        print('Detector ID `{}` not found!'.format(ID))
                        sys.exit(1)
                    detectors[-1].ID = ID
                    detectors[-1].comment = comment
                elif command == 'ROC':
                    if detectors[-1].rocs[-1].ID > 0:
                        detectors[-1].rocs.append(Roc())
                    detectors[-1].rocs[-1].ID = ID
                    detectors[-1].rocs[-1].comment = comment

                elif command == 'SLOT':
                    if detectors[-1].rocs[-1].slots[-1].ID > 0:
                        detectors[-1].rocs[-1].slots.append(Slot())
                    detectors[-1].rocs[-1].slots[-1].ID = ID
                    detectors[-1].rocs[-1].slots[-1].comment = comment

                elif command in slotKWs:
                    detectors[-1].rocs[-1].slots[-1].KWs[command] = ID

                elif command in skipKWs:
                    pass

                else:
                    print('Unknown command `{}` in line:'.format(command))
                    print(line)
            # This must be channel line.
            values = line.split(',')
            detectors[-1].rocs[-1].slots[-1].channels.append(
                Channel(*values, comment=comment)
            )
# Check if each detector has defined at least one ROC and slot.
for ID, KW in sorted(zip(header['IDs'], header['KWs'])):
    found = False
    for detector in detectors:
        if detector.ID == ID:
            found = True

            if detector.rocs[0].ID < 0:
                print('No crate defined for detector {}!'.format(ID))
            for roc in detector.rocs:
                if roc.slots[0].ID < 0:
                    print(
                        'No slot defined for crate {} in detector {}!'.format(
                            roc.ID, detector.ID
                        )
                    )
                    sys.exit(1)

    if not found:
        print('No entry for detector {}!'.format(ID))
# Write merged map file.
with open(mergedName, 'w') as fo:
    # Write header.
    for ID, KW, signals in sorted(zip(
        header['IDs'], header['KWs'], header['signals']
    )):
Jure Bericic's avatar
Jure Bericic committed
        IDString = '{0}_ID={1}'.format(KW, ID)
        fo.write('! {0:15}  ::  {1}\n'.format(IDString, signals))
    # Write detector maps sorted by IDs.
    for ID, KW in sorted(zip(
        header['IDs'], header['KWs']
    )):
        for detector in detectors:
            if detector.ID == ID:
Jure Bericic's avatar
Jure Bericic committed
                fo.write('\n\n{0}\n'.format(detector))
                for roc in detector.rocs:
Jure Bericic's avatar
Jure Bericic committed
                    fo.write('\n{0}\n'.format(roc))
                    for slot in roc.slots:
Jure Bericic's avatar
Jure Bericic committed
                        fo.write('\n{0}'.format(slot))
                        for channel in slot.channels:
Jure Bericic's avatar
Jure Bericic committed
                            fo.write('{0}\n'.format(channel))
print('\nDone.')