Exemple #1
0
 def getSEED(self, compact=False):
     """
     Returns a SEED representation of the current Parser object.
     """
     self.compact = compact
     # Nothing to write if not all necessary data is available.
     if not self.volume or not self.abbreviations or not self.stations:
         msg = 'No data to be written available.'
         raise SEEDParserException(msg)
     # Check blockettes:
     if not self._checkBlockettes():
         msg = 'Not all necessary blockettes are available.'
         raise SEEDParserException(msg)
     # String to be written to:
     seed_string = ''
     cur_count = 1
     volume, abbreviations, stations = self._createBlockettes11and12()
     # Delete Blockette 11 again.
     self._deleteBlockettes11and12()
     # Finally write the actual SEED String.
     for _i in volume:
         seed_string += '%06i' % cur_count + _i
         cur_count += 1
     for _i in abbreviations:
         seed_string += '%06i' % cur_count + _i
         cur_count += 1
     # Remove name of the stations.
     stations = [_i[1:] for _i in stations]
     for _i in stations:
         for _j in _i:
             seed_string += '%06i' % cur_count + _j
             cur_count += 1
     return seed_string
Exemple #2
0
 def _select(self, seed_id, datetime=None):
     """
     Selects all blockettes related to given SEED id and datetime.
     """
     old_format = self._format
     # parse blockettes if not SEED. Needed foe XSEED to be intialized.
     # XXX: Should potentially be fixed at some point.
     if self._format != 'SEED':
         self.__init__(self.getSEED())
     if old_format == "XSEED":
         self._format = "XSEED"
     # split id
     if '.' in seed_id:
         net, sta, loc, cha = seed_id.split('.')
     else:
         cha = seed_id
         net = sta = loc = None
     # create a copy of station list
     stations = list(self.stations)
     # filter blockettes list by given SEED id
     station_flag = False
     channel_flag = False
     blockettes = []
     for station in stations:
         for blk in station:
             if blk.id == 50:
                 station_flag = False
                 if net is not None and blk.network_code != net:
                     continue
                 if sta is not None and blk.station_call_letters != sta:
                     continue
                 station_flag = True
                 tmpb50 = blk
             elif blk.id == 52 and station_flag:
                 channel_flag = False
                 if loc is not None and blk.location_identifier != loc:
                     continue
                 if blk.channel_identifier != cha:
                     continue
                 if datetime is not None:
                     if blk.start_date > datetime:
                         continue
                     if blk.end_date and blk.end_date < datetime:
                         continue
                 channel_flag = True
                 blockettes.append(tmpb50)
                 blockettes.append(blk)
             elif channel_flag and station_flag:
                 blockettes.append(blk)
     # check number of selected channels (equals number of blockette 52)
     b50s = [b for b in blockettes if b.id == 50]
     b52s = [b for b in blockettes if b.id == 52]
     if len(b50s) == 0 or len(b52s) == 0:
         msg = 'No channel found with the given SEED id: %s'
         raise SEEDParserException(msg % (seed_id))
     elif len(b50s) > 1 or len(b52s) > 1:
         msg = 'More than one channel found with the given SEED id: %s'
         raise SEEDParserException(msg % (seed_id))
     return blockettes
Exemple #3
0
 def _parseXMLBlockette(self, XML_blockette, record_type, xseed_version):
     """
     Takes the lxml tree of any blockette and returns a blockette object.
     """
     # Get blockette number.
     blockette_id = int(XML_blockette.values()[0])
     if blockette_id in HEADER_INFO[record_type].get('blockettes', []):
         class_name = 'Blockette%03d' % blockette_id
         if not hasattr(blockette, class_name):
             raise SEEDParserException('Blockette %d not implemented!' %
                                       blockette_id)
         blockette_class = getattr(blockette, class_name)
         blockette_obj = blockette_class(debug=self.debug,
                                         strict=self.strict,
                                         compact=self.compact,
                                         version=self.version,
                                         record_type=record_type,
                                         xseed_version=xseed_version)
         blockette_obj.parseXML(XML_blockette)
         return blockette_obj
     elif blockette_id != 0:
         msg = "Unknown blockette type %d found" % blockette_id
         raise SEEDParserException(msg)
