Skip to content

Commit 77587cf

Browse files
authored
Merge pull request #777 from OpenSimulationInterface/760-bug-in-osi-docu-on-tracefiles
Removal of the historical .txt trace file format and related scripts
2 parents 41f14a3 + f38c922 commit 77587cf

File tree

5 files changed

+25
-229
lines changed

5 files changed

+25
-229
lines changed

doc/architecture/formatting_scripts.adoc

-22
Original file line numberDiff line numberDiff line change
@@ -7,28 +7,6 @@ endif::[]
77
The OSI repository contains Python scripts for converting trace files from one format to another.
88
The formatting scripts are stored in `open-simulation-interface/format/`
99

10-
**txt2osi.py**
11-
12-
`txt2osi.py` converts plain-text trace files to binary `.osi` trace files.
13-
This script takes the following parameters:
14-
15-
`--data`, `-d`::
16-
String containing the path to the file with serialized data.
17-
18-
`--type`, `-t`::
19-
Optional string describing the message type used to serialize data.
20-
`'SensorView'`, `'GroundTruth'`, or `'SensorData'` are permitted values.
21-
The default value is `'SensorView'`.
22-
23-
`--output`, `-o`::
24-
Optional string containing the name of the output file.
25-
The default value is `'converted.osi'`.
26-
27-
`--compress`, `-c`::
28-
Optional Boolean controlling whether to compress the output to an lzma file.
29-
`True`, or `False` are permitted values.
30-
The default value is `False`.
31-
3210
**osi2read.py**
3311

3412
`osi2read.py` converts trace files to human-readable `.txth` trace files.

doc/architecture/trace_file_formats.adoc

