Skip to content

Commit

Permalink
various gps parsers support
Browse files Browse the repository at this point in the history
  • Loading branch information
nicokant committed Jan 19, 2024
1 parent 2eeb923 commit 7099409
Show file tree
Hide file tree
Showing 4 changed files with 151 additions and 10 deletions.
7 changes: 7 additions & 0 deletions wizard/parsers/helpers.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,13 @@ def stream_starts_with(stream, text):
return chunk == text


def stream_chunk_contains(stream, length, text):
position = stream.tell()
chunk = stream.read(length)
stream.seek(position)
return text in chunk


def read_csv(data, separator=",", newline="\n", trailing=""):
for line in data.split(newline):
if not line:
Expand Down
6 changes: 2 additions & 4 deletions wizard/parsers/parser.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,13 @@
import logging

from .parser_base import Parser
from .parser_gps import GPSParser, GPSCSVParser
from .parser_gps import PARSERS as GPS_PARSERS
from .parser_pathtrack import PathtrackParser, PathtrackParserNoUnknown

available_parsers = [
GPSParser,
GPSCSVParser,
PathtrackParser,
PathtrackParserNoUnknown,
]
] + GPS_PARSERS


def detect(stream) -> Parser:
Expand Down
9 changes: 5 additions & 4 deletions wizard/parsers/parser_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,16 +37,17 @@ class CSVParser(Parser):
DATATYPE = "generic_csv"
FIELDS = []
SEPARATOR = ','
SKIP_INITIAL_SPACE = True

def __init__(self, stream):
super().__init__(stream)
if not self.stream.seekable():
self._raise_not_supported('Stream not seekable')

reader = csv.reader(self.stream, delimiter=self.SEPARATOR)
reader = csv.reader(self.stream, delimiter=self.SEPARATOR, skipinitialspace=self.SKIP_INITIAL_SPACE)
header = next(reader)
if len(header) != len(self.FIELDS):
self._raise_not_supported(f"Stream have a number of fields different than expected, {len(header)} != {len(self.FIELDS)}")
if header != self.FIELDS:
self._raise_not_supported(f"Stream have a header different than expected, {header} != {self.FIELDS}")

self.stream.seek(0)
self.data = pd.read_csv(self.stream, sep=self.SEPARATOR)
self.data = pd.read_csv(self.stream, header=1, names=self.FIELDS, sep=self.SEPARATOR)
139 changes: 137 additions & 2 deletions wizard/parsers/parser_gps.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,9 @@
import pandas as pd
import csv
import io
import logging
from .parser_base import CSVParser
from .helpers import stream_starts_with, stream_chunk_contains


class GPSParser(CSVParser):
Expand Down Expand Up @@ -31,8 +36,138 @@ class GPSParser(CSVParser):
]


class GPSCSVParser(CSVParser):
DATATYPE = "gps_csv"
class IGotU_GT_Parser(CSVParser):
'''
Parser for IGotU_GT X version Logger
'''
DATATYPE = "gps_igotugl"
FIELDS = [
"Date", "Time", "Latitude", "Longitude", "Altitude", "Speed", "Course", "Type", "Distance", "Essential"
]


class IGotU_GT_TabSeparatedParser(IGotU_GT_Parser):
'''
Parser for Earth&Ocean Logger separated by tabs
'''
SEPARATOR = '\t'


class GPSUnknownFormatParser(CSVParser):
'''
Parser for a format, its a GPS CSV like format
with the following fields
'''
DATATYPE = "gps_unknown"
SEPARATOR = '\t'
FIELDS = [
"DataID", "ID","Ring_nr","Date","Time","Altitude","Speed","Course","HDOP","Latitude","Longitude","TripNr"]


class GPSUnknownFormatParserWithEmptyColumns(GPSUnknownFormatParser):
'''
Parser for a format, its a GPS CSV like format
with the following fields
'''

def __init__(self, stream):
self.stream = stream
self.data = []

if not self.stream.seekable():
self._raise_not_supported('Stream not seekable')

reader = csv.reader(self.stream, delimiter=self.SEPARATOR, skipinitialspace=self.SKIP_INITIAL_SPACE)
header = next(reader)

# Filter empty columns
header = [c for c in header if c != ""]

if header != self.FIELDS:
self._raise_not_supported(f"Stream have a header different than expected, {header} != {self.FIELDS}")

self.stream.seek(0)
self.data = pd.read_csv(self.stream, header=1, names=self.FIELDS, sep=self.SEPARATOR)


class GPSCatTrackParser(CSVParser):
'''
Parser for a format, its a GPS CSV like format
with the following fields
'''
DATATYPE = "gps_cattrack"
DIVIDER = "--------\n"
FIELDS = [
"Date", "Time", "Latitude", "Longitude", "Altitude", "Satellites", "HDOP", "PDOP", "Temperature [C]", "Speed [km/h]", "TTFF", "SNR", "tbd"]

def __init__(self, stream):
self.stream = stream
self.data = []

if not self.stream.seekable():
self._raise_not_supported('Stream not seekable')

if not stream_starts_with(self.stream, "Name:CatLog"):
self._raise_not_supported(f"Stream must start with Name:CatLog")

_intro, data = self.stream.read().split(self.DIVIDER)
content = io.StringIO(data)

reader = csv.reader(content, delimiter=self.SEPARATOR, skipinitialspace=self.SKIP_INITIAL_SPACE)
header = next(reader)
if header != self.FIELDS:
self._raise_not_supported(f"Stream have fields different than expected, {header} != {self.FIELDS}")

self.data = pd.read_csv(content, header=0, names=self.FIELDS, sep=self.SEPARATOR)


class GPS2JMParser(CSVParser):
'''
Parser for 2Jm format
'''
DATATYPE = "gps_2jm"
# TODO: define fields
FIELDS = [str(x) for x in range(0,13)]
SEPARATOR = " "
ENDINGS = [
"[EOF]",
"---- End of data ----",
]

def __init__(self, stream):
self.stream = stream
self.data = []

if not self.stream.seekable():
self._raise_not_supported('Stream not seekable')

if not stream_chunk_contains(self.stream, 30, "2JmGPS-LOG"):
self._raise_not_supported(f"Stream must start with 2JmGPS-LOG")

groups = self.stream.read().split('\n\n')[1:]
data = None
for group in groups:
if group in self.ENDINGS:
break
data = group

content = io.StringIO(data)

reader = csv.reader(content, delimiter=self.SEPARATOR, skipinitialspace=self.SKIP_INITIAL_SPACE)
header = next(reader)
if len(header) != len(self.FIELDS):
self._raise_not_supported(f"Stream have fields different than expected, {len(header)} != {len(self.FIELDS)}")

self.data = pd.read_csv(content, header=0, names=self.FIELDS, sep=self.SEPARATOR)



PARSERS = [
GPSParser,
GPSUnknownFormatParser,
GPSUnknownFormatParserWithEmptyColumns,
GPSCatTrackParser,
IGotU_GT_Parser,
IGotU_GT_TabSeparatedParser,
GPS2JMParser,
]

0 comments on commit 7099409

Please sign in to comment.