diff --git a/simulations/lib/__init__.py b/simulations/lib/__init__.py index 82df24a..d9b269d 100644 --- a/simulations/lib/__init__.py +++ b/simulations/lib/__init__.py @@ -1,3 +1,3 @@ from .travelsignal import * -from .location import * +from . import location from .util import * diff --git a/simulations/lib/location.py b/simulations/lib/location.py deleted file mode 100644 index 666af82..0000000 --- a/simulations/lib/location.py +++ /dev/null @@ -1,137 +0,0 @@ -""" -Locations are wrappers around a Numpy N-dimensional -array. -""" - -import numpy as np -from functools import partial - -try: - from travelsignal import TravelSignal -except ModuleNotFoundError: - from .travelsignal import TravelSignal - -class Location: - """ - A location is a point designated by a spatial coordinate x. - """ - - def __init__(self, x): - self.x = np.asarray(x) - - def __repr__(self): - return "Location({})".format(repr(self.x)) - - def __getitem__(self, key): - return self.x[key] - - def __setitem__(self, key, val): - self.x[key] = val - - # math - def __add__(self, other): - if isinstance(other, Location): - other = other.x - - return self.__class__(self.x + other) - - def __sub__(self, other): - if isinstance(other, Location): - other = other.x - - return self.__class__(self.x - other) - - def __mul__(self, other): - return self.__class__(self.x * other) - - def __eq__(self, other): - if isinstance(other, Location): - other = other.x - - return np.all(self.x == other) - - # math alias functions - __radd__ = __add__ - __rsub__ = __sub__ - __rmul__ = __mul__ - -class Receiver(Location): - """ - A location able to trace a signal over time. - - Optionally applies a transformation to the traced signal. - """ - def __repr__(self): - return "Receiver({})".format(repr(self.x)) - - def recv(self, travel_signal: TravelSignal) -> TravelSignal: - """ - Return a function that traces the signal as a function of time - at the receiver's location - """ - return partial(travel_signal, x_f=self.x) - - receive = recv - -class Emitter(Location): - """ - Emit a signal from position x_0 (and time t_0) - """ - def __repr__(self): - return "Emitter({})".format(repr(self.x)) - - def emit(self, travel_signal: TravelSignal) -> TravelSignal: - return partial(travel_signal, x_0=self.x) - - -if __name__ == "__main__": - import matplotlib.pyplot as plt - from mpl_toolkits.mplot3d import axes3d - - # 2D showcase - source = Emitter([1,1]) - - antennae = [ - Receiver([2,3]), - Receiver([10,10]), - Receiver([-2,-3]), - Receiver([-10,0]), - ] - - fig, ax = plt.subplots() - - ax.set_title("Geometry of Emitter(s) and Antennae") - ax.set_ylabel("y") - ax.set_xlabel("x") - ax.plot(*source.x, '*', label="Emitter") - - for j, ant in enumerate(antennae): - ax.plot(*ant.x, '+', label="Antenna {}".format(j)) - - ax.legend() - fig.show() - - # 3D showcase - source = Emitter([1,1,1]) - - antennae = [ - Receiver([2,3,0]), - Receiver([10,10,-5]), - Receiver([-2,-3,9]), - Receiver([-10,0,-5]), - ] - - fig = plt.figure() - ax = fig.add_subplot(111, projection='3d') - - ax.set_title("Geometry of Emitter(s) and Antennae") - ax.set_xlabel("x") - ax.set_ylabel("y") - ax.set_zlabel("z") - ax.plot([source.x[0]], *source.x[1:], '*', label="Emitter") - - for j, ant in enumerate(antennae): - ax.plot([ant.x[0]], *ant.x[1:], '+', label="Antenna {}".format(j)) - - ax.legend() - plt.show() diff --git a/simulations/lib/location/__init__.py b/simulations/lib/location/__init__.py new file mode 100644 index 0000000..90bb9fb --- /dev/null +++ b/simulations/lib/location/__init__.py @@ -0,0 +1,3 @@ +from .location import * +from .emitter import * +from .receiver import * diff --git a/simulations/lib/location/emitter.py b/simulations/lib/location/emitter.py new file mode 100644 index 0000000..b4cc656 --- /dev/null +++ b/simulations/lib/location/emitter.py @@ -0,0 +1,16 @@ +from functools import partial + +try: + from .location import Location +except ImportError: + from location import Location + +class Emitter(Location): + """ + Emit a signal from position x_0 (and time t_0) + """ + def __repr__(self): + return "Emitter({})".format(repr(self.x)) + + def emit(self, travel_signal: callable) -> callable: + return partial(travel_signal, x_0=self.x) diff --git a/simulations/lib/location/example.py b/simulations/lib/location/example.py new file mode 100755 index 0000000..2648567 --- /dev/null +++ b/simulations/lib/location/example.py @@ -0,0 +1,55 @@ +#!/usr/bin/env python3 + +import matplotlib.pyplot as plt +from mpl_toolkits.mplot3d import axes3d + +from receiver import Receiver +from emitter import Emitter + +# 2D showcase +source = Emitter([1,1]) + +antennae = [ + Receiver([2,3]), + Receiver([10,10]), + Receiver([-2,-3]), + Receiver([-10,0]), +] + +fig, ax = plt.subplots() + +ax.set_title("Geometry of Emitter(s) and Antennae") +ax.set_ylabel("y") +ax.set_xlabel("x") +ax.plot(*source.x, '*', label="Emitter") + +for j, ant in enumerate(antennae): + ax.plot(*ant.x, '+', label="Antenna {}".format(j)) + +ax.legend() +fig.show() + +# 3D showcase +source = Emitter([1,1,1]) + +antennae = [ + Receiver([2,3,0]), + Receiver([10,10,-5]), + Receiver([-2,-3,9]), + Receiver([-10,0,-5]), +] + +fig = plt.figure() +ax = fig.add_subplot(111, projection='3d') + +ax.set_title("Geometry of Emitter(s) and Antennae") +ax.set_xlabel("x") +ax.set_ylabel("y") +ax.set_zlabel("z") +ax.plot([source.x[0]], *source.x[1:], '*', label="Emitter") + +for j, ant in enumerate(antennae): + ax.plot([ant.x[0]], *ant.x[1:], '+', label="Antenna {}".format(j)) + +ax.legend() +plt.show() diff --git a/simulations/lib/location/location.py b/simulations/lib/location/location.py new file mode 100644 index 0000000..2f181a2 --- /dev/null +++ b/simulations/lib/location/location.py @@ -0,0 +1,48 @@ +import numpy as np +from functools import partial + +class Location: + """ + A location is a point designated by a spatial coordinate x. + + Locations are wrappers around a Numpy N-dimensional array. + """ + + def __init__(self, x): + self.x = np.asarray(x) + + def __repr__(self): + return "Location({})".format(repr(self.x)) + + def __getitem__(self, key): + return self.x[key] + + def __setitem__(self, key, val): + self.x[key] = val + + # math + def __add__(self, other): + if isinstance(other, Location): + other = other.x + + return self.__class__(self.x + other) + + def __sub__(self, other): + if isinstance(other, Location): + other = other.x + + return self.__class__(self.x - other) + + def __mul__(self, other): + return self.__class__(self.x * other) + + def __eq__(self, other): + if isinstance(other, Location): + other = other.x + + return np.all(self.x == other) + + # math alias functions + __radd__ = __add__ + __rsub__ = __sub__ + __rmul__ = __mul__ diff --git a/simulations/lib/location/receiver.py b/simulations/lib/location/receiver.py new file mode 100644 index 0000000..5eeb299 --- /dev/null +++ b/simulations/lib/location/receiver.py @@ -0,0 +1,24 @@ +from functools import partial + +try: + from .location import Location +except ImportError: + from location import Location + +class Receiver(Location): + """ + A location able to trace a signal over time. + + Optionally applies a transformation to the traced signal. + """ + def __repr__(self): + return "Receiver({})".format(repr(self.x)) + + def recv(self, travel_signal: callable) -> callable: + """ + Return a function that traces the signal as a function of time + at the receiver's location + """ + return partial(travel_signal, x_f=self.x) + + receive = recv