• Facebook
  • Twitter
  • Reddit
  • StumbleUpon
  • Digg
  • email

# metadata_reader.py
 
# By Nathan C. Hearn
#    November 21, 2007
#
# Reader for metadata files from omega_slicer and layer_distrib.
 
 
from sys import stderr
 
 
class KeywordGroup :
 
    def __init__(self, group_name=None, group_type=None) :
 
        self.__name = group_name
        self.__type = group_type
 
        self.__sort_key = int(-1)  # Default is higher precedence than zero
 
        self.__values = dict()
 
 
    def set_group_name(self, group_name) :
        self.__name = group_name
 
    def get_group_name(self) :
        return self.__name
 
 
    def get_group_type(self) :
        return self.__type
 
 
    def set_sort_key(self, key) :
        self.__sort_key = key
 
 
    def get_sort_key(self) :
        return self.__sort_key
 
 
    def __cmp__(self, other) :
        return cmp(self.__sort_key, other.get_sort_key())
 
 
    def get_string(self, line_prefix="") :
 
        string = line_prefix + "Name [ " + str(self.__name) + " ]\n"
 
        if (self.__type is not None) :
            string += line_prefix + "  Type [ " + str(self.__type) + " ]\n"
 
        string += line_prefix + "  Sort key [ " + str(self.__sort_key) + " ]\n"
 
        for key in self.__values :
            string += line_prefix + "  Key [ " + str(key) + " ] Value [ " \
                      + str(self.__values[key]) + " ]\n"
 
        return string
 
 
    def __str__(self) :
        return self.get_string()
 
 
    def add_keyword_value(self, keyword, value=None) :
 
        if (self.__values.has_key(keyword)) :
            stderr.write("\nDuplicate keyword [ " + str(keyword) + " ]\n\n")
            raise RuntimeError("Duplicate keyword")
 
        self.__values[keyword] = value
 
 
    def keyword_present(self, keyword) :
        return self.__values.has_key(keyword)
 
 
    def get_value(self, keyword) :
        return self.__values[keyword]
 
 
    def __getitem__(self, keyword) :
        return self.get_value(keyword)
 
 
    def get_keyword_list(self) :
        return self.__values.keys()
 
 
class DataGroup(KeywordGroup) :
 
    def __init__(self, group_name, group_type=None) :
 
        KeywordGroup.__init__(self, group_name, group_type)
 
        self.__keyword_group_list = list()
 
 
    def get_string(self, line_prefix="") :
 
        string = KeywordGroup.get_string(self) + "\n"
 
        for group in self.__keyword_group_list :
            string += group.get_string(line_prefix + "  ") + "\n"
 
        return string
 
 
    def __str__(self) :
        return self.get_string()
 
 
    def add_keyword_group(self, keyword_group) :
 
        sort_key = keyword_group.get_sort_key()
 
        # Find the sorted location for this group
 
        num_groups = len(self.__keyword_group_list)
 
        index = (0)
 
        found_it = False
 
        while ((not found_it) and (index < num_groups)) :
 
            if (self.__keyword_group_list[index].get_sort_key() > sort_key) :
                found_it = True
            else :
                index += 1
 
        if (not found_it) :
            self.__keyword_group_list.append(keyword_group)
        else :
            self.__keyword_group_list.insert(index, keyword_group)
 
 
    def get_keyword_group_list(self, group_type=None) :
 
        keyword_group_list = list()
 
        for group in self.__keyword_group_list :
 
            include_group = False
 
            if (group_type is None) :
                include_group = True
            elif (group.get_group_type() == group_type) :
                include_group = True
 
            if (include_group) :
                keyword_group_list.append(group)
 
        return keyword_group_list
 
 
def split_vector(vector_string) :
 
    ## Split on both "," and " "
 
    split_words = vector_string.split()
 
    vector_elems = list()
 
    for word in split_words :
        comma_words = word.split(",")
 
        for elem in comma_words :
            vector_elems.append(elem)
 
    return vector_elems
 
 
def remove_comments(line) :
    return line.split("#")[0].strip()
 
 
def read_next_line(input_file) :
 
    ret_val = None  # Return None if at end of file
 
    finished = False
 
    while (not finished) :
 
        current_line = input_file.readline()
 
        if (current_line == "") :
 
            finished = True  # End of file
 
        else :
 
            work_line = remove_comments(current_line)
 
            if (work_line != "") :
                ret_val = work_line
                finished = True
 
    return ret_val
 
 
