Files
secondo/apis/python1/api/algebras/secondospatiotemporalalgebra.py
2026-01-23 17:03:45 +08:00

676 lines
19 KiB
Python

# ----------------------------------------------------------------------------------------------------------------------
# The Secondo Python API (pySecondo)
# Victor Silva (victor.silva@posteo.de)
# January 2020
# ----------------------------------------------------------------------------------------------------------------------
# Module
# ----------------------------------------------------------------------------------------------------------------------
# Secondo Spatio-Temporal Algebra
# secondospatiotemporalalgebra.py
# ----------------------------------------------------------------------------------------------------------------------
"""
The module Secondo Spatio-Temporal Algebra implements the data types for the conversion of list expression objects with
values of the types contained in the TemporalAlgebra of the |sec| system. The data types are implemented in Python
using Data Classes. Data Classes are implemented in the API like normal classes without behaviour.
Like regular classes their attributes can be called through the given names.
"""
from collections import namedtuple
from dataclasses import dataclass
from secondodb.api.support.secondolistexpr import ListExp
import secondodb.api.algebras.secondospatialalgebra as spatial
from datetime import datetime
@dataclass
class Interval:
"""
Implements a time interval.
"""
__slots__ = ["start_time", "end_time", "close_left", "close_right"]
start_time: datetime
end_time: datetime
close_left: bool
close_right: bool
@dataclass
class MotionVector:
"""
Implements a motion vector of a moving point.
"""
__slots__ = ["x1", "y1", "x2", "y2"]
x1: float
y1: float
x2: float
y2: float
@dataclass
class PointInInterval:
"""
Implements a structure to store the time interval and the motion vector of a moving point.
"""
__slots__ = ["interval", "motion_vector"]
interval: Interval
motion_vector: MotionVector
@dataclass
class MPoint:
"""
Implements a moving point as a series of points in intervals.
"""
__slots__ = ['intervals']
intervals: []
@dataclass
class MapPoint:
"""
Implements a map point, i.e. a motion vector for a point of a moving region.
"""
__slots__ = ["x1", "y1", "x2", "y2"]
x1: float
y1: float
x2: float
y2: float
@dataclass
class RegionInInterval:
"""
Implements a structure to store the time interval and the motion vector of a moving region.
"""
__slots__ = ["interval", "map_faces"]
interval: Interval
map_faces: []
@dataclass
class MRegion:
"""
Implements a moving region as a series of regions in intervals.
"""
__slots__ = ['intervals']
intervals: []
@dataclass
class MBool:
"""
Implements a moving boolean as a series of booleans in intervals.
"""
__slots__ = ['intervals']
intervals: []
@dataclass
class BoolInInterval:
"""
Implements a structure to store the time interval and the value vector of a moving boolean.
"""
__slots__ = ["interval", "value_vector"]
interval: Interval
value_vector: []
@dataclass
class ValueVectorBool:
"""
Implements the value vector for a moving boolean.
"""
__slots__ = ["value"]
value: bool
@dataclass
class RealInInterval:
"""
Implements a structure to store the time interval and the value vector of a moving real.
"""
__slots__ = ["interval", "value_vector"]
interval: Interval
value_vector: []
@dataclass
class ValueVectorReal:
"""
Implements the value vector for a moving real.
"""
__slots__ = ["start_value", "end_value", "boolean"]
start_value: float
end_value: float
boolean: bool
@dataclass
class MReal:
"""
Implements a moving real as a series of real values in intervals.
"""
__slots__ = ['intervals']
intervals: []
@dataclass
class MString:
"""
Implements a moving string as a series of string values in intervals.
"""
__slots__ = ['intervals']
intervals: []
@dataclass
class StringInInterval:
"""
Implements a structure to store the time interval and the value vector of a moving string.
"""
__slots__ = ["interval", "value_vector"]
interval: Interval
value_vector: []
@dataclass
class ValueVectorString:
"""
Implements the value vector for a moving string.
"""
__slots__ = ["value"]
value: str
@dataclass
class MInt:
"""
Implements a moving integer as a series of integer values in intervals.
"""
__slots__ = ['intervals']
intervals: []
@dataclass
class IntInInterval:
"""
Implements a structure to store the time interval and the value vector of a moving integer.
"""
__slots__ = ["interval", "value_vector"]
interval: Interval
value_vector: []
@dataclass
class ValueVectorInt:
"""
Implements the value vector for a moving integer.
"""
__slots__ = ["value"]
value: int
@dataclass
class IRegion:
"""
Implements an instant region as a region for a specific instant.
"""
__slots__ = ["instant", "region"]
instant: datetime
region: spatial.Region
@dataclass
class IPoint:
"""
Implements an instant point as a point for a specific instant.
"""
__slots__ = ["instant", "point"]
instant: datetime
point: spatial.Point
def parse_timestamp(timestamp: str) -> datetime:
"""
Parses a timestamp string using the Python module datetime.
Formats supported:
'%Y-%m-%d-%H:%M'
'%Y-%m-%d-%H:%M:%S'
'%Y-%m-%d-%H:%M:%S.%f'
:param timestamp: A string with a timestamp.
:return: A datetime object.
"""
try:
timestamp_as_datetime = datetime.strptime(timestamp, '%Y-%m-%d-%H:%M')
except ValueError:
pass
else:
return timestamp_as_datetime
try:
timestamp_as_datetime = datetime.strptime(timestamp, '%Y-%m-%d-%H:%M:%S')
except ValueError:
pass
else:
return timestamp_as_datetime
try:
timestamp_as_datetime = datetime.strptime(timestamp, '%Y-%m-%d-%H:%M:%S.%f')
except ValueError:
pass
else:
return timestamp_as_datetime
try:
timestamp_as_datetime = datetime.strptime(timestamp, '%Y-%m-%d')
except ValueError:
pass
else:
return timestamp_as_datetime
if timestamp == 'begin of time':
try:
timestamp_as_datetime = datetime.strptime('1900-01-01', '%Y-%m-%d')
except ValueError:
pass
else:
return timestamp_as_datetime
if timestamp == 'end of time':
try:
timestamp_as_datetime = datetime.strptime('9999-12-31', '%Y-%m-%d')
except ValueError:
pass
else:
return timestamp_as_datetime
def parse_mpoint(list_expr: ListExp) -> MPoint:
"""
Transforms a list expression object containing a moving point (mpoint) to a named tuple.
:param list_expr: A list expression object containing a moving point (mpoint).
:return: An object of the data class MPoint with the moving point.
"""
number_of_intervals = list_expr.get_list_length()
intervals = []
for i in range(1, number_of_intervals):
point_in_interval_as_le: ListExp = list_expr.get_the_n_element(i)
# Parse interval
interval_as_le: ListExp = point_in_interval_as_le.get_first_element()
start_time = parse_timestamp(interval_as_le.get_first_element().value)
end_time = parse_timestamp(interval_as_le.get_second_element().value)
close_left = interval_as_le.get_third_element().value
close_right = interval_as_le.get_fourth_element().value
interval = Interval(start_time=start_time, end_time=end_time, close_left=close_left, close_right=close_right)
# Parse motion vector
motion_vector_as_le: ListExp = point_in_interval_as_le.get_second_element()
x1 = motion_vector_as_le.get_first_element().value
y1 = motion_vector_as_le.get_second_element().value
x2 = motion_vector_as_le.get_third_element().value
y2 = motion_vector_as_le.get_fourth_element().value
motion_vector = MotionVector(x1=x1, y1=y1, x2=x2, y2=y2)
point_in_interval = PointInInterval(interval, motion_vector)
intervals.append(point_in_interval)
return MPoint(intervals)
def parse_mregion(list_expr: ListExp) -> MRegion:
"""
Transforms a list expression object containing a moving region (mregion) to a named tuple.
:param list_expr: A list expression object containing a moving region (mregion).
:return: An object of the data class MRegion with the moving region.
"""
number_of_intervals = list_expr.get_list_length()
intervals = []
for i in range(1, number_of_intervals):
region_in_interval_as_le: ListExp = list_expr.get_the_n_element(i)
# Parse interval
interval_as_le: ListExp = region_in_interval_as_le.get_first_element()
start_time = parse_timestamp(interval_as_le.get_first_element().value)
end_time = parse_timestamp(interval_as_le.get_second_element().value)
close_left = interval_as_le.get_third_element().value
close_right = interval_as_le.get_fourth_element().value
interval = Interval(start_time=start_time, end_time=end_time, close_left=close_left, close_right=close_right)
# Parse map faces
map_faces_as_le: ListExp = region_in_interval_as_le.get_second_element()
number_of_map_faces = map_faces_as_le.get_list_length()
map_faces = []
for j in range(1, number_of_map_faces):
map_face_as_le: ListExp = map_faces_as_le.get_the_n_element(j)
number_of_cycles = map_face_as_le.get_list_length() - 1
if number_of_cycles == 1:
# Parse outercycle
outercycle_as_le: ListExp = map_face_as_le.get_first_element()
number_of_map_points = outercycle_as_le.get_list_length()
map_points = []
for k in range(1, number_of_map_points):
map_point_as_le: ListExp = outercycle_as_le.get_the_n_element(k)
x1 = map_point_as_le.get_first_element().value
y1 = map_point_as_le.get_second_element().value
x2 = map_point_as_le.get_third_element().value
y2 = map_point_as_le.get_fourth_element().value
map_points.append(MapPoint(x1=x1, y1=y1, x2=x2, y2=y2))
map_faces.append(spatial.Face(outercycle=map_points, holecycles=[]))
elif number_of_cycles == 2:
# Parse outercycle
outercycle_as_le: ListExp = map_face_as_le.get_first_element()
number_of_map_points = outercycle_as_le.get_list_length()
outercycle = []
for k in range(1, number_of_map_points):
map_point_as_le: ListExp = outercycle_as_le.get_the_n_element(k)
x1 = map_point_as_le.get_first_element().value
y1 = map_point_as_le.get_second_element().value
x2 = map_point_as_le.get_third_element().value
y2 = map_point_as_le.get_fourth_element().value
outercycle.append(MapPoint(x1=x1, y1=y1, x2=x2, y2=y2))
# Parse holecycle
holecycle_as_le: ListExp = map_face_as_le.get_second_element()
number_of_map_points = holecycle_as_le.get_list_length()
holecycle = []
for k in range(1, number_of_map_points):
map_point = namedtuple('map_point', ['x1', 'y1', 'x2', 'y2'])
map_point_as_le: ListExp = holecycle_as_le.get_the_n_element(k)
map_point.x1 = map_point_as_le.get_first_element().value
map_point.y1 = map_point_as_le.get_second_element().value
map_point.x2 = map_point_as_le.get_third_element().value
map_point.y2 = map_point_as_le.get_fourth_element().value
holecycle.append(map_point)
map_faces.append(spatial.Face(outercycle=outercycle, holecycles=[holecycle]))
intervals.append(RegionInInterval(interval, map_faces))
return MRegion(intervals)
def parse_mreal(list_expr) -> MReal:
"""
Transforms a list expression object containing a moving real (mreal) to a named tuple.
:param list_expr: A list expression object containing a moving real (mreal).
:return: An object of the data class MReal with the moving real.
"""
number_of_intervals = list_expr.get_list_length()
intervals = []
for i in range(1, number_of_intervals):
real_in_interval_as_le: ListExp = list_expr.get_the_n_element(i)
# Parse interval
interval_as_le: ListExp = real_in_interval_as_le.get_first_element()
start_time = parse_timestamp(interval_as_le.get_first_element().value)
end_time = parse_timestamp(interval_as_le.get_second_element().value)
close_left = interval_as_le.get_third_element().value
close_right = interval_as_le.get_fourth_element().value
interval = Interval(start_time=start_time, end_time=end_time, close_left=close_left, close_right=close_right)
# Parse value vector
motion_vector_as_le: ListExp = real_in_interval_as_le.get_second_element()
start_value = motion_vector_as_le.get_second_element().value
end_value = motion_vector_as_le.get_third_element().value
boolean = motion_vector_as_le.get_fourth_element().value
value_vector = ValueVectorReal(start_value=start_value, end_value=end_value, boolean=boolean)
intervals.append(RealInInterval(interval=interval, value_vector=value_vector))
return MReal(intervals=intervals)
def parse_mbool(list_expr: ListExp) -> MBool:
"""
Transforms a list expression object containing a moving boolean (mbool) to a named tuple.
:param list_expr: A list expression object containing a moving boolean (mbool).
:return: An object of the data class MBool with the moving boolean.
"""
number_of_intervals = list_expr.get_list_length()
intervals = []
for i in range(1, number_of_intervals):
bool_in_interval_as_le: ListExp = list_expr.get_the_n_element(i)
# Parse interval
interval_as_le: ListExp = bool_in_interval_as_le.get_first_element()
start_time = parse_timestamp(interval_as_le.get_first_element().value)
end_time = parse_timestamp(interval_as_le.get_second_element().value)
close_left = interval_as_le.get_third_element().value
close_right = interval_as_le.get_fourth_element().value
interval = Interval(start_time=start_time, end_time=end_time, close_left=close_left, close_right=close_right)
# Parse value vector
value_vector_as_le: ListExp = bool_in_interval_as_le.get_second_element()
value = value_vector_as_le.value
value_vector = ValueVectorBool(value=value)
bool_in_interval = BoolInInterval(interval=interval, value_vector=value_vector)
intervals.append(bool_in_interval)
return MBool(intervals)
def parse_mstring(list_expr: ListExp) -> MString:
"""
Transforms a list expression object containing a moving string (mstring) to a named tuple.
:param list_expr: A list expression object containing a moving string (mstring).
:return: An object of the data class MString with the moving string.
"""
number_of_intervals = list_expr.get_list_length()
intervals = []
for i in range(1, number_of_intervals):
string_in_interval_as_le: ListExp = list_expr.get_the_n_element(i)
# Parse interval
interval_as_le: ListExp = string_in_interval_as_le.get_first_element()
start_time = parse_timestamp(interval_as_le.get_first_element().value)
end_time = parse_timestamp(interval_as_le.get_second_element().value)
close_left = interval_as_le.get_third_element().value
close_right = interval_as_le.get_fourth_element().value
interval = Interval(start_time=start_time, end_time=end_time, close_left=close_left, close_right=close_right)
# Parse value vector
value_vector_as_le: ListExp = string_in_interval_as_le.get_second_element()
value_vector = ValueVectorString(value=value_vector_as_le.value)
string_in_interval = StringInInterval(interval=interval, value_vector=value_vector)
intervals.append(string_in_interval)
return MString(intervals=intervals)
def parse_mint(list_expr: ListExp) -> MInt:
"""
Transforms a list expression object containing a moving integer (mint) to a named tuple.
:param list_expr: A list expression object containing a moving integer (mint).
:return: An object of the data class MInt with the moving integer.
"""
number_of_intervals = list_expr.get_list_length()
intervals = []
for i in range(1, number_of_intervals):
int_in_interval_as_le: ListExp = list_expr.get_the_n_element(i)
# Parse interval
interval_as_le: ListExp = int_in_interval_as_le.get_first_element()
start_time = parse_timestamp(interval_as_le.get_first_element().value)
end_time = parse_timestamp(interval_as_le.get_second_element().value)
close_left = interval_as_le.get_third_element().value
close_right = interval_as_le.get_fourth_element().value
interval = Interval(start_time=start_time, end_time=end_time, close_left=close_left, close_right=close_right)
# Parse value vector
value_vector_as_le: ListExp = int_in_interval_as_le.get_second_element()
value_vector = ValueVectorInt(value_vector_as_le.value)
int_in_interval = IntInInterval(interval=interval, value_vector=value_vector)
intervals.append(int_in_interval)
return MInt(intervals=intervals)
def parse_iregion(list_expr: ListExp) -> IRegion:
"""
Transforms a list expression object containing an instant region (iregion) to a named tuple.
:param list_expr: A list expression object containing an instant region (iregion).
:return: An object of the data class IRegion with the instant region.
"""
# Parse instant
instant_as_le: ListExp = list_expr.get_first_element()
instant = parse_timestamp(instant_as_le.value)
# Parse region
region_as_le: ListExp = list_expr.get_second_element()
region = spatial.parse_region(region_as_le)
return IRegion(instant=instant, region=region)
def parse_ipoint(list_expr: ListExp) -> IPoint:
"""
Transforms a list expression object containing an instant point (ipoint) to a named tuple.
:param list_expr: A list expression object containing an instant region (ipoint).
:return: An object of the data class IPoint with the instant point.
"""
# Parse instant
instant_as_le: ListExp = list_expr.get_first_element()
instant = parse_timestamp(instant_as_le.value)
# Parse point
point_as_le: ListExp = list_expr.get_second_element()
point = spatial.parse_point(point_as_le)
return IPoint(instant=instant, point=point)