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)
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)
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