def parse_file_line_slicer(line) :
 
    work_line = line.strip()
 
    keyword_values = dict()
 
    split_pairs = work_line.split("]")
 
    num_split_pairs= len(split_pairs)
 
    # Parse the elements
 
    for pair in split_pairs :
 
        pair_elems = pair.split("[")
 
        num_elems = len(pair_elems)
 
        if ((num_elems > 2) or (num_elems < 1)) :
            stderr.write("\nError parsing metadata [ " + work_line + " ]\n\n")
            raise RuntimeError("Error parsing metadata")
 
        keyword = None
        value = None
 
        keyword = pair_elems[0].strip()
 
        temp_value = None
 
        if (num_elems > 1) :
            temp_value = pair_elems[1].strip()
 
        include_pair = True
 
        if (keyword == "") :
            if ((num_elems < 2) or (temp_value == "")) :
                include_pair = False
            else :
                stderr.write("\nError: Missing keyword [ " + work_line
                             + " ]\n\n")
                raise RuntimeError("Missing keyword")
 
        if (include_pair) :
 
            if (num_elems > 1) :
                if (temp_value != "") :
                    value = split_vector(temp_value)
 
                if (len(value) == 1) :
                    value = value[0]
                elif (len(value) < 1) :
                    value = None
 
            keyword_values[keyword] = value
 
    return keyword_values
 
 