Exemple #4
0
    def _parseSEED(self, data):
        """
        Parses through a whole SEED volume.

        It will always parse the whole file and skip any time span data.

        :type data: File pointer or StringIO object.
        """
        # Jump to the beginning of the file.
        data.seek(0)
        # Retrieve some basic data like version and record length.
        temp = data.read(8)
        # Check whether it starts with record sequence number 1 and a volume
        # index control header.
        if temp != '000001V ':
            raise SEEDParserException("Expecting 000001V ")
        # The first blockette has to be Blockette 10.
        temp = data.read(3)
        if temp not in ['010', '008', '005']:
            raise SEEDParserException("Expecting blockette 010, 008 or 005")
        # Skip the next four bytes containing the length of the blockette.
        data.seek(4, 1)
        # Set the version.
        self.version = float(data.read(4))
        # Get the record length.
        length = pow(2, int(data.read(2)))
        # Test record length.
        data.seek(length)
        temp = data.read(6)
        if temp != '000002':
            msg = "Got an invalid logical record length %d" % length
            raise SEEDParserException(msg)
        self.record_length = length
        if self.debug:
            print("RECORD LENGTH: %d" % (self.record_length))
        # Set all temporary attributes.
        self.temp = {'volume': [], 'abbreviations': [], 'stations': []}
        # Jump back to beginning.
        data.seek(0)
        # Read the first record.
        record = data.read(self.record_length)
        merged_data = ''
        record_type = None
        # Loop through file and pass merged records to _parseMergedData.
        while record:
            record_continuation = (record[7] == CONTINUE_FROM_LAST_RECORD)
            same_record_type = (record[6] == record_type)
            if record_type == 'S' and record[8:11] != '050':
                record_continuation = True
            if record_continuation and same_record_type:
                # continued record
                merged_data += record[8:]
            else:
                self._parseMergedData(merged_data.strip(), record_type)
                # first or new type of record
                record_type = record[6]
                merged_data = record[8:]
                if record_type not in HEADERS:
                    # only parse headers, no data
                    merged_data = ''
                    record_type = None
                    break
            if self.debug:
                if not record_continuation:
                    print("========")
                print(record[0:8])
            record = data.read(self.record_length)
        # Use parse once again.
        self._parseMergedData(merged_data.strip(), record_type)
        # Update the internal structure to finish parsing.
        self._updateInternalSEEDStructure()
