Skip to content

Commit

Permalink
Merge pull request #48 from UMDBPP/develop
Browse files Browse the repository at this point in the history
add sorting, fix slicing, add dataframe property
  • Loading branch information
zacharyburnett authored Mar 21, 2021
2 parents 8a73c66 + 6ad243f commit b943213
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 6 deletions.
18 changes: 15 additions & 3 deletions packetraven/structures.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from typing import Any, Iterable, List, Union

from numpy import int32, int64


class DoublyLinkedList:
"""
Expand Down Expand Up @@ -149,6 +151,12 @@ def count(self, value) -> int:

return sum([1 for node_value in self if node_value == value])

def sort(self):
sorted_values = sorted(self)
self.head = None
self.tail = None
self.extend(sorted_values)

@property
def difference(self) -> [Any]:
"""
Expand Down Expand Up @@ -216,12 +224,16 @@ def _remove_node(self, node: Node):
self.head = node.next_node

def __getitem__(self, index: Union[int, Iterable[int], slice]) -> Union[Any, List[Any]]:
if isinstance(index, int):
if isinstance(index, int) or isinstance(index, int32) or isinstance(index, int64):
return self._node_at_index(index).value
elif isinstance(index, Iterable):
return [self.__getitem__(value) for value in index]
return self.__class__([self.__getitem__(value) for value in index])
elif isinstance(index, slice):
return self.__getitem__(range(*(value for value in (index.start, index.stop, index.step) if value is not None)))
slice_parameters = [value for value in (index.start, index.stop, index.step) if value is not None]
if all(slice_parameter is None for slice_parameter in slice_parameters):
return self
else:
return self.__getitem__(range(*slice_parameters))
else:
raise ValueError(f'unrecognized index: {index}')

Expand Down
35 changes: 32 additions & 3 deletions packetraven/tracks.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
from datetime import datetime, timedelta
from typing import Union
from typing import Iterable, Union

from dateutil.parser import parse as parse_date
import numpy
from pandas import DataFrame
from pyproj import CRS

from .model import SECONDS_TO_GROUND
Expand Down Expand Up @@ -36,6 +37,13 @@ def append(self, packet: LocationPacket):
packet.transform_to(self.crs)
self.packets.append(packet)

def extend(self, packets: [LocationPacket]):
for packet in packets:
self.append(packet)

def sort(self):
self.packets.sort()

@property
def times(self) -> numpy.ndarray:
return numpy.array([packet.time for packet in self.packets], dtype=numpy.datetime64)
Expand Down Expand Up @@ -137,8 +145,13 @@ def length(self) -> float:
""" total length of the packet track over the ground """
return sum([distance.overground for distance in self.packets.difference])

def __getitem__(self, index: Union[int, slice]) -> LocationPacket:
return self.packets[index]
def __getitem__(self, index: Union[int, Iterable[int], slice]) -> Union[LocationPacket, 'LocationPacketTrack']:
if isinstance(index, int):
return self.packets[index]
elif isinstance(index, Iterable) or isinstance(index, slice):
return self.__class__(self.name, self.packets[index], self.crs)
else:
raise ValueError(f'unrecognized index: {index}')

def __iter__(self):
return iter(self.packets)
Expand All @@ -158,6 +171,22 @@ def __eq__(self, other) -> bool:
def __str__(self) -> str:
return str(list(self))

@property
def dataframe(self) -> DataFrame:
return DataFrame({
'name': [self.name for _ in range(len(self))],
'times': self.times,
'x': self.coordinates[:, 0],
'y': self.coordinates[:, 1],
'z': self.coordinates[:, 2],
'intervals': self.intervals,
'overground_distances': self.overground_distances,
'ascents': self.ascents,
'ascent_rates': self.ascent_rates,
'ground_speeds': self.ground_speeds,
'cumulative_overground_distances': self.cumulative_overground_distances,
})


class BalloonTrack(LocationPacketTrack):
def __init__(self, name: str, packets: [LocationPacket] = None, crs: CRS = None):
Expand Down
1 change: 1 addition & 0 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@
'aprslib',
'haversine',
'numpy>=1.20.0',
'pandas',
'pyserial',
'geojson',
'fastkml',
Expand Down
2 changes: 2 additions & 0 deletions tests/test_packets.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,8 @@ def test_append():
assert track[0] is packet_1
assert track[1] is packet_2
assert track[-1] is packet_2
assert track[:] == track
assert track[1:] == APRSTrack(track.name, track.packets[1:], track.crs)


def test_values():
Expand Down

0 comments on commit b943213

Please sign in to comment.