def parse_slicer_metadata(filename) :
 
    datafile_group = None
 
    dataset_list = list()
 
    current_line = None
 
    f = file(filename, "r")
 
    # Read the file metadata
 
    current_line = read_next_line(f)
 
    if (current_line is None) :
        raise RuntimeError("EOF reached early")
 
    current_metadata = parse_file_line_slicer(current_line)
 
    if (len(current_metadata) != 1) :
        raise RuntimeError("Improper flash filename entry")
 
    flash_file_name = current_metadata["FlashFile"]
 
    datafile_group = KeywordGroup(flash_file_name)
 
    finished_header = False
 
    while (not finished_header) :
 
        current_line = read_next_line(f)
 
        if (current_line is None) :
 
            finished_header = True  # End of file
            current_metadata = None
 
        else :
 
            current_metadata = parse_file_line(current_line)
 
            if (current_metadata.has_key("Dataset")) :
 
                finished_header = True  ## Keep current_metadata for next part
 
            else :
 
                if (current_metadata.has_key("Time")) :
 
                    time = float(current_metadata["Time"])
                    datafile_group.add_keyword_value("Time", time)
 
                elif (current_metadata.has_key("Dimensions")) :
 
                    dims = int(current_metadata["Dimensions"])
                    datafile_group.add_keyword_value("Dims", dims)
 
                elif (current_metadata.has_key("EnvelopeMinPos")) :
 
                    pos = float(current_metadata["EnvelopeMinPos"])
                    datafile_group.add_keyword_value("EnvelopeMinPos", pos)
 
                elif (current_metadata.has_key("EnvelopeMaxPos")) :
 
                    pos = float(current_metadata["EnvelopeMaxPos"])
                    datafile_group.add_keyword_value("EnvelopeMaxPos", pos)
 
                elif (current_metadata.has_key("GridMinCoords")) :
 
                    min_coords_str = current_metadata["GridMinCoords"]
                    min_coords = list()
 
                    for elem in min_coords_str :
                        min_coords.append(float(elem))
 
                    datafile_group.add_keyword_value("GridMinCoords",
                                                     min_coords)
 
                elif (current_metadata.has_key("GridMaxCoords")) :
 
                    max_coords_str = current_metadata["GridMaxCoords"]
                    max_coords = list()
 
                    for elem in max_coords_str :
                        max_coords.append(float(elem))
 
                    datafile_group.add_keyword_value("GridMaxCoords",
                                                     max_coords)
 
                elif (current_metadata.has_key("GridCenter")) :
 
                    center_coords_str = current_metadata["GridCenter"]
                    center_coords = list()
 
                    for elem in center_coords_str :
                        center_coords.append(float(elem))
 
                    datafile_group.add_keyword_value("GridCenter",
                                                     center_coords)
 
                elif (current_metadata.has_key("GridWidth")) :
 
                    axis_width_str = current_metadata["GridWidth"]
                    axis_width = list()
 
                    for elem in axis_width_str :
                        axis_width.append(float(elem))
 
                    datafile_group.add_keyword_value("GridWidth", axis_width)
 
                elif (current_metadata.has_key("GridPixels")) :
 
                    grid_pixels_str = current_metadata["GridPixels"]
                    grid_pixels = list()
 
                    for elem in grid_pixels_str :
                        grid_pixels.append(int(elem))
 
                    datafile_group.add_keyword_value("GridPixels",
                                                     grid_pixels)
 
                elif (current_metadata.has_key("XSectGridMinCoords")) :
 
                    min_coords_str = current_metadata["XSectGridMinCoords"]
                    min_coords = list()
 
                    for elem in min_coords_str :
                        min_coords.append(float(elem))
 
                    datafile_group.add_keyword_value("XSectGridMinCoords",
                                                     min_coords)
 
                elif (current_metadata.has_key("XSectGridMaxCoords")) :
 
                    max_coords_str = current_metadata["XSectGridMaxCoords"]
                    max_coords = list()
 
                    for elem in max_coords_str :
                        max_coords.append(float(elem))
 
                    datafile_group.add_keyword_value("XSectGridMaxCoords",
                                                     max_coords)
 
                elif (current_metadata.has_key("XSectGridCenter")) :
 
                    center_coords_str = current_metadata["XSectGridCenter"]
                    center_coords = list()
 
                    for elem in center_coords_str :
                        center_coords.append(float(elem))
 
                    datafile_group.add_keyword_value("XSectGridCenter",
                                                     center_coords)
 
                elif (current_metadata.has_key("XSectGridWidth")) :
 
                    axis_width_str = current_metadata["XSectGridWidth"]
                    axis_width = list()
 
                    for elem in axis_width_str :
                        axis_width.append(float(elem))
 
                    datafile_group.add_keyword_value("XSectGridWidth",
                                                     axis_width)
 
                elif (current_metadata.has_key("XSectGridPixels")) :
 
                    grid_pixels_str = current_metadata["XSectGridPixels"]
                    grid_pixels = list()
 
                    for elem in grid_pixels_str :
                        grid_pixels.append(int(elem))
 
                    datafile_group.add_keyword_value("XSectGridPixels",
                                                     grid_pixels)
 
                elif (current_metadata.has_key("XSectLowerPlanePos")) :
 
                    xsect_bottom_pos \
                        = float(current_metadata["XSectLowerPlanePos"])
 
                    datafile_group.add_keyword_value("XSectLowerPlanePos",
                                                     xsect_bottom_pos)
 
                elif (current_metadata.has_key("XSectMiddlePlanePos")) :
 
                    xsect_flame_front_pos \
                        = float(current_metadata["XSectMiddlePlanePos"])
 
                    datafile_group.add_keyword_value("XSectMiddlePlanePos",
                                                     xsect_flame_front_pos)
 
                elif (current_metadata.has_key("XSectUpperPlanePos")) :
 
                    xsect_top_pos \
                        = float(current_metadata["XSectUpperPlanePos"])
 
                    datafile_group.add_keyword_value("XSectUpperPlanePos",
                                                     xsect_top_pos)
 
    # Process datasets
 
    finished_datasets = False
 
    while (not finished_datasets) :
 
        if (current_metadata is None) :
 
            finished_datasets = True
 
        else :
 
            if (not current_metadata.has_key("Dataset")) :
                raise RuntimeError("Unrecognized file line")
 
            dataset_name = current_metadata["Dataset"]
 
            dataset_group = DataGroup(dataset_name, "Dataset")
 
            min_value = float(current_metadata["MinValue"])
            max_value = float(current_metadata["MaxValue"])
 
            dataset_group.add_keyword_value("MinValue", min_value)
            dataset_group.add_keyword_value("MaxValue", max_value)
 
            # Read the Image, data, and cross section info
 
            dataset_complete = False
 
            while (not dataset_complete) :
 
                current_line = read_next_line(f)
 
                if (current_line is None) :
 
                    dataset_complete = True
                    current_metadata = None
 
                else :
 
                    current_metadata = parse_file_line_slicer(current_line)
 
                    if (current_metadata.has_key("Dataset")) :
 
                        dataset_complete = True
 
                    else :
 
                        if (current_metadata.has_key("Image")) :
 
                            image_group \
                                = KeywordGroup(current_metadata["Image"],
                                               "Image")
 
                            filename = current_metadata["File"]
 
                            image_group.add_keyword_value("File", filename)
 
                            min_coords = list()
                            max_coords = list()
 
                            for elem in current_metadata["MinCoords"] :
                                min_coords.append(float(elem))
 
                            for elem in current_metadata["MaxCoords"] :
                                max_coords.append(float(elem))
 
                            image_group.add_keyword_value("MinCoords",
                                                          min_coords)
 
                            image_group.add_keyword_value("MaxCoords",
                                                          max_coords)
 
                            min_val = float(current_metadata["MinValue"])
                            max_val = float(current_metadata["MaxValue"])
 
                            image_group.add_keyword_value("MinValue", min_val)
                            image_group.add_keyword_value("MaxValue", max_val)
 
                            dataset_group.add_keyword_group(image_group)
 
                        elif (current_metadata.has_key("Data")) :
 
                            image_group \
                                = KeywordGroup(current_metadata["Data"],
                                               "Data")
 
                            filename = current_metadata["File"]
 
                            image_group.add_keyword_value("File", filename)
 
                            min_coords = list()
                            max_coords = list()
 
                            for elem in current_metadata["MinCoords"] :
                                min_coords.append(float(elem))
 
                            for elem in current_metadata["MaxCoords"] :
                                max_coords.append(float(elem))
 
                            image_group.add_keyword_value("MinCoords",
                                                          min_coords)
 
                            image_group.add_keyword_value("MaxCoords",
                                                          max_coords)
 
                            min_val = float(current_metadata["MinValue"])
                            max_val = float(current_metadata["MaxValue"])
 
                            image_group.add_keyword_value("MinValue", min_val)
                            image_group.add_keyword_value("MaxValue", max_val)
 
                            dataset_group.add_keyword_group(image_group)
 
                        elif (current_metadata.has_key("XSect")) :
 
                            xsect_type = current_metadata["XSect"]
 
                            group_type = "XSect_" + xsect_type
 
                            image_group \
                                = KeywordGroup(current_metadata["File"],
                                               group_type)
 
                            filename = current_metadata["File"]
 
                            image_group.add_keyword_value("File", filename)
 
                            if (current_metadata.has_key("Index")) :
                                xsect_index = int(current_metadata["Index"])
                                image_group.set_sort_key(xsect_index)
 
                            xsect_type = str(current_metadata["Type"])
                            image_group.add_keyword_value("Type", xsect_type)
 
                            x_pos = float(current_metadata["Pos"])
                            image_group.add_keyword_value("Pos", x_pos)
 
                            min_coords = list()
                            max_coords = list()
 
                            for elem in current_metadata["MinCoords"] :
                                min_coords.append(float(elem))
 
                            for elem in current_metadata["MaxCoords"] :
                                max_coords.append(float(elem))
 
                            image_group.add_keyword_value("MinCoords",
                                                          min_coords)
 
                            image_group.add_keyword_value("MaxCoords",
                                                          max_coords)
 
                            min_val = float(current_metadata["MinValue"])
                            max_val = float(current_metadata["MaxValue"])
 
                            image_group.add_keyword_value("MinValue", min_val)
                            image_group.add_keyword_value("MaxValue", max_val)
 
                            dataset_group.add_keyword_group(image_group)
 
 
            dataset_list.append(dataset_group)
 
    return datafile_group, dataset_list
 
 