+6-5
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,20 @@ endif::[]
55
[#top-osi_trace_file_formats]
66
= OSI trace file formats
77

8-
There are multiple formats for storing multiple serialized OSI messages in one trace file.
8+
There are two formats for storing multiple serialized OSI messages in one trace file.
99

1010
*.osi::
1111
Binary trace file.
1212
Messages are separated by a length specification before each message.
1313
The length is represented by a four-byte, little-endian, unsigned integer.
1414
The length does not include the integer itself.
1515
16-
*.txt::
17-
Plain-text trace file.
18-
Messages are separated by `$$__$$`.
19-
2016
*.txth::
2117
Human-readable plain-text trace file.
2218
Messages are separated by newlines.
19+
20+
NOTE: Previous releases of OSI also supported a so-called plain-text trace file format, with file extension `.txt`.
21+
This legacy format did not contain plain-text, but rather binary protobuf messages separated by a special separator.
22+
For obvious reasons the format was deprecated and fully replaced with the `.osi` binary file format.
23+
This release no longer contains any support for the legacy `.txt` file format.
2324
These files may be used for manual checks.

format/OSITrace.py

+16-101
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,6 @@
1313

1414
warnings.simplefilter("default")
1515

16-
SEPARATOR = b"$$__$$"
17-
SEPARATOR_LENGTH = len(SEPARATOR)
1816
BUFFER_SIZE = 1000000
1917

2018

@@ -47,7 +45,7 @@ def __init__(self, path=None, type_name="SensorView"):
4745
self.retrieved_scenario_size = 0
4846
self._int_length = len(struct.pack("<L", 0))
4947

50-
def from_file(self, path, type_name="SensorView", max_index=-1, format_type=None):
48+
def from_file(self, path, type_name="SensorView", max_index=-1):
5149
"""Import a scenario from a file"""
5250

5351
if path.lower().endswith((".lzma", ".xz")):
@@ -56,69 +54,7 @@ def from_file(self, path, type_name="SensorView", max_index=-1, format_type=None
5654
self.scenario_file = open(path, "rb")
5755

5856
self.type_name = type_name
59-
self.format_type = format_type
60-
61-
if self.format_type == "separated":
62-
# warnings.warn("The separated trace files will be completely removed in the near future. Please convert them to *.osi files with the converter in the main OSI repository.", PendingDeprecationWarning)
63-
self.timestep_count = self.retrieve_message_offsets(max_index)
64-
else:
65-
self.timestep_count = self.retrieve_message()
66-
67-
def retrieve_message_offsets(self, max_index):
68-
"""
69-
Retrieve the offsets of all the messages of the scenario and store them
70-
in the `message_offsets` attribute of the object
71-
72-
It returns the number of discovered timesteps
73-
"""
74-
scenario_size = get_size_from_file_stream(self.scenario_file)
75-
76-
if max_index == -1:
77-
max_index = float("inf")
78-
79-
buffer_deque = deque(maxlen=2)
80-
81-
self.message_offsets = [0]
82-
eof = False
83-
84-
self.scenario_file.seek(0)
85-
86-
while not eof and len(self.message_offsets) <= max_index:
87-
found = -1 # SEP offset in buffer
88-
buffer_deque.clear()
89-
90-
while found == -1 and not eof:
91-
new_read = self.scenario_file.read(BUFFER_SIZE)
92-
buffer_deque.append(new_read)
93-
buffer = b"".join(buffer_deque)
94-
found = buffer.find(SEPARATOR)
95-
eof = len(new_read) != BUFFER_SIZE
96-
97-
buffer_offset = self.scenario_file.tell() - len(buffer)
98-
message_offset = found + buffer_offset + SEPARATOR_LENGTH
99-
self.message_offsets.append(message_offset)
100-
101-
self.scenario_file.seek(message_offset)
102-
103-
while eof and found != -1:
104-
buffer = buffer[found + SEPARATOR_LENGTH :]
105-
found = buffer.find(SEPARATOR)
106-
107-
buffer_offset = scenario_size - len(buffer)
108-
109-
message_offset = found + buffer_offset + SEPARATOR_LENGTH
110-
111-
if message_offset >= scenario_size:
112-
break
113-
self.message_offsets.append(message_offset)
114-
115-
if eof:
116-
self.retrieved_scenario_size = scenario_size
117-
else:
118-
self.retrieved_scenario_size = self.message_offsets[-1]
119-
self.message_offsets.pop()
120-
121-
return len(self.message_offsets)
57+
self.timestep_count = self.retrieve_message()
12258

12359
def retrieve_message(self):
12460
scenario_size = get_size_from_file_stream(self.scenario_file)
@@ -180,42 +116,21 @@ def get_messages_in_index_range(self, begin, end):
180116
for abs_message_offset in self.message_offsets[begin:end]
181117
]
182118

183-
if self.format_type == "separated":
184-
message_sequence_len = abs_last_offset - abs_first_offset - SEPARATOR_LENGTH
185-
serialized_messages_extract = self.scenario_file.read(message_sequence_len)
186-
187-
for rel_index, rel_message_offset in enumerate(rel_message_offsets):
188-
rel_begin = rel_message_offset
189-
rel_end = (
190-
rel_message_offsets[rel_index + 1] - SEPARATOR_LENGTH
191-
if rel_index + 1 < len(rel_message_offsets)
192-
else message_sequence_len
193-
)
194-
message = MESSAGES_TYPE[self.type_name]()
195-
serialized_message = serialized_messages_extract[rel_begin:rel_end]
196-
message.ParseFromString(serialized_message)
197-
yield message
198-
199-
elif self.format_type is None:
200-
message_sequence_len = abs_last_offset - abs_first_offset
201-
serialized_messages_extract = self.scenario_file.read(message_sequence_len)
202-
203-
for rel_index, rel_message_offset in enumerate(rel_message_offsets):
204-
rel_begin = rel_message_offset + self._int_length
205-
rel_end = (
206-
rel_message_offsets[rel_index + 1]
207-
if rel_index + 1 < len(rel_message_offsets)
208-
else message_sequence_len
209-
)
210-
211-
message = MESSAGES_TYPE[self.type_name]()
212-
serialized_message = serialized_messages_extract[rel_begin:rel_end]
213-
message.ParseFromString(serialized_message)
214-
yield message
119+
message_sequence_len = abs_last_offset - abs_first_offset
120+
serialized_messages_extract = self.scenario_file.read(message_sequence_len)
215121

216-
else:
217-
self.scenario_file.close()
218-
raise Exception(f"The defined format {self.format_type} does not exist.")
122+
for rel_index, rel_message_offset in enumerate(rel_message_offsets):
123+
rel_begin = rel_message_offset + self._int_length
124+
rel_end = (
125+
rel_message_offsets[rel_index + 1]
126+
if rel_index + 1 < len(rel_message_offsets)
127+
else message_sequence_len
128+
)
129+
130+
message = MESSAGES_TYPE[self.type_name]()
131+
serialized_message = serialized_messages_extract[rel_begin:rel_end]
132+
message.ParseFromString(serialized_message)
133+
yield message
219134

220135
def make_readable(self, name, interval=None, index=None):
221136
self.scenario_file.seek(0)

format/osi2read.py

+3-13
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
"""
2-
This program converts serialized txt/osi trace files into a human readable txth file.
2+
This program converts serialized osi trace files into a human readable txth file.
33
44
Example usage:
55
python3 osi2read.py -d trace.osi -o myreadableosifile
6-
python3 osi2read.py -d trace.txt -f separated -o myreadableosifile
76
"""
87

98
from OSITrace import OSITrace
@@ -19,7 +18,7 @@ def command_line_arguments():
1918
dir_path = os.path.dirname(os.path.dirname(os.path.realpath(__file__)))
2019

2120
parser = argparse.ArgumentParser(
22-
description="Convert a serialized osi/txt trace file to a readable txth output.",
21+
description="Convert a serialized osi trace file to a readable txth output.",
2322
prog="osi2read converter",
2423
)
2524
parser.add_argument(
@@ -42,15 +41,6 @@ def command_line_arguments():
4241
type=str,
4342
required=False,
4443
)
45-
parser.add_argument(
46-
"--format",
47-
"-f",
48-
help="Set the format type of the trace.",
49-
choices=["separated", None],
50-
default=None,
51-
type=str,
52-
required=False,
53-
)
5444

5545
return parser.parse_args()
5646

@@ -61,7 +51,7 @@ def main():
6151

6252
# Initialize the OSI trace class
6353
trace = OSITrace()
64-
trace.from_file(path=args.data, type_name=args.type, format_type=args.format)
54+
trace.from_file(path=args.data, type_name=args.type)
6555

6656
args.output = args.output.split(".", 1)[0] + ".txth"
6757

format/txt2osi.py

-88
This file was deleted.

0 commit comments

Comments
 (0)