In [13]:
%matplotlib inline
from construct import *
import numpy as np
import subprocess
import sys
import matplotlib.pyplot as plt
import pandas as pd
import struct
import re
# SSDV_PATH = 'ssdv'
SSDV_PATH = '/Users/dijkema/Desktop/dslwp/ssdv/ssdv/ssdv'
In [2]:
TMPrimaryHeader = BitStruct('transfer_frame_version_number' / BitsInteger(2),
'spacecraft_id' / BitsInteger(10),
'virtual_channel_id' / BitsInteger(3),
'ocf_flag' / Flag,
'master_channel_frame_count' / BitsInteger(8),
'virtual_channel_frame_count' / BitsInteger(8),
'first_header_pointer' / BitsInteger(8))
In [3]:
def format_range(missing_range):
(beginstr, endstr) = missing_range
begin = int(beginstr) + 1
end = int(endstr) - 1
if begin == end:
return str(begin)
else:
return f"{begin}-{end}"
def format_missing_packets(ssdv_output):
matches = re.findall("Gap detected between packets (.*) and (.*)", ssdv_output)
return ",".join([format_range(missing_range) for missing_range in matches])
In [19]:
def seqnum(packet):
return packet[1]*256 + packet[2]
def unwrap(seqnums):
count = 0
location = 0
for j,x in enumerate(seqnums):
if x >= 240:
count += 1
if count == 5:
location = j
break
else:
count = 0
s = seqnums.copy().astype('int')
s[location:][s[location:] < 230] += 256
return s
def crc32(data, initial_value = 0):
"""Implementation taken from crc32() in ssdv.c"""
crc = initial_value
for d in data:
x = (crc ^ d) & 0xFF
for _ in range(8):
if x & 1:
x = (x >> 1) ^ 0xEDB88320
else:
x >>= 1
crc = (crc >> 8) ^ x
return crc ^ 0xFFFFFFFF
def check_ssdv_crc(frame):
return crc32(frame[5:-4], 0x4EE4FDE1) == struct.unpack('>I', frame[-4:])[0]
def process_ssdv_frames(frames, output_path):
missing_packets = {}
x = np.frombuffer(bytes().join(frames), dtype = 'uint8').reshape((-1,223))[:,5:]
seq = unwrap(x[:,0])
ids = set(seq)
for i in ids:
l = list(x[seq==i,:])
l.sort(key=seqnum)
ssdv = '{}_{:03d}.ssdv'.format(output_path, i)
jpeg = '{}_{:03d}.jpg'.format(output_path, i)
np.array(l).tofile(ssdv)
ssdv_output = subprocess.run([SSDV_PATH, '-d', '-D', ssdv, jpeg],
stderr=subprocess.PIPE)
missing_packets[i] = format_missing_packets(
ssdv_output.stderr.decode('utf-8'))
return missing_packets
In [7]:
frames = pd.read_csv('/Users/dijkema/Desktop/dslwp/dslwp-data/raw_frame.csv')
frames['raw_data'] = frames['raw_data'].apply(bytes().fromhex)
frames['is_ssdv'] = [TMPrimaryHeader.parse(frame).virtual_channel_id == 1 \
and check_ssdv_crc(frame) for frame in frames['raw_data']]
In [11]:
frames = frames[frames['remark']!="replay"]
In [20]:
missing_packets = process_ssdv_frames(frames[frames['is_ssdv']]['raw_data'].values,
'output/img')
In [43]:
image_df = pd.DataFrame.from_dict(missing_packets, orient='index', columns=['missing_packets'])
In [47]:
def to_numpy_array(byteslist):
return np.frombuffer(bytes().join(byteslist), dtype='uint8').reshape((-1,223))
In [48]:
frames['imageID'] = -1
In [49]:
frames.loc[frames['is_ssdv'], 'imageID'] = \
unwrap(to_numpy_array(frames[frames['is_ssdv']]['raw_data'].values)[:,5])
In [50]:
plt.plot(frames[frames['is_ssdv']]['imageID']);
In [59]:
image_df['contributors'] = ''
for imageID in range(300):
imageframes = frames[frames['imageID']==imageID]
if len(imageframes) > 0:
contributors = np.unique(frames[frames['imageID']==imageID]['proxy_nickname'].values)
image_df.loc[imageID, "contributors"] = ", ".join(contributors)
In [66]:
image_df["last_receive"] = frames[frames['is_ssdv']].groupby('imageID')['proxy_receive_time'].max()
image_df["first_receive"] = frames[frames['is_ssdv']].groupby('imageID')['proxy_receive_time'].min()
In [68]:
image_df.to_csv("temp.csv")
In [ ]: