Skip to content

Commit

Permalink
Alpha endpoint to correctly split path into selection parts
Browse files Browse the repository at this point in the history
fixes #253

TODO: altitude, see #256
  • Loading branch information
landswellsong committed Jun 4, 2017
1 parent bb3eb99 commit e786900
Show file tree
Hide file tree
Showing 6 changed files with 76 additions and 27 deletions.
78 changes: 66 additions & 12 deletions backend/promis/backend_api/serializer.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
from backend_api import helpers
import parsers
import unix_time
import math


class LookupById:
Expand Down Expand Up @@ -78,19 +79,8 @@ def get_geo_line(self, obj):
# Just in case for the future
#return obj.geo_line.wkb.hex()

poly = self.context['request'].query_params.get('polygon')

# Convert polygon to GEOS object as intersection doesn't auto-convert
if poly:
try:
poly = GEOSGeometry(poly, srid = 4326)
except ValueError:
raise NotFound("Invalid WKT for polygon selection")

geo_line = obj.geo_line if not poly else obj.geo_line.intersection(poly)

# TODO: study whether pre-building the list or JSON would speed up things
return parsers.wkb(geo_line.wkb) # <- Generator
return parsers.wkb(obj.geo_line.wkb) # <- Generator

def get_timelapse(self, obj):
# TODO: change to time_start in model for consistency
Expand Down Expand Up @@ -260,3 +250,67 @@ def update(self, instance, validated_data):
password = validated_data.pop('password')
instance.set_password(password)
return super().update(instance, validated_data)

# TODO: REFACTOR, alpha code below
class DataSerializer(serializers.ModelSerializer):
session = SwaggerHyperlinkedRelatedField(many = False, view_name = 'session-detail', read_only = True)
channel = SwaggerHyperlinkedRelatedField(many = False, view_name = 'channel-detail', read_only = True)
parameter = SwaggerHyperlinkedRelatedField(many = False, view_name = 'parameter-detail', read_only = True)
selection = serializers.SerializerMethodField()


class Meta(LookupById):
# TODO: add 'url' here, currently it's broken, see #196
fields = ('id', 'session', 'parameter', 'channel', 'sampling_frequency', 'min_frequency', 'max_frequency', 'selection')
model = models.Measurement

def get_selection(self, obj):
def gen_selection():
# Extracting request information
poly = self.context['request'].query_params.get('polygon')
time_begin = self.context['request'].query_params.get('time_begin')
time_end = self.context['request'].query_params.get('time_end')

# Agreeing on time boundaries
session_start = unix_time.datetime_to_utc(obj.session.time_begin)
session_end = unix_time.datetime_to_utc(obj.session.time_end)
time_begin = int(time_begin) if time_begin else session_start
time_end = int(time_end) if time_end else session_end

# Convert polygon to GEOS object as intersection doesn't auto-convert
if poly:
try:
poly = GEOSGeometry(poly, srid = 4326)

# FIXME: Django's GEOS implementation
# doesn't support 4D linestrings
# TODO: patch upstream, it's horrible!

# Intersection of search polygon and the orbit
for sect in obj.session.geo_line.intersection(poly):
# NOTE: taking the first and last point within the selection
sect_start = math.ceil(sect[0][2]) + session_start
sect_end = math.floor(sect[-1][2]) + session_start

# TODO: if you ever catch this assert, call me
assert sect_end >= sect_start

print(sect_start, sect_end)
print(time_begin, time_end)

# If the data not within time selection, skip completely
if sect_end < time_begin or sect_start > time_end:
continue

yield { 'start': max(time_begin, sect_start), 'end': min(time_end, sect_end) }


except ValueError:
raise NotFound("Invalid WKT for polygon selection")
# Otherwise take the whole session, just make sure to trim the time values
else:
yield { 'start': max(time_begin, session_start),
'end': min(time_end, session_end) }

# TODO: data links
return [ x for x in gen_selection() ]
15 changes: 5 additions & 10 deletions backend/promis/backend_api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@
from rest_framework.exceptions import NotAuthenticated, NotFound, MethodNotAllowed
from rest_framework.renderers import JSONRenderer, BrowsableAPIRenderer

from django.contrib.gis.geos import GEOSGeometry