def parse_file_line_distrib(line) :
 
    work_line = line.strip()
 
    keyword = None
    value_string = None
 
    split_line = work_line.split(" ", 1)
 
    num_items = len(split_line)
 
    if (num_items > 0) :
 
        keyword = split_line[0]
 
        if (num_items > 1) :
            value_string = split_line[1]
 
    return keyword, value_string
 
 
def parse_distrib_metadata(filename) :
 
    from sys import stderr
 
    datafile_group = None
 
    dataset_list = list()
 
    current_line = None
 
    f = file(filename, "r")
 
    # Read the file metadata
 
    datafile_group = KeywordGroup()
    slice_list = list()
 
    finished = False
 
    while (not finished) :
 
        current_line = read_next_line(f)
 
        if (current_line is None) :
 
            finished = True  # End of file
 
        else :
 
            keyword, value_string = parse_file_line_distrib(current_line)
 
            if (keyword == "DataFile") :
 
                datafile = value_string
                datafile_group.set_group_name(datafile)
 
            elif (keyword == "SimTime") :
 
                sim_time = float(value_string)
                datafile_group.add_keyword_value("SimTime", sim_time)
 
            elif (keyword == "Dimensions") :
 
                dims = int(value_string)
                datafile_group.add_keyword_value("Dims", dims)
 
            elif (keyword == "EnvelopeDataset") :
 
                dataset = value_string
                datafile_group.add_keyword_value("EnvelopeDataset", dataset)
 
            elif (keyword == "MaxSampleRadius") :
 
                sample_rad = float(value_string)
                datafile_group.add_keyword_value("MaxSampleRadius", sample_rad)
 
            elif (keyword == "DistribBinWidth") :
 
                distrib_bin_width = float(value_string)
                datafile_group.add_keyword_value("DistribBinWidth",
                                                 distrib_bin_width)
 
            elif (keyword == "MaxSlices") :
 
                max_slices = int(value_string)
                datafile_group.add_keyword_value("MaxSlices", max_slices)
 
            elif (keyword == "EnvelopeMinPos") :
 
                pos = float(value_string)
                datafile_group.add_keyword_value("EnvelopeMinPos", pos)
 
            elif (keyword == "EnvelopeMaxPos") :
 
                pos = float(value_string)
                datafile_group.add_keyword_value("EnvelopeMaxPos", pos)
 
            elif (keyword == "EnvelopeWidth") :
 
                width = float(value_string)
                datafile_group.add_keyword_value("EnvelopeWidth", width)
 
            elif (keyword == "MinArrayPos") :
 
                pos = float(value_string)
                datafile_group.add_keyword_value("MinArrayPos", pos)
 
            elif (keyword == "MaxArrayPos") :
 
                pos = float(value_string)
                datafile_group.add_keyword_value("MaxArrayPos", pos)
 
            elif (keyword == "ArrayTotalMass") :
 
                mass = float(value_string)
                datafile_group.add_keyword_value("ArrayTotalMass", mass)
 
            elif (keyword == "ArrayPolyMass") :
 
                mass = float(value_string)
                datafile_group.add_keyword_value("ArrayPolyMass", mass)
 
            elif (keyword == "ArrayCHBrMass") :
 
                mass = float(value_string)
                datafile_group.add_keyword_value("ArrayCHBrMass", mass)
 
            elif (keyword == "ArrayFoamMass") :
 
                mass = float(value_string)
                datafile_group.add_keyword_value("ArrayFoamMass", mass)
 
            elif (keyword == "LayerDistribFile") :
 
                distrib_file = value_string
                datafile_group.add_keyword_value("LayerDistribFile",
                                                 distrib_file)
 
            elif (keyword == "FoundLayerMin") :
 
                state = False
 
                if (value_string == "true") :
                    state = True
 
                datafile_group.add_keyword_value("FoundLayerMin", state)
 
            elif (keyword == "FoundLayerMax") :
 
                state = False
 
                if (value_string == "true") :
                    state = True
 
                datafile_group.add_keyword_value("FoundLayerMax", state)
 
            elif (keyword == "LayerPeakValueFract") :
 
                fract = float(value_string)
                datafile_group.add_keyword_value("LayerPeakValueFract", fract)
 
            elif (keyword == "LayerMinPos") :
 
                pos = float(value_string)
                datafile_group.add_keyword_value("LayerMinPos", pos)
 
            elif (keyword == "LayerMaxPos") :
 
                pos = float(value_string)
                datafile_group.add_keyword_value("LayerMaxPos", pos)
 
            elif (keyword == "LayerWidth") :
 
                width = float(value_string)
                datafile_group.add_keyword_value("LayerWidth", pos)
 
            elif (keyword == "MinEnvelopePos") :
 
                pos = float(value_string)
                datafile_group.add_keyword_value("MinEnvelopePos", pos)
 
            elif (keyword == "MaxEnvelopePos") :
 
                pos = float(value_string)
                datafile_group.add_keyword_value("MaxEnvelopePos", pos)
 
            elif (keyword == "FoundShockFront") :
 
                state = False
 
                if (value_string == "true") :
                    state = True
 
                datafile_group.add_keyword_value("FoundShockFront", state)
 
            elif (keyword == "SliceSpacing") :
 
                spacing = float(value_string)
                datafile_group.add_keyword_value("SliceSpacing", spacing)
 
            elif (keyword == "SliceWidth") :
 
                width = float(value_string)
                datafile_group.add_keyword_value("SliceWidth", width)
 
            elif (keyword == "SliceBinWidth") :
 
                width = float(value_string)
                datafile_group.add_keyword_value("SliceBinWidth", width)
 
            elif (keyword == "Slice1D") :
 
                words = value_string.split()
 
                num_words = len(words)
 
                if (num_words != 3) :
                    stderr.write("\nError: Incompatible slice value string [ "
                                 + value_string + " ]")
                    raise RuntimeError("Incompatible slice value string")
 
                slice_id = int(words[0])
                slice_pos = float(words[1])
                slice_output_file = words[2]
 
                slice_group = KeywordGroup(slice_id, keyword)
 
                slice_group.add_keyword_value("SlicePos", slice_pos)
                slice_group.add_keyword_value("OutputFile", slice_output_file)
 
                slice_list.append(slice_group)
 
 
    return datafile_group, slice_list