+
+
+
+
+
+
+
+
+
Admin 0 – Countries
+
+
+
+
+

+
About
+
Countries distinguish between metropolitan (homeland) and independent and semi-independent portions of sovereign states. If you want to see the dependent overseas regions broken out (like in ISO codes, see France for example), use map units instead.
+
Each country is coded with a world region that roughly follows the United Nations setup.
+
Includes some thematic data from the United Nations, U.S. Central Intelligence Agency, and elsewhere.
+
Disclaimer
+
Natural Earth Vector draws boundaries of countries according to defacto status. We show who actually controls the situation on the ground. Please feel free to mashup our disputed areas (link) theme to match your particular political outlook.
+
Known Problems
+
None.
+
Version History
+
+
+
The master changelog is available on Github ยป
+
+
+
+
+
+ This entry was posted
+ on Monday, September 21st, 2009 at 10:21 am and is filed under 110m-cultural-vectors.
+ You can follow any responses to this entry through the RSS 2.0 feed.
+
+ Both comments and pings are currently closed.
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/sharc/topology/countries/ne_110m_admin_0_countries.VERSION.txt b/sharc/topology/countries/ne_110m_admin_0_countries.VERSION.txt
new file mode 100644
index 000000000..ac14c3dfa
--- /dev/null
+++ b/sharc/topology/countries/ne_110m_admin_0_countries.VERSION.txt
@@ -0,0 +1 @@
+5.1.1
diff --git a/sharc/topology/countries/ne_110m_admin_0_countries.cpg b/sharc/topology/countries/ne_110m_admin_0_countries.cpg
new file mode 100644
index 000000000..3ad133c04
--- /dev/null
+++ b/sharc/topology/countries/ne_110m_admin_0_countries.cpg
@@ -0,0 +1 @@
+UTF-8
\ No newline at end of file
diff --git a/sharc/topology/countries/ne_110m_admin_0_countries.dbf b/sharc/topology/countries/ne_110m_admin_0_countries.dbf
new file mode 100644
index 000000000..e0acd0664
Binary files /dev/null and b/sharc/topology/countries/ne_110m_admin_0_countries.dbf differ
diff --git a/sharc/topology/countries/ne_110m_admin_0_countries.prj b/sharc/topology/countries/ne_110m_admin_0_countries.prj
new file mode 100644
index 000000000..b13a71791
--- /dev/null
+++ b/sharc/topology/countries/ne_110m_admin_0_countries.prj
@@ -0,0 +1 @@
+GEOGCS["GCS_WGS_1984",DATUM["D_WGS_1984",SPHEROID["WGS_1984",6378137.0,298.257223563]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.017453292519943295]]
\ No newline at end of file
diff --git a/sharc/topology/countries/ne_110m_admin_0_countries.shp b/sharc/topology/countries/ne_110m_admin_0_countries.shp
new file mode 100644
index 000000000..9318e45c7
Binary files /dev/null and b/sharc/topology/countries/ne_110m_admin_0_countries.shp differ
diff --git a/sharc/topology/countries/ne_110m_admin_0_countries.shx b/sharc/topology/countries/ne_110m_admin_0_countries.shx
new file mode 100644
index 000000000..c3728e0dd
Binary files /dev/null and b/sharc/topology/countries/ne_110m_admin_0_countries.shx differ
diff --git a/sharc/topology/topology.py b/sharc/topology/topology.py
index 32499b1b2..5b77721aa 100644
--- a/sharc/topology/topology.py
+++ b/sharc/topology/topology.py
@@ -9,13 +9,16 @@
import numpy as np
import matplotlib.axes
+
class Topology(object):
__metaclass__ = ABCMeta
- def __init__(self,
- intersite_distance: float,
- cell_radius: float):
+ def __init__(
+ self,
+ intersite_distance: float,
+ cell_radius: float,
+ ):
self.intersite_distance = intersite_distance
self.cell_radius = cell_radius
@@ -25,22 +28,19 @@ def __init__(self,
self.y = np.empty(0)
self.azimuth = np.empty(0)
self.indoor = np.empty(0)
+ self.is_space_station = False
self.num_base_stations = -1
self.static_base_stations = False
-
@abstractmethod
def calculate_coordinates(self, random_number_gen=np.random.RandomState()):
"""
Calculates the coordinates of the stations according to the class
atributes.
"""
- pass
-
@abstractmethod
def plot(self, ax: matplotlib.axes.Axes):
"""
Plots the topology on the given axis.
"""
- pass
diff --git a/sharc/topology/topology_factory.py b/sharc/topology/topology_factory.py
index 1d4f5503e..6418c3ae2 100644
--- a/sharc/topology/topology_factory.py
+++ b/sharc/topology/topology_factory.py
@@ -10,21 +10,45 @@
from sharc.topology.topology_macrocell import TopologyMacrocell
from sharc.topology.topology_hotspot import TopologyHotspot
from sharc.topology.topology_indoor import TopologyIndoor
+from sharc.topology.topology_ntn import TopologyNTN
from sharc.topology.topology_single_base_station import TopologySingleBaseStation
from sharc.parameters.parameters import Parameters
+
class TopologyFactory(object):
-
+
@staticmethod
def createTopology(parameters: Parameters) -> Topology:
- if parameters.imt.topology == "SINGLE_BS":
- return TopologySingleBaseStation(parameters.imt.intersite_distance*2/3, parameters.imt.num_clusters)
- elif parameters.imt.topology == "MACROCELL":
- return TopologyMacrocell(parameters.imt.intersite_distance, parameters.imt.num_clusters)
- elif parameters.imt.topology == "HOTSPOT":
- return TopologyHotspot(parameters.hotspot, parameters.imt.intersite_distance, parameters.imt.num_clusters)
- elif parameters.imt.topology == "INDOOR":
- return TopologyIndoor(parameters.indoor)
+ if parameters.imt.topology.type == "SINGLE_BS":
+ return TopologySingleBaseStation(
+ parameters.imt.topology.single_bs.cell_radius,
+ parameters.imt.topology.single_bs.num_clusters
+ )
+ elif parameters.imt.topology.type == "MACROCELL":
+ return TopologyMacrocell(
+ parameters.imt.topology.macrocell.intersite_distance,
+ parameters.imt.topology.macrocell.num_clusters
+ )
+ elif parameters.imt.topology.type == "HOTSPOT":
+ return TopologyHotspot(
+ parameters.imt.topology.hotspot,
+ parameters.imt.topology.hotspot.intersite_distance,
+ parameters.imt.topology.hotspot.num_clusters
+ )
+ elif parameters.imt.topology.type == "INDOOR":
+ return TopologyIndoor(parameters.imt.topology.indoor)
+ elif parameters.imt.topology.type == "NTN":
+ return TopologyNTN(
+ parameters.imt.topology.ntn.intersite_distance,
+ parameters.imt.topology.ntn.cell_radius,
+ parameters.imt.topology.ntn.bs_height,
+ parameters.imt.topology.ntn.bs_azimuth,
+ parameters.imt.topology.ntn.bs_elevation,
+ parameters.imt.topology.ntn.num_sectors,
+ )
else:
- sys.stderr.write("ERROR\nInvalid topology: " + parameters.imt.topology)
- sys.exit(1)
+ sys.stderr.write(
+ "ERROR\nInvalid topology: " +
+ parameters.imt.topology,
+ )
+ sys.exit(1)
diff --git a/sharc/topology/topology_hotspot.py b/sharc/topology/topology_hotspot.py
index da68d7d59..25a0e6c99 100644
--- a/sharc/topology/topology_hotspot.py
+++ b/sharc/topology/topology_hotspot.py
@@ -16,7 +16,7 @@
from sharc.topology.topology import Topology
from sharc.topology.topology_macrocell import TopologyMacrocell
-from sharc.parameters.parameters_hotspot import ParametersHotspot
+from sharc.parameters.imt.parameters_hotspot import ParametersHotspot
class TopologyHotspot(Topology):
@@ -56,28 +56,35 @@ def calculate_coordinates(self, random_number_gen=np.random.RandomState()):
y = np.empty(0)
azimuth = np.empty(0)
for cell_x, cell_y, cell_azimuth in zip(self.macrocell.x, self.macrocell.y, self.macrocell.azimuth):
- #print("base station #{}".format(i))
+ # print("base station #{}".format(i))
i += 1
# find the center coordinates of the sector (hexagon)
- macro_cell_x = cell_x + self.macrocell.intersite_distance/3*math.cos(math.radians(cell_azimuth))
- macro_cell_y = cell_y + self.macrocell.intersite_distance/3*math.sin(math.radians(cell_azimuth))
+ macro_cell_x = cell_x + self.macrocell.intersite_distance / \
+ 3 * math.cos(math.radians(cell_azimuth))
+ macro_cell_y = cell_y + self.macrocell.intersite_distance / \
+ 3 * math.sin(math.radians(cell_azimuth))
# Hotspots are generated inside an inscribed circle of a regular hexagon (sector).
# The backoff factor (1.0) controls the overlapping rate between hotspots
# coverage areas (overlapping of hotspots in different macro cells)
- r = np.maximum(0, (self.macrocell.intersite_distance/3)*np.sqrt(3)/2 - self.param.max_dist_hotspot_ue/1.0)
+ r = np.maximum(
+ 0, (self.macrocell.intersite_distance / 3) *
+ np.sqrt(3) / 2 - self.param.max_dist_hotspot_ue / 1.0,
+ )
hotspot_x = np.array(0)
hotspot_y = np.array(0)
hotspot_azimuth = np.array(0)
-
+
for hs in range(self.param.num_hotspots_per_cell):
num_attempts = 0
- while(True):
+ while (True):
# create one hotspot
- hotspot_radius = r*random_number_gen.rand(1)
- hotspot_angle = 2*np.pi*random_number_gen.rand(1)
- candidate_x = hotspot_radius*np.cos(hotspot_angle) + macro_cell_x
- candidate_y = hotspot_radius*np.sin(hotspot_angle) + macro_cell_y
- candidate_azimuth = 360*random_number_gen.rand(1)
+ hotspot_radius = r * random_number_gen.rand(1)
+ hotspot_angle = 2 * np.pi * random_number_gen.rand(1)
+ candidate_x = hotspot_radius * \
+ np.cos(hotspot_angle) + macro_cell_x
+ candidate_y = hotspot_radius * \
+ np.sin(hotspot_angle) + macro_cell_y
+ candidate_azimuth = 360 * random_number_gen.rand(1)
if hs == 0:
# the candidate is valid if it is the first to be created
hotspot_x = candidate_x
@@ -85,51 +92,67 @@ def calculate_coordinates(self, random_number_gen=np.random.RandomState()):
hotspot_azimuth = candidate_azimuth
break
else:
- overlapping_hotspots = self.overlapping_hotspots(candidate_x,
- candidate_y,
- candidate_azimuth,
- hotspot_x,
- hotspot_y,
- hotspot_azimuth,
- self.cell_radius)
- min_dist_validated = self.validade_min_dist_bs_hotspot(candidate_x,
- candidate_y,
- self.macrocell.x,
- self.macrocell.y,
- self.param.min_dist_bs_hotspot)
- candidate_valid = (not overlapping_hotspots) and min_dist_validated
+ overlapping_hotspots = self.overlapping_hotspots(
+ candidate_x,
+ candidate_y,
+ candidate_azimuth,
+ hotspot_x,
+ hotspot_y,
+ hotspot_azimuth,
+ self.cell_radius,
+ )
+ min_dist_validated = self.validade_min_dist_bs_hotspot(
+ candidate_x,
+ candidate_y,
+ self.macrocell.x,
+ self.macrocell.y,
+ self.param.min_dist_bs_hotspot,
+ )
+ candidate_valid = (
+ not overlapping_hotspots
+ ) and min_dist_validated
if candidate_valid:
- hotspot_x = np.concatenate((hotspot_x, candidate_x))
- hotspot_y = np.concatenate((hotspot_y, candidate_y))
- hotspot_azimuth = np.concatenate((hotspot_azimuth, candidate_azimuth))
+ hotspot_x = np.concatenate(
+ (hotspot_x, candidate_x),
+ )
+ hotspot_y = np.concatenate(
+ (hotspot_y, candidate_y),
+ )
+ hotspot_azimuth = np.concatenate(
+ (hotspot_azimuth, candidate_azimuth),
+ )
break
else:
num_attempts = num_attempts + 1
-
+
if num_attempts > TopologyHotspot.MAX_NUM_LOOPS:
- sys.stderr.write("ERROR\nInfinite loop while creating hotspots.\nTry less hotspots per cell or greater macro cell intersite distance.\n")
+ sys.stderr.write(
+ "ERROR\nInfinite loop while creating hotspots.\n \
+ Try less hotspots per cell or greater macro cell intersite distance.\n",
+ )
sys.exit(1)
- #if num_attempts > 1: print("number of attempts: {}".format(num_attempts))
+ # if num_attempts > 1: print("number of attempts: {}".format(num_attempts))
x = np.concatenate([x, hotspot_x])
y = np.concatenate([y, hotspot_y])
- azimuth = np.concatenate([azimuth, hotspot_azimuth])
-
+ azimuth = np.concatenate([azimuth, hotspot_azimuth])
+
self.x = x
self.y = y
self.azimuth = azimuth
# In the end, we have to update the number of base stations
self.num_base_stations = len(self.x)
- self.indoor = np.zeros(self.num_base_stations, dtype = bool)
-
-
- def overlapping_hotspots(self,
- candidate_x: np.array,
- candidate_y: np.array,
- candidate_azimuth: np.array,
- set_x: np.array,
- set_y: np.array,
- set_azimuth: np.array,
- radius: float) -> bool:
+ self.indoor = np.zeros(self.num_base_stations, dtype=bool)
+
+ def overlapping_hotspots(
+ self,
+ candidate_x: np.array,
+ candidate_y: np.array,
+ candidate_azimuth: np.array,
+ set_x: np.array,
+ set_y: np.array,
+ set_azimuth: np.array,
+ radius: float,
+ ) -> bool:
"""
Evaluates the spatial relationships among hotspots and checks whether
the hotspot defined by (x, y, azimuth) intersects with any hotspot of
@@ -142,7 +165,7 @@ def overlapping_hotspots(self,
candidate_azimuth: horizontal angle of the candidate hotspot (orientation)
set_x: x-coordinates of the set of hotspots
set_y: y-coordinates of the set of hotspots
- set_azimuth: horizontal angle of the set of hotspots (orientation)
+ set_azimuth: horizontal angle of the set of hotspots (orientation)
radius: radius of all hotspots
Returns
@@ -157,20 +180,24 @@ def overlapping_hotspots(self,
set_points = list()
set_points.append((x, y))
for a in range(len(azimuth_values)):
- set_points.append((x + radius*math.cos(np.radians(azimuth + azimuth_values[a])),
- y + radius*math.sin(np.radians(azimuth + azimuth_values[a]))))
+ set_points.append((
+ x + radius * math.cos(np.radians(azimuth + azimuth_values[a])),
+ y + radius * math.sin(np.radians(azimuth + azimuth_values[a])),
+ ))
set_polygons.append(Polygon(set_points))
# Creating the candidate polygon
points = list()
points.append((candidate_x, candidate_y))
for a in range(len(azimuth_values)):
- points.append((candidate_x + radius*math.cos(np.radians(candidate_azimuth + azimuth_values[a])),
- candidate_y + radius*math.sin(np.radians(candidate_azimuth + azimuth_values[a]))))
+ points.append((
+ candidate_x + radius * math.cos(np.radians(candidate_azimuth + azimuth_values[a])),
+ candidate_y + radius * math.sin(np.radians(candidate_azimuth + azimuth_values[a])),
+ ))
polygon = Polygon(points)
-
- # Check if there is overlapping between the candidate hotspot and
- # any of the hotspots of the set. In other words, check if any polygons
+
+ # Check if there is overlapping between the candidate hotspot and
+ # any of the hotspots of the set. In other words, check if any polygons
# intersect
for p in range(len(set_polygons)):
overlapping = polygon.intersects(set_polygons[p])
@@ -182,13 +209,14 @@ def overlapping_hotspots(self,
# If this point is reached, then there is no intersection between polygons
return False
-
- def validade_min_dist_bs_hotspot(self,
- hotspot_x: np.array,
- hotspot_y: np.array,
- macrocell_x: np.array,
- macrocell_y: np.array,
- min_dist_bs_hotspot: float) -> bool:
+ def validade_min_dist_bs_hotspot(
+ self,
+ hotspot_x: np.array,
+ hotspot_y: np.array,
+ macrocell_x: np.array,
+ macrocell_y: np.array,
+ min_dist_bs_hotspot: float,
+ ) -> bool:
"""
Checks minimum 2D distance between macro cell base stations and
hotspots.
@@ -202,30 +230,35 @@ def validade_min_dist_bs_hotspot(self,
# Here we have a 2D matrix whose values indicates the distance between
# base station and hotspots. In this matrix, each line corresponds to
# a macro cell base station and each column corresponds to a hotspot
- distance = np.sqrt((hotspot_x - macrocell_x.reshape((-1, 1)))**2 +
- (hotspot_y - macrocell_y.reshape((-1, 1)))**2)
+ distance = np.sqrt(
+ (hotspot_x - macrocell_x.reshape((-1, 1)))**2 +
+ (hotspot_y - macrocell_y.reshape((-1, 1)))**2,
+ )
# count the number of values that are less than the minimum distance and
# return true if any value is equal os less than minimum 2D distance
# between macro cell base stations and hotspot centers
occ = np.where(distance < min_dist_bs_hotspot)[0]
return len(occ) == 0
-
def plot(self, ax: matplotlib.axes.Axes):
# plot macrocells
self.macrocell.plot(ax)
# plot hotspots
- plt.scatter(self.x, self.y, color='g', edgecolor="w", linewidth=0.5, label="Hotspot")
+ plt.scatter(
+ self.x, self.y, color='g', edgecolor="w",
+ linewidth=0.5, label="Hotspot",
+ )
# plot hotspots coverage area
for x, y, a in zip(self.x, self.y, self.azimuth):
- pa = patches.Wedge( (x, y), self.cell_radius, a-60, a+60, fill=False,
- edgecolor="green", linestyle='solid' )
+ pa = patches.Wedge(
+ (x, y), self.cell_radius, a - 60, a + 60, fill=False,
+ edgecolor="green", linestyle='solid',
+ )
ax.add_patch(pa)
-
if __name__ == '__main__':
param = ParametersHotspot()
param.num_hotspots_per_cell = 2
@@ -239,7 +272,10 @@ def plot(self, ax: matplotlib.axes.Axes):
topology = TopologyHotspot(param, intersite_distance, num_clusters)
topology.calculate_coordinates()
- fig = plt.figure(figsize=(8,8), facecolor='w', edgecolor='k') # create a figure object
+ fig = plt.figure(
+ figsize=(8, 8), facecolor='w',
+ edgecolor='k',
+ ) # create a figure object
ax = fig.add_subplot(1, 1, 1) # create an axes object in the figure
topology.plot(ax)
diff --git a/sharc/topology/topology_indoor.py b/sharc/topology/topology_indoor.py
index 5b804f441..7465ca8eb 100644
--- a/sharc/topology/topology_indoor.py
+++ b/sharc/topology/topology_indoor.py
@@ -6,24 +6,24 @@
"""
from sharc.topology.topology import Topology
-from sharc.parameters.parameters_indoor import ParametersIndoor
+from sharc.parameters.imt.parameters_indoor import ParametersIndoor
import matplotlib.pyplot as plt
import matplotlib.axes
import numpy as np
from itertools import product
+
class TopologyIndoor(Topology):
"""
Generates the coordinates of the sites based on the indoor network
- topology.
+ topology.
"""
-
def __init__(self, param: ParametersIndoor):
"""
Constructor method that sets the parameters.
-
+
Parameters
----------
param : parameters of the indoor topology
@@ -34,10 +34,10 @@ def __init__(self, param: ParametersIndoor):
self.b_w = 120
self.b_d = 50
self.b_h = 3
-
- cell_radius = param.intersite_distance/2
+
+ cell_radius = param.intersite_distance / 2
super().__init__(param.intersite_distance, cell_radius)
-
+
self.n_rows = param.n_rows
self.n_colums = param.n_colums
self.street_width = param.street_width
@@ -47,55 +47,64 @@ def __init__(self, param: ParametersIndoor):
self.num_floors = param.num_floors
if param.num_imt_buildings == 'ALL':
self.all_buildings = True
- self.num_imt_buildings = self.n_rows*self.n_colums
+ self.num_imt_buildings = self.n_rows * self.n_colums
else:
self.all_buildings = False
self.num_imt_buildings = int(param.num_imt_buildings)
self.imt_buildings = list()
- self.total_bs_level = self.num_imt_buildings*self.num_cells
-
+ self.total_bs_level = self.num_imt_buildings * self.num_cells
+
self.height = np.empty(0)
-
-
+
def calculate_coordinates(self, random_number_gen=np.random.RandomState()):
"""
Calculates the coordinates of the stations according to the inter-site
- distance parameter. This method is invoked in all snapshots but it can
- be called only once for the indoor topology. So we set
+ distance parameter. This method is invoked in all snapshots but it can
+ be called only once for the indoor topology. So we set
static_base_stations to True to avoid unnecessary calculations.
"""
if not self.static_base_stations:
self.reset()
self.static_base_stations = self.all_buildings
-
- x_base = np.array([ (2*k + 1)*self.cell_radius for k in range(self.num_cells)])
- y_base = self.b_d/2*np.ones(self.num_cells)
-
+
+ x_base = np.array(
+ [(2 * k + 1) * self.cell_radius for k in range(self.num_cells)],
+ )
+ y_base = self.b_d / 2 * np.ones(self.num_cells)
+
# Choose random buildings
- all_buildings = list(product(range(self.n_rows),range(self.n_colums)))
+ all_buildings = list(
+ product(range(self.n_rows), range(self.n_colums)),
+ )
random_number_gen.shuffle(all_buildings)
self.imt_buildings = all_buildings[:self.num_imt_buildings]
-
+
floor_x = np.empty(0)
floor_y = np.empty(0)
for build in self.imt_buildings:
r = build[0]
c = build[1]
- floor_x = np.concatenate((floor_x, x_base + c*(self.b_w + self.street_width)))
- floor_y = np.concatenate((floor_y, y_base + r*(self.b_d + self.street_width)))
+ floor_x = np.concatenate(
+ (floor_x, x_base + c * (self.b_w + self.street_width)),
+ )
+ floor_y = np.concatenate(
+ (floor_y, y_base + r * (self.b_d + self.street_width)),
+ )
for f in range(self.num_floors):
self.x = np.concatenate((self.x, floor_x))
self.y = np.concatenate((self.y, floor_y))
- self.height = np.concatenate((self.height,
- (f+1)*self.b_h*np.ones_like(floor_x)))
+ self.height = np.concatenate((
+ self.height,
+ (f + 1) * self.b_h * np.ones_like(floor_x),
+ ))
# In the end, we have to update the number of base stations
- self.num_base_stations = len(self.x)
+ self.num_base_stations = len(self.x)
self.azimuth = np.zeros(self.num_base_stations)
- self.indoor = np.ones(self.num_base_stations, dtype = bool)
-
+ self.indoor = np.ones(self.num_base_stations, dtype=bool)
+
def reset(self):
self.x = np.empty(0)
self.y = np.empty(0)
@@ -104,67 +113,84 @@ def reset(self):
self.indoor = np.empty(0)
self.num_base_stations = -1
self.static_base_stations = False
-
- def plot(self, ax: matplotlib.axes.Axes, top_view = True):
+
+ def plot(self, ax: matplotlib.axes.Axes, top_view=True):
if top_view:
self.plot_top_view(ax)
else:
self.plot_side_view(ax)
-
+
def plot_top_view(self, ax: matplotlib.axes.Axes):
# create the building
- for b in range(int(self.num_base_stations/self.num_cells)):
- x_b = self.x[self.num_cells*b] - self.cell_radius
- y_b = self.y[self.num_cells*b] - self.b_d/2
- points = list([[x_b, y_b],
- [x_b + self.b_w, y_b],
- [x_b + self.b_w, y_b + self.b_d],
- [x_b, y_b + + self.b_d]])
+ for b in range(int(self.num_base_stations / self.num_cells)):
+ x_b = self.x[self.num_cells * b] - self.cell_radius
+ y_b = self.y[self.num_cells * b] - self.b_d / 2
+ points = list([
+ [x_b, y_b],
+ [x_b + self.b_w, y_b],
+ [x_b + self.b_w, y_b + self.b_d],
+ [x_b, y_b + + self.b_d],
+ ])
sector = plt.Polygon(points, fill=None, edgecolor='k')
- ax.add_patch(sector)
+ ax.add_patch(sector)
for q in range(8):
points = list()
- x_b = self.x[self.num_cells*b] - self.cell_radius + q*15
- y_b = self.y[self.num_cells*b] + 10
- points.extend([[x_b, y_b],
- [x_b + 15, y_b],
- [x_b + 15, y_b + 15],
- [x_b, y_b + 15]])
+ x_b = self.x[self.num_cells * b] - self.cell_radius + q * 15
+ y_b = self.y[self.num_cells * b] + 10
+ points.extend([
+ [x_b, y_b],
+ [x_b + 15, y_b],
+ [x_b + 15, y_b + 15],
+ [x_b, y_b + 15],
+ ])
sector = plt.Polygon(points, fill=None, edgecolor='k')
ax.add_patch(sector)
-
+
for q in range(8):
points = list()
- x_b = self.x[self.num_cells*b] - self.cell_radius + q*15
- y_b = self.y[self.num_cells*b] - self.b_d/2
- points.extend([[x_b, y_b],
- [x_b + 15, y_b],
- [x_b + 15, y_b + 15],
- [x_b, y_b + 15]])
+ x_b = self.x[self.num_cells * b] - self.cell_radius + q * 15
+ y_b = self.y[self.num_cells * b] - self.b_d / 2
+ points.extend([
+ [x_b, y_b],
+ [x_b + 15, y_b],
+ [x_b + 15, y_b + 15],
+ [x_b, y_b + 15],
+ ])
sector = plt.Polygon(points, fill=None, edgecolor='k')
- ax.add_patch(sector)
-
-
+ ax.add_patch(sector)
+
# indoor base stations
- ax.scatter(self.x, self.y, color='k', edgecolor="k", linewidth=2, label="Base station")
-
+ ax.scatter(
+ self.x, self.y, color='k', edgecolor="k",
+ linewidth=2, label="Base station",
+ )
+
def plot_side_view(self, ax: matplotlib.axes.Axes):
-
+
# Loop on each floor of each column of buildings
for f in range(int(self.num_floors)):
for build in self.imt_buildings:
c = build[1]
- x_b = self.x[f*self.total_bs_level + c*self.num_cells] - self.cell_radius
- z_b = self.height[f*self.total_bs_level + c*self.num_cells]
- points = list([[x_b, z_b],
- [x_b + self.b_w, z_b],
- [x_b + self.b_w, z_b - self.b_h],
- [x_b, z_b - self.b_h]])
+ x_b = self.x[
+ f * self.total_bs_level +
+ c * self.num_cells
+ ] - self.cell_radius
+ z_b = self.height[f * self.total_bs_level + c * self.num_cells]
+ points = list([
+ [x_b, z_b],
+ [x_b + self.b_w, z_b],
+ [x_b + self.b_w, z_b - self.b_h],
+ [x_b, z_b - self.b_h],
+ ])
sector = plt.Polygon(points, fill=None, edgecolor='k')
- ax.add_patch(sector)
-
- ax.scatter(self.x, self.height-0.05, color='k', edgecolor="k", linewidth=2, label="Base station")
+ ax.add_patch(sector)
+
+ ax.scatter(
+ self.x, self.height - 0.05, color='k',
+ edgecolor="k", linewidth=2, label="Base station",
+ )
+
if __name__ == '__main__':
param = ParametersIndoor()
@@ -180,36 +206,44 @@ def plot_side_view(self, ax: matplotlib.axes.Axes):
param.building_class = "TRADITIONAL"
topology = TopologyIndoor(param)
topology.calculate_coordinates()
-
+
# Plot top view
- fig = plt.figure(figsize=(10,8), facecolor='w', edgecolor='k') # create a figure object
+ fig = plt.figure(
+ figsize=(10, 8), facecolor='w',
+ edgecolor='k',
+ ) # create a figure object
ax = fig.add_subplot(1, 1, 1) # create an axes object in the figure
-
+
topology.plot(ax)
-
- plt.axis('image')
+
+ plt.axis('image')
plt.title("Indoor topology")
plt.xlabel("x-coordinate [m]")
plt.ylabel("y-coordinate [m]")
- plt.tight_layout()
-
+ plt.tight_layout()
+
axes = plt.gca()
-# axes.set_xlim([-param.street_width, param.n_colums*3*param.intersite_distance + (param.n_colums-1)*param.street_width + param.street_width])
-# axes.set_ylim([-param.street_width, param.n_rows*topology.b_d + (param.n_rows-1)*param.street_width + param.street_width])
-
- plt.show()
-
+# axes.set_xlim([-param.street_width, param.n_colums*3*param.intersite_distance + \
+# (param.n_colums-1)*param.street_width + param.street_width])
+# axes.set_ylim([-param.street_width, param.n_rows*topology.b_d + \
+# (param.n_rows-1)*param.street_width + param.street_width])
+
+ plt.show()
+
# Plot side view
- fig = plt.figure(figsize=(10,8), facecolor='w', edgecolor='k') # create a figure object
+ fig = plt.figure(
+ figsize=(10, 8), facecolor='w',
+ edgecolor='k',
+ ) # create a figure object
ax = fig.add_subplot(1, 1, 1) # create an axes object in the figure
-
- topology.plot(ax,top_view=False)
-
+
+ topology.plot(ax, top_view=False)
+
plt.title("Indoor topology")
plt.xlabel("x-coordinate [m]")
- plt.ylabel("z-coordinate [m]")
+ plt.ylabel("z-coordinate [m]")
plt.tight_layout()
-
+
axes = plt.gca()
- axes.set_ylim((0,3*param.num_floors + 1))
- plt.show()
\ No newline at end of file
+ axes.set_ylim((0, 3 * param.num_floors + 1))
+ plt.show()
diff --git a/sharc/topology/topology_macrocell.py b/sharc/topology/topology_macrocell.py
index 59466312c..7764785f2 100644
--- a/sharc/topology/topology_macrocell.py
+++ b/sharc/topology/topology_macrocell.py
@@ -12,6 +12,7 @@
import math
import numpy as np
+
class TopologyMacrocell(Topology):
"""
Generates the coordinates of the sites based on the macrocell network
@@ -34,10 +35,12 @@ def __init__(self, intersite_distance: float, num_clusters: int):
num_clusters : Number of clusters, should be 1 or 7
"""
if num_clusters not in TopologyMacrocell.ALLOWED_NUM_CLUSTERS:
- error_message = "invalid number of clusters ({})".format(num_clusters)
+ error_message = "invalid number of clusters ({})".format(
+ num_clusters,
+ )
raise ValueError(error_message)
- cell_radius = intersite_distance*2/3
+ cell_radius = intersite_distance * 2 / 3
super().__init__(intersite_distance, cell_radius)
self.num_clusters = num_clusters
@@ -55,49 +58,63 @@ def calculate_coordinates(self, random_number_gen=np.random.RandomState()):
self.static_base_stations = True
d = self.intersite_distance
- h = (d/3)*math.sqrt(3)/2
+ h = (d / 3) * math.sqrt(3) / 2
# these are the coordinates of the central cluster
- x_central = np.array([0, d, d/2, -d/2, -d, -d/2,
- d/2, 2*d, 3*d/2, d, 0, -d,
- -3*d/2, -2*d, -3*d/2, -d, 0, d, 3*d/2])
- y_central = np.array([0, 0, 3*h, 3*h, 0, -3*h,
- -3*h, 0, 3*h, 6*h, 6*h, 6*h,
- 3*h, 0, -3*h, -6*h, -6*h, -6*h, -3*h])
+ x_central = np.array([
+ 0, d, d / 2, -d / 2, -d, -d / 2,
+ d / 2, 2 * d, 3 * d / 2, d, 0, -d,
+ -3 * d / 2, -2 * d, -3 * d / 2, -d, 0, d, 3 * d / 2,
+ ])
+ y_central = np.array([
+ 0, 0, 3 * h, 3 * h, 0, -3 * h,
+ -3 * h, 0, 3 * h, 6 * h, 6 * h, 6 * h,
+ 3 * h, 0, -3 * h, -6 * h, -6 * h, -6 * h, -3 * h,
+ ])
self.x = np.copy(x_central)
self.y = np.copy(y_central)
# other clusters are calculated by shifting the central cluster
if self.num_clusters == 7:
- x_shift = np.array([7*d/2, -d/2, -4*d, -7*d/2, d/2, 4*d])
- y_shift = np.array([9*h, 15*h, 6*h, -9*h, -15*h, -6*h])
+ x_shift = np.array(
+ [7 * d / 2, -d / 2, -4 * d, -7 * d / 2, d / 2, 4 * d],
+ )
+ y_shift = np.array(
+ [9 * h, 15 * h, 6 * h, -9 * h, -15 * h, -6 * h],
+ )
for xs, ys in zip(x_shift, y_shift):
self.x = np.concatenate((self.x, x_central + xs))
self.y = np.concatenate((self.y, y_central + ys))
self.x = np.repeat(self.x, 3)
self.y = np.repeat(self.y, 3)
- self.azimuth = np.tile(self.AZIMUTH, 19*self.num_clusters)
+ self.azimuth = np.tile(self.AZIMUTH, 19 * self.num_clusters)
# In the end, we have to update the number of base stations
self.num_base_stations = len(self.x)
- self.indoor = np.zeros(self.num_base_stations, dtype = bool)
+ self.indoor = np.zeros(self.num_base_stations, dtype=bool)
def plot(self, ax: matplotlib.axes.Axes):
# create the hexagons
- r = self.intersite_distance/3
+ r = self.intersite_distance / 3
for x, y, az in zip(self.x, self.y, self.azimuth):
- se = list([[x,y]])
+ se = list([[x, y]])
angle = int(az - 60)
for a in range(6):
- se.extend([[se[-1][0] + r*math.cos(math.radians(angle)), se[-1][1] + r*math.sin(math.radians(angle))]])
+ se.extend([[
+ se[-1][0] + r * math.cos(math.radians(angle)),
+ se[-1][1] + r * math.sin(math.radians(angle)),
+ ]])
angle += 60
sector = plt.Polygon(se, fill=None, edgecolor='k')
ax.add_patch(sector)
# macro cell base stations
- ax.scatter(self.x, self.y, color='k', edgecolor="k", linewidth=4, label="Macro cell")
+ ax.scatter(
+ self.x, self.y, color='k', edgecolor="k",
+ linewidth=4, label="Macro cell",
+ )
if __name__ == '__main__':
@@ -106,7 +123,10 @@ def plot(self, ax: matplotlib.axes.Axes):
topology = TopologyMacrocell(intersite_distance, num_clusters)
topology.calculate_coordinates()
- fig = plt.figure(figsize=(8,8), facecolor='w', edgecolor='k') # create a figure object
+ fig = plt.figure(
+ figsize=(8, 8), facecolor='w',
+ edgecolor='k',
+ ) # create a figure object
ax = fig.add_subplot(1, 1, 1) # create an axes object in the figure
topology.plot(ax)
@@ -117,5 +137,3 @@ def plot(self, ax: matplotlib.axes.Axes):
plt.ylabel("y-coordinate [m]")
plt.tight_layout()
plt.show()
-
-
diff --git a/sharc/topology/topology_ntn.py b/sharc/topology/topology_ntn.py
new file mode 100644
index 000000000..0896d9dbc
--- /dev/null
+++ b/sharc/topology/topology_ntn.py
@@ -0,0 +1,300 @@
+from sharc.topology.topology import Topology
+import numpy as np
+import math
+import matplotlib.pyplot as plt
+import matplotlib.axes
+import geopandas as gpd
+from shapely.geometry import Polygon, MultiPolygon
+
+
+class TopologyNTN(Topology):
+ """
+ Class to generate and manage the topology of Non-Terrestrial Network (NTN) sites
+ based on a specified macrocell network topology.
+ """
+
+ ALLOWED_NUM_SECTORS = [1, 7, 19]
+
+ def __init__(
+ self, intersite_distance: float, cell_radius: int, bs_height: float, bs_azimuth: float,
+ bs_elevation: float, num_sectors=7,
+ ):
+ """
+ Initializes the NTN topology with specific network settings.
+
+ Parameters:
+ intersite_distance: Distance between adjacent sites in meters.
+ cell_radius: Radius of the coverage area for each site in meters.
+ bs_height: Height of the base station (satellite) from the x-y plane.
+ bs_azimuth: Azimuth angle of the base station in degrees.
+ bs_elevation: Elevation angle of the base station in degrees.
+ num_sectors: Number of sectors for the topology (default is 7).
+ """
+
+ if num_sectors not in self.ALLOWED_NUM_SECTORS:
+ raise ValueError(
+ f"Invalid number of sectors: {num_sectors}. Allowed values are {self.ALLOWED_NUM_SECTORS}.",
+ )
+
+ # Call to the superclass constructor to set common properties
+ super().__init__(intersite_distance, cell_radius)
+ self.is_space_station = True
+ self.space_station_x = None
+ self.space_station_y = None
+ self.space_station_z = None
+ self.bs_azimuth = np.radians(bs_azimuth)
+ self.bs_elevation = np.radians(bs_elevation)
+ self.bs_radius = bs_height / np.sin(self.bs_elevation)
+ self.num_sectors = num_sectors
+
+ # Calculate the base station coordinates
+
+ self.space_station_x = self.bs_radius * \
+ np.cos(self.bs_elevation) * np.cos(self.bs_azimuth)
+ self.space_station_y = self.bs_radius * \
+ np.cos(self.bs_elevation) * np.sin(self.bs_azimuth)
+ self.space_station_z = bs_height
+
+ self.calculate_coordinates()
+
+ def calculate_coordinates(self, random_number_gen=np.random.RandomState()):
+ """
+ Computes the coordinates of each site. This is where the actual layout calculation would be implemented.
+ """
+
+ d = self.intersite_distance
+
+ self.x = [0]
+ self.y = [0]
+
+ # First ring (6 points)
+ if self.num_sectors == 7 or self.num_sectors == 19:
+
+ for k in range(6):
+ angle = k * 60
+ self.x.append(d * np.cos(np.radians(angle)))
+ self.y.append(d * np.sin(np.radians(angle)))
+
+ if self.num_sectors == 19:
+ # Coordinates with 19 sectors
+ # Second ring (12 points)
+ for k in range(6):
+ angle = k * 60
+ self.x.append(2 * d * np.cos(np.radians(angle)))
+ self.y.append(2 * d * np.sin(np.radians(angle)))
+ self.x.append(
+ d * np.cos(np.radians(angle)) +
+ d * np.cos(np.radians(angle + 60)),
+ )
+ self.y.append(
+ d * np.sin(np.radians(angle)) +
+ d * np.sin(np.radians(angle + 60)),
+ )
+
+ self.x = np.array(self.x)
+ self.y = np.array(self.y)
+
+ # Assuming all points are at ground level
+ self.z = np.zeros(len(self.x))
+
+ # Rotate the anchor points by 30 degrees
+ theta = np.radians(30)
+ cos_theta = np.cos(theta)
+ sin_theta = np.sin(theta)
+ self.x_rotated = self.x * cos_theta - self.y * sin_theta
+ self.y_rotated = self.x * sin_theta + self.y * cos_theta
+
+ # Calculate azimuth and elevation for each point
+ self.azimuth = np.arctan2(
+ self.y_rotated - self.space_station_y,
+ self.x_rotated - self.space_station_x,
+ ) * 180 / np.pi
+ distance_xy = np.sqrt(
+ (self.x_rotated - self.space_station_x) **
+ 2 + (self.y_rotated - self.space_station_y)**2,
+ )
+ self.elevation = np.arctan2(
+ self.z - self.space_station_z, distance_xy,
+ ) * 180 / np.pi
+
+ # Update the number of base stations after setup
+ self.num_base_stations = len(self.x)
+ self.indoor = np.zeros(self.num_base_stations, dtype=bool)
+
+ self.x = self.x_rotated
+ self.y = self.y_rotated
+
+ def plot(self, axis: matplotlib.axes.Axes):
+ r = self.cell_radius / 1000 # Convert to kilometers
+
+ # Plot each sector
+ for x, y in zip(self.x / 1000, self.y / 1000): # Convert to kilometers
+ hexagon = []
+ for a in range(6):
+ angle_rad = math.radians(a * 60)
+ hexagon.append([
+ x + r * math.cos(angle_rad),
+ y + r * math.sin(angle_rad),
+ ])
+ hexagon.append(hexagon[0]) # Close the hexagon
+ hexagon = np.array(hexagon)
+
+ sector = plt.Polygon(hexagon, fill=None, edgecolor='k')
+ axis.add_patch(sector)
+
+ # Plot base stations
+ axis.scatter(
+ self.x / 1000, self.y / 1000, s=200, marker='v', c='k', edgecolor='k', linewidth=1, alpha=1,
+ label="Anchor Points",
+ )
+
+ # Add labels and title
+ axis.set_xlabel("x-coordinate [km]")
+ axis.set_ylabel("y-coordinate [km]")
+ axis.set_title(f"NTN Topology - {self.num_sectors} Sectors")
+ axis.legend()
+ plt.tight_layout()
+
+ def plot_3d(self, axis: matplotlib.axes.Axes, map=False):
+ r = self.cell_radius / 1000 # Convert to kilometers
+
+ if map:
+ # Load the map of Brazil using GeoPandas
+ brazil = gpd.read_file(
+ "${workspaceFolder}\\sharc\\topology\\countries\\ne_110m_admin_0_countries.shp",
+ )
+ brazil = brazil[brazil['NAME'] == "Brazil"]
+
+ # Coordinates of the Federal District (Brasรญlia)
+ federal_district_coords = (-47.9292, -15.7801)
+
+ # Approximate conversion factors (1 degree latitude = 111 km, 1 degree longitude = 111 km)
+ lat_to_km = 111
+ lon_to_km = 111
+
+ # Convert Federal District coordinates to kilometers
+ federal_district_coords_km = (
+ federal_district_coords[0] * lon_to_km, federal_district_coords[1] * lat_to_km,
+ )
+
+ # Calculate the shift required to move the Federal District to (0, 0)
+ x_shift = federal_district_coords_km[0]
+ y_shift = federal_district_coords_km[1]
+
+ # Manually plot the map of Brazil on the xy-plane
+ for geom in brazil.geometry:
+ if isinstance(geom, Polygon):
+ lon, lat = geom.exterior.xy
+ x = np.array(lon) * lon_to_km - x_shift
+ y = np.array(lat) * lat_to_km - y_shift
+ axis.plot(x, y, zs=0, zdir='z', color='lightgray')
+ elif isinstance(geom, MultiPolygon):
+ for poly in geom:
+ lon, lat = poly.exterior.xy
+ x = np.array(lon) * lon_to_km - x_shift
+ y = np.array(lat) * lat_to_km - y_shift
+ axis.plot(x, y, zs=0, zdir='z', color='lightgray')
+
+ # Add the Federal District location to the plot
+ axis.scatter(0, 0, 0, color='red', zorder=5)
+ axis.text(0, 0, 0, 'Federal District', fontsize=12, ha='right')
+
+ # Plot each sector
+ for x, y in zip(self.x / 1000, self.y / 1000): # Convert to kilometers
+ hexagon = []
+ for a in range(6):
+ angle_rad = math.radians(a * 60)
+ hexagon.append([
+ x + r * math.cos(angle_rad),
+ y + r * math.sin(angle_rad),
+ ])
+ hexagon.append(hexagon[0]) # Close the hexagon
+ hexagon = np.array(hexagon)
+
+ # 3D hexagon
+ axis.plot(
+ hexagon[:, 0], hexagon[:, 1],
+ np.zeros_like(hexagon[:, 0]), 'k-',
+ )
+
+ # Plot base stations
+ axis.scatter(
+ self.x / 1000, self.y / 1000, np.zeros_like(self.x), s=75, marker='v', c='k', edgecolor='k',
+ linewidth=1, alpha=1,
+ label="Anchor Points",
+ )
+
+ # Plot the satellite
+ axis.scatter(
+ self.space_station_x / 1000, self.space_station_y / 1000, self.space_station_z / 1000, s=75, c='r',
+ marker='^', edgecolor='k', linewidth=1, alpha=1,
+ label=f"Satellite (ฯ={np.degrees(self.bs_azimuth):.1f}ยฐ, ฮธ={np.degrees(self.bs_elevation):.1f}ยฐ)",
+ )
+
+ # Plot the height line
+ axis.plot(
+ [self.space_station_x / 1000, self.space_station_x / 1000],
+ [self.space_station_y / 1000, self.space_station_y / 1000],
+ [0, self.space_station_z / 1000], 'b-', label=f'Height = {self.space_station_z / 1000:.1f} km',
+ )
+
+ # Plot the slant range line
+ axis.plot(
+ [0, self.space_station_x / 1000],
+ [0, self.space_station_y / 1000],
+ [0, self.space_station_z / 1000], 'g--', label=f'Slant range = {self.bs_radius / 1000:.1f} km',
+ )
+
+ # Add labels and title
+ axis.set_xlabel("x-coordinate [km]")
+ axis.set_ylabel("y-coordinate [km]")
+ axis.set_zlabel("z-coordinate [km]")
+ axis.set_title(f"NTN Topology - {self.num_sectors} Sectors")
+ axis.legend()
+ plt.tight_layout()
+
+
+# Example usage
+if __name__ == '__main__':
+
+ bs_height = 1000e3 # meters
+ bs_azimuth = 45 # degrees
+ bs_elevation = 45 # degrees
+ beamwidth = 10
+ cell_radius = bs_height * \
+ math.tan(np.radians(beamwidth)) / math.cos(bs_elevation)
+ intersite_distance = cell_radius * np.sqrt(3) # meters
+ map = False
+
+ # Test for 1 sector
+ ntn_topology_1 = TopologyNTN(
+ intersite_distance, cell_radius, bs_height, bs_azimuth, bs_elevation, num_sectors=1,
+ )
+ ntn_topology_1.calculate_coordinates() # Calculate the site coordinates
+
+ fig = plt.figure()
+ ax = fig.add_subplot(111, projection='3d')
+ ntn_topology_1.plot_3d(ax, map) # Plot the 3D topology
+ plt.show()
+
+ # Test for 7 sectors
+ ntn_topology_7 = TopologyNTN(
+ intersite_distance, cell_radius, bs_height, bs_azimuth, bs_elevation, num_sectors=7,
+ )
+ ntn_topology_7.calculate_coordinates() # Calculate the site coordinates
+
+ fig = plt.figure()
+ ax = fig.add_subplot(111, projection='3d')
+ ntn_topology_7.plot_3d(ax, map) # Plot the 3D topology
+ plt.show()
+
+ # Test for 19 sectors
+ ntn_topology_19 = TopologyNTN(
+ intersite_distance, cell_radius, bs_height, bs_azimuth, bs_elevation, num_sectors=19,
+ )
+ ntn_topology_19.calculate_coordinates() # Calculate the site coordinates
+
+ fig = plt.figure()
+ ax = fig.add_subplot(111, projection='3d')
+ ntn_topology_19.plot_3d(ax, map) # Plot the 3D topology
+ plt.show()
diff --git a/sharc/topology/topology_single_base_station.py b/sharc/topology/topology_single_base_station.py
index 8fd3b932c..f19cfe944 100644
--- a/sharc/topology/topology_single_base_station.py
+++ b/sharc/topology/topology_single_base_station.py
@@ -11,6 +11,7 @@
from sharc.topology.topology import Topology
+
class TopologySingleBaseStation(Topology):
"""
Generates the a single base station centered at (0,0), with azimuth = 0ยฐ
@@ -21,7 +22,6 @@ class TopologySingleBaseStation(Topology):
AZIMUTH = [0, 180]
ALLOWED_NUM_CLUSTERS = [1, 2]
-
def __init__(self, cell_radius: float, num_clusters: int):
"""
Constructor method that sets the object attributes
@@ -31,10 +31,12 @@ def __init__(self, cell_radius: float, num_clusters: int):
cell_radius : radius of the cell
"""
if num_clusters not in TopologySingleBaseStation.ALLOWED_NUM_CLUSTERS:
- error_message = "invalid number of clusters ({})".format(num_clusters)
+ error_message = "invalid number of clusters ({})".format(
+ num_clusters,
+ )
raise ValueError(error_message)
- intersite_distance = 2*cell_radius
+ intersite_distance = 2 * cell_radius
super().__init__(intersite_distance, cell_radius)
self.num_clusters = num_clusters
@@ -47,24 +49,30 @@ def calculate_coordinates(self, random_number_gen=np.random.RandomState()):
if self.num_clusters == 1:
self.x = np.array([0])
self.y = np.array([0])
- self.azimuth = TopologySingleBaseStation.AZIMUTH[0]*np.ones(1)
+ self.azimuth = TopologySingleBaseStation.AZIMUTH[0] * np.ones(
+ 1,
+ )
self.num_base_stations = 1
elif self.num_clusters == 2:
self.x = np.array([0, self.intersite_distance])
self.y = np.array([0, 0])
self.azimuth = np.array(TopologySingleBaseStation.AZIMUTH)
self.num_base_stations = 2
- self.indoor = np.zeros(self.num_base_stations, dtype = bool)
-
+ self.indoor = np.zeros(self.num_base_stations, dtype=bool)
def plot(self, ax: matplotlib.axes.Axes):
# plot base station
- plt.scatter(self.x, self.y, color='g', edgecolor="w", linewidth=0.5, label="Hotspot")
+ plt.scatter(
+ self.x, self.y, color='g', edgecolor="w",
+ linewidth=0.5, label="Hotspot",
+ )
# plot base station coverage area
for x, y, a in zip(self.x, self.y, self.azimuth):
- pa = patches.Wedge( (x, y), self.cell_radius, a-60, a+60, fill=False,
- edgecolor="green", linestyle='solid' )
+ pa = patches.Wedge(
+ (x, y), self.cell_radius, a - 60, a + 60, fill=False,
+ edgecolor="green", linestyle='solid',
+ )
ax.add_patch(pa)
@@ -74,7 +82,10 @@ def plot(self, ax: matplotlib.axes.Axes):
topology = TopologySingleBaseStation(cell_radius, num_clusters)
topology.calculate_coordinates()
- fig = plt.figure(figsize=(8,8), facecolor='w', edgecolor='k') # create a figure object
+ fig = plt.figure(
+ figsize=(8, 8), facecolor='w',
+ edgecolor='k',
+ ) # create a figure object
ax = fig.add_subplot(1, 1, 1) # create an axes object in the figure
topology.plot(ax)
@@ -85,4 +96,3 @@ def plot(self, ax: matplotlib.axes.Axes):
plt.ylabel("y-coordinate [m]")
plt.tight_layout()
plt.show()
-
diff --git a/tests/_test_beamforming_normalizer.py b/tests/_test_beamforming_normalizer.py
index dbe3db662..beae7061c 100644
--- a/tests/_test_beamforming_normalizer.py
+++ b/tests/_test_beamforming_normalizer.py
@@ -14,13 +14,14 @@
from sharc.support.named_tuples import AntennaPar
from sharc.antenna.antenna_beamforming_imt import AntennaBeamformingImt
+
class BeamformingNormalizerTest(unittest.TestCase):
-
+
def setUp(self):
# Test 1
resolution = 30
tolerance = 1e-2
- self.norm_1 = BeamformingNormalizer(resolution,tolerance)
+ self.norm_1 = BeamformingNormalizer(resolution, tolerance)
adjacent_antenna_model = "SINGLE_ELEMENT"
norm = False
norm_file = None
@@ -53,11 +54,11 @@ def setUp(self):
multiplication_factor,
minimum_array_gain,
downtilt)
-
+
# Test 2: UE configuration
resolution = 5
tolerance = 1e-2
- self.norm_2 = BeamformingNormalizer(resolution,tolerance)
+ self.norm_2 = BeamformingNormalizer(resolution, tolerance)
adjacent_antenna_model = "SINGLE_ELEMENT"
norm = False
norm_file = None
@@ -90,11 +91,11 @@ def setUp(self):
multiplication_factor,
minimum_array_gain,
downtilt)
-
+
# Test 3: BS configuration
resolution = 180
tolerance = 5e-2
- self.norm_3 = BeamformingNormalizer(resolution,tolerance)
+ self.norm_3 = BeamformingNormalizer(resolution, tolerance)
adjacent_antenna_model = "SINGLE_ELEMENT"
norm = False
norm_file = None
@@ -127,78 +128,79 @@ def setUp(self):
multiplication_factor,
minimum_array_gain,
downtilt)
-
+
def test_construction(self):
# Test 1
- self.assertEqual(self.norm_1.resolution_deg,30)
- self.assertEqual(self.norm_1.phi_min_deg,-180)
- self.assertEqual(self.norm_1.phi_max_deg,180)
- self.assertEqual(self.norm_1.theta_min_deg,0)
- self.assertEqual(self.norm_1.theta_max_deg,180)
- self.assertEqual(self.norm_1.phi_min_rad,-np.pi)
- self.assertEqual(self.norm_1.phi_max_rad,np.pi)
- self.assertEqual(self.norm_1.theta_min_rad,0)
- self.assertEqual(self.norm_1.theta_max_rad,np.pi)
- npt.assert_equal(self.norm_1.phi_vals_deg,np.arange(-180,180,30))
- npt.assert_equal(self.norm_1.theta_vals_deg,np.arange(0,180,30))
-
+ self.assertEqual(self.norm_1.resolution_deg, 30)
+ self.assertEqual(self.norm_1.phi_min_deg, -180)
+ self.assertEqual(self.norm_1.phi_max_deg, 180)
+ self.assertEqual(self.norm_1.theta_min_deg, 0)
+ self.assertEqual(self.norm_1.theta_max_deg, 180)
+ self.assertEqual(self.norm_1.phi_min_rad, -np.pi)
+ self.assertEqual(self.norm_1.phi_max_rad, np.pi)
+ self.assertEqual(self.norm_1.theta_min_rad, 0)
+ self.assertEqual(self.norm_1.theta_max_rad, np.pi)
+ npt.assert_equal(self.norm_1.phi_vals_deg, np.arange(-180, 180, 30))
+ npt.assert_equal(self.norm_1.theta_vals_deg, np.arange(0, 180, 30))
+
def test_calculate_correction_factor(self):
# Test 1: omni pattern
azi = 0
ele = 0
- self.norm_1.antenna = AntennaBeamformingImt(self.par_1,azi,ele)
+ self.norm_1.antenna = AntennaBeamformingImt(self.par_1, azi, ele)
# Test adjacent channel case: single antenna element
c_chan = False
- c_fac, err = self.norm_1.calculate_correction_factor(0,0,c_chan)
- self.assertAlmostEqual(c_fac,0.0,delta = 1e-2)
- self.assertLess(np.max(np.abs(err)),1e-3)
-
+ c_fac, err = self.norm_1.calculate_correction_factor(0, 0, c_chan)
+ self.assertAlmostEqual(c_fac, 0.0, delta=1e-2)
+ self.assertLess(np.max(np.abs(err)), 1e-3)
+
# Test 2: UE element pattern
azi = 0
ele = 0
- self.norm_2.antenna = AntennaBeamformingImt(self.par_2,azi,ele)
+ self.norm_2.antenna = AntennaBeamformingImt(self.par_2, azi, ele)
# Test adjacent channel case: single antenna element
c_chan = False
- c_fac, err = self.norm_2.calculate_correction_factor(0,0,c_chan)
- self.assertAlmostEqual(c_fac,2.4,delta = 1e-1)
- self.assertGreater(err[0],2.35)
- self.assertLess(err[1],2.45)
-
+ c_fac, err = self.norm_2.calculate_correction_factor(0, 0, c_chan)
+ self.assertAlmostEqual(c_fac, 2.4, delta=1e-1)
+ self.assertGreater(err[0], 2.35)
+ self.assertLess(err[1], 2.45)
+
# Test 3.1: BS element pattern
azi = 0
ele = 0
- self.norm_3.antenna = AntennaBeamformingImt(self.par_3,azi,ele)
+ self.norm_3.antenna = AntennaBeamformingImt(self.par_3, azi, ele)
# Test adjacent channel case: single antenna element
c_chan = False
- c_fac, err = self.norm_3.calculate_correction_factor(0,0,c_chan)
- self.assertAlmostEqual(c_fac,4.8,delta = 1e-1)
- self.assertGreater(err[0],4.75)
- self.assertLess(err[1],4.85)
-
+ c_fac, err = self.norm_3.calculate_correction_factor(0, 0, c_chan)
+ self.assertAlmostEqual(c_fac, 4.8, delta=1e-1)
+ self.assertGreater(err[0], 4.75)
+ self.assertLess(err[1], 4.85)
+
# Test 3.2: BS array
azi = 0
ele = 0
- self.norm_3.antenna = AntennaBeamformingImt(self.par_3,azi,ele)
+ self.norm_3.antenna = AntennaBeamformingImt(self.par_3, azi, ele)
# Test adjacent channel case: single antenna element
c_chan = True
- c_fac, err = self.norm_3.calculate_correction_factor(0,0,c_chan)
- self.assertAlmostEqual(c_fac,8.0,delta = 1e-1)
- self.assertGreater(err[0],7.5)
- self.assertLess(err[1],8.5)
-
+ c_fac, err = self.norm_3.calculate_correction_factor(0, 0, c_chan)
+ self.assertAlmostEqual(c_fac, 8.0, delta=1e-1)
+ self.assertGreater(err[0], 7.5)
+ self.assertLess(err[1], 8.5)
+
def test_generate_correction_matrix(self):
# Test 3.1: BS element pattern
file_name = "test_2.npz"
self.norm_3.generate_correction_matrix(self.par_3, file_name, True)
- data = np.load(file_name)
+ data = np.load(file_name)
self.assertAlmostEqual(data['correction_factor_adj_channel'],
- 4.8,delta = 1e-1)
-
+ 4.8, delta=1e-1)
+
# Test 3.2: BS array
npt.assert_allclose(data['correction_factor_co_channel'],
- np.array([[8.0],[8.0]]),atol = 1e-1)
+ np.array([[8.0], [8.0]]), atol=1e-1)
data.close()
os.remove(file_name)
-
+
+
if __name__ == '__main__':
- unittest.main()
\ No newline at end of file
+ unittest.main()
diff --git a/tests/_test_propagation_p619.py b/tests/_test_propagation_p619.py
index 5eeb66359..863b2bcb3 100644
--- a/tests/_test_propagation_p619.py
+++ b/tests/_test_propagation_p619.py
@@ -23,7 +23,7 @@ class TestPropagationP619(unittest.TestCase):
def setUp(self):
self.p619 = PropagationP619(np.random.RandomState())
- def test_atmospheric_gasses_loss (self):
+ def test_atmospheric_gasses_loss(self):
# compare with benchmark from ITU-R P-619 Fig. 3
frequency_MHz = 30000.
sat_params = DummyParams()
@@ -47,13 +47,12 @@ def test_atmospheric_gasses_loss (self):
self.assertLessEqual(loss_lower, loss)
self.assertGreaterEqual(loss_upper, loss)
-
def test_beam_spreading_attenuation(self):
# compare with benchmark from ITU-R P-619 Fig. 7
- altitude_vec = np.array([0,1,2,3,4,6]) * 1000
- elevation_vec = [0,.5,1,2,3,5]
- att_lower_vec = [.8, .6 , .4, .2, .1, .05]
+ altitude_vec = np.array([0, 1, 2, 3, 4, 6]) * 1000
+ elevation_vec = [0, .5, 1, 2, 3, 5]
+ att_lower_vec = [.8, .6, .4, .2, .1, .05]
att_upper_vec = [.9, .7, .5, .3, .2, .1]
earth_to_space_vec = [True, False, True, False, True, False]
@@ -63,7 +62,8 @@ def test_beam_spreading_attenuation(self):
att_upper_vec,
earth_to_space_vec):
- attenuation = self.p619._get_beam_spreading_att(elevation, altitude, earth_to_space)
+ attenuation = self.p619._get_beam_spreading_att(
+ elevation, altitude, earth_to_space)
self.assertLessEqual(lower, abs(attenuation))
self.assertGreaterEqual(upper, abs(attenuation))
diff --git a/tests/main.py b/tests/main.py
index 2f80560b4..d1f6069ac 100644
--- a/tests/main.py
+++ b/tests/main.py
@@ -13,5 +13,5 @@
testRunner = unittest.runner.TextTestRunner()
test_results = testRunner.run(tests)
-if(test_results.errors != [] or test_results.failures != []): sys.exit(1)
-
\ No newline at end of file
+if (test_results.errors != [] or test_results.failures != []):
+ sys.exit(1)
diff --git a/sharc/input/__init__.py b/tests/parameters/__init__.py
similarity index 92%
rename from sharc/input/__init__.py
rename to tests/parameters/__init__.py
index faaaf799c..40a96afc6 100644
--- a/sharc/input/__init__.py
+++ b/tests/parameters/__init__.py
@@ -1,3 +1 @@
# -*- coding: utf-8 -*-
-
-
diff --git a/tests/parameters/parameters_for_testing.ini b/tests/parameters/parameters_for_testing.ini
new file mode 100644
index 000000000..f192b9802
--- /dev/null
+++ b/tests/parameters/parameters_for_testing.ini
@@ -0,0 +1,813 @@
+[GENERAL]
+###########################################################################
+# Number of simulation snapshots
+num_snapshots = 100
+###########################################################################
+# IMT link that will be simulated (DOWNLINK or UPLINK)
+imt_link = DOWNLINK
+###########################################################################
+# The chosen system for sharing study
+# EESS_SS, FSS_SS, FSS_ES, FS, RAS
+system = FSS_ES
+###########################################################################
+# Compatibility scenario (co-channel and/or adjacent channel interference)
+enable_cochannel = FALSE
+enable_adjacent_channel = TRUE
+###########################################################################
+# Seed for random number generator
+seed = 101
+###########################################################################
+# if FALSE, then a new output directory is created
+overwrite_output = TRUE
+
+[IMT]
+###########################################################################
+# Network topology. Possible values are "MACROCELL", "HOTSPOT", "SINGLE_BS"
+# "INDOOR"
+topology = INDOOR
+###########################################################################
+# Enable wrap around. Available only for "MACROCELL" and "HOTSPOT" topologies
+wrap_around = FALSE
+###########################################################################
+# Number of clusters in macro cell topology
+num_clusters = 1
+###########################################################################
+# Inter-site distance in macrocell network topology [m]
+intersite_distance = 399
+###########################################################################
+# Minimum 2D separation distance from BS to UE [m]
+minimum_separation_distance_bs_ue = 1.3
+###########################################################################
+# Defines if IMT service is the interferer or interfered-with service
+# TRUE : IMT suffers interference
+# FALSE : IMT generates interference
+interfered_with = FALSE
+###########################################################################
+# IMT center frequency [MHz]
+frequency = 24360
+###########################################################################
+# IMT bandwidth [MHz]
+bandwidth = 200.5
+###########################################################################
+# IMT resource block bandwidth [MHz]
+rb_bandwidth = 0.181
+###########################################################################
+# IMT spectrum emission mask. Options are:
+# "IMT-2020" : for mmWave as described in ITU-R TG 5/1 Contribution 36
+# "3GPP E-UTRA" : for E-UTRA bands > 1 GHz as described in
+# TS 36.104 v11.2.0 (BS) and TS 36.101 v11.2.0 (UE)
+spectral_mask = 3GPP E-UTRA
+###########################################################################
+# level of spurious emissions [dBm/MHz]
+spurious_emissions = -13.1
+###########################################################################
+# Amount of guard band wrt total bandwidth. Setting this parameter to 0.1
+# means that 10% of the total bandwidth will be used as guard band: 5% in
+# the lower
+guard_band_ratio = 0.14
+###########################################################################
+# The load probability (or activity factor) models the statistical
+# variation of the network load by defining the number of fully loaded
+# base stations that are simultaneously transmitting
+bs_load_probability = .2
+###########################################################################
+# Conducted power per antenna element [dBm/bandwidth]
+bs_conducted_power = 11.1
+###########################################################################
+# Base station height [m]
+bs_height = 6.1
+###########################################################################
+# Base station noise figure [dB]
+bs_noise_figure = 10.1
+###########################################################################
+# User equipment noise temperature [K]
+bs_noise_temperature = 290.1
+###########################################################################
+# Base station array ohmic loss [dB]
+bs_ohmic_loss = 3.1
+###########################################################################
+# Uplink attenuation factor used in link-to-system mapping
+ul_attenuation_factor = 0.4
+###########################################################################
+# Uplink minimum SINR of the code set [dB]
+ul_sinr_min = -10
+###########################################################################
+# Uplink maximum SINR of the code set [dB]
+ul_sinr_max = 22
+###########################################################################
+# Number of UEs that are allocated to each cell within handover margin.
+# Remember that in macrocell network each base station has 3 cells (sectors)
+ue_k = 3
+###########################################################################
+# Multiplication factor that is used to ensure that the sufficient number
+# of UE's will distributed throughout ths system area such that the number
+# of K users is allocated to each cell. Normally, this values varies
+# between 2 and 10 according to the user drop method
+ue_k_m = 1
+###########################################################################
+# Percentage of indoor UE's [%]
+ue_indoor_percent = 5
+###########################################################################
+# Regarding the distribution of active UE's over the cell area, this
+# parameter states how the UEs will be distributed
+# Possible values: UNIFORM : UEs will be uniformly distributed within the
+# whole simulation area. Not applicable to
+# hotspots.
+# ANGLE_AND_DISTANCE : UEs will be distributed following
+# given distributions for angle and
+# distance. In this case, these must be
+# defined later.
+ue_distribution_type = ANGLE_AND_DISTANCE
+###########################################################################
+# Regarding the distribution of active UE's over the cell area, this
+# parameter models the distance between UE's and BS.
+# Possible values: RAYLEIGH, UNIFORM
+ue_distribution_distance = UNIFORM
+###########################################################################
+# Regarding the distribution of active UE's over the cell area, this
+# parameter models the azimuth between UE and BS (within ยฑ60ยฐ range).
+# Possible values: NORMAL, UNIFORM
+ue_distribution_azimuth = NORMAL
+###########################################################################
+# Power control algorithm
+# ue_tx_power_control = "ON",power control On
+# ue_tx_power_control = "OFF",power control Off
+ue_tx_power_control = ON
+###########################################################################
+# Power per RB used as target value [dBm]
+ue_p_o_pusch = -95
+###########################################################################
+# Alfa is the balancing factor for UEs with bad channel
+# and UEs with good channel
+ue_alpha = 1
+###########################################################################
+# Maximum UE transmit power [dBm]
+ue_p_cmax = 22
+###########################################################################
+# UE power dynamic range [dB]
+# The minimum transmit power of a UE is (ue_p_cmax - ue_dynamic_range)
+ue_power_dynamic_range = 63
+###########################################################################
+# UE height [m]
+ue_height = 1.5
+###########################################################################
+# User equipment noise figure [dB]
+ue_noise_figure = 10
+###########################################################################
+# User equipment feed loss [dB]
+ue_ohmic_loss = 3
+###########################################################################
+# User equipment body loss [dB]
+ue_body_loss = 4
+###########################################################################
+# Downlink attenuation factor used in link-to-system mapping
+dl_attenuation_factor = 0.6
+###########################################################################
+# Downlink minimum SINR of the code set [dB]
+dl_sinr_min = -10
+###########################################################################
+# Downlink maximum SINR of the code set [dB]
+dl_sinr_max = 30
+###########################################################################
+# Channel parameters
+# channel model, possible values are "FSPL" (free-space path loss),
+# "CI" (close-in FS reference distance)
+# "UMa" (Urban Macro - 3GPP)
+# "UMi" (Urban Micro - 3GPP)
+# "TVRO-URBAN"
+# "TVRO-SUBURBAN"
+# "ABG" (Alpha-Beta-Gamma)
+channel_model = FSPL
+###########################################################################
+# Adjustment factor for LoS probability in UMi path loss model.
+# Original value: 18 (3GPP)
+los_adjustment_factor = 18
+###########################################################################
+# If shadowing should be applied or not
+shadowing = FALSE
+noise_temperature = 290
+
+[IMT_ANTENNA]
+###########################################################################
+# Defines the antenna model to be used in compatibility studies between
+# IMT and other services in adjacent band
+# Possible values: SINGLE_ELEMENT, BEAMFORMING
+adjacent_antenna_model = BEAMFORMING
+###########################################################################
+# If normalization of M2101 should be applied for BS
+bs_normalization = FALSE
+###########################################################################
+# If normalization of M2101 should be applied for UE
+ue_normalization = FALSE
+###########################################################################
+# File to be used in the BS beamforming normalization
+# Normalization files can be generated with the
+# antenna/beamforming_normalization/normalize_script.py script
+bs_normalization_file = antenna/beamforming_normalization/bs_norm.npz
+###########################################################################
+# File to be used in the UE beamforming normalization
+# Normalization files can be generated with the
+# antenna/beamforming_normalization/normalize_script.py script
+ue_normalization_file = antenna/beamforming_normalization/ue_norm.npz
+###########################################################################
+# Radiation pattern of each antenna element
+# Possible values: "M2101", "F1336", "FIXED"
+bs_element_pattern = F1336
+ue_element_pattern = F1336
+###########################################################################
+# Minimum array gain for the beamforming antenna [dBi]
+bs_minimum_array_gain = -200
+ue_minimum_array_gain = -200
+###########################################################################
+# mechanical downtilt [degrees]
+# NOTE: consider defining it to 90 degrees in case of indoor simulations
+bs_downtilt = 6
+###########################################################################
+# BS/UE maximum transmit/receive element gain [dBi]
+# default: bs_element_max_g = 5, for M.2101
+# = 15, for M.2292
+# default: ue_element_max_g = 5, for M.2101
+# = -3, for M.2292
+bs_element_max_g = 5
+ue_element_max_g = 5
+###########################################################################
+# BS/UE horizontal 3dB beamwidth of single element [degrees]
+bs_element_phi_3db = 65
+ue_element_phi_3db = 90
+###########################################################################
+# BS/UE vertical 3dB beamwidth of single element [degrees]
+# For F1336: if equal to 0, then beamwidth is calculated automaticaly
+bs_element_theta_3db = 65
+ue_element_theta_3db = 90
+###########################################################################
+# BS/UE number of rows in antenna array
+bs_n_rows = 8
+ue_n_rows = 4
+###########################################################################
+# BS/UE number of columns in antenna array
+bs_n_columns = 8
+ue_n_columns = 4
+###########################################################################
+# BS/UE array horizontal element spacing (d/lambda)
+bs_element_horiz_spacing = 0.5
+ue_element_horiz_spacing = 0.5
+###########################################################################
+# BS/UE array vertical element spacing (d/lambda)
+bs_element_vert_spacing = 0.5
+ue_element_vert_spacing = 0.5
+###########################################################################
+# BS/UE front to back ratio of single element [dB]
+bs_element_am = 30
+ue_element_am = 25
+###########################################################################
+# BS/UE single element vertical sidelobe attenuation [dB]
+bs_element_sla_v = 30
+ue_element_sla_v = 25
+###########################################################################
+# Multiplication factor k that is used to adjust the single-element pattern.
+# According to Report ITU-R M.[IMT.AAS], this may give a closer match of the
+# side lobes when beamforming is assumed in adjacent channel.
+# Original value: 12 (Rec. ITU-R M.2101)
+bs_multiplication_factor = 12
+ue_multiplication_factor = 12
+
+[HOTSPOT]
+###########################################################################
+# Number of hotspots per macro cell (sector)
+num_hotspots_per_cell = 1
+###########################################################################
+# Maximum 2D distance between hotspot and UE [m]
+# This is the hotspot radius
+max_dist_hotspot_ue = 99.9
+###########################################################################
+# Minimum 2D distance between macro cell base station and hotspot [m]
+min_dist_bs_hotspot = 1.2
+
+[INDOOR]
+###########################################################################
+# Basic path loss model for indoor topology. Possible values:
+# "FSPL" (free-space path loss),
+# "INH_OFFICE" (3GPP Indoor Hotspot - Office)
+basic_path_loss = FSPL
+###########################################################################
+# Number of rows of buildings in the simulation scenario
+n_rows = 3
+###########################################################################
+# Number of colums of buildings in the simulation scenario
+n_colums = 2
+###########################################################################
+# Number of buildings containing IMT stations. Options:
+# 'ALL': all buildings contain IMT stations.
+# Number of buildings.
+num_imt_buildings = 2
+###########################################################################
+# Street width (building separation) [m]
+street_width = 30.1
+###########################################################################
+# Intersite distance [m]
+intersite_distance = 40.1
+###########################################################################
+# Number of cells per floor
+num_cells = 3
+###########################################################################
+# Number of floors per building
+num_floors = 1
+###########################################################################
+# Percentage of indoor UE's [0, 1]
+ue_indoor_percent = .95
+###########################################################################
+# Building class: "TRADITIONAL" or "THERMALLY_EFFICIENT"
+building_class = THERMALLY_EFFICIENT
+
+[FSS_SS]
+###########################################################################
+# satellite center frequency [MHz]
+frequency = 43000
+###########################################################################
+# satellite bandwidth [MHz]
+bandwidth = 200
+###########################################################################
+# satellite altitude [m] and latitude [deg]
+altitude = 35780000
+lat_deg = 0
+###########################################################################
+# Elevation angle [deg]
+elevation = 270
+###########################################################################
+# Azimuth angle [deg]
+azimuth = 0
+###########################################################################
+# Peak transmit power spectral density (clear sky) [dBW/Hz]
+tx_power_density = -5
+###########################################################################
+# System receive noise temperature [K]
+noise_temperature = 950
+###########################################################################
+# adjacent channel selectivity (dB)
+adjacent_ch_selectivity = 0
+###########################################################################
+# Satellite peak receive antenna gain [dBi]
+antenna_gain = 46.6
+###########################################################################
+# Antenna pattern of the FSS space station
+# Possible values: "ITU-R S.672", "ITU-R S.1528", "FSS_SS", "OMNI"
+antenna_pattern = FSS_SS
+# IMT parameters relevant to the satellite system
+# altitude of IMT system (in meters)
+# latitude of IMT system (in degrees)
+# difference between longitudes of IMT and satellite system
+# (positive if space-station is to the East of earth-station)
+imt_altitude = 0
+imt_lat_deg = 0
+imt_long_diff_deg = 0
+season = SUMMER
+###########################################################################
+# Channel parameters
+# channel model, possible values are "FSPL" (free-space path loss),
+# "SatelliteSimple" (FSPL + 4 + clutter loss)
+# "P619"
+channel_model = P619
+###########################################################################
+# The required near-in-side-lobe level (dB) relative to peak gain
+# according to ITU-R S.672-4
+antenna_l_s = -20
+###########################################################################
+# 3 dB beamwidth angle (3 dB below maximum gain) [degrees]
+antenna_3_dB = 0.65
+###########################################################################
+# Constants
+BOLTZMANN_CONSTANT = 1.38064852e-23
+EARTH_RADIUS = 6371000
+
+[FSS_ES]
+###########################################################################
+# type of FSS-ES location:
+# FIXED - position must be given
+# CELL - random within central cell
+# NETWORK - random within whole network
+# UNIFORM_DIST - uniform distance from cluster centre,
+# between min_dist_to_bs and max_dist_to_bs
+location = UNIFORM_DIST
+###########################################################################
+# x-y coordinates [m] (only if FIXED location is chosen)
+x = 10000
+y = 0
+###########################################################################
+# minimum distance from BSs [m]
+min_dist_to_bs = 10
+###########################################################################
+# maximum distance from centre BSs [m] (only if UNIFORM_DIST is chosen)
+max_dist_to_bs = 600
+###########################################################################
+# antenna height [m]
+height = 6
+###########################################################################
+# Elevation angle [deg], minimum and maximum, values
+elevation_min = 48
+elevation_max = 80
+###########################################################################
+# Azimuth angle [deg]
+# either a specific angle or string 'RANDOM'
+azimuth = RANDOM
+###########################################################################
+# center frequency [MHz]
+frequency = 43000
+###########################################################################
+# bandwidth [MHz]
+bandwidth = 6
+###########################################################################
+# System receive noise temperature [K]
+noise_temperature = 950
+###########################################################################
+# adjacent channel selectivity (dB)
+adjacent_ch_selectivity = 0
+###########################################################################
+# Peak transmit power spectral density (clear sky) [dBW/Hz]
+tx_power_density = -68.3
+###########################################################################
+# antenna peak gain [dBi]
+antenna_gain = 32
+###########################################################################
+# Antenna pattern of the FSS Earth station
+# Possible values: "ITU-R S.1855", "ITU-R S.465", "ITU-R S.580", "OMNI",
+# "Modified ITU-R S.465"
+antenna_pattern = Modified ITU-R S.465
+###########################################################################
+# Diameter of antenna [m]
+diameter = 1.8
+###########################################################################
+# Antenna envelope gain (dBi) - only relevant for "Modified ITU-R S.465" model
+antenna_envelope_gain = 0
+###########################################################################
+# Channel parameters
+# channel model, possible values are "FSPL" (free-space path loss),
+# "TerrestrialSimple" (FSPL + clutter loss)
+# "P452"
+# "TVRO-URBAN"
+# "TVRO-SUBURBAN"
+# "HDFSS"
+channel_model = P452
+###########################################################################
+# Constants
+BOLTZMANN_CONSTANT = 1.38064852e-23
+EARTH_RADIUS = 6371000
+###########################################################################
+# P452 parameters
+###########################################################################
+# Total air pressure in hPa
+atmospheric_pressure = 935
+###########################################################################
+# Temperature in Kelvin
+air_temperature = 300
+###########################################################################
+#Sea-level surface refractivity (use the map)
+N0 = 352.58
+###########################################################################
+#Average radio-refractive (use the map)
+delta_N = 43.127
+###########################################################################
+#percentage p. Float (0 to 100) or RANDOM
+percentage_p = 0.2
+###########################################################################
+#Distance over land from the transmit and receive antennas to the coast (km)
+Dct = 70
+###########################################################################
+#Distance over land from the transmit and receive antennas to the coast (km)
+Dcr = 70
+###########################################################################
+##Effective height of interfering antenna (m)
+Hte = 20
+###########################################################################
+#Effective height of interfered-with antenna (m)
+Hre = 3
+###########################################################################
+##Latitude of transmitter
+tx_lat = -23.55028
+###########################################################################
+#Latitude of receiver
+rx_lat = -23.17889
+###########################################################################
+#Antenna polarization
+polarization = horizontal
+###########################################################################
+#determine whether clutter loss following ITU-R P.2108 is added (TRUE/FALSE)
+clutter_loss = TRUE
+###########################################################################
+# HDFSS propagation parameters
+###########################################################################
+# HDFSS position relative to building it is on. Possible values are
+# ROOFTOP and BUILDINGSIDE
+es_position = ROOFTOP
+###########################################################################
+# Enable shadowing loss
+shadow_enabled = TRUE
+###########################################################################
+# Enable building entry loss
+building_loss_enabled = TRUE
+###########################################################################
+# Enable interference from IMT stations at the same building as the HDFSS
+same_building_enabled = FALSE
+###########################################################################
+# Enable diffraction loss
+diffraction_enabled = FALSE
+###########################################################################
+# Building entry loss type applied between BSs and HDFSS ES. Options are:
+# P2109_RANDOM: random probability at P.2109 model, considering elevation
+# P2109_FIXED: fixed probability at P.2109 model, considering elevation.
+# Probability must be specified in bs_building_entry_loss_prob.
+# FIXED_VALUE: fixed value per BS. Value must be specified in
+# bs_building_entry_loss_value.
+bs_building_entry_loss_type = P2109_FIXED
+###########################################################################
+# Probability of building entry loss not exceeded if
+# bs_building_entry_loss_type = P2109_FIXED
+bs_building_entry_loss_prob = 0.75
+###########################################################################
+# Value in dB of building entry loss if
+# bs_building_entry_loss_type = FIXED_VALUE
+bs_building_entry_loss_value = 35
+
+[FS]
+###########################################################################
+# x-y coordinates [m]
+x = 1000
+y = 0
+###########################################################################
+# antenna height [m]
+height = 15
+###########################################################################
+# Elevation angle [deg]
+elevation = -10
+###########################################################################
+# Azimuth angle [deg]
+azimuth = 180
+###########################################################################
+# center frequency [MHz]
+frequency = 27250
+###########################################################################
+# bandwidth [MHz]
+bandwidth = 112
+###########################################################################
+# System receive noise temperature [K]
+noise_temperature = 290
+###########################################################################
+# adjacent channel selectivity (dB)
+adjacent_ch_selectivity = 20
+###########################################################################
+# Peak transmit power spectral density (clear sky) [dBW/Hz]
+tx_power_density = -68.3
+###########################################################################
+# antenna peak gain [dBi]
+antenna_gain = 36.9
+###########################################################################
+# Antenna pattern of the fixed wireless service
+# Possible values: "ITU-R F.699", "OMNI"
+antenna_pattern = OMNI
+###########################################################################
+# Diameter of antenna [m]
+diameter = 0.3
+###########################################################################
+# Channel parameters
+# channel model, possible values are "FSPL" (free-space path loss),
+# "TerrestrialSimple" (FSPL + clutter loss)
+channel_model = TerrestrialSimple
+
+[HAPS]
+###########################################################################
+# HAPS center frequency [MHz]
+frequency = 27251.1
+###########################################################################
+# HAPS bandwidth [MHz]
+bandwidth = 200
+###########################################################################
+# HAPS altitude [m] and latitude [deg]
+altitude = 20001.1
+lat_deg = 0.1
+###########################################################################
+# Elevation angle [deg]
+elevation = 270
+###########################################################################
+# Azimuth angle [deg]
+azimuth = 0
+###########################################################################
+# EIRP spectral density [dBW/MHz]
+eirp_density = 4.4
+###########################################################################
+# HAPS peak antenna gain [dBi]
+antenna_gain = 28.1
+###########################################################################
+# Adjacent channel selectivity [dB]
+acs = 30
+###########################################################################
+# Antenna pattern of the HAPS (airbone) station
+# Possible values: "ITU-R F.1891", "OMNI"
+antenna_pattern = OMNI
+# IMT parameters relevant to the HAPS system
+# altitude of IMT system (in meters)
+# latitude of IMT system (in degrees)
+# difference between longitudes of IMT and satellite system
+# (positive if space-station is to the East of earth-station)
+imt_altitude = 0
+imt_lat_deg = 0
+imt_long_diff_deg = 0
+season = SUMMER
+
+###########################################################################
+# Channel parameters
+# channel model, possible values are "FSPL" (free-space path loss),
+# "SatelliteSimple" (FSPL + 4 + clutter loss)
+# "P619"
+channel_model = P619
+
+###########################################################################
+# Near side-lobe level (dB) relative to the peak gain required by the system
+# design, and has a maximum value of โ25 dB
+antenna_l_n = -25
+###########################################################################
+# Constants
+BOLTZMANN_CONSTANT = 1.38064852e-23
+EARTH_RADIUS = 6371000
+
+[RNS]
+###########################################################################
+# x-y coordinates [m]
+x = 660.1
+y = -370.1
+###########################################################################
+# altitude [m]
+altitude = 150.1
+###########################################################################
+# center frequency [MHz]
+frequency = 32000.1
+###########################################################################
+# bandwidth [MHz]
+bandwidth = 60.1
+###########################################################################
+# System receive noise temperature [K]
+noise_temperature = 1154.1
+###########################################################################
+# Peak transmit power spectral density (clear sky) [dBW/Hz]
+tx_power_density = -70.79
+###########################################################################
+# antenna peak gain [dBi]
+antenna_gain = 30.1
+###########################################################################
+# Adjacent channel selectivity [dB]
+acs = 30.1
+###########################################################################
+# Antenna pattern of the fixed wireless service
+# Possible values: "ITU-R M.1466", "OMNI"
+antenna_pattern = ITU-R M.1466
+###########################################################################
+# Channel parameters
+# channel model, possible values are "FSPL" (free-space path loss),
+# "SatelliteSimple" (FSPL + 4 dB + clutter loss)
+# "P619"
+channel_model = P619
+###########################################################################
+# Specific parameters for P619
+season = SUMMER
+imt_altitude = 0
+imt_lat_deg = 0
+
+[RAS]
+###########################################################################
+# x-y coordinates [m]
+x = 81000.1
+y = 0.1
+###########################################################################
+# antenna height [m]
+height = 15.1
+###########################################################################
+# Elevation angle [deg]
+elevation = 45.1
+###########################################################################
+# Azimuth angle [deg]
+azimuth = -90.1
+###########################################################################
+# center frequency [MHz]
+frequency = 43000.1
+###########################################################################
+# bandwidth [MHz]
+bandwidth = 1000.1
+###########################################################################
+# Antenna noise temperature [K]
+antenna_noise_temperature = 25.1
+###########################################################################
+# Receiver noise temperature [K]
+receiver_noise_temperature = 65.1
+###########################################################################
+# adjacent channel selectivity (dB)
+adjacent_ch_selectivity = 20.1
+###########################################################################
+# Antenna efficiency
+antenna_efficiency = 0.9
+###########################################################################
+# Antenna pattern of the FSS Earth station
+# Possible values: "ITU-R SA.509", "OMNI"
+antenna_pattern = ITU-R SA.509
+###########################################################################
+# Antenna gain for "OMNI" pattern
+antenna_gain = 0.5
+###########################################################################
+# Diameter of antenna [m]
+diameter = 15.1
+
+###########################################################################
+# Channel parameters
+# channel model, possible values are "FSPL" (free-space path loss),
+# "TerrestrialSimple" (FSPL + clutter loss)
+# "P452"
+channel_model = P452
+###########################################################################
+# P452 parameters
+###########################################################################
+# Total air pressure in hPa
+atmospheric_pressure = 935.2
+###########################################################################
+# Temperature in Kelvin
+air_temperature = 300.1
+###########################################################################
+#Sea-level surface refractivity (use the map)
+N0 = 352.58
+###########################################################################
+#Average radio-refractive (use the map)
+delta_N = 43.127
+###########################################################################
+#percentage p. Float (0 to 100) or RANDOM
+percentage_p = 0.2
+###########################################################################
+#Distance over land from the transmit and receive antennas to the coast (km)
+Dct = 70.1
+###########################################################################
+#Distance over land from the transmit and receive antennas to the coast (km)
+Dcr = 70.1
+###########################################################################
+##Effective height of interfering antenna (m)
+Hte = 20.1
+###########################################################################
+#Effective height of interfered-with antenna (m)
+Hre = 3.1
+###########################################################################
+##Latitude of transmitter
+tx_lat = -23.55028
+###########################################################################
+#Latitude of receiver
+rx_lat = -23.17889
+###########################################################################
+#Antenna polarization
+polarization = horizontal
+###########################################################################
+#determine whether clutter loss following ITU-R P.2108 is added (TRUE/FALSE)
+clutter_loss = TRUE
+
+[EESS_SS]
+###########################################################################
+# sensor center frequency [MHz]
+frequency = 23900.1
+###########################################################################
+# sensor bandwidth [MHz]
+bandwidth = 200.1
+###########################################################################
+# Off-nadir pointing angle [deg]
+nadir_angle = 46.6
+###########################################################################
+# sensor altitude [m]
+altitude = 828000.1
+###########################################################################
+# Antenna pattern of the sensor
+# Possible values: "ITU-R RS.1813"
+# "ITU-R RS.1861 9a"
+# "ITU-R RS.1861 9b"
+# "ITU-R RS.1861 9c"
+# "OMNI"
+antenna_pattern = ITU-R RS.1813
+# Antenna efficiency for pattern described in ITU-R RS.1813 [0-1]
+antenna_efficiency = 0.6
+# Antenna diameter for ITU-R RS.1813 [m]
+antenna_diameter = 2.2
+###########################################################################
+# receive antenna gain - applicable for 9a, 9b and OMNI [dBi]
+antenna_gain = 52.1
+###########################################################################
+# Channel parameters
+# channel model, possible values are "FSPL" (free-space path loss),
+# "P619"
+channel_model = FSPL
+# Relevant IMT parameters which apply for ITU-R P.619
+# altitude of IMT system (in meters)
+# latitude of IMT system (in degrees)
+# season of the year: "SUMMER", "WINTER"
+imt_altitude = 20.1
+imt_lat_deg = -22.9
+season = WINTER
+###########Creates a statistical distribution of nadir angle###############
+##############following variables nadir_angle_distribution#################
+# if distribution_enable = ON, nadir_angle will vary statistically#########
+# if distribution_enable = OFF, nadir_angle follow nadir_angle variable ###
+# distribution_type = UNIFORM
+# UNIFORM = UNIFORM distribution in nadir_angle
+# - nadir_angle_distribution = initial nadir angle, final nadir angle
+distribution_enable = ON
+distribution_type = UNIFORM
+nadir_angle_distribution = 18.6,49.4
diff --git a/tests/parameters/parameters_for_testing.yaml b/tests/parameters/parameters_for_testing.yaml
new file mode 100644
index 000000000..153e91bf4
--- /dev/null
+++ b/tests/parameters/parameters_for_testing.yaml
@@ -0,0 +1,1119 @@
+general:
+ ###########################################################################
+ # Number of simulation snapshots
+ num_snapshots : 100
+ ###########################################################################
+ # IMT link that will be simulated (DOWNLINK or UPLINK)
+ imt_link : DOWNLINK
+ ###########################################################################
+ # The chosen system for sharing study
+ # EESS_PASSIVE, FSS_SS, FSS_ES, FS, RAS
+ system : FSS_ES
+ ###########################################################################
+ # Compatibility scenario (co-channel and/or adjacent channel interference)
+ enable_cochannel : FALSE
+ enable_adjacent_channel : TRUE
+ ###########################################################################
+ # Seed for random number generator
+ seed : 101
+ ###########################################################################
+ # if FALSE, then a new output directory is created
+ overwrite_output : TRUE
+imt:
+ ###########################################################################
+ # Minimum 2D separation distance from BS to UE [m]
+ minimum_separation_distance_bs_ue : 1.3
+ ###########################################################################
+ # Defines if IMT service is the interferer or interfered-with service
+ # TRUE : IMT suffers interference
+ # FALSE : IMT generates interference
+ interfered_with : FALSE
+ ###########################################################################
+ # IMT center frequency [MHz]
+ frequency : 24360
+ ###########################################################################
+ # IMT bandwidth [MHz]
+ bandwidth : 200.5
+ ###########################################################################
+ # IMT resource block bandwidth [MHz]
+ rb_bandwidth : 0.181
+ ###########################################################################
+ # IMT spectrum emission mask. Options are:
+ # "IMT-2020" : for mmWave as described in ITU-R TG 5/1 Contribution 36
+ # "3GPP E-UTRA" : for E-UTRA bands > 1 GHz as described in
+ # TS 36.104 v11.2.0 (BS) and TS 36.101 v11.2.0 (UE)
+ spectral_mask : 3GPP E-UTRA
+ ###########################################################################
+ # level of spurious emissions [dBm/MHz]
+ spurious_emissions : -13.1
+ ###########################################################################
+ # Amount of guard band wrt total bandwidth. Setting this parameter to 0.1
+ # means that 10% of the total bandwidth will be used as guard band: 5% in
+ # the lower
+ guard_band_ratio : 0.14
+ ###########################################################################
+ # Network topology parameters.
+ topology:
+ ###########################################################################
+ # Topology Type. Possible values are "MACROCELL", "HOTSPOT", "SINGLE_BS"
+ # "INDOOR"
+ type: INDOOR
+ ###########################################################################
+ # Macrocell Topology parameters. Relevant when imt.topology.type == "MACROCELL"
+ macrocell:
+ ###########################################################################
+ # Inter-site distance in macrocell network topology [m]
+ intersite_distance: 543
+ ###########################################################################
+ # Enable wrap around.
+ wrap_around: true
+ ###########################################################################
+ # Number of clusters in macro cell topology
+ num_clusters: 7
+ ###########################################################################
+ # Single Base Station Topology parameters. Relevant when imt.topology.type == "SINGLE_BS"
+ single_bs:
+ ###########################################################################
+ # Inter-site distance or Cell Radius in single Base Station network topology [m]
+ # You can either provide 'cell_radius' or 'intersite_distance' for this topology
+ # The relationship used is cell_radius = intersite_distance * 2 / 3
+ cell_radius: 543
+ # intersite_distance: 1
+ ###########################################################################
+ # Number of clusters in single base station topology
+ # You can simulate 1 or 2 BS's with this topology
+ num_clusters: 2
+ ###########################################################################
+ # Hotspot Topology parameters. Relevant when imt.topology.type == "HOTSPOT"
+ hotspot:
+ ###########################################################################
+ # Inter-site distance in hotspot network topology [m]
+ intersite_distance: 321
+ ###########################################################################
+ # Enable wrap around.
+ wrap_around: true
+ ###########################################################################
+ # Number of clusters in macro cell topology
+ num_clusters: 7
+ ###########################################################################
+ # Number of hotspots per macro cell (sector)
+ num_hotspots_per_cell : 1
+ ###########################################################################
+ # Maximum 2D distance between hotspot and UE [m]
+ # This is the hotspot radius
+ max_dist_hotspot_ue : 99.9
+ ###########################################################################
+ # Minimum 2D distance between macro cell base station and hotspot [m]
+ min_dist_bs_hotspot : 1.2
+ ###########################################################################
+ # Indoor Topology parameters. Relevant when imt.topology.type == "INOOR"
+ indoor:
+ ###########################################################################
+ # Basic path loss model for indoor topology. Possible values:
+ # "FSPL" (free-space path loss),
+ # "INH_OFFICE" (3GPP Indoor Hotspot - Office)
+ basic_path_loss : FSPL
+ ###########################################################################
+ # Number of rows of buildings in the simulation scenario
+ n_rows : 3
+ ###########################################################################
+ # Number of colums of buildings in the simulation scenario
+ n_colums : 2
+ ###########################################################################
+ # Number of buildings containing IMT stations. Options:
+ # 'ALL': all buildings contain IMT stations.
+ # Number of buildings.
+ num_imt_buildings : 2
+ ###########################################################################
+ # Street width (building separation) [m]
+ street_width : 30.1
+ ###########################################################################
+ # Intersite distance [m]
+ intersite_distance : 40.1
+ ###########################################################################
+ # Number of cells per floor
+ num_cells : 3
+ ###########################################################################
+ # Number of floors per building
+ num_floors : 1
+ ###########################################################################
+ # Percentage of indoor UE's [0, 1]
+ ue_indoor_percent : .95
+ ###########################################################################
+ # Building class: "TRADITIONAL" or "THERMALLY_EFFICIENT"
+ building_class : THERMALLY_EFFICIENT
+ ###########################################################################
+ # NTN Topology Parameters
+ ntn:
+ ###########################################################################
+ # NTN cell radius or intersite distance in network topology [m]
+ # @important: You can set only one of cell_radius or intersite_distance
+ # NTN Intersite Distance (m). Intersite distance = Cell Radius * sqrt(3)
+ # NOTE: note that intersite distance has a different geometric meaning in ntn
+ cell_radius : 123
+ # intersite_distance : 155884
+ ###########################################################################
+ # NTN space station azimuth [degree]
+ bs_azimuth : 45
+ ###########################################################################
+ # NTN space station elevation [degree]
+ bs_elevation : 45
+ ###########################################################################
+ # number of sectors [degree]
+ num_sectors : 19
+ ###########################################################################
+ # Conducted power per element [dBm/bandwidth]
+ bs_conducted_power : 37
+ ###########################################################################
+ # Backoff Power [Layer 2] [dB]. Allowed: 7 sector topology - Layer 2
+ bs_backoff_power : 3
+ ###########################################################################
+ # NTN Antenna configuration
+ bs_n_rows_layer1 : 2
+ bs_n_columns_layer1 : 2
+ bs_n_rows_layer2 : 4
+ bs_n_columns_layer2 : 2
+ ###########################################################################
+ # Defines the antenna model to be used in compatibility studies between
+ # IMT and other services in adjacent band
+ # Possible values: SINGLE_ELEMENT, BEAMFORMING
+ adjacent_antenna_model : BEAMFORMING
+ # Base station parameters
+ bs:
+ ###########################################################################
+ # The load probability (or activity factor) models the statistical
+ # variation of the network load by defining the number of fully loaded
+ # base stations that are simultaneously transmitting
+ load_probability : .2
+ ###########################################################################
+ # Conducted power per antenna element [dBm/bandwidth]
+ conducted_power : 11.1
+ ###########################################################################
+ # Base station height [m]
+ height : 6.1
+ ###########################################################################
+ # Base station noise figure [dB]
+ noise_figure : 10.1
+ ###########################################################################
+ # Base station array ohmic loss [dB]
+ ohmic_loss : 3.1
+ # Base Station Antenna parameters:
+ antenna:
+ ###########################################################################
+ # If normalization of M2101 should be applied for BS
+ normalization : FALSE
+ ###########################################################################
+ # If normalization of M2101 should be applied for UE
+ ###########################################################################
+ # File to be used in the BS beamforming normalization
+ # Normalization files can be generated with the
+ # antenna/beamforming_normalization/normalize_script.py script
+ normalization_file : antenna/beamforming_normalization/bs_norm.npz
+ ###########################################################################
+ # File to be used in the UE beamforming normalization
+ # Normalization files can be generated with the
+ # antenna/beamforming_normalization/normalize_script.py script
+ ###########################################################################
+ # Radiation pattern of each antenna element
+ # Possible values: "M2101", "F1336", "FIXED"
+ element_pattern : F1336
+ ###########################################################################
+ # Minimum array gain for the beamforming antenna [dBi]
+ minimum_array_gain : -200
+ ###########################################################################
+ # mechanical downtilt [degrees]
+ # NOTE: consider defining it to 90 degrees in case of indoor simulations
+ downtilt : 6
+ ###########################################################################
+ # BS/UE maximum transmit/receive element gain [dBi]
+ # default: element_max_g = 5, for M.2101
+ # = 15, for M.2292
+ # = -3, for M.2292
+ element_max_g : 5
+ ###########################################################################
+ # BS/UE horizontal 3dB beamwidth of single element [degrees]
+ element_phi_3db : 65
+ ###########################################################################
+ # BS/UE vertical 3dB beamwidth of single element [degrees]
+ # For F1336: if equal to 0, then beamwidth is calculated automaticaly
+ element_theta_3db : 65
+ ###########################################################################
+ # BS/UE number of rows in antenna array
+ n_rows : 8
+ ###########################################################################
+ # BS/UE number of columns in antenna array
+ n_columns : 8
+ ###########################################################################
+ # BS/UE array horizontal element spacing (d/lambda)
+ element_horiz_spacing : 0.5
+ ###########################################################################
+ # BS/UE array vertical element spacing (d/lambda)
+ element_vert_spacing : 0.5
+ ###########################################################################
+ # BS/UE front to back ratio of single element [dB]
+ element_am : 30
+ ###########################################################################
+ # BS/UE single element vertical sidelobe attenuation [dB]
+ element_sla_v : 30
+ ###########################################################################
+ # Multiplication factor k that is used to adjust the single-element pattern.
+ # According to Report ITU-R M.[IMT.AAS], this may give a closer match of the
+ # side lobes when beamforming is assumed in adjacent channel.
+ # Original value: 12 (Rec. ITU-R M.2101)
+ multiplication_factor : 12
+
+ ###########################################################################
+ # User Equipment parameters:
+ ue:
+ ###########################################################################
+ # Number of UEs that are allocated to each cell within handover margin.
+ # Remember that in macrocell network each base station has 3 cells (sectors)
+ k : 3
+ ###########################################################################
+ # Multiplication factor that is used to ensure that the sufficient number
+ # of UE's will distributed throughout ths system area such that the number
+ # of K users is allocated to each cell. Normally, this values varies
+ # between 2 and 10 according to the user drop method
+ k_m : 1
+ ###########################################################################
+ # Percentage of indoor UE's [%]
+ indoor_percent : 5
+ ###########################################################################
+ # Regarding the distribution of active UE's over the cell area, this
+ # parameter states how the UEs will be distributed
+ # Possible values: UNIFORM : UEs will be uniformly distributed within the
+ # whole simulation area. Not applicable to
+ # hotspots.
+ # ANGLE_AND_DISTANCE : UEs will be distributed following
+ # given distributions for angle and
+ # distance. In this case, these must be
+ # defined later.
+ distribution_type : ANGLE_AND_DISTANCE
+ ###########################################################################
+ # Regarding the distribution of active UE's over the cell area, this
+ # parameter models the distance between UE's and BS.
+ # Possible values: RAYLEIGH, UNIFORM
+ distribution_distance : UNIFORM
+ ###########################################################################
+ # Regarding the distribution of active UE's over the cell area, this
+ # parameter models the azimuth between UE and BS (within ยฑ60ยฐ range).
+ # Possible values: NORMAL, UNIFORM
+ distribution_azimuth : NORMAL
+ ###########################################################################
+ # Azimuth range used when distributing the UE within the cell.
+ # Default value is (-60, 60) which representes a 120 degree sector.
+ # Change this to (-180, 180) when deploying the NTN topology
+ azimuth_range: !!python/tuple [-70, 90]
+ ###########################################################################
+ # Power control algorithm
+ # tx_power_control = "ON",power control On
+ # tx_power_control = "OFF",power control Off
+ tx_power_control : ON
+ ###########################################################################
+ # Power per RB used as target value [dBm]
+ p_o_pusch : -95
+ ###########################################################################
+ # Alfa is the balancing factor for UEs with bad channel
+ # and UEs with good channel
+ alpha : 1
+ ###########################################################################
+ # Maximum UE transmit power [dBm]
+ p_cmax : 22
+ ###########################################################################
+ # UE power dynamic range [dB]
+ # The minimum transmit power of a UE is (p_cmax - dynamic_range)
+ power_dynamic_range : 63
+ ###########################################################################
+ # UE height [m]
+ height : 1.5
+ ###########################################################################
+ # User equipment noise figure [dB]
+ noise_figure : 10
+ ###########################################################################
+ # User equipment feed loss [dB]
+ ohmic_loss : 3
+ ###########################################################################
+ # User equipment body loss [dB]
+ body_loss : 4
+ antenna:
+ ###########################################################################
+ # If normalization of M2101 should be applied for UE
+ normalization : FALSE
+ ###########################################################################
+ # File to be used in the UE beamforming normalization
+ # Normalization files can be generated with the
+ # antenna/beamforming_normalization/normalize_script.py script
+ normalization_file : antenna/beamforming_normalization/ue_norm.npz
+ ###########################################################################
+ # Radiation pattern of each antenna element
+ # Possible values: "M2101", "F1336", "FIXED"
+ element_pattern : F1336
+ ###########################################################################
+ # Minimum array gain for the beamforming antenna [dBi]
+ minimum_array_gain : -200
+ ###########################################################################
+ # BS/UE maximum transmit/receive element gain [dBi]
+ # = 15, for M.2292
+ # default: element_max_g = 5, for M.2101
+ # = -3, for M.2292
+ element_max_g : 5
+ ###########################################################################
+ # BS/UE horizontal 3dB beamwidth of single element [degrees]
+ element_phi_3db : 90
+ ###########################################################################
+ # BS/UE vertical 3dB beamwidth of single element [degrees]
+ # For F1336: if equal to 0, then beamwidth is calculated automaticaly
+ element_theta_3db : 90
+ ###########################################################################
+ # BS/UE number of rows in antenna array
+ n_rows : 4
+ ###########################################################################
+ # BS/UE number of columns in antenna array
+ n_columns : 4
+ ###########################################################################
+ # BS/UE array horizontal element spacing (d/lambda)
+ element_horiz_spacing : 0.5
+ ###########################################################################
+ # BS/UE array vertical element spacing (d/lambda)
+ element_vert_spacing : 0.5
+ ###########################################################################
+ # BS/UE front to back ratio of single element [dB]
+ element_am : 25
+ ###########################################################################
+ # BS/UE single element vertical sidelobe attenuation [dB]
+ element_sla_v : 25
+ ###########################################################################
+ # Multiplication factor k that is used to adjust the single-element pattern.
+ # According to Report ITU-R M.[IMT.AAS], this may give a closer match of the
+ # side lobes when beamforming is assumed in adjacent channel.
+ # Original value: 12 (Rec. ITU-R M.2101)
+ multiplication_factor : 12
+ ###########################################################################
+ # Uplink parameters. Only needed when using uplink on imt
+ uplink:
+ ###########################################################################
+ # Uplink attenuation factor used in link-to-system mapping
+ attenuation_factor : 0.4
+ ###########################################################################
+ # Uplink minimum SINR of the code set [dB]
+ sinr_min : -10
+ ###########################################################################
+ # Uplink maximum SINR of the code set [dB]
+ sinr_max : 22
+ ###########################################################################
+ # Downlink parameters. Only needed when using donwlink on imt
+ downlink:
+ ###########################################################################
+ # Downlink attenuation factor used in link-to-system mapping
+ attenuation_factor : 0.6
+ ###########################################################################
+ # Downlink minimum SINR of the code set [dB]
+ sinr_min : -10
+ ###########################################################################
+ # Downlink maximum SINR of the code set [dB]
+ sinr_max : 30
+ ###########################################################################
+ # Channel parameters
+ # channel model, possible values are "FSPL" (free-space path loss),
+ # "CI" (close-in FS reference distance)
+ # "UMa" (Urban Macro - 3GPP)
+ # "UMi" (Urban Micro - 3GPP)
+ # "TVRO-URBAN"
+ # "TVRO-SUBURBAN"
+ # "ABG" (Alpha-Beta-Gamma)
+ # "P619"
+ channel_model : FSPL
+ ###########################################################################
+ # Adjustment factor for LoS probability in UMi path loss model.
+ # Original value: 18 (3GPP)
+ los_adjustment_factor : 18
+ ###########################################################################
+ # If shadowing should be applied or not
+ shadowing : FALSE
+ noise_temperature : 290
+ param_p619:
+ ###########################################################################
+ # altitude of the space station [m]
+ space_station_alt_m: 540000
+ ###########################################################################
+ # altitude of ES system [m]
+ earth_station_alt_m: 1200
+ ###########################################################################
+ # latitude of ES system [m]
+ earth_station_lat_deg: 13
+ ###########################################################################
+ # difference between longitudes of IMT-NTN station and FSS-ES system [deg]
+ # (positive if space-station is to the East of earth-station)
+ earth_station_long_diff_deg: 10
+fss_ss:
+ ###########################################################################
+ # satellite center frequency [MHz]
+ frequency : 43000
+ ###########################################################################
+ # satellite bandwidth [MHz]
+ bandwidth : 200
+ ###########################################################################
+ # satellite altitude [m] and latitude [deg]
+ altitude : 35780000
+ lat_deg : 0
+ ###########################################################################
+ # Elevation angle [deg]
+ elevation : 270
+ ###########################################################################
+ # Azimuth angle [deg]
+ azimuth : 0
+ ###########################################################################
+ # Peak transmit power spectral density (clear sky) [dBW/Hz]
+ tx_power_density : -5
+ ###########################################################################
+ # System receive noise temperature [K]
+ noise_temperature : 950
+ ###########################################################################
+ # adjacent channel selectivity (dB)
+ adjacent_ch_selectivity : 0
+ ###########################################################################
+ # Satellite peak receive antenna gain [dBi]
+ antenna_gain : 46.6
+ ###########################################################################
+ # Antenna pattern of the FSS space station
+ # Possible values: "ITU-R S.672", "ITU-R S.1528", "FSS_SS", "OMNI"
+ antenna_pattern : FSS_SS
+ ###########################################################################
+ # Paramters for the Antenna ITU-R S.1528
+ antenna_s1528:
+ # Antenna pattern according to ITU-R-S.1528. Possible values are
+ # "ITU-R-S.1528-Section1.2", "ITU-R-S.1528-LEO", "ITU-R-S.1528-Taylor"
+ antenna_pattern: "ITU-R-S.1528-LEO"
+ ###########################################################################
+ # SLR is the side-lobe ratio of the pattern (dB), the difference in gain between the maximum
+ # gain and the gain at the peak of the first side lobe.
+ slr: 21
+ # Number of secondary lobes considered in the diagram (coincide with the roots of the Bessel function)
+ n_side_lobes : 5
+ # Radial and transverse sizes of the effective radiating area of the satellite transmit antenna (m).
+ l_r : 0.4
+ l_t : 0.4
+ # Roll-off factor
+ roll_off : 2
+ # IMT parameters relevant to the satellite system
+ # altitude of IMT system (in meters)
+ # latitude of IMT system (in degrees)
+ # difference between longitudes of IMT and satellite system
+ # (positive if space-station is to the East of earth-station)
+ earth_station_alt_m : 0
+ earth_station_lat_deg : 0
+ earth_station_long_diff_deg : 0
+ season : SUMMER
+ ###########################################################################
+ # Channel parameters
+ # channel model, possible values are "FSPL" (free-space path loss),
+ # "SatelliteSimple" (FSPL + 4 + clutter loss)
+ # "P619"
+ channel_model : P619
+ ###########################################################################
+ # The required near-in-side-lobe level (dB) relative to peak gain
+ # according to ITU-R S.672-4
+ antenna_l_s : -20.1
+ ###########################################################################
+ # 3 dB beamwidth angle (3 dB below maximum gain) [degrees]
+ antenna_3_dB : 0.65
+
+fss_es:
+ ###########################################################################
+ # type of FSS-ES location:
+ # FIXED - position must be given
+ # CELL - random within central cell
+ # NETWORK - random within whole network
+ # UNIFORM_DIST - uniform distance from cluster centre,
+ # between min_dist_to_bs and max_dist_to_bs
+ location : UNIFORM_DIST
+ ###########################################################################
+ # x-y coordinates [m] (only if FIXED location is chosen)
+ x : 10000
+ y : 0
+ ###########################################################################
+ # minimum distance from BSs [m]
+ min_dist_to_bs : 10
+ ###########################################################################
+ # maximum distance from centre BSs [m] (only if UNIFORM_DIST is chosen)
+ max_dist_to_bs : 600
+ ###########################################################################
+ # antenna height [m]
+ height : 6
+ ###########################################################################
+ # Elevation angle [deg], minimum and maximum, values
+ elevation_min : 48
+ elevation_max : 80
+ ###########################################################################
+ # Azimuth angle [deg]
+ # either a specific angle or string 'RANDOM'
+ azimuth : RANDOM
+ ###########################################################################
+ # center frequency [MHz]
+ frequency : 43000
+ ###########################################################################
+ # bandwidth [MHz]
+ bandwidth : 6
+ ###########################################################################
+ # System receive noise temperature [K]
+ noise_temperature : 950
+ ###########################################################################
+ # adjacent channel selectivity (dB)
+ adjacent_ch_selectivity : 0
+ ###########################################################################
+ # Peak transmit power spectral density (clear sky) [dBW/Hz]
+ tx_power_density : -68.3
+ ###########################################################################
+ # antenna peak gain [dBi]
+ antenna_gain : 32
+ ###########################################################################
+ # Antenna pattern of the FSS Earth station
+ # Possible values: "ITU-R S.1855", "ITU-R S.465", "ITU-R S.580", "OMNI",
+ # "Modified ITU-R S.465"
+ antenna_pattern : Modified ITU-R S.465
+ ###########################################################################
+ # Diameter of antenna [m]
+ diameter : 1.8
+ ###########################################################################
+ # Antenna envelope gain (dBi) - only relevant for "Modified ITU-R S.465" model
+ antenna_envelope_gain : 0
+ ###########################################################################
+ # Channel parameters
+ # channel model, possible values are "FSPL" (free-space path loss),
+ # "TerrestrialSimple" (FSPL + clutter loss)
+ # "P452"
+ # "TVRO-URBAN"
+ # "TVRO-SUBURBAN"
+ # "HDFSS"
+ channel_model : P452
+ ###########################################################################
+ # Constants
+ BOLTZMANN_CONSTANT : 1.38064852e-23
+ EARTH_RADIUS : 6371000
+ ###########################################################################
+ # P452 parameters
+ ###########################################################################
+ # Total air pressure in hPa
+ atmospheric_pressure : 935
+ ###########################################################################
+ # Temperature in Kelvin
+ air_temperature : 300
+ ###########################################################################
+ #Sea-level surface refractivity (use the map)
+ N0 : 352.58
+ ###########################################################################
+ #Average radio-refractive (use the map)
+ delta_N : 43.127
+ ###########################################################################
+ #percentage p. Float (0 to 100) or RANDOM
+ percentage_p : 0.2
+ ###########################################################################
+ #Distance over land from the transmit and receive antennas to the coast (km)
+ Dct : 70
+ ###########################################################################
+ #Distance over land from the transmit and receive antennas to the coast (km)
+ Dcr : 70
+ ###########################################################################
+ ##Effective height of interfering antenna (m)
+ Hte : 20
+ ###########################################################################
+ #Effective height of interfered-with antenna (m)
+ Hre : 3
+ ###########################################################################
+ ##Latitude of transmitter
+ tx_lat : -23.55028
+ ###########################################################################
+ #Latitude of receiver
+ rx_lat : -23.17889
+ ###########################################################################
+ #Antenna polarization
+ polarization : horizontal
+ ###########################################################################
+ #determine whether clutter loss following ITU-R P.2108 is added (TRUE/FALSE)
+ clutter_loss : TRUE
+ ###########################################################################
+ # HDFSS propagation parameters
+ ###########################################################################
+ # HDFSS position relative to building it is on. Possible values are
+ # ROOFTOP and BUILDINGSIDE
+ es_position : ROOFTOP
+ ###########################################################################
+ # Enable shadowing loss
+ shadow_enabled : TRUE
+ ###########################################################################
+ # Enable building entry loss
+ building_loss_enabled : TRUE
+ ###########################################################################
+ # Enable interference from IMT stations at the same building as the HDFSS
+ same_building_enabled : FALSE
+ ###########################################################################
+ # Enable diffraction loss
+ diffraction_enabled : FALSE
+ ###########################################################################
+ # Building entry loss type applied between BSs and HDFSS ES. Options are:
+ # P2109_RANDOM: random probability at P.2109 model, considering elevation
+ # P2109_FIXED: fixed probability at P.2109 model, considering elevation.
+ # Probability must be specified in bs_building_entry_loss_prob.
+ # FIXED_VALUE: fixed value per BS. Value must be specified in
+ # bs_building_entry_loss_value.
+ bs_building_entry_loss_type : P2109_FIXED
+ ###########################################################################
+ # Probability of building entry loss not exceeded if
+ # bs_building_entry_loss_type = P2109_FIXED
+ bs_building_entry_loss_prob : 0.75
+ ###########################################################################
+ # Value in dB of building entry loss if
+ # bs_building_entry_loss_type = FIXED_VALUE
+ bs_building_entry_loss_value : 35
+fs:
+ ###########################################################################
+ # x-y coordinates [m]
+ x : 1000
+ y : 0
+ ###########################################################################
+ # antenna height [m]
+ height : 15
+ ###########################################################################
+ # Elevation angle [deg]
+ elevation : -10
+ ###########################################################################
+ # Azimuth angle [deg]
+ azimuth : 180
+ ###########################################################################
+ # center frequency [MHz]
+ frequency : 27250
+ ###########################################################################
+ # bandwidth [MHz]
+ bandwidth : 112
+ ###########################################################################
+ # System receive noise temperature [K]
+ noise_temperature : 290
+ ###########################################################################
+ # adjacent channel selectivity (dB)
+ adjacent_ch_selectivity : 20
+ ###########################################################################
+ # Peak transmit power spectral density (clear sky) [dBW/Hz]
+ tx_power_density : -68.3
+ ###########################################################################
+ # antenna peak gain [dBi]
+ antenna_gain : 36.9
+ ###########################################################################
+ # Antenna pattern of the fixed wireless service
+ # Possible values: "ITU-R F.699", "OMNI"
+ antenna_pattern : OMNI
+ ###########################################################################
+ # Diameter of antenna [m]
+ diameter : 0.3
+ ###########################################################################
+ # Channel parameters
+ # channel model, possible values are "FSPL" (free-space path loss),
+ # "TerrestrialSimple" (FSPL + clutter loss)
+ channel_model : TerrestrialSimple
+haps:
+ ###########################################################################
+ # HAPS center frequency [MHz]
+ frequency : 27251.1
+ ###########################################################################
+ # HAPS bandwidth [MHz]
+ bandwidth : 200
+ ###########################################################################
+ # HAPS altitude [m] and latitude [deg]
+ altitude : 20001.1
+ lat_deg : 0.1
+ ###########################################################################
+ # Elevation angle [deg]
+ elevation : 270
+ ###########################################################################
+ # Azimuth angle [deg]
+ azimuth : 0
+ ###########################################################################
+ # EIRP spectral density [dBW/MHz]
+ eirp_density : 4.4
+ ###########################################################################
+ # HAPS peak antenna gain [dBi]
+ antenna_gain : 28.1
+ ###########################################################################
+ # Adjacent channel selectivity [dB]
+ acs : 30
+ ###########################################################################
+ # Antenna pattern of the HAPS (airbone) station
+ # Possible values: "ITU-R F.1891", "OMNI"
+ antenna_pattern : OMNI
+ # IMT parameters relevant to the HAPS system
+ # altitude of IMT system (in meters)
+ # latitude of IMT system (in degrees)
+ # difference between longitudes of IMT and satellite system
+ # (positive if space-station is to the East of earth-station)
+ earth_station_alt_m : 0
+ earth_station_lat_deg : 0
+ earth_station_long_diff_deg : 0
+ season : SUMMER
+ ###########################################################################
+ # Channel parameters
+ # channel model, possible values are "FSPL" (free-space path loss),
+ # "SatelliteSimple" (FSPL + 4 + clutter loss)
+ # "P619"
+ channel_model : P619
+ ###########################################################################
+ # Near side-lobe level (dB) relative to the peak gain required by the system
+ # design, and has a maximum value of โ25 dB
+ antenna_l_n : -25
+ ###########################################################################
+ # Constants
+ BOLTZMANN_CONSTANT : 1.38064852e-23
+ EARTH_RADIUS : 6371000
+rns:
+ ###########################################################################
+ # x-y coordinates [m]
+ x : 660.1
+ y : -370.1
+ ###########################################################################
+ # altitude [m]
+ altitude : 150.1
+ ###########################################################################
+ # center frequency [MHz]
+ frequency : 32000.1
+ ###########################################################################
+ # bandwidth [MHz]
+ bandwidth : 60.1
+ ###########################################################################
+ # System receive noise temperature [K]
+ noise_temperature : 1154.1
+ ###########################################################################
+ # Peak transmit power spectral density (clear sky) [dBW/Hz]
+ tx_power_density : -70.79
+ ###########################################################################
+ # antenna peak gain [dBi]
+ antenna_gain : 30.1
+ ###########################################################################
+ # Adjacent channel selectivity [dB]
+ acs : 30.1
+ ###########################################################################
+ # Antenna pattern of the fixed wireless service
+ # Possible values: "ITU-R M.1466", "OMNI"
+ antenna_pattern : ITU-R M.1466
+ ###########################################################################
+ # Channel parameters
+ # channel model, possible values are "FSPL" (free-space path loss),
+ # "SatelliteSimple" (FSPL + 4 dB + clutter loss)
+ # "P619"
+ channel_model : P619
+ ###########################################################################
+ # Specific parameters for P619
+ season : SUMMER
+ earth_station_alt_m : 0
+ earth_station_lat_deg : 0
+ras:
+ ###########################################################################
+ # frequency [MHz]
+ frequency: 2695
+ ###########################################################################
+ # bandwidth [MHz]
+ bandwidth: 10
+ ###########################################################################
+ # Station noise temperature [K]
+ noise_temperature: 90
+ ###########################################################################
+ # Peak transmit power spectral density (clear sky) [dBW/Hz]
+ tx_power_density: 0
+ # Adjacent channel selectivity [dB]
+ adjacent_ch_selectivity: 20.1
+ geometry:
+ ###########################################################################
+ # Antenna height [meters]
+ height: 15
+ ###########################################################################
+ # Azimuth angle [degrees]
+ azimuth:
+ type: FIXED
+ fixed: -90
+ ###########################################################################
+ # Elevation angle [degrees]
+ elevation:
+ type: FIXED
+ fixed: 45
+ ###########################################################################
+ # Station 2d location [meters]:
+ location:
+ ###########################################################################
+ type: FIXED
+ fixed:
+ ###########################################################################
+ x: 0
+ ###########################################################################
+ y: 0
+ antenna:
+ pattern: OMNI
+ gain: 0.5
+ channel_model: P452
+
+ param_p619:
+ space_station_alt_m: 20000.0
+ # Enter the RAS antenna heigth above sea level
+ earth_station_alt_m: 15
+ # The RAS station lat
+ earth_station_lat_deg: -23.17889
+ # This parameter is ignored as it will be calculated from x,y positions in run time
+ earth_station_long_diff_deg: 0.0
+
+ season: SUMMER
+eess_passive:
+ ###########################################################################
+ # sensor center frequency [MHz]
+ frequency : 23900.1
+ ###########################################################################
+ # sensor bandwidth [MHz]
+ bandwidth : 200.1
+ ###########################################################################
+ # Off-nadir pointing angle [deg]
+ nadir_angle : 46.6
+ ###########################################################################
+ # sensor altitude [m]
+ altitude : 828000.1
+ ###########################################################################
+ # Antenna pattern of the sensor
+ # Possible values: "ITU-R RS.1813"
+ # "ITU-R RS.1861 9a"
+ # "ITU-R RS.1861 9b"
+ # "ITU-R RS.1861 9c"
+ # "OMNI"
+ antenna_pattern : ITU-R RS.1813
+ # Antenna efficiency for pattern described in ITU-R RS.1813 [0-1]
+ antenna_efficiency : 0.6
+ # Antenna diameter for ITU-R RS.1813 [m]
+ antenna_diameter : 2.2
+ ###########################################################################
+ # receive antenna gain - applicable for 9a, 9b and OMNI [dBi]
+ antenna_gain : 52.1
+ ###########################################################################
+ # Channel parameters
+ # channel model, possible values are "FSPL" (free-space path loss),
+ # "P619"
+ channel_model : FSPL
+ # Relevant IMT parameters which apply for ITU-R P.619
+ # altitude of IMT system (in meters)
+ # latitude of IMT system (in degrees)
+ # season of the year: "SUMMER", "WINTER"
+ earth_station_alt_m : 20.1
+ earth_station_lat_deg : -22.9
+ season : WINTER
+ ###########################################################################
+ # Constants
+ BOLTZMANN_CONSTANT : 1.38064852e-23
+ EARTH_RADIUS : 6371000
+
+single_earth_station:
+ ###########################################################################
+ # Sensor center frequency [MHz]
+ frequency: 8250
+ ###########################################################################
+ # Sensor bandwidth [MHz]
+ bandwidth: 100
+ ###########################################################################
+ # System receive noise temperature [K]
+ noise_temperature: 300
+ ###########################################################################
+ # Peak transmit power spectral density (clear sky) [dBW/Hz]
+ tx_power_density: -65
+ # Adjacent channel selectivity [dB]
+ adjacent_ch_selectivity: 20.0
+ geometry:
+ ###########################################################################
+ # Antenna height [meters]
+ height: 6
+ ###########################################################################
+ # Azimuth angle [degrees]
+ azimuth:
+ ###########################################################################
+ # Type of azimuth. May be "UNIFORM_DIST", "FIXED"
+ type: FIXED
+ ###########################################################################
+ # Value of azimuth when type == "FIXED" [deg]
+ fixed: 0
+ ###########################################################################
+ # Limits of random uniform distribution when type == "UNIFORM_DIST"
+ uniform_dist:
+ ###########################################################################
+ # uniform distribution lower bound [deg]
+ min: -180
+ ###########################################################################
+ # uniform distribution upper bound [deg]
+ max: 180
+ ###########################################################################
+ # Elevation angle [degrees]
+ elevation:
+ # Type of elevation. May be "UNIFORM_DIST", "FIXED"
+ type: FIXED
+ # Value of elevation when type == "FIXED" [deg]
+ fixed: 60
+ # Limits of random uniform distribution when type == "UNIFORM_DIST"
+ uniform_dist:
+ # uniform distribution lower bound [deg]
+ min: 30
+ # uniform distribution upper bound [deg]
+ max: 65
+ ###########################################################################
+ # Station 2d location [meters]:
+ location:
+ ###########################################################################
+ # choose way to set location. May be "CELL", "NETWORK", "UNIFORM_DIST" or "FIXED"
+ # location.type == CELL means that the ES will be distributed randomly,
+ # but always in the central cell
+ # location.type == NETWORK means that the ES will be distributed randomly,
+ # in a random cell
+ # location.type == UNIFORM_DIST means that the ES will be distributed randomly,
+ # in a ring shaped section with delimited outer and inner radius
+ # location.type == FIXED means that the ES will be always at SAME fixed location
+ type: CELL
+ ###########################################################################
+ # Value of position (x,y) when type == "FIXED" [(m, m)]
+ fixed:
+ x: 10
+ y: 100
+ cell:
+ ###########################################################################
+ # Minimum distance to IMT BS when location.type == CELL [m]
+ min_dist_to_bs: 100
+ network:
+ ###########################################################################
+ # Minimum distance to IMT BS when location.type == NETWORK [m]
+ min_dist_to_bs: 150
+ uniform_dist:
+ ###########################################################################
+ # Ring inner radius [m]
+ min_dist_to_center: 101
+ ###########################################################################
+ # Ring outer radius [m]
+ max_dist_to_center: 102
+ antenna:
+ ###########################################################################
+ # Choose the antenna pattern. Can be one of:
+ # "OMNI", "ITU-R F.699", "ITU-R S.465", "ITU-R S.580", "MODIFIED ITU-R S.465", "ITU-R S.1855"
+ pattern: ITU-R S.465
+ ###########################################################################
+ # Earth station peak receive antenna gain [dBi]
+ gain: 28
+ itu_r_f_699:
+ ###########################################################################
+ # Antenna diameter [m]
+ diameter: 1.1
+ itu_r_s_465:
+ ###########################################################################
+ # Antenna diameter [m]
+ diameter: 1.1
+ itu_r_s_580:
+ ###########################################################################
+ # Antenna diameter [m]
+ diameter: 1.1
+ itu_r_s_1855:
+ ###########################################################################
+ # Antenna diameter [m]
+ diameter: 1.1
+ itu_r_s_465_modified:
+ ###########################################################################
+ # Antenna envelope gain [dBi]
+ envelope_gain: -4
+ ###########################################################################
+ # Selected channel model
+ # Possible values are "P619", "P452", "TerrestrialSimple"
+ channel_model: "P619"
+
+ ###########################################################################
+ # Parameters for P619 channel model
+ param_p619:
+ ###########################################################################
+ # altitude of the space station [m]
+ space_station_alt_m: 540000
+ ###########################################################################
+ # altitude of ES system [m]
+ earth_station_alt_m: 1200
+ ###########################################################################
+ # latitude of ES system [m]
+ earth_station_lat_deg: 13
+ ###########################################################################
+ # difference between longitudes of IMT-NTN station and FSS-ES system [deg]
+ # (positive if space-station is to the East of earth-station)
+ earth_station_long_diff_deg: 10
+
+ ###########################################################################
+ # season - season of the year.
+ # Only actually useful for P619, but we can't put it inside param_p619 without changing more code
+ season: SUMMER
+
+ ###########################################################################
+ # Parameters for P452 channel model
+ param_p452:
+ ###########################################################################
+ # Total air pressure [hPa]
+ atmospheric_pressure: 1
+ ###########################################################################
+ # Temperature [K]
+ air_temperature: 2
+ ###########################################################################
+ # Sea-level surface refractivity (use the map)
+ N0: 3
+ ###########################################################################
+ # Average radio-refractive (use the map)
+ delta_N: 4
+ ###########################################################################
+ # percentage p. Float (0 to 100) or RANDOM
+ percentage_p: 5
+ ###########################################################################
+ # Distance over land from the transmit and receive antennas to the coast (km)
+ Dct: 6
+ ###########################################################################
+ # Distance over land from the transmit and receive antennas to the coast (km)
+ Dcr: 7
+ ###########################################################################
+ # Effective height of interfering antenna (m)
+ Hte: 8
+ ###########################################################################
+ # Effective height of interfered-with antenna (m)
+ Hre: 9
+ ###########################################################################
+ # Latitude of transmitter
+ tx_lat: 10
+ ###########################################################################
+ # Latitude of receiver
+ rx_lat: 11
+ ###########################################################################
+ # Antenna polarization. Possible values are "horizontal", "vertical"
+ polarization: horizontal
+ ###########################################################################
+ # determine whether clutter loss following ITU-R P.2108 is added (TRUE/FALSE)
+ clutter_loss: TRUE
+
+ # HDFSS propagation parameters
+ param_hdfss:
+ ###########################################################################
+ # HDFSS position relative to building it is on. Possible values are
+ # ROOFTOP and BUILDINGSIDE
+ es_position: BUILDINGSIDE
+ ###########################################################################
+ # Enable shadowing loss
+ shadow_enabled: FALSE
+ ###########################################################################
+ # Enable building entry loss
+ building_loss_enabled: FALSE
+ ###########################################################################
+ # Enable interference from IMT stations at the same building as the HDFSS
+ same_building_enabled: TRUE
+ ###########################################################################
+ # Enable diffraction loss
+ diffraction_enabled: FALSE
+ ###########################################################################
+ # Building entry loss type applied between BSs and HDFSS ES. Options are:
+ # P2109_RANDOM: random probability at P.2109 model, considering elevation
+ # P2109_FIXED: fixed probability at P.2109 model, considering elevation.
+ # Probability must be specified in bs_building_entry_loss_prob.
+ # FIXED_VALUE: fixed value per BS. Value must be specified in
+ # bs_building_entry_loss_value.
+ bs_building_entry_loss_type: FIXED_VALUE
+ ###########################################################################
+ # Probability of building entry loss not exceeded if
+ # bs_building_entry_loss_type = P2109_FIXED
+ bs_building_entry_loss_prob: 0.19
+ ###########################################################################
+ # Value in dB of building entry loss if
+ # bs_building_entry_loss_type = FIXED_VALUE
+ bs_building_entry_loss_value: 47
diff --git a/tests/parameters/test_parameters.py b/tests/parameters/test_parameters.py
new file mode 100644
index 000000000..04af455e3
--- /dev/null
+++ b/tests/parameters/test_parameters.py
@@ -0,0 +1,454 @@
+from pathlib import Path
+import unittest
+from sharc.parameters.parameters import Parameters
+import numpy as np
+
+
+class ParametersTest(unittest.TestCase):
+ """Run Parameter class tests.
+ """
+
+ def setUp(self):
+ self.parameters = Parameters()
+ param_file = Path(__file__).parent.resolve() / \
+ 'parameters_for_testing.yaml'
+ self.parameters.set_file_name(param_file)
+ self.parameters.read_params()
+
+ def test_parameters_imt(self):
+ """Unit test for ParametersIMT
+ """
+ self.assertEqual(self.parameters.imt.topology.type, "INDOOR")
+ self.assertEqual(
+ self.parameters.imt.minimum_separation_distance_bs_ue, 1.3)
+ self.assertEqual(self.parameters.imt.interfered_with, False)
+ self.assertEqual(self.parameters.imt.frequency, 24360)
+ self.assertEqual(self.parameters.imt.bandwidth, 200.5)
+ self.assertEqual(self.parameters.imt.rb_bandwidth, 0.181)
+ self.assertEqual(self.parameters.imt.spectral_mask, "3GPP E-UTRA")
+ self.assertEqual(self.parameters.imt.spurious_emissions, -13.1)
+ self.assertEqual(self.parameters.imt.guard_band_ratio, 0.14)
+
+ self.assertEqual(self.parameters.imt.bs.load_probability, 0.2)
+ self.assertEqual(self.parameters.imt.bs.conducted_power, 11.1)
+ self.assertEqual(self.parameters.imt.bs.height, 6.1)
+ self.assertEqual(self.parameters.imt.bs.noise_figure, 10.1)
+ self.assertEqual(self.parameters.imt.bs.ohmic_loss, 3.1)
+ self.assertEqual(self.parameters.imt.uplink.attenuation_factor, 0.4)
+ self.assertEqual(self.parameters.imt.uplink.sinr_min, -10.0)
+ self.assertEqual(self.parameters.imt.uplink.sinr_max, 22.0)
+ self.assertEqual(self.parameters.imt.ue.k, 3)
+ self.assertEqual(self.parameters.imt.ue.k_m, 1)
+ self.assertEqual(self.parameters.imt.ue.indoor_percent, 5.0)
+ self.assertEqual(
+ self.parameters.imt.ue.distribution_type,
+ "ANGLE_AND_DISTANCE")
+ self.assertEqual(
+ self.parameters.imt.ue.distribution_distance,
+ "UNIFORM")
+ self.assertEqual(self.parameters.imt.ue.azimuth_range, (-70, 90))
+ self.assertEqual(self.parameters.imt.ue.tx_power_control, True)
+ self.assertEqual(self.parameters.imt.ue.p_o_pusch, -95.0)
+ self.assertEqual(self.parameters.imt.ue.alpha, 1.0)
+ self.assertEqual(self.parameters.imt.ue.p_cmax, 22.0)
+ self.assertEqual(self.parameters.imt.ue.power_dynamic_range, 63.0)
+ self.assertEqual(self.parameters.imt.ue.height, 1.5)
+ self.assertEqual(self.parameters.imt.ue.noise_figure, 10.0)
+ self.assertEqual(self.parameters.imt.ue.ohmic_loss, 3.0)
+ self.assertEqual(self.parameters.imt.ue.body_loss, 4.0)
+ self.assertEqual(self.parameters.imt.downlink.attenuation_factor, 0.6)
+ self.assertEqual(self.parameters.imt.downlink.sinr_min, -10.0)
+ self.assertEqual(self.parameters.imt.downlink.sinr_max, 30.0)
+ self.assertEqual(self.parameters.imt.channel_model, "FSPL")
+ self.assertEqual(self.parameters.imt.los_adjustment_factor, 18.0)
+ self.assertEqual(self.parameters.imt.shadowing, False)
+
+ """Test ParametersImtAntenna parameters
+ """
+ self.assertEqual(
+ self.parameters.imt.adjacent_antenna_model,
+ "BEAMFORMING")
+ self.assertEqual(self.parameters.imt.bs.antenna.normalization, False)
+ self.assertEqual(self.parameters.imt.ue.antenna.normalization, False)
+ self.assertEqual(self.parameters.imt.bs.antenna.normalization_file,
+ "antenna/beamforming_normalization/bs_norm.npz")
+ self.assertEqual(self.parameters.imt.ue.antenna.normalization_file,
+ "antenna/beamforming_normalization/ue_norm.npz")
+ self.assertEqual(
+ self.parameters.imt.bs.antenna.element_pattern,
+ "F1336")
+ self.assertEqual(
+ self.parameters.imt.ue.antenna.element_pattern,
+ "F1336")
+ self.assertEqual(
+ self.parameters.imt.bs.antenna.minimum_array_gain, -200)
+ self.assertEqual(
+ self.parameters.imt.ue.antenna.minimum_array_gain, -200)
+ self.assertEqual(self.parameters.imt.bs.antenna.downtilt, 6)
+ self.assertEqual(self.parameters.imt.bs.antenna.element_max_g, 5)
+ self.assertEqual(self.parameters.imt.ue.antenna.element_max_g, 5)
+ self.assertEqual(self.parameters.imt.bs.antenna.element_phi_3db, 65)
+ self.assertEqual(self.parameters.imt.ue.antenna.element_phi_3db, 90)
+ self.assertEqual(self.parameters.imt.bs.antenna.element_theta_3db, 65)
+ self.assertEqual(self.parameters.imt.ue.antenna.element_theta_3db, 90)
+ self.assertEqual(self.parameters.imt.bs.antenna.n_rows, 8)
+ self.assertEqual(self.parameters.imt.ue.antenna.n_rows, 4)
+ self.assertEqual(self.parameters.imt.bs.antenna.n_columns, 8)
+ self.assertEqual(self.parameters.imt.ue.antenna.n_columns, 4)
+ self.assertEqual(
+ self.parameters.imt.bs.antenna.element_horiz_spacing, 0.5)
+ self.assertEqual(
+ self.parameters.imt.ue.antenna.element_horiz_spacing, 0.5)
+ self.assertEqual(
+ self.parameters.imt.bs.antenna.element_vert_spacing, 0.5)
+ self.assertEqual(
+ self.parameters.imt.ue.antenna.element_vert_spacing, 0.5)
+ self.assertEqual(self.parameters.imt.bs.antenna.element_am, 30)
+ self.assertEqual(self.parameters.imt.ue.antenna.element_am, 25)
+ self.assertEqual(self.parameters.imt.bs.antenna.element_sla_v, 30)
+ self.assertEqual(self.parameters.imt.ue.antenna.element_sla_v, 25)
+ self.assertEqual(
+ self.parameters.imt.bs.antenna.multiplication_factor, 12)
+ self.assertEqual(
+ self.parameters.imt.ue.antenna.multiplication_factor, 12)
+
+ """Test ParametersHotspot
+ """
+ self.assertEqual(self.parameters.imt.topology.hotspot.num_hotspots_per_cell, 1)
+ self.assertEqual(self.parameters.imt.topology.hotspot.max_dist_hotspot_ue, 99.9)
+ self.assertEqual(self.parameters.imt.topology.hotspot.min_dist_bs_hotspot, 1.2)
+ self.assertEqual(self.parameters.imt.topology.hotspot.intersite_distance, 321)
+ self.assertEqual(self.parameters.imt.topology.hotspot.num_clusters, 7)
+ self.assertEqual(self.parameters.imt.topology.hotspot.wrap_around, True)
+
+ """Test ParametersMacrocell
+ """
+ self.assertEqual(self.parameters.imt.topology.macrocell.intersite_distance, 543)
+ self.assertEqual(self.parameters.imt.topology.macrocell.num_clusters, 7)
+ self.assertEqual(self.parameters.imt.topology.macrocell.wrap_around, True)
+
+ """Test ParametersSingleBaseStation
+ """
+ self.assertEqual(self.parameters.imt.topology.single_bs.cell_radius, 543)
+ self.assertEqual(self.parameters.imt.topology.single_bs.intersite_distance,
+ self.parameters.imt.topology.single_bs.cell_radius * 3 / 2)
+ self.assertEqual(self.parameters.imt.topology.single_bs.num_clusters, 2)
+
+ """Test ParametersIndoor
+ """
+ self.assertEqual(self.parameters.imt.topology.indoor.basic_path_loss, "FSPL")
+ self.assertEqual(self.parameters.imt.topology.indoor.n_rows, 3)
+ self.assertEqual(self.parameters.imt.topology.indoor.n_colums, 2)
+ self.assertEqual(self.parameters.imt.topology.indoor.num_imt_buildings, 2)
+ self.assertEqual(self.parameters.imt.topology.indoor.street_width, 30.1)
+ self.assertEqual(self.parameters.imt.topology.indoor.intersite_distance, 40.1)
+ self.assertEqual(self.parameters.imt.topology.indoor.num_cells, 3)
+ self.assertEqual(self.parameters.imt.topology.indoor.num_floors, 1)
+ self.assertEqual(self.parameters.imt.topology.indoor.ue_indoor_percent, .95)
+ self.assertEqual(
+ self.parameters.imt.topology.indoor.building_class,
+ "THERMALLY_EFFICIENT")
+
+ self.assertEqual(self.parameters.imt.topology.ntn.bs_height, self.parameters.imt.bs.height)
+ self.assertEqual(self.parameters.imt.topology.ntn.cell_radius, 123)
+ self.assertEqual(self.parameters.imt.topology.ntn.intersite_distance,
+ self.parameters.imt.topology.ntn.cell_radius * np.sqrt(3))
+ self.assertEqual(self.parameters.imt.topology.ntn.bs_azimuth, 45)
+ self.assertEqual(self.parameters.imt.topology.ntn.bs_elevation, 45)
+ self.assertEqual(self.parameters.imt.topology.ntn.num_sectors, 19)
+
+ def test_parameters_fss_ss(self):
+ """Test ParametersFssSs
+ """
+ self.assertEqual(self.parameters.fss_ss.frequency, 43000.0)
+ self.assertEqual(self.parameters.fss_ss.bandwidth, 200.0)
+ self.assertEqual(self.parameters.fss_ss.tx_power_density, -5.0)
+ self.assertEqual(self.parameters.fss_ss.altitude, 35780000.0)
+ self.assertEqual(self.parameters.fss_ss.lat_deg, 0.0)
+ self.assertEqual(self.parameters.fss_ss.elevation, 270.0)
+ self.assertEqual(self.parameters.fss_ss.azimuth, 0.0)
+ self.assertEqual(self.parameters.fss_ss.noise_temperature, 950.0)
+ self.assertEqual(self.parameters.fss_ss.adjacent_ch_selectivity, 0.0)
+ self.assertEqual(self.parameters.fss_ss.antenna_gain, 46.6)
+ self.assertEqual(self.parameters.fss_ss.antenna_pattern, "FSS_SS")
+ self.assertEqual(self.parameters.fss_ss.earth_station_alt_m, 0.0)
+ self.assertEqual(self.parameters.fss_ss.earth_station_lat_deg, 0.0)
+ self.assertEqual(
+ self.parameters.fss_ss.earth_station_long_diff_deg, 0.0)
+ self.assertEqual(self.parameters.fss_ss.season, "SUMMER")
+ self.assertEqual(self.parameters.fss_ss.channel_model, "P619")
+ self.assertEqual(self.parameters.fss_ss.antenna_l_s, -20.1)
+ self.assertEqual(self.parameters.fss_ss.antenna_3_dB, 0.65)
+
+ self.assertEqual(self.parameters.fss_ss.antenna_s1528.antenna_pattern, "ITU-R-S.1528-LEO")
+ self.assertEqual(self.parameters.fss_ss.antenna_s1528.slr, 21)
+ self.assertEqual(self.parameters.fss_ss.antenna_s1528.antenna_l_s, -20.1)
+ self.assertEqual(self.parameters.fss_ss.antenna_s1528.n_side_lobes, 5)
+ self.assertEqual(self.parameters.fss_ss.antenna_s1528.l_r, .4)
+ self.assertEqual(self.parameters.fss_ss.antenna_s1528.l_t, .4)
+ self.assertEqual(self.parameters.fss_ss.antenna_s1528.roll_off, 2)
+
+ def test_parameters_fss_es(self):
+ """Test ParametersFssEs
+ """
+ self.assertEqual(self.parameters.fss_es.location, "UNIFORM_DIST")
+ self.assertEqual(self.parameters.fss_es.x, 10000)
+ self.assertEqual(self.parameters.fss_es.y, 0)
+ self.assertEqual(self.parameters.fss_es.min_dist_to_bs, 10)
+ self.assertEqual(self.parameters.fss_es.max_dist_to_bs, 600)
+ self.assertEqual(self.parameters.fss_es.height, 6)
+ self.assertEqual(self.parameters.fss_es.elevation_min, 48)
+ self.assertEqual(self.parameters.fss_es.elevation_max, 80)
+ self.assertEqual(self.parameters.fss_es.azimuth, "RANDOM")
+ self.assertEqual(self.parameters.fss_es.frequency, 43000)
+ self.assertEqual(self.parameters.fss_es.bandwidth, 6)
+ self.assertEqual(self.parameters.fss_es.adjacent_ch_selectivity, 0)
+ self.assertEqual(self.parameters.fss_es.tx_power_density, -68.3)
+ self.assertEqual(self.parameters.fss_es.noise_temperature, 950)
+ self.assertEqual(self.parameters.fss_es.antenna_gain, 32)
+ self.assertEqual(
+ self.parameters.fss_es.antenna_pattern,
+ "Modified ITU-R S.465")
+ self.assertEqual(self.parameters.fss_es.antenna_envelope_gain, 0)
+ self.assertEqual(self.parameters.fss_es.diameter, 1.8)
+ self.assertEqual(self.parameters.fss_es.channel_model, "P452")
+ self.assertEqual(self.parameters.fss_es.atmospheric_pressure, 935)
+ self.assertEqual(self.parameters.fss_es.air_temperature, 300)
+ self.assertEqual(self.parameters.fss_es.N0, 352.58)
+ self.assertEqual(self.parameters.fss_es.delta_N, 43.127)
+ self.assertEqual(self.parameters.fss_es.percentage_p, 0.2)
+ self.assertEqual(self.parameters.fss_es.Dct, 70)
+ self.assertEqual(self.parameters.fss_es.Dcr, 70)
+ self.assertEqual(self.parameters.fss_es.Hte, 20)
+ self.assertEqual(self.parameters.fss_es.Hre, 3)
+ self.assertEqual(self.parameters.fss_es.tx_lat, -23.55028)
+ self.assertEqual(self.parameters.fss_es.rx_lat, -23.17889)
+ self.assertEqual(self.parameters.fss_es.polarization, "horizontal")
+ self.assertEqual(self.parameters.fss_es.clutter_loss, True)
+ self.assertEqual(self.parameters.fss_es.es_position, "ROOFTOP")
+ self.assertEqual(self.parameters.fss_es.shadow_enabled, True)
+ self.assertEqual(self.parameters.fss_es.building_loss_enabled, True)
+ self.assertEqual(self.parameters.fss_es.same_building_enabled, False)
+ self.assertEqual(self.parameters.fss_es.diffraction_enabled, False)
+ self.assertEqual(
+ self.parameters.fss_es.bs_building_entry_loss_type,
+ "P2109_FIXED")
+ self.assertEqual(
+ self.parameters.fss_es.bs_building_entry_loss_prob, 0.75)
+ self.assertEqual(
+ self.parameters.fss_es.bs_building_entry_loss_value, 35.0)
+
+ def test_parameters_fs(self):
+ """Test ParametersFs
+ """
+ self.assertEqual(self.parameters.fs.x, 1000.0)
+ self.assertEqual(self.parameters.fs.y, 0.0)
+ self.assertEqual(self.parameters.fs.height, 15.0)
+ self.assertEqual(self.parameters.fs.elevation, -10.0)
+ self.assertEqual(self.parameters.fs.azimuth, 180.0)
+ self.assertEqual(self.parameters.fs.frequency, 27250.0)
+ self.assertEqual(self.parameters.fs.bandwidth, 112.0)
+ self.assertEqual(self.parameters.fs.noise_temperature, 290.0)
+ self.assertEqual(self.parameters.fs.adjacent_ch_selectivity, 20.0)
+ self.assertEqual(self.parameters.fs.tx_power_density, -68.3)
+ self.assertEqual(self.parameters.fs.antenna_gain, 36.9)
+ self.assertEqual(self.parameters.fs.antenna_pattern, "OMNI")
+ self.assertEqual(self.parameters.fs.diameter, 0.3)
+ self.assertEqual(self.parameters.fs.channel_model, "TerrestrialSimple")
+
+ def test_parameters_haps(self):
+ """Test ParametersHaps
+ """
+ self.assertEqual(self.parameters.haps.frequency, 27251.1)
+ self.assertEqual(self.parameters.haps.bandwidth, 200.0)
+ self.assertEqual(self.parameters.haps.antenna_gain, 28.1)
+ self.assertEqual(self.parameters.haps.eirp_density, 4.4)
+ self.assertEqual(self.parameters.haps.tx_power_density,
+ self.parameters.haps.eirp_density - self.parameters.haps.antenna_gain - 60)
+ self.assertEqual(self.parameters.haps.altitude, 20001.1)
+ self.assertEqual(self.parameters.haps.lat_deg, 0.1)
+ self.assertEqual(self.parameters.haps.elevation, 270.0)
+ self.assertEqual(self.parameters.haps.azimuth, 0)
+ self.assertEqual(self.parameters.haps.antenna_pattern, "OMNI")
+ self.assertEqual(self.parameters.haps.earth_station_alt_m, 0.0)
+ self.assertEqual(self.parameters.haps.earth_station_lat_deg, 0.0)
+ self.assertEqual(self.parameters.haps.earth_station_long_diff_deg, 0.0)
+ self.assertEqual(self.parameters.haps.season, "SUMMER")
+ self.assertEqual(self.parameters.haps.acs, 30.0)
+ self.assertEqual(self.parameters.haps.channel_model, "P619")
+ self.assertEqual(self.parameters.haps.antenna_l_n, -25)
+
+ def test_paramters_rns(self):
+ """Test ParametersRns
+ """
+ self.assertEqual(self.parameters.rns.x, 660.1)
+ self.assertEqual(self.parameters.rns.y, -370.1)
+ self.assertEqual(self.parameters.rns.altitude, 150.1)
+ self.assertEqual(self.parameters.rns.frequency, 32000.1)
+ self.assertEqual(self.parameters.rns.bandwidth, 60.1)
+ self.assertEqual(self.parameters.rns.noise_temperature, 1154.1)
+ self.assertEqual(self.parameters.rns.tx_power_density, -70.79)
+ self.assertEqual(self.parameters.rns.antenna_gain, 30.1)
+ self.assertEqual(self.parameters.rns.antenna_pattern, "ITU-R M.1466")
+ self.assertEqual(self.parameters.rns.channel_model, "P619")
+ self.assertEqual(self.parameters.rns.season, "SUMMER")
+ self.assertEqual(self.parameters.rns.earth_station_alt_m, 0.0)
+ self.assertEqual(self.parameters.rns.earth_station_lat_deg, 0.0)
+ self.assertEqual(self.parameters.rns.acs, 30.1)
+
+ def test_parametes_ras(self):
+ """Test ParametersRas
+ """
+ self.assertEqual(self.parameters.ras.frequency, 2695)
+ self.assertEqual(self.parameters.ras.bandwidth, 10)
+ self.assertEqual(self.parameters.ras.noise_temperature, 90)
+ self.assertEqual(self.parameters.ras.adjacent_ch_selectivity, 20.1)
+
+ self.assertEqual(self.parameters.ras.geometry.height, 15)
+ self.assertEqual(self.parameters.ras.geometry.azimuth.type, "FIXED")
+ self.assertEqual(self.parameters.ras.geometry.azimuth.fixed, -90)
+ self.assertEqual(self.parameters.ras.geometry.elevation.type, "FIXED")
+ self.assertEqual(self.parameters.ras.geometry.elevation.fixed, 45)
+ self.assertEqual(self.parameters.ras.antenna.pattern, "OMNI")
+ self.assertEqual(self.parameters.ras.antenna.gain, 0.5)
+ self.assertEqual(self.parameters.ras.channel_model, "P452")
+ self.assertEqual(self.parameters.ras.polarization_loss, 0.0)
+
+ def test_parameters_single_earth_station(self):
+ """Test ParametersSingleEarthStation
+ """
+ self.assertEqual(self.parameters.single_earth_station.frequency, 8250)
+ self.assertEqual(self.parameters.single_earth_station.bandwidth, 100)
+ self.assertEqual(
+ self.parameters.single_earth_station.adjacent_ch_selectivity, 20.0)
+ self.assertEqual(
+ self.parameters.single_earth_station.tx_power_density, -65.0)
+ self.assertEqual(
+ self.parameters.single_earth_station.noise_temperature, 300)
+ self.assertEqual(
+ self.parameters.single_earth_station.geometry.height, 6)
+ self.assertEqual(
+ self.parameters.single_earth_station.geometry.azimuth.type,
+ "FIXED")
+ self.assertEqual(
+ self.parameters.single_earth_station.geometry.azimuth.fixed, 0)
+ self.assertEqual(
+ self.parameters.single_earth_station.geometry.azimuth.uniform_dist.min, -180)
+ self.assertEqual(
+ self.parameters.single_earth_station.geometry.azimuth.uniform_dist.max, 180)
+ self.assertEqual(
+ self.parameters.single_earth_station.geometry.elevation.type,
+ "FIXED")
+ self.assertEqual(
+ self.parameters.single_earth_station.geometry.elevation.fixed, 60)
+ self.assertEqual(
+ self.parameters.single_earth_station.geometry.elevation.uniform_dist.min, 30)
+ self.assertEqual(
+ self.parameters.single_earth_station.geometry.elevation.uniform_dist.max, 65)
+ self.assertEqual(
+ self.parameters.single_earth_station.geometry.location.type,
+ "CELL")
+ self.assertEqual(
+ self.parameters.single_earth_station.geometry.location.fixed.x, 10)
+ self.assertEqual(
+ self.parameters.single_earth_station.geometry.location.fixed.y, 100)
+ self.assertEqual(
+ self.parameters.single_earth_station.geometry.location.uniform_dist.min_dist_to_center,
+ 101)
+ self.assertEqual(
+ self.parameters.single_earth_station.geometry.location.uniform_dist.max_dist_to_center,
+ 102)
+ self.assertEqual(
+ self.parameters.single_earth_station.geometry.location.cell.min_dist_to_bs,
+ 100)
+ self.assertEqual(
+ self.parameters.single_earth_station.geometry.location.network.min_dist_to_bs,
+ 150)
+ self.assertEqual(self.parameters.single_earth_station.antenna.gain, 28)
+ self.assertEqual(
+ self.parameters.single_earth_station.antenna.itu_r_f_699.diameter, 1.1)
+ self.assertEqual(
+ self.parameters.single_earth_station.antenna.itu_r_f_699.frequency,
+ self.parameters.single_earth_station.frequency)
+ self.assertEqual(
+ self.parameters.single_earth_station.antenna.itu_r_f_699.antenna_gain,
+ self.parameters.single_earth_station.antenna.gain)
+
+ self.assertEqual(
+ self.parameters.single_earth_station.param_p619.earth_station_alt_m, 1200)
+ self.assertEqual(
+ self.parameters.single_earth_station.param_p619.space_station_alt_m,
+ 540000)
+ self.assertEqual(
+ self.parameters.single_earth_station.param_p619.earth_station_lat_deg, 13)
+ self.assertEqual(
+ self.parameters.single_earth_station.param_p619.earth_station_long_diff_deg,
+ 10)
+
+ self.assertEqual(
+ self.parameters.single_earth_station.param_p452.atmospheric_pressure, 1)
+ self.assertEqual(
+ self.parameters.single_earth_station.param_p452.air_temperature, 2)
+ self.assertEqual(self.parameters.single_earth_station.param_p452.N0, 3)
+ self.assertEqual(
+ self.parameters.single_earth_station.param_p452.delta_N, 4)
+ self.assertEqual(
+ self.parameters.single_earth_station.param_p452.percentage_p, 5)
+ self.assertEqual(
+ self.parameters.single_earth_station.param_p452.Dct, 6)
+ self.assertEqual(
+ self.parameters.single_earth_station.param_p452.Dcr, 7)
+ self.assertEqual(
+ self.parameters.single_earth_station.param_p452.Hte, 8)
+ self.assertEqual(
+ self.parameters.single_earth_station.param_p452.Hre, 9)
+ self.assertEqual(
+ self.parameters.single_earth_station.param_p452.tx_lat, 10)
+ self.assertEqual(
+ self.parameters.single_earth_station.param_p452.rx_lat, 11)
+ self.assertEqual(
+ self.parameters.single_earth_station.param_p452.polarization,
+ "horizontal")
+ self.assertEqual(
+ self.parameters.single_earth_station.param_p452.clutter_loss, True)
+
+ self.assertEqual(
+ self.parameters.single_earth_station.param_hdfss.es_position,
+ "BUILDINGSIDE")
+ self.assertEqual(
+ self.parameters.single_earth_station.param_hdfss.shadow_enabled,
+ False)
+ self.assertEqual(
+ self.parameters.single_earth_station.param_hdfss.building_loss_enabled,
+ False)
+ self.assertEqual(
+ self.parameters.single_earth_station.param_hdfss.same_building_enabled, True)
+ self.assertEqual(
+ self.parameters.single_earth_station.param_hdfss.diffraction_enabled,
+ False)
+ self.assertEqual(
+ self.parameters.single_earth_station.param_hdfss.bs_building_entry_loss_type,
+ "FIXED_VALUE")
+ self.assertEqual(
+ self.parameters.single_earth_station.param_hdfss.bs_building_entry_loss_prob,
+ 0.19)
+ self.assertEqual(
+ self.parameters.single_earth_station.param_hdfss.bs_building_entry_loss_value,
+ 47)
+
+ self.parameters.single_earth_station.geometry.azimuth.uniform_dist.max = None
+ # this should still not throw, since azimuth is using fixed type
+ self.parameters.single_earth_station.validate()
+
+ # now it should throw:
+ with self.assertRaises(ValueError) as err_context:
+ self.parameters.single_earth_station.geometry.azimuth.type = "UNIFORM_DIST"
+ self.parameters.single_earth_station.validate()
+
+ self.assertTrue(
+ 'azimuth.uniform_dist.max' in str(
+ err_context.exception))
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/test_adjacent_channel.py b/tests/test_adjacent_channel.py
index 2b785f714..40d062e18 100644
--- a/tests/test_adjacent_channel.py
+++ b/tests/test_adjacent_channel.py
@@ -16,6 +16,9 @@
from sharc.antenna.antenna_omni import AntennaOmni
from sharc.station_factory import StationFactory
from sharc.propagation.propagation_factory import PropagationFactory
+from sharc.parameters.imt.parameters_imt_topology import ParametersImtTopology
+from sharc.parameters.imt.parameters_single_bs import ParametersSingleBS
+
class SimulationAdjacentTest(unittest.TestCase):
@@ -28,88 +31,92 @@ def setUp(self):
self.param.general.overwrite_output = True
self.param.general.seed = 101
- self.param.imt.topology = "SINGLE_BS"
- self.param.imt.wrap_around = False
- self.param.imt.num_clusters = 2
- self.param.imt.intersite_distance = 150
+ self.param.imt.topology = ParametersImtTopology(
+ type="SINGLE_BS",
+ single_bs=ParametersSingleBS(
+ num_clusters=2,
+ intersite_distance=150,
+ cell_radius=2 * 150 / 3
+ )
+ )
self.param.imt.minimum_separation_distance_bs_ue = 10
self.param.imt.interfered_with = False
- self.param.imt.frequency = 10000
+ self.param.imt.frequency = 10000.0
self.param.imt.bandwidth = 100
self.param.imt.spectral_mask = "IMT-2020"
self.param.imt.spurious_emissions = -13
self.param.imt.rb_bandwidth = 0.180
self.param.imt.guard_band_ratio = 0.1
self.param.imt.ho_margin = 3
- self.param.imt.bs_load_probability = 1
- self.param.imt.num_resource_blocks = 10
- self.param.imt.bs_conducted_power = 10
- self.param.imt.bs_height = 6
- self.param.imt.bs_acs = 30
- self.param.imt.bs_noise_figure = 7
- self.param.imt.bs_noise_temperature = 290
- self.param.imt.bs_ohmic_loss = 3
- self.param.imt.ul_attenuation_factor = 0.4
- self.param.imt.ul_sinr_min = -10
- self.param.imt.ul_sinr_max = 22
- self.param.imt.ue_k = 2
- self.param.imt.ue_k_m = 1
- self.param.imt.ue_indoor_percent = 0
- self.param.imt.ue_distribution_distance = "RAYLEIGH"
- self.param.imt.ue_distribution_azimuth = "UNIFORM"
- self.param.imt.ue_distribution_type = "ANGLE_AND_DISTANCE"
- self.param.imt.ue_tx_power_control = "OFF"
- self.param.imt.ue_p_o_pusch = -95
- self.param.imt.ue_alpha = 0.8
- self.param.imt.ue_p_cmax = 20
- self.param.imt.ue_conducted_power = 10
- self.param.imt.ue_height = 1.5
- self.param.imt.ue_aclr = 20
- self.param.imt.ue_acs = 25
- self.param.imt.ue_noise_figure = 9
- self.param.imt.ue_ohmic_loss = 3
- self.param.imt.ue_body_loss = 4
- self.param.imt.dl_attenuation_factor = 0.6
- self.param.imt.dl_sinr_min = -10
- self.param.imt.dl_sinr_max = 30
+ self.param.imt.bs.load_probability = 1
+
+ self.param.imt.bs.conducted_power = 10
+ self.param.imt.bs.height = 6
+ self.param.imt.bs.acs = 30
+ self.param.imt.bs.noise_figure = 7
+ self.param.imt.bs.ohmic_loss = 3
+ self.param.imt.uplink.attenuation_factor = 0.4
+ self.param.imt.uplink.sinr_min = -10
+ self.param.imt.uplink.sinr_max = 22
+ self.param.imt.ue.k = 2
+ self.param.imt.ue.k_m = 1
+ self.param.imt.ue.indoor_percent = 0
+ self.param.imt.ue.distribution_distance = "RAYLEIGH"
+ self.param.imt.ue.distribution_azimuth = "UNIFORM"
+ self.param.imt.ue.distribution_type = "ANGLE_AND_DISTANCE"
+ self.param.imt.ue.tx_power_control = "OFF"
+ self.param.imt.ue.p_o_pusch = -95
+ self.param.imt.ue.alpha = 0.8
+ self.param.imt.ue.p_cmax = 20
+ self.param.imt.ue.conducted_power = 10
+ self.param.imt.ue.height = 1.5
+ self.param.imt.ue.aclr = 20
+ self.param.imt.ue.acs = 25
+ self.param.imt.ue.noise_figure = 9
+ self.param.imt.ue.ohmic_loss = 3
+ self.param.imt.ue.body_loss = 4
+ self.param.imt.downlink.attenuation_factor = 0.6
+ self.param.imt.downlink.sinr_min = -10
+ self.param.imt.downlink.sinr_max = 30
self.param.imt.channel_model = "FSPL"
- self.param.imt.line_of_sight_prob = 0.75 # probability of line-of-sight (not for FSPL)
+ # probability of line-of-sight (not for FSPL)
+ self.param.imt.line_of_sight_prob = 0.75
self.param.imt.shadowing = False
self.param.imt.noise_temperature = 290
- self.param.imt.BOLTZMANN_CONSTANT = 1.38064852e-23
-
- self.param.antenna_imt.adjacent_antenna_model = "SINGLE_ELEMENT"
- self.param.antenna_imt.bs_normalization = False
- self.param.antenna_imt.ue_normalization = False
-
- self.param.antenna_imt.bs_normalization_file = None
- self.param.antenna_imt.bs_element_pattern = "M2101"
- self.param.antenna_imt.bs_minimum_array_gain = -200
- self.param.antenna_imt.bs_element_max_g = 10
- self.param.antenna_imt.bs_element_phi_3db = 80
- self.param.antenna_imt.bs_element_theta_3db = 80
- self.param.antenna_imt.bs_element_am = 25
- self.param.antenna_imt.bs_element_sla_v = 25
- self.param.antenna_imt.bs_n_rows = 16
- self.param.antenna_imt.bs_n_columns = 16
- self.param.antenna_imt.bs_element_horiz_spacing = 1
- self.param.antenna_imt.bs_element_vert_spacing = 1
- self.param.antenna_imt.bs_multiplication_factor = 12
- self.param.antenna_imt.bs_downtilt = 10
-
- self.param.antenna_imt.ue_element_pattern = "M2101"
- self.param.antenna_imt.ue_minimum_array_gain = -200
- self.param.antenna_imt.ue_normalization_file = None
- self.param.antenna_imt.ue_element_max_g = 5
- self.param.antenna_imt.ue_element_phi_3db = 65
- self.param.antenna_imt.ue_element_theta_3db = 65
- self.param.antenna_imt.ue_element_am = 30
- self.param.antenna_imt.ue_element_sla_v = 30
- self.param.antenna_imt.ue_n_rows = 2
- self.param.antenna_imt.ue_n_columns = 1
- self.param.antenna_imt.ue_element_horiz_spacing = 0.5
- self.param.antenna_imt.ue_element_vert_spacing = 0.5
- self.param.antenna_imt.ue_multiplication_factor = 12
+
+ self.param.imt.bs.antenna.adjacent_antenna_model = "SINGLE_ELEMENT"
+ self.param.imt.ue.antenna.adjacent_antenna_model = "SINGLE_ELEMENT"
+ self.param.imt.bs.antenna.normalization = False
+ self.param.imt.ue.antenna.normalization = False
+
+ self.param.imt.bs.antenna.normalization_file = None
+ self.param.imt.bs.antenna.element_pattern = "M2101"
+ self.param.imt.bs.antenna.minimum_array_gain = -200
+ self.param.imt.bs.antenna.element_max_g = 10
+ self.param.imt.bs.antenna.element_phi_3db = 80
+ self.param.imt.bs.antenna.element_theta_3db = 80
+ self.param.imt.bs.antenna.element_am = 25
+ self.param.imt.bs.antenna.element_sla_v = 25
+ self.param.imt.bs.antenna.n_rows = 16
+ self.param.imt.bs.antenna.n_columns = 16
+ self.param.imt.bs.antenna.element_horiz_spacing = 1
+ self.param.imt.bs.antenna.element_vert_spacing = 1
+ self.param.imt.bs.antenna.multiplication_factor = 12
+ self.param.imt.bs.antenna.downtilt = 10
+
+ self.param.imt.ue.antenna.element_pattern = "M2101"
+ self.param.imt.ue.antenna.minimum_array_gain = -200
+ self.param.imt.ue.antenna.normalization_file = None
+ self.param.imt.ue.antenna.element_max_g = 5
+ self.param.imt.ue.antenna.element_phi_3db = 65
+ self.param.imt.ue.antenna.element_theta_3db = 65
+ self.param.imt.ue.antenna.element_am = 30
+ self.param.imt.ue.antenna.element_sla_v = 30
+ self.param.imt.ue.antenna.n_rows = 2
+ self.param.imt.ue.antenna.n_columns = 1
+ self.param.imt.ue.antenna.element_horiz_spacing = 0.5
+ self.param.imt.ue.antenna.element_vert_spacing = 0.5
+ self.param.imt.ue.antenna.multiplication_factor = 12
self.param.fss_ss.frequency = 5000
self.param.fss_ss.bandwidth = 100
@@ -123,7 +130,7 @@ def setUp(self):
self.param.fss_ss.antenna_pattern = "OMNI"
self.param.fss_ss.imt_altitude = 1000
self.param.fss_ss.imt_lat_deg = -23.5629739
- self.param.fss_ss.imt_long_diff_deg = (-46.6555132-75)
+ self.param.fss_ss.imt_long_diff_deg = (-46.6555132 - 75)
self.param.fss_ss.channel_model = "FSPL"
self.param.fss_ss.line_of_sight_prob = 0.01
self.param.fss_ss.surf_water_vapour_density = 7.5
@@ -131,8 +138,6 @@ def setUp(self):
self.param.fss_ss.time_ratio = 0.5
self.param.fss_ss.antenna_l_s = -20
self.param.fss_ss.acs = 10
- self.param.fss_ss.BOLTZMANN_CONSTANT = 1.38064852e-23
- self.param.fss_ss.EARTH_RADIUS = 6371000
def test_simulation_2bs_4ue_downlink(self):
self.param.general.imt_link = "DOWNLINK"
@@ -148,85 +153,94 @@ def test_simulation_2bs_4ue_downlink(self):
random_number_gen = np.random.RandomState()
self.simulation.bs = StationFactory.generate_imt_base_stations(self.param.imt,
- self.param.antenna_imt,
+ self.param.imt.bs.antenna,
self.simulation.topology,
random_number_gen)
self.simulation.bs.antenna = np.array([AntennaOmni(1), AntennaOmni(2)])
self.simulation.bs.active = np.ones(2, dtype=bool)
self.simulation.ue = StationFactory.generate_imt_ue(self.param.imt,
- self.param.antenna_imt,
+ self.param.imt.bs.antenna,
self.simulation.topology,
random_number_gen)
self.simulation.ue.x = np.array([20, 70, 110, 170])
- self.simulation.ue.y = np.array([ 0, 0, 0, 0])
- self.simulation.ue.antenna = np.array([AntennaOmni(10), AntennaOmni(11), AntennaOmni(22), AntennaOmni(23)])
+ self.simulation.ue.y = np.array([0, 0, 0, 0])
+ self.simulation.ue.antenna = np.array(
+ [AntennaOmni(10), AntennaOmni(11), AntennaOmni(22), AntennaOmni(23)])
self.simulation.ue.active = np.ones(4, dtype=bool)
# test connection method
self.simulation.connect_ue_to_bs()
- self.assertEqual(self.simulation.link, {0: [0,1], 1: [2,3]})
+ self.assertEqual(self.simulation.link, {0: [0, 1], 1: [2, 3]})
self.simulation.select_ue(random_number_gen)
- self.simulation.link = {0:[0,1],1:[2,3]}
+ self.simulation.link = {0: [0, 1], 1: [2, 3]}
# We do not test the selection method here because in this specific
# scenario we do not want to change the order of the UE's
self.simulation.propagation_imt = PropagationFactory.create_propagation(self.param.imt.channel_model,
- self.param, random_number_gen)
+ self.param,
+ self.simulation.param_system,
+ random_number_gen)
self.simulation.propagation_system = PropagationFactory.create_propagation(self.param.fss_ss.channel_model,
- self.param, random_number_gen)
+ self.param,
+ self.simulation.param_system,
+ random_number_gen)
# test coupling loss method
- self.simulation.coupling_loss_imt = self.simulation.calculate_coupling_loss(self.simulation.bs,
- self.simulation.ue,
- self.simulation.propagation_imt)
+ self.simulation.coupling_loss_imt = self.simulation.calculate_intra_imt_coupling_loss(self.simulation.ue,
+ self.simulation.bs)
npt.assert_allclose(self.simulation.coupling_loss_imt,
- np.array([[88.47-1-10, 99.35-1-11, 103.27-1-22, 107.05-1-23],
- [107.55-2-10, 104.72-2-11, 101.53-2-22, 91.99-2-23]]),
+ np.array([[88.68 - 1 - 10, 99.36 - 1 - 11, 103.28 - 1 - 22, 107.06 - 1 - 23],
+ [107.55 - 2 - 10, 104.73 - 2 - 11, 101.54 - 2 - 22, 92.08 - 2 - 23]]),
atol=1e-2)
# test scheduler and bandwidth allocation
self.simulation.scheduler()
- bandwidth_per_ue = math.trunc((1 - 0.1)*100/2)
- npt.assert_allclose(self.simulation.ue.bandwidth, bandwidth_per_ue*np.ones(4), atol=1e-2)
+ bandwidth_per_ue = math.trunc((1 - 0.1) * 100 / 2)
+ npt.assert_allclose(
+ self.simulation.ue.bandwidth,
+ bandwidth_per_ue * np.ones(4),
+ atol=1e-2)
# there is no power control, so BS's will transmit at maximum power
self.simulation.power_control()
- tx_power = 10 - 10*math.log10(2)
- npt.assert_allclose(self.simulation.bs.tx_power[0], np.array([tx_power, tx_power]), atol=1e-2)
- npt.assert_allclose(self.simulation.bs.tx_power[1], np.array([tx_power, tx_power]), atol=1e-2)
-
- npt.assert_equal(self.simulation.bs.spectral_mask.mask_dbm,np.array([-50, -20, -10, -10, -10, -20, -50]))
+ tx_power = 10 - 10 * math.log10(2)
+ npt.assert_allclose(self.simulation.bs.tx_power[0], np.array(
+ [tx_power, tx_power]), atol=1e-2)
+ npt.assert_allclose(self.simulation.bs.tx_power[1], np.array(
+ [tx_power, tx_power]), atol=1e-2)
# create system
- self.simulation.system = StationFactory.generate_fss_space_station(self.param.fss_ss)
- self.simulation.system.x = np.array([0.01]) # avoids zero-division
+ self.simulation.system = StationFactory.generate_fss_space_station(
+ self.param.fss_ss)
+ self.simulation.system.x = np.array([0.01]) # avoids zero-division
self.simulation.system.y = np.array([0])
self.simulation.system.height = np.array([self.param.fss_ss.altitude])
- # test the method that calculates interference from IMT UE to FSS space station
+ # test the method that calculates interference from IMT UE to FSS space
+ # station
self.simulation.calculate_external_interference()
# check coupling loss
- coupling_loss_imt_system_adj = np.array([209.52-51-1, 209.52-51-1, 209.52-51-2, 209.52-51-2])
+ coupling_loss_imt_system_adj = np.array(
+ [209.52 - 51 - 1, 209.52 - 51 - 1, 209.52 - 51 - 2, 209.52 - 51 - 2])
npt.assert_allclose(self.simulation.coupling_loss_imt_system_adjacent,
coupling_loss_imt_system_adj,
atol=1e-2)
# check interference generated by BS to FSS space station
- interf_pow = np.power(10, 0.1*(-50))*100
- rx_interf_bs1 = 10*math.log10(interf_pow)\
- - coupling_loss_imt_system_adj[0]
- rx_interf_bs2 = 10*math.log10(interf_pow)\
- - coupling_loss_imt_system_adj[2]
- rx_interference = 10*math.log10(math.pow(10,0.1*rx_interf_bs1) + \
- math.pow(10,0.1*rx_interf_bs2)) + 3
+ interf_pow = np.power(10, 0.1 * (self.param.imt.bs.conducted_power))
+ rx_interf_bs1 = 10 * math.log10(interf_pow)\
+ - coupling_loss_imt_system_adj[0]
+ rx_interf_bs2 = 10 * math.log10(interf_pow)\
+ - coupling_loss_imt_system_adj[2]
+ rx_interference = 10 * math.log10(math.pow(10, 0.1 * rx_interf_bs1) +
+ math.pow(10, 0.1 * rx_interf_bs2))
self.assertAlmostEqual(self.simulation.system.rx_interference,
rx_interference,
delta=.01)
-
def test_simulation_2bs_4ue_uplink(self):
self.param.general.imt_link = "UPLINK"
@@ -241,82 +255,93 @@ def test_simulation_2bs_4ue_uplink(self):
random_number_gen = np.random.RandomState()
self.simulation.bs = StationFactory.generate_imt_base_stations(self.param.imt,
- self.param.antenna_imt,
+ self.param.imt.bs.antenna,
self.simulation.topology,
random_number_gen)
self.simulation.bs.antenna = np.array([AntennaOmni(1), AntennaOmni(2)])
self.simulation.bs.active = np.ones(2, dtype=bool)
self.simulation.ue = StationFactory.generate_imt_ue(self.param.imt,
- self.param.antenna_imt,
+ self.param.imt.bs.antenna,
self.simulation.topology,
random_number_gen)
self.simulation.ue.x = np.array([20, 70, 110, 170])
- self.simulation.ue.y = np.array([ 0, 0, 0, 0])
- self.simulation.ue.antenna = np.array([AntennaOmni(10), AntennaOmni(11), AntennaOmni(22), AntennaOmni(23)])
+ self.simulation.ue.y = np.array([0, 0, 0, 0])
+ self.simulation.ue.antenna = np.array(
+ [AntennaOmni(10), AntennaOmni(11), AntennaOmni(22), AntennaOmni(23)])
self.simulation.ue.active = np.ones(4, dtype=bool)
# test connection method
self.simulation.connect_ue_to_bs()
- self.assertEqual(self.simulation.link, {0: [0,1], 1: [2,3]})
+ self.assertEqual(self.simulation.link, {0: [0, 1], 1: [2, 3]})
self.simulation.select_ue(random_number_gen)
- self.simulation.link = {0:[0,1],1:[2,3]}
+ self.simulation.link = {0: [0, 1], 1: [2, 3]}
# We do not test the selection method here because in this specific
# scenario we do not want to change the order of the UE's
self.simulation.propagation_imt = PropagationFactory.create_propagation(self.param.imt.channel_model,
- self.param, random_number_gen)
+ self.param,
+ self.simulation.param_system,
+ random_number_gen)
self.simulation.propagation_system = PropagationFactory.create_propagation(self.param.fss_ss.channel_model,
- self.param, random_number_gen)
+ self.param,
+ self.simulation.param_system,
+ random_number_gen)
# test coupling loss method
- self.simulation.coupling_loss_imt = self.simulation.calculate_coupling_loss(self.simulation.bs,
- self.simulation.ue,
- self.simulation.propagation_imt)
- coupling_loss_imt = np.array([[88.47-1-10, 99.35-1-11, 103.27-1-22, 107.05-1-23],
- [107.55-2-10, 104.72-2-11, 101.53-2-22, 91.99-2-23]])
+ self.simulation.coupling_loss_imt = self.simulation.calculate_intra_imt_coupling_loss(self.simulation.ue,
+ self.simulation.bs)
+ coupling_loss_imt = np.array([[88.68 - 1 - 10, 99.36 - 1 - 11, 103.28 - 1 - 22, 107.06 - 1 - 23],
+ [107.55 - 2 - 10, 104.73 - 2 - 11, 101.54 - 2 - 22, 92.08 - 2 - 23]])
npt.assert_allclose(self.simulation.coupling_loss_imt,
coupling_loss_imt,
atol=1e-2)
# test scheduler and bandwidth allocation
self.simulation.scheduler()
- bandwidth_per_ue = math.trunc((1 - 0.1)*100/2)
- npt.assert_allclose(self.simulation.ue.bandwidth, bandwidth_per_ue*np.ones(4), atol=1e-2)
+ bandwidth_per_ue = math.trunc((1 - 0.1) * 100 / 2)
+ npt.assert_allclose(
+ self.simulation.ue.bandwidth,
+ bandwidth_per_ue * np.ones(4),
+ atol=1e-2)
# there is no power control, so UE's will transmit at maximum power
self.simulation.power_control()
- npt.assert_equal(self.simulation.ue_power_diff,np.zeros(4))
+ npt.assert_equal(self.simulation.ue_power_diff, np.zeros(4))
tx_power = 20
- npt.assert_allclose(self.simulation.ue.tx_power, tx_power*np.ones(4))
+ npt.assert_allclose(self.simulation.ue.tx_power, tx_power * np.ones(4))
- npt.assert_equal(self.simulation.ue.spectral_mask.mask_dbm,np.array([-13, -13, -5, -20, -5, -13, -13]))
+ npt.assert_equal(self.simulation.ue.spectral_mask.mask_dbm,
+ np.array([-13, -13, -5, -20, -5, -13, -13]))
# create system
- self.simulation.system = StationFactory.generate_fss_space_station(self.param.fss_ss)
+ self.simulation.system = StationFactory.generate_fss_space_station(
+ self.param.fss_ss)
self.simulation.system.x = np.array([0])
self.simulation.system.y = np.array([0])
self.simulation.system.height = np.array([self.param.fss_ss.altitude])
- # test the method that calculates interference from IMT UE to FSS space station
+ # test the method that calculates interference from IMT UE to FSS space
+ # station
self.simulation.calculate_external_interference()
# check coupling loss
- coupling_loss_imt_system_adj = np.array([213.52-51-10, 213.52-51-11, 213.52-51-22, 213.52-51-23])
+ coupling_loss_imt_system_adj = np.array(
+ [213.52 - 51 - 10, 213.52 - 51 - 11, 213.52 - 51 - 22, 213.52 - 51 - 23])
npt.assert_allclose(self.simulation.coupling_loss_imt_system_adjacent,
coupling_loss_imt_system_adj,
atol=1e-2)
# check interference generated by UE to FSS space station
- interf_pow = np.power(10, 0.1*(-13))*100
- interference = 10*math.log10(interf_pow) \
- - coupling_loss_imt_system_adj
- rx_interference = 10*math.log10(np.sum(np.power(10, 0.1*interference))) + 3
+ interf_pow = np.power(10, 0.1 * (-13)) * 100
+ interference = 10 * math.log10(interf_pow) \
+ - coupling_loss_imt_system_adj
+ rx_interference = 10 * \
+ math.log10(np.sum(np.power(10, 0.1 * interference))) + 3
self.assertAlmostEqual(self.simulation.system.rx_interference,
rx_interference,
delta=.01)
-
if __name__ == '__main__':
unittest.main()
diff --git a/tests/test_antenna_beamforming_imt.py b/tests/test_antenna_beamforming_imt.py
index c520e8a76..cfcdcb83b 100644
--- a/tests/test_antenna_beamforming_imt.py
+++ b/tests/test_antenna_beamforming_imt.py
@@ -10,107 +10,110 @@
import numpy.testing as npt
from sharc.antenna.antenna_beamforming_imt import AntennaBeamformingImt
-from sharc.parameters.parameters_antenna_imt import ParametersAntennaImt
+from sharc.parameters.imt.parameters_antenna_imt import ParametersAntennaImt
from sharc.support.named_tuples import AntennaPar
from sharc.support.enumerations import StationType
+
class AntennaBeamformingImtTest(unittest.TestCase):
def setUp(self):
- #Array parameters
- self.param = ParametersAntennaImt()
-
- self.param.adjacent_antenna_model = "SINGLE_ELEMENT"
- self.param.bs_normalization = False
- self.param.bs_normalization_file = None
- self.param.bs_element_pattern = "M2101"
- self.param.bs_minimum_array_gain = -200
- self.param.bs_downtilt = 0
-
- self.param.bs_element_max_g = 5
- self.param.bs_element_phi_3db = 80
- self.param.bs_element_theta_3db = 60
- self.param.bs_element_am = 30
- self.param.bs_element_sla_v = 30
- self.param.bs_n_rows = 16
- self.param.bs_n_columns = 16
- self.param.bs_element_horiz_spacing = 1
- self.param.bs_element_vert_spacing = 1
- self.param.bs_multiplication_factor = 12
-
- self.param.ue_element_pattern = "M2101"
- self.param.ue_normalization = False
- self.param.ue_normalization_file = None
- self.param.ue_minimum_array_gain = -200
-
- self.param.ue_element_max_g = 10
- self.param.ue_element_phi_3db = 75
- self.param.ue_element_theta_3db = 65
- self.param.ue_element_am = 25
- self.param.ue_element_sla_v = 35
- self.param.ue_n_rows = 2
- self.param.ue_n_columns = 2
- self.param.ue_element_horiz_spacing = 0.5
- self.param.ue_element_vert_spacing = 0.5
- self.param.ue_multiplication_factor = 12
+ # Array parameters
+ self.bs_param = ParametersAntennaImt()
+ self.ue_param = ParametersAntennaImt()
+
+ self.bs_param.adjacent_antenna_model = "SINGLE_ELEMENT"
+ self.ue_param.adjacent_antenna_model = "SINGLE_ELEMENT"
+ self.bs_param.normalization = False
+ self.bs_param.normalization_file = None
+ self.bs_param.element_pattern = "M2101"
+ self.bs_param.minimum_array_gain = -200
+ self.bs_param.downtilt = 0
+
+ self.bs_param.element_max_g = 5
+ self.bs_param.element_phi_3db = 80
+ self.bs_param.element_theta_3db = 60
+ self.bs_param.element_am = 30
+ self.bs_param.element_sla_v = 30
+ self.bs_param.n_rows = 16
+ self.bs_param.n_columns = 16
+ self.bs_param.element_horiz_spacing = 1
+ self.bs_param.element_vert_spacing = 1
+ self.bs_param.multiplication_factor = 12
+
+ self.ue_param.element_pattern = "M2101"
+ self.ue_param.normalization = False
+ self.ue_param.normalization_file = None
+ self.ue_param.minimum_array_gain = -200
+
+ self.ue_param.element_max_g = 10
+ self.ue_param.element_phi_3db = 75
+ self.ue_param.element_theta_3db = 65
+ self.ue_param.element_am = 25
+ self.ue_param.element_sla_v = 35
+ self.ue_param.n_rows = 2
+ self.ue_param.n_columns = 2
+ self.ue_param.element_horiz_spacing = 0.5
+ self.ue_param.element_vert_spacing = 0.5
+ self.ue_param.multiplication_factor = 12
# Create antenna objects
- par = self.param.get_antenna_parameters(StationType.IMT_BS)
- self.antenna1 = AntennaBeamformingImt(par,300,-10)
- par = self.param.get_antenna_parameters(StationType.IMT_UE)
- self.antenna2 = AntennaBeamformingImt(par,-33.21,-5.31)
+ par = self.bs_param.get_antenna_parameters()
+ self.antenna1 = AntennaBeamformingImt(par, 300, -10)
+ par = self.ue_param.get_antenna_parameters()
+ self.antenna2 = AntennaBeamformingImt(par, -33.21, -5.31)
def test_azimuth(self):
- self.assertEqual(self.antenna1.azimuth,300)
- self.assertEqual(self.antenna2.azimuth,-33.21)
+ self.assertEqual(self.antenna1.azimuth, 300)
+ self.assertEqual(self.antenna2.azimuth, -33.21)
def test_elevation(self):
- self.assertEqual(self.antenna1.elevation,-10)
- self.assertEqual(self.antenna2.elevation,-5.31)
+ self.assertEqual(self.antenna1.elevation, -10)
+ self.assertEqual(self.antenna2.elevation, -5.31)
def test_g_max(self):
- self.assertEqual(self.antenna1.element.g_max,5)
- self.assertEqual(self.antenna2.element.g_max,10)
+ self.assertEqual(self.antenna1.element.g_max, 5)
+ self.assertEqual(self.antenna2.element.g_max, 10)
def test_phi_3db(self):
- self.assertEqual(self.antenna1.element.phi_3db,80)
- self.assertEqual(self.antenna2.element.phi_3db,75)
+ self.assertEqual(self.antenna1.element.phi_3db, 80)
+ self.assertEqual(self.antenna2.element.phi_3db, 75)
def test_theta_3db(self):
- self.assertEqual(self.antenna1.element.theta_3db,60)
- self.assertEqual(self.antenna2.element.theta_3db,65)
+ self.assertEqual(self.antenna1.element.theta_3db, 60)
+ self.assertEqual(self.antenna2.element.theta_3db, 65)
def test_am(self):
- self.assertEqual(self.antenna1.element.am,30)
- self.assertEqual(self.antenna2.element.am,25)
+ self.assertEqual(self.antenna1.element.am, 30)
+ self.assertEqual(self.antenna2.element.am, 25)
def test_sla_v(self):
- self.assertEqual(self.antenna1.element.sla_v,30)
- self.assertEqual(self.antenna2.element.sla_v,35)
+ self.assertEqual(self.antenna1.element.sla_v, 30)
+ self.assertEqual(self.antenna2.element.sla_v, 35)
def test_n_rows(self):
- self.assertEqual(self.antenna1.n_rows,16)
- self.assertEqual(self.antenna2.n_rows,2)
+ self.assertEqual(self.antenna1.n_rows, 16)
+ self.assertEqual(self.antenna2.n_rows, 2)
def test_n_cols(self):
- self.assertEqual(self.antenna1.n_cols,16)
- self.assertEqual(self.antenna2.n_cols,2)
+ self.assertEqual(self.antenna1.n_cols, 16)
+ self.assertEqual(self.antenna2.n_cols, 2)
def test_dh(self):
- self.assertEqual(self.antenna1.dh,1)
- self.assertEqual(self.antenna2.dh,0.5)
+ self.assertEqual(self.antenna1.dh, 1)
+ self.assertEqual(self.antenna2.dh, 0.5)
def test_dv(self):
- self.assertEqual(self.antenna1.dv,1)
- self.assertEqual(self.antenna2.dv,0.5)
+ self.assertEqual(self.antenna1.dv, 1)
+ self.assertEqual(self.antenna2.dv, 0.5)
def test_beams_list(self):
- self.assertEqual(len(self.antenna1.beams_list),0)
- self.assertEqual(len(self.antenna2.beams_list),0)
+ self.assertEqual(len(self.antenna1.beams_list), 0)
+ self.assertEqual(len(self.antenna2.beams_list), 0)
def test_w_vec_list(self):
- self.assertEqual(len(self.antenna1.w_vec_list),0)
- self.assertEqual(len(self.antenna2.w_vec_list),0)
+ self.assertEqual(len(self.antenna1.w_vec_list), 0)
+ self.assertEqual(len(self.antenna2.w_vec_list), 0)
def test_super_position_vector(self):
# Error margin
@@ -120,43 +123,43 @@ def test_super_position_vector(self):
phi = 0
theta = 0
v_vec = self.antenna2._super_position_vector(phi, theta)
- expected_v_vec = np.array([[1.0, 1.0],[-1.0, -1.0]])
- self.assertTrue(np.allclose(np.real(v_vec),\
- np.real(expected_v_vec),rtol = eps))
- self.assertTrue(np.allclose(np.imag(v_vec),\
- np.imag(expected_v_vec),rtol = eps))
+ expected_v_vec = np.array([[1.0, 1.0], [-1.0, -1.0]])
+ self.assertTrue(np.allclose(np.real(v_vec),
+ np.real(expected_v_vec), rtol=eps))
+ self.assertTrue(np.allclose(np.imag(v_vec),
+ np.imag(expected_v_vec), rtol=eps))
# Test 2
phi = 90
theta = 90
v_vec = self.antenna2._super_position_vector(phi, theta)
- expected_v_vec = np.array([[1.0, -1.0],[1.0, -1.0]])
- self.assertTrue(np.allclose(np.real(v_vec),\
- np.real(expected_v_vec),rtol = eps))
- self.assertTrue(np.allclose(np.imag(v_vec),\
- np.imag(expected_v_vec),rtol = eps))
+ expected_v_vec = np.array([[1.0, -1.0], [1.0, -1.0]])
+ self.assertTrue(np.allclose(np.real(v_vec),
+ np.real(expected_v_vec), rtol=eps))
+ self.assertTrue(np.allclose(np.imag(v_vec),
+ np.imag(expected_v_vec), rtol=eps))
# Test 3
phi = 45
theta = 45
v_vec = self.antenna2._super_position_vector(phi, theta)
- expected_v_vec = np.array([[1.0 + 0.0j, 0.0 + 1.0j],\
- [-0.6056998+0.7956932j, -0.7956932-0.6056998j]])
- self.assertTrue(np.allclose(np.real(v_vec),\
- np.real(expected_v_vec),rtol = eps))
- self.assertTrue(np.allclose(np.imag(v_vec),\
- np.imag(expected_v_vec),rtol = eps))
+ expected_v_vec = np.array([[1.0 + 0.0j, 0.0 + 1.0j],
+ [-0.6056998 + 0.7956932j, -0.7956932 - 0.6056998j]])
+ self.assertTrue(np.allclose(np.real(v_vec),
+ np.real(expected_v_vec), rtol=eps))
+ self.assertTrue(np.allclose(np.imag(v_vec),
+ np.imag(expected_v_vec), rtol=eps))
# Test 4
phi = 60
theta = 90
v_vec = self.antenna2._super_position_vector(phi, theta)
- expected_v_vec = np.array([[1.0 + 0.0j, -0.912724 + 0.408576j],\
- [1.0 + 0.0j, -0.912724 + 0.408576j]])
- self.assertTrue(np.allclose(np.real(v_vec),\
- np.real(expected_v_vec),rtol = eps))
- self.assertTrue(np.allclose(np.imag(v_vec),\
- np.imag(expected_v_vec),rtol = eps))
+ expected_v_vec = np.array([[1.0 + 0.0j, -0.912724 + 0.408576j],
+ [1.0 + 0.0j, -0.912724 + 0.408576j]])
+ self.assertTrue(np.allclose(np.real(v_vec),
+ np.real(expected_v_vec), rtol=eps))
+ self.assertTrue(np.allclose(np.imag(v_vec),
+ np.imag(expected_v_vec), rtol=eps))
def test_weight_vector(self):
# Error margin
@@ -166,111 +169,110 @@ def test_weight_vector(self):
phi_scan = 0
theta_tilt = 0
w_vec = self.antenna2._weight_vector(phi_scan, theta_tilt)
- expected_w_vec = np.array([[0.5, 0.5],[0.5, 0.5]])
- self.assertTrue(np.allclose(np.real(w_vec),\
- np.real(expected_w_vec),rtol = eps))
- self.assertTrue(np.allclose(np.imag(w_vec),\
- np.imag(expected_w_vec),rtol = eps))
+ expected_w_vec = np.array([[0.5, 0.5], [0.5, 0.5]])
+ self.assertTrue(np.allclose(np.real(w_vec),
+ np.real(expected_w_vec), rtol=eps))
+ self.assertTrue(np.allclose(np.imag(w_vec),
+ np.imag(expected_w_vec), rtol=eps))
# Test 2
phi_scan = 90
theta_tilt = 90
w_vec = self.antenna2._weight_vector(phi_scan, theta_tilt)
- expected_w_vec = np.array([[0.5, 0.5],[-0.5, -0.5]])
- self.assertTrue(np.allclose(np.real(w_vec),\
- np.real(expected_w_vec),rtol = eps))
- self.assertTrue(np.allclose(np.imag(w_vec),\
- np.imag(expected_w_vec),rtol = eps))
+ expected_w_vec = np.array([[0.5, 0.5], [-0.5, -0.5]])
+ self.assertTrue(np.allclose(np.real(w_vec),
+ np.real(expected_w_vec), rtol=eps))
+ self.assertTrue(np.allclose(np.imag(w_vec),
+ np.imag(expected_w_vec), rtol=eps))
# Test 3
phi_scan = 45
theta_tilt = 45
w_vec = self.antenna2._weight_vector(phi_scan, theta_tilt)
- expected_w_vec = np.array([[0.5 + 0.0j, 0.0 - 0.5j],\
- [-0.3028499+0.3978466j, 0.3978466+0.3028499j]])
- self.assertTrue(np.allclose(np.real(w_vec),\
- np.real(expected_w_vec),rtol = eps))
- self.assertTrue(np.allclose(np.imag(w_vec),\
- np.imag(expected_w_vec),rtol = eps))
+ expected_w_vec = np.array([[0.5 + 0.0j, 0.0 - 0.5j],
+ [-0.3028499 + 0.3978466j, 0.3978466 + 0.3028499j]])
+ self.assertTrue(np.allclose(np.real(w_vec),
+ np.real(expected_w_vec), rtol=eps))
+ self.assertTrue(np.allclose(np.imag(w_vec),
+ np.imag(expected_w_vec), rtol=eps))
# Test 4
phi_scan = 0
theta_tilt = 90
w_vec = self.antenna2._weight_vector(phi_scan, theta_tilt)
- expected_w_vec = np.array([[0.5, 0.5],[-0.5, -0.5]])
- self.assertTrue(np.allclose(np.real(w_vec),\
- np.real(expected_w_vec),rtol = eps))
- self.assertTrue(np.allclose(np.imag(w_vec),\
- np.imag(expected_w_vec),rtol = eps))
+ expected_w_vec = np.array([[0.5, 0.5], [-0.5, -0.5]])
+ self.assertTrue(np.allclose(np.real(w_vec),
+ np.real(expected_w_vec), rtol=eps))
+ self.assertTrue(np.allclose(np.imag(w_vec),
+ np.imag(expected_w_vec), rtol=eps))
# Test 5
phi_scan = 45
theta_tilt = 30
w_vec = self.antenna2._weight_vector(phi_scan, theta_tilt)
- expected_w_vec = np.array([[0.5 + 0.0j, -0.172870 - 0.469169j],\
- [0.0 + 0.5j, 0.469165 - 0.172870j]])
- self.assertTrue(np.allclose(np.real(w_vec),\
- np.real(expected_w_vec),rtol = eps))
- self.assertTrue(np.allclose(np.imag(w_vec),\
- np.imag(expected_w_vec),rtol = eps))
-
+ expected_w_vec = np.array([[0.5 + 0.0j, -0.172870 - 0.469169j],
+ [0.0 + 0.5j, 0.469165 - 0.172870j]])
+ self.assertTrue(np.allclose(np.real(w_vec),
+ np.real(expected_w_vec), rtol=eps))
+ self.assertTrue(np.allclose(np.imag(w_vec),
+ np.imag(expected_w_vec), rtol=eps))
def test_add_beam(self):
# Error margin and antenna object
eps = 1e-5
- par = self.param.get_antenna_parameters(StationType.IMT_UE)
- self.antenna2 = AntennaBeamformingImt(par,0,0)
+ par = self.ue_param.get_antenna_parameters()
+ self.antenna2 = AntennaBeamformingImt(par, 0, 0)
# Add first beam
phi_scan = 45
theta_tilt = 120
- self.antenna2.add_beam(phi_scan,theta_tilt)
+ self.antenna2.add_beam(phi_scan, theta_tilt)
- self.assertEqual(len(self.antenna2.beams_list),1)
- self.assertEqual(len(self.antenna2.w_vec_list),1)
+ self.assertEqual(len(self.antenna2.beams_list), 1)
+ self.assertEqual(len(self.antenna2.w_vec_list), 1)
# Add second beam
phi_scan = 90
theta_tilt = 180.0
- self.antenna2.add_beam(phi_scan,theta_tilt)
+ self.antenna2.add_beam(phi_scan, theta_tilt)
# Test beams_list
- self.assertEqual(len(self.antenna2.beams_list),2)
- self.assertEqual(len(self.antenna2.w_vec_list),2)
+ self.assertEqual(len(self.antenna2.beams_list), 2)
+ self.assertEqual(len(self.antenna2.w_vec_list), 2)
# Test first beam
- self.assertAlmostEqual(self.antenna2.beams_list[0][0],45,delta=eps)
- self.assertAlmostEqual(self.antenna2.beams_list[0][1],30,delta=eps)
+ self.assertAlmostEqual(self.antenna2.beams_list[0][0], 45, delta=eps)
+ self.assertAlmostEqual(self.antenna2.beams_list[0][1], 30, delta=eps)
w_vec = self.antenna2.w_vec_list[0]
- expected_w_vec = np.array([[0.5 + 0.0j, -0.172870 - 0.469169j],\
- [0.0 + 0.5j, 0.469165 - 0.172870j]])
- self.assertTrue(np.allclose(np.real(w_vec),\
- np.real(expected_w_vec),rtol = eps))
- self.assertTrue(np.allclose(np.imag(w_vec),\
- np.imag(expected_w_vec),rtol = eps))
+ expected_w_vec = np.array([[0.5 + 0.0j, -0.172870 - 0.469169j],
+ [0.0 + 0.5j, 0.469165 - 0.172870j]])
+ self.assertTrue(np.allclose(np.real(w_vec),
+ np.real(expected_w_vec), rtol=eps))
+ self.assertTrue(np.allclose(np.imag(w_vec),
+ np.imag(expected_w_vec), rtol=eps))
# Test second beam
- self.assertEqual(self.antenna2.beams_list[1][0],90)
- self.assertEqual(self.antenna2.beams_list[1][1],90)
+ self.assertEqual(self.antenna2.beams_list[1][0], 90)
+ self.assertEqual(self.antenna2.beams_list[1][1], 90)
w_vec = self.antenna2.w_vec_list[1]
- expected_w_vec = np.array([[0.5, 0.5],[-0.5, -0.5]])
- self.assertTrue(np.allclose(np.real(w_vec),\
- np.real(expected_w_vec),rtol = eps))
- self.assertTrue(np.allclose(np.imag(w_vec),\
- np.imag(expected_w_vec),rtol = eps))
+ expected_w_vec = np.array([[0.5, 0.5], [-0.5, -0.5]])
+ self.assertTrue(np.allclose(np.real(w_vec),
+ np.real(expected_w_vec), rtol=eps))
+ self.assertTrue(np.allclose(np.imag(w_vec),
+ np.imag(expected_w_vec), rtol=eps))
# Reset beams and test
self.antenna2.reset_beams()
- self.assertEqual(len(self.antenna2.beams_list),0)
- self.assertEqual(len(self.antenna2.w_vec_list),0)
+ self.assertEqual(len(self.antenna2.beams_list), 0)
+ self.assertEqual(len(self.antenna2.w_vec_list), 0)
def test_beam_gain(self):
# Error margin and antenna
eps = 1e-4
- par = self.param.get_antenna_parameters(StationType.IMT_UE)
- self.antenna2 = AntennaBeamformingImt(par,0,0)
+ par = self.ue_param.get_antenna_parameters()
+ self.antenna2 = AntennaBeamformingImt(par, 0, 0)
# Test 1
phi = 45
@@ -278,9 +280,9 @@ def test_beam_gain(self):
beam = 0
phi_scan = 45
theta_tilt = 135
- self.antenna2.add_beam(phi_scan,theta_tilt)
- beam_g = self.antenna2._beam_gain(phi,theta,beam)
- self.assertAlmostEqual(beam_g,1.594268,delta = eps)
+ self.antenna2.add_beam(phi_scan, theta_tilt)
+ beam_g = self.antenna2._beam_gain(phi, theta, beam)
+ self.assertAlmostEqual(beam_g, 1.594268, delta=eps)
# Test 2
phi = 0
@@ -288,29 +290,30 @@ def test_beam_gain(self):
beam = 1
phi_scan = 45
theta_tilt = 180
- self.antenna2.add_beam(phi_scan,theta_tilt)
- beam_g = self.antenna2._beam_gain(phi,theta,beam)
- self.assertAlmostEqual(beam_g,10.454087,delta = eps)
+ self.antenna2.add_beam(phi_scan, theta_tilt)
+ beam_g = self.antenna2._beam_gain(phi, theta, beam)
+ self.assertAlmostEqual(beam_g, 10.454087, delta=eps)
# Test 3
phi = 32.5
theta = 115.2
- beam_g = self.antenna2._beam_gain(phi,theta)
- self.assertAlmostEqual(beam_g,11.9636,delta = eps)
+ beam_g = self.antenna2._beam_gain(phi, theta)
+ self.assertAlmostEqual(beam_g, 11.9636, delta=eps)
def test_calculate_gain(self):
# Error margin and antenna
eps = 1e-4
- par = self.param.get_antenna_parameters(StationType.IMT_BS)
- self.antenna1 = AntennaBeamformingImt(par,0,0)
- par = self.param.get_antenna_parameters(StationType.IMT_UE)
- self.antenna2 = AntennaBeamformingImt(par,0,0)
+ par = self.bs_param.get_antenna_parameters()
+ self.antenna1 = AntennaBeamformingImt(par, 0, 0)
+ par = self.ue_param.get_antenna_parameters()
+ self.antenna2 = AntennaBeamformingImt(par, 0, 0)
# Test 1
phi_vec = np.array([45.0, 32.5])
theta_vec = np.array([45.0, 115.2])
- gains = self.antenna2.calculate_gain(phi_vec=phi_vec, theta_vec=theta_vec)
- npt.assert_allclose(gains,np.array([5.9491,11.9636]),atol=eps)
+ gains = self.antenna2.calculate_gain(
+ phi_vec=phi_vec, theta_vec=theta_vec)
+ npt.assert_allclose(gains, np.array([5.9491, 11.9636]), atol=eps)
# Test 2
phi = 0.0
@@ -321,24 +324,24 @@ def test_calculate_gain(self):
beams_l = np.zeros_like(phi_vec, dtype=int)
gains = self.antenna2.calculate_gain(phi_vec=phi, theta_vec=theta,
beams_l=beams_l)
- npt.assert_allclose(gains,np.array([10.454087]),atol=eps)
+ npt.assert_allclose(gains, np.array([10.454087]), atol=eps)
# Test 3
phi = 40
theta = 100
gains = self.antenna1.calculate_gain(phi_vec=phi, theta_vec=theta,
co_channel=False)
- npt.assert_allclose(gains,np.array([1.6667]),atol=eps)
-
+ npt.assert_allclose(gains, np.array([1.6667]), atol=eps)
+
def test_normalization(self):
# Create dummy normalization data
adjacent_antenna_model = "SINGLE_ELEMENT"
normalization = True
norm_data = {'norm_file': 'dummy_file.npz',
'resolution': 1,
- 'phi_range': (-180,+180),
- 'theta_range': (0,180),
- 'correction_factor_co_channel': np.ones((360,180)),
+ 'phi_range': (-180, +180),
+ 'theta_range': (0, 180),
+ 'correction_factor_co_channel': np.ones((360, 180)),
'error_co_channel': 0.0,
'correction_factor_adj_channel': 5,
'error_adj_channel': 0.0,
@@ -372,20 +375,20 @@ def test_normalization(self):
multiplication_factor,
minimum_array_gain,
downtilt)
-
-
+
# Create antenna objects
- self.antenna3 = AntennaBeamformingImt(par,0.0,0.0) # Normalized
- par = par._replace(normalization = False)
- self.antenna4 = AntennaBeamformingImt(par,0.0,0.0) # Unormalized
-
+ self.antenna3 = AntennaBeamformingImt(par, 0.0, 0.0) # Normalized
+ par = par._replace(normalization=False)
+ self.antenna4 = AntennaBeamformingImt(par, 0.0, 0.0) # Unormalized
+
# Test co-channel gain: no beam
phi_v = np.array([11.79, -0.71])
theta_v = np.array([50.31, 120.51])
- gain_ref = self.antenna4.calculate_gain(phi_vec=phi_v, theta_vec=theta_v)
+ gain_ref = self.antenna4.calculate_gain(
+ phi_vec=phi_v, theta_vec=theta_v)
gain = self.antenna3.calculate_gain(phi_vec=phi_v, theta_vec=theta_v)
- npt.assert_equal(gain,gain_ref + 1)
-
+ npt.assert_equal(gain, gain_ref + 1)
+
# Test co-channel gain: add beam
phi_scan = 11.79
theta_tilt = 185.31
@@ -393,126 +396,128 @@ def test_normalization(self):
self.antenna4.add_beam(phi_scan, theta_tilt)
beams_l = np.zeros_like(phi_v, dtype=int)
gain_ref = self.antenna4.calculate_gain(phi_vec=phi_v, theta_vec=theta_v,
- beams_l=beams_l)
+ beams_l=beams_l)
gain = self.antenna3.calculate_gain(phi_vec=phi_v, theta_vec=theta_v,
- beams_l=beams_l)
- npt.assert_equal(gain,gain_ref + 1)
-
+ beams_l=beams_l)
+ npt.assert_equal(gain, gain_ref + 1)
+
# Test adjacent channel
phi_v = np.array([11.79, -0.71])
theta_v = np.array([50.31, 120.51])
- gain_ref = self.antenna4.calculate_gain(phi_vec=phi_v, theta_vec=theta_v, co_channel=False)
- gain = self.antenna3.calculate_gain(phi_vec=phi_v, theta_vec=theta_v, co_channel=False)
- npt.assert_equal(gain,gain_ref + 5)
+ gain_ref = self.antenna4.calculate_gain(
+ phi_vec=phi_v, theta_vec=theta_v, co_channel=False)
+ gain = self.antenna3.calculate_gain(
+ phi_vec=phi_v, theta_vec=theta_v, co_channel=False)
+ npt.assert_equal(gain, gain_ref + 5)
def test_to_local_coord(self):
# Test 1
# Create antenna object
- par = self.param.get_antenna_parameters(StationType.IMT_BS)
+ par = self.bs_param.get_antenna_parameters()
azi = 0.0
ele = 90.0
- self.antenna3 = AntennaBeamformingImt(par,azi,ele)
-
+ self.antenna3 = AntennaBeamformingImt(par, azi, ele)
+
# Angles to be converted: z, x and y axis
- phi = np.array([ 0, 90, 0])
+ phi = np.array([0, 90, 0])
theta = np.array([90, 90, 0])
# Convert to local coordinates
lo_phi, lo_theta = self.antenna3.to_local_coord(phi, theta)
- exp_lo_phi = np.array([0,90,0])
- exp_lo_theta = np.array([180,90,90])
- npt.assert_array_almost_equal(lo_phi,exp_lo_phi,decimal=2)
- npt.assert_array_almost_equal(lo_theta,exp_lo_theta,decimal=2)
-
+ exp_lo_phi = np.array([0, 90, 0])
+ exp_lo_theta = np.array([180, 90, 90])
+ npt.assert_array_almost_equal(lo_phi, exp_lo_phi, decimal=2)
+ npt.assert_array_almost_equal(lo_theta, exp_lo_theta, decimal=2)
+
# Test 2
# Create antenna object
azi = -15.0
ele = 90.0
- self.antenna3 = AntennaBeamformingImt(par,azi,ele)
-
+ self.antenna3 = AntennaBeamformingImt(par, azi, ele)
+
# Angles to be converted
- phi = np.array([ 0, 0, 90, 10])
+ phi = np.array([0, 0, 90, 10])
theta = np.array([0, 90, 90, 90])
# Convert to local coordinates
lo_phi, lo_theta = self.antenna3.to_local_coord(phi, theta)
exp_lo_phi = np.array([0, 90, 90, 90])
exp_lo_theta = np.array([90, 165, 75, 155])
- npt.assert_array_almost_equal(lo_phi,exp_lo_phi,decimal=2)
- npt.assert_array_almost_equal(lo_theta,exp_lo_theta,decimal=2)
-
+ npt.assert_array_almost_equal(lo_phi, exp_lo_phi, decimal=2)
+ npt.assert_array_almost_equal(lo_theta, exp_lo_theta, decimal=2)
+
# Test 3
# Create antenna object
azi = +15.0
ele = 90.0
- self.antenna3 = AntennaBeamformingImt(par,azi,ele)
-
+ self.antenna3 = AntennaBeamformingImt(par, azi, ele)
+
# Angles to be converted: z, x and y axis
- phi = np.array([ 0, 0, 90])
+ phi = np.array([0, 0, 90])
theta = np.array([0, 90, 90])
# Convert to local coordinates
lo_phi, lo_theta = self.antenna3.to_local_coord(phi, theta)
- exp_lo_phi = np.array([0,-90, 90])
+ exp_lo_phi = np.array([0, -90, 90])
exp_lo_theta = np.array([90, 165, 105])
- npt.assert_array_almost_equal(lo_phi,exp_lo_phi,decimal=2)
- npt.assert_array_almost_equal(lo_theta,exp_lo_theta,decimal=2)
-
+ npt.assert_array_almost_equal(lo_phi, exp_lo_phi, decimal=2)
+ npt.assert_array_almost_equal(lo_theta, exp_lo_theta, decimal=2)
+
# Test 4
# Create antenna object
azi = 0.0
ele = 15.0
- self.antenna3 = AntennaBeamformingImt(par,azi,ele)
-
+ self.antenna3 = AntennaBeamformingImt(par, azi, ele)
+
# Angles to be converted: z, x and y axis
- phi = np.array([ 0, 0, 90])
+ phi = np.array([0, 0, 90])
theta = np.array([0, 90, 90])
# Convert to local coordinates
lo_phi, lo_theta = self.antenna3.to_local_coord(phi, theta)
exp_lo_phi = np.array([0, 0, 90])
exp_lo_theta = np.array([15, 105, 90])
- npt.assert_array_almost_equal(lo_phi,exp_lo_phi,decimal=2)
- npt.assert_array_almost_equal(lo_theta,exp_lo_theta,decimal=2)
-
+ npt.assert_array_almost_equal(lo_phi, exp_lo_phi, decimal=2)
+ npt.assert_array_almost_equal(lo_theta, exp_lo_theta, decimal=2)
+
# Test 5
# Create antenna object
azi = 0.0
ele = -15.0
- self.antenna3 = AntennaBeamformingImt(par,azi,ele)
-
+ self.antenna3 = AntennaBeamformingImt(par, azi, ele)
+
# Angles to be converted: z, x and y axis
- phi = np.array([ 0, 0, 90])
+ phi = np.array([0, 0, 90])
theta = np.array([0, 90, 90])
# Convert to local coordinates
lo_phi, lo_theta = self.antenna3.to_local_coord(phi, theta)
exp_lo_phi = np.array([180, 0, 90])
exp_lo_theta = np.array([15, 75, 90])
- npt.assert_array_almost_equal(lo_phi,exp_lo_phi,decimal=2)
- npt.assert_array_almost_equal(lo_theta,exp_lo_theta,decimal=2)
-
+ npt.assert_array_almost_equal(lo_phi, exp_lo_phi, decimal=2)
+ npt.assert_array_almost_equal(lo_theta, exp_lo_theta, decimal=2)
+
# Test 6
# Create antenna object
azi = 180.0
ele = 45.0
- self.antenna3 = AntennaBeamformingImt(par,azi,ele)
-
+ self.antenna3 = AntennaBeamformingImt(par, azi, ele)
+
# Angles to be converted: z, x and y axis
- phi = np.array([ 0, 0, 90])
+ phi = np.array([0, 0, 90])
theta = np.array([0, 90, 90])
# Convert to local coordinates
lo_phi, lo_theta = self.antenna3.to_local_coord(phi, theta)
exp_lo_phi = np.array([0, -180, -90])
exp_lo_theta = np.array([45, 45, 90])
- npt.assert_array_almost_equal(lo_phi,exp_lo_phi,decimal=2)
- npt.assert_array_almost_equal(lo_theta,exp_lo_theta,decimal=2)
-
-
+ npt.assert_array_almost_equal(lo_phi, exp_lo_phi, decimal=2)
+ npt.assert_array_almost_equal(lo_theta, exp_lo_theta, decimal=2)
+
+
if __name__ == '__main__':
unittest.main()
-#
+#
# suite = unittest.TestSuite()
# suite.addTest(AntennaBeamformingImtTest('test_calculate_gain'))
# unittest.TextTestRunner().run(suite)
diff --git a/tests/test_antenna_beamforming_imt_f1336.py b/tests/test_antenna_beamforming_imt_f1336.py
index 5de5cc399..8f452ae9e 100644
--- a/tests/test_antenna_beamforming_imt_f1336.py
+++ b/tests/test_antenna_beamforming_imt_f1336.py
@@ -10,181 +10,171 @@
import numpy.testing as npt
from sharc.antenna.antenna_beamforming_imt import AntennaBeamformingImt
-from sharc.parameters.parameters_antenna_imt import ParametersAntennaImt
+from sharc.parameters.imt.parameters_antenna_imt import ParametersAntennaImt
from sharc.support.named_tuples import AntennaPar
from sharc.support.enumerations import StationType
+
class AntennaBeamformingImtF1336Test(unittest.TestCase):
def setUp(self):
- #Array parameters
- self.param = ParametersAntennaImt()
-
- self.param.adjacent_antenna_model = "SINGLE_ELEMENT"
- self.param.bs_element_pattern = "F1336"
- self.param.bs_minimum_array_gain = -200
- self.param.bs_normalization = False
- self.param.bs_downtilt = 0
-
- self.param.bs_normalization_file = None
- self.param.bs_element_max_g = 18
- self.param.bs_element_phi_3db = 65
- self.param.bs_element_theta_3db = 0
- self.param.bs_n_rows = 1
- self.param.bs_n_columns = 1
-
- self.param.bs_element_am = 30
- self.param.bs_element_sla_v = 30
- self.param.bs_element_horiz_spacing = 0.5
- self.param.bs_element_vert_spacing = 0.5
- self.param.bs_multiplication_factor = 12
+ # Array parameters
+ self.bs_param = ParametersAntennaImt()
+
+ self.bs_param.adjacent_antenna_model = "SINGLE_ELEMENT"
+ self.bs_param.element_pattern = "F1336"
+ self.bs_param.minimum_array_gain = -200
+ self.bs_param.normalization = False
+ self.bs_param.downtilt = 0
+
+ self.bs_param.normalization_file = None
+ self.bs_param.element_max_g = 18
+ self.bs_param.element_phi_3db = 65
+ self.bs_param.element_theta_3db = 0
+ self.bs_param.n_rows = 1
+ self.bs_param.n_columns = 1
+
+ self.bs_param.element_am = 30
+ self.bs_param.element_sla_v = 30
+ self.bs_param.element_horiz_spacing = 0.5
+ self.bs_param.element_vert_spacing = 0.5
+ self.bs_param.multiplication_factor = 12
# Create antenna objects
- par = self.param.get_antenna_parameters(StationType.IMT_BS)
+ par = self.bs_param.get_antenna_parameters()
self.antenna1 = AntennaBeamformingImt(par, 300, -10)
-
def test_azimuth(self):
self.assertEqual(self.antenna1.azimuth, 300)
-
def test_elevation(self):
self.assertEqual(self.antenna1.elevation, -10)
-
def test_g_max(self):
self.assertEqual(self.antenna1.element.g_max, 18)
-
def test_phi_3db(self):
self.assertEqual(self.antenna1.element.phi_3db, 65)
-
def test_theta_3db(self):
- self.assertAlmostEqual(self.antenna1.element.theta_3db, 7.55, delta = 1e-2)
-
+ self.assertAlmostEqual(
+ self.antenna1.element.theta_3db, 7.55, delta=1e-2)
def test_n_rows(self):
self.assertEqual(self.antenna1.n_rows, 1)
-
def test_n_cols(self):
self.assertEqual(self.antenna1.n_cols, 1)
-
def test_beams_list(self):
self.assertEqual(len(self.antenna1.beams_list), 0)
-
def test_w_vec_list(self):
self.assertEqual(len(self.antenna1.w_vec_list), 0)
-
def test_super_position_vector(self):
phi = 0
theta = 0
v_vec = self.antenna1._super_position_vector(phi, theta)
expected_v_vec = np.array([[1]])
- npt.assert_allclose(np.real(v_vec),
- np.real(expected_v_vec),
- atol = 1e-2)
- npt.assert_allclose(np.imag(v_vec),
- np.imag(expected_v_vec),
- atol = 1e-2)
+ npt.assert_allclose(np.real(v_vec),
+ np.real(expected_v_vec),
+ atol=1e-2)
+ npt.assert_allclose(np.imag(v_vec),
+ np.imag(expected_v_vec),
+ atol=1e-2)
phi = 90
theta = 90
v_vec = self.antenna1._super_position_vector(phi, theta)
expected_v_vec = np.array([[1]])
- npt.assert_allclose(np.real(v_vec),
- np.real(expected_v_vec),
- atol = 1e-2)
- npt.assert_allclose(np.imag(v_vec),
- np.imag(expected_v_vec),
- atol = 1e-2)
+ npt.assert_allclose(np.real(v_vec),
+ np.real(expected_v_vec),
+ atol=1e-2)
+ npt.assert_allclose(np.imag(v_vec),
+ np.imag(expected_v_vec),
+ atol=1e-2)
phi = 45
theta = 45
v_vec = self.antenna1._super_position_vector(phi, theta)
expected_v_vec = np.array([[1]])
- npt.assert_allclose(np.real(v_vec),
- np.real(expected_v_vec),
- atol = 1e-2)
- npt.assert_allclose(np.imag(v_vec),
- np.imag(expected_v_vec),
- atol = 1e-2)
+ npt.assert_allclose(np.real(v_vec),
+ np.real(expected_v_vec),
+ atol=1e-2)
+ npt.assert_allclose(np.imag(v_vec),
+ np.imag(expected_v_vec),
+ atol=1e-2)
phi = 60
theta = 90
v_vec = self.antenna1._super_position_vector(phi, theta)
expected_v_vec = np.array([[1]])
- npt.assert_allclose(np.real(v_vec),
- np.real(expected_v_vec),
- atol = 1e-2)
- npt.assert_allclose(np.imag(v_vec),
- np.imag(expected_v_vec),
- atol = 1e-2)
-
+ npt.assert_allclose(np.real(v_vec),
+ np.real(expected_v_vec),
+ atol=1e-2)
+ npt.assert_allclose(np.imag(v_vec),
+ np.imag(expected_v_vec),
+ atol=1e-2)
def test_weight_vector(self):
phi_scan = 0
theta_tilt = 0
w_vec = self.antenna1._weight_vector(phi_scan, theta_tilt)
expected_w_vec = np.array([[1]])
- npt.assert_allclose(np.real(w_vec),
- np.real(expected_w_vec),
- atol = 1e-2)
- npt.assert_allclose(np.imag(w_vec),
- np.imag(expected_w_vec),
- atol = 1e-2)
+ npt.assert_allclose(np.real(w_vec),
+ np.real(expected_w_vec),
+ atol=1e-2)
+ npt.assert_allclose(np.imag(w_vec),
+ np.imag(expected_w_vec),
+ atol=1e-2)
phi_scan = 90
theta_tilt = 90
w_vec = self.antenna1._weight_vector(phi_scan, theta_tilt)
expected_w_vec = np.array([[1]])
- npt.assert_allclose(np.real(w_vec),
- np.real(expected_w_vec),
- atol = 1e-2)
- npt.assert_allclose(np.imag(w_vec),
- np.imag(expected_w_vec),
- atol = 1e-2)
+ npt.assert_allclose(np.real(w_vec),
+ np.real(expected_w_vec),
+ atol=1e-2)
+ npt.assert_allclose(np.imag(w_vec),
+ np.imag(expected_w_vec),
+ atol=1e-2)
phi_scan = 45
theta_tilt = 45
w_vec = self.antenna1._weight_vector(phi_scan, theta_tilt)
expected_w_vec = np.array([[1]])
- npt.assert_allclose(np.real(w_vec),
- np.real(expected_w_vec),
- atol = 1e-2)
- npt.assert_allclose(np.imag(w_vec),
- np.imag(expected_w_vec),
- atol = 1e-2)
+ npt.assert_allclose(np.real(w_vec),
+ np.real(expected_w_vec),
+ atol=1e-2)
+ npt.assert_allclose(np.imag(w_vec),
+ np.imag(expected_w_vec),
+ atol=1e-2)
phi_scan = 0
theta_tilt = 90
w_vec = self.antenna1._weight_vector(phi_scan, theta_tilt)
expected_w_vec = np.array([[1]])
- npt.assert_allclose(np.real(w_vec),
- np.real(expected_w_vec),
- atol = 1e-2)
- npt.assert_allclose(np.imag(w_vec),
- np.imag(expected_w_vec),
- atol = 1e-2)
+ npt.assert_allclose(np.real(w_vec),
+ np.real(expected_w_vec),
+ atol=1e-2)
+ npt.assert_allclose(np.imag(w_vec),
+ np.imag(expected_w_vec),
+ atol=1e-2)
phi_scan = 45
theta_tilt = 30
w_vec = self.antenna1._weight_vector(phi_scan, theta_tilt)
expected_w_vec = np.array([[1]])
- npt.assert_allclose(np.real(w_vec),
- np.real(expected_w_vec),
- atol = 1e-2)
- npt.assert_allclose(np.imag(w_vec),
- np.imag(expected_w_vec),
- atol = 1e-2)
-
+ npt.assert_allclose(np.real(w_vec),
+ np.real(expected_w_vec),
+ atol=1e-2)
+ npt.assert_allclose(np.imag(w_vec),
+ np.imag(expected_w_vec),
+ atol=1e-2)
def test_add_beam(self):
eps = 1e-5
- par = self.param.get_antenna_parameters(StationType.IMT_BS)
+ par = self.bs_param.get_antenna_parameters()
self.antenna1 = AntennaBeamformingImt(par, 0, 0)
# Add first beam
@@ -205,17 +195,17 @@ def test_add_beam(self):
self.assertEqual(len(self.antenna1.w_vec_list), 2)
# Test first beam
- self.assertAlmostEqual(self.antenna1.beams_list[0][0], 45, delta = eps)
- self.assertAlmostEqual(self.antenna1.beams_list[0][1], 30, delta = eps)
+ self.assertAlmostEqual(self.antenna1.beams_list[0][0], 45, delta=eps)
+ self.assertAlmostEqual(self.antenna1.beams_list[0][1], 30, delta=eps)
w_vec = self.antenna1.w_vec_list[0]
expected_w_vec = np.array([[1]])
- npt.assert_allclose(np.real(w_vec),
- np.real(expected_w_vec),
- atol = 1e-2)
- npt.assert_allclose(np.imag(w_vec),
- np.imag(expected_w_vec),
- atol = 1e-2)
+ npt.assert_allclose(np.real(w_vec),
+ np.real(expected_w_vec),
+ atol=1e-2)
+ npt.assert_allclose(np.imag(w_vec),
+ np.imag(expected_w_vec),
+ atol=1e-2)
# Test second beam
self.assertEqual(self.antenna1.beams_list[1][0], 90)
@@ -223,12 +213,12 @@ def test_add_beam(self):
w_vec = self.antenna1.w_vec_list[1]
expected_w_vec = np.array([[1]])
- npt.assert_allclose(np.real(w_vec),
- np.real(expected_w_vec),
- atol = 1e-2)
- npt.assert_allclose(np.imag(w_vec),
- np.imag(expected_w_vec),
- atol = 1e-2)
+ npt.assert_allclose(np.real(w_vec),
+ np.real(expected_w_vec),
+ atol=1e-2)
+ npt.assert_allclose(np.imag(w_vec),
+ np.imag(expected_w_vec),
+ atol=1e-2)
# Reset beams and test
self.antenna1.reset_beams()
@@ -238,7 +228,7 @@ def test_add_beam(self):
def test_beam_gain(self):
# Error margin and antenna
eps = 1e-2
- par = self.param.get_antenna_parameters(StationType.IMT_BS)
+ par = self.bs_param.get_antenna_parameters()
self.antenna1 = AntennaBeamformingImt(par, 0, 0)
# Test 1
@@ -249,7 +239,7 @@ def test_beam_gain(self):
theta_tilt = 135
self.antenna1.add_beam(phi_scan, theta_tilt)
beam_g = self.antenna1._beam_gain(phi, theta, beam)
- self.assertAlmostEqual(beam_g, 18, delta = eps)
+ self.assertAlmostEqual(beam_g, 18, delta=eps)
# Test 2
phi = 30
@@ -259,26 +249,26 @@ def test_beam_gain(self):
theta_tilt = 180
self.antenna1.add_beam(phi_scan, theta_tilt)
beam_g = self.antenna1._beam_gain(phi, theta, beam)
- self.assertAlmostEqual(beam_g, -1.48, delta = eps)
+ self.assertAlmostEqual(beam_g, -1.48, delta=eps)
# Test 3
phi = 150
theta = 180
beam_g = self.antenna1._beam_gain(phi, theta)
- self.assertAlmostEqual(beam_g, -6.45, delta = eps)
+ self.assertAlmostEqual(beam_g, -6.45, delta=eps)
def test_calculate_gain(self):
# Error margin and antenna
eps = 1e-2
- par = self.param.get_antenna_parameters(StationType.IMT_BS)
- self.antenna1 = AntennaBeamformingImt(par,0,0)
+ par = self.bs_param.get_antenna_parameters()
+ self.antenna1 = AntennaBeamformingImt(par, 0, 0)
# Test 1
phi_vec = np.array([0, 30])
theta_vec = np.array([90, 100])
- gains = self.antenna1.calculate_gain(phi_vec = phi_vec,
- theta_vec = theta_vec)
- npt.assert_allclose(gains,np.array([18, 4.52]), atol=eps)
+ gains = self.antenna1.calculate_gain(phi_vec=phi_vec,
+ theta_vec=theta_vec)
+ npt.assert_allclose(gains, np.array([18, 4.52]), atol=eps)
# Test 2
phi = 0
@@ -287,19 +277,19 @@ def test_calculate_gain(self):
theta_tilt = 180
self.antenna1.add_beam(phi_scan, theta_tilt)
beams_l = np.zeros_like(phi_vec, dtype=int)
- gains = self.antenna1.calculate_gain(phi_vec = phi,
- theta_vec = theta,
- beams_l = beams_l)
+ gains = self.antenna1.calculate_gain(phi_vec=phi,
+ theta_vec=theta,
+ beams_l=beams_l)
npt.assert_allclose(gains, np.array([12.74]), atol=eps)
# Test 3
phi = 5
theta = 98
- gains = self.antenna1.calculate_gain(phi_vec = phi,
- theta_vec = theta,
- co_channel = False)
- npt.assert_allclose(gains, np.array([6.81]), atol = eps)
-
-
+ gains = self.antenna1.calculate_gain(phi_vec=phi,
+ theta_vec=theta,
+ co_channel=False)
+ npt.assert_allclose(gains, np.array([6.81]), atol=eps)
+
+
if __name__ == '__main__':
unittest.main()
diff --git a/tests/test_antenna_element_imt.py b/tests/test_antenna_element_imt.py
index 92aa90357..e05df5482 100644
--- a/tests/test_antenna_element_imt.py
+++ b/tests/test_antenna_element_imt.py
@@ -9,142 +9,147 @@
import unittest
from sharc.antenna.antenna_element_imt_m2101 import AntennaElementImtM2101
-from sharc.parameters.parameters_antenna_imt import ParametersAntennaImt
+from sharc.parameters.imt.parameters_antenna_imt import ParametersAntennaImt
from sharc.support.enumerations import StationType
+
class AntennaImtTest(unittest.TestCase):
def setUp(self):
- #Element parameters
- self.param = ParametersAntennaImt()
-
- self.param.adjacent_antenna_model = "SINGLE_ELEMENT"
- self.param.bs_element_pattern = "M2101"
- self.param.ue_element_pattern = "M2101"
- self.param.bs_minimum_array_gain = -200
- self.param.ue_minimum_array_gain = -200
- self.param.bs_normalization = False
- self.param.bs_downtilt = 0
-
- self.param.bs_normalization_file = None
- self.param.bs_element_max_g = 5
- self.param.bs_element_phi_3db = 80
- self.param.bs_element_theta_3db = 60
- self.param.bs_element_am = 30
- self.param.bs_element_sla_v = 30
- self.param.bs_n_rows = 8
- self.param.bs_n_columns = 8
- self.param.bs_element_horiz_spacing = 0.5
- self.param.bs_element_vert_spacing = 0.5
- self.param.bs_multiplication_factor = 12
-
- self.param.ue_normalization_file = None
- self.param.ue_normalization = False
- self.param.ue_element_max_g = 10
- self.param.ue_element_phi_3db = 75
- self.param.ue_element_theta_3db = 65
- self.param.ue_element_am = 25
- self.param.ue_element_sla_v = 35
- self.param.ue_n_rows = 4
- self.param.ue_n_columns = 4
- self.param.ue_element_horiz_spacing = 0.5
- self.param.ue_element_vert_spacing = 0.5
- self.param.ue_multiplication_factor = 12
+ # Element parameters
+ self.ue_param = ParametersAntennaImt()
+ self.bs_param = ParametersAntennaImt()
+
+ self.bs_param.adjacent_antenna_model = "SINGLE_ELEMENT"
+ self.ue_param.adjacent_antenna_model = "SINGLE_ELEMENT"
+ self.bs_param.element_pattern = "M2101"
+ self.ue_param.element_pattern = "M2101"
+ self.bs_param.minimum_array_gain = -200
+ self.ue_param.minimum_array_gain = -200
+ self.bs_param.normalization = False
+ self.bs_param.downtilt = 0
+
+ self.bs_param.normalization_file = None
+ self.bs_param.element_max_g = 5
+ self.bs_param.element_phi_3db = 80
+ self.bs_param.element_theta_3db = 60
+ self.bs_param.element_am = 30
+ self.bs_param.element_sla_v = 30
+ self.bs_param.n_rows = 8
+ self.bs_param.n_columns = 8
+ self.bs_param.element_horiz_spacing = 0.5
+ self.bs_param.element_vert_spacing = 0.5
+ self.bs_param.multiplication_factor = 12
+
+ self.ue_param.normalization_file = None
+ self.ue_param.normalization = False
+ self.ue_param.element_max_g = 10
+ self.ue_param.element_phi_3db = 75
+ self.ue_param.element_theta_3db = 65
+ self.ue_param.element_am = 25
+ self.ue_param.element_sla_v = 35
+ self.ue_param.n_rows = 4
+ self.ue_param.n_columns = 4
+ self.ue_param.element_horiz_spacing = 0.5
+ self.ue_param.element_vert_spacing = 0.5
+ self.ue_param.multiplication_factor = 12
# Create antenna IMT objects
- par = self.param.get_antenna_parameters(StationType.IMT_BS)
+ par = self.bs_param.get_antenna_parameters()
self.antenna1 = AntennaElementImtM2101(par)
- par = self.param.get_antenna_parameters(StationType.IMT_UE)
+ par = self.ue_param.get_antenna_parameters()
self.antenna2 = AntennaElementImtM2101(par)
def test_g_max(self):
- self.assertEqual(self.antenna1.g_max,5)
- self.assertEqual(self.antenna2.g_max,10)
+ self.assertEqual(self.antenna1.g_max, 5)
+ self.assertEqual(self.antenna2.g_max, 10)
def test_phi_3db(self):
- self.assertEqual(self.antenna1.phi_3db,80)
- self.assertEqual(self.antenna2.phi_3db,75)
+ self.assertEqual(self.antenna1.phi_3db, 80)
+ self.assertEqual(self.antenna2.phi_3db, 75)
def test_theta_3db(self):
- self.assertEqual(self.antenna1.theta_3db,60)
- self.assertEqual(self.antenna2.theta_3db,65)
+ self.assertEqual(self.antenna1.theta_3db, 60)
+ self.assertEqual(self.antenna2.theta_3db, 65)
def test_am(self):
- self.assertEqual(self.antenna1.am,30)
- self.assertEqual(self.antenna2.am,25)
+ self.assertEqual(self.antenna1.am, 30)
+ self.assertEqual(self.antenna2.am, 25)
def test_sla_v(self):
- self.assertEqual(self.antenna1.sla_v,30)
- self.assertEqual(self.antenna2.sla_v,35)
+ self.assertEqual(self.antenna1.sla_v, 30)
+ self.assertEqual(self.antenna2.sla_v, 35)
def test_horizontal_pattern(self):
# phi = 0 results in zero gain
phi = 0
h_att = self.antenna1.horizontal_pattern(phi)
- self.assertEqual(h_att,0.0)
+ self.assertEqual(h_att, 0.0)
# phi = 120 implies horizontal gain of of -27 dB
phi = 120
h_att = self.antenna1.horizontal_pattern(phi)
- self.assertEqual(h_att,-27.0)
+ self.assertEqual(h_att, -27.0)
# phi = 150, horizontal attenuation equals to the front-to-back ratio
phi = 150
h_att = self.antenna1.horizontal_pattern(phi)
- self.assertEqual(h_att,-30)
- self.assertEqual(h_att,-1.0*self.antenna1.am)
+ self.assertEqual(h_att, -30)
+ self.assertEqual(h_att, -1.0 * self.antenna1.am)
# Test vector
phi = np.array([0, 120, 150])
h_att = self.antenna1.horizontal_pattern(phi)
- self.assertTrue(np.all(h_att == np.array([0.0,-27.0,-30.0])))
+ self.assertTrue(np.all(h_att == np.array([0.0, -27.0, -30.0])))
def test_vertical_pattern(self):
# theta = 90 results in zero gain
theta = 90
v_att = self.antenna1.vertical_pattern(theta)
- self.assertEqual(v_att,0.0)
+ self.assertEqual(v_att, 0.0)
# theta = 180 implies vertical gain of -27 dB
theta = 180
v_att = self.antenna1.vertical_pattern(theta)
- self.assertEqual(v_att,-27.0)
+ self.assertEqual(v_att, -27.0)
- # theta = 210, vertical attenuation equals vertical sidelobe attenuation
+ # theta = 210, vertical attenuation equals vertical sidelobe
+ # attenuation
theta = 210
v_att = self.antenna1.vertical_pattern(theta)
- self.assertEqual(v_att,-30)
- self.assertEqual(v_att,-1.0*self.antenna1.sla_v)
+ self.assertEqual(v_att, -30)
+ self.assertEqual(v_att, -1.0 * self.antenna1.sla_v)
# Test vector
theta = np.array([90, 180, 210])
v_att = self.antenna1.vertical_pattern(theta)
- self.assertTrue(np.all(v_att == np.array([0.0,-27.0,-30.0])))
+ self.assertTrue(np.all(v_att == np.array([0.0, -27.0, -30.0])))
def test_element_pattern(self):
# theta = 0 and phi = 90 result in maximum gain
phi = 0
theta = 90
- e_gain = self.antenna1.element_pattern(phi,theta)
- self.assertEqual(e_gain,5.0)
- self.assertEqual(e_gain,self.antenna1.g_max)
+ e_gain = self.antenna1.element_pattern(phi, theta)
+ self.assertEqual(e_gain, 5.0)
+ self.assertEqual(e_gain, self.antenna1.g_max)
phi = 80
theta = 150
- e_gain = self.antenna1.element_pattern(phi,theta)
- self.assertEqual(e_gain,-19.0)
+ e_gain = self.antenna1.element_pattern(phi, theta)
+ self.assertEqual(e_gain, -19.0)
phi = 150
theta = 210
- e_gain = self.antenna1.element_pattern(phi,theta)
- self.assertEqual(e_gain,-25.0)
- self.assertEqual(e_gain,self.antenna1.g_max - self.antenna1.am)
+ e_gain = self.antenna1.element_pattern(phi, theta)
+ self.assertEqual(e_gain, -25.0)
+ self.assertEqual(e_gain, self.antenna1.g_max - self.antenna1.am)
# Test vector
- phi = np.array([0,80,150])
- theta = np.array([90,150,210])
- e_gain = self.antenna1.element_pattern(phi,theta)
- self.assertTrue(np.all(e_gain == np.array([5.0,-19.0,-25.0])))
+ phi = np.array([0, 80, 150])
+ theta = np.array([90, 150, 210])
+ e_gain = self.antenna1.element_pattern(phi, theta)
+ self.assertTrue(np.all(e_gain == np.array([5.0, -19.0, -25.0])))
+
if __name__ == '__main__':
unittest.main()
diff --git a/tests/test_antenna_element_imt_f1336.py b/tests/test_antenna_element_imt_f1336.py
index e27b2beb1..49cda9954 100644
--- a/tests/test_antenna_element_imt_f1336.py
+++ b/tests/test_antenna_element_imt_f1336.py
@@ -10,36 +10,37 @@
import numpy.testing as npt
from sharc.antenna.antenna_element_imt_f1336 import AntennaElementImtF1336
-from sharc.parameters.parameters_antenna_imt import ParametersAntennaImt
+from sharc.parameters.imt.parameters_antenna_imt import ParametersAntennaImt
from sharc.support.enumerations import StationType
+
class AntennaElementImtF1336Test(unittest.TestCase):
def setUp(self):
- #Element parameters
- self.param = ParametersAntennaImt()
-
- self.param.adjacent_antenna_model = "SINGLE_ELEMENT"
- self.param.bs_element_pattern = "F1336"
- self.param.bs_minimum_array_gain = -200
- self.param.bs_normalization = False
- self.param.bs_downtilt = 0
-
- self.param.bs_normalization_file = None
- self.param.bs_element_max_g = 18
- self.param.bs_element_phi_3db = 65
- self.param.bs_element_theta_3db = 0
- self.param.bs_n_rows = 1
- self.param.bs_n_columns = 1
-
- self.param.bs_element_am = 30
- self.param.bs_element_sla_v = 30
- self.param.bs_element_horiz_spacing = 0.5
- self.param.bs_element_vert_spacing = 0.5
- self.param.bs_multiplication_factor = 12
+ # Element parameters
+ self.bs_param = ParametersAntennaImt()
+
+ self.bs_param.adjacent_antenna_model = "SINGLE_ELEMENT"
+ self.bs_param.element_pattern = "F1336"
+ self.bs_param.minimum_array_gain = -200
+ self.bs_param.normalization = False
+ self.bs_param.downtilt = 0
+
+ self.bs_param.normalization_file = None
+ self.bs_param.element_max_g = 18
+ self.bs_param.element_phi_3db = 65
+ self.bs_param.element_theta_3db = 0
+ self.bs_param.n_rows = 1
+ self.bs_param.n_columns = 1
+
+ self.bs_param.element_am = 30
+ self.bs_param.element_sla_v = 30
+ self.bs_param.element_horiz_spacing = 0.5
+ self.bs_param.element_vert_spacing = 0.5
+ self.bs_param.multiplication_factor = 12
# Create antenna IMT objects
- par = self.param.get_antenna_parameters(StationType.IMT_BS)
+ par = self.bs_param.get_antenna_parameters()
self.antenna1 = AntennaElementImtF1336(par)
def test_g_max(self):
@@ -49,58 +50,55 @@ def test_phi_3db(self):
self.assertEqual(self.antenna1.phi_3db, 65)
def test_theta_3db(self):
- self.assertAlmostEqual(self.antenna1.theta_3db, 7.55, delta = 1e-2)
+ self.assertAlmostEqual(self.antenna1.theta_3db, 7.55, delta=1e-2)
def test_antenna_parameters(self):
- self.assertAlmostEqual(self.antenna1.k_a, 0.7, delta = 1e-2)
- self.assertAlmostEqual(self.antenna1.k_p, 0.7, delta = 1e-2)
- self.assertAlmostEqual(self.antenna1.k_h, 0.7, delta = 1e-2)
- self.assertAlmostEqual(self.antenna1.lambda_k_h, -1.87, delta = 1e-2)
- self.assertAlmostEqual(self.antenna1.k_v, 0.3, delta = 1e-2)
- self.assertAlmostEqual(self.antenna1.incline_factor, 18.45, delta = 1e-2)
- self.assertAlmostEqual(self.antenna1.x_k, 0.94, delta = 1e-2)
- self.assertAlmostEqual(self.antenna1.lambda_k_v, 4.60, delta = 1e-2)
- self.assertAlmostEqual(self.antenna1.g_hr_180, -24.45, delta = 1e-2)
- self.assertAlmostEqual(self.antenna1.g_hr_0, 0, delta = 1e-2)
-
-
+ self.assertAlmostEqual(self.antenna1.k_a, 0.7, delta=1e-2)
+ self.assertAlmostEqual(self.antenna1.k_p, 0.7, delta=1e-2)
+ self.assertAlmostEqual(self.antenna1.k_h, 0.7, delta=1e-2)
+ self.assertAlmostEqual(self.antenna1.lambda_k_h, -1.87, delta=1e-2)
+ self.assertAlmostEqual(self.antenna1.k_v, 0.3, delta=1e-2)
+ self.assertAlmostEqual(self.antenna1.incline_factor, 18.45, delta=1e-2)
+ self.assertAlmostEqual(self.antenna1.x_k, 0.94, delta=1e-2)
+ self.assertAlmostEqual(self.antenna1.lambda_k_v, 4.60, delta=1e-2)
+ self.assertAlmostEqual(self.antenna1.g_hr_180, -24.45, delta=1e-2)
+ self.assertAlmostEqual(self.antenna1.g_hr_0, 0, delta=1e-2)
+
def test_horizontal_pattern(self):
phi = 0
h_att = self.antenna1.horizontal_pattern(phi)
- self.assertAlmostEqual(h_att, 0, delta = 1e-2)
+ self.assertAlmostEqual(h_att, 0, delta=1e-2)
phi = 30
h_att = self.antenna1.horizontal_pattern(phi)
- self.assertAlmostEqual(h_att, -2.55, delta = 1e-2)
+ self.assertAlmostEqual(h_att, -2.55, delta=1e-2)
phi = 150
h_att = self.antenna1.horizontal_pattern(phi)
- self.assertAlmostEqual(h_att, -24.45, delta = 1e-2)
+ self.assertAlmostEqual(h_att, -24.45, delta=1e-2)
# Test vector
phi = np.array([0, 30, 150])
h_att = self.antenna1.horizontal_pattern(phi)
- npt.assert_allclose(h_att, np.array([0, -2.55, -24.45]), atol = 1e-2)
-
+ npt.assert_allclose(h_att, np.array([0, -2.55, -24.45]), atol=1e-2)
def test_vertical_pattern(self):
theta = 90
v_att = self.antenna1.vertical_pattern(theta)
- self.assertAlmostEqual(v_att, 0, delta = 1e-2)
+ self.assertAlmostEqual(v_att, 0, delta=1e-2)
theta = 135
v_att = self.antenna1.vertical_pattern(theta)
- self.assertAlmostEqual(v_att, -18.90, delta = 1e-2)
+ self.assertAlmostEqual(v_att, -18.90, delta=1e-2)
theta = 180
v_att = self.antenna1.vertical_pattern(theta)
- self.assertAlmostEqual(v_att, -24.45, delta = 1e-2)
+ self.assertAlmostEqual(v_att, -24.45, delta=1e-2)
# Test vector
theta = np.array([90, 135, 180])
v_att = self.antenna1.vertical_pattern(theta)
- npt.assert_allclose(v_att, np.array([0, -18.90, -24.45]), atol = 1e-2)
-
+ npt.assert_allclose(v_att, np.array([0, -18.90, -24.45]), atol=1e-2)
def test_element_pattern(self):
phi = 0
@@ -112,18 +110,19 @@ def test_element_pattern(self):
phi = 30
theta = 135
e_gain = self.antenna1.element_pattern(phi, theta)
- self.assertAlmostEqual(e_gain, -1.48, delta = 1e-2)
+ self.assertAlmostEqual(e_gain, -1.48, delta=1e-2)
phi = 150
theta = 180
e_gain = self.antenna1.element_pattern(phi, theta)
- self.assertAlmostEqual(e_gain, -6.45, delta = 1e-2)
+ self.assertAlmostEqual(e_gain, -6.45, delta=1e-2)
# Test vector
phi = np.array([0, 30, 150])
theta = np.array([90, 135, 180])
e_gain = self.antenna1.element_pattern(phi, theta)
- npt.assert_allclose(e_gain, np.array([18, -1.48, -6.45]), atol = 1e-2)
+ npt.assert_allclose(e_gain, np.array([18, -1.48, -6.45]), atol=1e-2)
+
if __name__ == '__main__':
unittest.main()
diff --git a/tests/test_antenna_fss_ss.py b/tests/test_antenna_fss_ss.py
index 4b4976e40..c311fff0d 100644
--- a/tests/test_antenna_fss_ss.py
+++ b/tests/test_antenna_fss_ss.py
@@ -13,6 +13,7 @@
import numpy as np
import numpy.testing as npt
+
class AntennaFssSsTest(unittest.TestCase):
def setUp(self):
@@ -27,16 +28,19 @@ def setUp(self):
param.antenna_l_s = -30
self.antenna30 = AntennaFssSs(param)
-
def test_calculate_gain(self):
psi = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100])
- ref_gain25 = np.array([0, -3, -12, -28, -28, -28, -28, -29.12, -30.57, -31.85, -33, -53])
- gain25 = self.antenna25.calculate_gain(off_axis_angle_vec=psi) - self.antenna25.peak_gain
+ ref_gain25 = np.array(
+ [0, -3, -12, -28, -28, -28, -28, -29.12, -30.57, -31.85, -33, -53])
+ gain25 = self.antenna25.calculate_gain(
+ off_axis_angle_vec=psi) - self.antenna25.peak_gain
npt.assert_allclose(gain25, ref_gain25, atol=1e-2)
- ref_gain30 = np.array([0, -3, -12, -27, -33, -33, -33, -34.12, -35.57, -36.85, -38, -53])
- gain30 = self.antenna30.calculate_gain(off_axis_angle_vec=psi) - self.antenna30.peak_gain
+ ref_gain30 = np.array(
+ [0, -3, -12, -27, -33, -33, -33, -34.12, -35.57, -36.85, -38, -53])
+ gain30 = self.antenna30.calculate_gain(
+ off_axis_angle_vec=psi) - self.antenna30.peak_gain
npt.assert_allclose(gain30, ref_gain30, atol=1e-2)
diff --git a/tests/test_antenna_omni.py b/tests/test_antenna_omni.py
index 66d2f39b0..327318bd6 100644
--- a/tests/test_antenna_omni.py
+++ b/tests/test_antenna_omni.py
@@ -10,40 +10,41 @@
from sharc.antenna.antenna_omni import AntennaOmni
+
class AntennaOmniTest(unittest.TestCase):
-
+
def setUp(self):
self.antenna1 = AntennaOmni()
self.antenna1.gain = 5
-
+
self.antenna2 = AntennaOmni()
self.antenna2.gain = 8.0
-
+
self.antenna3 = AntennaOmni(10)
-
+
def test_gain(self):
self.assertEqual(self.antenna1.gain, 5)
self.assertEqual(self.antenna2.gain, 8)
self.assertEqual(self.antenna3.gain, 10)
-
+
def test_calculate_gain(self):
phi = [30, 60, 90, 45]
-
+
# Test antenna1
gains1 = self.antenna1.calculate_gain(phi_vec=phi)
self.assertEqual(len(gains1), len(phi))
npt.assert_allclose(gains1, self.antenna1.gain)
-
+
# Test antenna2
gains2 = self.antenna2.calculate_gain(phi_vec=phi)
self.assertEqual(len(gains2), len(phi))
npt.assert_allclose(gains2, self.antenna2.gain)
-
+
# Test antenna3
gains3 = self.antenna3.calculate_gain(phi_vec=phi)
self.assertEqual(len(gains3), len(phi))
npt.assert_allclose(gains3, self.antenna3.gain)
-
-
+
+
if __name__ == '__main__':
unittest.main()
diff --git a/tests/test_antenna_s1528.py b/tests/test_antenna_s1528.py
index f2984a769..1ce09e3b9 100644
--- a/tests/test_antenna_s1528.py
+++ b/tests/test_antenna_s1528.py
@@ -13,6 +13,7 @@
import numpy as np
import numpy.testing as npt
+
class AntennaS1528Test(unittest.TestCase):
def setUp(self):
@@ -30,13 +31,29 @@ def setUp(self):
def test_calculate_gain(self):
psi = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 80, 100])
- ref_gain20 = np.array([0, -3, -8.48, -20, -20, -20, -20, -21.10, -22.55, -23.83, -24.98, -39, -34.25])
- gain20 = self.antenna20.calculate_gain(off_axis_angle_vec=psi) - self.antenna20.peak_gain
+ ref_gain20 = np.array([0, -
+ 3, -
+ 8.48, -
+ 20, -
+ 20, -
+ 20, -
+ 20, -
+ 21.10, -
+ 22.55, -
+ 23.83, -
+ 24.98, -
+ 39, -
+ 34.25])
+ gain20 = self.antenna20.calculate_gain(
+ off_axis_angle_vec=psi) - self.antenna20.peak_gain
npt.assert_allclose(gain20, ref_gain20, atol=1e-2)
- ref_gain30 = np.array([0, -3, -8.48, -30, -30, -30, -30, -31.10, -32.55, -33.83, -34.98, -39, -39])
- gain30 = self.antenna30.calculate_gain(off_axis_angle_vec=psi) - self.antenna30.peak_gain
+ ref_gain30 = np.array(
+ [0, -3, -8.48, -30, -30, -30, -30, -31.10, -32.55, -33.83, -34.98, -39, -39])
+ gain30 = self.antenna30.calculate_gain(
+ off_axis_angle_vec=psi) - self.antenna30.peak_gain
npt.assert_allclose(gain30, ref_gain30, atol=1e-2)
+
if __name__ == '__main__':
unittest.main()
diff --git a/tests/test_antenna_s1855.py b/tests/test_antenna_s1855.py
index a23c770b0..e4834e19d 100644
--- a/tests/test_antenna_s1855.py
+++ b/tests/test_antenna_s1855.py
@@ -13,10 +13,11 @@
from sharc.antenna.antenna_s1855 import AntennaS1855
from sharc.parameters.parameters_fss_es import ParametersFssEs
+
class AntennaS1855Test(unittest.TestCase):
def setUp(self):
- #Earth Station Antenna parameters
+ # Earth Station Antenna parameters
params = ParametersFssEs()
params.diameter = 9.1
params.frequency = 27200
@@ -31,10 +32,11 @@ def test_get_gain(self):
off_axis_angle = np.array([7, 8, 15, 100])
theta = np.array([90, 45, 45, 45])
- expected_result = np.array([ 10.87, 8.71, 2.59, -10 ])
- gain = self.antenna.calculate_gain(off_axis_angle_vec = off_axis_angle,
- theta_vec = theta)
+ expected_result = np.array([10.87, 8.71, 2.59, -10])
+ gain = self.antenna.calculate_gain(off_axis_angle_vec=off_axis_angle,
+ theta_vec=theta)
npt.assert_allclose(gain, expected_result, atol=1e-2)
+
if __name__ == '__main__':
unittest.main()
diff --git a/tests/test_antenna_s672.py b/tests/test_antenna_s672.py
index e694e0cdb..22c73bf6a 100644
--- a/tests/test_antenna_s672.py
+++ b/tests/test_antenna_s672.py
@@ -13,6 +13,7 @@
import numpy as np
import numpy.testing as npt
+
class AntennaS672Test(unittest.TestCase):
def setUp(self):
@@ -27,17 +28,21 @@ def setUp(self):
param.antenna_l_s = -30
self.antenna30 = AntennaS672(param)
-
def test_calculate_gain(self):
psi = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 100])
- ref_gain20 = np.array([0, -3, -12, -20, -20, -20, -20, -21.12, -22.57, -23.85, -25, -50])
- gain20 = self.antenna20.calculate_gain(off_axis_angle_vec=psi) - self.antenna20.peak_gain
+ ref_gain20 = np.array(
+ [0, -3, -12, -20, -20, -20, -20, -21.12, -22.57, -23.85, -25, -50])
+ gain20 = self.antenna20.calculate_gain(
+ off_axis_angle_vec=psi) - self.antenna20.peak_gain
npt.assert_allclose(gain20, ref_gain20, atol=1e-2)
- ref_gain30 = np.array([0, -3, -12, -27, -30, -30, -30, -31.12, -32.57, -33.85, -35, -50])
- gain30 = self.antenna30.calculate_gain(off_axis_angle_vec=psi) - self.antenna30.peak_gain
+ ref_gain30 = np.array(
+ [0, -3, -12, -27, -30, -30, -30, -31.12, -32.57, -33.85, -35, -50])
+ gain30 = self.antenna30.calculate_gain(
+ off_axis_angle_vec=psi) - self.antenna30.peak_gain
npt.assert_allclose(gain30, ref_gain30, atol=1e-2)
+
if __name__ == '__main__':
unittest.main()
diff --git a/tests/test_antenna_sa509.py b/tests/test_antenna_sa509.py
index 04586b5ac..d148b6442 100644
--- a/tests/test_antenna_sa509.py
+++ b/tests/test_antenna_sa509.py
@@ -12,29 +12,29 @@
import unittest
import numpy.testing as npt
+
class AntennaSA509Test(unittest.TestCase):
def setUp(self):
- self.par = ParametersRas();
+ self.par = ParametersRas()
self.par.diameter = 10
self.par.antenna_efficiency = 1
self.par.frequency = 30000
- self.par.SPEED_OF_LIGHT = 3e8
self.antenna = AntennaSA509(self.par)
def test_construction(self):
- self.assertEqual(self.antenna.diameter,10)
- self.assertEqual(self.antenna.efficiency,1)
- self.assertEqual(self.antenna.wavelength,1e-2)
+ self.assertEqual(self.antenna.diameter, 10)
+ self.assertEqual(self.antenna.efficiency, 1)
+ self.assertAlmostEqual(self.antenna.wavelength, 1e-2, places=3)
- self.assertAlmostEqual(self.antenna.effective_area,78.539,delta=1e-2)
+ self.assertAlmostEqual(self.antenna.effective_area, 78.539, delta=1e-2)
- self.assertAlmostEqual(self.antenna.g_0,69.943,delta=1e-2)
- self.assertAlmostEqual(self.antenna.phi_0,0.03464,delta=1e-4)
+ self.assertAlmostEqual(self.antenna.g_0, 69.943, delta=1e-2)
+ self.assertAlmostEqual(self.antenna.phi_0, 0.03464, delta=1e-4)
- self.assertAlmostEqual(self.antenna.phi_1,0.08944,delta=1e-4)
- self.assertAlmostEqual(self.antenna.phi_2,0.14531,delta=1e-4)
+ self.assertAlmostEqual(self.antenna.phi_1, 0.08944, delta=1e-4)
+ self.assertAlmostEqual(self.antenna.phi_2, 0.14531, delta=1e-4)
def test_calculate_gain(self):
phi = np.array([0.03464, 0.05, 0.1, 10, 25, 50, 100, 150])
diff --git a/tests/test_atmosphere.py b/tests/test_atmosphere.py
index 5c3dfa1e0..6dbcb3820 100644
--- a/tests/test_atmosphere.py
+++ b/tests/test_atmosphere.py
@@ -10,14 +10,15 @@
import numpy.testing as npt
from sharc.propagation.atmosphere import ReferenceAtmosphere
+
class TestAtmosphere(unittest.TestCase):
def setUp(self):
self.atmosphere = ReferenceAtmosphere()
def test_specific_attenuation(self):
- temperature = 15 + 273.15 # K
- vapour_density = 7.5 # g/m**3
+ temperature = 15 + 273.15 # K
+ vapour_density = 7.5 # g/m**3
pressure_hPa = 1013.25
vapour_pressure_hPa = vapour_density * temperature / 216.7
@@ -35,5 +36,6 @@ def test_specific_attenuation(self):
npt.assert_array_less(specific_att_p676_lower, specific_att)
npt.assert_array_less(specific_att, specific_att_p676_upper)
+
if __name__ == '__main__':
unittest.main()
diff --git a/tests/test_footprint.py b/tests/test_footprint.py
index a2710d4c8..ea8883b37 100644
--- a/tests/test_footprint.py
+++ b/tests/test_footprint.py
@@ -3,54 +3,142 @@
Created on Mon Nov 27 08:53:15 2017
@author: Calil
+
+Updated on Sun Jul 29 21:34:07 2024
+
+Request for Issue 33 correction suggestion, adding the unitary tests for LEO type satellite in 600Km and 1200Km heights.
+
+@author: Thiago Ferreira
"""
+# Thiago Ferreira - 231025717
+
+# from footprint import Footprint # Old importing for testing and debugging space
+# Importing Footprint class from the given module in repository
+from sharc.support.footprint import Footprint
import unittest
import numpy as np
import numpy.testing as npt
-from sharc.support.footprint import Footprint
+# Added the matplotlib for plotting the footprint generated in the test
+import matplotlib.pyplot as plt
+
+
+class FootprintTest(unittest.TestCase):
+ """
+ Unit testing class for Footprint calculations, focusing on different satellite configurations
+ such as beam width, elevation angle, and satellite height.
+ """
-class FootprintAreaTest(unittest.TestCase):
-
def setUp(self):
- self.fa1 = Footprint(0.1,bore_lat_deg=0,bore_subsat_long_deg=0.0)
- self.fa2 = Footprint(0.325,bore_lat_deg = 0)
- self.fa3 = Footprint(0.325,elevation_deg = 20)
-
+ """
+ Set up the test environment by initializing Footprint instances with different parameters.
+ """
+ # Geostationary (GEO type) satellite height (35786000 m) and different
+ # beam widths and elevations
+ self.fa1 = Footprint(0.1, bore_lat_deg=0, bore_subsat_long_deg=0.0)
+ self.fa2 = Footprint(0.325, bore_lat_deg=0)
+ self.fa3 = Footprint(0.325, elevation_deg=20)
+ self.fa4 = Footprint(0.325, elevation_deg=30, sat_height=1200000)
+ self.fa5 = Footprint(0.325, elevation_deg=30, sat_height=600000)
+ self.fa6 = Footprint(
+ 0.325,
+ sat_height=1200000,
+ bore_lat_deg=0,
+ bore_subsat_long_deg=17.744178387,
+ )
+
+ """
+ Requested tests for Low Earth Orbit (LEO) Satellite at 1200Km and 600Km added bellow (Issue 33).
+ """
+
+ # New tests obtained for the LEO satellite type heights (1200km and
+ # 600km)
+ # Different satellite heights (1200 km and 600 km)
+ self.sat_heights = [1200000, 600000]
+
def test_construction(self):
- self.assertEqual(self.fa1.bore_lat_deg,0)
- self.assertEqual(self.fa1.bore_subsat_long_deg,0)
- self.assertEqual(self.fa1.beam_width_deg,0.1)
- self.assertEqual(self.fa1.bore_lat_rad,0)
- self.assertEqual(self.fa1.bore_subsat_long_rad,0)
- self.assertEqual(self.fa1.beam_width_rad,np.pi/1800)
- self.assertEqual(self.fa1.beta,0)
- self.assertEqual(self.fa1.bore_tilt,0)
-
- self.assertEqual(self.fa2.bore_lat_deg,0)
- self.assertEqual(self.fa2.bore_subsat_long_deg,0)
- self.assertEqual(self.fa2.bore_lat_rad,0)
- self.assertEqual(self.fa2.bore_subsat_long_rad,0)
-
- self.assertEqual(self.fa3.bore_lat_deg,0)
- self.assertAlmostEqual(self.fa3.bore_subsat_long_deg,61.84,delta=0.01)
-
+ """
+ Test the correct construction of Footprint instances with expected values.
+ """
+ # Verify properties of fa1
+ self.assertEqual(self.fa1.bore_lat_deg, 0)
+ self.assertEqual(self.fa1.bore_subsat_long_deg, 0)
+ self.assertEqual(self.fa1.beam_width_deg, 0.1)
+ self.assertEqual(self.fa1.bore_lat_rad, 0)
+ self.assertEqual(self.fa1.bore_subsat_long_rad, 0)
+ self.assertEqual(self.fa1.beam_width_rad, np.pi / 1800)
+ self.assertEqual(self.fa1.beta, 0)
+ self.assertEqual(self.fa1.bore_tilt, 0)
+
+ # Verify properties of fa2
+ self.assertEqual(self.fa2.bore_lat_deg, 0)
+ self.assertEqual(self.fa2.bore_subsat_long_deg, 0)
+ self.assertEqual(self.fa2.bore_lat_rad, 0)
+ self.assertEqual(self.fa2.bore_subsat_long_rad, 0)
+
+ # Verify properties of fa3
+ self.assertEqual(self.fa3.bore_lat_deg, 0)
+ self.assertAlmostEqual(
+ self.fa3.bore_subsat_long_deg, 61.84, delta=0.01)
+
+ # Verify properties of fa4
+ self.assertEqual(self.fa4.bore_lat_deg, 0)
+ self.assertAlmostEqual(
+ self.fa4.bore_subsat_long_deg, 13.22, delta=0.01)
+
+ # Verify properties of fa5
+ self.assertEqual(self.fa5.bore_lat_deg, 0)
+ self.assertAlmostEqual(self.fa5.bore_subsat_long_deg, 7.68, delta=0.01)
+
+ self.assertEqual(self.fa6.sat_height, 1200000)
+ self.assertAlmostEqual(self.fa6.elevation_deg, 20, delta=0.01)
+
def test_set_elevation(self):
+ """
+ Test the set_elevation method to ensure it correctly updates the elevation angle.
+ """
self.fa2.set_elevation(20)
- self.assertEqual(self.fa2.bore_lat_deg,0)
- self.assertAlmostEqual(self.fa2.bore_subsat_long_deg,61.84,delta=0.01)
-
+ self.assertEqual(self.fa2.bore_lat_deg, 0)
+ self.assertAlmostEqual(
+ self.fa2.bore_subsat_long_deg, 61.84, delta=0.01)
+
def test_calc_footprint(self):
+ """
+ Test the calc_footprint method to verify the coordinates of the generated footprint polygon.
+ """
fp_long, fp_lat = self.fa1.calc_footprint(4)
- npt.assert_allclose(fp_long,np.array([0.0, 0.487, -0.487, 0.0]),atol=1e-2)
- npt.assert_allclose(fp_lat,np.array([-0.562, 0.281, 0.281, -0.562]),atol=1e-2)
-
+ npt.assert_allclose(fp_long, np.array(
+ [0.0, 0.487, -0.487, 0.0]), atol=1e-2)
+ npt.assert_allclose(fp_lat, np.array(
+ [-0.562, 0.281, 0.281, -0.562]), atol=1e-2)
+
def test_calc_area(self):
+ """
+ Test the calc_area method to verify the calculation of the footprint area.
+ """
a1 = self.fa2.calc_area(1000)
- self.assertAlmostEqual(a1,130000,delta=200)
+ self.assertAlmostEqual(a1, 130000, delta=130000 * 0.0025)
a2 = self.fa3.calc_area(1000)
- self.assertAlmostEqual(a2,486300,delta=200)
-
+ self.assertAlmostEqual(a2, 486300, delta=486300 * 0.0025)
+ a3 = self.fa4.calc_area(1000)
+ self.assertAlmostEqual(a3, 810, delta=810 * 0.0025)
+ a4 = self.fa5.calc_area(1000)
+ self.assertAlmostEqual(a4, 234, delta=234 * 0.0025)
+
+ for height in self.sat_heights:
+ beam_deg = 0.325
+ footprint = Footprint(
+ beam_deg, elevation_deg=90, sat_height=height)
+ cone_radius_in_km = height * np.tan(np.deg2rad(beam_deg)) / 1000
+ cone_base_area_in_km2 = np.pi * (cone_radius_in_km**2)
+ footprint_area_in_km2 = footprint.calc_area(1000)
+ self.assertAlmostEqual(
+ footprint_area_in_km2,
+ cone_base_area_in_km2,
+ delta=cone_base_area_in_km2 * 0.01,
+ )
+
+
if __name__ == '__main__':
- unittest.main()
\ No newline at end of file
+ unittest.main()
diff --git a/tests/test_post_processor.py b/tests/test_post_processor.py
new file mode 100644
index 000000000..24aa5ca70
--- /dev/null
+++ b/tests/test_post_processor.py
@@ -0,0 +1,36 @@
+
+import unittest
+
+from sharc.results import Results
+from sharc.post_processor import PostProcessor
+
+
+class StationTest(unittest.TestCase):
+ def setUp(self):
+ self.post_processor = PostProcessor()
+ # We just prepare to write beacause Results class is not fully initialized
+ # before preparing to read or loading from previous results
+ self.results = Results().prepare_to_write(
+ None,
+ True
+ )
+
+ def test_generate_and_add_cdf_plots_from_results(self):
+ self.results.imt_coupling_loss.extend([0, 1, 2, 3, 4, 5])
+ self.results.imt_dl_inr.extend([0, 1, 2, 3, 4, 5])
+
+ trace_legend = "any legendd. Lorem ipsum"
+ self.post_processor.add_plot_legend_pattern(dir_name_contains="output", legend=trace_legend)
+
+ self.post_processor.add_plots(
+ self.post_processor.generate_cdf_plots_from_results(
+ [self.results]
+ )
+ )
+
+ self.assertEqual(len(self.post_processor.plots), 2)
+ self.assertEqual(self.post_processor.plots[0].data[0].name, trace_legend)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/test_propagation_abg.py b/tests/test_propagation_abg.py
index 887422176..093191253 100644
--- a/tests/test_propagation_abg.py
+++ b/tests/test_propagation_abg.py
@@ -13,46 +13,37 @@
from sharc.propagation.propagation_abg import PropagationABG
+
class PropagationABGTest(unittest.TestCase):
def setUp(self):
- self.abg = PropagationABG(np.random.RandomState())
+ self.abg = PropagationABG(
+ random_number_gen=np.random.RandomState(),
+ alpha=3.4,
+ beta=19.2,
+ gamma=2.3,
+ building_loss=20,
+ shadowing_sigma_dB=6.5,
+ )
def test_loss(self):
- d = np.array([[100, 500],[400, 60]])
- f = 27000
- indoor = np.zeros(d.shape, dtype=bool)
- alpha = 3.4
- beta = 19.2
- gamma = 2.3
- shadowing = 0
- loss = np.array ([[120.121, 143.886347],[140.591406, 112.578509]])
-
- npt.assert_allclose(self.abg.get_loss(distance_2D = d,
- frequency = f,
- indoor_stations = indoor,
- line_of_sight_prob = 1,
- alpha = alpha,
- beta = beta,
- gamma = gamma,
- shadowing = shadowing),
- loss,atol=1e-2)
-
- d = np.array([500, 3000])
- f = np.array([27000, 40000])
- indoor = np.zeros(d.shape, dtype=bool)
- alpha = 3.4
- beta = 19.2
- gamma = 2.3
- shadowing = 0
-
- loss = np.array ([143.886,174.269])
- npt.assert_allclose(self.abg.get_loss(distance_2D = d,
- frequency = f,
- indoor_stations = indoor,
- line_of_sight_prob = 1,
- alpha = alpha,
- beta = beta,
- gamma = gamma,
- shadowing = shadowing),
- loss ,atol=1e-2)
+ d = np.array([[100, 500], [400, 60]])
+ f = np.ones(d.shape, dtype=float) * 27000.0
+ indoor = np.zeros(d.shape[0], dtype=bool)
+ shadowing = False
+ loss = np.array([[120.121, 143.886347], [140.591406, 112.578509]])
+
+ npt.assert_allclose(self.abg.get_loss(d, f, indoor, shadowing),
+ loss, atol=1e-2)
+
+ d = np.array([500, 3000])[:, np.newaxis]
+ f = np.array([27000, 40000])[:, np.newaxis]
+ indoor = np.zeros(d.shape[0], dtype=bool)
+ shadowing = False
+ loss = np.array([143.886, 174.269])[:, np.newaxis]
+ npt.assert_allclose(self.abg.get_loss(d, f, indoor, shadowing),
+ loss, atol=1e-2)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/test_propagation_building_entry_loss.py b/tests/test_propagation_building_entry_loss.py
index c8fa6740e..6f10d41fb 100644
--- a/tests/test_propagation_building_entry_loss.py
+++ b/tests/test_propagation_building_entry_loss.py
@@ -14,7 +14,8 @@
class TestPropagationBuildingEntryLoss(unittest.TestCase):
def setUp(self):
- self.building_entry_loss = PropagationBuildingEntryLoss(np.random.RandomState())
+ self.building_entry_loss = PropagationBuildingEntryLoss(
+ np.random.RandomState())
def test_building_entry_loss(self):
# compare with benchmark from ITU-R P-2109-0 Fig. 1
@@ -25,8 +26,8 @@ def test_building_entry_loss(self):
loss_lower = np.array([9, 10, 11, 15, 16, 19, 21])
loss_upper = np.array([10, 12, 15, 17, 18, 21, 25])
-
- loss = self.building_entry_loss.get_loss(f_GHz_vec * 1000, 0, prob=.5, test=True)
+ loss = self.building_entry_loss.get_loss(
+ f_GHz_vec * 1000, 0, prob=.5, test=True)
npt.assert_array_less(loss_lower, loss)
npt.assert_array_less(loss, loss_upper)
diff --git a/tests/test_propagation_clear_air.py b/tests/test_propagation_clear_air.py
index 5061f311a..687009a48 100644
--- a/tests/test_propagation_clear_air.py
+++ b/tests/test_propagation_clear_air.py
@@ -3,75 +3,59 @@
import unittest
import numpy as np
-import matplotlib.pyplot as plt
-from sharc.parameters.parameters_fss_es import ParametersFssEs
-
import numpy.testing as npt
-
+from sharc.parameters.parameters_p452 import ParametersP452
from sharc.propagation.propagation_clear_air_452 import PropagationClearAir
+
class PropagationClearAirTest(unittest.TestCase):
def setUp(self):
- self.__ClearAir = PropagationClearAir(np.random.RandomState())
-
- def test_loss(self):
-
- params = ParametersFssEs()
-
- d = 10000
- f = 27000
- params.atmospheric_pressure = 1013
- params.air_temperature = 288
- params.water_vapour = 7.5
- params.Dlt = 30
- params.Dlr = 10
- params.Dct = 10
- params.Dcr = 10
-
- params.Hts = 244
- params.Hrs = 280
- params.Hte = 50
- params.Hre = 50
-
- params.theta_tx = 20
- params.theta_rx = 20
+ param_p452 = ParametersP452()
+ # param_p452.atmospheric_pressure = 1013
+ # param_p452.air_temperature = 288
+ # param_p452.Dct = 10
+ # param_p452.Dcr = 10
- params.N0 = 355
- params.delta_N = 60
- params.percentage_p = 40
+ # param_p452.Hte = 50
+ # param_p452.Hre = 50
- params.omega = 0
- params.phi = 60
- params.dtm = .8
- params.dlm = .8
+ # param_p452.N0 = 355
+ # param_p452.delta_N = 60
+ # param_p452.percentage_p = 40
- params.epsilon = 3.5
+ # param_p452.clutter_loss = False
- params.hm = 15
- params.Hsr = 45
- params.Hst = 48
+ self.prop_clear_air = PropagationClearAir(
+ np.random.RandomState(), param_p452)
- params.H0 = 15
- params.Hn = 17
-
- params.thetaJ = 0.3
- params.par_ep = 0.8
-
- params.clutter_loss = False
-
- Gt = 10
- Gr = 10
-
- di = [1,1,1]
- hi = [2,4,6]
-
-
-# Ld50, Ldbeta, Ldb = self.__Diffraction.get_loss(beta = Beta, distance=d, frequency=f, atmospheric_pressure=Ph, air_temperature=T, water_vapour=ro, delta_N=deltaN, Hrs=hrs, Hts=hts, Hte=hte, Hre=hre, Hsr=hsr, Hst=hst, H0=h0, Hn=hn, dist_di=di, hight_hi=hi, omega=omega, Dlt=dlt ,Dlr=dlr, percentage_p=p)
-#
-# npt.assert_allclose(158.491,Ldb,atol=1e-3)
+ def test_loss(self):
- #Grafico da perda de difraรงao em funรงao da distancia e da frequencia
+ # distance between stations in meters
+ distances = np.ones((1, 1), dtype=float) * 1000
+ frequencies = np.ones((1, 1), dtype=float) * 27000 # frequency in MHz
+ indoor_stations = np.zeros((1, 1), dtype=bool)
+ # elevation between stations in degrees
+ elevations = np.zeros((1, 1), dtype=float)
+ tx_gain = np.ones((1, 1), dtype=float) * 0
+ rx_gain = np.ones((1, 1), dtype=float) * 0
+
+ loss = self.prop_clear_air.get_loss(
+ distances,
+ frequencies,
+ indoor_stations,
+ elevations,
+ tx_gain,
+ rx_gain)
+ # npt.assert_allclose(158.491, loss, atol=1e-3)
+
+ # Ld50, Ldbeta, Ldb = self.__Diffraction.get_loss(beta = Beta, distance=d, frequency=f, atmospheric_pressure=Ph,
+ # air_temperature=T, water_vapour=ro, delta_N=deltaN, Hrs=hrs, Hts=hts, Hte=hte, Hre=hre, Hsr=hsr, Hst=hst, H0=h0,
+ # Hn=hn, dist_di=di, hight_hi=hi, omega=omega, Dlt=dlt ,Dlr=dlr, percentage_p=p)
+
+ # npt.assert_allclose(158.491,Ldb,atol=1e-3)
+
+ # Grafico da perda de difraรงao em funรงao da distancia e da frequencia
# data1 = []
# data2 = []
# data3 = []
diff --git a/tests/test_propagation_clutter.py b/tests/test_propagation_clutter.py
index 257cd0af0..7b716e55c 100644
--- a/tests/test_propagation_clutter.py
+++ b/tests/test_propagation_clutter.py
@@ -1,63 +1,63 @@
-# -*- coding: utf-8 -*-
+import unittest
+import numpy as np
+from sharc.propagation.propagation_clutter_loss import PropagationClutterLoss
+from sharc.support.enumerations import StationType
-"""
-Created on Tue Mai 02 15:02:31 2017
-@author: LeticiaValle_Mac
-"""
+class TestPropagationClutterLoss(unittest.TestCase):
+ def setUp(self):
+ self.clutter_loss = PropagationClutterLoss(np.random.RandomState(42))
-import unittest
-import numpy as np
+ def test_spatial_clutter_loss(self):
+ frequency = np.array([27000]) # MHz
+ elevation = np.array([0, 45, 90])
+ loc_percentage = np.array([0.1, 0.5, 0.9])
+ distance = np.array([1000]) # meters, dummy value
+ loss = self.clutter_loss.get_loss(
+ distance=distance,
+ frequency=frequency,
+ elevation=elevation,
+ loc_percentage=loc_percentage,
+ station_type=StationType.FSS_SS
+ )
-from sharc.propagation.propagation_clutter_loss import PropagationClutterLoss
+ # Check the shape of the output
+ self.assertEqual(loss.shape, (3,))
-class PropagationClutterLossTest(unittest.TestCase):
+ # Check if loss decreases with increasing elevation
+ self.assertTrue(loss[0] >= loss[1] >= loss[2])
- def setUp(self):
- self.__ClutterAtt = PropagationClutterLoss(np.random.RandomState())
-
- def test_loss(self):
-
- f = 27000 #GHz
- theta = 0
- per_p =50
- d = 10000
- P = 0.9
- dist = 10
- r = 12.64
- s = 3.72
- t = 0.96
- u = 9.6
- v = 2
- w = 9.1
- x = -3
- y = 4.5
- z = -2
- #npt.assert_allclose(73.150,
- # self.__ClutterAtt.get_loss(frequency=f, distance = d,percentage_p = per_p, dist = dist, elevation_angle_facade=theta, probability_loss_notExceeded=P, coeff_r=r, coeff_s=s, coeff_t=t, coeff_u=u,coeff_v=v, coeff_w=w,coeff_x=x,coeff_y=y,coeff_z=z),atol=1e-3)
-
-
-# f = [10,20] #GHz
-# d = 10
-# Ph = 1013
-# T = 288
-# ro = 7.5
-# npt.assert_allclose([0.140, 1.088],
-# self.__gasAtt.get_loss_Ag(distance=d, frequency=f, atmospheric_pressure=Ph, air_temperature=T, water_vapour=ro),atol=1e-3)
-
-
-# d = [[10, 20, 30],[40, 50, 60]]
-# f = 10
-# Ph = 1013
-# T = 288
-# ro = 7.5
-# self.assertTrue(np.all(np.isclose([0.140, 0.280, 0.420],[0.560, 0.700, 0.840],
-# self.__gasAtt.get_loss_Ag(distance=d, frequency=f,atmospheric_pressure=Ph, air_temperature=T, water_vapour=ro), atol=1e-3)))
-#
-#
+ def test_terrestrial_clutter_loss(self):
+ frequency = np.array([2000, 6000]) # MHz
+ distance = np.array([500, 2000]) # meters
+ # Using a single value for location percentage
+ loc_percentage = np.array([0.5])
+
+ loss = self.clutter_loss.get_loss(
+ frequency=frequency,
+ distance=distance,
+ loc_percentage=loc_percentage,
+ station_type=StationType.IMT_BS
+ )
+
+ self.assertEqual(loss.shape, (2,))
+
+ self.assertTrue(loss[1] >= loss[0])
+
+ def test_random_loc_percentage(self):
+ frequency = np.array([4000]) # MHz
+ distance = np.array([1000]) # meters
+
+ loss = self.clutter_loss.get_loss(
+ frequency=frequency,
+ distance=distance,
+ loc_percentage="RANDOM",
+ station_type=StationType.IMT_UE
+ )
+
+ self.assertTrue(0 <= loss <= 100)
if __name__ == '__main__':
unittest.main()
-
diff --git a/tests/test_propagation_free_space.py b/tests/test_propagation_free_space.py
index 7eb24fe71..8fc1484f5 100644
--- a/tests/test_propagation_free_space.py
+++ b/tests/test_propagation_free_space.py
@@ -20,27 +20,27 @@ def setUp(self):
def test_loss(self):
d = np.array([10])
f = np.array([10])
- loss = self.freeSpace.get_loss(distance_2D=d, frequency=f)
+ loss = self.freeSpace.get_loss(d, f)
ref_loss = np.array([12.45])
npt.assert_allclose(ref_loss, loss, atol=1e-2)
- d = np.array([ 10, 100 ])
- f = np.array([ 10, 100 ])
- loss = self.freeSpace.get_loss(distance_2D=d, frequency=f)
+ d = np.array([10, 100])
+ f = np.array([10, 100])
+ loss = self.freeSpace.get_loss(d, f)
ref_loss = np.array([12.45, 52.45])
npt.assert_allclose(ref_loss, loss, atol=1e-2)
- d = np.array([ 10, 100, 1000 ])
- f = np.array([ 10, 100, 1000 ])
- loss = self.freeSpace.get_loss(distance_2D=d, frequency=f)
+ d = np.array([10, 100, 1000])
+ f = np.array([10, 100, 1000])
+ loss = self.freeSpace.get_loss(d, f)
ref_loss = np.array([12.45, 52.45, 92.45])
npt.assert_allclose(ref_loss, loss, atol=1e-2)
d = np.array([[10, 20, 30], [40, 50, 60]])
- f = np.array([ 100 ])
- loss = self.freeSpace.get_loss(distance_2D=d, frequency=f)
- ref_loss = np.array([[ 32.45, 38.47, 41.99],
- [ 44.49, 46.42, 48.01]])
+ f = np.array([100])
+ loss = self.freeSpace.get_loss(d, f)
+ ref_loss = np.array([[32.45, 38.47, 41.99],
+ [44.49, 46.42, 48.01]])
npt.assert_allclose(ref_loss, loss, atol=1e-2)
diff --git a/tests/test_propagation_hdfss_building_side.py b/tests/test_propagation_hdfss_building_side.py
index 1ef143040..546076f7e 100644
--- a/tests/test_propagation_hdfss_building_side.py
+++ b/tests/test_propagation_hdfss_building_side.py
@@ -9,16 +9,17 @@
import numpy as np
import numpy.testing as npt
-from sharc.parameters.parameters_fss_es import ParametersFssEs
+from sharc.parameters.parameters_hdfss import ParametersHDFSS
from sharc.support.enumerations import StationType
from sharc.propagation.propagation_hdfss_building_side import PropagationHDFSSBuildingSide
+
class PropagationHDFSSBuildingSideTest(unittest.TestCase):
def setUp(self):
# Basic propagation
rnd = np.random.RandomState(101)
- par = ParametersFssEs()
+ par = ParametersHDFSS()
par.building_loss_enabled = False
par.shadow_enabled = False
par.same_building_enabled = True
@@ -26,11 +27,11 @@ def setUp(self):
par.bs_building_entry_loss_type = 'FIXED_VALUE'
par.bs_building_entry_loss_prob = 0.5
par.bs_building_entry_loss_value = 50
- self.propagation = PropagationHDFSSBuildingSide(par,rnd)
-
+ self.propagation = PropagationHDFSSBuildingSide(par, rnd)
+
# Propagation with fixed BEL
rnd = np.random.RandomState(101)
- par = ParametersFssEs()
+ par = ParametersHDFSS()
par.building_loss_enabled = True
par.shadow_enabled = False
par.same_building_enabled = True
@@ -38,11 +39,11 @@ def setUp(self):
par.bs_building_entry_loss_type = 'FIXED_VALUE'
par.bs_building_entry_loss_prob = 0.6
par.bs_building_entry_loss_value = 50
- self.propagation_fixed_value = PropagationHDFSSBuildingSide(par,rnd)
-
+ self.propagation_fixed_value = PropagationHDFSSBuildingSide(par, rnd)
+
# Propagation with fixed probability
rnd = np.random.RandomState(101)
- par = ParametersFssEs()
+ par = ParametersHDFSS()
par.building_loss_enabled = True
par.shadow_enabled = False
par.same_building_enabled = True
@@ -50,11 +51,11 @@ def setUp(self):
par.bs_building_entry_loss_type = 'P2109_FIXED'
par.bs_building_entry_loss_prob = 0.6
par.bs_building_entry_loss_value = 50
- self.propagation_fixed_prob = PropagationHDFSSBuildingSide(par,rnd)
-
+ self.propagation_fixed_prob = PropagationHDFSSBuildingSide(par, rnd)
+
# Propagation with random probability
rnd = np.random.RandomState(101)
- par = ParametersFssEs()
+ par = ParametersHDFSS()
par.building_loss_enabled = True
par.shadow_enabled = False
par.same_building_enabled = True
@@ -62,20 +63,20 @@ def setUp(self):
par.bs_building_entry_loss_type = 'P2109_RANDOM'
par.bs_building_entry_loss_prob = 0.6
par.bs_building_entry_loss_value = 50
- self.propagation_random_prob = PropagationHDFSSBuildingSide(par,rnd)
-
+ self.propagation_random_prob = PropagationHDFSSBuildingSide(par, rnd)
+
def test_get_loss(self):
# On same building
d = np.array([[10.0, 80.0, 200.0]])
- f = 40000*np.ones_like(d)
+ f = 40000 * np.ones_like(d)
ele = np.transpose(np.zeros_like(d))
es_x = np.array([0.0])
es_y = np.array([25.0])
es_z = np.array([10.0])
- imt_x = np.array([ 0.0, 0.0, -200.0])
- imt_y = np.array([15.0, 80.0, 25.0])
- imt_z = np.array([ 1.5, 6.0, 7.5])
-
+ imt_x = np.array([0.0, 0.0, -200.0])
+ imt_y = np.array([15.0, 80.0, 25.0])
+ imt_z = np.array([1.5, 6.0, 7.5])
+
loss = self.propagation.get_loss(distance_3D=d,
frequency=f,
elevation=ele,
@@ -87,83 +88,83 @@ def test_get_loss(self):
es_y=es_y,
es_z=es_z)
loss = loss[0]
-
+
expected_loss = np.array([[84.48, 103.35, 140.05]])
-
- npt.assert_allclose(loss,expected_loss,atol=1e-1)
-
+
+ npt.assert_allclose(loss, expected_loss, atol=1e-1)
+
def test_get_build_loss(self):
# Initialize variables
- ele = np.array([[ 0.0, 45.0, 90.0]])
- f = 40000*np.ones_like(ele)
+ ele = np.array([[0.0, 45.0, 90.0]])
+ f = 40000 * np.ones_like(ele)
sta_type = StationType.IMT_BS
-
+
# Test 1: fixed value
expected_build_loss = 50.0
build_loss = self.propagation_fixed_value.get_building_loss(sta_type,
f,
ele)
- self.assertEqual(build_loss,expected_build_loss)
-
+ self.assertEqual(build_loss, expected_build_loss)
+
# Test 2: fixed probability
expected_build_loss = np.array([[24.4, 33.9, 43.4]])
build_loss = self.propagation_fixed_prob.get_building_loss(sta_type,
f,
ele)
- npt.assert_allclose(build_loss,expected_build_loss,atol=1e-1)
-
+ npt.assert_allclose(build_loss, expected_build_loss, atol=1e-1)
+
# Test 3: random probability
expected_build_loss = np.array([[21.7, 32.9, 15.9]])
build_loss = self.propagation_random_prob.get_building_loss(sta_type,
f,
ele)
- npt.assert_allclose(build_loss,expected_build_loss,atol=1e-1)
-
+ npt.assert_allclose(build_loss, expected_build_loss, atol=1e-1)
+
# Test 4: UE station
sta_type = StationType.IMT_UE
expected_build_loss = np.array([[21.7, 32.9, 15.9]])
build_loss = self.propagation_fixed_value.get_building_loss(sta_type,
f,
ele)
- npt.assert_allclose(build_loss,expected_build_loss,atol=1e-1)
+ npt.assert_allclose(build_loss, expected_build_loss, atol=1e-1)
build_loss = self.propagation_fixed_prob.get_building_loss(sta_type,
- f,
- ele)
- npt.assert_allclose(build_loss,expected_build_loss,atol=1e-1)
+ f,
+ ele)
+ npt.assert_allclose(build_loss, expected_build_loss, atol=1e-1)
expected_build_loss = np.array([[10.1, 36.8, 52.6]])
build_loss = self.propagation_random_prob.get_building_loss(sta_type,
f,
ele)
- npt.assert_allclose(build_loss,expected_build_loss,atol=1e-1)
-
+ npt.assert_allclose(build_loss, expected_build_loss, atol=1e-1)
+
def test_is_same_build(self):
# Test is_same_building()
es_x = np.array([0.0])
es_y = np.array([25.0])
- imt_x = np.array([1.0, 0.0,80.0,-70.0,12.0])
- imt_y = np.array([1.0,30.0, 0.0,-29.3,-3.6])
-
- expected_in_build = np.array([True,False,False,False,True])
+ imt_x = np.array([1.0, 0.0, 80.0, -70.0, 12.0])
+ imt_y = np.array([1.0, 30.0, 0.0, -29.3, -3.6])
+
+ expected_in_build = np.array([True, False, False, False, True])
in_build = self.propagation.is_same_building(imt_x,
imt_y,
es_x,
es_y)
- npt.assert_array_equal(in_build,expected_in_build)
-
+ npt.assert_array_equal(in_build, expected_in_build)
+
def test_is_next_build(self):
# Test is_same_building()
es_x = np.array([0.0])
es_y = np.array([25.0])
- imt_x = np.array([1.0, 0.0,80.0,-70.0,12.0])
- imt_y = np.array([1.0,30.0, 0.0,-29.3,-3.6]) + 80.0
-
- expected_in_build = np.array([True,False,False,False,True])
+ imt_x = np.array([1.0, 0.0, 80.0, -70.0, 12.0])
+ imt_y = np.array([1.0, 30.0, 0.0, -29.3, -3.6]) + 80.0
+
+ expected_in_build = np.array([True, False, False, False, True])
in_build = self.propagation.is_next_building(imt_x,
imt_y,
es_x,
es_y)
- npt.assert_array_equal(in_build,expected_in_build)
-
-
+ npt.assert_array_equal(in_build, expected_in_build)
+
+
if __name__ == '__main__':
- unittest.main()
\ No newline at end of file
+ unittest.main()
diff --git a/tests/test_propagation_hdfss_roof_top.py b/tests/test_propagation_hdfss_roof_top.py
index 5a92432da..15d9fa03a 100644
--- a/tests/test_propagation_hdfss_roof_top.py
+++ b/tests/test_propagation_hdfss_roof_top.py
@@ -9,15 +9,16 @@
import numpy as np
import numpy.testing as npt
-from sharc.parameters.parameters_fss_es import ParametersFssEs
+from sharc.parameters.parameters_hdfss import ParametersHDFSS
from sharc.support.enumerations import StationType
from sharc.propagation.propagation_hdfss_roof_top import PropagationHDFSSRoofTop
+
class PropagationHDFSSRoofTopTest(unittest.TestCase):
def setUp(self):
rnd = np.random.RandomState(101)
- par = ParametersFssEs()
+ par = ParametersHDFSS()
par.building_loss_enabled = False
par.shadow_enabled = False
par.same_building_enabled = True
@@ -25,11 +26,11 @@ def setUp(self):
par.bs_building_entry_loss_type = 'FIXED_VALUE'
par.bs_building_entry_loss_prob = 0.5
par.bs_building_entry_loss_value = 50
- self.propagation = PropagationHDFSSRoofTop(par,rnd)
-
+ self.propagation = PropagationHDFSSRoofTop(par, rnd)
+
# Propagation with fixed BEL
rnd = np.random.RandomState(101)
- par = ParametersFssEs()
+ par = ParametersHDFSS()
par.building_loss_enabled = True
par.shadow_enabled = False
par.same_building_enabled = True
@@ -37,11 +38,11 @@ def setUp(self):
par.bs_building_entry_loss_type = 'FIXED_VALUE'
par.bs_building_entry_loss_prob = 0.6
par.bs_building_entry_loss_value = 50
- self.propagation_fixed_value = PropagationHDFSSRoofTop(par,rnd)
-
+ self.propagation_fixed_value = PropagationHDFSSRoofTop(par, rnd)
+
# Propagation with fixed probability
rnd = np.random.RandomState(101)
- par = ParametersFssEs()
+ par = ParametersHDFSS()
par.building_loss_enabled = True
par.shadow_enabled = False
par.same_building_enabled = True
@@ -49,11 +50,11 @@ def setUp(self):
par.bs_building_entry_loss_type = 'P2109_FIXED'
par.bs_building_entry_loss_prob = 0.6
par.bs_building_entry_loss_value = 50
- self.propagation_fixed_prob = PropagationHDFSSRoofTop(par,rnd)
-
+ self.propagation_fixed_prob = PropagationHDFSSRoofTop(par, rnd)
+
# Propagation with random probability
rnd = np.random.RandomState(101)
- par = ParametersFssEs()
+ par = ParametersHDFSS()
par.building_loss_enabled = True
par.shadow_enabled = False
par.same_building_enabled = True
@@ -61,11 +62,11 @@ def setUp(self):
par.bs_building_entry_loss_type = 'P2109_RANDOM'
par.bs_building_entry_loss_prob = 0.6
par.bs_building_entry_loss_value = 50
- self.propagation_random_prob = PropagationHDFSSRoofTop(par,rnd)
-
+ self.propagation_random_prob = PropagationHDFSSRoofTop(par, rnd)
+
# Same building disabled
rnd = np.random.RandomState(101)
- par = ParametersFssEs()
+ par = ParametersHDFSS()
par.building_loss_enabled = False
par.shadow_enabled = False
par.same_building_enabled = False
@@ -73,11 +74,12 @@ def setUp(self):
par.bs_building_entry_loss_type = 'FIXED_VALUE'
par.bs_building_entry_loss_prob = 0.5
par.bs_building_entry_loss_value = 50
- self.propagation_same_build_disabled = PropagationHDFSSRoofTop(par,rnd)
-
+ self.propagation_same_build_disabled = PropagationHDFSSRoofTop(
+ par, rnd)
+
# Diffraction loss enabled
rnd = np.random.RandomState(101)
- par = ParametersFssEs()
+ par = ParametersHDFSS()
par.building_loss_enabled = False
par.shadow_enabled = False
par.same_building_enabled = True
@@ -85,41 +87,42 @@ def setUp(self):
par.bs_building_entry_loss_type = 'FIXED_VALUE'
par.bs_building_entry_loss_prob = 0.5
par.bs_building_entry_loss_value = 50
- self.propagation_diff_enabled = PropagationHDFSSRoofTop(par,rnd)
-
+ self.propagation_diff_enabled = PropagationHDFSSRoofTop(par, rnd)
+
def test_get_loss(self):
# Not on same building
d = np.array([[10.0, 20.0, 30.0, 60.0, 90.0, 300.0, 1000.0]])
- f = 40000*np.ones_like(d)
+ f = 40000 * np.ones_like(d)
ele = np.transpose(np.zeros_like(d))
-
+
loss = self.propagation.get_loss(distance_3D=d,
frequency=f,
elevation=ele,
imt_sta_type=StationType.IMT_BS,
- imt_x = 100.0*np.ones(7),
- imt_y = 100.0*np.ones(7),
- imt_z = 100.0*np.ones(7),
- es_x = np.array([0.0]),
- es_y = np.array([0.0]),
- es_z = np.array([0.0]))
+ imt_x=100.0 * np.ones(7),
+ imt_y=100.0 * np.ones(7),
+ imt_z=100.0 * np.ones(7),
+ es_x=np.array([0.0]),
+ es_y=np.array([0.0]),
+ es_z=np.array([0.0]))
loss = loss[0]
-
- expected_loss = np.array([[84.48, 90.50, 94.02, 100.72, 104.75, 139.33, 162.28]])
-
- npt.assert_allclose(loss,expected_loss,atol=1e-1)
-
+
+ expected_loss = np.array(
+ [[84.48, 90.50, 94.02, 100.72, 104.75, 139.33, 162.28]])
+
+ npt.assert_allclose(loss, expected_loss, atol=1e-1)
+
# On same building
d = np.array([[10.0, 20.0, 30.0]])
- f = 40000*np.ones_like(d)
+ f = 40000 * np.ones_like(d)
ele = np.transpose(np.zeros_like(d))
es_x = np.array([0.0])
es_y = np.array([0.0])
es_z = np.array([10.0])
- imt_x = np.array([ 0.0, 20.0, 30.0])
- imt_y = np.array([10.0, 0.0, 0.0])
- imt_z = np.array([ 1.5, 6.0, 7.5])
-
+ imt_x = np.array([0.0, 20.0, 30.0])
+ imt_y = np.array([10.0, 0.0, 0.0])
+ imt_z = np.array([1.5, 6.0, 7.5])
+
loss = self.propagation.get_loss(distance_3D=d,
frequency=f,
elevation=ele,
@@ -131,77 +134,77 @@ def test_get_loss(self):
es_y=es_y,
es_z=es_z)
loss = loss[0]
-
+
expected_loss = np.array([[150 + 84.48, 100 + 90.50, 50 + 94.02]])
-
- npt.assert_allclose(loss,expected_loss,atol=1e-1)
-
+
+ npt.assert_allclose(loss, expected_loss, atol=1e-1)
+
def test_get_build_loss(self):
# Initialize variables
- ele = np.array([[ 0.0, 45.0, 90.0]])
- f = 40000*np.ones_like(ele)
+ ele = np.array([[0.0, 45.0, 90.0]])
+ f = 40000 * np.ones_like(ele)
sta_type = StationType.IMT_BS
-
+
# Test 1: fixed value
expected_build_loss = 50.0
build_loss = self.propagation_fixed_value.get_building_loss(sta_type,
f,
ele)
- self.assertEqual(build_loss,expected_build_loss)
-
+ self.assertEqual(build_loss, expected_build_loss)
+
# Test 2: fixed probability
expected_build_loss = np.array([[24.4, 33.9, 43.4]])
build_loss = self.propagation_fixed_prob.get_building_loss(sta_type,
f,
ele)
- npt.assert_allclose(build_loss,expected_build_loss,atol=1e-1)
-
+ npt.assert_allclose(build_loss, expected_build_loss, atol=1e-1)
+
# Test 3: random probability
expected_build_loss = np.array([[21.7, 32.9, 15.9]])
build_loss = self.propagation_random_prob.get_building_loss(sta_type,
f,
ele)
- npt.assert_allclose(build_loss,expected_build_loss,atol=1e-1)
-
+ npt.assert_allclose(build_loss, expected_build_loss, atol=1e-1)
+
# Test 4: UE station
sta_type = StationType.IMT_UE
expected_build_loss = np.array([[21.7, 32.9, 15.9]])
build_loss = self.propagation_fixed_value.get_building_loss(sta_type,
f,
ele)
- npt.assert_allclose(build_loss,expected_build_loss,atol=1e-1)
+ npt.assert_allclose(build_loss, expected_build_loss, atol=1e-1)
build_loss = self.propagation_fixed_prob.get_building_loss(sta_type,
- f,
- ele)
- npt.assert_allclose(build_loss,expected_build_loss,atol=1e-1)
+ f,
+ ele)
+ npt.assert_allclose(build_loss, expected_build_loss, atol=1e-1)
expected_build_loss = np.array([[10.1, 36.8, 52.6]])
build_loss = self.propagation_random_prob.get_building_loss(sta_type,
f,
ele)
- npt.assert_allclose(build_loss,expected_build_loss,atol=1e-1)
-
+ npt.assert_allclose(build_loss, expected_build_loss, atol=1e-1)
+
def test_same_building(self):
# Test is_same_building()
es_x = np.array([0.0])
es_y = np.array([0.0])
es_z = np.array([19.0])
- imt_x = np.array([1.0, 0.0,80.0,-70.0,12.0])
- imt_y = np.array([1.0,30.0, 0.0,-29.3,-3.6])
- imt_z = 3*np.ones_like(imt_x)
-
- expected_in_build = np.array([True,False,False,False,True])
+ imt_x = np.array([1.0, 0.0, 80.0, -70.0, 12.0])
+ imt_y = np.array([1.0, 30.0, 0.0, -29.3, -3.6])
+ imt_z = 3 * np.ones_like(imt_x)
+
+ expected_in_build = np.array([True, False, False, False, True])
in_build = self.propagation_same_build_disabled.is_same_building(imt_x,
- imt_y,
- es_x,
- es_y)
- npt.assert_array_equal(in_build,expected_in_build)
-
+ imt_y,
+ es_x,
+ es_y)
+ npt.assert_array_equal(in_build, expected_in_build)
+
# Test loss
- d = np.sqrt(np.power(imt_x,2) + np.power(imt_y,2))
+ d = np.sqrt(np.power(imt_x, 2) + np.power(imt_y, 2))
d = np.array([list(d)])
- f = 40000*np.ones_like(d)
+ f = 40000 * np.ones_like(d)
ele = np.transpose(np.zeros_like(d))
-
+
loss = self.propagation_same_build_disabled.get_loss(distance_3D=d,
frequency=f,
elevation=ele,
@@ -213,54 +216,54 @@ def test_same_building(self):
es_y=es_y,
es_z=es_z)
loss = loss[0]
- expected_loss = np.array([[4067.5,94.0,103.6,103.1,4086.5]])
-
- npt.assert_allclose(loss,expected_loss,atol=1e-1)
-
+ expected_loss = np.array([[4067.5, 94.0, 103.6, 103.1, 4086.5]])
+
+ npt.assert_allclose(loss, expected_loss, atol=1e-1)
+
def test_get_diff_distances(self):
es_x = np.array([10.0])
es_y = np.array([15.0])
es_z = np.array([19.0])
- imt_x = np.array([ 80.0, 50.0, 10.0,-80.0, 0.0])
- imt_y = np.array([ 15.0, 55.0, 95.0, 15.0,-40.0])
- imt_z = np.array([ 1.5, 3.0, 6.0, 7.5, 20.5])
-
+ imt_x = np.array([80.0, 50.0, 10.0, -80.0, 0.0])
+ imt_y = np.array([15.0, 55.0, 95.0, 15.0, -40.0])
+ imt_z = np.array([1.5, 3.0, 6.0, 7.5, 20.5])
+
# 2D distances
distances = self.propagation.get_diff_distances(imt_x,
- imt_y,
- imt_z,
- es_x,
- es_y,
- es_z,
+ imt_y,
+ imt_z,
+ es_x,
+ es_y,
+ es_z,
dist_2D=True)
- expected_distances = (np.array([60.0,35.4,25.0,60.0,25.4]),
- np.array([10.0,21.2,55.0,30.0,30.5]))
- npt.assert_allclose(distances,expected_distances,atol=1e-1)
-
+ expected_distances = (np.array([60.0, 35.4, 25.0, 60.0, 25.4]),
+ np.array([10.0, 21.2, 55.0, 30.0, 30.5]))
+ npt.assert_allclose(distances, expected_distances, atol=1e-1)
+
# 3D distances
distances = self.propagation.get_diff_distances(imt_x,
- imt_y,
- imt_z,
- es_x,
- es_y,
+ imt_y,
+ imt_z,
+ es_x,
+ es_y,
es_z)
- expected_distances = (np.array([ 14.0, 9.0, 3.0, 6.7, -1.7]),
- np.array([ 60.0, 35.4, 25.0, 60.0, 25.4]),
- np.array([ 19.3, 25.9, 56.3, 31.8, 30.6]))
- npt.assert_allclose(distances,expected_distances,atol=1e-1)
-
+ expected_distances = (np.array([14.0, 9.0, 3.0, 6.7, -1.7]),
+ np.array([60.0, 35.4, 25.0, 60.0, 25.4]),
+ np.array([19.3, 25.9, 56.3, 31.8, 30.6]))
+ npt.assert_allclose(distances, expected_distances, atol=1e-1)
+
def test_diffration_loss(self):
# Test diffraction loss
- h = np.array([7.64,-0.56,-1.2,-0.1])
- d1 = np.array([34.99,1060.15,5.0,120.0])
- d2 = np.array([25.02,25.02,2.33,245.0])
- f = 40000*np.ones_like(h)
-
- loss = self.propagation_diff_enabled.get_diffraction_loss(h,d1,d2,f)
- expected_loss = np.array([43.17,0.0,0.0,4.48])
-
- npt.assert_allclose(loss,expected_loss,atol=1e-1)
-
-
+ h = np.array([7.64, -0.56, -1.2, -0.1])
+ d1 = np.array([34.99, 1060.15, 5.0, 120.0])
+ d2 = np.array([25.02, 25.02, 2.33, 245.0])
+ f = 40000 * np.ones_like(h)
+
+ loss = self.propagation_diff_enabled.get_diffraction_loss(h, d1, d2, f)
+ expected_loss = np.array([43.17, 0.0, 0.0, 4.48])
+
+ npt.assert_allclose(loss, expected_loss, atol=1e-1)
+
+
if __name__ == '__main__':
- unittest.main()
\ No newline at end of file
+ unittest.main()
diff --git a/tests/test_propagation_indoor.py b/tests/test_propagation_indoor.py
index 8740ef1e5..f77b8b36c 100644
--- a/tests/test_propagation_indoor.py
+++ b/tests/test_propagation_indoor.py
@@ -6,43 +6,49 @@
"""
import unittest
-import numpy as np
-import numpy.testing as npt
+# import numpy as np
-from sharc.propagation.propagation_indoor import PropagationIndoor
-from sharc.parameters.parameters_indoor import ParametersIndoor
+# from sharc.propagation.propagation_indoor import PropagationIndoor
+# from sharc.parameters.parameters_indoor import ParametersIndoor
class PropagationIndoorTest(unittest.TestCase):
+ """Tests PropagationIndoor class
+ """
def setUp(self):
pass
def test_loss(self):
- params = ParametersIndoor()
- params.basic_path_loss = "INH_OFFICE"
- params.n_rows = 3
- params.n_colums = 1
- # params.street_width = 30
- params.ue_indoor_percent = .95
- params.building_class = "TRADITIONAL"
- params.num_cells = 3
-
- bs_per_building = 3
- ue_per_bs = 3
-
- num_bs = bs_per_building*params.n_rows*params.n_colums
- num_ue = num_bs*ue_per_bs
- distance_2D = 150*np.random.random((num_bs, num_ue))
- frequency = 27000*np.ones(distance_2D.shape)
- indoor = np.random.rand(num_bs) < params.ue_indoor_percent
- h_bs = 3*np.ones(num_bs)
- h_ue = 1.5*np.ones(num_ue)
- distance_3D = np.sqrt(distance_2D**2 + (h_bs[:,np.newaxis] - h_ue)**2)
- height_diff = np.tile(h_bs, (num_bs, 3)) - np.tile(h_ue, (num_bs, 1))
- elevation = np.degrees(np.arctan(height_diff/distance_2D))
-
- propagation_indoor = PropagationIndoor(np.random.RandomState(), params, ue_per_bs)
+ """Tests the get_loss method
+ """
+ pass
+ # params = ParametersIndoor()
+ # params.basic_path_loss = "INH_OFFICE"
+ # params.n_rows = 3
+ # params.n_colums = 1
+ # # params.street_width = 30
+ # params.ue_indoor_percent = .95
+ # params.building_class = "TRADITIONAL"
+ # params.num_cells = 3
+
+ # bs_per_building = 3
+ # ue_per_bs = 3
+
+ # num_bs = bs_per_building * params.n_rows * params.n_colums
+ # num_ue = num_bs * ue_per_bs
+ # distance_2D = 150 * np.random.random((num_bs, num_ue))
+ # frequency = 27000 * np.ones(distance_2D.shape)
+ # indoor = np.random.rand(num_bs) < params.ue_indoor_percent
+ # h_bs = 3 * np.ones(num_bs)
+ # h_ue = 1.5 * np.ones(num_ue)
+ # distance_3D = np.sqrt(distance_2D**2 + (h_bs[:, np.newaxis] - h_ue)**2)
+ # height_diff = np.tile(h_bs, (num_bs, 3)) - np.tile(h_ue, (num_bs, 1))
+ # elevation = np.degrees(np.arctan(height_diff / distance_2D))
+
+ # propagation_indoor = PropagationIndoor(
+ # np.random.RandomState(), params, ue_per_bs)
+
if __name__ == '__main__':
unittest.main()
diff --git a/tests/test_propagation_sat_simple.py b/tests/test_propagation_sat_simple.py
index 715d71c7f..fcb8e7315 100644
--- a/tests/test_propagation_sat_simple.py
+++ b/tests/test_propagation_sat_simple.py
@@ -15,64 +15,69 @@
class PropagationSatSimpleTest(unittest.TestCase):
def setUp(self):
- self.propagation = PropagationSatSimple(np.random.RandomState())
+ self.propagation = PropagationSatSimple(
+ random_number_gen=np.random.RandomState(),
+ enable_clutter_loss=False)
def test_loss(self):
d = np.array(10)
f = np.array(10)
- loc_percentage = 0
- elevation = {'free_space': 90*np.ones(d.shape), 'apparent': 90*np.ones(d.shape)}
+ elevation = {
+ 'free_space': 90 *
+ np.ones(
+ d.shape),
+ 'apparent': 90 *
+ np.ones(
+ d.shape)}
indoor_stations = np.zeros(d.shape, dtype=bool)
self.assertAlmostEqual(13.19,
- self.propagation.get_loss(distance_3D=d,
- frequency=f,
- loc_percentage=loc_percentage,
- indoor_stations=indoor_stations,
- elevation=elevation,
- enable_clutter_loss=False),
- delta = 1e-2)
+ self.propagation.get_loss(
+ d, f, indoor_stations, elevation),
+ delta=1e-2)
- d = np.array([ 10, 100 ])
- f = np.array([ 10, 100 ])
- loc_percentage = 0
- elevation = {'free_space': 90*np.ones(d.shape), 'apparent': 90*np.ones(d.shape)}
+ d = np.array([10, 100])
+ f = np.array([10, 100])
+ elevation = {
+ 'free_space': 90 *
+ np.ones(
+ d.shape),
+ 'apparent': 90 *
+ np.ones(
+ d.shape)}
indoor_stations = np.zeros(d.shape, dtype=bool)
npt.assert_allclose([13.2, 53.2],
- self.propagation.get_loss(distance_3D=d,
- frequency=f,
- loc_percentage=loc_percentage,
- indoor_stations=indoor_stations,
- elevation=elevation,
- enable_clutter_loss=False),
+ self.propagation.get_loss(
+ d, f, indoor_stations, elevation),
atol=1e-2)
- d = np.array([ 10, 100, 1000 ])
- f = np.array([ 10, 100, 1000 ])
- loc_percentage = 0
- elevation = {'free_space': 90*np.ones(d.shape), 'apparent': 90*np.ones(d.shape)}
+ d = np.array([10, 100, 1000])
+ f = np.array([10, 100, 1000])
+ elevation = {
+ 'free_space': 90 *
+ np.ones(
+ d.shape),
+ 'apparent': 90 *
+ np.ones(
+ d.shape)}
indoor_stations = np.array([0, 0, 0], dtype=bool)
npt.assert_allclose([13.2, 53.2, 93.2],
- self.propagation.get_loss(distance_3D=d,
- frequency=f,
- loc_percentage=loc_percentage,
- indoor_stations=indoor_stations,
- elevation=elevation,
- enable_clutter_loss=False),
+ self.propagation.get_loss(
+ d, f, indoor_stations, elevation),
atol=1e-2)
- d = np.array([[10, 20, 30],[40, 50, 60]])
- f = np.array([ 100 ])
- loc_percentage = 0
- elevation = {'free_space': 90*np.ones(d.shape), 'apparent': 90*np.ones(d.shape)}
+ d = np.array([[10, 20, 30], [40, 50, 60]])
+ f = np.array([100])
+ elevation = {
+ 'free_space': 90 *
+ np.ones(
+ d.shape),
+ 'apparent': 90 *
+ np.ones(
+ d.shape)}
indoor_stations = np.zeros(d.shape, dtype=bool)
- ref_loss = [[ 33.2, 39.2, 42.7],
- [ 45.2, 47.1, 48.7]]
- loss = self.propagation.get_loss(distance_3D=d,
- frequency=f,
- loc_percentage=loc_percentage,
- indoor_stations=indoor_stations,
- elevation=elevation,
- enable_clutter_loss=False)
+ ref_loss = [[33.2, 39.2, 42.7],
+ [45.2, 47.1, 48.7]]
+ loss = self.propagation.get_loss(d, f, indoor_stations, elevation)
npt.assert_allclose(ref_loss, loss, atol=1e-1)
diff --git a/tests/test_propagation_uma.py b/tests/test_propagation_uma.py
index 2132ece60..40ff78084 100644
--- a/tests/test_propagation_uma.py
+++ b/tests/test_propagation_uma.py
@@ -11,6 +11,7 @@
from sharc.propagation.propagation_uma import PropagationUMa
+
class PropagationUMaTest(unittest.TestCase):
def setUp(self):
@@ -20,88 +21,97 @@ def test_los_probability(self):
distance_2D = np.array([[10, 15, 40],
[17, 60, 80]])
h_ue = np.array([1.5, 8, 15])
- los_probability = np.array([[1, 1, 0.74],
+ los_probability = np.array([[1, 1, 0.74],
[1, 0.57, 0.45]])
npt.assert_allclose(self.uma.get_los_probability(distance_2D, h_ue),
los_probability,
atol=1e-2)
-
def test_breakpoint_distance(self):
h_bs = np.array([15, 20, 25, 30])
h_ue = np.array([3, 4])
- h_e = np.ones((len(h_bs), len(h_ue)))
- frequency = 30000*np.ones((len(h_bs), len(h_ue)))
- breakpoint_distance = np.array([[ 11200, 16800],
- [ 15200, 22800],
- [ 19200, 28800],
- [ 23200, 34800]])
+ h_e = np.ones((h_ue.size, h_bs.size))
+ frequency = 30000 * np.ones(h_e.shape)
+ breakpoint_distance = np.array([[11200, 15200, 19200, 23200],
+ [16800, 22800, 28800, 34800]])
npt.assert_array_equal(self.uma.get_breakpoint_distance(frequency, h_bs, h_ue, h_e),
breakpoint_distance)
-
def test_loss_los(self):
- distance_2D = np.array([[100, 200, 300, 400],
- [500, 600, 700, 800]])
+ distance_2D = np.array([[100, 500],
+ [200, 600],
+ [300, 700],
+ [400, 800]])
h_bs = np.array([30, 35])
h_ue = np.array([2, 3, 4, 5])
h_e = np.ones(distance_2D.shape)
- distance_3D = np.sqrt(distance_2D**2 + (h_bs[:,np.newaxis] - h_ue)**2)
- frequency = 30000*np.ones(distance_2D.shape)
+ distance_3D = np.sqrt(distance_2D**2 + (h_bs - h_ue[:, np.newaxis])**2)
+ frequency = 30000 * np.ones(distance_2D.shape)
shadowing_std = 0
- loss = np.array([[102.32, 108.09, 111.56, 114.05],
- [115.99, 117.56, 118.90, 120.06]])
+ loss = np.array([[102.32, 115.99],
+ [108.09, 117.56],
+ [111.56, 118.90],
+ [114.05, 120.06]])
npt.assert_allclose(self.uma.get_loss_los(distance_2D, distance_3D, frequency,
h_bs, h_ue, h_e, shadowing_std),
loss,
atol=1e-2)
-
- distance_2D = np.array([[100, 200, 300, 400],
- [500, 600, 700, 800]])
+ distance_2D = np.array([[100, 500],
+ [200, 600],
+ [300, 700],
+ [400, 800]])
h_bs = np.array([30, 35])
h_ue = np.array([2, 3, 4, 5])
h_e = np.ones(distance_2D.shape)
- distance_3D = np.sqrt(distance_2D**2 + (h_bs[:,np.newaxis] - h_ue)**2)
- frequency = 300*np.ones(distance_2D.shape)
+ distance_3D = np.sqrt(distance_2D**2 + (h_bs - h_ue[:, np.newaxis])**2)
+ frequency = 300 * np.ones(distance_2D.shape)
shadowing_std = 0
- loss = np.array([[62.32, 68.09, 71.56, 74.05],
- [87.06, 84.39, 83.57, 83.40]])
+ loss = np.array([[62.32, 87.06],
+ [68.09, 84.39],
+ [71.56, 83.57],
+ [74.05, 83.40]])
npt.assert_allclose(self.uma.get_loss_los(distance_2D, distance_3D, frequency,
h_bs, h_ue, h_e, shadowing_std),
loss,
atol=1e-2)
-
def test_loss_nlos(self):
- distance_2D = np.array([[100, 200, 300, 400],
- [500, 600, 700, 800]])
+ distance_2D = np.array([[100, 500],
+ [200, 600],
+ [300, 700],
+ [400, 800]])
h_bs = np.array([30, 35])
h_ue = np.array([2, 3, 4, 5])
h_e = np.ones(distance_2D.shape)
- distance_3D = np.sqrt(distance_2D**2 + (h_bs[:,np.newaxis] - h_ue)**2)
- frequency = 30000*np.ones(distance_2D.shape)
+ distance_3D = np.sqrt(distance_2D**2 + (h_bs - h_ue[:, np.newaxis])**2)
+ frequency = 30000 * np.ones(distance_2D.shape)
shadowing_std = 0
- loss = np.array([[121.58, 132.25, 138.45, 142.70],
- [148.29, 150.77, 152.78, 154.44]])
+ loss = np.array([[121.58, 148.29],
+ [132.25, 150.77],
+ [138.45, 152.78],
+ [142.70, 154.44]])
npt.assert_allclose(self.uma.get_loss_nlos(distance_2D, distance_3D, frequency,
- h_bs, h_ue, h_e, shadowing_std),
+ h_bs, h_ue, h_e, shadowing_std),
loss,
atol=1e-2)
-
- distance_2D = np.array([[1000, 2000, 5000, 4000],
- [3000, 6000, 7000, 8000]])
+ distance_2D = np.array([[1000, 3000],
+ [2000, 6000],
+ [5000, 7000],
+ [4000, 8000]])
h_bs = np.array([30, 35])
h_ue = np.array([2, 3, 4, 5])
h_e = np.ones(distance_2D.shape)
- distance_3D = np.sqrt(distance_2D**2 + (h_bs[:,np.newaxis] - h_ue)**2)
- frequency = 300*np.ones(distance_2D.shape)
+ distance_3D = np.sqrt(distance_2D**2 + (h_bs - h_ue[:, np.newaxis])**2)
+ frequency = 300 * np.ones(distance_2D.shape)
shadowing_std = 0
- loss = np.array([[120.02, 131.18, 146.13, 141.75],
- [138.66, 149.83, 151.84, 153.51]])
+ loss = np.array([[120.02, 138.66],
+ [131.18, 149.83],
+ [146.13, 151.84],
+ [141.75, 153.51]])
npt.assert_allclose(self.uma.get_loss_nlos(distance_2D, distance_3D, frequency,
- h_bs, h_ue, h_e, shadowing_std),
+ h_bs, h_ue, h_e, shadowing_std),
loss,
atol=1e-2)
diff --git a/tests/test_propagation_umi.py b/tests/test_propagation_umi.py
index fb3ac1371..2eadd31f2 100644
--- a/tests/test_propagation_umi.py
+++ b/tests/test_propagation_umi.py
@@ -12,98 +12,110 @@
from sharc.propagation.propagation_umi import PropagationUMi
+
class PropagationUMiTest(unittest.TestCase):
def setUp(self):
los_adjustment_factor = 18
- self.umi = PropagationUMi(np.random.RandomState(), los_adjustment_factor)
+ self.umi = PropagationUMi(
+ np.random.RandomState(),
+ los_adjustment_factor)
def test_los_probability(self):
distance_2D = np.array([[10, 15, 40],
[17, 60, 80]])
- los_probability = np.array([[1, 1, 0.631],
+ los_probability = np.array([[1, 1, 0.631],
[1, 0.432, 0.308]])
npt.assert_allclose(self.umi.get_los_probability(distance_2D,
- self.umi.los_adjustment_factor),
+ self.umi.los_adjustment_factor),
los_probability,
atol=1e-2)
-
def test_breakpoint_distance(self):
h_bs = np.array([15, 20, 25, 30])
h_ue = np.array([3, 4])
- h_e = np.ones((len(h_bs), len(h_ue)))
- frequency = 30000*np.ones((len(h_bs), len(h_ue)))
- breakpoint_distance = np.array([[ 11200, 16800],
- [ 15200, 22800],
- [ 19200, 28800],
- [ 23200, 34800]])
+ h_e = np.ones((h_ue.size, h_bs.size))
+ frequency = 30000 * np.ones(h_e.shape)
+ breakpoint_distance = np.array([[11200, 15200, 19200, 23200],
+ [16800, 22800, 28800, 34800]])
npt.assert_array_equal(self.umi.get_breakpoint_distance(frequency, h_bs, h_ue, h_e),
breakpoint_distance)
-
def test_loss_los(self):
- distance_2D = np.array([[100, 200, 300, 400],
- [500, 600, 700, 800]])
+ distance_2D = np.array([[100, 500],
+ [200, 600],
+ [300, 700],
+ [400, 800]])
h_bs = np.array([30, 35])
h_ue = np.array([2, 3, 4, 5])
h_e = np.ones(distance_2D.shape)
- distance_3D = np.sqrt(distance_2D**2 + (h_bs[:,np.newaxis] - h_ue)**2)
- frequency = 30000*np.ones(distance_2D.shape)
+ distance_3D = np.sqrt(distance_2D**2 + (h_bs - h_ue[:, np.newaxis])**2)
+ frequency = 30000 * np.ones(distance_2D.shape)
shadowing_std = 0
- loss = np.array([[104.336, 110.396, 114.046, 116.653],
- [118.690, 120.346, 121.748, 122.963]])
+ loss = np.array([[104.336, 118.690],
+ [110.396, 120.346],
+ [114.046, 121.748],
+ [116.653, 122.963]])
npt.assert_allclose(self.umi.get_loss_los(distance_2D, distance_3D, frequency,
h_bs, h_ue, h_e, shadowing_std),
loss,
atol=1e-2)
-
- distance_2D = np.array([[100, 200, 300, 400],
- [500, 600, 700, 800]])
+ distance_2D = np.array([[100, 500],
+ [200, 600],
+ [300, 700],
+ [400, 800]])
h_bs = np.array([30, 35])
h_ue = np.array([2, 3, 4, 5])
h_e = np.ones(distance_2D.shape)
- distance_3D = np.sqrt(distance_2D**2 + (h_bs[:,np.newaxis] - h_ue)**2)
- frequency = 300*np.ones(distance_2D.shape)
+ distance_3D = np.sqrt(distance_2D**2 + (h_bs - h_ue[:, np.newaxis])**2)
+ frequency = 300 * np.ones(distance_2D.shape)
shadowing_std = 0
- loss = np.array([[64.336, 70.396, 74.046, 76.653],
- [89.215, 86.829, 86.187, 86.139]])
+ loss = np.array([[64.336, 89.215],
+ [70.396, 86.829],
+ [74.046, 86.187],
+ [76.653, 86.139]])
npt.assert_allclose(self.umi.get_loss_los(distance_2D, distance_3D, frequency,
h_bs, h_ue, h_e, shadowing_std),
loss,
atol=1e-2)
-
def test_loss_nlos(self):
- distance_2D = np.array([[100, 200, 300, 400],
- [500, 600, 700, 800]])
+ distance_2D = np.array([[100, 500],
+ [200, 600],
+ [300, 700],
+ [400, 800]])
h_bs = np.array([30, 35])
h_ue = np.array([2, 3, 4, 5])
h_e = np.ones(distance_2D.shape)
- distance_3D = np.sqrt(distance_2D**2 + (h_bs[:,np.newaxis] - h_ue)**2)
- frequency = 30000*np.ones(distance_2D.shape)
+ distance_3D = np.sqrt(distance_2D**2 + (h_bs - h_ue[:, np.newaxis])**2)
+ frequency = 30000 * np.ones(distance_2D.shape)
shadowing_std = 0
- loss = np.array([[128.84, 138.72, 144.56, 148.64],
- [152.96, 155.45, 157.50, 159.25]])
+ loss = np.array([[128.84, 152.96],
+ [138.72, 155.45],
+ [144.56, 157.50],
+ [148.64, 159.25]])
npt.assert_allclose(self.umi.get_loss_nlos(distance_2D, distance_3D, frequency,
- h_bs, h_ue, h_e, shadowing_std),
+ h_bs, h_ue, h_e, shadowing_std),
loss,
atol=1e-2)
-
- distance_2D = np.array([[1000, 2000, 5000, 4000],
- [3000, 6000, 7000, 8000]])
+ distance_2D = np.array([[1000, 3000],
+ [2000, 6000],
+ [5000, 7000],
+ [4000, 8000]])
h_bs = np.array([30, 35])
h_ue = np.array([2, 3, 4, 5])
h_e = np.ones(distance_2D.shape)
- distance_3D = np.sqrt(distance_2D**2 + (h_bs[:,np.newaxis] - h_ue)**2)
- frequency = 300*np.ones(distance_2D.shape)
+ distance_3D = np.sqrt(distance_2D**2 + (h_bs - h_ue[:, np.newaxis])**2)
+ frequency = 300 * np.ones(distance_2D.shape)
shadowing_std = 0
- loss = np.array([[ 120.96 , 131.29, 145.03, 141.31],
- [ 137.80 , 148.13 , 150.19, 151.94]])
+ loss = np.array([[120.96, 137.80],
+ [131.29, 148.13],
+ [145.03, 150.19],
+ [141.31, 151.94]])
npt.assert_allclose(self.umi.get_loss_nlos(distance_2D, distance_3D, frequency,
- h_bs, h_ue, h_e, shadowing_std),
+ h_bs, h_ue, h_e, shadowing_std),
loss,
atol=1e-2)
diff --git a/tests/test_results.py b/tests/test_results.py
new file mode 100644
index 000000000..94b004298
--- /dev/null
+++ b/tests/test_results.py
@@ -0,0 +1,87 @@
+import unittest
+
+from sharc.results import Results
+
+
+class StationTest(unittest.TestCase):
+ def setUp(self):
+ self.results = Results().prepare_to_write(
+ None,
+ True,
+ output_dir="output",
+ output_dir_prefix="out"
+ )
+
+ def test_flush_to_and_load_from_file(self):
+ arr1 = [1., 2., 3., 4., 5., 6., 7., 8., 9., 100.]
+ self.results.imt_coupling_loss.extend(arr1)
+ self.assertGreater(len(self.results.imt_coupling_loss), 0)
+ # Results should flush
+ self.results.write_files(1)
+ # check that no results are left in arr
+ self.assertEqual(len(self.results.imt_coupling_loss), 0)
+
+ arr2 = [101., 102., 103., 104., 105., 106., 107., 108., 109.]
+ self.results.imt_coupling_loss.extend(arr2)
+ self.assertGreater(len(self.results.imt_coupling_loss), 0)
+ self.results.write_files(2)
+ # check that no results are left in arr
+ self.assertEqual(len(self.results.imt_coupling_loss), 0)
+
+ results_recuperated_from_file = Results().load_from_dir(self.results.output_directory)
+
+ results_arr = arr1
+ results_arr.extend(arr2)
+
+ self.assertEqual(results_recuperated_from_file.imt_coupling_loss, results_arr)
+
+ def test_get_most_recent_dirs(self):
+ dir_2024_01_01_04 = "caminho_abs/prefixo_2024-01-01_04"
+ dir_2024_01_01_10 = "caminho_abs/prefixo_2024-01-01_10"
+
+ dir_2024_01_02_01 = "caminho_abs/prefixo_2024-01-02_01"
+ dir_2024_10_01_01 = "caminho_abs/prefixo_2024-10-01_01"
+ another_dir = "caminho_abs/prefixo2_2024-10-01_01"
+
+ dirs = self.results.get_most_recent_outputs_for_each_prefix([
+ dir_2024_01_01_04,
+ dir_2024_01_01_10,
+ dir_2024_01_02_01,
+ dir_2024_10_01_01,
+ another_dir,
+ ])
+
+ self.assertEqual(len(dirs), 2)
+
+ self.assertIn(dir_2024_10_01_01, dirs)
+ self.assertIn(another_dir, dirs)
+
+ dirs = self.results.get_most_recent_outputs_for_each_prefix([
+ dir_2024_01_01_04,
+ dir_2024_01_01_10,
+ dir_2024_01_02_01,
+ ])
+
+ self.assertEqual(len(dirs), 1)
+
+ self.assertIn(dir_2024_01_02_01, dirs)
+
+ dirs = self.results.get_most_recent_outputs_for_each_prefix([
+ dir_2024_01_01_04,
+ dir_2024_01_01_10,
+ ])
+
+ self.assertEqual(len(dirs), 1)
+
+ self.assertIn(dir_2024_01_01_10, dirs)
+
+ def test_get_prefix_date_and_id(self):
+ dir_2024_01_01_04 = "caminho_abs/prefixo_2024-01-01_04"
+ prefix, date, id = Results.get_prefix_date_and_id(dir_2024_01_01_04)
+ self.assertEqual(prefix, "caminho_abs/prefixo_")
+ self.assertEqual(date, "2024-01-01")
+ self.assertEqual(id, "04")
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/test_scintillation.py b/tests/test_scintillation.py
index cf7566c8a..1bf1c52a8 100644
--- a/tests/test_scintillation.py
+++ b/tests/test_scintillation.py
@@ -22,8 +22,10 @@ def test_tropo_scintillation_attenuation(self):
frequency_MHz = 30000.
wet_refractivity = 42.5
- elevation_vec = np.array([5., 10., 20., 90., 35., 5., 10., 20., 35., 90.])
- percentage_gain_exceeded = np.array([.01, .1, 1, 3, 10, 90, 98, 99, 99.9, 99.99])
+ elevation_vec = np.array(
+ [5., 10., 20., 90., 35., 5., 10., 20., 35., 90.])
+ percentage_gain_exceeded = np.array(
+ [.01, .1, 1, 3, 10, 90, 98, 99, 99.9, 99.99])
attenuation_lower = [5, 1, .5, .1, .1, 1, 1, .5, .4, .3]
attenuation_upper = [7, 2, .6, .2, .2, 2, 2, .7, .6, .5]
sign = [-1, -1, -1, -1, -1, +1, +1, +1, +1, +1]
diff --git a/tests/test_simulation_downlink.py b/tests/test_simulation_downlink.py
index b590216ee..468948ee1 100644
--- a/tests/test_simulation_downlink.py
+++ b/tests/test_simulation_downlink.py
@@ -15,6 +15,9 @@
from sharc.antenna.antenna_omni import AntennaOmni
from sharc.station_factory import StationFactory
from sharc.propagation.propagation_factory import PropagationFactory
+from sharc.parameters.imt.parameters_imt_topology import ParametersImtTopology
+from sharc.parameters.imt.parameters_single_bs import ParametersSingleBS
+
class SimulationDownlinkTest(unittest.TestCase):
@@ -27,88 +30,92 @@ def setUp(self):
self.param.general.enable_adjacent_channel = False
self.param.general.overwrite_output = True
- self.param.imt.topology = "SINGLE_BS"
- self.param.imt.wrap_around = False
- self.param.imt.num_clusters = 2
- self.param.imt.intersite_distance = 150
+ self.param.imt.topology = ParametersImtTopology(
+ type="SINGLE_BS",
+ single_bs=ParametersSingleBS(
+ num_clusters=2,
+ intersite_distance=150,
+ cell_radius=2 * 150 / 3
+ )
+ )
self.param.imt.minimum_separation_distance_bs_ue = 10
self.param.imt.interfered_with = False
- self.param.imt.frequency = 10000
+ self.param.imt.frequency = 10000.0
self.param.imt.bandwidth = 100
self.param.imt.rb_bandwidth = 0.180
self.param.imt.spectral_mask = "IMT-2020"
self.param.imt.spurious_emissions = -13
self.param.imt.guard_band_ratio = 0.1
self.param.imt.ho_margin = 3
- self.param.imt.bs_load_probability = 1
- self.param.imt.num_resource_blocks = 10
- self.param.imt.bs_conducted_power = 10
- self.param.imt.bs_height = 6
- self.param.imt.bs_acs = 30
- self.param.imt.bs_noise_figure = 7
- self.param.imt.bs_noise_temperature = 290
- self.param.imt.bs_ohmic_loss = 3
- self.param.imt.ul_attenuation_factor = 0.4
- self.param.imt.ul_sinr_min = -10
- self.param.imt.ul_sinr_max = 22
- self.param.imt.ue_k = 2
- self.param.imt.ue_k_m = 1
- self.param.imt.ue_indoor_percent = 0
- self.param.imt.ue_distribution_distance = "RAYLEIGH"
- self.param.imt.ue_distribution_azimuth = "UNIFORM"
- self.param.imt.ue_distribution_type = "ANGLE_AND_DISTANCE"
- self.param.imt.ue_tx_power_control = "OFF"
- self.param.imt.ue_p_o_pusch = -95
- self.param.imt.ue_alpha = 0.8
- self.param.imt.ue_p_cmax = 20
- self.param.imt.ue_conducted_power = 10
- self.param.imt.ue_height = 1.5
- self.param.imt.ue_acs = 25
- self.param.imt.ue_noise_figure = 9
- self.param.imt.ue_ohmic_loss = 3
- self.param.imt.ue_body_loss = 4
- self.param.imt.dl_attenuation_factor = 0.6
- self.param.imt.dl_sinr_min = -10
- self.param.imt.dl_sinr_max = 30
+ self.param.imt.bs.load_probability = 1
+
+ self.param.imt.bs.conducted_power = 10
+ self.param.imt.bs.height = 6
+ self.param.imt.bs.acs = 30
+ self.param.imt.bs.noise_figure = 7
+ self.param.imt.bs.ohmic_loss = 3
+ self.param.imt.uplink.attenuation_factor = 0.4
+ self.param.imt.uplink.sinr_min = -10
+ self.param.imt.uplink.sinr_max = 22
+ self.param.imt.ue.k = 2
+ self.param.imt.ue.k_m = 1
+ self.param.imt.ue.indoor_percent = 0
+ self.param.imt.ue.distribution_distance = "RAYLEIGH"
+ self.param.imt.ue.distribution_azimuth = "UNIFORM"
+ self.param.imt.ue.distribution_type = "ANGLE_AND_DISTANCE"
+ self.param.imt.ue.tx_power_control = "OFF"
+ self.param.imt.ue.p_o_pusch = -95
+ self.param.imt.ue.alpha = 0.8
+ self.param.imt.ue.p_cmax = 20
+ self.param.imt.ue.conducted_power = 10
+ self.param.imt.ue.height = 1.5
+ self.param.imt.ue.acs = 25
+ self.param.imt.ue.noise_figure = 9
+ self.param.imt.ue.ohmic_loss = 3
+ self.param.imt.ue.body_loss = 4
+ self.param.imt.downlink.attenuation_factor = 0.6
+ self.param.imt.downlink.sinr_min = -10
+ self.param.imt.downlink.sinr_max = 30
self.param.imt.channel_model = "FSPL"
- self.param.imt.line_of_sight_prob = 0.75 # probability of line-of-sight (not for FSPL)
+ # probability of line-of-sight (not for FSPL)
+ self.param.imt.line_of_sight_prob = 0.75
self.param.imt.shadowing = False
self.param.imt.noise_temperature = 290
- self.param.imt.BOLTZMANN_CONSTANT = 1.38064852e-23
-
- self.param.antenna_imt.adjacent_antenna_model = "SINGLE_ELEMENT"
- self.param.antenna_imt.bs_normalization = False
- self.param.antenna_imt.bs_element_pattern = "M2101"
- self.param.antenna_imt.bs_normalization_file = None
- self.param.antenna_imt.bs_minimum_array_gain = -200
- self.param.antenna_imt.bs_element_max_g = 10
- self.param.antenna_imt.bs_element_phi_3db = 80
- self.param.antenna_imt.bs_element_theta_3db = 80
- self.param.antenna_imt.bs_element_am = 25
- self.param.antenna_imt.bs_element_sla_v = 25
- self.param.antenna_imt.bs_n_rows = 16
- self.param.antenna_imt.bs_n_columns = 16
- self.param.antenna_imt.bs_element_horiz_spacing = 1
- self.param.antenna_imt.bs_element_vert_spacing = 1
- self.param.antenna_imt.bs_multiplication_factor = 12
- self.param.antenna_imt.bs_downtilt = 10
-
- self.param.antenna_imt.ue_element_pattern = "M2101"
- self.param.antenna_imt.ue_normalization = False
- self.param.antenna_imt.ue_normalization_file = None
- self.param.antenna_imt.ue_minimum_array_gain = -200
- self.param.antenna_imt.ue_element_max_g = 5
- self.param.antenna_imt.ue_element_phi_3db = 65
- self.param.antenna_imt.ue_element_theta_3db = 65
- self.param.antenna_imt.ue_element_am = 30
- self.param.antenna_imt.ue_element_sla_v = 30
- self.param.antenna_imt.ue_n_rows = 2
- self.param.antenna_imt.ue_n_columns = 1
- self.param.antenna_imt.ue_element_horiz_spacing = 0.5
- self.param.antenna_imt.ue_element_vert_spacing = 0.5
- self.param.antenna_imt.ue_multiplication_factor = 12
-
- self.param.fss_ss.frequency = 10000
+
+ self.param.imt.bs.antenna.adjacent_antenna_model = "SINGLE_ELEMENT"
+ self.param.imt.ue.antenna.adjacent_antenna_model = "SINGLE_ELEMENT"
+ self.param.imt.bs.antenna.normalization = False
+ self.param.imt.bs.antenna.element_pattern = "M2101"
+ self.param.imt.bs.antenna.normalization_file = None
+ self.param.imt.bs.antenna.minimum_array_gain = -200
+ self.param.imt.bs.antenna.element_max_g = 10
+ self.param.imt.bs.antenna.element_phi_3db = 80
+ self.param.imt.bs.antenna.element_theta_3db = 80
+ self.param.imt.bs.antenna.element_am = 25
+ self.param.imt.bs.antenna.element_sla_v = 25
+ self.param.imt.bs.antenna.n_rows = 16
+ self.param.imt.bs.antenna.n_columns = 16
+ self.param.imt.bs.antenna.element_horiz_spacing = 1
+ self.param.imt.bs.antenna.element_vert_spacing = 1
+ self.param.imt.bs.antenna.multiplication_factor = 12
+ self.param.imt.bs.antenna.downtilt = 10
+
+ self.param.imt.ue.antenna.element_pattern = "M2101"
+ self.param.imt.ue.antenna.normalization = False
+ self.param.imt.ue.antenna.normalization_file = None
+ self.param.imt.ue.antenna.minimum_array_gain = -200
+ self.param.imt.ue.antenna.element_max_g = 5
+ self.param.imt.ue.antenna.element_phi_3db = 65
+ self.param.imt.ue.antenna.element_theta_3db = 65
+ self.param.imt.ue.antenna.element_am = 30
+ self.param.imt.ue.antenna.element_sla_v = 30
+ self.param.imt.ue.antenna.n_rows = 2
+ self.param.imt.ue.antenna.n_columns = 1
+ self.param.imt.ue.antenna.element_horiz_spacing = 0.5
+ self.param.imt.ue.antenna.element_vert_spacing = 0.5
+ self.param.imt.ue.antenna.multiplication_factor = 12
+
+ self.param.fss_ss.frequency = 10000.0
self.param.fss_ss.bandwidth = 100
self.param.fss_ss.acs = 0
self.param.fss_ss.altitude = 35786000
@@ -121,7 +128,7 @@ def setUp(self):
self.param.fss_ss.antenna_pattern = "OMNI"
self.param.fss_ss.imt_altitude = 1000
self.param.fss_ss.imt_lat_deg = -23.5629739
- self.param.fss_ss.imt_long_diff_deg = (-46.6555132-75)
+ self.param.fss_ss.imt_long_diff_deg = (-46.6555132 - 75)
self.param.fss_ss.channel_model = "FSPL"
self.param.fss_ss.line_of_sight_prob = 0.01
self.param.fss_ss.surf_water_vapour_density = 7.5
@@ -129,8 +136,6 @@ def setUp(self):
self.param.fss_ss.time_ratio = 0.5
self.param.fss_ss.antenna_l_s = -20
self.param.fss_ss.acs = 0
- self.param.fss_ss.BOLTZMANN_CONSTANT = 1.38064852e-23
- self.param.fss_ss.EARTH_RADIUS = 6371000
self.param.fss_es.x = -5000
self.param.fss_es.y = 0
@@ -139,7 +144,7 @@ def setUp(self):
self.param.fss_es.elevation_min = 20
self.param.fss_es.elevation_max = 20
self.param.fss_es.azimuth = "0"
- self.param.fss_es.frequency = 10000
+ self.param.fss_es.frequency = 10000.0
self.param.fss_es.bandwidth = 100
self.param.fss_es.noise_temperature = 100
self.param.fss_es.tx_power_density = -60
@@ -148,29 +153,25 @@ def setUp(self):
self.param.fss_es.channel_model = "FSPL"
self.param.fss_es.line_of_sight_prob = 1
self.param.fss_es.acs = 0
- self.param.fss_es.BOLTZMANN_CONSTANT = 1.38064852e-23
- self.param.fss_es.EARTH_RADIUS = 6371000
- self.param.ras.x = -5000
- self.param.ras.y = 0
+ self.param.ras.geometry.location.type = "FIXED"
+ self.param.ras.geometry.location.x = -5000
+ self.param.ras.geometry.location.y = 0
self.param.ras.height = 10
- self.param.ras.elevation = 20
- self.param.ras.azimuth = 0
- self.param.ras.frequency = 10000
+ self.param.ras.geometry.elevation.type = "FIXED"
+ self.param.ras.geometry.elevation.fixed = 20
+ self.param.ras.geometry.azimuth.fixed = 0
+ self.param.ras.geometry.azimuth.type = "FIXED"
+ self.param.ras.frequency = 10000.0
self.param.ras.bandwidth = 100
- self.param.ras.antenna_noise_temperature = 50
- self.param.ras.receiver_noise_temperature = 50
- self.param.ras.antenna_gain = 50
+ self.param.ras.noise_temperature = 100
+ self.param.ras.antenna.gain = 50
self.param.ras.antenna_efficiency = 0.7
- self.param.ras.diameter = 10
self.param.ras.acs = 0
- self.param.ras.antenna_pattern = "OMNI"
+ self.param.ras.antenna.pattern = "OMNI"
self.param.ras.channel_model = "FSPL"
self.param.ras.line_of_sight_prob = 1
- self.param.ras.BOLTZMANN_CONSTANT = 1.38064852e-23
- self.param.ras.EARTH_RADIUS = 6371000
- self.param.ras.SPEED_OF_LIGHT = 299792458
-
+ self.param.ras.tx_power_density = -500
def test_simulation_2bs_4ue_fss_ss(self):
self.param.general.system = "FSS_SS"
@@ -186,47 +187,51 @@ def test_simulation_2bs_4ue_fss_ss(self):
random_number_gen = np.random.RandomState()
self.simulation.bs = StationFactory.generate_imt_base_stations(self.param.imt,
- self.param.antenna_imt,
+ self.param.imt.bs.antenna,
self.simulation.topology,
random_number_gen)
self.simulation.bs.antenna = np.array([AntennaOmni(1), AntennaOmni(2)])
self.simulation.bs.active = np.ones(2, dtype=bool)
self.simulation.ue = StationFactory.generate_imt_ue(self.param.imt,
- self.param.antenna_imt,
+ self.param.imt.ue.antenna,
self.simulation.topology,
random_number_gen)
self.simulation.ue.x = np.array([20, 70, 110, 170])
- self.simulation.ue.y = np.array([ 0, 0, 0, 0])
- self.simulation.ue.antenna = np.array([AntennaOmni(10), AntennaOmni(11), AntennaOmni(22), AntennaOmni(23)])
+ self.simulation.ue.y = np.array([0, 0, 0, 0])
+ self.simulation.ue.antenna = np.array(
+ [AntennaOmni(10), AntennaOmni(11), AntennaOmni(22), AntennaOmni(23)])
self.simulation.ue.active = np.ones(4, dtype=bool)
# test connection method
self.simulation.connect_ue_to_bs()
self.simulation.select_ue(random_number_gen)
- self.simulation.link = {0:[0,1],1:[2,3]}
- self.assertEqual(self.simulation.link, {0: [0,1], 1: [2,3]})
+ self.simulation.link = {0: [0, 1], 1: [2, 3]}
+ self.assertEqual(self.simulation.link, {0: [0, 1], 1: [2, 3]})
# We do not test the selection method here because in this specific
# scenario we do not want to change the order of the UE's
self.simulation.propagation_imt = PropagationFactory.create_propagation(self.param.imt.channel_model,
- self.param, random_number_gen)
+ self.param,
+ self.simulation.param_system,
+ random_number_gen)
self.simulation.propagation_system = PropagationFactory.create_propagation(self.param.fss_ss.channel_model,
- self.param, random_number_gen)
+ self.param,
+ self.simulation.param_system,
+ random_number_gen)
# test coupling loss method
- self.simulation.coupling_loss_imt = self.simulation.calculate_coupling_loss(self.simulation.bs,
- self.simulation.ue,
- self.simulation.propagation_imt)
- path_loss_imt = np.array([[78.47, 89.35, 93.27, 97.05],
- [97.55, 94.72, 91.53, 81.99]])
- bs_antenna_gains = np.array([[ 1, 1, 1, 1], [ 2, 2, 2, 2]])
- ue_antenna_gains = np.array([[ 10, 11, 22, 23], [ 10, 11, 22, 23]])
+ self.simulation.coupling_loss_imt = self.simulation.calculate_intra_imt_coupling_loss(self.simulation.ue,
+ self.simulation.bs)
+ path_loss_imt = np.array([[78.68, 89.36, 93.28, 97.06],
+ [97.55, 94.73, 91.54, 82.08]])
+ bs_antenna_gains = np.array([[1, 1, 1, 1], [2, 2, 2, 2]])
+ ue_antenna_gains = np.array([[10, 11, 22, 23], [10, 11, 22, 23]])
coupling_loss_imt = path_loss_imt - bs_antenna_gains - ue_antenna_gains \
- + self.param.imt.bs_ohmic_loss \
- + self.param.imt.ue_ohmic_loss \
- + self.param.imt.ue_body_loss
+ + self.param.imt.bs.ohmic_loss \
+ + self.param.imt.ue.ohmic_loss \
+ + self.param.imt.ue.body_loss
npt.assert_allclose(self.simulation.coupling_loss_imt,
coupling_loss_imt,
@@ -234,74 +239,92 @@ def test_simulation_2bs_4ue_fss_ss(self):
# test scheduler and bandwidth allocation
self.simulation.scheduler()
- bandwidth_per_ue = math.trunc((1 - 0.1)*100/2)
- npt.assert_allclose(self.simulation.ue.bandwidth, bandwidth_per_ue*np.ones(4), atol=1e-2)
+ bandwidth_per_ue = math.trunc((1 - 0.1) * 100 / 2)
+ npt.assert_allclose(self.simulation.ue.bandwidth,
+ bandwidth_per_ue * np.ones(4), atol=1e-2)
# there is no power control, so BS's will transmit at maximum power
self.simulation.power_control()
- tx_power = 10 - 10*math.log10(2)
- npt.assert_allclose(self.simulation.bs.tx_power[0], np.array([tx_power, tx_power]), atol=1e-2)
- npt.assert_allclose(self.simulation.bs.tx_power[1], np.array([tx_power, tx_power]), atol=1e-2)
+ tx_power = 10 - 10 * math.log10(2)
+ npt.assert_allclose(self.simulation.bs.tx_power[0], np.array(
+ [tx_power, tx_power]), atol=1e-2)
+ npt.assert_allclose(self.simulation.bs.tx_power[1], np.array(
+ [tx_power, tx_power]), atol=1e-2)
# test method that calculates SINR
self.simulation.calculate_sinr()
# check UE received power
- rx_power = tx_power - np.concatenate((coupling_loss_imt[0][:2], coupling_loss_imt[1][2:]))
+ rx_power = tx_power - \
+ np.concatenate(
+ (coupling_loss_imt[0][:2], coupling_loss_imt[1][2:]))
npt.assert_allclose(self.simulation.ue.rx_power, rx_power, atol=1e-2)
# check UE received interference
- rx_interference = tx_power - np.concatenate((coupling_loss_imt[1][:2], coupling_loss_imt[0][2:]))
- npt.assert_allclose(self.simulation.ue.rx_interference, rx_interference, atol=1e-2)
+ rx_interference = tx_power - \
+ np.concatenate(
+ (coupling_loss_imt[1][:2], coupling_loss_imt[0][2:]))
+ npt.assert_allclose(self.simulation.ue.rx_interference,
+ rx_interference, atol=1e-2)
# check UE thermal noise
- thermal_noise = 10*np.log10(1.38064852e-23*290*bandwidth_per_ue*1e3*1e6) + 9
- npt.assert_allclose(self.simulation.ue.thermal_noise, thermal_noise, atol=1e-2)
+ thermal_noise = 10 * \
+ np.log10(1.38064852e-23 * 290 * bandwidth_per_ue * 1e3 * 1e6) + 9
+ npt.assert_allclose(self.simulation.ue.thermal_noise,
+ thermal_noise, atol=1e-2)
# check UE thermal noise + interference
- total_interference = 10*np.log10(np.power(10, 0.1*rx_interference) + np.power(10, 0.1*thermal_noise))
- npt.assert_allclose(self.simulation.ue.total_interference, total_interference, atol=1e-2)
+ total_interference = 10 * \
+ np.log10(np.power(10, 0.1 * rx_interference) +
+ np.power(10, 0.1 * thermal_noise))
+ npt.assert_allclose(
+ self.simulation.ue.total_interference, total_interference, atol=1e-2)
# check SNR
- npt.assert_allclose(self.simulation.ue.snr, rx_power - thermal_noise, atol=1e-2)
+ npt.assert_allclose(self.simulation.ue.snr,
+ rx_power - thermal_noise, atol=1e-2)
# check SINR
- npt.assert_allclose(self.simulation.ue.sinr, rx_power - total_interference, atol=1e-2)
+ npt.assert_allclose(self.simulation.ue.sinr,
+ rx_power - total_interference, atol=1e-2)
- self.simulation.system = StationFactory.generate_fss_space_station(self.param.fss_ss)
- self.simulation.system.x = np.array([0.01]) # avoids zero-division
+ self.simulation.system = StationFactory.generate_fss_space_station(
+ self.param.fss_ss)
+ self.simulation.system.x = np.array([0.01]) # avoids zero-division
self.simulation.system.y = np.array([0])
self.simulation.system.height = np.array([self.param.fss_ss.altitude])
- # test the method that calculates interference from IMT UE to FSS space station
+ # test the method that calculates interference from IMT UE to FSS space
+ # station
self.simulation.calculate_external_interference()
# check coupling loss
- # 4 values because we have 2 BS * 2 beams for each base station.
+ # 4 values because we have 2 BS * 2 beams for each base station.
path_loss_imt_system = 203.52
polarization_loss = 3
sat_antenna_gain = 51
bs_antenna_gain = np.array([1, 2])
coupling_loss_imt_system = path_loss_imt_system - sat_antenna_gain \
- - np.array([bs_antenna_gain[0], bs_antenna_gain[0], bs_antenna_gain[1], bs_antenna_gain[1]]) \
- + polarization_loss \
- + self.param.imt.bs_ohmic_loss
-
+ - np.array([bs_antenna_gain[0], bs_antenna_gain[0], bs_antenna_gain[1], bs_antenna_gain[1]]) \
+ + polarization_loss \
+ + self.param.imt.bs.ohmic_loss
+
npt.assert_allclose(self.simulation.coupling_loss_imt_system,
coupling_loss_imt_system,
atol=1e-2)
# check interference generated by BS to FSS space station
interference = tx_power - coupling_loss_imt_system
- rx_interference = 10*math.log10(np.sum(np.power(10, 0.1*interference)))
+ rx_interference = 10 * \
+ math.log10(np.sum(np.power(10, 0.1 * interference)))
self.assertAlmostEqual(self.simulation.system.rx_interference,
rx_interference,
delta=.01)
# check FSS space station thermal noise
- thermal_noise = 10*np.log10(1.38064852e-23*950*1e3*100*1e6)
+ thermal_noise = 10 * np.log10(1.38064852e-23 * 950 * 1e3 * 100 * 1e6)
self.assertAlmostEqual(self.simulation.system.thermal_noise,
thermal_noise,
delta=.01)
@@ -311,7 +334,7 @@ def test_simulation_2bs_4ue_fss_ss(self):
# np.array([ -147.448 - (-88.821) ]),
# delta=.01)
self.assertAlmostEqual(self.simulation.system.inr,
- np.array([ rx_interference - thermal_noise ]),
+ np.array([rx_interference - thermal_noise]),
delta=.01)
def test_simulation_2bs_4ue_fss_es(self):
@@ -320,90 +343,109 @@ def test_simulation_2bs_4ue_fss_es(self):
self.simulation = SimulationDownlink(self.param, "")
self.simulation.initialize()
-
self.simulation.bs_power_gain = 0
self.simulation.ue_power_gain = 0
random_number_gen = np.random.RandomState()
self.simulation.bs = StationFactory.generate_imt_base_stations(self.param.imt,
- self.param.antenna_imt,
+ self.param.imt.bs.antenna,
self.simulation.topology,
random_number_gen)
self.simulation.bs.antenna = np.array([AntennaOmni(1), AntennaOmni(2)])
self.simulation.bs.active = np.ones(2, dtype=bool)
self.simulation.ue = StationFactory.generate_imt_ue(self.param.imt,
- self.param.antenna_imt,
+ self.param.imt.ue.antenna,
self.simulation.topology,
random_number_gen)
self.simulation.ue.x = np.array([20, 70, 110, 170])
- self.simulation.ue.y = np.array([ 0, 0, 0, 0])
- self.simulation.ue.antenna = np.array([AntennaOmni(10), AntennaOmni(11), AntennaOmni(22), AntennaOmni(23)])
+ self.simulation.ue.y = np.array([0, 0, 0, 0])
+ self.simulation.ue.antenna = np.array(
+ [AntennaOmni(10), AntennaOmni(11), AntennaOmni(22), AntennaOmni(23)])
self.simulation.ue.active = np.ones(4, dtype=bool)
self.simulation.propagation_imt = PropagationFactory.create_propagation(self.param.imt.channel_model,
- self.param, random_number_gen)
+ self.param,
+ self.simulation.param_system,
+ random_number_gen)
self.simulation.connect_ue_to_bs()
self.simulation.select_ue(random_number_gen)
- self.simulation.link = {0:[0,1],1:[2,3]}
- self.simulation.coupling_loss_imt = self.simulation.calculate_coupling_loss(self.simulation.bs,
- self.simulation.ue,
- self.simulation.propagation_imt)
+ self.simulation.link = {0: [0, 1], 1: [2, 3]}
+ self.simulation.coupling_loss_imt = self.simulation.calculate_intra_imt_coupling_loss(self.simulation.ue,
+ self.simulation.bs)
self.simulation.scheduler()
self.simulation.power_control()
self.simulation.calculate_sinr()
- bandwidth_per_ue = math.trunc((1 - 0.1)*100/2)
+ bandwidth_per_ue = math.trunc((1 - 0.1) * 100 / 2)
- tx_power = 10 - 10*math.log10(2)
- npt.assert_allclose(self.simulation.bs.tx_power[0], np.array([tx_power, tx_power]), atol=1e-2)
- npt.assert_allclose(self.simulation.bs.tx_power[1], np.array([tx_power, tx_power]), atol=1e-2)
+ tx_power = 10 - 10 * math.log10(2)
+ npt.assert_allclose(self.simulation.bs.tx_power[0], np.array(
+ [tx_power, tx_power]), atol=1e-2)
+ npt.assert_allclose(self.simulation.bs.tx_power[1], np.array(
+ [tx_power, tx_power]), atol=1e-2)
# check UE received power
- rx_power = np.array([tx_power-3-(78.47-1-10)-4-3, tx_power-3-(89.35-1-11)-4-3, tx_power-3-(91.53-2-22)-4-3, tx_power-3-(81.99-2-23)-4-3])
+ path_loss_imt = np.array([78.68, 89.37, 91.54, 82.09])
+ rx_power = np.array([tx_power - 3 + 1 + 10 - 4 - 3, tx_power - 3 + 1 + 11 -
+ 4 - 3, tx_power - 3 + 2 + 22 - 4 - 3, tx_power - 3 + 2 + 23 - 4 - 3]) - path_loss_imt
npt.assert_allclose(self.simulation.ue.rx_power, rx_power, atol=1e-2)
# check UE received interference
- rx_interference = np.array([tx_power-3-(97.55-2-10)-4-3, tx_power-3-(94.72-2-11)-4-3, tx_power-3-(93.27-1-22)-4-3, tx_power-3-(97.05-1-23)-4-3])
- npt.assert_allclose(self.simulation.ue.rx_interference, rx_interference, atol=1e-2)
+ rx_interference = np.array([tx_power - 3 - (97.55 - 2 - 10) - 4 - 3, tx_power - 3 - (
+ 94.73 - 2 - 11) - 4 - 3, tx_power - 3 - (93.28 - 1 - 22) - 4 - 3, tx_power - 3 - (97.06 - 1 - 23) - 4 - 3])
+ npt.assert_allclose(self.simulation.ue.rx_interference,
+ rx_interference, atol=1e-2)
# check UE thermal noise
- thermal_noise = 10*np.log10(1.38064852e-23*290*bandwidth_per_ue*1e3*1e6) + 9
- npt.assert_allclose(self.simulation.ue.thermal_noise, thermal_noise, atol=1e-2)
+ thermal_noise = 10 * \
+ np.log10(1.38064852e-23 * 290 * bandwidth_per_ue * 1e3 * 1e6) + 9
+ npt.assert_allclose(self.simulation.ue.thermal_noise,
+ thermal_noise, atol=1e-2)
# check UE thermal noise + interference
- total_interference = 10*np.log10(np.power(10, 0.1*rx_interference) + np.power(10, 0.1*thermal_noise))
- npt.assert_allclose(self.simulation.ue.total_interference, total_interference, atol=1e-2)
-
- self.simulation.system = StationFactory.generate_fss_earth_station(self.param.fss_es, random_number_gen)
+ total_interference = 10 * \
+ np.log10(np.power(10, 0.1 * rx_interference) +
+ np.power(10, 0.1 * thermal_noise))
+ npt.assert_allclose(
+ self.simulation.ue.total_interference, total_interference, atol=1e-2)
+
+ self.simulation.system = StationFactory.generate_fss_earth_station(
+ self.param.fss_es, random_number_gen)
self.simulation.system.x = np.array([-2000])
self.simulation.system.y = np.array([0])
self.simulation.system.height = np.array([self.param.fss_es.height])
self.simulation.propagation_imt = PropagationFactory.create_propagation(self.param.imt.channel_model,
- self.param, random_number_gen)
+ self.param,
+ self.simulation.param_system,
+ random_number_gen)
+
self.simulation.propagation_system = PropagationFactory.create_propagation(self.param.fss_es.channel_model,
- self.param, random_number_gen)
+ self.param,
+ self.simulation.param_system,
+ random_number_gen)
# what if FSS ES is the interferer?
self.simulation.calculate_sinr_ext()
# check coupling loss between FSS_ES and IMT_UE
- coupling_loss_imt_system = np.array([128.55-50-10, 128.76-50-11, 128.93-50-22, 129.17-50-23])
+ coupling_loss_imt_system = np.array(
+ [128.55 - 50 - 10, 128.77 - 50 - 11, 128.93 - 50 - 22, 129.18 - 50 - 23])
npt.assert_allclose(self.simulation.coupling_loss_imt_system,
coupling_loss_imt_system,
atol=1e-2)
# check interference from FSS_ES to IMT_UE
- system_tx_power = -60 + 10*math.log10(bandwidth_per_ue*1e6) + 30
+ system_tx_power = -60 + 10 * math.log10(bandwidth_per_ue * 1e6) + 30
ext_interference = system_tx_power - coupling_loss_imt_system
npt.assert_allclose(self.simulation.ue.ext_interference,
ext_interference,
atol=1e-2)
- ext_interference_total = 10*np.log10(np.power(10, 0.1*total_interference) \
- + np.power(10, 0.1*ext_interference))
+ ext_interference_total = 10 * np.log10(np.power(10, 0.1 * total_interference) +
+ np.power(10, 0.1 * ext_interference))
npt.assert_allclose(self.simulation.ue.sinr_ext,
rx_power - ext_interference_total,
@@ -417,125 +459,137 @@ def test_simulation_2bs_4ue_fss_es(self):
self.simulation.calculate_external_interference()
# check coupling loss from IMT_BS to FSS_ES
- coupling_loss_imt_system = np.array([124.47-50-1, 124.47-50-1, 125.29-50-2, 125.29-50-2])
+ coupling_loss_imt_system = np.array(
+ [124.47 - 50 - 1, 124.47 - 50 - 1, 125.29 - 50 - 2, 125.29 - 50 - 2])
npt.assert_allclose(self.simulation.coupling_loss_imt_system,
coupling_loss_imt_system,
atol=1e-2)
interference = tx_power - coupling_loss_imt_system
- rx_interference = 10*math.log10(np.sum(np.power(10, 0.1*interference)))
+ rx_interference = 10 * \
+ math.log10(np.sum(np.power(10, 0.1 * interference)))
self.assertAlmostEqual(self.simulation.system.rx_interference,
rx_interference,
delta=.01)
# check FSS Earth station thermal noise
- thermal_noise = 10*np.log10(1.38064852e-23*100*1e3*100*1e6)
+ thermal_noise = 10 * np.log10(1.38064852e-23 * 100 * 1e3 * 100 * 1e6)
self.assertAlmostEqual(self.simulation.system.thermal_noise,
thermal_noise,
delta=.01)
# check INR at FSS Earth station
self.assertAlmostEqual(self.simulation.system.inr,
- np.array([ rx_interference - thermal_noise ]),
+ np.array([rx_interference - thermal_noise]),
delta=.01)
-
def test_simulation_2bs_4ue_ras(self):
self.param.general.system = "RAS"
self.simulation = SimulationDownlink(self.param, "")
self.simulation.initialize()
-
self.simulation.bs_power_gain = 0
self.simulation.ue_power_gain = 0
random_number_gen = np.random.RandomState()
self.simulation.bs = StationFactory.generate_imt_base_stations(self.param.imt,
- self.param.antenna_imt,
+ self.param.imt.bs.antenna,
self.simulation.topology,
random_number_gen)
self.simulation.bs.antenna = np.array([AntennaOmni(1), AntennaOmni(2)])
self.simulation.bs.active = np.ones(2, dtype=bool)
self.simulation.ue = StationFactory.generate_imt_ue(self.param.imt,
- self.param.antenna_imt,
+ self.param.imt.ue.antenna,
self.simulation.topology,
random_number_gen)
self.simulation.ue.x = np.array([20, 70, 110, 170])
- self.simulation.ue.y = np.array([ 0, 0, 0, 0])
- self.simulation.ue.antenna = np.array([AntennaOmni(10), AntennaOmni(11), AntennaOmni(22), AntennaOmni(23)])
+ self.simulation.ue.y = np.array([0, 0, 0, 0])
+ self.simulation.ue.antenna = np.array(
+ [AntennaOmni(10), AntennaOmni(11), AntennaOmni(22), AntennaOmni(23)])
self.simulation.ue.active = np.ones(4, dtype=bool)
self.simulation.propagation_imt = PropagationFactory.create_propagation(self.param.imt.channel_model,
- self.param, random_number_gen)
+ self.param,
+ self.simulation.param_system,
+ random_number_gen)
self.simulation.propagation_system = PropagationFactory.create_propagation(self.param.ras.channel_model,
- self.param, random_number_gen)
+ self.param,
+ self.simulation.param_system,
+ random_number_gen)
self.simulation.connect_ue_to_bs()
self.simulation.select_ue(random_number_gen)
- self.simulation.link = {0:[0,1],1:[2,3]}
+ self.simulation.link = {0: [0, 1], 1: [2, 3]}
self.simulation.select_ue(random_number_gen)
- self.simulation.link = {0:[0,1],1:[2,3]}
- self.simulation.coupling_loss_imt = self.simulation.calculate_coupling_loss(self.simulation.bs,
- self.simulation.ue,
- self.simulation.propagation_imt)
+ self.simulation.link = {0: [0, 1], 1: [2, 3]}
+ self.simulation.coupling_loss_imt = self.simulation.calculate_intra_imt_coupling_loss(self.simulation.ue,
+ self.simulation.bs)
self.simulation.scheduler()
self.simulation.power_control()
self.simulation.calculate_sinr()
# check UE thermal noise
- bandwidth_per_ue = math.trunc((1 - 0.1)*100/2)
- thermal_noise = 10*np.log10(1.38064852e-23*290*bandwidth_per_ue*1e3*1e6) + 9
+ bandwidth_per_ue = math.trunc((1 - 0.1) * 100 / 2)
+ thermal_noise = 10 * \
+ np.log10(1.38064852e-23 * 290 * bandwidth_per_ue * 1e3 * 1e6) + 9
npt.assert_allclose(self.simulation.ue.thermal_noise,
thermal_noise,
atol=1e-2)
# check SINR
npt.assert_allclose(self.simulation.ue.sinr,
- np.array([-70.48 - (-85.49), -80.36 - (-83.19), -70.54 - (-73.15), -60.00 - (-75.82)]),
+ np.array(
+ [-70.70 - (-85.49), -80.37 - (-83.19), -70.55 - (-73.15), -60.10 - (-75.82)]),
atol=1e-2)
- self.simulation.system = StationFactory.generate_ras_station(self.param.ras)
+ self.simulation.system = StationFactory.generate_ras_station(
+ self.param.ras, random_number_gen, topology=None
+ )
self.simulation.system.x = np.array([-2000])
self.simulation.system.y = np.array([0])
self.simulation.system.height = np.array([self.param.ras.height])
self.simulation.system.antenna[0].effective_area = 54.9779
# Test gain calculation
- gains = self.simulation.calculate_gains(self.simulation.system,self.simulation.bs)
- npt.assert_equal(gains,np.array([[50, 50]]))
+ gains = self.simulation.calculate_gains(
+ self.simulation.system, self.simulation.bs)
+ npt.assert_equal(gains, np.array([[50, 50]]))
self.simulation.calculate_external_interference()
polarization_loss = 3
npt.assert_allclose(self.simulation.coupling_loss_imt_system,
- np.array([118.47-50-1, 118.47-50-1, 119.29-50-2, 119.29-50-2]) + polarization_loss,
+ np.array([118.47 - 50 - 1, 118.47 - 50 - 1, 119.29 -
+ 50 - 2, 119.29 - 50 - 2]) + polarization_loss,
atol=1e-2)
# Test RAS interference
- interference = self.param.imt.bs_conducted_power - 10*np.log10(self.param.imt.ue_k) \
- - np.array([118.47-50-1, 118.47-50-1, 119.29-50-2, 119.29-50-2]) - polarization_loss
- rx_interference = 10*math.log10(np.sum(np.power(10, 0.1*interference)))
+ interference = self.param.imt.bs.conducted_power - 10 * np.log10(self.param.imt.ue.k) \
+ - np.array([118.47 - 50 - 1, 118.47 - 50 - 1, 119.29 -
+ 50 - 2, 119.29 - 50 - 2]) - polarization_loss
+ rx_interference = 10 * \
+ math.log10(np.sum(np.power(10, 0.1 * interference)))
self.assertAlmostEqual(self.simulation.system.rx_interference,
rx_interference,
delta=.01)
# Test RAS PFD
- pfd = 10*np.log10(10**(rx_interference/10)/54.9779)
+ pfd = 10 * np.log10(10**(rx_interference / 10) / 54.9779)
self.assertAlmostEqual(self.simulation.system.pfd,
- pfd,
- delta=.01)
+ pfd,
+ delta=.01)
# check RAS station thermal noise
- thermal_noise = 10*np.log10(1.38064852e-23*100*1e3*100*1e6)
+ thermal_noise = 10 * np.log10(1.38064852e-23 * 100 * 1e3 * 100 * 1e6)
self.assertAlmostEqual(self.simulation.system.thermal_noise,
thermal_noise,
delta=.01)
# check INR at RAS station
self.assertAlmostEqual(self.simulation.system.inr,
- np.array([ rx_interference - (-98.599) ]),
+ np.array([rx_interference - (-98.599)]),
delta=.01)
def test_calculate_bw_weights(self):
@@ -545,93 +599,94 @@ def test_calculate_bw_weights(self):
bw_imt = 200
bw_sys = 33.33
ue_k = 3
- ref_weights = np.array([ 0.5, 0, 0])
+ ref_weights = np.array([0.5, 0, 0])
weights = self.simulation.calculate_bw_weights(bw_imt, bw_sys, ue_k)
npt.assert_allclose(ref_weights, weights, atol=1e-2)
bw_imt = 100
bw_sys = 25
ue_k = 3
- ref_weights = np.array([ 0.75, 0, 0])
+ ref_weights = np.array([0.75, 0, 0])
weights = self.simulation.calculate_bw_weights(bw_imt, bw_sys, ue_k)
npt.assert_allclose(ref_weights, weights, atol=1e-2)
bw_imt = 200
bw_sys = 66.67
ue_k = 3
- ref_weights = np.array([ 1, 0, 0])
+ ref_weights = np.array([1, 0, 0])
weights = self.simulation.calculate_bw_weights(bw_imt, bw_sys, ue_k)
npt.assert_allclose(ref_weights, weights, atol=1e-2)
bw_imt = 400
bw_sys = 200
ue_k = 3
- ref_weights = np.array([ 1, 0.49, 0])
+ ref_weights = np.array([1, 0.49, 0])
weights = self.simulation.calculate_bw_weights(bw_imt, bw_sys, ue_k)
npt.assert_allclose(ref_weights, weights, atol=1e-2)
bw_imt = 200
bw_sys = 133.33
ue_k = 3
- ref_weights = np.array([ 1, 1, 0])
+ ref_weights = np.array([1, 1, 0])
weights = self.simulation.calculate_bw_weights(bw_imt, bw_sys, ue_k)
npt.assert_allclose(ref_weights, weights, atol=1e-2)
bw_imt = 200
bw_sys = 150
ue_k = 3
- ref_weights = np.array([ 1, 1, 0.25])
+ ref_weights = np.array([1, 1, 0.25])
weights = self.simulation.calculate_bw_weights(bw_imt, bw_sys, ue_k)
npt.assert_allclose(ref_weights, weights, atol=1e-2)
bw_imt = 150
bw_sys = 150
ue_k = 3
- ref_weights = np.array([ 1, 1, 1])
+ ref_weights = np.array([1, 1, 1])
weights = self.simulation.calculate_bw_weights(bw_imt, bw_sys, ue_k)
npt.assert_allclose(ref_weights, weights, atol=1e-2)
bw_imt = 200
bw_sys = 300
ue_k = 3
- ref_weights = np.array([ 1, 1, 1])
+ ref_weights = np.array([1, 1, 1])
weights = self.simulation.calculate_bw_weights(bw_imt, bw_sys, ue_k)
npt.assert_allclose(ref_weights, weights, atol=1e-2)
bw_imt = 200
bw_sys = 50
ue_k = 2
- ref_weights = np.array([ 0.5, 0])
+ ref_weights = np.array([0.5, 0])
weights = self.simulation.calculate_bw_weights(bw_imt, bw_sys, ue_k)
npt.assert_allclose(ref_weights, weights, atol=1e-2)
bw_imt = 100
bw_sys = 60
ue_k = 2
- ref_weights = np.array([ 1, 0.2])
+ ref_weights = np.array([1, 0.2])
weights = self.simulation.calculate_bw_weights(bw_imt, bw_sys, ue_k)
npt.assert_allclose(ref_weights, weights, atol=1e-2)
bw_imt = 300
bw_sys = 300
ue_k = 2
- ref_weights = np.array([ 1, 1])
+ ref_weights = np.array([1, 1])
weights = self.simulation.calculate_bw_weights(bw_imt, bw_sys, ue_k)
npt.assert_allclose(ref_weights, weights, atol=1e-2)
bw_imt = 100
bw_sys = 50
ue_k = 1
- ref_weights = np.array([ 0.5 ])
+ ref_weights = np.array([0.5])
weights = self.simulation.calculate_bw_weights(bw_imt, bw_sys, ue_k)
npt.assert_allclose(ref_weights, weights, atol=1e-2)
bw_imt = 200
bw_sys = 180
ue_k = 1
- ref_weights = np.array([ 0.9])
+ ref_weights = np.array([0.9])
weights = self.simulation.calculate_bw_weights(bw_imt, bw_sys, ue_k)
npt.assert_allclose(ref_weights, weights, atol=1e-2)
+
if __name__ == '__main__':
unittest.main()
diff --git a/tests/test_simulation_downlink_haps.py b/tests/test_simulation_downlink_haps.py
index ae3cf381d..5a5345c5b 100644
--- a/tests/test_simulation_downlink_haps.py
+++ b/tests/test_simulation_downlink_haps.py
@@ -15,6 +15,9 @@
from sharc.antenna.antenna_omni import AntennaOmni
from sharc.station_factory import StationFactory
from sharc.propagation.propagation_factory import PropagationFactory
+from sharc.parameters.imt.parameters_imt_topology import ParametersImtTopology
+from sharc.parameters.imt.parameters_single_bs import ParametersSingleBS
+
class SimulationDownlinkHapsTest(unittest.TestCase):
@@ -27,88 +30,92 @@ def setUp(self):
self.param.general.enable_adjacent_channel = False
self.param.general.overwrite_output = True
- self.param.imt.topology = "SINGLE_BS"
- self.param.imt.wrap_around = False
- self.param.imt.num_clusters = 2
- self.param.imt.intersite_distance = 150
+ self.param.imt.topology = ParametersImtTopology(
+ type="SINGLE_BS",
+ single_bs=ParametersSingleBS(
+ num_clusters=2,
+ intersite_distance=150,
+ cell_radius=2 * 150 / 3
+ )
+ )
self.param.imt.minimum_separation_distance_bs_ue = 10
self.param.imt.interfered_with = False
- self.param.imt.frequency = 10000
+ self.param.imt.frequency = 10000.0
self.param.imt.bandwidth = 100
self.param.imt.rb_bandwidth = 0.180
self.param.imt.spectral_mask = "IMT-2020"
self.param.imt.spurious_emissions = -13
self.param.imt.guard_band_ratio = 0.1
self.param.imt.ho_margin = 3
- self.param.imt.bs_load_probability = 1
- self.param.imt.num_resource_blocks = 10
- self.param.imt.bs_conducted_power = 10
- self.param.imt.bs_height = 6
- self.param.imt.bs_acs = 30
- self.param.imt.bs_noise_figure = 7
- self.param.imt.bs_noise_temperature = 290
- self.param.imt.bs_ohmic_loss = 3
- self.param.imt.ul_attenuation_factor = 0.4
- self.param.imt.ul_sinr_min = -10
- self.param.imt.ul_sinr_max = 22
- self.param.imt.ue_k = 2
- self.param.imt.ue_k_m = 1
- self.param.imt.ue_indoor_percent = 0
- self.param.imt.ue_distribution_distance = "RAYLEIGH"
- self.param.imt.ue_distribution_azimuth = "UNIFORM"
- self.param.imt.ue_distribution_type = "ANGLE_AND_DISTANCE"
- self.param.imt.ue_tx_power_control = "OFF"
- self.param.imt.ue_p_o_pusch = -95
- self.param.imt.ue_alpha = 0.8
- self.param.imt.ue_p_cmax = 20
- self.param.imt.ue_conducted_power = 10
- self.param.imt.ue_height = 1.5
- self.param.imt.ue_aclr = 20
- self.param.imt.ue_acs = 25
- self.param.imt.ue_noise_figure = 9
- self.param.imt.ue_ohmic_loss = 3
- self.param.imt.ue_body_loss = 4
- self.param.imt.dl_attenuation_factor = 0.6
- self.param.imt.dl_sinr_min = -10
- self.param.imt.dl_sinr_max = 30
+ self.param.imt.bs.load_probability = 1
+
+ self.param.imt.bs.conducted_power = 10
+ self.param.imt.bs.height = 6
+ self.param.imt.bs.acs = 30
+ self.param.imt.bs.noise_figure = 7
+ self.param.imt.bs.ohmic_loss = 3
+ self.param.imt.uplink.attenuation_factor = 0.4
+ self.param.imt.uplink.sinr_min = -10
+ self.param.imt.uplink.sinr_max = 22
+ self.param.imt.ue.k = 2
+ self.param.imt.ue.k_m = 1
+ self.param.imt.ue.indoor_percent = 0
+ self.param.imt.ue.distribution_distance = "RAYLEIGH"
+ self.param.imt.ue.distribution_azimuth = "UNIFORM"
+ self.param.imt.ue.distribution_type = "ANGLE_AND_DISTANCE"
+ self.param.imt.ue.tx_power_control = "OFF"
+ self.param.imt.ue.p_o_pusch = -95
+ self.param.imt.ue.alpha = 0.8
+ self.param.imt.ue.p_cmax = 20
+ self.param.imt.ue.conducted_power = 10
+ self.param.imt.ue.height = 1.5
+ self.param.imt.ue.aclr = 20
+ self.param.imt.ue.acs = 25
+ self.param.imt.ue.noise_figure = 9
+ self.param.imt.ue.ohmic_loss = 3
+ self.param.imt.ue.body_loss = 4
+ self.param.imt.downlink.attenuation_factor = 0.6
+ self.param.imt.downlink.sinr_min = -10
+ self.param.imt.downlink.sinr_max = 30
self.param.imt.channel_model = "FSPL"
- self.param.imt.line_of_sight_prob = 0.75 # probability of line-of-sight (not for FSPL)
+ # probability of line-of-sight (not for FSPL)
+ self.param.imt.line_of_sight_prob = 0.75
self.param.imt.shadowing = False
self.param.imt.noise_temperature = 290
- self.param.imt.BOLTZMANN_CONSTANT = 1.38064852e-23
-
- self.param.antenna_imt.adjacent_antenna_model = "SINGLE_ELEMENT"
- self.param.antenna_imt.bs_normalization = False
- self.param.antenna_imt.bs_normalization_file = None
- self.param.antenna_imt.bs_element_pattern = "M2101"
- self.param.antenna_imt.bs_minimum_array_gain = -200
- self.param.antenna_imt.bs_element_max_g = 10
- self.param.antenna_imt.bs_element_phi_3db = 80
- self.param.antenna_imt.bs_element_theta_3db = 80
- self.param.antenna_imt.bs_element_am = 25
- self.param.antenna_imt.bs_element_sla_v = 25
- self.param.antenna_imt.bs_n_rows = 16
- self.param.antenna_imt.bs_n_columns = 16
- self.param.antenna_imt.bs_element_horiz_spacing = 1
- self.param.antenna_imt.bs_element_vert_spacing = 1
- self.param.antenna_imt.bs_multiplication_factor = 12
- self.param.antenna_imt.bs_downtilt = 10
-
- self.param.antenna_imt.ue_normalization_file = None
- self.param.antenna_imt.ue_normalization = False
- self.param.antenna_imt.ue_element_pattern = "M2101"
- self.param.antenna_imt.ue_minimum_array_gain = -200
- self.param.antenna_imt.ue_element_max_g = 5
- self.param.antenna_imt.ue_element_phi_3db = 65
- self.param.antenna_imt.ue_element_theta_3db = 65
- self.param.antenna_imt.ue_element_am = 30
- self.param.antenna_imt.ue_element_sla_v = 30
- self.param.antenna_imt.ue_n_rows = 2
- self.param.antenna_imt.ue_n_columns = 1
- self.param.antenna_imt.ue_element_horiz_spacing = 0.5
- self.param.antenna_imt.ue_element_vert_spacing = 0.5
- self.param.antenna_imt.ue_multiplication_factor = 12
-
+
+ self.param.imt.bs.antenna.adjacent_antenna_model = "SINGLE_ELEMENT"
+ self.param.imt.ue.antenna.adjacent_antenna_model = "SINGLE_ELEMENT"
+ self.param.imt.bs.antenna.normalization = False
+ self.param.imt.bs.antenna.normalization_file = None
+ self.param.imt.bs.antenna.element_pattern = "M2101"
+ self.param.imt.bs.antenna.minimum_array_gain = -200
+ self.param.imt.bs.antenna.element_max_g = 10
+ self.param.imt.bs.antenna.element_phi_3db = 80
+ self.param.imt.bs.antenna.element_theta_3db = 80
+ self.param.imt.bs.antenna.element_am = 25
+ self.param.imt.bs.antenna.element_sla_v = 25
+ self.param.imt.bs.antenna.n_rows = 16
+ self.param.imt.bs.antenna.n_columns = 16
+ self.param.imt.bs.antenna.element_horiz_spacing = 1
+ self.param.imt.bs.antenna.element_vert_spacing = 1
+ self.param.imt.bs.antenna.multiplication_factor = 12
+ self.param.imt.bs.antenna.downtilt = 10
+
+ self.param.imt.ue.antenna.normalization_file = None
+ self.param.imt.ue.antenna.normalization = False
+ self.param.imt.ue.antenna.element_pattern = "M2101"
+ self.param.imt.ue.antenna.minimum_array_gain = -200
+ self.param.imt.ue.antenna.element_max_g = 5
+ self.param.imt.ue.antenna.element_phi_3db = 65
+ self.param.imt.ue.antenna.element_theta_3db = 65
+ self.param.imt.ue.antenna.element_am = 30
+ self.param.imt.ue.antenna.element_sla_v = 30
+ self.param.imt.ue.antenna.n_rows = 2
+ self.param.imt.ue.antenna.n_columns = 1
+ self.param.imt.ue.antenna.element_horiz_spacing = 0.5
+ self.param.imt.ue.antenna.element_vert_spacing = 0.5
+ self.param.imt.ue.antenna.multiplication_factor = 12
+
self.param.haps.frequency = 10000
self.param.haps.bandwidth = 200
self.param.haps.altitude = 20000
@@ -117,7 +124,8 @@ def setUp(self):
self.param.haps.azimuth = 0
self.param.haps.eirp_density = 4.4
self.param.haps.antenna_gain = 28
- self.param.haps.tx_power_density = self.param.haps.eirp_density - self.param.haps.antenna_gain - 60
+ self.param.haps.tx_power_density = self.param.haps.eirp_density - \
+ self.param.haps.antenna_gain - 60
self.param.haps.antenna_pattern = "OMNI"
self.param.haps.imt_altitude = 0
self.param.haps.imt_lat_deg = 0
@@ -125,10 +133,6 @@ def setUp(self):
self.param.haps.season = "SUMMER"
self.param.haps.channel_model = "FSPL"
self.param.haps.antenna_l_n = -25
- self.param.haps.BOLTZMANN_CONSTANT = 1.38064852e-23
- self.param.haps.EARTH_RADIUS = 6371000
-
-
def test_simulation_2bs_4ue_1haps(self):
"""
@@ -146,78 +150,135 @@ def test_simulation_2bs_4ue_1haps(self):
random_number_gen = np.random.RandomState()
self.simulation.bs = StationFactory.generate_imt_base_stations(self.param.imt,
- self.param.antenna_imt,
+ self.param.imt.bs.antenna,
self.simulation.topology,
random_number_gen)
self.simulation.bs.antenna = np.array([AntennaOmni(1), AntennaOmni(2)])
self.simulation.bs.active = np.ones(2, dtype=bool)
self.simulation.ue = StationFactory.generate_imt_ue(self.param.imt,
- self.param.antenna_imt,
+ self.param.imt.ue.antenna,
self.simulation.topology,
random_number_gen)
self.simulation.ue.x = np.array([20, 70, 110, 170])
- self.simulation.ue.y = np.array([ 0, 0, 0, 0])
- self.simulation.ue.antenna = np.array([AntennaOmni(10), AntennaOmni(11), AntennaOmni(22), AntennaOmni(23)])
+ self.simulation.ue.y = np.array([0, 0, 0, 0])
+ self.simulation.ue.antenna = np.array(
+ [AntennaOmni(10), AntennaOmni(11), AntennaOmni(22), AntennaOmni(23)])
self.simulation.ue.active = np.ones(4, dtype=bool)
self.simulation.propagation_imt = PropagationFactory.create_propagation(self.param.imt.channel_model,
- self.param, random_number_gen)
+ self.param,
+ self.simulation.param_system,
+ random_number_gen)
self.simulation.propagation_system = PropagationFactory.create_propagation(self.param.haps.channel_model,
- self.param, random_number_gen)
+ self.param,
+ self.simulation.param_system,
+ random_number_gen)
self.simulation.connect_ue_to_bs()
self.simulation.select_ue(random_number_gen)
- self.simulation.link = {0:[0,1],1:[2,3]}
- self.simulation.coupling_loss_imt = self.simulation.calculate_coupling_loss(self.simulation.bs,
- self.simulation.ue,
- self.simulation.propagation_imt)
+ self.simulation.link = {0: [0, 1], 1: [2, 3]}
+ self.simulation.coupling_loss_imt = \
+ self.simulation.calculate_intra_imt_coupling_loss(self.simulation.ue,
+ self.simulation.bs)
self.simulation.scheduler()
self.simulation.power_control()
self.simulation.calculate_sinr()
- bandwidth_per_ue = math.trunc((1 - 0.1)*100/2)
- thermal_noise = 10*np.log10(1.38064852e-23*290*bandwidth_per_ue*1e3*1e6) + 9
+ bandwidth_per_ue = math.trunc((1 - 0.1) * 100 / 2)
+ thermal_noise = 10 * \
+ np.log10(1.38064852e-23 * 290 * bandwidth_per_ue * 1e3 * 1e6) + 9
- tx_power = 10 - 10*math.log10(2)
- npt.assert_allclose(self.simulation.bs.tx_power[0], np.array([tx_power, tx_power]), atol=1e-2)
- npt.assert_allclose(self.simulation.bs.tx_power[1], np.array([tx_power, tx_power]), atol=1e-2)
+ tx_power = 10 - 10 * math.log10(2)
+ npt.assert_allclose(self.simulation.bs.tx_power[0], np.array(
+ [tx_power, tx_power]), atol=1e-2)
+ npt.assert_allclose(self.simulation.bs.tx_power[1], np.array(
+ [tx_power, tx_power]), atol=1e-2)
# check UE received power
- rx_power = np.array([tx_power-3-(78.47-1-10)-4-3, tx_power-3-(89.35-1-11)-4-3, tx_power-3-(91.53-2-22)-4-3, tx_power-3-(81.99-2-23)-4-3])
+ rx_power = np.array([tx_power - 3 - (78.68 - 1 - 10) - 4 - 3,
+ tx_power - 3 - (89.37 - 1 - 11) - 4 - 3,
+ tx_power - 3 - (91.54 - 2 - 22) - 4 - 3,
+ tx_power - 3 - (82.09 - 2 - 23) - 4 - 3])
npt.assert_allclose(self.simulation.ue.rx_power, rx_power, atol=1e-2)
# check UE received interference
- rx_interference = np.array([tx_power-3-(97.55-2-10)-4-3, tx_power-3-(94.72-2-11)-4-3, tx_power-3-(93.27-1-22)-4-3, tx_power-3-(97.05-1-23)-4-3])
- npt.assert_allclose(self.simulation.ue.rx_interference, rx_interference, atol=1e-2)
+ rx_interference = np.array([tx_power -
+ 3 -
+ (97.55 -
+ 2 -
+ 10) -
+ 4 -
+ 3, tx_power -
+ 3 -
+ (94.73 -
+ 2 -
+ 11) -
+ 4 -
+ 3, tx_power -
+ 3 -
+ (93.28 -
+ 1 -
+ 22) -
+ 4 -
+ 3, tx_power -
+ 3 -
+ (97.07 -
+ 1 -
+ 23) -
+ 4 -
+ 3])
+ npt.assert_allclose(
+ self.simulation.ue.rx_interference,
+ rx_interference,
+ atol=1e-2)
# check UE thermal noise
- thermal_noise = 10*np.log10(1.38064852e-23*290*bandwidth_per_ue*1e3*1e6) + 9
- npt.assert_allclose(self.simulation.ue.thermal_noise, thermal_noise, atol=1e-2)
+ thermal_noise = 10 * \
+ np.log10(1.38064852e-23 * 290 * bandwidth_per_ue * 1e3 * 1e6) + 9
+ npt.assert_allclose(
+ self.simulation.ue.thermal_noise,
+ thermal_noise,
+ atol=1e-2)
# check UE thermal noise + interference
- total_interference = 10*np.log10(np.power(10, 0.1*rx_interference) + np.power(10, 0.1*thermal_noise))
- npt.assert_allclose(self.simulation.ue.total_interference, total_interference, atol=1e-2)
-
- self.simulation.system = StationFactory.generate_haps(self.param.haps, 0, random_number_gen)
+ total_interference = 10 * \
+ np.log10(
+ np.power(
+ 10,
+ 0.1 *
+ rx_interference) +
+ np.power(
+ 10,
+ 0.1 *
+ thermal_noise))
+ npt.assert_allclose(
+ self.simulation.ue.total_interference,
+ total_interference,
+ atol=1e-2)
+
+ self.simulation.system = StationFactory.generate_haps(
+ self.param.haps, 0, random_number_gen)
# now we evaluate interference from HAPS to IMT UE
self.simulation.calculate_sinr_ext()
# check coupling loss between FSS_ES and IMT_UE
- coupling_loss_imt_system = np.array([148.47-28-10, 148.47-28-11, 148.47-28-22, 148.47-28-23])
+ coupling_loss_imt_system = np.array(
+ [148.47 - 28 - 10, 148.47 - 28 - 11, 148.47 - 28 - 22, 148.47 - 28 - 23])
npt.assert_allclose(self.simulation.coupling_loss_imt_system,
coupling_loss_imt_system,
atol=1e-2)
- system_tx_power = (4.4 - 28 - 60) + 10*math.log10(bandwidth_per_ue*1e6) + 30
+ system_tx_power = (4.4 - 28 - 60) + 10 * \
+ math.log10(bandwidth_per_ue * 1e6) + 30
ext_interference = system_tx_power - coupling_loss_imt_system
npt.assert_allclose(self.simulation.ue.ext_interference,
ext_interference,
atol=1e-2)
- ext_interference_total = 10*np.log10(np.power(10, 0.1*total_interference) \
- + np.power(10, 0.1*ext_interference))
+ ext_interference_total = 10 * np.log10(np.power(10, 0.1 * total_interference) +
+ np.power(10, 0.1 * ext_interference))
npt.assert_allclose(self.simulation.ue.sinr_ext,
rx_power - ext_interference_total,
@@ -228,8 +289,5 @@ def test_simulation_2bs_4ue_1haps(self):
atol=1e-2)
-
-
-
if __name__ == '__main__':
unittest.main()
diff --git a/tests/test_simulation_downlink_tvro.py b/tests/test_simulation_downlink_tvro.py
index 6b0485174..dbce8f18d 100644
--- a/tests/test_simulation_downlink_tvro.py
+++ b/tests/test_simulation_downlink_tvro.py
@@ -15,6 +15,7 @@
from sharc.station_factory import StationFactory
from sharc.propagation.propagation_factory import PropagationFactory
+
class SimulationDownlinkTvroTest(unittest.TestCase):
def setUp(self):
@@ -27,91 +28,91 @@ def setUp(self):
self.param.general.seed = 101
self.param.general.overwrite_output = True
- self.param.imt.topology = "SINGLE_BS"
- self.param.imt.wrap_around = False
- self.param.imt.num_clusters = 2
- self.param.imt.intersite_distance = 150
+ self.param.imt.topology.type = "SINGLE_BS"
+ self.param.imt.topology.single_bs.num_clusters = 2
+ self.param.imt.topology.single_bs.intersite_distance = 150
+ self.param.imt.topology.single_bs.cell_radius = 100
self.param.imt.minimum_separation_distance_bs_ue = 10
self.param.imt.interfered_with = False
- self.param.imt.frequency = 3590
+ self.param.imt.frequency = 3590.0
self.param.imt.bandwidth = 20
self.param.imt.rb_bandwidth = 0.180
self.param.imt.spectral_mask = "3GPP E-UTRA"
self.param.imt.spurious_emissions = -13
self.param.imt.guard_band_ratio = 0.1
- self.param.imt.bs_load_probability = 1
- self.param.imt.num_resource_blocks = 10
- self.param.imt.bs_conducted_power = 46
- self.param.imt.bs_height = 20
- self.param.imt.bs_noise_figure = 5
- self.param.imt.bs_noise_temperature = 290
- self.param.imt.bs_ohmic_loss = 3
- self.param.imt.ul_attenuation_factor = 0.4
- self.param.imt.ul_sinr_min = -10
- self.param.imt.ul_sinr_max = 22
- self.param.imt.ue_k = 2
- self.param.imt.ue_k_m = 1
- self.param.imt.ue_indoor_percent = 0
- self.param.imt.ue_distribution_type = "ANGLE_AND_DISTANCE"
- self.param.imt.ue_distribution_distance = "UNIFORM"
- self.param.imt.ue_distribution_azimuth = "UNIFORM"
- self.param.imt.ue_tx_power_control = "OFF"
- self.param.imt.ue_p_o_pusch = -95
- self.param.imt.ue_alpha = 1
- self.param.imt.ue_p_cmax = 23
- self.param.imt.ue_power_dynamic_range = 63
- self.param.imt.ue_height = 1.5
- self.param.imt.ue_acs = 25
- self.param.imt.ue_noise_figure = 9
- self.param.imt.ue_ohmic_loss = 3
- self.param.imt.ue_body_loss = 4
- self.param.imt.dl_attenuation_factor = 0.6
- self.param.imt.dl_sinr_min = -10
- self.param.imt.dl_sinr_max = 30
+ self.param.imt.bs.load_probability = 1
+
+ self.param.imt.bs.conducted_power = 46
+ self.param.imt.bs.height = 20
+ self.param.imt.bs.noise_figure = 5
+ self.param.imt.bs.ohmic_loss = 3
+ self.param.imt.uplink.attenuation_factor = 0.4
+ self.param.imt.uplink.sinr_min = -10
+ self.param.imt.uplink.sinr_max = 22
+ self.param.imt.ue.k = 2
+ self.param.imt.ue.k_m = 1
+ self.param.imt.ue.indoor_percent = 0
+ self.param.imt.ue.distribution_type = "ANGLE_AND_DISTANCE"
+ self.param.imt.ue.distribution_distance = "UNIFORM"
+ self.param.imt.ue.distribution_azimuth = "UNIFORM"
+ self.param.imt.ue.tx_power_control = "OFF"
+ self.param.imt.ue.p_o_pusch = -95
+ self.param.imt.ue.alpha = 1
+ self.param.imt.ue.p_cmax = 23
+ self.param.imt.ue.power_dynamic_range = 63
+ self.param.imt.ue.height = 1.5
+ self.param.imt.ue.acs = 25
+ self.param.imt.ue.noise_figure = 9
+ self.param.imt.ue.ohmic_loss = 3
+ self.param.imt.ue.body_loss = 4
+ self.param.imt.downlink.attenuation_factor = 0.6
+ self.param.imt.downlink.sinr_min = -10
+ self.param.imt.downlink.sinr_max = 30
self.param.imt.channel_model = "FSPL"
self.param.imt.los_adjustment_factor = 29
- self.param.imt.line_of_sight_prob = 0.75 # probability of line-of-sight (not for FSPL)
+ # probability of line-of-sight (not for FSPL)
+ self.param.imt.line_of_sight_prob = 0.75
self.param.imt.shadowing = False
self.param.imt.noise_temperature = 290
- self.param.imt.BOLTZMANN_CONSTANT = 1.38064852e-23
-
- self.param.antenna_imt.adjacent_antenna_model = "BEAMFORMING"
- self.param.antenna_imt.bs_normalization = False
- self.param.antenna_imt.bs_element_pattern = "F1336"
- self.param.antenna_imt.bs_normalization_file = None
- self.param.antenna_imt.bs_minimum_array_gain = -200
- self.param.antenna_imt.bs_element_max_g = 18
- self.param.antenna_imt.bs_element_phi_3db = 65
- self.param.antenna_imt.bs_element_theta_3db = 0
- self.param.antenna_imt.bs_element_am = 25
- self.param.antenna_imt.bs_element_sla_v = 25
- self.param.antenna_imt.bs_n_rows = 1
- self.param.antenna_imt.bs_n_columns = 1
- self.param.antenna_imt.bs_element_horiz_spacing = 1
- self.param.antenna_imt.bs_element_vert_spacing = 1
- self.param.antenna_imt.bs_multiplication_factor = 12
- self.param.antenna_imt.bs_downtilt = 10
-
- self.param.antenna_imt.ue_element_pattern = "FIXED"
- self.param.antenna_imt.ue_normalization = False
- self.param.antenna_imt.ue_normalization_file = None
- self.param.antenna_imt.ue_minimum_array_gain = -200
- self.param.antenna_imt.ue_element_max_g = -4
- self.param.antenna_imt.ue_element_phi_3db = 0
- self.param.antenna_imt.ue_element_theta_3db = 0
- self.param.antenna_imt.ue_element_am = 0
- self.param.antenna_imt.ue_element_sla_v = 0
- self.param.antenna_imt.ue_n_rows = 1
- self.param.antenna_imt.ue_n_columns = 1
- self.param.antenna_imt.ue_element_horiz_spacing = 0.5
- self.param.antenna_imt.ue_element_vert_spacing = 0.5
- self.param.antenna_imt.ue_multiplication_factor = 12
+
+ self.param.imt.bs.antenna.adjacent_antenna_model = "BEAMFORMING"
+ self.param.imt.ue.antenna.adjacent_antenna_model = "BEAMFORMING"
+ self.param.imt.bs.antenna.normalization = False
+ self.param.imt.bs.antenna.element_pattern = "F1336"
+ self.param.imt.bs.antenna.normalization_file = None
+ self.param.imt.bs.antenna.minimum_array_gain = -200
+ self.param.imt.bs.antenna.element_max_g = 18
+ self.param.imt.bs.antenna.element_phi_3db = 65
+ self.param.imt.bs.antenna.element_theta_3db = 0
+ self.param.imt.bs.antenna.element_am = 25
+ self.param.imt.bs.antenna.element_sla_v = 25
+ self.param.imt.bs.antenna.n_rows = 1
+ self.param.imt.bs.antenna.n_columns = 1
+ self.param.imt.bs.antenna.element_horiz_spacing = 1
+ self.param.imt.bs.antenna.element_vert_spacing = 1
+ self.param.imt.bs.antenna.multiplication_factor = 12
+ self.param.imt.bs.antenna.downtilt = 10
+
+ self.param.imt.ue.antenna.element_pattern = "FIXED"
+ self.param.imt.ue.antenna.normalization = False
+ self.param.imt.ue.antenna.normalization_file = None
+ self.param.imt.ue.antenna.minimum_array_gain = -200
+ self.param.imt.ue.antenna.element_max_g = -4
+ self.param.imt.ue.antenna.element_phi_3db = 0
+ self.param.imt.ue.antenna.element_theta_3db = 0
+ self.param.imt.ue.antenna.element_am = 0
+ self.param.imt.ue.antenna.element_sla_v = 0
+ self.param.imt.ue.antenna.n_rows = 1
+ self.param.imt.ue.antenna.n_columns = 1
+ self.param.imt.ue.antenna.element_horiz_spacing = 0.5
+ self.param.imt.ue.antenna.element_vert_spacing = 0.5
+ self.param.imt.ue.antenna.multiplication_factor = 12
self.param.fss_es.location = "FIXED"
self.param.fss_es.x = 100
self.param.fss_es.y = 0
self.param.fss_es.min_dist_to_bs = 10
- self.param.fss_es.max_dist_to_bs = 600
+ self.param.fss_es.max_dist_to_bs = 600
self.param.fss_es.height = 6
self.param.fss_es.elevation_min = 49.8
self.param.fss_es.elevation_max = 49.8
@@ -127,9 +128,6 @@ def setUp(self):
self.param.fss_es.antenna_envelope_gain = 0
self.param.fss_es.channel_model = "FSPL"
self.param.fss_es.line_of_sight_prob = 1
- self.param.fss_es.BOLTZMANN_CONSTANT = 1.38064852e-23
- self.param.fss_es.EARTH_RADIUS = 6371000
-
def test_simulation_1bs_1ue_tvro(self):
self.param.general.system = "FSS_ES"
@@ -137,20 +135,20 @@ def test_simulation_1bs_1ue_tvro(self):
self.simulation = SimulationDownlink(self.param, "")
self.simulation.initialize()
random_number_gen = np.random.RandomState(self.param.general.seed)
-
+
self.assertTrue(self.simulation.co_channel)
self.simulation.bs = StationFactory.generate_imt_base_stations(self.param.imt,
- self.param.antenna_imt,
+ self.param.imt.bs.antenna,
self.simulation.topology,
random_number_gen)
self.simulation.bs.x = np.array([0, -200])
self.simulation.bs.y = np.array([0, 0])
self.simulation.bs.azimuth = np.array([0, 180])
self.simulation.bs.elevation = np.array([-10, -10])
-
+
self.simulation.ue = StationFactory.generate_imt_ue(self.param.imt,
- self.param.antenna_imt,
+ self.param.imt.ue.antenna,
self.simulation.topology,
random_number_gen)
self.simulation.ue.x = np.array([30, 60, -220, -300])
@@ -159,98 +157,117 @@ def test_simulation_1bs_1ue_tvro(self):
# test connection method
self.simulation.connect_ue_to_bs()
self.simulation.select_ue(random_number_gen)
- self.simulation.link = {0:[0,1], 1:[2,3]}
- self.assertEqual(self.simulation.link, {0: [0,1], 1: [2,3]})
-
+ self.simulation.link = {0: [0, 1], 1: [2, 3]}
+ self.assertEqual(self.simulation.link, {0: [0, 1], 1: [2, 3]})
+
self.simulation.propagation_imt = PropagationFactory.create_propagation(self.param.imt.channel_model,
- self.param, random_number_gen)
+ self.param,
+ self.simulation.param_system,
+ random_number_gen)
self.simulation.propagation_system = PropagationFactory.create_propagation(self.param.fss_es.channel_model,
+ self.simulation.param_system,
self.param, random_number_gen)
# test coupling loss method
- self.simulation.coupling_loss_imt = self.simulation.calculate_coupling_loss(self.simulation.bs,
- self.simulation.ue,
- self.simulation.propagation_imt)
- path_loss_imt = np.array([[73.09, 79.11, 90.40, 93.09],
- [90.78, 91.85, 69.57, 83.55]])
- bs_antenna_gains = np.array([[ 3.04, 7.30, -6.45, -6.45],
- [ -6.45, -6.45, 1.63, 17.95]])
- ue_antenna_gains = np.array([[ -4, -4, -4, -4], [ -4, -4, -4, -4]])
+ self.simulation.coupling_loss_imt = self.simulation.calculate_intra_imt_coupling_loss(self.simulation.ue,
+ self.simulation.bs)
+ path_loss_imt = np.array([[74.49, 79.50, 90.43, 93.11],
+ [90.81, 91.87, 72.25, 83.69]])
+ bs_antenna_gains = np.array([[3.04, 7.30, -6.45, -6.45],
+ [-6.45, -6.45, 1.63, 17.95]])
+ ue_antenna_gains = np.array([[-4, -4, -4, -4], [-4, -4, -4, -4]])
coupling_loss_imt = path_loss_imt - bs_antenna_gains - ue_antenna_gains \
- + self.param.imt.bs_ohmic_loss \
- + self.param.imt.ue_ohmic_loss \
- + self.param.imt.ue_body_loss
+ + self.param.imt.bs.ohmic_loss \
+ + self.param.imt.ue.ohmic_loss \
+ + self.param.imt.ue.body_loss
npt.assert_allclose(self.simulation.coupling_loss_imt,
coupling_loss_imt,
atol=1e-1)
# test scheduler and bandwidth allocation
self.simulation.scheduler()
- bandwidth_per_ue = math.trunc((1 - 0.1)*20/2)
- npt.assert_allclose(self.simulation.ue.bandwidth, bandwidth_per_ue*np.ones(4), atol=1e-2)
-
+ bandwidth_per_ue = math.trunc((1 - 0.1) * 20 / 2)
+ npt.assert_allclose(self.simulation.ue.bandwidth,
+ bandwidth_per_ue * np.ones(4), atol=1e-2)
+
# there is no power control, so BS's will transmit at maximum power
self.simulation.power_control()
- tx_power = 46 - 10*np.log10(2)
- npt.assert_allclose(self.simulation.bs.tx_power[0], np.array([tx_power, tx_power]), atol=1e-2)
- npt.assert_allclose(self.simulation.bs.tx_power[1], np.array([tx_power, tx_power]), atol=1e-2)
+ tx_power = 46 - 10 * np.log10(2)
+ npt.assert_allclose(self.simulation.bs.tx_power[0], np.array(
+ [tx_power, tx_power]), atol=1e-2)
+ npt.assert_allclose(self.simulation.bs.tx_power[1], np.array(
+ [tx_power, tx_power]), atol=1e-2)
# test method that calculates SINR
self.simulation.calculate_sinr()
-
+
# check UE received power
- rx_power = tx_power - np.concatenate((coupling_loss_imt[0][:2], coupling_loss_imt[1][2:]))
+ rx_power = tx_power - \
+ np.concatenate(
+ (coupling_loss_imt[0][:2], coupling_loss_imt[1][2:]))
npt.assert_allclose(self.simulation.ue.rx_power, rx_power, atol=1e-1)
# check UE received interference
- rx_interference = tx_power - np.concatenate((coupling_loss_imt[1][:2], coupling_loss_imt[0][2:]))
- npt.assert_allclose(self.simulation.ue.rx_interference, rx_interference, atol=1e-1)
+ rx_interference = tx_power - \
+ np.concatenate(
+ (coupling_loss_imt[1][:2], coupling_loss_imt[0][2:]))
+ npt.assert_allclose(self.simulation.ue.rx_interference,
+ rx_interference, atol=1e-1)
# check UE thermal noise
- thermal_noise = 10*np.log10(1.38064852e-23*290*bandwidth_per_ue*1e3*1e6) + 9
- npt.assert_allclose(self.simulation.ue.thermal_noise, thermal_noise, atol=1e-1)
+ thermal_noise = 10 * \
+ np.log10(1.38064852e-23 * 290 * bandwidth_per_ue * 1e3 * 1e6) + 9
+ npt.assert_allclose(self.simulation.ue.thermal_noise,
+ thermal_noise, atol=1e-1)
# check UE thermal noise + interference
- total_interference = 10*np.log10(np.power(10, 0.1*rx_interference) + np.power(10, 0.1*thermal_noise))
- npt.assert_allclose(self.simulation.ue.total_interference, total_interference, atol=1e-1)
+ total_interference = 10 * \
+ np.log10(np.power(10, 0.1 * rx_interference) +
+ np.power(10, 0.1 * thermal_noise))
+ npt.assert_allclose(
+ self.simulation.ue.total_interference, total_interference, atol=1e-1)
# check SNR
- npt.assert_allclose(self.simulation.ue.snr, rx_power - thermal_noise, atol=1e-1)
+ npt.assert_allclose(self.simulation.ue.snr,
+ rx_power - thermal_noise, atol=1e-1)
# check SINR
- npt.assert_allclose(self.simulation.ue.sinr, rx_power - total_interference, atol=1e-1)
+ npt.assert_allclose(self.simulation.ue.sinr,
+ rx_power - total_interference, atol=1e-1)
#######################################################################
- self.simulation.system = StationFactory.generate_fss_earth_station(self.param.fss_es, random_number_gen)
+ self.simulation.system = StationFactory.generate_fss_earth_station(
+ self.param.fss_es, random_number_gen)
self.simulation.system.x = np.array([600])
self.simulation.system.y = np.array([0])
-
- # test the method that calculates interference from IMT UE to FSS space station
- self.simulation.calculate_external_interference()
-
+
+ # test the method that calculates interference from IMT UE to FSS space
+ # station
+ self.simulation.calculate_external_interference()
+
# check coupling loss from IMT_BS to FSS_ES
- # 4 values because we have 2 BS * 2 beams for each base station.
- path_loss_imt_system = np.array([99.11, 99.11, 101.61, 101.61])
+ # 4 values because we have 2 BS * 2 beams for each base station.
+ path_loss_imt_system = np.array([99.11, 99.11, 101.61, 101.61])
polarization_loss = 3
- tvro_antenna_gain = np.array([ 0, 0, 0, 0])
- bs_antenna_gain = np.array([6.47, 6.47, -6.45, -6.45])
+ tvro_antenna_gain = np.array([0, 0, 0, 0])
+ bs_antenna_gain = np.array([6.47, 6.47, -6.45, -6.45])
coupling_loss_imt_system = path_loss_imt_system - tvro_antenna_gain \
- - bs_antenna_gain \
- + polarization_loss \
- + self.param.imt.bs_ohmic_loss
-
+ - bs_antenna_gain \
+ + polarization_loss \
+ + self.param.imt.bs.ohmic_loss
+
npt.assert_allclose(self.simulation.coupling_loss_imt_system,
coupling_loss_imt_system,
atol=1e-1)
-
+
# check blocking signal
interference = tx_power - coupling_loss_imt_system
- rx_interference = 10*math.log10(np.sum(np.power(10, 0.1*interference)))
+ rx_interference = 10 * \
+ math.log10(np.sum(np.power(10, 0.1 * interference)))
self.assertAlmostEqual(self.simulation.system.rx_interference,
rx_interference,
delta=.01)
-
if __name__ == '__main__':
- unittest.main()
\ No newline at end of file
+ unittest.main()
diff --git a/tests/test_simulation_indoor.py b/tests/test_simulation_indoor.py
index fc38f16da..63a2d2b58 100644
--- a/tests/test_simulation_indoor.py
+++ b/tests/test_simulation_indoor.py
@@ -15,7 +15,9 @@
from sharc.parameters.parameters import Parameters
from sharc.antenna.antenna_omni import AntennaOmni
from sharc.station_factory import StationFactory
-from sharc.propagation.propagation_factory import PropagationFactory
+from sharc.parameters.imt.parameters_imt_topology import ParametersImtTopology
+from sharc.parameters.imt.parameters_indoor import ParametersIndoor
+
class SimulationIndoorTest(unittest.TestCase):
@@ -28,9 +30,7 @@ def setUp(self):
self.param.general.enable_adjacent_channel = False
self.param.general.overwrite_output = True
- self.param.imt.topology = "INDOOR"
- self.param.imt.num_clusters = 1
- self.param.imt.intersite_distance = 339
+ self.param.imt.topology.type = "INDOOR"
self.param.imt.minimum_separation_distance_bs_ue = 10
self.param.imt.interfered_with = False
self.param.imt.frequency = 40000
@@ -39,81 +39,81 @@ def setUp(self):
self.param.imt.spectral_mask = "IMT-2020"
self.param.imt.spurious_emissions = -13
self.param.imt.guard_band_ratio = 0.1
- self.param.imt.bs_load_probability = 1
- self.param.imt.num_resource_blocks = 10
- self.param.imt.bs_conducted_power = 2
- self.param.imt.bs_height = 3
- self.param.imt.bs_noise_figure = 12
- self.param.imt.bs_noise_temperature = 290
- self.param.imt.bs_ohmic_loss = 3
- self.param.imt.ul_attenuation_factor = 0.4
- self.param.imt.ul_sinr_min = -10
- self.param.imt.ul_sinr_max = 22
- self.param.imt.ue_k = 1
- self.param.imt.ue_k_m = 1
- self.param.imt.ue_indoor_percent = 95
- self.param.imt.ue_distribution_type = "ANGLE_AND_DISTANCE"
- self.param.imt.ue_distribution_distance = "RAYLEIGH"
- self.param.imt.ue_distribution_azimuth = "UNIFORM"
- self.param.imt.ue_tx_power_control = "OFF"
- self.param.imt.ue_p_o_pusch = -95
- self.param.imt.ue_alpha = 1
- self.param.imt.ue_p_cmax = 22
- self.param.imt.ue_height = 1.5
- self.param.imt.ue_noise_figure = 12
- self.param.imt.ue_ohmic_loss = 3
- self.param.imt.ue_body_loss = 4
- self.param.imt.dl_attenuation_factor = 0.6
- self.param.imt.dl_sinr_min = -10
- self.param.imt.dl_sinr_max = 30
+ self.param.imt.bs.load_probability = 1
+
+ self.param.imt.bs.conducted_power = 2
+ self.param.imt.bs.height = 3
+ self.param.imt.bs.noise_figure = 12
+ self.param.imt.bs.ohmic_loss = 3
+ self.param.imt.uplink.attenuation_factor = 0.4
+ self.param.imt.uplink.sinr_min = -10
+ self.param.imt.uplink.sinr_max = 22
+ self.param.imt.ue.k = 1
+ self.param.imt.ue.k_m = 1
+ self.param.imt.ue.indoor_percent = 95
+ self.param.imt.ue.distribution_type = "ANGLE_AND_DISTANCE"
+ self.param.imt.ue.distribution_distance = "RAYLEIGH"
+ self.param.imt.ue.distribution_azimuth = "UNIFORM"
+ self.param.imt.ue.tx_power_control = "OFF"
+ self.param.imt.ue.p_o_pusch = -95
+ self.param.imt.ue.alpha = 1
+ self.param.imt.ue.p_cmax = 22
+ self.param.imt.ue.height = 1.5
+ self.param.imt.ue.noise_figure = 12
+ self.param.imt.ue.ohmic_loss = 3
+ self.param.imt.ue.body_loss = 4
+ self.param.imt.downlink.attenuation_factor = 0.6
+ self.param.imt.downlink.sinr_min = -10
+ self.param.imt.downlink.sinr_max = 30
self.param.imt.channel_model = "FSPL"
self.param.imt.shadowing = False
- self.param.imt.wrap_around = False
self.param.imt.noise_temperature = 290
- self.param.imt.BOLTZMANN_CONSTANT = 1.38064852e-23
-
- self.param.antenna_imt.adjacent_antenna_model = "SINGLE_ELEMENT"
- self.param.antenna_imt.bs_normalization = False
- self.param.antenna_imt.bs_normalization_file = path.join('..','sharc','antenna','beamforming_normalization','bs_indoor_norm.npz')
- self.param.antenna_imt.ue_normalization_file = path.join('..','sharc','antenna','beamforming_normalization','ue_norm.npz')
- self.param.antenna_imt.bs_element_pattern = "M2101"
- self.param.antenna_imt.bs_minimum_array_gain = -200
- self.param.antenna_imt.bs_element_max_g = 5
- self.param.antenna_imt.bs_element_phi_3db = 90
- self.param.antenna_imt.bs_element_theta_3db = 90
- self.param.antenna_imt.bs_element_am = 25
- self.param.antenna_imt.bs_element_sla_v = 25
- self.param.antenna_imt.bs_n_rows = 8
- self.param.antenna_imt.bs_n_columns = 16
- self.param.antenna_imt.bs_element_horiz_spacing = 0.5
- self.param.antenna_imt.bs_element_vert_spacing = 0.5
- self.param.antenna_imt.bs_multiplication_factor = 12
- self.param.antenna_imt.bs_downtilt = 90
-
- self.param.antenna_imt.ue_element_pattern = "M2101"
- self.param.antenna_imt.ue_normalization = False
- self.param.antenna_imt.ue_minimum_array_gain = -200
- self.param.antenna_imt.ue_element_max_g = 5
- self.param.antenna_imt.ue_element_phi_3db = 90
- self.param.antenna_imt.ue_element_theta_3db = 90
- self.param.antenna_imt.ue_element_am = 25
- self.param.antenna_imt.ue_element_sla_v = 25
- self.param.antenna_imt.ue_n_rows = 4
- self.param.antenna_imt.ue_n_columns = 4
- self.param.antenna_imt.ue_element_horiz_spacing = 0.5
- self.param.antenna_imt.ue_element_vert_spacing = 0.5
- self.param.antenna_imt.ue_multiplication_factor = 12
-
- self.param.indoor.basic_path_loss = "FSPL"
- self.param.indoor.n_rows = 1
- self.param.indoor.n_colums = 1
- self.param.indoor.num_imt_buildings = 'ALL'
- self.param.indoor.street_width = 30
- self.param.indoor.ue_indoor_percent = 0.95
- self.param.indoor.building_class = "TRADITIONAL"
- self.param.indoor.intersite_distance = 30
- self.param.indoor.num_cells = 4
- self.param.indoor.num_floors = 1
+
+ self.param.imt.bs.antenna.adjacent_antenna_model = "SINGLE_ELEMENT"
+ self.param.imt.ue.antenna.adjacent_antenna_model = "SINGLE_ELEMENT"
+ self.param.imt.bs.antenna.normalization = False
+ self.param.imt.bs.antenna.normalization_file = path.join(
+ '..', 'sharc', 'antenna', 'beamforming_normalization', 'bs_indoor_norm.npz')
+ self.param.imt.ue.antenna.normalization_file = path.join(
+ '..', 'sharc', 'antenna', 'beamforming_normalization', 'ue_norm.npz')
+ self.param.imt.bs.antenna.element_pattern = "M2101"
+ self.param.imt.bs.antenna.minimum_array_gain = -200
+ self.param.imt.bs.antenna.element_max_g = 5
+ self.param.imt.bs.antenna.element_phi_3db = 90
+ self.param.imt.bs.antenna.element_theta_3db = 90
+ self.param.imt.bs.antenna.element_am = 25
+ self.param.imt.bs.antenna.element_sla_v = 25
+ self.param.imt.bs.antenna.n_rows = 8
+ self.param.imt.bs.antenna.n_columns = 16
+ self.param.imt.bs.antenna.element_horiz_spacing = 0.5
+ self.param.imt.bs.antenna.element_vert_spacing = 0.5
+ self.param.imt.bs.antenna.multiplication_factor = 12
+ self.param.imt.bs.antenna.downtilt = 90
+
+ self.param.imt.ue.antenna.element_pattern = "M2101"
+ self.param.imt.ue.antenna.normalization = False
+ self.param.imt.ue.antenna.minimum_array_gain = -200
+ self.param.imt.ue.antenna.element_max_g = 5
+ self.param.imt.ue.antenna.element_phi_3db = 90
+ self.param.imt.ue.antenna.element_theta_3db = 90
+ self.param.imt.ue.antenna.element_am = 25
+ self.param.imt.ue.antenna.element_sla_v = 25
+ self.param.imt.ue.antenna.n_rows = 4
+ self.param.imt.ue.antenna.n_columns = 4
+ self.param.imt.ue.antenna.element_horiz_spacing = 0.5
+ self.param.imt.ue.antenna.element_vert_spacing = 0.5
+ self.param.imt.ue.antenna.multiplication_factor = 12
+
+ self.param.imt.topology.indoor.basic_path_loss = "FSPL"
+ self.param.imt.topology.indoor.n_rows = 1
+ self.param.imt.topology.indoor.n_colums = 1
+ self.param.imt.topology.indoor.num_imt_buildings = 'ALL'
+ self.param.imt.topology.indoor.street_width = 30
+ self.param.imt.topology.indoor.ue_indoor_percent = 0.95
+ self.param.imt.topology.indoor.building_class = "TRADITIONAL"
+ self.param.imt.topology.indoor.intersite_distance = 30
+ self.param.imt.topology.indoor.num_cells = 4
+ self.param.imt.topology.indoor.num_floors = 1
self.param.fss_es.x = 135
self.param.fss_es.y = 65
@@ -132,9 +132,6 @@ def setUp(self):
self.param.fss_es.line_of_sight_prob = 1
self.param.fss_es.adjacent_ch_selectivity = 0
self.param.fss_es.diameter = 0.74
- self.param.fss_es.BOLTZMANN_CONSTANT = 1.38064852e-23
- self.param.fss_es.EARTH_RADIUS = 6371000
-
def test_simulation_fss_es(self):
# Initialize stations
@@ -146,94 +143,104 @@ def test_simulation_fss_es(self):
random_number_gen = np.random.RandomState(101)
self.simulation.bs = StationFactory.generate_imt_base_stations(self.param.imt,
- self.param.antenna_imt,
+ self.param.imt.bs.antenna,
self.simulation.topology,
random_number_gen)
self.assertTrue(np.all(self.simulation.bs.active))
-
+
self.simulation.system = StationFactory.generate_fss_earth_station(self.param.fss_es,
random_number_gen)
self.simulation.ue = StationFactory.generate_imt_ue(self.param.imt,
- self.param.antenna_imt,
+ self.param.imt.ue.antenna,
self.simulation.topology,
random_number_gen)
-
+
# print("Random position:")
# self.simulation.plot_scenario()
- self.simulation.ue.x = np.array([0.0, 45.0, 75.0,120.0])
- self.simulation.ue.y = np.array([0.0, 50.0, 0.0, 50.0])
+ self.simulation.ue.x = np.array([0.0, 45.0, 75.0, 120.0])
+ self.simulation.ue.y = np.array([0.0, 50.0, 0.0, 50.0])
# print("Forced position:")
# self.simulation.plot_scenario()
-
+
# Connect and select UEs
self.simulation.connect_ue_to_bs()
self.simulation.select_ue(random_number_gen)
self.assertTrue(np.all(self.simulation.ue.active))
- self.assertDictEqual(self.simulation.link,{0:[0],1:[1],2:[2],3:[3]})
-
+ self.assertDictEqual(
+ self.simulation.link, {
+ 0: [0], 1: [1], 2: [2], 3: [3]})
+
# Test BS-to-UE angles in the IMT coord system
- expected_azi = np.array([[-120.96, 39.80, -22.62, 13.39],
- [-150.95, 90.00, -39.81, 18.43],
- [-161.57, 140.19, -90.00, 29.06],
- [-166.61, 157.38,-140.19, 59.03]])
+ expected_azi = np.array([[-120.96, 39.80, -22.62, 13.39],
+ [-150.95, 90.00, -39.81, 18.43],
+ [-161.57, 140.19, -90.00, 29.06],
+ [-166.61, 157.38, -140.19, 59.03]])
npt.assert_allclose(self.simulation.bs_to_ue_phi,
expected_azi,
atol=1e-2)
- expected_ele = np.array([[92.95, 92.20, 91.32, 90.79],
- [91.67, 93.43, 92.20, 91.09],
- [91.09, 92.20, 93.43, 91.67],
- [90.79, 91.32, 92.20, 92.95]])
+ expected_ele = np.array([[92.95, 92.20, 91.32, 90.79],
+ [91.67, 93.43, 92.20, 91.09],
+ [91.09, 92.20, 93.43, 91.67],
+ [90.79, 91.32, 92.20, 92.95]])
npt.assert_allclose(self.simulation.bs_to_ue_theta,
expected_ele,
atol=1e-2)
-
+
# Test BS-to-UE angles in the local coord system
- expected_loc = [(np.array([-86.57]),np.array([120.92])),
- (np.array([ 86.57]),np.array([ 90.00])),
- (np.array([-86.57]),np.array([ 90.00])),
- (np.array([ 86.57]),np.array([ 59.08]))]
- expected_beam = [(-86.57,30.92),
- ( 86.57, 0.00),
+ expected_loc = [(np.array([-86.57]), np.array([120.92])),
+ (np.array([86.57]), np.array([90.00])),
+ (np.array([-86.57]), np.array([90.00])),
+ (np.array([86.57]), np.array([59.08]))]
+ expected_beam = [(-86.57, 30.92),
+ (86.57, 0.00),
(-86.57, 0.00),
- ( 86.57,-30.92)]
+ (86.57, -30.92)]
for k in range(self.simulation.bs.num_stations):
-
- self.assertEqual(self.simulation.bs.antenna[k].azimuth,0.0)
- self.assertEqual(self.simulation.bs.antenna[k].elevation,-90.0)
-
- lo_angles = self.simulation.bs.antenna[k].to_local_coord(expected_azi[k,k],
- expected_ele[k,k])
- npt.assert_array_almost_equal(lo_angles,expected_loc[k],decimal=2)
+
+ self.assertEqual(self.simulation.bs.antenna[k].azimuth, 0.0)
+ self.assertEqual(self.simulation.bs.antenna[k].elevation, -90.0)
+
+ lo_angles = self.simulation.bs.antenna[k].to_local_coord(expected_azi[k, k],
+ expected_ele[k, k])
+ npt.assert_array_almost_equal(
+ lo_angles, expected_loc[k], decimal=2)
npt.assert_array_almost_equal(self.simulation.bs.antenna[k].beams_list[0],
- expected_beam[k],decimal=2)
-
+ expected_beam[k], decimal=2)
+
# Test angle to ES in the IMT coord system
- phi_es, theta_es = self.simulation.bs.get_pointing_vector_to(self.simulation.system)
- expected_phi_es = np.array([[18.44],[23.96],[33.69],[53.13]])
- npt.assert_array_almost_equal(phi_es,expected_phi_es,decimal=2)
- expected_theta_es = np.array([[86.83],[85.94],[84.46],[82.03]])
- npt.assert_array_almost_equal(theta_es,expected_theta_es,decimal=2)
-
+ phi_es, theta_es = self.simulation.bs.get_pointing_vector_to(
+ self.simulation.system)
+ expected_phi_es = np.array([[18.44], [23.96], [33.69], [53.13]])
+ npt.assert_array_almost_equal(phi_es, expected_phi_es, decimal=2)
+ expected_theta_es = np.array([[86.83], [85.94], [84.46], [82.03]])
+ npt.assert_array_almost_equal(theta_es, expected_theta_es, decimal=2)
+
# Test angle to ES in the local coord system
- expected_es_loc = [(np.array([99.92]),np.array([18.70])),
- (np.array([99.92]),np.array([24.28])),
- (np.array([99.92]),np.array([34.09])),
- (np.array([99.92]),np.array([53.54]))]
+ expected_es_loc = [(np.array([99.92]), np.array([18.70])),
+ (np.array([99.92]), np.array([24.28])),
+ (np.array([99.92]), np.array([34.09])),
+ (np.array([99.92]), np.array([53.54]))]
for k in range(self.simulation.bs.num_stations):
lo_angles = self.simulation.bs.antenna[k].to_local_coord(expected_phi_es[k],
expected_theta_es[k])
- npt.assert_array_almost_equal(lo_angles,expected_es_loc[k],decimal=2)
-
+ npt.assert_array_almost_equal(
+ lo_angles, expected_es_loc[k], decimal=2)
+
# Test gain to ES
calc_gain = self.simulation.calculate_gains(self.simulation.bs,
- self.simulation.system)
+ self.simulation.system)
for k in range(self.simulation.bs.num_stations):
beam = 0
exp_gain = self.simulation.bs.antenna[k]._beam_gain(expected_es_loc[k][0],
expected_es_loc[k][1],
beam)
- self.assertAlmostEqual(np.asscalar(calc_gain[k]),np.asscalar(exp_gain),places=1)
-
+ self.assertAlmostEqual(
+ np.ndarray.item(
+ calc_gain[k]),
+ np.ndarray.item(exp_gain),
+ places=1)
+
+
if __name__ == '__main__':
- unittest.main()
\ No newline at end of file
+ unittest.main()
diff --git a/tests/test_simulation_uplink.py b/tests/test_simulation_uplink.py
index 2a38a0861..0e6d3da2f 100644
--- a/tests/test_simulation_uplink.py
+++ b/tests/test_simulation_uplink.py
@@ -17,6 +17,7 @@
from sharc.propagation.propagation_factory import PropagationFactory
from sharc.support.enumerations import StationType
+
class SimulationUplinkTest(unittest.TestCase):
def setUp(self):
@@ -28,87 +29,87 @@ def setUp(self):
self.param.general.enable_adjacent_channel = False
self.param.general.overwrite_output = True
- self.param.imt.topology = "SINGLE_BS"
- self.param.imt.wrap_around = True
- self.param.imt.num_clusters = 2
- self.param.imt.intersite_distance = 150
+ self.param.imt.topology.type = "SINGLE_BS"
+ self.param.imt.topology.single_bs.num_clusters = 2
+ self.param.imt.topology.single_bs.intersite_distance = 150
+ self.param.imt.topology.single_bs.cell_radius = 100
self.param.imt.minimum_separation_distance_bs_ue = 10
self.param.imt.interfered_with = False
- self.param.imt.frequency = 10000
- self.param.imt.bandwidth = 100
+ self.param.imt.frequency = 10000.0
+ self.param.imt.bandwidth = 100.0
self.param.imt.rb_bandwidth = 0.180
self.param.imt.spectral_mask = "IMT-2020"
self.param.imt.spurious_emissions = -13
self.param.imt.guard_band_ratio = 0.1
self.param.imt.ho_margin = 3
- self.param.imt.bs_load_probability = 1
- self.param.imt.num_resource_blocks = 10
- self.param.imt.bs_conducted_power = 10
- self.param.imt.bs_height = 6
- self.param.imt.bs_acs = 30
- self.param.imt.bs_noise_figure = 7
- self.param.imt.bs_noise_temperature = 290
- self.param.imt.bs_ohmic_loss = 3
- self.param.imt.ul_attenuation_factor = 0.4
- self.param.imt.ul_sinr_min = -10
- self.param.imt.ul_sinr_max = 22
- self.param.imt.ue_k = 2
- self.param.imt.ue_k_m = 1
- self.param.imt.ue_indoor_percent = 0
- self.param.imt.ue_distribution_distance = "RAYLEIGH"
- self.param.imt.ue_distribution_azimuth = "UNIFORM"
- self.param.imt.ue_distribution_type = "ANGLE_AND_DISTANCE"
- self.param.imt.ue_tx_power_control = "OFF"
- self.param.imt.ue_p_o_pusch = -95
- self.param.imt.ue_alpha = 0.8
- self.param.imt.ue_p_cmax = 20
- self.param.imt.ue_conducted_power = 10
- self.param.imt.ue_height = 1.5
- self.param.imt.ue_aclr = 20
- self.param.imt.ue_acs = 25
- self.param.imt.ue_noise_figure = 9
- self.param.imt.ue_ohmic_loss = 3
- self.param.imt.ue_body_loss = 4
- self.param.imt.dl_attenuation_factor = 0.6
- self.param.imt.dl_sinr_min = -10
- self.param.imt.dl_sinr_max = 30
+ self.param.imt.bs.load_probability = 1
+
+ self.param.imt.bs.conducted_power = 10
+ self.param.imt.bs.height = 6
+ self.param.imt.bs.acs = 30
+ self.param.imt.bs.noise_figure = 7
+ self.param.imt.bs.ohmic_loss = 3
+ self.param.imt.uplink.attenuation_factor = 0.4
+ self.param.imt.uplink.sinr_min = -10
+ self.param.imt.uplink.sinr_max = 22
+ self.param.imt.ue.k = 2
+ self.param.imt.ue.k_m = 1
+ self.param.imt.ue.indoor_percent = 0
+ self.param.imt.ue.distribution_distance = "RAYLEIGH"
+ self.param.imt.ue.distribution_azimuth = "UNIFORM"
+ self.param.imt.ue.distribution_type = "ANGLE_AND_DISTANCE"
+ self.param.imt.ue.tx_power_control = "OFF"
+ self.param.imt.ue.p_o_pusch = -95
+ self.param.imt.ue.alpha = 0.8
+ self.param.imt.ue.p_cmax = 20
+ self.param.imt.ue.conducted_power = 10
+ self.param.imt.ue.height = 1.5
+ self.param.imt.ue.aclr = 20
+ self.param.imt.ue.acs = 25
+ self.param.imt.ue.noise_figure = 9
+ self.param.imt.ue.ohmic_loss = 3
+ self.param.imt.ue.body_loss = 4
+ self.param.imt.downlink.attenuation_factor = 0.6
+ self.param.imt.downlink.sinr_min = -10
+ self.param.imt.downlink.sinr_max = 30
self.param.imt.channel_model = "FSPL"
- self.param.imt.line_of_sight_prob = 0.75 # probability of line-of-sight (not for FSPL)
+ # probability of line-of-sight (not for FSPL)
+ self.param.imt.line_of_sight_prob = 0.75
self.param.imt.shadowing = False
self.param.imt.noise_temperature = 290
- self.param.imt.BOLTZMANN_CONSTANT = 1.38064852e-23
-
- self.param.antenna_imt.adjacent_antenna_model = "SINGLE_ELEMENT"
- self.param.antenna_imt.bs_normalization = False
- self.param.antenna_imt.bs_element_pattern = "M2101"
- self.param.antenna_imt.bs_minimum_array_gain = -200
- self.param.antenna_imt.bs_normalization_file = None
- self.param.antenna_imt.bs_element_max_g = 10
- self.param.antenna_imt.bs_element_phi_3db = 80
- self.param.antenna_imt.bs_element_theta_3db = 80
- self.param.antenna_imt.bs_element_am = 25
- self.param.antenna_imt.bs_element_sla_v = 25
- self.param.antenna_imt.bs_n_rows = 16
- self.param.antenna_imt.bs_n_columns = 16
- self.param.antenna_imt.bs_element_horiz_spacing = 1
- self.param.antenna_imt.bs_element_vert_spacing = 1
- self.param.antenna_imt.bs_multiplication_factor = 12
- self.param.antenna_imt.bs_downtilt = 10
-
- self.param.antenna_imt.ue_element_pattern = "M2101"
- self.param.antenna_imt.ue_normalization = False
- self.param.antenna_imt.ue_minimum_array_gain = -200
- self.param.antenna_imt.ue_normalization_file = None
- self.param.antenna_imt.ue_element_max_g = 5
- self.param.antenna_imt.ue_element_phi_3db = 65
- self.param.antenna_imt.ue_element_theta_3db = 65
- self.param.antenna_imt.ue_element_am = 30
- self.param.antenna_imt.ue_element_sla_v = 30
- self.param.antenna_imt.ue_n_rows = 2
- self.param.antenna_imt.ue_n_columns = 1
- self.param.antenna_imt.ue_element_horiz_spacing = 0.5
- self.param.antenna_imt.ue_element_vert_spacing = 0.5
- self.param.antenna_imt.ue_multiplication_factor = 12
+
+ self.param.imt.bs.antenna.adjacent_antenna_model = "SINGLE_ELEMENT"
+ self.param.imt.ue.antenna.adjacent_antenna_model = "SINGLE_ELEMENT"
+ self.param.imt.bs.antenna.normalization = False
+ self.param.imt.bs.antenna.element_pattern = "M2101"
+ self.param.imt.bs.antenna.minimum_array_gain = -200
+ self.param.imt.bs.antenna.normalization_file = None
+ self.param.imt.bs.antenna.element_max_g = 10
+ self.param.imt.bs.antenna.element_phi_3db = 80
+ self.param.imt.bs.antenna.element_theta_3db = 80
+ self.param.imt.bs.antenna.element_am = 25
+ self.param.imt.bs.antenna.element_sla_v = 25
+ self.param.imt.bs.antenna.n_rows = 16
+ self.param.imt.bs.antenna.n_columns = 16
+ self.param.imt.bs.antenna.element_horiz_spacing = 1
+ self.param.imt.bs.antenna.element_vert_spacing = 1
+ self.param.imt.bs.antenna.multiplication_factor = 12
+ self.param.imt.bs.antenna.downtilt = 10
+
+ self.param.imt.ue.antenna.element_pattern = "M2101"
+ self.param.imt.ue.antenna.normalization = False
+ self.param.imt.ue.antenna.minimum_array_gain = -200
+ self.param.imt.ue.antenna.normalization_file = None
+ self.param.imt.ue.antenna.element_max_g = 5
+ self.param.imt.ue.antenna.element_phi_3db = 65
+ self.param.imt.ue.antenna.element_theta_3db = 65
+ self.param.imt.ue.antenna.element_am = 30
+ self.param.imt.ue.antenna.element_sla_v = 30
+ self.param.imt.ue.antenna.n_rows = 2
+ self.param.imt.ue.antenna.n_columns = 1
+ self.param.imt.ue.antenna.element_horiz_spacing = 0.5
+ self.param.imt.ue.antenna.element_vert_spacing = 0.5
+ self.param.imt.ue.antenna.multiplication_factor = 12
self.param.fss_ss.frequency = 10000
self.param.fss_ss.bandwidth = 100
@@ -122,7 +123,7 @@ def setUp(self):
self.param.fss_ss.antenna_pattern = "OMNI"
self.param.fss_ss.imt_altitude = 1000
self.param.fss_ss.imt_lat_deg = -23.5629739
- self.param.fss_ss.imt_long_diff_deg = (-46.6555132-75)
+ self.param.fss_ss.imt_long_diff_deg = (-46.6555132 - 75)
self.param.fss_ss.channel_model = "FSPL"
self.param.fss_ss.line_of_sight_prob = 0.01
self.param.fss_ss.surf_water_vapour_density = 7.5
@@ -130,8 +131,6 @@ def setUp(self):
self.param.fss_ss.time_ratio = 0.5
self.param.fss_ss.antenna_l_s = -20
self.param.fss_ss.acs = 0
- self.param.fss_ss.BOLTZMANN_CONSTANT = 1.38064852e-23
- self.param.fss_ss.EARTH_RADIUS = 6371000
self.param.fss_es.x = -5000
self.param.fss_es.y = 0
@@ -149,30 +148,29 @@ def setUp(self):
self.param.fss_es.channel_model = "FSPL"
self.param.fss_es.line_of_sight_prob = 1
self.param.fss_es.acs = 0
- self.param.fss_es.BOLTZMANN_CONSTANT = 1.38064852e-23
- self.param.fss_es.EARTH_RADIUS = 6371000
- self.param.ras.x = -5000
- self.param.ras.y = 0
+ self.param.ras.geometry.location.type = "FIXED"
+ self.param.ras.geometry.location.fixed.x = -5000
+ self.param.ras.geometry.location.fixed.y = 0
self.param.ras.height = 10
- self.param.ras.elevation = 20
- self.param.ras.azimuth = 0
- self.param.ras.frequency = 10000
+ self.param.ras.geometry.elevation.fixed = 20
+ self.param.ras.geometry.azimuth.fixed = 0
+ self.param.ras.geometry.elevation.type = "FIXED"
+ self.param.ras.geometry.azimuth.type = "FIXED"
+ self.param.ras.frequency = 1000
self.param.ras.bandwidth = 100
- self.param.ras.antenna_noise_temperature = 50
- self.param.ras.receiver_noise_temperature = 50
- self.param.ras.antenna_gain = 50
+ self.param.ras.noise_temperature = 100
+ self.param.ras.antenna.gain = 50
self.param.ras.antenna_efficiency = 0.7
- self.param.ras.diameter = 10
- self.param.ras.acs = 0
- self.param.ras.antenna_pattern = "OMNI"
+ self.param.ras.adjacent_ch_selectivity = 0
+ self.param.ras.tx_power_density = -500
+ self.param.ras.antenna.pattern = "OMNI"
self.param.ras.channel_model = "FSPL"
self.param.ras.line_of_sight_prob = 1
self.param.ras.BOLTZMANN_CONSTANT = 1.38064852e-23
self.param.ras.EARTH_RADIUS = 6371000
self.param.ras.SPEED_OF_LIGHT = 299792458
-
def test_simulation_2bs_4ue_ss(self):
self.param.general.system = "FSS_SS"
@@ -187,61 +185,66 @@ def test_simulation_2bs_4ue_ss(self):
self.assertTrue(self.simulation.co_channel)
self.simulation.bs = StationFactory.generate_imt_base_stations(self.param.imt,
- self.param.antenna_imt,
+ self.param.imt.bs.antenna,
self.simulation.topology,
random_number_gen)
self.simulation.bs.antenna = np.array([AntennaOmni(1), AntennaOmni(2)])
self.simulation.bs.active = np.ones(2, dtype=bool)
self.simulation.ue = StationFactory.generate_imt_ue(self.param.imt,
- self.param.antenna_imt,
+ self.param.imt.ue.antenna,
self.simulation.topology,
random_number_gen)
self.simulation.ue.x = np.array([20, 70, 110, 170])
- self.simulation.ue.y = np.array([ 0, 0, 0, 0])
- self.simulation.ue.antenna = np.array([AntennaOmni(10), AntennaOmni(11), AntennaOmni(22), AntennaOmni(23)])
+ self.simulation.ue.y = np.array([0, 0, 0, 0])
+ self.simulation.ue.antenna = np.array(
+ [AntennaOmni(10), AntennaOmni(11), AntennaOmni(22), AntennaOmni(23)])
self.simulation.ue.active = np.ones(4, dtype=bool)
# test connection method
self.simulation.connect_ue_to_bs()
- self.assertEqual(self.simulation.link, {0: [0,1], 1: [2,3]})
+ self.assertEqual(self.simulation.link, {0: [0, 1], 1: [2, 3]})
self.simulation.select_ue(random_number_gen)
- self.simulation.link = {0:[0,1],1:[2,3]}
+ self.simulation.link = {0: [0, 1], 1: [2, 3]}
# We do not test the selection method here because in this specific
# scenario we do not want to change the order of the UE's
self.simulation.propagation_imt = PropagationFactory.create_propagation(self.param.imt.channel_model,
- self.param, random_number_gen)
+ self.param,
+ self.simulation.param_system,
+ random_number_gen)
self.simulation.propagation_system = PropagationFactory.create_propagation(self.param.fss_ss.channel_model,
- self.param, random_number_gen)
+ self.param,
+ self.simulation.param_system,
+ random_number_gen)
# test coupling loss method
- self.simulation.coupling_loss_imt = self.simulation.calculate_coupling_loss(self.simulation.bs,
- self.simulation.ue,
- self.simulation.propagation_imt)
- coupling_loss_imt = np.array([[88.47-1-10, 99.35-1-11, 103.27-1-22, 107.05-1-23],
- [107.55-2-10, 104.72-2-11, 101.53-2-22, 91.99-2-23]])
+ self.simulation.coupling_loss_imt = self.simulation.calculate_intra_imt_coupling_loss(self.simulation.ue,
+ self.simulation.bs)
+ coupling_loss_imt = np.array([[88.68 - 1 - 10, 99.36 - 1 - 11, 103.28 - 1 - 22, 107.06 - 1 - 23],
+ [107.55 - 2 - 10, 104.73 - 2 - 11, 101.54 - 2 - 22, 92.08 - 2 - 23]])
npt.assert_allclose(self.simulation.coupling_loss_imt,
coupling_loss_imt,
atol=1e-2)
# test scheduler and bandwidth allocation
self.simulation.scheduler()
- bandwidth_per_ue = math.trunc((1 - 0.1)*100/2)
- npt.assert_allclose(self.simulation.ue.bandwidth, bandwidth_per_ue*np.ones(4), atol=1e-2)
+ bandwidth_per_ue = math.trunc((1 - 0.1) * 100 / 2)
+ npt.assert_allclose(self.simulation.ue.bandwidth,
+ bandwidth_per_ue * np.ones(4), atol=1e-2)
# there is no power control, so UE's will transmit at maximum power
self.simulation.power_control()
tx_power = 20
- npt.assert_allclose(self.simulation.ue.tx_power, tx_power*np.ones(4))
+ npt.assert_allclose(self.simulation.ue.tx_power, tx_power * np.ones(4))
# test method that calculates SINR
self.simulation.calculate_sinr()
# check BS received power
- rx_power = { 0: np.array([tx_power, tx_power] - coupling_loss_imt[0,0:2]),
- 1: np.array([tx_power, tx_power] - coupling_loss_imt[1,2:4])}
+ rx_power = {0: np.array([tx_power, tx_power] - coupling_loss_imt[0, 0:2]),
+ 1: np.array([tx_power, tx_power] - coupling_loss_imt[1, 2:4])}
npt.assert_allclose(self.simulation.bs.rx_power[0],
rx_power[0],
atol=1e-2)
@@ -250,8 +253,8 @@ def test_simulation_2bs_4ue_ss(self):
atol=1e-2)
# check BS received interference
- rx_interference = { 0: np.array([tx_power, tx_power] - coupling_loss_imt[0,2:4]),
- 1: np.array([tx_power, tx_power] - coupling_loss_imt[1,0:2])}
+ rx_interference = {0: np.array([tx_power, tx_power] - coupling_loss_imt[0, 2:4]),
+ 1: np.array([tx_power, tx_power] - coupling_loss_imt[1, 0:2])}
npt.assert_allclose(self.simulation.bs.rx_interference[0],
rx_interference[0],
@@ -261,14 +264,15 @@ def test_simulation_2bs_4ue_ss(self):
atol=1e-2)
# check BS thermal noise
- thermal_noise = 10*np.log10(1.38064852e-23*290*bandwidth_per_ue*1e3*1e6) + 7
+ thermal_noise = 10 * \
+ np.log10(1.38064852e-23 * 290 * bandwidth_per_ue * 1e3 * 1e6) + 7
npt.assert_allclose(self.simulation.bs.thermal_noise,
thermal_noise,
atol=1e-2)
# check BS thermal noise + interference
- total_interference = { 0: 10*np.log10(np.power(10, 0.1*rx_interference[0]) + np.power(10, 0.1*thermal_noise)),
- 1: 10*np.log10(np.power(10, 0.1*rx_interference[1]) + np.power(10, 0.1*thermal_noise))}
+ total_interference = {0: 10 * np.log10(np.power(10, 0.1 * rx_interference[0]) + np.power(10, 0.1 * thermal_noise)),
+ 1: 10 * np.log10(np.power(10, 0.1 * rx_interference[1]) + np.power(10, 0.1 * thermal_noise))}
npt.assert_allclose(self.simulation.bs.total_interference[0],
total_interference[0],
atol=1e-2)
@@ -292,28 +296,32 @@ def test_simulation_2bs_4ue_ss(self):
rx_power[1] - total_interference[1],
atol=1e-2)
- self.simulation.system = StationFactory.generate_fss_space_station(self.param.fss_ss)
+ self.simulation.system = StationFactory.generate_fss_space_station(
+ self.param.fss_ss)
self.simulation.system.x = np.array([0])
self.simulation.system.y = np.array([0])
self.simulation.system.height = np.array([self.param.fss_ss.altitude])
- # test the method that calculates interference from IMT UE to FSS space station
+ # test the method that calculates interference from IMT UE to FSS space
+ # station
self.simulation.calculate_external_interference()
# check coupling loss
- coupling_loss_imt_system = np.array([213.52-51-10, 213.52-51-11, 213.52-51-22, 213.52-51-23])
+ coupling_loss_imt_system = np.array(
+ [213.52 - 51 - 10, 213.52 - 51 - 11, 213.52 - 51 - 22, 213.52 - 51 - 23])
npt.assert_allclose(self.simulation.coupling_loss_imt_system,
coupling_loss_imt_system,
atol=1e-2)
# check interference generated by UE to FSS space station
interference_ue = tx_power - coupling_loss_imt_system
- rx_interference = 10*math.log10(np.sum(np.power(10, 0.1*interference_ue)))
+ rx_interference = 10 * \
+ math.log10(np.sum(np.power(10, 0.1 * interference_ue)))
self.assertAlmostEqual(self.simulation.system.rx_interference,
rx_interference,
delta=.01)
# check FSS space station thermal noise
- thermal_noise = 10*np.log10(1.38064852e-23*950*100*1e3*1e6)
+ thermal_noise = 10 * np.log10(1.38064852e-23 * 950 * 100 * 1e3 * 1e6)
self.assertAlmostEqual(self.simulation.system.thermal_noise,
thermal_noise,
delta=.01)
@@ -323,7 +331,6 @@ def test_simulation_2bs_4ue_ss(self):
rx_interference - thermal_noise,
delta=.01)
-
def test_simulation_2bs_4ue_es(self):
self.param.general.system = "FSS_ES"
@@ -336,39 +343,42 @@ def test_simulation_2bs_4ue_es(self):
random_number_gen = np.random.RandomState()
self.simulation.bs = StationFactory.generate_imt_base_stations(self.param.imt,
- self.param.antenna_imt,
+ self.param.imt.bs.antenna,
self.simulation.topology,
random_number_gen)
self.simulation.bs.antenna = np.array([AntennaOmni(1), AntennaOmni(2)])
self.simulation.bs.active = np.ones(2, dtype=bool)
self.simulation.ue = StationFactory.generate_imt_ue(self.param.imt,
- self.param.antenna_imt,
+ self.param.imt.ue.antenna,
self.simulation.topology,
random_number_gen)
self.simulation.ue.x = np.array([20, 70, 110, 170])
- self.simulation.ue.y = np.array([ 0, 0, 0, 0])
- self.simulation.ue.antenna = np.array([AntennaOmni(10), AntennaOmni(11), AntennaOmni(22), AntennaOmni(23)])
+ self.simulation.ue.y = np.array([0, 0, 0, 0])
+ self.simulation.ue.antenna = np.array(
+ [AntennaOmni(10), AntennaOmni(11), AntennaOmni(22), AntennaOmni(23)])
self.simulation.ue.active = np.ones(4, dtype=bool)
self.simulation.connect_ue_to_bs()
self.simulation.select_ue(random_number_gen)
- self.simulation.link = {0:[0,1],1:[2,3]}
+ self.simulation.link = {0: [0, 1], 1: [2, 3]}
# We do not test the selection method here because in this specific
# scenario we do not want to change the order of the UE's
self.simulation.propagation_imt = PropagationFactory.create_propagation(self.param.imt.channel_model,
- self.param, random_number_gen)
+ self.param, self.simulation.param_system,
+ random_number_gen)
self.simulation.propagation_system = PropagationFactory.create_propagation(self.param.fss_ss.channel_model,
- self.param, random_number_gen)
+ self.param,
+ self.simulation.param_system,
+ random_number_gen)
# test coupling loss method
- self.simulation.coupling_loss_imt = self.simulation.calculate_coupling_loss(self.simulation.bs,
- self.simulation.ue,
- self.simulation.propagation_imt)
+ self.simulation.coupling_loss_imt = self.simulation.calculate_intra_imt_coupling_loss(self.simulation.ue,
+ self.simulation.bs)
self.simulation.scheduler()
- bandwidth_per_ue = math.trunc((1 - 0.1)*100/2)
+ bandwidth_per_ue = math.trunc((1 - 0.1) * 100 / 2)
self.simulation.power_control()
self.simulation.calculate_sinr()
@@ -376,15 +386,15 @@ def test_simulation_2bs_4ue_es(self):
tx_power = 20
# check coupling loss IMT
- coupling_loss_imt = np.array([[88.47-1-10, 99.35-1-11, 103.27-1-22, 107.05-1-23],
- [107.55-2-10, 104.72-2-11, 101.53-2-22, 91.99-2-23]])
+ coupling_loss_imt = np.array([[88.68 - 1 - 10, 99.36 - 1 - 11, 103.28 - 1 - 22, 107.06 - 1 - 23],
+ [107.55 - 2 - 10, 104.73 - 2 - 11, 101.54 - 2 - 22, 92.08 - 2 - 23]])
npt.assert_allclose(self.simulation.coupling_loss_imt,
coupling_loss_imt,
atol=1e-2)
# check BS received power
- rx_power = { 0: np.array([tx_power, tx_power] - coupling_loss_imt[0,0:2]),
- 1: np.array([tx_power, tx_power] - coupling_loss_imt[1,2:4])}
+ rx_power = {0: np.array([tx_power, tx_power] - coupling_loss_imt[0, 0:2]),
+ 1: np.array([tx_power, tx_power] - coupling_loss_imt[1, 2:4])}
npt.assert_allclose(self.simulation.bs.rx_power[0],
rx_power[0],
atol=1e-2)
@@ -393,8 +403,8 @@ def test_simulation_2bs_4ue_es(self):
atol=1e-2)
# check BS received interference
- rx_interference = { 0: np.array([tx_power, tx_power] - coupling_loss_imt[0,2:4]),
- 1: np.array([tx_power, tx_power] - coupling_loss_imt[1,0:2])}
+ rx_interference = {0: np.array([tx_power, tx_power] - coupling_loss_imt[0, 2:4]),
+ 1: np.array([tx_power, tx_power] - coupling_loss_imt[1, 0:2])}
npt.assert_allclose(self.simulation.bs.rx_interference[0],
rx_interference[0],
@@ -404,14 +414,15 @@ def test_simulation_2bs_4ue_es(self):
atol=1e-2)
# check BS thermal noise
- thermal_noise = 10*np.log10(1.38064852e-23*290*bandwidth_per_ue*1e3*1e6) + 7
+ thermal_noise = 10 * \
+ np.log10(1.38064852e-23 * 290 * bandwidth_per_ue * 1e3 * 1e6) + 7
npt.assert_allclose(self.simulation.bs.thermal_noise,
thermal_noise,
atol=1e-2)
# check BS thermal noise + interference
- total_interference = { 0: 10*np.log10(np.power(10, 0.1*rx_interference[0]) + np.power(10, 0.1*thermal_noise)),
- 1: 10*np.log10(np.power(10, 0.1*rx_interference[1]) + np.power(10, 0.1*thermal_noise))}
+ total_interference = {0: 10 * np.log10(np.power(10, 0.1 * rx_interference[0]) + np.power(10, 0.1 * thermal_noise)),
+ 1: 10 * np.log10(np.power(10, 0.1 * rx_interference[1]) + np.power(10, 0.1 * thermal_noise))}
npt.assert_allclose(self.simulation.bs.total_interference[0],
total_interference[0],
atol=1e-2)
@@ -435,7 +446,8 @@ def test_simulation_2bs_4ue_es(self):
rx_power[1] - total_interference[1],
atol=1e-2)
- self.simulation.system = StationFactory.generate_fss_earth_station(self.param.fss_es, random_number_gen)
+ self.simulation.system = StationFactory.generate_fss_earth_station(
+ self.param.fss_es, random_number_gen)
self.simulation.system.x = np.array([-2000])
self.simulation.system.y = np.array([0])
self.simulation.system.height = np.array([self.param.fss_es.height])
@@ -444,15 +456,16 @@ def test_simulation_2bs_4ue_es(self):
self.simulation.calculate_sinr_ext()
# coupling loss FSS_ES <-> IMT BS
- coupling_loss_imt_system = np.array([124.47-50-1, 124.47-50-1, 125.29-50-2, 125.29-50-2])
+ coupling_loss_imt_system = np.array(
+ [124.47 - 50 - 1, 124.47 - 50 - 1, 125.29 - 50 - 2, 125.29 - 50 - 2])
npt.assert_allclose(self.simulation.coupling_loss_imt_system,
coupling_loss_imt_system,
atol=1e-2)
# external interference
- system_tx_power = -60 + 10*math.log10(bandwidth_per_ue*1e6) + 30
- ext_interference = { 0: system_tx_power - coupling_loss_imt_system[0:2],
- 1: system_tx_power - coupling_loss_imt_system[2:4]}
+ system_tx_power = -60 + 10 * math.log10(bandwidth_per_ue * 1e6) + 30
+ ext_interference = {0: system_tx_power - coupling_loss_imt_system[0:2],
+ 1: system_tx_power - coupling_loss_imt_system[2:4]}
npt.assert_allclose(self.simulation.bs.ext_interference[0],
ext_interference[0],
atol=1e-2)
@@ -461,10 +474,10 @@ def test_simulation_2bs_4ue_es(self):
atol=1e-2)
# SINR with external interference
- interference = { 0: 10*np.log10(np.power(10, 0.1*total_interference[0]) \
- + np.power(10, 0.1*ext_interference[0])),
- 1: 10*np.log10(np.power(10, 0.1*total_interference[1]) \
- + np.power(10, 0.1*ext_interference[1]))}
+ interference = {0: 10 * np.log10(np.power(10, 0.1 * total_interference[0]) +
+ np.power(10, 0.1 * ext_interference[0])),
+ 1: 10 * np.log10(np.power(10, 0.1 * total_interference[1]) +
+ np.power(10, 0.1 * ext_interference[1]))}
npt.assert_allclose(self.simulation.bs.sinr_ext[0],
rx_power[0] - interference[0],
@@ -485,27 +498,29 @@ def test_simulation_2bs_4ue_es(self):
self.simulation.calculate_external_interference()
# coupling loss
- coupling_loss_imt_system = np.array([128.55-50-10, 128.76-50-11, 128.93-50-22, 129.17-50-23])
+ coupling_loss_imt_system = np.array(
+ [128.55 - 50 - 10, 128.76 - 50 - 11, 128.93 - 50 - 22, 129.17 - 50 - 23])
npt.assert_allclose(self.simulation.coupling_loss_imt_system,
coupling_loss_imt_system,
atol=1e-2)
# interference
interference = tx_power - coupling_loss_imt_system
- rx_interference = 10*math.log10(np.sum(np.power(10, 0.1*interference)))
+ rx_interference = 10 * \
+ math.log10(np.sum(np.power(10, 0.1 * interference)))
self.assertAlmostEqual(self.simulation.system.rx_interference,
rx_interference,
delta=.01)
# check FSS Earth station thermal noise
- thermal_noise = 10*np.log10(1.38064852e-23*100*1e3*100*1e6)
+ thermal_noise = 10 * np.log10(1.38064852e-23 * 100 * 1e3 * 100 * 1e6)
self.assertAlmostEqual(self.simulation.system.thermal_noise,
thermal_noise,
delta=.01)
# check INR at FSS Earth station
self.assertAlmostEqual(self.simulation.system.inr,
- np.array([ rx_interference - thermal_noise ]),
+ np.array([rx_interference - thermal_noise]),
delta=.01)
def test_simulation_2bs_4ue_ras(self):
@@ -520,92 +535,105 @@ def test_simulation_2bs_4ue_ras(self):
random_number_gen = np.random.RandomState()
self.simulation.bs = StationFactory.generate_imt_base_stations(self.param.imt,
- self.param.antenna_imt,
+ self.param.imt.bs.antenna,
self.simulation.topology,
random_number_gen)
self.simulation.bs.antenna = np.array([AntennaOmni(1), AntennaOmni(2)])
self.simulation.bs.active = np.ones(2, dtype=bool)
self.simulation.ue = StationFactory.generate_imt_ue(self.param.imt,
- self.param.antenna_imt,
+ self.param.imt.ue.antenna,
self.simulation.topology,
random_number_gen)
self.simulation.ue.x = np.array([20, 70, 110, 170])
- self.simulation.ue.y = np.array([ 0, 0, 0, 0])
- self.simulation.ue.antenna = np.array([AntennaOmni(10), AntennaOmni(11), AntennaOmni(22), AntennaOmni(23)])
+ self.simulation.ue.y = np.array([0, 0, 0, 0])
+ self.simulation.ue.antenna = np.array(
+ [AntennaOmni(10), AntennaOmni(11), AntennaOmni(22), AntennaOmni(23)])
self.simulation.ue.active = np.ones(4, dtype=bool)
self.simulation.connect_ue_to_bs()
self.simulation.select_ue(random_number_gen)
- self.simulation.link = {0:[0,1],1:[2,3]}
+ self.simulation.link = {0: [0, 1], 1: [2, 3]}
self.simulation.propagation_imt = PropagationFactory.create_propagation(self.param.imt.channel_model,
- self.param, random_number_gen)
+ self.param,
+ self.simulation.param_system,
+ random_number_gen)
+
self.simulation.propagation_system = PropagationFactory.create_propagation(self.param.fss_ss.channel_model,
- self.param, random_number_gen)
+ self.param,
+ self.simulation.param_system,
+ random_number_gen)
# test coupling loss method
- self.simulation.coupling_loss_imt = self.simulation.calculate_coupling_loss(self.simulation.bs,
- self.simulation.ue,
- self.simulation.propagation_imt)
+ self.simulation.coupling_loss_imt = self.simulation.calculate_intra_imt_coupling_loss(self.simulation.ue,
+ self.simulation.bs)
self.simulation.scheduler()
- bandwidth_per_ue = math.trunc((1 - 0.1)*100/2)
+ bandwidth_per_ue = math.trunc((1 - 0.1) * 100 / 2)
self.simulation.power_control()
self.simulation.calculate_sinr()
# check BS thermal noise
- thermal_noise = 10*np.log10(1.38064852e-23*290*bandwidth_per_ue*1e3*1e6) + 7
+ thermal_noise = 10 * \
+ np.log10(1.38064852e-23 * 290 * bandwidth_per_ue * 1e3 * 1e6) + 7
npt.assert_allclose(self.simulation.bs.thermal_noise,
thermal_noise,
atol=1e-2)
# check SINR
npt.assert_allclose(self.simulation.bs.sinr[0],
- np.array([-57.47 - (-60.27), -67.35 - (-63.05)]),
+ np.array([-57.47 - (-60.06), -67.35 - (-63.04)]),
atol=1e-2)
npt.assert_allclose(self.simulation.bs.sinr[1],
- np.array([-57.53 - (-75.41), -46.99 - (-71.67)]),
+ np.array([-57.53 - (-75.40), -46.99 - (-71.57)]),
atol=1e-2)
# Create system
- self.simulation.system = StationFactory.generate_ras_station(self.param.ras)
+ self.simulation.system = StationFactory.generate_ras_station(
+ self.param.ras, random_number_gen, None
+ )
self.simulation.system.x = np.array([-2000])
self.simulation.system.y = np.array([0])
self.simulation.system.height = np.array([self.param.ras.height])
self.simulation.system.antenna[0].effective_area = 54.9779
# Test gain calculation
- gains = self.simulation.calculate_gains(self.simulation.system,self.simulation.ue)
- npt.assert_equal(gains,np.array([[50, 50, 50, 50]]))
+ gains = self.simulation.calculate_gains(
+ self.simulation.system, self.simulation.ue)
+ npt.assert_equal(gains, np.array([[50, 50, 50, 50]]))
# Test external interference
self.simulation.calculate_external_interference()
npt.assert_allclose(self.simulation.coupling_loss_imt_system,
- np.array([125.55-50-10, 125.76-50-11, 125.93-50-22, 126.17-50-23]),
+ np.array([125.55 - 50 - 10, 125.76 - 50 - 11,
+ 125.93 - 50 - 22, 126.17 - 50 - 23]),
atol=1e-2)
# Test RAS PFD
- interference = 20 - np.array([125.55-50-10, 125.76-50-11, 125.93-50-22, 126.17-50-23])
- rx_interference = 10*math.log10(np.sum(np.power(10, 0.1*interference)))
+ interference = 20 - \
+ np.array([125.55 - 50 - 10, 125.76 - 50 - 11,
+ 125.93 - 50 - 22, 126.17 - 50 - 23])
+ rx_interference = 10 * \
+ math.log10(np.sum(np.power(10, 0.1 * interference)))
self.assertAlmostEqual(self.simulation.system.rx_interference,
rx_interference,
delta=.01)
# Test RAS PFD
- pfd = 10*np.log10(10**(rx_interference/10)/54.9779)
+ pfd = 10 * np.log10(10**(rx_interference / 10) / 54.9779)
self.assertAlmostEqual(self.simulation.system.pfd,
- pfd,
- delta=.01)
+ pfd,
+ delta=.01)
# check RAS station thermal noise
- thermal_noise = 10*np.log10(1.38064852e-23*100*1e3*100*1e6)
+ thermal_noise = 10 * np.log10(1.38064852e-23 * 100 * 1e3 * 100 * 1e6)
self.assertAlmostEqual(self.simulation.system.thermal_noise,
thermal_noise,
delta=.01)
# check INR at RAS station
self.assertAlmostEqual(self.simulation.system.inr,
- np.array([ rx_interference - (-98.599) ]),
+ np.array([rx_interference - (-98.599)]),
delta=.01)
def test_beamforming_gains(self):
@@ -619,50 +647,51 @@ def test_beamforming_gains(self):
# Set scenario
self.simulation.bs = StationFactory.generate_imt_base_stations(self.param.imt,
- self.param.antenna_imt,
+ self.param.imt.bs.antenna,
self.simulation.topology,
random_number_gen)
self.simulation.ue = StationFactory.generate_imt_ue(self.param.imt,
- self.param.antenna_imt,
+ self.param.imt.ue.antenna,
self.simulation.topology,
random_number_gen)
self.simulation.ue.x = np.array([50.000, 43.301, 150.000, 175.000])
- self.simulation.ue.y = np.array([ 0.000, 25.000, 0.000, 43.301])
+ self.simulation.ue.y = np.array([0.000, 25.000, 0.000, 43.301])
# Physical pointing angles
- self.assertEqual(self.simulation.bs.antenna[0].azimuth,0)
- self.assertEqual(self.simulation.bs.antenna[0].elevation,-10)
- self.assertEqual(self.simulation.bs.antenna[1].azimuth,180)
- self.assertEqual(self.simulation.bs.antenna[0].elevation,-10)
+ self.assertEqual(self.simulation.bs.antenna[0].azimuth, 0)
+ self.assertEqual(self.simulation.bs.antenna[0].elevation, -10)
+ self.assertEqual(self.simulation.bs.antenna[1].azimuth, 180)
+ self.assertEqual(self.simulation.bs.antenna[0].elevation, -10)
# Change UE pointing
self.simulation.ue.azimuth = np.array([180, -90, 90, -90])
self.simulation.ue.elevation = np.array([-30, -15, 15, 30])
- par = self.param.antenna_imt.get_antenna_parameters(StationType.IMT_UE)
+ par = self.param.imt.ue.antenna.get_antenna_parameters()
for i in range(self.simulation.ue.num_stations):
self.simulation.ue.antenna[i] = AntennaBeamformingImt(par, self.simulation.ue.azimuth[i],
self.simulation.ue.elevation[i])
- self.assertEqual(self.simulation.ue.antenna[0].azimuth,180)
- self.assertEqual(self.simulation.ue.antenna[0].elevation,-30)
- self.assertEqual(self.simulation.ue.antenna[1].azimuth,-90)
- self.assertEqual(self.simulation.ue.antenna[1].elevation,-15)
- self.assertEqual(self.simulation.ue.antenna[2].azimuth,90)
- self.assertEqual(self.simulation.ue.antenna[2].elevation,15)
- self.assertEqual(self.simulation.ue.antenna[3].azimuth,-90)
- self.assertEqual(self.simulation.ue.antenna[3].elevation,30)
+ self.assertEqual(self.simulation.ue.antenna[0].azimuth, 180)
+ self.assertEqual(self.simulation.ue.antenna[0].elevation, -30)
+ self.assertEqual(self.simulation.ue.antenna[1].azimuth, -90)
+ self.assertEqual(self.simulation.ue.antenna[1].elevation, -15)
+ self.assertEqual(self.simulation.ue.antenna[2].azimuth, 90)
+ self.assertEqual(self.simulation.ue.antenna[2].elevation, 15)
+ self.assertEqual(self.simulation.ue.antenna[3].azimuth, -90)
+ self.assertEqual(self.simulation.ue.antenna[3].elevation, 30)
# Simulate connection and selection
self.simulation.connect_ue_to_bs()
- self.assertEqual(self.simulation.link,{0:[0,1],1:[2,3]})
+ self.assertEqual(self.simulation.link, {0: [0, 1], 1: [2, 3]})
# Test BS gains
# Test pointing vector
- phi, theta = self.simulation.bs.get_pointing_vector_to(self.simulation.ue)
- npt.assert_allclose(phi,np.array([[0.0, 30.0, 0.0, 13.898],
- [180.0, 170.935, 180.0, 120.0 ]]),atol=eps)
- npt.assert_allclose(theta,np.array([[95.143, 95.143, 91.718, 91.430],
- [91.718, 91.624, 95.143, 95.143]]),atol=eps)
+ phi, theta = self.simulation.bs.get_pointing_vector_to(
+ self.simulation.ue)
+ npt.assert_allclose(phi, np.array([[0.0, 30.0, 0.0, 13.898],
+ [180.0, 170.935, 180.0, 120.0]]), atol=eps)
+ npt.assert_allclose(theta, np.array([[95.143, 95.143, 91.718, 91.430],
+ [91.718, 91.624, 95.143, 95.143]]), atol=eps)
self.simulation.bs_to_ue_phi = phi
self.simulation.bs_to_ue_theta = theta
@@ -670,47 +699,53 @@ def test_beamforming_gains(self):
# method shufles the link dictionary, the order of the beams cannot be
# predicted. Thus, the beams need to be added outside of the function
self.simulation.ue.active = np.ones(4, dtype=bool)
- self.simulation.bs.antenna[0].add_beam(phi[0,0],theta[0,0])
- self.simulation.bs.antenna[0].add_beam(phi[0,1],theta[0,1])
- self.simulation.bs.antenna[1].add_beam(phi[1,2],theta[1,2])
- self.simulation.bs.antenna[1].add_beam(phi[1,3],theta[1,3])
- self.simulation.ue.antenna[0].add_beam(phi[0,0]-180,180-theta[0,0])
- self.simulation.ue.antenna[1].add_beam(phi[0,1]-180,180-theta[0,1])
- self.simulation.ue.antenna[2].add_beam(phi[1,2]-180,180-theta[1,2])
- self.simulation.ue.antenna[3].add_beam(phi[1,3]-180,180-theta[1,3])
- self.simulation.bs_to_ue_beam_rbs = np.array([0, 1, 0, 1],dtype=int)
+ self.simulation.bs.antenna[0].add_beam(phi[0, 0], theta[0, 0])
+ self.simulation.bs.antenna[0].add_beam(phi[0, 1], theta[0, 1])
+ self.simulation.bs.antenna[1].add_beam(phi[1, 2], theta[1, 2])
+ self.simulation.bs.antenna[1].add_beam(phi[1, 3], theta[1, 3])
+ self.simulation.ue.antenna[0].add_beam(
+ phi[0, 0] - 180, 180 - theta[0, 0])
+ self.simulation.ue.antenna[1].add_beam(
+ phi[0, 1] - 180, 180 - theta[0, 1])
+ self.simulation.ue.antenna[2].add_beam(
+ phi[1, 2] - 180, 180 - theta[1, 2])
+ self.simulation.ue.antenna[3].add_beam(
+ phi[1, 3] - 180, 180 - theta[1, 3])
+ self.simulation.bs_to_ue_beam_rbs = np.array([0, 1, 0, 1], dtype=int)
# Test beams pointing
npt.assert_allclose(self.simulation.bs.antenna[0].beams_list[0],
- (0.0,-4.857),atol=eps)
+ (0.0, -4.857), atol=eps)
npt.assert_allclose(self.simulation.bs.antenna[0].beams_list[1],
- (29.92,-3.53),atol=eps)
+ (29.92, -3.53), atol=eps)
npt.assert_allclose(self.simulation.bs.antenna[1].beams_list[0],
- (0.0,-4.857),atol=eps)
+ (0.0, -4.857), atol=eps)
npt.assert_allclose(self.simulation.bs.antenna[1].beams_list[1],
- (-59.60,0.10),atol=eps)
+ (-59.60, 0.10), atol=eps)
npt.assert_allclose(self.simulation.ue.antenna[0].beams_list[0],
- (0.0,-35.143),atol=eps)
+ (0.0, -35.143), atol=eps)
npt.assert_allclose(self.simulation.ue.antenna[1].beams_list[0],
- (-62.04,-12.44),atol=eps)
+ (-62.04, -12.44), atol=eps)
npt.assert_allclose(self.simulation.ue.antenna[2].beams_list[0],
- (-88.66,-4.96),atol=eps)
+ (-88.66, -4.96), atol=eps)
npt.assert_allclose(self.simulation.ue.antenna[3].beams_list[0],
- (32.16,20.71),atol=eps)
+ (32.16, 20.71), atol=eps)
# BS Gain matrix
- ref_gain = np.array([[ 34.03, 32.37, 8.41, -9.71],
- [ 8.41, -8.94, 34.03, 27.42]])
- gain = self.simulation.calculate_gains(self.simulation.bs,self.simulation.ue)
- npt.assert_allclose(gain,ref_gain,atol=eps)
+ ref_gain = np.array([[34.03, 32.37, 8.41, -9.71],
+ [8.41, -8.94, 34.03, 27.42]])
+ gain = self.simulation.calculate_gains(
+ self.simulation.bs, self.simulation.ue)
+ npt.assert_allclose(gain, ref_gain, atol=eps)
# UE Gain matrix
- ref_gain = np.array([[ 4.503, -44.198],
- [ -3.362, -11.206],
+ ref_gain = np.array([[4.503, -44.198],
+ [-3.362, -11.206],
[-14.812, -14.389],
- [ -9.726, 3.853]])
- gain = self.simulation.calculate_gains(self.simulation.ue,self.simulation.bs)
- npt.assert_allclose(gain,ref_gain,atol=eps)
+ [-9.726, 3.853]])
+ gain = self.simulation.calculate_gains(
+ self.simulation.ue, self.simulation.bs)
+ npt.assert_allclose(gain, ref_gain, atol=eps)
def test_calculate_imt_ul_tput(self):
self.param.general.system = "FSS_SS"
@@ -722,13 +757,13 @@ def test_calculate_imt_ul_tput(self):
# Test 1
snir = np.array([0.0, 1.0, 15.0, -5.0, 100.00, 200.00])
- ref_tput = np.array([ 0.400, 0.470, 2.011, 0.159, 2.927, 2.927])
+ ref_tput = np.array([0.400, 0.470, 2.011, 0.159, 2.927, 2.927])
tput = self.simulation.calculate_imt_tput(snir,
- self.param.imt.ul_sinr_min,
- self.param.imt.ul_sinr_max,
- self.param.imt.ul_attenuation_factor)
- npt.assert_allclose(tput,ref_tput,atol=eps)
+ self.param.imt.uplink.sinr_min,
+ self.param.imt.uplink.sinr_max,
+ self.param.imt.uplink.attenuation_factor)
+ npt.assert_allclose(tput, ref_tput, atol=eps)
+
if __name__ == '__main__':
unittest.main()
-
diff --git a/tests/test_spectral_mask_3gpp.py b/tests/test_spectral_mask_3gpp.py
index ecca99d1b..5a3be9141 100644
--- a/tests/test_spectral_mask_3gpp.py
+++ b/tests/test_spectral_mask_3gpp.py
@@ -11,8 +11,9 @@
from sharc.mask.spectral_mask_3gpp import SpectralMask3Gpp
from sharc.support.enumerations import StationType
+
class SpectalMask3GppTest(unittest.TestCase):
-
+
def setUp(self):
# Initialize variables for BS Cat-A mask (3.5 GHz)
sta_type = StationType.IMT_BS
@@ -20,28 +21,30 @@ def setUp(self):
frequency = 3490
bandwidth = 20
spurious = -13
- self.mask_bs_a = SpectralMask3Gpp(sta_type, frequency, bandwidth, spurious)
- self.mask_bs_a.set_mask(power = p_tx)
-
+ self.mask_bs_a = SpectralMask3Gpp(
+ sta_type, frequency, bandwidth, spurious)
+ self.mask_bs_a.set_mask(p_tx)
+
# Initialize variables for BS Cat-B mask (3.5 GHz)
sta_type = StationType.IMT_BS
p_tx = 46
frequency = 3490
bandwidth = 20
spurious = -30
- self.mask_bs_b = SpectralMask3Gpp(sta_type, frequency, bandwidth, spurious)
- self.mask_bs_b.set_mask(power = p_tx)
-
+ self.mask_bs_b = SpectralMask3Gpp(
+ sta_type, frequency, bandwidth, spurious)
+ self.mask_bs_b.set_mask(p_tx)
+
# Initialize variables for UE mask (3.5 GHz)
sta_type = StationType.IMT_UE
p_tx = 22
frequency = 3490
bandwidth = 20
spurious = -30
- self.mask_ue = SpectralMask3Gpp(sta_type, frequency, bandwidth, spurious)
- self.mask_ue.set_mask(power = p_tx)
-
-
+ self.mask_ue = SpectralMask3Gpp(
+ sta_type, frequency, bandwidth, spurious)
+ self.mask_ue.set_mask(p_tx)
+
def test_power_calc_bs_a(self):
#######################################################################
# BS Cat-A mask
@@ -49,132 +52,138 @@ def test_power_calc_bs_a(self):
fc = 3502.5
bandwidth = 5
poob = self.mask_bs_a.power_calc(fc, bandwidth)
- self.assertAlmostEqual(poob, 7.01, delta = 1e-2)
+ self.assertAlmostEqual(poob, 7.01, delta=1e-2)
#######################################################################
fc = 3507.5
bandwidth = 5
poob = self.mask_bs_a.power_calc(fc, bandwidth)
- self.assertAlmostEqual(poob, 2.98, delta = 1e-2)
-
+ self.assertAlmostEqual(poob, 2.98, delta=1e-2)
+
#######################################################################
fc = 3505
bandwidth = 10
poob = self.mask_bs_a.power_calc(fc, bandwidth)
- self.assertAlmostEqual(poob, 8.46, delta = 1e-2)
-
+ self.assertAlmostEqual(poob, 8.46, delta=1e-2)
+
#######################################################################
fc = 3510
bandwidth = 10
poob = self.mask_bs_a.power_calc(fc, bandwidth)
- self.assertAlmostEqual(poob, 3.50, delta = 1e-2)
-
+ self.assertAlmostEqual(poob, 3.50, delta=1e-2)
+
#######################################################################
fc = 3515
bandwidth = 10
poob = self.mask_bs_a.power_calc(fc, bandwidth)
- self.assertAlmostEqual(poob, -3, delta = 1e-2)
+ self.assertAlmostEqual(poob, -3, delta=1e-2)
#######################################################################
fc = 3520
bandwidth = 20
poob = self.mask_bs_a.power_calc(fc, bandwidth)
- self.assertAlmostEqual(poob, 0.01, delta = 1e-2)
-
- def test_power_calc_bs_b(self):
+ self.assertAlmostEqual(poob, 0.01, delta=1e-2)
+
+ def test_power_calc_bs_b(self):
#######################################################################
# BS Cat-B mask
#######################################################################
fc = 3502.5
bandwidth = 5
poob = self.mask_bs_b.power_calc(fc, bandwidth)
- self.assertAlmostEqual(poob, 7.01, delta = 1e-2)
+ self.assertAlmostEqual(poob, 7.01, delta=1e-2)
#######################################################################
fc = 3507.5
bandwidth = 5
poob = self.mask_bs_b.power_calc(fc, bandwidth)
- self.assertAlmostEqual(poob, 2.98, delta = 1e-2)
-
+ self.assertAlmostEqual(poob, 2.98, delta=1e-2)
+
#######################################################################
fc = 3505
bandwidth = 10
poob = self.mask_bs_b.power_calc(fc, bandwidth)
- self.assertAlmostEqual(poob, 8.46, delta = 1e-2)
-
+ self.assertAlmostEqual(poob, 8.46, delta=1e-2)
+
#######################################################################
fc = 3510
bandwidth = 10
poob = self.mask_bs_b.power_calc(fc, bandwidth)
- self.assertAlmostEqual(poob, 3, delta = 1e-2)
-
+ self.assertAlmostEqual(poob, 3, delta=1e-2)
+
#######################################################################
fc = 3515
bandwidth = 10
poob = self.mask_bs_b.power_calc(fc, bandwidth)
- self.assertAlmostEqual(poob, -20, delta = 1e-2)
+ self.assertAlmostEqual(poob, -20, delta=1e-2)
#######################################################################
fc = 3520
bandwidth = 20
poob = self.mask_bs_b.power_calc(fc, bandwidth)
- self.assertAlmostEqual(poob, -16.98, delta = 1e-2)
-
- def test_power_calc_ue(self):
+ self.assertAlmostEqual(poob, -16.98, delta=1e-2)
+
+ def test_power_calc_ue(self):
#######################################################################
# UE mask
#######################################################################
fc = 3500.5
bandwidth = 1
poob = self.mask_ue.power_calc(fc, bandwidth)
- self.assertAlmostEqual(poob, -21 + 10*np.log10(1/0.03), delta = 1e-2)
+ self.assertAlmostEqual(poob, -21 + 10 * np.log10(1 / 0.03), delta=1e-2)
#######################################################################
fc = 3503
bandwidth = 4
poob = self.mask_ue.power_calc(fc, bandwidth)
- self.assertAlmostEqual(poob, -10 + 10*np.log10(4), delta = 1e-2)
-
+ self.assertAlmostEqual(poob, -10 + 10 * np.log10(4), delta=1e-2)
+
######################################################################
fc = 3502.5
bandwidth = 5
poob = self.mask_ue.power_calc(fc, bandwidth)
- self.assertAlmostEqual(poob,
- 10*np.log10(np.power(10, 0.1*(-21 + 10*np.log10(1/0.03))) + np.power(10, 0.1*(-10 + 10*np.log10(4)))),
- delta = 1e-2)
-
+ self.assertAlmostEqual(poob,
+ 10 * np.log10(np.power(10,
+ 0.1 * (-21 + 10 * np.log10(1 / 0.03))) + np.power(10,
+ 0.1 * (-10 + 10 * np.log10(4)))),
+ delta=1e-2)
+
#######################################################################
fc = 3510
bandwidth = 10
poob = self.mask_ue.power_calc(fc, bandwidth)
- self.assertAlmostEqual(poob,
- -13 + 10*np.log10(10),
- delta = 1e-2)
-
+ self.assertAlmostEqual(poob,
+ -13 + 10 * np.log10(10),
+ delta=1e-2)
+
######################################################################
fc = 3520
bandwidth = 10
poob = self.mask_ue.power_calc(fc, bandwidth)
- self.assertAlmostEqual(poob,
- 10*np.log10(np.power(10, 0.1*(-13 + 10*np.log10(5))) + np.power(10, 0.1*(-25 + 10*np.log10(5)))),
- delta = 1e-2)
+ self.assertAlmostEqual(poob,
+ 10 * np.log10(np.power(10,
+ 0.1 * (-13 + 10 * np.log10(5))) + np.power(10,
+ 0.1 * (-25 + 10 * np.log10(5)))),
+ delta=1e-2)
#######################################################################
fc = 3525
bandwidth = 10
poob = self.mask_ue.power_calc(fc, bandwidth)
- self.assertAlmostEqual(poob,
- 10*np.log10(np.power(10, 0.1*(-25 + 10*np.log10(5))) + np.power(10, 0.1*(-30 + 10*np.log10(5)))),
- delta = 1e-2)
+ self.assertAlmostEqual(poob,
+ 10 * np.log10(np.power(10,
+ 0.1 * (-25 + 10 * np.log10(5))) + np.power(10,
+ 0.1 * (-30 + 10 * np.log10(5)))),
+ delta=1e-2)
#######################################################################
fc = 3600
bandwidth = 50
poob = self.mask_ue.power_calc(fc, bandwidth)
- self.assertAlmostEqual(poob,
- -30 + 10*np.log10(50),
- delta = 1e-2)
+ self.assertAlmostEqual(poob,
+ -30 + 10 * np.log10(50),
+ delta=1e-2)
+
-
if __name__ == '__main__':
- unittest.main()
\ No newline at end of file
+ unittest.main()
diff --git a/tests/test_spectral_mask_imt.py b/tests/test_spectral_mask_imt.py
index bed233744..4d9733e7a 100644
--- a/tests/test_spectral_mask_imt.py
+++ b/tests/test_spectral_mask_imt.py
@@ -11,8 +11,9 @@
from sharc.mask.spectral_mask_imt import SpectralMaskImt
from sharc.support.enumerations import StationType
+
class SpectalMaskImtTest(unittest.TestCase):
-
+
def setUp(self):
# Initialize variables for 40 GHz
sta_type = StationType.IMT_BS
@@ -20,27 +21,47 @@ def setUp(self):
freq = 43000
band = 200
spurious = -13
-
+
# Create mask for 40 GHz
self.mask_bs_40GHz = SpectralMaskImt(sta_type, freq, band, spurious)
- self.mask_bs_40GHz.set_mask(power = p_tx)
-
+ self.mask_bs_40GHz.set_mask(p_tx)
+
# Initialize variables for 40 GHz
sta_type = StationType.IMT_BS
p_tx = 28.1
freq = 24350
band = 200
-
+
# Create mask for BS at 26 GHz
self.mask_bs_26GHz = SpectralMaskImt(sta_type, freq, band, spurious)
- self.mask_bs_26GHz.set_mask(power = p_tx)
+ self.mask_bs_26GHz.set_mask(p_tx)
# Create mask for UE at 26 GHz
sta_type = StationType.IMT_UE
self.mask_ue_26GHz = SpectralMaskImt(sta_type, freq, band, spurious)
- self.mask_ue_26GHz.set_mask(power = p_tx)
-
-
+ self.mask_ue_26GHz.set_mask(p_tx)
+
+ # Initialize variables for 9GHz -13dBm/MHz
+ sta_type = StationType.IMT_BS
+ p_tx = 28.1
+ freq = 9000
+ band = 200
+
+ # Create mask for BS at 9 GHz
+ self.mask_bs_9GHz = SpectralMaskImt(sta_type, freq, band, -13)
+ self.mask_bs_9GHz.set_mask(p_tx)
+
+ # Initialize variables for 9GHz -30dBm/MHz
+ sta_type = StationType.IMT_BS
+ p_tx = 28.1
+ freq = 9000
+ band = 200
+
+ # Create mask for BS at 9 GHz and spurious emission at -30dBm/MHz
+ self.mask_bs_9GHz_30_spurious = SpectralMaskImt(
+ sta_type, freq, band, -30)
+ self.mask_bs_9GHz_30_spurious.set_mask(p_tx)
+
def test_power_calc(self):
#######################################################################
# Testing mask for 40 GHz
@@ -52,29 +73,29 @@ def test_power_calc(self):
with self.assertWarns(RuntimeWarning):
poob = self.mask_bs_40GHz.power_calc(fc, band)
self.assertAlmostEqual(poob, -np.inf, delta=1e-2)
-
+
# Test 2
fc = 43300
band = 600
poob = self.mask_bs_40GHz.power_calc(fc, band)
self.assertAlmostEqual(poob, 11.8003, delta=1e-2)
-
+
# Test 3
fc = 43000
band = 1200
poob = self.mask_bs_40GHz.power_calc(fc, band)
self.assertAlmostEqual(poob, 14.8106, delta=1e-2)
-
+
# Test 4
fc = 45000
band = 1000
poob = self.mask_bs_40GHz.power_calc(fc, band)
- self.assertAlmostEqual(poob, 17, delta=1e-2)
-
+ self.assertAlmostEqual(poob, 17, delta=1e-2)
+
#######################################################################
# Testing mask for 26 GHz
#######################################################################
-
+
# Test 1 - BS
fc = 23800
band = 400
@@ -92,7 +113,7 @@ def test_power_calc(self):
band = 400
poob = self.mask_bs_26GHz.power_calc(fc, band)
self.assertAlmostEqual(poob, 13.02, delta=1e-2)
-
+
# Test 1 - UE
fc = 23800
band = 400
@@ -111,7 +132,54 @@ def test_power_calc(self):
poob = self.mask_ue_26GHz.power_calc(fc, band)
self.assertAlmostEqual(poob, 13.02, delta=1e-2)
+ #######################################################################
+ # Testing mask for 9 GHz and -13dBm/MHz spurious emissions (alternative mask, for BS only)
+ #######################################################################
+
+ # Test 1 - BS
+ fc = 9200
+ band = 200
+ poob = self.mask_bs_9GHz.power_calc(fc, band)
+ # for this test to pass, alternative mask sample size needed to be at
+ # least approx. 30 for OOB start
+ self.assertAlmostEqual(poob, 10.09, delta=1e-2)
+
+ # Test 2 - BS
+ fc = 8800
+ band = 200
+ poob = self.mask_bs_9GHz.power_calc(fc, band)
+ self.assertAlmostEqual(poob, 10.09, delta=1e-2)
+
+ # Test 3 - BS
+ fc = 9400
+ band = 400
+ poob = self.mask_bs_9GHz.power_calc(fc, band)
+ self.assertAlmostEqual(poob, 13.02, delta=1e-2)
+
+ #######################################################################
+ # Testing mask for 9 GHz and -30dBm/MHz spurious emissions (alternative mask, for BS only)
+ #######################################################################
+
+ # Test 1 - BS
+ fc = 9200
+ band = 200
+ poob = self.mask_bs_9GHz_30_spurious.power_calc(fc, band)
+ # for this test to pass, 'ALTERNATIVE_MASK_DIAGONAL_SAMPLESIZE' needed
+ # to be at least approx. 40
+ self.assertAlmostEqual(poob, 8.26, delta=1e-2)
+
+ # Test 2 - BS
+ fc = 8800
+ band = 200
+ poob = self.mask_bs_9GHz_30_spurious.power_calc(fc, band)
+ self.assertAlmostEqual(poob, 8.26, delta=1e-2)
+
+ # Test 3 - BS
+ fc = 9400
+ band = 400
+ poob = self.mask_bs_9GHz_30_spurious.power_calc(fc, band)
+ self.assertAlmostEqual(poob, 8.14, delta=1e-2)
+
-
if __name__ == '__main__':
- unittest.main()
\ No newline at end of file
+ unittest.main()
diff --git a/tests/test_station.py b/tests/test_station.py
index 3c4256171..365e43d67 100644
--- a/tests/test_station.py
+++ b/tests/test_station.py
@@ -10,46 +10,48 @@
from sharc.support.enumerations import StationType
from sharc.antenna.antenna_beamforming_imt import AntennaBeamformingImt
from sharc.antenna.antenna_omni import AntennaOmni
-from sharc.parameters.parameters_antenna_imt import ParametersAntennaImt
+from sharc.parameters.imt.parameters_antenna_imt import ParametersAntennaImt
from sharc.station import Station
+
class StationTest(unittest.TestCase):
def setUp(self):
- #Array parameters
- self.param = ParametersAntennaImt()
-
- self.param.adjacent_antenna_model = "SINGLE_ELEMENT"
- self.param.bs_normalization = False
- self.param.bs_normalization_file = None
- self.param.bs_element_pattern = "M2101"
- self.param.bs_minimum_array_gain = -200
- self.param.bs_element_max_g = 10
- self.param.bs_element_phi_3db = 65
- self.param.bs_element_theta_3db = 75
- self.param.bs_element_am = 35
- self.param.bs_element_sla_v = 25
- self.param.bs_n_rows = 8
- self.param.bs_n_columns = 8
- self.param.bs_element_horiz_spacing = 0.5
- self.param.bs_element_vert_spacing = 0.5
- self.param.bs_multiplication_factor = 12
- self.param.bs_downtilt = 0
-
- self.param.ue_element_pattern = "M2101"
- self.param.ue_normalization = False
- self.param.ue_normalization_file = None
- self.param.ue_minimum_array_gain = -200
- self.param.ue_element_max_g = 10
- self.param.ue_element_phi_3db = 75
- self.param.ue_element_theta_3db = 65
- self.param.ue_element_am = 25
- self.param.ue_element_sla_v = 35
- self.param.ue_n_rows = 2
- self.param.ue_n_columns = 2
- self.param.ue_element_horiz_spacing = 0.5
- self.param.ue_element_vert_spacing = 0.5
- self.param.ue_multiplication_factor = 12
+ # Array parameters
+ self.bs_param = ParametersAntennaImt()
+ self.ue_param = ParametersAntennaImt()
+
+ self.bs_param.adjacent_antenna_model = "SINGLE_ELEMENT"
+ self.bs_param.normalization = False
+ self.bs_param.normalization_file = None
+ self.bs_param.element_pattern = "M2101"
+ self.bs_param.minimum_array_gain = -200
+ self.bs_param.element_max_g = 10
+ self.bs_param.element_phi_3db = 65
+ self.bs_param.element_theta_3db = 75
+ self.bs_param.element_am = 35
+ self.bs_param.element_sla_v = 25
+ self.bs_param.n_rows = 8
+ self.bs_param.n_columns = 8
+ self.bs_param.element_horiz_spacing = 0.5
+ self.bs_param.element_vert_spacing = 0.5
+ self.bs_param.multiplication_factor = 12
+ self.bs_param.downtilt = 0
+
+ self.ue_param.element_pattern = "M2101"
+ self.ue_param.normalization = False
+ self.ue_param.normalization_file = None
+ self.ue_param.minimum_array_gain = -200
+ self.ue_param.element_max_g = 10
+ self.ue_param.element_phi_3db = 75
+ self.ue_param.element_theta_3db = 65
+ self.ue_param.element_am = 25
+ self.ue_param.element_sla_v = 35
+ self.ue_param.n_rows = 2
+ self.ue_param.n_columns = 2
+ self.ue_param.element_horiz_spacing = 0.5
+ self.ue_param.element_vert_spacing = 0.5
+ self.ue_param.multiplication_factor = 12
self.station = Station()
self.station.id = 1
@@ -59,8 +61,8 @@ def setUp(self):
self.station.height = 6
self.station.tx_power = 20
self.station.rx_power = -3
- par = self.param.get_antenna_parameters(StationType.IMT_BS)
- self.station.antenna = AntennaBeamformingImt(par,300,-10)
+ par = self.bs_param.get_antenna_parameters()
+ self.station.antenna = AntennaBeamformingImt(par, 300, -10)
self.station2 = Station()
self.station2.id = 1
@@ -70,8 +72,8 @@ def setUp(self):
self.station2.height = 6
self.station2.tx_power = 17
self.station2.rx_power = 9
- par = self.param.get_antenna_parameters(StationType.IMT_UE)
- self.station2.antenna = AntennaBeamformingImt(par,270,2)
+ par = self.ue_param.get_antenna_parameters()
+ self.station2.antenna = AntennaBeamformingImt(par, 270, 2)
self.station3 = Station()
self.station3.id = 2
@@ -87,7 +89,7 @@ def test_id(self):
self.assertEqual(self.station.id, 1)
def test_station_type(self):
- self.assertEqual(self.station.station_type,StationType.IMT_BS)
+ self.assertEqual(self.station.station_type, StationType.IMT_BS)
def test_x(self):
self.assertEqual(self.station.x, 10)
diff --git a/tests/test_station_factory.py b/tests/test_station_factory.py
index 96cf8cf39..ffe4b79e2 100644
--- a/tests/test_station_factory.py
+++ b/tests/test_station_factory.py
@@ -9,16 +9,89 @@
import numpy as np
import numpy.testing as npt
+from sharc.parameters.imt.parameters_imt import ParametersImt
from sharc.station_factory import StationFactory
+from sharc.topology.topology_ntn import TopologyNTN
+
class StationFactoryTest(unittest.TestCase):
-
+ """Test cases for StationFactory."""
+
def setUp(self):
- pass
-
+ self.station_factory = StationFactory()
+
def test_generate_imt_base_stations(self):
pass
-
-
+
+ def test_generate_imt_base_stations_ntn(self):
+ """Test for IMT-NTN space station generation."""
+ seed = 100
+ rng = np.random.RandomState(seed)
+
+ param_imt = ParametersImt()
+ param_imt.topology.type = "NTN"
+
+ # Paramters for IMT-NTN
+ param_imt.topology.ntn.bs_height = 1200000 # meters
+ param_imt.topology.ntn.cell_radius = 45000 # meters
+ param_imt.topology.ntn.bs_azimuth = 60 # degrees
+ param_imt.topology.ntn.bs_elevation = 45 # degrees
+ param_imt.topology.ntn.num_sectors = 1
+
+ ntn_topology = TopologyNTN(
+ param_imt.topology.ntn.intersite_distance,
+ param_imt.topology.ntn.cell_radius,
+ param_imt.topology.ntn.bs_height,
+ param_imt.topology.ntn.bs_azimuth,
+ param_imt.topology.ntn.bs_elevation,
+ param_imt.topology.ntn.num_sectors)
+
+ ntn_topology.calculate_coordinates()
+ ntn_bs = StationFactory.generate_imt_base_stations(param_imt, param_imt.bs.antenna, ntn_topology, rng)
+ npt.assert_equal(ntn_bs.height, param_imt.topology.ntn.bs_height)
+ # the azimuth seen from BS antenna
+ npt.assert_almost_equal(ntn_bs.azimuth[0], param_imt.topology.ntn.bs_azimuth - 180, 1e-3)
+ # Elevation w.r.t to xy plane
+ npt.assert_almost_equal(ntn_bs.elevation[0], -45.0, 1e-2)
+ npt.assert_almost_equal(ntn_bs.x, param_imt.topology.ntn.bs_height *
+ np.tan(np.radians(param_imt.topology.ntn.bs_elevation)) *
+ np.cos(np.radians(param_imt.topology.ntn.bs_azimuth)), 1e-2)
+
+ def test_generate_imt_ue_outdoor_ntn(self):
+ """Basic test for IMT UE NTN generation."""
+ seed = 100
+ rng = np.random.RandomState(seed)
+
+ # Parameters used for IMT-NTN and UE distribution
+ param_imt = ParametersImt()
+ param_imt.topology.type = "NTN"
+ param_imt.ue.azimuth_range = (-180, 180)
+ param_imt.ue.distribution_type = "ANGLE_AND_DISTANCE"
+ param_imt.ue.distribution_azimuth = "UNIFORM"
+ param_imt.ue.distribution_distance = "UNIFORM"
+ param_imt.ue.k = 1000
+
+ # Paramters for IMT-NTN
+ param_imt.topology.ntn.bs_height = 1200000 # meters
+ param_imt.topology.ntn.cell_radius = 45000 # meters
+ param_imt.topology.ntn.bs_azimuth = 60 # degrees
+ param_imt.topology.ntn.bs_elevation = 45 # degrees
+ param_imt.topology.ntn.num_sectors = 1
+
+ ntn_topology = TopologyNTN(
+ param_imt.topology.ntn.intersite_distance,
+ param_imt.topology.ntn.cell_radius,
+ param_imt.topology.ntn.bs_height,
+ param_imt.topology.ntn.bs_azimuth,
+ param_imt.topology.ntn.bs_elevation,
+ param_imt.topology.ntn.num_sectors)
+
+ ntn_topology.calculate_coordinates()
+ ntn_ue = StationFactory.generate_imt_ue_outdoor(param_imt, param_imt.ue.antenna, rng, ntn_topology)
+ dist = np.sqrt(ntn_ue.x**2 + ntn_ue.y**2)
+ # test if the maximum distance is close to the cell radius within a 100km range
+ npt.assert_almost_equal(dist.max(), param_imt.topology.ntn.cell_radius, -2)
+
+
if __name__ == '__main__':
- unittest.main()
\ No newline at end of file
+ unittest.main()
diff --git a/tests/test_station_manager.py b/tests/test_station_manager.py
index a1dbf64a0..6b1c1ef10 100644
--- a/tests/test_station_manager.py
+++ b/tests/test_station_manager.py
@@ -11,7 +11,7 @@
from sharc.support.enumerations import StationType
from sharc.antenna.antenna_beamforming_imt import AntennaBeamformingImt
-from sharc.parameters.parameters_antenna_imt import ParametersAntennaImt
+from sharc.parameters.imt.parameters_antenna_imt import ParametersAntennaImt
from sharc.station import Station
from sharc.station_manager import StationManager
@@ -19,42 +19,44 @@
class StationManagerTest(unittest.TestCase):
def setUp(self):
- #Array parameters
- self.param = ParametersAntennaImt()
-
- self.param.adjacent_antenna_model = "SINGLE_ELEMENT"
- self.param.bs_normalization = False
- self.param.bs_normalization_file = None
- self.param.bs_element_pattern = "M2101"
- self.param.bs_minimum_array_gain = -200
- self.param.bs_downtilt = 0
-
- self.param.bs_element_max_g = 10
- self.param.bs_element_phi_3db = 65
- self.param.bs_element_theta_3db = 75
- self.param.bs_element_am = 35
- self.param.bs_element_sla_v = 25
- self.param.bs_n_rows = 8
- self.param.bs_n_columns = 8
- self.param.bs_element_horiz_spacing = 0.5
- self.param.bs_element_vert_spacing = 0.5
- self.param.bs_multiplication_factor = 12
-
- self.param.ue_element_pattern = "M2101"
- self.param.ue_normalization = False
- self.param.ue_normalization_file = None
- self.param.ue_minimum_array_gain = -200
-
- self.param.ue_element_max_g = 10
- self.param.ue_element_phi_3db = 75
- self.param.ue_element_theta_3db = 65
- self.param.ue_element_am = 25
- self.param.ue_element_sla_v = 35
- self.param.ue_n_rows = 2
- self.param.ue_n_columns = 2
- self.param.ue_element_horiz_spacing = 0.5
- self.param.ue_element_vert_spacing = 0.5
- self.param.ue_multiplication_factor = 12
+ # Array parameters
+ self.bs_param = ParametersAntennaImt()
+ self.ue_param = ParametersAntennaImt()
+
+ self.ue_param.adjacent_antenna_model = "SINGLE_ELEMENT"
+ self.bs_param.adjacent_antenna_model = "SINGLE_ELEMENT"
+ self.bs_param.normalization = False
+ self.bs_param.normalization_file = None
+ self.bs_param.element_pattern = "M2101"
+ self.bs_param.minimum_array_gain = -200
+ self.bs_param.downtilt = 0
+
+ self.bs_param.element_max_g = 10
+ self.bs_param.element_phi_3db = 65
+ self.bs_param.element_theta_3db = 75
+ self.bs_param.element_am = 35
+ self.bs_param.element_sla_v = 25
+ self.bs_param.n_rows = 8
+ self.bs_param.n_columns = 8
+ self.bs_param.element_horiz_spacing = 0.5
+ self.bs_param.element_vert_spacing = 0.5
+ self.bs_param.multiplication_factor = 12
+
+ self.ue_param.element_pattern = "M2101"
+ self.ue_param.normalization = False
+ self.ue_param.normalization_file = None
+ self.ue_param.minimum_array_gain = -200
+
+ self.ue_param.element_max_g = 10
+ self.ue_param.element_phi_3db = 75
+ self.ue_param.element_theta_3db = 65
+ self.ue_param.element_am = 25
+ self.ue_param.element_sla_v = 35
+ self.ue_param.n_rows = 2
+ self.ue_param.n_columns = 2
+ self.ue_param.element_horiz_spacing = 0.5
+ self.ue_param.element_vert_spacing = 0.5
+ self.ue_param.multiplication_factor = 12
self.station_manager = StationManager(3)
self.station_manager.x = np.array([10, 20, 30])
@@ -64,8 +66,9 @@ def setUp(self):
# this is for downlink
self.station_manager.tx_power = dict({0: [27, 30], 1: [35], 2: [40]})
self.station_manager.rx_power = np.array([-50, -35, -10])
- par = self.param.get_antenna_parameters(StationType.IMT_BS)
- self.station_manager.antenna = np.array([AntennaBeamformingImt(par,60,-10), AntennaBeamformingImt(par,180,-10), AntennaBeamformingImt(par,300,-10)])
+ par = self.bs_param.get_antenna_parameters()
+ self.station_manager.antenna = np.array([AntennaBeamformingImt(
+ par, 60, -10), AntennaBeamformingImt(par, 180, -10), AntennaBeamformingImt(par, 300, -10)])
self.station_manager.station_type = StationType.IMT_BS
self.station_manager2 = StationManager(2)
@@ -74,10 +77,11 @@ def setUp(self):
self.station_manager2.height = np.array([4, 5])
self.station_manager2.intersite_dist = 100.0
# this is for downlink
- self.station_manager2.tx_power = dict({0: [25], 1: [28,35]})
+ self.station_manager2.tx_power = dict({0: [25], 1: [28, 35]})
self.station_manager2.rx_power = np.array([-50, -35])
- par = self.param.get_antenna_parameters(StationType.IMT_BS)
- self.station_manager2.antenna = np.array([AntennaBeamformingImt(par,0,-5), AntennaBeamformingImt(par,180,-5)])
+ par = self.bs_param.get_antenna_parameters()
+ self.station_manager2.antenna = np.array(
+ [AntennaBeamformingImt(par, 0, -5), AntennaBeamformingImt(par, 180, -5)])
self.station_manager2.station_type = StationType.IMT_BS
self.station_manager3 = StationManager(1)
@@ -87,9 +91,10 @@ def setUp(self):
self.station_manager3.intersite_dist = 100.0
# this is for uplink
self.station_manager3.tx_power = 22
- self.station_manager3.rx_power = np.array([-50,-35])
- par = self.param.get_antenna_parameters(StationType.IMT_UE)
- self.station_manager3.antenna = np.array([AntennaBeamformingImt(par,0,-30), AntennaBeamformingImt(par,35,45)])
+ self.station_manager3.rx_power = np.array([-50, -35])
+ par = self.ue_param.get_antenna_parameters()
+ self.station_manager3.antenna = np.array(
+ [AntennaBeamformingImt(par, 0, -30), AntennaBeamformingImt(par, 35, 45)])
self.station_manager3.station_type = StationType.IMT_UE
self.station = Station()
@@ -99,8 +104,8 @@ def setUp(self):
self.station.height = 1
self.station.tx_power = 30
self.station.rx_power = -50
- par = self.param.get_antenna_parameters(StationType.IMT_UE)
- self.station.antenna = AntennaBeamformingImt(par,100,-10)
+ par = self.ue_param.get_antenna_parameters()
+ self.station.antenna = AntennaBeamformingImt(par, 100, -10)
self.station.station_type = StationType.IMT_UE
self.station2 = Station()
@@ -110,11 +115,10 @@ def setUp(self):
self.station2.height = 2
self.station2.tx_power = 35
self.station2.rx_power = -35
- par = self.param.get_antenna_parameters(StationType.IMT_BS)
- self.station2.antenna = AntennaBeamformingImt(par,-90,-15)
+ par = self.bs_param.get_antenna_parameters()
+ self.station2.antenna = AntennaBeamformingImt(par, -90, -15)
self.station2.station_type = StationType.IMT_BS
-
def test_num_stations(self):
self.assertEqual(self.station_manager.num_stations, 3)
self.assertEqual(self.station_manager2.num_stations, 2)
@@ -122,85 +126,95 @@ def test_num_stations(self):
def test_station_type(self):
self.assertEqual(self.station_manager.station_type, StationType.IMT_BS)
- self.assertEqual(self.station_manager2.station_type, StationType.IMT_BS)
- self.assertEqual(self.station_manager3.station_type, StationType.IMT_UE)
+ self.assertEqual(
+ self.station_manager2.station_type,
+ StationType.IMT_BS)
+ self.assertEqual(
+ self.station_manager3.station_type,
+ StationType.IMT_UE)
def test_x(self):
# get a single value from the original array
self.assertEqual(self.station_manager.x[0], 10)
# get two specific values
- npt.assert_array_equal(self.station_manager.x[[1,2]], [20,30])
+ npt.assert_array_equal(self.station_manager.x[[1, 2]], [20, 30])
# get values in reverse order
- npt.assert_array_equal(self.station_manager.x[[2,1,0]], [30,20,10])
+ npt.assert_array_equal(self.station_manager.x[[2, 1, 0]], [30, 20, 10])
# get all values (no need to specify the id's)
- npt.assert_array_equal(self.station_manager.x, [10,20,30])
+ npt.assert_array_equal(self.station_manager.x, [10, 20, 30])
# set a single value and get it
self.station_manager.x[0] = 8
- npt.assert_array_equal(self.station_manager.x[[0,1]], [8,20])
+ npt.assert_array_equal(self.station_manager.x[[0, 1]], [8, 20])
# set two values and then get all values
- self.station_manager.x[[1,2]] = [16,32]
- npt.assert_array_equal(self.station_manager.x, [8,16,32])
+ self.station_manager.x[[1, 2]] = [16, 32]
+ npt.assert_array_equal(self.station_manager.x, [8, 16, 32])
def test_y(self):
# get a single value from the original array
self.assertEqual(self.station_manager.y[0], 15)
# get two specific values
- npt.assert_array_equal(self.station_manager.y[[1,2]], [25,35])
+ npt.assert_array_equal(self.station_manager.y[[1, 2]], [25, 35])
# get values in reverse order
- npt.assert_array_equal(self.station_manager.y[[2,1,0]], [35,25,15])
+ npt.assert_array_equal(self.station_manager.y[[2, 1, 0]], [35, 25, 15])
# get all values (no need to specify the id's)
- npt.assert_array_equal(self.station_manager.y, [15,25,35])
+ npt.assert_array_equal(self.station_manager.y, [15, 25, 35])
# set a single value and get it
self.station_manager.y[1] = 9
- npt.assert_array_equal(self.station_manager.y[[0,1]], [15,9])
+ npt.assert_array_equal(self.station_manager.y[[0, 1]], [15, 9])
# set two values and then get all values
- self.station_manager.y[[0,2]] = [7,21]
- npt.assert_array_equal(self.station_manager.y, [7,9,21])
+ self.station_manager.y[[0, 2]] = [7, 21]
+ npt.assert_array_equal(self.station_manager.y, [7, 9, 21])
def test_height(self):
# get a single value from the original array
self.assertEqual(self.station_manager.height[0], 1)
# get two specific values
- npt.assert_array_equal(self.station_manager.height[[0,2]], [1,3])
+ npt.assert_array_equal(self.station_manager.height[[0, 2]], [1, 3])
# get values in reverse order
- npt.assert_array_equal(self.station_manager.height[[2,1,0]], [3,2,1])
+ npt.assert_array_equal(
+ self.station_manager.height[[2, 1, 0]], [3, 2, 1])
# get all values (no need to specify the id's)
- npt.assert_array_equal(self.station_manager.height, [1,2,3])
+ npt.assert_array_equal(self.station_manager.height, [1, 2, 3])
# set a single value and get it
self.station_manager.height[1] = 7
- npt.assert_array_equal(self.station_manager.height[[1,2]], [7,3])
+ npt.assert_array_equal(self.station_manager.height[[1, 2]], [7, 3])
# set two values and then get all values
- self.station_manager.height[[0,2]] = [5,4]
- npt.assert_array_equal(self.station_manager.height, [5,7,4])
+ self.station_manager.height[[0, 2]] = [5, 4]
+ npt.assert_array_equal(self.station_manager.height, [5, 7, 4])
def test_tx_power(self):
# get a single value from the original array
- self.assertEqual(self.station_manager.tx_power[0], [27,30])
+ self.assertEqual(self.station_manager.tx_power[0], [27, 30])
self.assertEqual(self.station_manager.tx_power[1], [35])
# get all values (no need to specify the id's)
- npt.assert_array_equal(self.station_manager.tx_power, dict({0: [27, 30], 1: [35], 2: [40]}))
+ npt.assert_array_equal(self.station_manager.tx_power, dict(
+ {0: [27, 30], 1: [35], 2: [40]}))
# set a single value and get it
- self.station_manager.tx_power[0] = [33,38]
- npt.assert_array_equal(self.station_manager.tx_power[0], [33,38])
+ self.station_manager.tx_power[0] = [33, 38]
+ npt.assert_array_equal(self.station_manager.tx_power[0], [33, 38])
# set two values and then get all values
- self.station_manager.tx_power[2] = [20,25]
- npt.assert_array_equal(self.station_manager.tx_power, dict({0: [33,38], 1: [35], 2: [20,25]}))
+ self.station_manager.tx_power[2] = [20, 25]
+ npt.assert_array_equal(self.station_manager.tx_power, dict(
+ {0: [33, 38], 1: [35], 2: [20, 25]}))
def test_rx_power(self):
# get a single value from the original array
self.assertEqual(self.station_manager.rx_power[2], -10)
# get two specific values
- npt.assert_array_equal(self.station_manager.rx_power[[0,1]], [-50,-35])
+ npt.assert_array_equal(
+ self.station_manager.rx_power[[0, 1]], [-50, -35])
# get values in reverse order
- npt.assert_array_equal(self.station_manager.rx_power[[2,1,0]], [-10,-35,-50] )
+ npt.assert_array_equal(
+ self.station_manager.rx_power[[2, 1, 0]], [-10, -35, -50])
# get all values (no need to specify the id's)
- npt.assert_array_equal(self.station_manager.rx_power, [-50,-35,-10])
+ npt.assert_array_equal(self.station_manager.rx_power, [-50, -35, -10])
# set a single value and get it
self.station_manager.rx_power[2] = -15
- npt.assert_array_equal(self.station_manager.rx_power[[2,0]], [-15,-50])
+ npt.assert_array_equal(
+ self.station_manager.rx_power[[2, 0]], [-15, -50])
# set two values and then get all values
- self.station_manager.rx_power[[0,1]] = [-60,-30]
- npt.assert_array_equal(self.station_manager.rx_power, [-60,-30,-15])
+ self.station_manager.rx_power[[0, 1]] = [-60, -30]
+ npt.assert_array_equal(self.station_manager.rx_power, [-60, -30, -15])
def test_antenna(self):
self.assertEqual(self.station_manager.antenna[0].azimuth, 60)
@@ -247,7 +261,7 @@ def test_station(self):
self.station.id = 1
self.assertTrue(self.station != self.station_manager.get_station(0))
# test station type
- self.assertEqual(self.station_manager.get_station(0).station_type,\
+ self.assertEqual(self.station_manager.get_station(0).station_type,
StationType.IMT_BS)
def test_station_list(self):
@@ -256,7 +270,7 @@ def test_station_list(self):
self.assertTrue(self.station in station_list)
self.assertTrue(self.station2 in station_list)
#
- station_list = self.station_manager.get_station_list([0,2])
+ station_list = self.station_manager.get_station_list([0, 2])
self.assertTrue(self.station in station_list)
self.assertTrue(self.station2 not in station_list)
#
@@ -265,86 +279,93 @@ def test_station_list(self):
self.assertTrue(self.station2 not in station_list)
def test_distance_to(self):
- ref_distance = np.array([[ 356.405, 180.277]])
+ ref_distance = np.array([[356.405, 180.277]])
distance = self.station_manager3.get_distance_to(self.station_manager2)
npt.assert_allclose(distance, ref_distance, atol=1e-2)
- ref_distance = np.asarray([[ 127.279, 302.200],
- [ 113.137, 288.140],
- [ 98.994, 274.089]])
+ ref_distance = np.asarray([[127.279, 302.200],
+ [113.137, 288.140],
+ [98.994, 274.089]])
distance = self.station_manager.get_distance_to(self.station_manager2)
npt.assert_allclose(distance, ref_distance, atol=1e-2)
def test_3d_distance_to(self):
- ref_distance = np.asarray([[ 356.411, 180.302]])
- distance = self.station_manager3.get_3d_distance_to(self.station_manager2)
+ ref_distance = np.asarray([[356.411, 180.302]])
+ distance = self.station_manager3.get_3d_distance_to(
+ self.station_manager2)
npt.assert_allclose(distance, ref_distance, atol=1e-2)
- ref_distance = np.asarray([[ 127.314, 302.226],
- [ 113.154, 288.156],
- [ 99, 274.096]])
- distance = self.station_manager.get_3d_distance_to(self.station_manager2)
+ ref_distance = np.asarray([[127.314, 302.226],
+ [113.154, 288.156],
+ [99, 274.096]])
+ distance = self.station_manager.get_3d_distance_to(
+ self.station_manager2)
npt.assert_allclose(distance, ref_distance, atol=1e-2)
-
+
def test_wrap_around(self):
self.station_manager = StationManager(2)
self.station_manager.x = np.array([0, 150])
self.station_manager.y = np.array([0, -32])
self.station_manager.height = np.array([4, 5])
self.station_manager.intersite_dist = 100.0
-
+
self.station_manager2 = StationManager(3)
- self.station_manager2.x = np.array([10, 200, 30])
+ self.station_manager2.x = np.array([10, 200, 30])
self.station_manager2.y = np.array([15, 250, -350])
self.station_manager2.height = np.array([1, 2, 3])
-
+
# 2D Distance
- d_2D, d_3D, phi, theta = self.station_manager.get_dist_angles_wrap_around(self.station_manager2)
- ref_d_2D = np.asarray([[ 18.03, 150.32, 85.39],
- [ 147.68, 181.12, 205.25]])
+ d_2D, d_3D, phi, theta = self.station_manager.get_dist_angles_wrap_around(
+ self.station_manager2)
+ ref_d_2D = np.asarray([[18.03, 150.32, 85.39],
+ [147.68, 181.12, 205.25]])
npt.assert_allclose(d_2D, ref_d_2D, atol=1e-2)
-
+
# 3D Distance
- ref_d_3D = np.asarray([[ 18.27, 150.33, 85.39],
- [ 147.73, 181.15, 205.26]])
+ ref_d_3D = np.asarray([[18.27, 150.33, 85.39],
+ [147.73, 181.15, 205.26]])
npt.assert_allclose(d_3D, ref_d_3D, atol=1e-2)
-
+
# Point vec
- ref_phi = np.asarray([[ 56.31, -176.26 , 103.55],
- [ 161.44, -56.49, 145.92]])
+ ref_phi = np.asarray([[56.31, -176.26, 103.55],
+ [161.44, -56.49, 145.92]])
npt.assert_allclose(phi, ref_phi, atol=1e-2)
-
- ref_theta = np.asarray([[ 99.45, 90.76, 90.67],
- [ 91.55, 90.95, 90.56]])
- npt.assert_allclose(theta,ref_theta, atol=1e-2)
+
+ ref_theta = np.asarray([[99.45, 90.76, 90.67],
+ [91.55, 90.95, 90.56]])
+ npt.assert_allclose(theta, ref_theta, atol=1e-2)
def test_pointing_vector_to(self):
eps = 1e-1
# Test 1
- phi, theta = self.station_manager.get_pointing_vector_to(self.station_manager2)
- npt.assert_allclose(phi,np.array([[45.00, 51.04],
+ phi, theta = self.station_manager.get_pointing_vector_to(
+ self.station_manager2)
+ npt.assert_allclose(phi, np.array([[45.00, 51.04],
[45.00, 51.34],
- [45.00, 51.67]]),atol=eps)
- npt.assert_allclose(theta,np.array([[88.65, 89.24],
+ [45.00, 51.67]]), atol=eps)
+ npt.assert_allclose(theta, np.array([[88.65, 89.24],
[88.89, 89.40],
- [89.42, 89.58]]),atol=eps)
+ [89.42, 89.58]]), atol=eps)
# Test 2
- phi, theta = self.station_manager2.get_pointing_vector_to(self.station_manager)
- npt.assert_allclose(phi,np.array([[-135.00, -135.00, -135.00],
- [-128.96, -128.66, -128.33]]),atol=eps)
- npt.assert_allclose(theta,np.array([[91.35, 91.01, 90.58],
- [90.76, 90.60, 90.42]]),atol=eps)
+ phi, theta = self.station_manager2.get_pointing_vector_to(
+ self.station_manager)
+ npt.assert_allclose(phi, np.array([[-135.00, -135.00, -135.00],
+ [-128.96, -128.66, -128.33]]), atol=eps)
+ npt.assert_allclose(theta, np.array([[91.35, 91.01, 90.58],
+ [90.76, 90.60, 90.42]]), atol=eps)
# Test 3
- phi, theta = self.station_manager3.get_pointing_vector_to(self.station_manager2)
- npt.assert_allclose(phi,np.array([[-124.13, -123.69]]),atol=eps)
- npt.assert_allclose(theta,np.array([[89.73, 89.05]]),atol=eps)
+ phi, theta = self.station_manager3.get_pointing_vector_to(
+ self.station_manager2)
+ npt.assert_allclose(phi, np.array([[-124.13, -123.69]]), atol=eps)
+ npt.assert_allclose(theta, np.array([[89.73, 89.05]]), atol=eps)
# Test 4
- phi, theta = self.station_manager2.get_pointing_vector_to(self.station_manager3)
- npt.assert_allclose(phi,np.array([[55.86], [56.31]]),atol=eps)
- npt.assert_allclose(theta,np.array([[90.32], [90.95]]),atol=eps)
+ phi, theta = self.station_manager2.get_pointing_vector_to(
+ self.station_manager3)
+ npt.assert_allclose(phi, np.array([[55.86], [56.31]]), atol=eps)
+ npt.assert_allclose(theta, np.array([[90.32], [90.95]]), atol=eps)
def test_off_axis_angle(self):
sm1 = StationManager(1)
@@ -416,36 +437,36 @@ def test_off_axis_angle(self):
sm7.elevation = np.array([0, 0])
phi_ref = np.array([[0, 45]])
- npt.assert_allclose(phi_ref, sm6.get_off_axis_angle(sm7), atol=1e-2)
-
-
+ npt.assert_allclose(phi_ref, sm6.get_off_axis_angle(sm7), atol=1e-2)
+
def test_elevation(self):
sm1 = StationManager(1)
sm1.x = np.array([0])
sm1.y = np.array([0])
sm1.height = np.array([10])
-
+
sm2 = StationManager(6)
- sm2.x = np.array([10, 10, 0, 0, 30, 20])
- sm2.y = np.array([ 0, 0, 5, 10, 30, 20])
- sm2.height = np.array([10, 20, 5, 0, 20, 20])
-
+ sm2.x = np.array([10, 10, 0, 0, 30, 20])
+ sm2.y = np.array([0, 0, 5, 10, 30, 20])
+ sm2.height = np.array([10, 20, 5, 0, 20, 20])
+
elevation_ref = np.array([[0, 45, -45, -45, 13.26, 19.47]])
- npt.assert_allclose(elevation_ref, sm1.get_elevation(sm2), atol=1e-2)
-
+ npt.assert_allclose(elevation_ref, sm1.get_elevation(sm2), atol=1e-2)
+
#######################################################################
sm3 = StationManager(2)
sm3.x = np.array([0, 30])
sm3.y = np.array([0, 0])
sm3.height = np.array([10, 10])
-
+
sm4 = StationManager(2)
- sm4.x = np.array([10, 10])
- sm4.y = np.array([ 0, 0])
+ sm4.x = np.array([10, 10])
+ sm4.y = np.array([0, 0])
sm4.height = np.array([10, 20])
-
+
elevation_ref = np.array([[0, 45], [0, 26.56]])
- npt.assert_allclose(elevation_ref, sm3.get_elevation(sm4), atol=1e-2)
+ npt.assert_allclose(elevation_ref, sm3.get_elevation(sm4), atol=1e-2)
+
if __name__ == '__main__':
unittest.main()
diff --git a/tests/test_topology_hotspot.py b/tests/test_topology_hotspot.py
index 3e6806950..d4c02ac20 100644
--- a/tests/test_topology_hotspot.py
+++ b/tests/test_topology_hotspot.py
@@ -7,14 +7,14 @@
import unittest
import numpy as np
-#import numpy.testing as npt
+# import numpy.testing as npt
-from sharc.parameters.parameters_hotspot import ParametersHotspot
+from sharc.parameters.imt.parameters_hotspot import ParametersHotspot
from sharc.topology.topology_hotspot import TopologyHotspot
+
class TopologyHotspotTest(unittest.TestCase):
-
-
+
def setUp(self):
# For this test case, hotspot parameters are useless because we are
# testing only the validation methods
@@ -26,25 +26,25 @@ def setUp(self):
intersite_distance = 1000
num_clusters = 1
- self.topology = TopologyHotspot(param, intersite_distance, num_clusters)
-
-
+ self.topology = TopologyHotspot(
+ param, intersite_distance, num_clusters)
+
def test_overlapping_hotspots(self):
candidate_x = np.array([300])
candidate_y = np.array([0])
candidate_azimuth = np.array([-180])
set_x = np.array([0, 200])
- set_y = np.array([0, 0])
+ set_y = np.array([0, 0])
set_azimuth = np.array([0, -180])
radius = 100
- self.assertFalse(self.topology.overlapping_hotspots(candidate_x,
- candidate_y,
- candidate_azimuth,
- set_x,
- set_y,
+ self.assertFalse(self.topology.overlapping_hotspots(candidate_x,
+ candidate_y,
+ candidate_azimuth,
+ set_x,
+ set_y,
set_azimuth,
radius))
-
+
candidate_x = np.array([0])
candidate_y = np.array([0])
candidate_azimuth = np.array([0])
@@ -52,45 +52,44 @@ def test_overlapping_hotspots(self):
set_y = np.array([150, 400])
set_azimuth = np.array([270, 270])
radius = 100
- self.assertTrue(self.topology.overlapping_hotspots(candidate_x,
- candidate_y,
- candidate_azimuth,
- set_x,
- set_y,
+ self.assertTrue(self.topology.overlapping_hotspots(candidate_x,
+ candidate_y,
+ candidate_azimuth,
+ set_x,
+ set_y,
set_azimuth,
radius))
-
+
candidate_x = np.array([0])
candidate_y = np.array([0])
candidate_azimuth = np.array([0])
- set_x = np.array([ -1, 101])
- set_y = np.array([ 0, 0])
+ set_x = np.array([-1, 101])
+ set_y = np.array([0, 0])
set_azimuth = np.array([180, 0])
radius = 100
- self.assertFalse(self.topology.overlapping_hotspots(candidate_x,
- candidate_y,
- candidate_azimuth,
- set_x,
- set_y,
+ self.assertFalse(self.topology.overlapping_hotspots(candidate_x,
+ candidate_y,
+ candidate_azimuth,
+ set_x,
+ set_y,
set_azimuth,
radius))
-
+
candidate_x = np.array([1])
candidate_y = np.array([0])
candidate_azimuth = np.array([0])
- set_x = np.array([ 0])
- set_y = np.array([ 1])
+ set_x = np.array([0])
+ set_y = np.array([1])
set_azimuth = np.array([90])
radius = 100
- self.assertTrue(self.topology.overlapping_hotspots(candidate_x,
- candidate_y,
- candidate_azimuth,
- set_x,
- set_y,
+ self.assertTrue(self.topology.overlapping_hotspots(candidate_x,
+ candidate_y,
+ candidate_azimuth,
+ set_x,
+ set_y,
set_azimuth,
radius))
-
-
-
+
+
if __name__ == '__main__':
- unittest.main()
\ No newline at end of file
+ unittest.main()
diff --git a/tests/test_topology_macrocell_.py b/tests/test_topology_macrocell_.py
index 659de69ca..06c4e12bb 100644
--- a/tests/test_topology_macrocell_.py
+++ b/tests/test_topology_macrocell_.py
@@ -11,11 +11,12 @@
from sharc.topology.topology_macrocell import TopologyMacrocell
+
class TopologyMacrocellTest(unittest.TestCase):
-
+
def setUp(self):
pass
-
+
def test_intersite_distance(self):
intersite_distance = 1000
num_clusters = 1
@@ -23,7 +24,7 @@ def test_intersite_distance(self):
topology.calculate_coordinates()
self.assertEqual(topology.intersite_distance, 1000)
self.assertAlmostEqual(topology.cell_radius, 666.66, places=1)
-
+
# when intersite distance changes, cell radius also changes
intersite_distance = 600
num_clusters = 1
@@ -31,7 +32,7 @@ def test_intersite_distance(self):
topology.calculate_coordinates()
self.assertEqual(topology.intersite_distance, 600)
self.assertEqual(topology.cell_radius, 400)
-
+
# let's change it one more time...
intersite_distance = 1500
num_clusters = 1
@@ -47,56 +48,56 @@ def test_num_clusters(self):
topology = TopologyMacrocell(intersite_distance, num_clusters)
topology.calculate_coordinates()
self.assertEqual(topology.num_clusters, 1)
-
+
# set to 7 clusters
intersite_distance = 1000
num_clusters = 7
topology = TopologyMacrocell(intersite_distance, num_clusters)
topology.calculate_coordinates()
self.assertEqual(topology.num_clusters, 7)
-
+
# set to any other value raises an exception
intersite_distance = 1000
num_clusters = 3
with self.assertRaises(ValueError):
topology = TopologyMacrocell(intersite_distance, num_clusters)
-
+
intersite_distance = 1000
num_clusters = 8
with self.assertRaises(ValueError):
topology = TopologyMacrocell(intersite_distance, num_clusters)
-
+
def test_coordinates(self):
"""
- TODO: test the case when number of clusters is 7
+ TODO: test the case when number of clusters is 7
"""
intersite_distance = 1000
num_clusters = 1
topology = TopologyMacrocell(intersite_distance, num_clusters)
topology.calculate_coordinates()
-
+
num_sites = 19
num_bs_per_site = 3
- num_bs = num_sites*num_bs_per_site
-
+ num_bs = num_sites * num_bs_per_site
+
# check the number of base stations
self.assertEqual(len(topology.x), num_bs)
self.assertEqual(len(topology.y), num_bs)
self.assertEqual(len(topology.azimuth), num_bs)
-
+
# check coordinates
- x_ref = np.repeat(np.array([0, 1000, 500, -500, -1000, -500,
- 500, 2000, 1500, 1000, 0, -1000,
- -1500, -2000, -1500, -1000, 0, 1000, 1500]), num_bs_per_site)
- y_ref = np.repeat(np.array([0, 0, 866.02, 866.02, 0, -866.02,
- -866.02, 0, 866.02, 1732.05, 1732.05, 1732.05,
- 866.02, 0, -866.02, -1732.05, -1732.05, -1732.05, -866.02]), num_bs_per_site)
+ x_ref = np.repeat(np.array([0, 1000, 500, -500, -1000, -500,
+ 500, 2000, 1500, 1000, 0, -1000,
+ -1500, -2000, -1500, -1000, 0, 1000, 1500]), num_bs_per_site)
+ y_ref = np.repeat(np.array([0, 0, 866.02, 866.02, 0, -866.02,
+ -866.02, 0, 866.02, 1732.05, 1732.05, 1732.05,
+ 866.02, 0, -866.02, -1732.05, -1732.05, -1732.05, -866.02]), num_bs_per_site)
az_ref = np.tile([60, 180, 300], num_sites)
-
+
npt.assert_allclose(topology.x, x_ref, atol=1e-2)
npt.assert_allclose(topology.y, y_ref, atol=1e-2)
npt.assert_allclose(topology.azimuth, az_ref, atol=1e-2)
-
+
# change intersite distance and check new cell radius and coordinates
intersite_distance = 500
num_clusters = 1
@@ -109,19 +110,18 @@ def test_coordinates(self):
self.assertEqual(len(topology.azimuth), num_bs)
# check coordinates
- x_ref = np.repeat(np.array([0, 500, 250, -250, -500, -250,
- 250, 1000, 750, 500, 0, -500,
- -750, -1000, -750, -500, 0, 500, 750]), num_bs_per_site)
- y_ref = np.repeat(np.array([0, 0, 433.01, 433.01, 0, -433.01,
- -433.01, 0, 433.01, 866.02, 866.02, 866.02,
- 433.01, 0, -433.01, -866.02, -866.02, -866.02, -433.01]), num_bs_per_site)
+ x_ref = np.repeat(np.array([0, 500, 250, -250, -500, -250,
+ 250, 1000, 750, 500, 0, -500,
+ -750, -1000, -750, -500, 0, 500, 750]), num_bs_per_site)
+ y_ref = np.repeat(np.array([0, 0, 433.01, 433.01, 0, -433.01,
+ -433.01, 0, 433.01, 866.02, 866.02, 866.02,
+ 433.01, 0, -433.01, -866.02, -866.02, -866.02, -433.01]), num_bs_per_site)
az_ref = np.tile([60, 180, 300], num_sites)
-
+
npt.assert_allclose(topology.x, x_ref, atol=1e-2)
npt.assert_allclose(topology.y, y_ref, atol=1e-2)
- npt.assert_allclose(topology.azimuth, az_ref, atol=1e-2)
+ npt.assert_allclose(topology.azimuth, az_ref, atol=1e-2)
+
-
if __name__ == '__main__':
unittest.main()
-
\ No newline at end of file
diff --git a/tests/test_topology_ntn.py b/tests/test_topology_ntn.py
new file mode 100644
index 000000000..0a09ecb36
--- /dev/null
+++ b/tests/test_topology_ntn.py
@@ -0,0 +1,171 @@
+"""
+Created on Tue Dec 28 21:41:00 2024
+
+@author: Vitor Borges
+"""
+
+import unittest
+import numpy as np
+import math
+from sharc.topology.topology_ntn import TopologyNTN
+
+
+class TopologyNTNTest(unittest.TestCase):
+
+ def setUp(self):
+ self.bs_height = 1000e3 # meters
+ self.bs_azimuth = 45 # degrees
+ self.bs_elevation = 45 # degrees
+ self.beamwidth = 10
+ denominator = math.tan(np.radians(self.beamwidth))
+ nominator = math.cos(np.radians(self.bs_elevation))
+ self.cell_radius = self.bs_height * denominator / nominator # meters
+ self.intersite_distance = self.cell_radius * np.sqrt(3) # meters
+
+ self.cos = lambda x: np.cos(np.radians(x))
+ self.sin = lambda x: np.sin(np.radians(x))
+ self.tan = lambda x: np.tan(np.radians(x))
+
+ def test_single_sector(self):
+ topology = TopologyNTN(
+ self.intersite_distance,
+ self.cell_radius,
+ self.bs_height,
+ self.bs_azimuth,
+ self.bs_elevation,
+ num_sectors=1)
+ topology.calculate_coordinates()
+ expected_x = expected_y = expected_z = [0]
+ self.assertListEqual(list(topology.x), expected_x)
+ self.assertListEqual(list(topology.y), expected_y)
+ self.assertListEqual(list(topology.z), expected_z)
+ expected_azimuth = [-135.0]
+ for actual_azi, expected_azi in zip(
+ topology.azimuth, expected_azimuth):
+ # cannot check asserListEqual because of float precision
+ self.assertAlmostEqual(actual_azi, expected_azi, places=3)
+ expected_elevation = [-45.0]
+ for expected_elev, actual_elev in zip(
+ topology.elevation, expected_elevation):
+ # cannot check asserListEqual because of float precision
+ self.assertAlmostEqual(actual_elev, expected_elev, places=3)
+
+ def test_seven_sectors(self):
+ topology = TopologyNTN(
+ self.intersite_distance,
+ self.cell_radius,
+ self.bs_height,
+ self.bs_azimuth,
+ self.bs_elevation,
+ num_sectors=7)
+ topology.calculate_coordinates()
+
+ d = self.intersite_distance
+
+ # defining expected x, y, z
+ expected_x = [0]
+ expected_x.extend([d * self.cos(30 + 60 * k) for k in range(6)])
+ expected_y = [0]
+ expected_y.extend([d * self.sin(30 + 60 * k) for k in range(6)])
+ expected_z = [0]
+ expected_z.extend([0 for _ in range(6)])
+
+ # testing expected x, y, z
+ for actual_x, expec_x in zip(topology.x, expected_x):
+ # cannot check asserListEqual because of float precision
+ self.assertAlmostEqual(actual_x, expec_x, places=3)
+ for actual_y, expec_y in zip(topology.y, expected_y):
+ # cannot check asserListEqual because of float precision
+ self.assertAlmostEqual(actual_y, expec_y, places=3)
+ self.assertListEqual(list(topology.z), expected_z)
+
+ # defining expected azimuth and elevation
+ space_x = np.repeat(topology.space_station_x, topology.num_sectors)
+ space_y = np.repeat(topology.space_station_y, topology.num_sectors)
+ space_z = np.repeat(topology.space_station_z, topology.num_sectors)
+ # using expected_x and expected_y so this test is independent of other
+ # tests
+ expected_azimuth = np.arctan2(
+ expected_y - space_y,
+ expected_x - space_x) * 180 / np.pi
+ expected_dist_xy = np.sqrt(
+ (expected_x - space_x)**2 + (expected_y - space_y)**2)
+ # using expected_z so this test is independent of other tests
+ expected_elevation = np.arctan2(
+ expected_z - space_z,
+ expected_dist_xy) * 180 / np.pi
+
+ # testing expected azimuth and elevation
+ for actual_azi, expected_azi in zip(
+ topology.azimuth, expected_azimuth):
+ # cannot check asserListEqual because of float precision
+ self.assertAlmostEqual(actual_azi, expected_azi, places=3)
+ for expected_elev, actual_elev in zip(
+ topology.elevation, expected_elevation):
+ # cannot check asserListEqual because of float precision
+ self.assertAlmostEqual(actual_elev, expected_elev, places=3)
+
+ def test_nineteen_sectors(self):
+ topology = TopologyNTN(
+ self.intersite_distance,
+ self.cell_radius,
+ self.bs_height,
+ self.bs_azimuth,
+ self.bs_elevation,
+ num_sectors=19)
+ topology.calculate_coordinates()
+
+ d = self.intersite_distance
+
+ # defining expected x, y, z
+ expected_x = [0]
+ expected_y = [0]
+ expected_x.extend([d * self.cos(30 + 60 * k) for k in range(6)])
+ expected_y.extend([d * self.sin(30 + 60 * k) for k in range(6)])
+ for k in range(6):
+ # already rotated 30 degrees
+ angle = 30 + k * 60
+ expected_x.append(2 * d * self.cos(angle))
+ expected_y.append(2 * d * self.sin(angle))
+ expected_x.append(d * self.cos(angle) + d * self.cos(angle + 60))
+ expected_y.append(d * self.sin(angle) + d * self.sin(angle + 60))
+ expected_z = [0 for _ in range(19)]
+
+ # testing expected x, y, z
+ for actual_x, expec_x in zip(topology.x, expected_x):
+ # cannot check asserListEqual because of float precision
+ self.assertAlmostEqual(actual_x, expec_x, places=3)
+ for actual_y, expec_y in zip(topology.y, expected_y):
+ # cannot check asserListEqual because of float precision
+ self.assertAlmostEqual(actual_y, expec_y, places=3)
+ self.assertListEqual(list(topology.z), expected_z)
+
+ # defining expected azimuth and elevation
+ space_x = np.repeat(topology.space_station_x, topology.num_sectors)
+ space_y = np.repeat(topology.space_station_y, topology.num_sectors)
+ space_z = np.repeat(topology.space_station_z, topology.num_sectors)
+ # using expected_x and expected_y so this test is independent of other
+ # tests
+ expected_azimuth = np.arctan2(
+ expected_y - space_y,
+ expected_x - space_x) * 180 / np.pi
+ expected_distance_xy = np.sqrt(
+ (expected_x - space_x)**2 + (expected_y - space_y)**2)
+ # using expected_z so this test is independent of other tests
+ expected_elevation = np.arctan2(
+ expected_z - space_z,
+ expected_distance_xy) * 180 / np.pi
+
+ # testing expected azimuth and elevation
+ for actual_azi, expected_azi in zip(
+ topology.azimuth, expected_azimuth):
+ # cannot check asserListEqual because of float precision
+ self.assertAlmostEqual(actual_azi, expected_azi, places=3)
+ for expected_elev, actual_elev in zip(
+ topology.elevation, expected_elevation):
+ # cannot check asserListEqual because of float precision
+ self.assertAlmostEqual(actual_elev, expected_elev, places=3)
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/tests/test_topology_single_base_station.py b/tests/test_topology_single_base_station.py
index 0fdd6fd88..8dd228ec8 100644
--- a/tests/test_topology_single_base_station.py
+++ b/tests/test_topology_single_base_station.py
@@ -11,11 +11,12 @@
from sharc.topology.topology_single_base_station import TopologySingleBaseStation
+
class TopologySingleBaseStationTest(unittest.TestCase):
-
+
def setUp(self):
pass
-
+
def test_coordinates(self):
cell_radius = 1500
num_clusters = 1
@@ -28,17 +29,16 @@ def test_coordinates(self):
num_clusters = 2
topology = TopologySingleBaseStation(cell_radius, num_clusters)
topology.calculate_coordinates()
- npt.assert_equal(topology.x, np.array([0, 2*cell_radius]))
+ npt.assert_equal(topology.x, np.array([0, 2 * cell_radius]))
npt.assert_equal(topology.y, np.array([0, 0]))
-
def test_num_clusters(self):
cell_radius = 1500
num_clusters = 1
topology = TopologySingleBaseStation(cell_radius, num_clusters)
topology.calculate_coordinates()
self.assertEqual(topology.num_clusters, 1)
-
+
cell_radius = 1500
num_clusters = 2
topology = TopologySingleBaseStation(cell_radius, num_clusters)
@@ -49,7 +49,6 @@ def test_num_clusters(self):
num_clusters = 3
with self.assertRaises(ValueError):
topology = TopologySingleBaseStation(cell_radius, num_clusters)
-
def test_intersite_distance(self):
cell_radius = 1500
@@ -57,42 +56,39 @@ def test_intersite_distance(self):
topology = TopologySingleBaseStation(cell_radius, num_clusters)
topology.calculate_coordinates()
self.assertEqual(topology.intersite_distance, 3000)
-
+
cell_radius = 1000
num_clusters = 1
topology = TopologySingleBaseStation(cell_radius, num_clusters)
topology.calculate_coordinates()
self.assertEqual(topology.intersite_distance, 2000)
-
def test_cell_radius(self):
cell_radius = 1500
num_clusters = 1
topology = TopologySingleBaseStation(cell_radius, num_clusters)
topology.calculate_coordinates()
self.assertEqual(topology.cell_radius, 1500)
-
+
cell_radius = 1000
num_clusters = 1
topology = TopologySingleBaseStation(cell_radius, num_clusters)
topology.calculate_coordinates()
self.assertEqual(topology.cell_radius, 1000)
-
-
+
def test_azimuth(self):
cell_radius = 1500
num_clusters = 1
topology = TopologySingleBaseStation(cell_radius, num_clusters)
topology.calculate_coordinates()
self.assertEqual(topology.azimuth, 0)
-
+
cell_radius = 1000
num_clusters = 2
topology = TopologySingleBaseStation(cell_radius, num_clusters)
topology.calculate_coordinates()
npt.assert_equal(topology.azimuth, np.array([0, 180]))
-
-
+
if __name__ == '__main__':
- unittest.main()
\ No newline at end of file
+ unittest.main()
diff --git a/tox.yaml b/tox.yaml
new file mode 100644
index 000000000..46abcda43
--- /dev/null
+++ b/tox.yaml
@@ -0,0 +1,9 @@
+tox:
+ envlist : py26, py27, py33, py34, py35, flake8
+testenv:flake8:
+ basepython :python
+ deps :flake8
+ commands :flake8 sharc
+testenv:
+ PYTHONPATH : {toxinidir}:{toxinidir}/sharc
+ py.test --basetemp :{envtmpdir}
[…] earlier. It’s the result of a conversion of a polygon shapefile of country boundaries (from Natural Earth, a fantastic, public domain, physical/cultural spatial data source) to a raster data […]
+ + +[…] Le mappe sono scaricate da https://www.naturalearthdata.com […]
+ + +[…] Le mappe sono scaricate da https://www.naturalearthdata.com […]
+ + +