import unix_time

import datetime
Expand Down Expand Up @@ -264,7 +262,7 @@ def UserUpdate(request):
# TODO: create a proper filterset
# TODO: make use of Q() to help django understand the request
class DataView(PromisViewSet):
serializer_class = serializer.MeasurementsSerializer
serializer_class = serializer.DataSerializer
# TODO: only to prevent Django from asking for base_name
queryset = models.Measurement.objects.all()

Expand All @@ -274,13 +272,14 @@ def get_queryset(self):
# Composing the filter
filter_opts = {}

# Begin-End's are reversed: we are looking for session that overlap the time selection
time_begin = self.request.query_params.get('time_begin')
if time_begin:
filter_opts['session__time_begin__gte'] = unix_time.maketime(int(time_begin))
filter_opts['session__time_end__gte'] = unix_time.maketime(int(time_begin))

time_end = self.request.query_params.get('time_end')
if time_end:
filter_opts['session__time_end__lte'] = unix_time.maketime(int(time_end))
filter_opts['session__time_begin__lte'] = unix_time.maketime(int(time_end))

# NOTE: channels and filters are combined as *AND* not *OR* at the moment
# so they are mutually exclusive in a sense, but this won't be a problem for alpha
Expand All @@ -296,15 +295,11 @@ def get_queryset(self):

poly = self.request.query_params.get('polygon')

# Convert polygon to GEOS object as intersection doesn't auto-convert
if poly:
try:
poly = GEOSGeometry(poly, srid = 4326)
filter_opts['session__geo_line__intersects'] = poly
except ValueError:
raise NotFound("Invalid WKT for polygon selection")

# Applying the filter
qs = models.Measurement.objects.filter(**filter_opts)

return qs
return models.Measurement.objects.filter(**filter_opts)
2 changes: 1 addition & 1 deletion backend/promis/classes/potential.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ def fetch(self, daydir):
ez_time_end = time_end

# Generator for the orbit
line_gen = ( (y.lon, y.lat, y.alt) for _, y, _ in orbit.generate_orbit(orbit_path, time_start, time_end) )
line_gen = ( (y.lon, y.lat, t) for t, y, _ in orbit.generate_orbit(orbit_path, time_start, time_end) )
# Converting time to python objects for convenience
# This is the point where onboard time gets converted to the UTC
time_start = unix_time.maketime(time_start)
Expand Down
2 changes: 1 addition & 1 deletion backend/promis/classes/test_set.py
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ def general_fetch(path, satellite_object):
timemark = int(sess_name)
ftp.cwd(sess_name)
with ftp.xopen("orbit.csv") as fp:
line_gen = [ pt for pt in parsers.csv(fp) ]
line_gen = [ (pt[0],pt[1],t) for t, pt in enumerate(parsers.csv(fp)) ]
time_start = unix_time.maketime(timemark)
time_end = unix_time.maketime(timemark + len(line_gen)) # Orbit points are 1 per second
time_dur = time_end - time_start
Expand Down
2 changes: 1 addition & 1 deletion backend/promis/orbit.py
Original file line number Diff line number Diff line change
Expand Up @@ -126,4 +126,4 @@ def predict(t):
res_vals[0] = ( res_vals[0] + 180 ) % 360 - 180
return OrbitPoint(*res_vals)

yield j, datapoints[j] if j in datapoints else predict(j), False if j in datapoints else True
yield j - orbit_start, datapoints[j] if j in datapoints else predict(j), False if j in datapoints else True
4 changes: 2 additions & 2 deletions frontend/app/components/CesiumMap.js
Original file line number Diff line number Diff line change
Expand Up @@ -458,8 +458,8 @@ export default class CesiumContainer extends Component {
let cartesians = new Array();

/* data is [lat, lon, hgt] */
data.forEach(function(point) {
cartesians.push(Cartesian3.fromDegrees(point[1], point[0], point[2] ? point[2] : 250000));
data.forEach(function(point) { // TODO temporary disabling altitude because it stores time temporarily
cartesians.push(Cartesian3.fromDegrees(point[1], point[0], /*point[2] ? point[2] :*/ 250000));
});

return this.viewer.entities.add({
Expand Down

0 comments on commit e786900

Please sign in to comment.