Coverage for /home/runner/work/torchcvnn/torchcvnn/src/torchcvnn/datasets/alos2/vol_file.py: 0%

31 statements  

« prev     ^ index     » next       coverage.py v7.8.0, created at 2025-04-13 08:53 +0000

1# MIT License 

2 

3# Copyright (c) 2024 Jeremy Fix 

4 

5# Permission is hereby granted, free of charge, to any person obtaining a copy 

6# of this software and associated documentation files (the "Software"), to deal 

7# in the Software without restriction, including without limitation the rights 

8# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 

9# copies of the Software, and to permit persons to whom the Software is 

10# furnished to do so, subject to the following conditions: 

11 

12# The above copyright notice and this permission notice shall be included in 

13# all copies or substantial portions of the Software. 

14 

15# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 

16# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 

17# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 

18# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 

19# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 

20# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 

21# SOFTWARE. 

22 

23# Standard imports 

24from typing import Union 

25import pathlib 

26 

27# Local imports 

28from . import parse_utils 

29 

30descriptor_format = [ 

31 ("record_sequence_number", 0, 4, "B", 1), 

32 ("first_record_subtype_code", 4, 1, "B", 192), 

33 ("record_type_code", 5, 1, "B", 192), 

34 ("second_subtype_code", 6, 1, "B", 18), 

35 ("third_subtype_code", 7, 1, "B", 18), 

36 ("length_record", 8, 4, "B", 360), 

37 ("flag", 12, 2, "A", "A "), 

38 # ("blanks", 14, 2, "A", " "), 

39 ("superstructure_doc_id", 16, 12, "A", "CEOS-SAR "), 

40 ("superstructure_doc_rev_level", 28, 2, "A", " A"), 

41 ("superstructure_fmt_rev_level", 30, 2, "A", " A"), 

42 ("software_release_level", 32, 12, "A", None), 

43 ("physical_volume_id", 44, 16, "A", None), 

44 ("logical_volume_id", 60, 16, "A", None), 

45 ("volume_set_id", 76, 16, "A", None), 

46 ("total_number_volumes", 92, 2, "I", 1), 

47 ("physical_volume_seq_num_first", 94, 2, "I", 1), 

48 ("physical_volume_seq_num_last", 96, 2, "I", 1), 

49 ("physical_volume_seq_num_cur", 98, 2, "I", 1), 

50 ("file_number", 100, 4, "I", None), 

51 ("logical_volume_within_volume", 104, 4, "I", None), 

52 ("logical_volume_within_physical", 108, 4, "I", None), 

53 ("logical_volume_creation_date", 112, 8, "A", None), # YYYYMMDD 

54 ("logical_volume_creation_time", 120, 8, "A", None), # HHMMSSXX 

55 ("logical_volume_creation_country", 128, 12, "A", None), 

56 ("logical_volume_creation_agency", 140, 8, "A", None), 

57 ("logical_volume_generation_facility", 148, 12, "A", None), 

58 ("number_of_file_pointer_records", 160, 4, "I", None), 

59 ("number_of_text_records", 164, 4, "I", None), 

60 # Volume descriptor spare A92 + local use segment A100 

61] 

62volume_descriptor_record_length = 360 

63 

64file_pointer_format = [ 

65 ("record_number", 0, 4, "B", None), 

66 ("record_type", 5, 1, "B", None), 

67 ("reference_id", 20, 16, "A", None), 

68 ("reference_file_class_code", 64, 4, "A", None), 

69 # ("number_of_records", 100, 8, "I", None), 

70 # ("number_of_physical", 140, 2, "I", None), 

71] 

72file_pointer_record_length = 360 

73 

74text_records_format = [ 

75 ("record_number", 0, 4, "B", None), 

76 ("product_id", 16, 40, "A", None), 

77 ("scene_id", 156, 40, "A", None), 

78 ("scene_location_id", 196, 40, "A", None), 

79] 

80text_record_length = 360 

81 

82 

83class VolFile: 

84 r""" 

85 Processing a Volume Directory file in the CEOS format. The parsed 

86 informations can be accessed through the attributes `descriptor_records`, 

87 `file_pointer_records` and `text_records` 

88 

89 Arguments: 

90 filepath: the path to the volume directory file 

91 """ 

92 

93 def __init__(self, filepath: Union[str, pathlib.Path]): 

94 self.descriptor_records = {} 

95 self.file_pointer_records = [] 

96 self.text_record = {} 

97 

98 with open(filepath, "rb") as fh: 

99 # Parsing the volume descriptor 

100 fh_offset = 0 

101 fh_offset = parse_utils.parse_from_format( 

102 fh, 

103 self.descriptor_records, 

104 descriptor_format, 

105 1, 

106 volume_descriptor_record_length, 

107 fh_offset, 

108 ) 

109 

110 # Parsing the file pointer 

111 number_of_file_pointer_records = self.descriptor_records[ 

112 "number_of_file_pointer_records" 

113 ] 

114 fh_offset = parse_utils.parse_from_format( 

115 fh, 

116 self.file_pointer_records, 

117 file_pointer_format, 

118 number_of_file_pointer_records, 

119 file_pointer_record_length, 

120 fh_offset, 

121 ) 

122 

123 # Parsing the file pointer 

124 fh_offset = parse_utils.parse_from_format( 

125 fh, 

126 self.text_record, 

127 text_records_format, 

128 1, 

129 text_record_length, 

130 fh_offset, 

131 ) 

132 

133 @property 

134 def num_polarizations(self): 

135 return len( 

136 [ 

137 True 

138 for fp in self.file_pointer_records 

139 if fp["reference_file_class_code"] == "IMOP" 

140 ] 

141 ) 

142 

143 def __repr__(self): 

144 descriptor_txt = parse_utils.format_dictionary(self.descriptor_records, 1) 

145 # text_txt = parse_utils.format_dictionary(self.text_records, 1) 

146 fp_texts = "" 

147 for i, fi in enumerate(self.file_pointer_records): 

148 fp_texts += f"File pointer {i} : \n" + parse_utils.format_dictionary(fi, 2) 

149 fp_texts += "\n" 

150 

151 text_texts = parse_utils.format_dictionary(self.text_record, 1) 

152 return f""" 

153Descriptor: 

154{descriptor_txt} 

155File pointers : {len(self.file_pointer_records)} records 

156{fp_texts} 

157 

158Text records: 

159{text_texts} 

160 """