-
Notifications
You must be signed in to change notification settings - Fork 8
/
Copy pathmodule_exportLogsort.py
470 lines (323 loc) · 13.5 KB
/
module_exportLogsort.py
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
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
import os
import shutil
import errno
import datetime
from module_CAMS2CMN import run_cams2cmn
from module_MTP2logsort import mtp2detected
logsort_name = 'LOG_SORT.INF'
capturestats_name = 'CaptureStats.log'
capturestats_dict_name = 'CaptureStats_logfile.txt'
def mkdir_p(path):
""" Makes a directory and handles all errors.
"""
try:
os.makedirs(path)
except OSError as exc:
if exc.errno == errno.EEXIST:
pass
else:
raise
def _makeCAMS2CMNdict(dir_path):
""" Returns a dictionary of names of converted FFbin files to fake Skypatrol C_ files.
"""
dict_path = dir_path+capturestats_dict_name
if not os.path.exists(dict_path):
print('No '+capturestats_dict_name+' found!')
return False
cams2cmn_dict = {}
for line in open(dict_path).readlines():
line = line.replace('\n', '').split()
ff_bin = line[3]
c_file = line[0]
cams2cmn_dict[ff_bin] = c_file
return cams2cmn_dict
def _getLogsortLines(dir_path, cams2cmn_dict, ff_bin, met_no):
""" Returns logsort lines of given meteor.
"""
if cams2cmn_dict is not None:
# CAMS
c_file = 'C_'+cams2cmn_dict[ff_bin]
else:
# Skypatrol
c_file = 'C_'+ff_bin.split('.')[0]
met_no = str(met_no).zfill(4)
logsort_list = []
for line in open(dir_path+logsort_name).readlines()[5:]:
if (line =='999') or (line == '999\n'):
break
line = line.split()
met_no_line = line[0]
c_file_line = line[4]
if (c_file == c_file_line) and (met_no == met_no_line):
logsort_list.append(line)
return logsort_list
def _getRecordDate(capturestats_path):
""" Returns a tuple containing date and time of recording start from CaptureStats.log file.
"""
capturestats_file = open(capturestats_path).readlines()
for line in capturestats_file:
if 'Start Time =' in line:
break
line = line.split()
month, date, year = map(int, line[3].split('/'))
hour, minute = map(int, line[4].split(':'))
return (year, month, date, hour, minute, 0)
def exportLogsort(dir_source, dir_dest, data_type, ff_bin, met_no, start_frame, end_frame, fps, image_list):
""" Export LOG_SORT.INF file from FTPdetectinfo for fireball analysis.
"""
# Find required files for processing
FTPdetect_status = False
FTPdetect_name = None
captured_stats_status = False
logfile_status = False
logfile_name = 'logfile.txt'
for line in os.listdir(dir_source):
if ('FTPdetectinfo' in line) and ('original' not in line):
FTPdetect_status = True
FTPdetect_name = line
if line == capturestats_name:
captured_stats_status = True
if line == logfile_name:
logfile_status = True
if FTPdetect_status and captured_stats_status and ((data_type == 1) or (data_type == 3)):
# CAMS processinig
mkdir_p(dir_dest)
shutil.copy2(dir_source + FTPdetect_name, dir_dest + FTPdetect_name)
shutil.copy2(dir_source + capturestats_name, dir_dest + capturestats_name)
# Convert CAMS format to CMN format
run_cams2cmn(dir_dest, 6, skip_calstars = True)
# Convert MTPdetections to LOG_SORT.INF
print('Converting MTPdetections to LOG_SORT.INF...')
mtp2detected(dir_dest, date = _getRecordDate(dir_dest + capturestats_name))
print('Done!')
cams2cmn_dict = _makeCAMS2CMNdict(dir_dest)
if cams2cmn_dict is False:
return False
logsort_list = _getLogsortLines(dir_dest, cams2cmn_dict, ff_bin, met_no)
elif logfile_status and (data_type == 2):
# Skypatrol processing
# Make output directory and copy logsort into it
mkdir_p(dir_dest)
shutil.copy2(dir_source + logsort_name, dir_dest + logsort_name)
logsort_list = _getLogsortLines(dir_dest, None, ff_bin, met_no)
else:
# No required files found
return False
logsort_list = _adjustLogsort(logsort_list, fps, start_frame = start_frame, end_frame = end_frame)
if logsort_list is False:
# GENERIC LOGSORT!
pass
logsort_list = _replaceImages(logsort_list, image_list)
# Write logsort changes to LOG_SORT.inf file
replaceLogsort(logsort_list, dir_dest+logsort_name)
return True
def replaceLogsort(logsort_list, logsort_path, header=None):
""" Write logsort list to a LOG_SORT.INF file.
"""
if os.path.exists(logsort_path):
if header is None:
# Read header from old logsort
old_logsort_header = open(logsort_path).readlines()[:5]
else:
old_logsort_header = header
# Open new logsort
newfile = open(logsort_path, 'w')
# Write old header to new logsort
for line in old_logsort_header:
newfile.write(line)
# Write new logsort data
for line in logsort_list:
newfile.write(" ".join(line)+'\n')
newfile.write('999')
newfile.close()
def _replaceImages(logsort_list, image_list):
""" Replaces images from logsort with ones provided in the list.
"""
if len(logsort_list) == len(image_list):
new_logsort = []
for i, line in enumerate(logsort_list):
new_logsort.append(line[:4] + [image_list[i]] + line[5:])
return new_logsort
else:
# Lists don't match!
return False
def _adjustLogsort(logsort_list, fps, start_frame, end_frame):
""" Adjusts frame number according to the given start and end frames, and replaces logsort image with given image names.
"""
def _getTime(time):
""" Returns datetime object from given format: HH:MM:SS:sss
"""
hour, minute, sec, msec = map(int, time.split(':'))
return datetime.datetime(year = 1970, month = 1, day = 1, hour = hour, minute = minute, second = sec, microsecond = msec*1000)
def _formatTime(time):
""" Returns formated string from datetime object in: HH:MM:SS:sss
"""
return ":".join([str(time.hour).zfill(2), str(time.minute).zfill(2), str(time.second).zfill(2), str(time.microsecond/1000).zfill(3)])
def _formatLogsortLine(met_no, frame, extend_time, julian_time):
""" Returns one line in logsort format, by given parameters.
"""
return [met_no, str(round(frame, 1)).zfill(6), extend_time, julian_time.zfill(9), "C_00000000", "00", "000", str(round(fill_x, 2)).zfill(6), str(round(fill_y, 2)).zfill(6), "000100"]
julian_diff = 0.02 # For interlaced frames
# Starting coordinates for filling missing frames
fill_x = 100.0
fill_y = 100.0
# Detect frame deinterlace
if len(logsort_list) >= 2:
frame_diff = abs(float(logsort_list[0][1]) - float(logsort_list[1][1]))
if frame_diff % 1 != 0:
interlaced = True
else:
interlaced = False
else:
# Too little frames for detection-based logsort, use the generic one!
print('Too little frames for detection-based logsort, use the generic one!')
return False
time_difference = 1.0 / (fps * ((int(interlaced) + 1)))
time_difference = datetime.timedelta(seconds = time_difference)
# Generate a list of frames to be written
if interlaced:
frame_list = range(start_frame*2, end_frame*2 + 2)
frame_list = map(float, frame_list)
frame_list = [x/2 for x in frame_list]
else:
julian_diff = julian_diff * 2
frame_list = range(start_frame, end_frame + 1)
met_no = logsort_list[0][0]
first_frame = float(logsort_list[0][1])
first_time = _getTime(logsort_list[0][2])
first_julian = float(logsort_list[0][3])
last_frame = float(logsort_list[-1][1])
last_time = _getTime(logsort_list[-1][2])
last_julian = float(logsort_list[-1][3])
# Cut or extand the beggining of a logsort list, according to the start frame
if first_frame < frame_list[0]:
# Cut beggining
start_pointer = 0
for line in logsort_list:
if float(line[1]) >= frame_list[0]:
break
start_pointer += 1
logsort_list = logsort_list[start_pointer:]
elif first_frame > frame_list[0]:
# Extend beggining
frame_extend = []
for frame in frame_list:
if float(logsort_list[0][1]) == frame:
break
frame_extend.append(frame)
extend_logsort_list = []
for i, ext_frame in enumerate(reversed(frame_extend)):
extend_time = _formatTime(first_time - (i+1) * time_difference)
julian_time = str(first_julian - (i+1) * julian_diff)
extend_line = _formatLogsortLine(met_no, ext_frame, extend_time, julian_time)
#fill_x += 1
#fill_y += 1
extend_logsort_list.append(extend_line)
extend_logsort_list = extend_logsort_list[::-1]
logsort_list = extend_logsort_list + logsort_list
# Cut or extand the end of a logsort list, according to the end frame
if last_frame > frame_list[-1]:
# Cut ending
end_pointer = 0
for line in logsort_list:
if float(line[1]) >= frame_list[-1]:
break
end_pointer += 1
logsort_list = logsort_list[:end_pointer+1]
elif last_frame < frame_list[-1]:
# Extend ending
frame_extend = []
for frame in reversed(frame_list):
if float(logsort_list[-1][1]) == frame:
break
frame_extend.append(frame)
frame_extend = frame_extend[::-1]
extend_logsort_list = []
for i, ext_frame in enumerate(frame_extend):
extend_time = _formatTime(last_time + (i+1) * time_difference)
julian_time = str(last_julian + (i+1) * julian_diff)
extend_line = _formatLogsortLine(met_no, ext_frame, extend_time, julian_time)
#fill_x += 1
#fill_y += 1
extend_logsort_list.append(extend_line)
logsort_list = logsort_list + extend_logsort_list
# Fill missing frames
for i, frame in enumerate(frame_list):
if float(logsort_list[i][1]) == frame:
previous_time = _getTime(logsort_list[i][2])
previous_julian = float(logsort_list[i][3])
else:
fill_time = _formatTime(previous_time + time_difference)
fill_julian = str(round(previous_julian + julian_diff, 3))
new_line = _formatLogsortLine(met_no, frame, fill_time, fill_julian)
logsort_list.insert(i, new_line)
previous_time = _getTime(fill_time)
previous_julian = float(fill_julian)
return logsort_list
def genericLogsort():
""" Generates a generic LOG_SORT.INF with placeholder positions.
"""
pass
def postAnalysisFix(logsort_path, data_type):
""" Fixes logsort after analysis with CMN_FBA.
"""
def _fixDoubleHeader(logsort_list):
""" Detects and removed double header produced by CMN_FBA.
"""
double_header = False
first_line = logsort_list[0]
count = 0
for line in logsort_list[1:]:
count += 1
if line == first_line:
double_header = True
break
if double_header:
logsort_list = logsort_list[count:]
header = logsort_list[:count]
else:
header = logsort_list[:5]
logsort_list = logsort_list[5:]
return header, logsort_list
# Load logsort content
try:
logsort_list = open(logsort_path).readlines()
except:
return False
# FBA can produce double header, fix that
header, logsort_list = _fixDoubleHeader(logsort_list)
# Save fixed logsort
replaceLogsort([line.split() for line in logsort_list], logsort_path, header = header)
if (data_type == 1) or (data_type == 3):
# CAMS processing
# Make a dictionary for a link between FF*.bin files and fake C_ files
parent_path = os.path.normpath(os.path.join(logsort_path, "..")) + os.sep
CAMS2CMNdict = _makeCAMS2CMNdict(parent_path)
if CAMS2CMNdict is False:
return False
image_list = []
logsort_split_list = []
for line in logsort_list:
if (line == '999') or (line == '999\n'):
break
line = line.split()
logsort_split_list.append(line)
if data_type == 1:
# CAMS processing
image = line[4].split('_frame')[0]+'.bin'
image_list.append('C_'+CAMS2CMNdict[image])
elif data_type == 2:
# Skypatrol processing
image = line[4].split('_frame')[0]+'.bmp'
image_list.append('C_'+image)
elif data_type == 3:
# RMS processing
image = line[4].split('_frame')[0] + '.fits'
image_list.append('C_' + CAMS2CMNdict[image])
logsort_list = _replaceImages(logsort_split_list, image_list)
# Rename LOG_SORT used with FBA
shutil.copy(logsort_path, '.'.join(logsort_path.split('.')[:-1])+'_FBA.inf')
replaceLogsort(logsort_list, logsort_path, header = header)
#exportLogsort("C:\\Users\\Administrator\\Desktop\\logsort_extract\\2014_08_19_00_30_28\\",
# "C:\\Users\\Administrator\\Desktop\\logsort_extract\\2014_08_19_00_30_28\\fireball_example\\", 'FF451_20140818_214533_437_0140032.bin', 5, 190, 210, 25, map(str, range(0, 42)))
#postAnalysisFix("C:\\Users\\Administrator\\Desktop\\fb_test\\LOG_SORT.INF")