Hot-keys on this page

r m x p   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

# -*- coding: utf-8 -*- 

 

from StringIO import StringIO 

from lxml.etree import Element 

from obspy.xseed import DEFAULT_XSEED_VERSION, utils 

from obspy.xseed.fields import Integer, Loop 

import os 

import warnings 

 

 

class BlocketteLengthException(Exception): 

    """ 

    Wrong blockette length detected. 

    """ 

    pass 

 

 

class BlocketteParserException(Exception): 

    """ 

    General Blockette Parser Exception. 

    """ 

    pass 

 

 

class Blockette(object): 

    """ 

    General blockette handling. 

    """ 

    # default field for each blockette 

    fields = [] 

    default_fields = [ 

        Integer(1, "Blockette type", 3), 

        Integer(2, "Length of blockette", 4, optional=True) 

    ] 

 

    def __init__(self, **kwargs): 

        self.debug = kwargs.get('debug', False) 

        self.strict = kwargs.get('strict', False) 

        self.compact = kwargs.get('compact', False) 

        self.record_type = kwargs.get('record_type', None) 

        self.record_id = kwargs.get('record_id', None) 

        self.blockette_id = "%03d" % self.id 

        self.blockette_name = utils.toTag(self.name) 

        # debug 

        if self.debug: 

            print("----") 

            print(str(self)) 

        # filter versions specific fields 

        self.xseed_version = kwargs.get('xseed_version', DEFAULT_XSEED_VERSION) 

        self.seed_version = kwargs.get('version', 2.4) 

 

    def __str__(self): 

        """ 

        Pretty prints the informations stored in the blockette. 

        """ 

        temp = 'Blockette %s: %s Blockette' % (self.blockette_id, 

                    utils.toString(self.blockette_name)) + os.linesep 

        keys = self.__dict__.keys() 

        keys = sorted(keys) 

        for key in keys: 

            if key in utils.IGNORE_ATTR: 

                continue 

            temp += '%30s: %s' % (utils.toString(key), self.__dict__[key]) 

            temp += os.linesep 

        return temp.strip() 

 

    def getFields(self, xseed_version=DEFAULT_XSEED_VERSION): 

        fields = [] 

        for field in self.fields: 

            # Check XML-SEED version 

            if field.xseed_version and \ 

               field.xseed_version != xseed_version: 

                continue 

            # Check SEED version 

            if field.seed_version and field.seed_version > self.seed_version: 

                continue 

            fields.append(field) 

        return fields 

 

    def parseSEED(self, data, expected_length=0): 

        """ 

        Parse given data for blockette fields and create attributes. 

        """ 

        # convert to stream for test issues 

        if isinstance(data, basestring): 

            expected_length = len(data) 

            data = StringIO(data) 

        start_pos = data.tell() 

        # debug 

        if self.debug: 

            print(' DATA: %s' % (data.read(expected_length))) 

            data.seek(-expected_length, 1) 

        blockette_fields = self.default_fields + self.getFields() 

        # loop over all blockette fields 

        for field in blockette_fields: 

            # if blockette length reached break with warning 

            if data.tell() - start_pos >= expected_length: 

                if not self.strict: 

                    break 

                if isinstance(field, Loop): 

                    break 

                msg = "End of blockette " + self.blockette_id + " reached " + \ 

                      "without parsing all expected fields, here: " + \ 

                      str(field) 

                if self.strict: 

                    raise BlocketteLengthException(msg) 

                else: 

                    warnings.warn(msg, category=Warning) 

                break 

            field.parseSEED(self, data) 

            if field.id == 2: 

                expected_length = field.data 

        # strict tests 

        if not self.strict: 

            return 

        # check length 

        end_pos = data.tell() 

        blockette_length = end_pos - start_pos 

        if expected_length == blockette_length: 

            return 

        # wrong length 

        msg = 'Wrong size of Blockette %s (%d of %d) in sequence %06d' 

        msg = msg % (self.blockette_id, blockette_length, 

                     expected_length, self.record_id or 0) 

        if self.strict: 

            raise BlocketteLengthException(msg) 

        else: 

            warnings.warn(msg, category=Warning) 

 

    def getSEED(self): 

        """ 

        Converts the blockette to a valid SEED string and returns it. 

        """ 

        # loop over all blockette fields 

        data = '' 

        for field in self.getFields(): 

            data += field.getSEED(self) 

        # add blockette id and length 

        return '%03d%04d%s' % (self.id, len(data) + 7, data) 

 

    def parseXML(self, xml_doc): 

        """ 

        Reads lxml etree and fills the blockette with the values of it. 

        """ 

        for field in self.getFields(self.xseed_version): 

            field.parseXML(self, xml_doc) 

 

    def getXML(self, show_optional=False, 

               xseed_version=DEFAULT_XSEED_VERSION): 

        """ 

        Returns a XML document representing this blockette. 

        """ 

        self.xseed_version = xseed_version 

        # root element 

        xml_doc = Element(self.blockette_name, blockette=self.blockette_id) 

        # loop over all blockette fields 

        for field in self.getFields(xseed_version=xseed_version): 

            node = field.getXML(self) 

            xml_doc.extend(node) 

        return xml_doc