Exemple #5
0
    def getXSEED(self, version=DEFAULT_XSEED_VERSION, split_stations=False):
        """
        Returns a XSEED representation of the current Parser object.

        :type version: float, optional
        :param version: XSEED version string (default is ``1.1``).
        :type split_stations: boolean, optional
        :param split_stations: Splits stations containing multiple channels
            into multiple documents.
        :rtype: str or dict
        :return: Returns either a string or a dict of strings depending
            on the flag ``split_stations``.
        """
        if version not in XSEED_VERSIONS:
            raise SEEDParserException("Unknown XML-SEED version!")
        doc = Element("xseed", version=version)
        # Nothing to write if not all necessary data is available.
        if not self.volume or not self.abbreviations or \
                len(self.stations) == 0:
            msg = 'No data to be written available.'
            raise SEEDParserException(msg)
        # Check blockettes:
        if not self._checkBlockettes():
            msg = 'Not all necessary blockettes are available.'
            raise SEEDParserException(msg)
        # Add blockettes 11 and 12 only for XSEED version 1.0.
        if version == '1.0':
            self._createBlockettes11and12(blockette12=True)
        # Now start actually filling the XML tree.
        # Volume header:
        sub = SubElement(doc, utils.toTag('Volume Index Control Header'))
        for blkt in self.volume:
            sub.append(blkt.getXML(xseed_version=version))
        # Delete blockettes 11 and 12 if necessary.
        if version == '1.0':
            self._deleteBlockettes11and12()
        # Abbreviations:
        sub = SubElement(doc,
                         utils.toTag('Abbreviation Dictionary Control Header'))
        for blkt in self.abbreviations:
            sub.append(blkt.getXML(xseed_version=version))
        if not split_stations:
            # Don't split stations
            for station in self.stations:
                sub = SubElement(doc, utils.toTag('Station Control Header'))
                for blkt in station:
                    sub.append(blkt.getXML(xseed_version=version))
            if version == '1.0':
                # To pass the XSD schema test an empty time span control header
                # is added to the end of the file.
                SubElement(doc, utils.toTag('Timespan Control Header'))
                # Also no data is present in all supported SEED files.
                SubElement(doc, utils.toTag('Data Records'))
            # Return single XML String.
            return tostring(doc,
                            pretty_print=True,
                            xml_declaration=True,
                            encoding='UTF-8')
        else:
            # generate a dict of XML resources for each station
            result = {}
            for station in self.stations:
                cdoc = copy.copy(doc)
                sub = SubElement(cdoc, utils.toTag('Station Control Header'))
                for blkt in station:
                    sub.append(blkt.getXML(xseed_version=version))
                if version == '1.0':
                    # To pass the XSD schema test an empty time span control
                    # header is added to the end of the file.
                    SubElement(doc, utils.toTag('Timespan Control Header'))
                    # Also no data is present in all supported SEED files.
                    SubElement(doc, utils.toTag('Data Records'))
                try:
                    id = station[0].end_effective_date.datetime
                except AttributeError:
                    id = ''
                result[id] = tostring(cdoc,
                                      pretty_print=True,
                                      xml_declaration=True,
                                      encoding='UTF-8')
            return result
Exemple #6
0
 def _parseMergedData(self, data, record_type):
     """
     This method takes any merged SEED record and writes its blockettes
     in the corresponding dictionary entry of self.temp.
     """
     if not data:
         return
     # Create StringIO for easier access.
     data = StringIO(data)
     # Do not do anything if no data is passed or if a time series header
     # is passed.
     if record_type not in HEADERS:
         return
     # Set standard values.
     blockette_length = 0
     blockette_id = -1
     # Find out what kind of record is being parsed.
     if record_type == 'S':
         # Create new station blockettes list.
         self.temp['stations'].append([])
         root_attribute = self.temp['stations'][-1]
     elif record_type == 'V':
         # Just one Volume header per file allowed.
         if len(self.temp['volume']):
             msg = 'More than one Volume index control header found!'
             raise SEEDParserException(msg)
         root_attribute = self.temp['volume']
     else:
         # Just one abbreviations header allowed!
         if len(self.temp['abbreviations']):
             msg = 'More than one Abbreviation Dictionary Control ' + \
                   'Headers found!'
             warnings.warn(msg, UserWarning)
         root_attribute = self.temp['abbreviations']
     # Loop over all blockettes in data.
     while blockette_id != 0:
         # remove spaces between blockettes
         while data.read(1) == ' ':
             continue
         data.seek(-1, 1)
         try:
             blockette_id = int(data.read(3))
             blockette_length = int(data.read(4))
         except:
             break
         data.seek(-7, 1)
         if blockette_id in HEADER_INFO[record_type].get('blockettes', []):
             class_name = 'Blockette%03d' % blockette_id
             if not hasattr(blockette, class_name):
                 raise SEEDParserException('Blockette %d not implemented!' %
                                           blockette_id)
             blockette_class = getattr(blockette, class_name)
             blockette_obj = blockette_class(debug=self.debug,
                                             strict=self.strict,
                                             compact=self.compact,
                                             version=self.version,
                                             record_type=record_type)
             blockette_obj.parseSEED(data, blockette_length)
             root_attribute.append(blockette_obj)
             self.blockettes.setdefault(blockette_id,
                                        []).append(blockette_obj)
         elif blockette_id != 0:
             msg = "Unknown blockette type %d found" % blockette_id
             raise SEEDParserException(msg)
     # check if everything is parsed
     if data.len != data.tell():
         warnings.warn("There exist unparsed elements!")