Example #1
0
def read_template(line_stream):
    """
    Read SAFNWC message template into a :class:`.Template`

    SAFNWC template lines look as follows:

    ``1       001033  0       0        8             Code table        Identification of originating/generating centre``

    :param line_stream: Lines of SAFNWC template file
    :return: the template as Template
    :rtype: Template
    :raises ValueError: if the template contains a desccriptor outside range [0,3]
    """
    descriptors = []
    metadata = {}
    for l in line_stream:
        if l.startswith("#") or l.startswith("/*"):
            # Ignore comments, does not support multiline comments properly
            continue
        elif l.startswith("NUM"):
            name, num = l.split(" ")
            metadata[name] = int(num)
        else:
            # Input lines look like this:
            # 1       001033  0       0        8             Code table        Identification of originating/generating centre
            num = int(l[:8])
            raw_descriptor = l[8:14]
            descriptor_code = fxy2int(raw_descriptor)
            scale = int(l[14:23])
            reference = int(l[23:33])
            bits = int(l[33:47])
            unit = l[47:65].strip()[:24]
            significance = l[65:].strip()[:64]

            descr_class = raw_descriptor[0]
            if descr_class == '0':
                descriptors.append(
                    ElementDescriptor(descriptor_code, bits, scale, reference,
                                      significance, unit))
            elif descr_class == '1':
                f, x, y = fxy(raw_descriptor)
                descriptors.append(
                    ReplicationDescriptor(descriptor_code, 0, x, y,
                                          significance))
            elif descr_class == '2':
                f, x, y = fxy(raw_descriptor)
                descriptors.append(
                    OperatorDescriptor(descriptor_code, 0, x, y, significance))
            elif descr_class == '3':
                # Ignore sequence descriptors, they are followed by constituent elements in the SAFNWC template format
                continue
            else:
                raise ValueError("Encountered unknown descriptor class: %s" %
                                 descr_class)
    name = "B0000000000%(NUM_ORIGINATING_CENTRE)03d%(NUM_BUFR_MAIN_TABLE)03d%(NUM_BUFR_LOCAL_TABLES)03d.TXT" % metadata
    return Template(name, descriptors)
Example #2
0
def read_template(line_stream):
    """
    Read SAFNWC message template into a :class:`.Template`

    SAFNWC template lines look as follows:

    ``1       001033  0       0        8             Code table        Identification of originating/generating centre``

    :param line_stream: Lines of SAFNWC template file
    :return: the template as Template
    :rtype: Template
    :raises ValueError: if the template contains a desccriptor outside range [0,3]
    """
    descriptors = []
    metadata = {}
    for l in line_stream:
        if l.startswith("#") or l.startswith("/*"):
            # Ignore comments, does not support multiline comments properly
            continue
        elif l.startswith("NUM"):
            name, num = l.split(" ")
            metadata[name] = int(num)
        else:
            # Input lines look like this:
            # 1       001033  0       0        8             Code table        Identification of originating/generating centre
            num = int(l[:8])
            raw_descriptor = l[8:14]
            descriptor_code = fxy2int(raw_descriptor)
            scale = int(l[14:23])
            reference = int(l[23:33])
            bits = int(l[33:47])
            unit = l[47:65].strip()[:24]
            significance = l[65:].strip()[:64]

            descr_class = raw_descriptor[0]
            if descr_class == "0":
                descriptors.append(ElementDescriptor(descriptor_code, bits, scale, reference, significance, unit))
            elif descr_class == "1":
                f, x, y = fxy(raw_descriptor)
                descriptors.append(ReplicationDescriptor(descriptor_code, 0, x, y, significance))
            elif descr_class == "2":
                f, x, y = fxy(raw_descriptor)
                descriptors.append(OperatorDescriptor(descriptor_code, 0, x, y, significance))
            elif descr_class == "3":
                # Ignore sequence descriptors, they are followed by constituent elements in the SAFNWC template format
                continue
            else:
                raise ValueError("Encountered unknown descriptor class: %s" % descr_class)
    name = "B0000000000%(NUM_ORIGINATING_CENTRE)03d%(NUM_BUFR_MAIN_TABLE)03d%(NUM_BUFR_LOCAL_TABLES)03d.TXT" % metadata
    return Template(name, descriptors)
Example #3
0
def read_tables(b_line_stream, d_line_stream=None):
    """
    Read BUFR table(s) in from libbufr text file(s).

    The return value is a dict that combines the tables read.

    :param b_line_stream: Iterable of lines, contents of the B-table file
    :param d_line_stream: Iterable of lines, contents of the D-table file
    :return: Mapping from FXY integers to descriptors
    :rtype: dict
    :raises NotImplementedError: if the table contains sequence descriptors
    :raises ValueError: if the table contains descriptors with illegal class (outside range [0,3])
    """
    descriptors = {}
    for line in b_line_stream:
        # Format from btable.F:146 in libbufr version 000400
        parts = slices(line, [1, 6, 1, 64, 1, 24, 1, 3, 1, 12, 1, 3])
        if not parts[11]:
            # Geo::BUFR skips lines without bit width definition,
            # libbufr defaults bit width to 0
            # choosing to skip here
            continue
        raw_descriptor = parts[1]
        descriptor_code = fxy2int(raw_descriptor)
        significance = parts[3].strip()
        unit = parts[5].strip()
        scale = int(parts[7])
        reference = int(parts[9])
        bits = int(parts[11])

        descr_class = raw_descriptor[0]
        if descr_class == '0':
            descriptors[descriptor_code] = ElementDescriptor(
                descriptor_code, bits, scale, reference, significance, unit)
        elif descr_class == '1':
            f, x, y = fxy(raw_descriptor)
            descriptors[descriptor_code] = ReplicationDescriptor(
                descriptor_code, 0, x, y, significance)
        elif descr_class == '2':
            f, x, y = fxy(raw_descriptor)
            descriptors[descriptor_code] = OperatorDescriptor(
                descriptor_code, 0, x, y, significance)
        elif descr_class == '3':
            raise ValueError(
                "B-table file should not contain descriptors of class 3: %s" %
                descr_class)
        else:
            raise ValueError("Encountered unknown descriptor class: %s" %
                             descr_class)

    def group_d_lines(ls):
        buf = None
        for line in ls:
            if line.startswith(' 3'):
                if buf:
                    yield buf
                buf = [line]
            else:
                buf.append(line)
        yield buf

    table = DescriptorTable(
        descriptors)  # descriptors is not copied, just referenced

    if d_line_stream:
        for lines in group_d_lines(d_line_stream):
            # Format inferred
            parts = slices(lines[0], [1, 6, 1, 2, 1, 6])
            raw_d_descriptor = parts[1]
            d_descriptor_code = fxy2int(raw_d_descriptor)
            n_elements = int(parts[3])
            actual_elements = len(lines)
            if n_elements != actual_elements:
                raise ValueError("Expected %d elements, found %d" %
                                 (n_elements, actual_elements))
            constituent_codes = []
            for line in lines:
                l_parts = slices(line, [1, 6, 1, 2, 1, 6])
                constituent_codes.append(fxy2int(l_parts[5]))

            descriptors[d_descriptor_code] = LazySequenceDescriptor(
                d_descriptor_code, constituent_codes, '', table)
    return table