Exemple #1
0
    def __init__(self,
                 arguments,
                 origin,
                 size,
                 snap_inside=False,
                 number_of_links=0):
        """
        Initialize the weight matrix object.

        The `arguments` is an `Arguments` object. The `origin` is a tuple of two
        coordinates in `(x, y)` form of the bottom left point of the network.
        `size` is a tuple of the same form, containing the width and height of
        the network.

        If `snap_inside` is `True`, then sensor locations inside the network are
        allowed, but snapped to the network boundary. Otherwise, they are
        silently excluded. If `number_of_links` is not `0`, then the weight
        matrix is prefilled with this number of rows, which may be useful in
        contexts where we know the number of measurements beforehand.
        """

        if isinstance(arguments, Arguments):
            settings = arguments.get_settings("reconstruction")
        else:
            raise TypeError("'arguments' must be an instance of Arguments")

        # Create the model object.
        import_manager = Import_Manager()
        model_class = settings.get("model_class")
        model_type = import_manager.load_class(
            model_class, relative_module="reconstruction")
        self._model = model_type(arguments)

        # Initialize variables for the matrix.
        self._distances = None
        self._matrix = None

        # Retrieve parameters.
        self._origin = origin
        self._width, self._height = size
        self._number_of_links = number_of_links

        # Create the snap to boundary object.
        self._snapper = Snap_To_Boundary(self._origin,
                                         self._width,
                                         self._height,
                                         snap_inside=snap_inside)

        # Create a grid for the space covered by the network. This represents a pixel
        # grid that we use to determine which pixels are intersected by a link. The
        # value 0.5 is used to obtain the center of each pixel.
        offset_x, offset_y = self._origin
        x = np.linspace(offset_x + 0.5, offset_x + self._width - 0.5,
                        self._width)
        y = np.linspace(offset_y + 0.5, offset_y + self._height - 0.5,
                        self._height)
        self._grid_x, self._grid_y = np.meshgrid(x, y)

        self.reset()
    def __init__(self, arguments, origin, size, snap_inside=False,
                 number_of_links=0):
        """
        Initialize the weight matrix object.

        The `arguments` is an `Arguments` object. The `origin` is a tuple of two
        coordinates in `(x, y)` form of the bottom left point of the network.
        `size` is a tuple of the same form, containing the width and height of
        the network.

        If `snap_inside` is `True`, then sensor locations inside the network are
        allowed, but snapped to the network boundary. Otherwise, they are
        silently excluded. If `number_of_links` is not `0`, then the weight
        matrix is prefilled with this number of rows, which may be useful in
        contexts where we know the number of measurements beforehand.
        """

        if isinstance(arguments, Arguments):
            settings = arguments.get_settings("reconstruction")
        else:
            raise TypeError("'arguments' must be an instance of Arguments")

        # Create the model object.
        import_manager = Import_Manager()
        model_class = settings.get("model_class")
        model_type = import_manager.load_class(model_class,
                                               relative_module="reconstruction")
        self._model = model_type(arguments)

        # Initialize variables for the matrix.
        self._distances = None
        self._matrix = None

        # Retrieve parameters.
        self._origin = origin
        self._width, self._height = size
        self._number_of_links = number_of_links

        # Create the snap to boundary object.
        self._snapper = Snap_To_Boundary(self._origin, self._width,
                                         self._height, snap_inside=snap_inside)

        # Create a grid for the space covered by the network. This represents a pixel
        # grid that we use to determine which pixels are intersected by a link. The
        # value 0.5 is used to obtain the center of each pixel.
        offset_x, offset_y = self._origin
        x = np.linspace(offset_x + 0.5, offset_x + self._width - 0.5, self._width)
        y = np.linspace(offset_y + 0.5, offset_y + self._height - 0.5, self._height)
        self._grid_x, self._grid_y = np.meshgrid(x, y)

        self.reset()
Exemple #3
0
class Weight_Matrix(object):
    def __init__(self,
                 arguments,
                 origin,
                 size,
                 snap_inside=False,
                 number_of_links=0):
        """
        Initialize the weight matrix object.

        The `arguments` is an `Arguments` object. The `origin` is a tuple of two
        coordinates in `(x, y)` form of the bottom left point of the network.
        `size` is a tuple of the same form, containing the width and height of
        the network.

        If `snap_inside` is `True`, then sensor locations inside the network are
        allowed, but snapped to the network boundary. Otherwise, they are
        silently excluded. If `number_of_links` is not `0`, then the weight
        matrix is prefilled with this number of rows, which may be useful in
        contexts where we know the number of measurements beforehand.
        """

        if isinstance(arguments, Arguments):
            settings = arguments.get_settings("reconstruction")
        else:
            raise TypeError("'arguments' must be an instance of Arguments")

        # Create the model object.
        import_manager = Import_Manager()
        model_class = settings.get("model_class")
        model_type = import_manager.load_class(
            model_class, relative_module="reconstruction")
        self._model = model_type(arguments)

        # Initialize variables for the matrix.
        self._distances = None
        self._matrix = None

        # Retrieve parameters.
        self._origin = origin
        self._width, self._height = size
        self._number_of_links = number_of_links

        # Create the snap to boundary object.
        self._snapper = Snap_To_Boundary(self._origin,
                                         self._width,
                                         self._height,
                                         snap_inside=snap_inside)

        # Create a grid for the space covered by the network. This represents a pixel
        # grid that we use to determine which pixels are intersected by a link. The
        # value 0.5 is used to obtain the center of each pixel.
        offset_x, offset_y = self._origin
        x = np.linspace(offset_x + 0.5, offset_x + self._width - 0.5,
                        self._width)
        y = np.linspace(offset_y + 0.5, offset_y + self._height - 0.5,
                        self._height)
        self._grid_x, self._grid_y = np.meshgrid(x, y)

        self.reset()

    def is_valid_point(self, point):
        """
        Check whether a given `point` is a valid sensor position, i.e., it is
        outside the network.
        """

        return self._snapper.is_outside(Point(point[0], point[1]))

    def update(self, source, destination):
        """
        Update the weight matrix with a measurement between a `source` and
        `destination` sensor, both given as a tuple of coordinates.
        Each successful update adds a new row to the matrix.
        This method returns a list of coordinate tuples for the two sensors
        in case the update was successful. Otherwise, `None` is returned.

        Refer to the following papers for the principles or code
        that this method is based on:
        - "Radio tomographic imaging with wireless networks" by
          Joey Wilson and Neal Patwari
        - "Algorithms and models for radio tomographic imaging"
          by Alyssa Milburn
        """

        # Snap the source and destination points to the boundaries of the network.
        snapped_points = self._snapper.execute(source, destination)
        if snapped_points is None:
            # If the points cannot be snapped, ignore the measurement.
            return None

        source, destination = snapped_points

        # Get the index of the source sensor. Add it if it does not exist.
        new_sensors = []
        try:
            source_index = self._sensors[source]
        except KeyError:
            source_index = len(self._sensors)
            self._sensors[source] = source_index
            new_sensors.append(source)

        # Get the index of the destination sensor. Add it if it does not exist.
        try:
            destination_index = self._sensors[destination]
        except KeyError:
            destination_index = len(self._sensors)
            self._sensors[destination] = destination_index
            new_sensors.append(destination)

        # Calculate the distance from a sensor to each center of a pixel on the
        # grid using the Pythagorean theorem. Do this only for new sensors.
        for sensor in new_sensors:
            distance = np.sqrt((self._grid_x - sensor[0])**2 +
                               (self._grid_y - sensor[1])**2)
            if self._distance_count >= self._number_of_links:
                self._distances = np.vstack(
                    [self._distances, distance.flatten()])
            else:
                self._distances[self._distance_count, :] = distance.flatten()

            self._distance_count += 1

        # Update the weight matrix by adding a row for the new link. We use the
        # Pythagorean theorem for calculation of the link's length. The weight matrix
        # contains the weight of each pixel on the grid for each link. An ellipse
        # model is applied to determine which pixels have an influence on the measured
        # signal strength of a link. Pixels that have no influence have a weight of
        # zero. A higher weight implies a higher influence on the signal strength.
        # Pixels of short links have a higher weight than those of longer links.
        length = np.sqrt((destination[0] - source[0])**2 +
                         (destination[1] - source[1])**2)
        if length == 0:
            # Source and destination are equal, which might happen after
            # snapping the points to the boundaries.
            return None

        row = self._model.assign(length, self._distances[source_index],
                                 self._distances[destination_index])
        if self._link_count >= self._number_of_links:
            self._matrix = np.vstack([self._matrix, row])
        else:
            self._matrix[self._link_count, :] = row

        self._link_count += 1

        return snapped_points

    def check(self):
        """
        Check if the weight matrix is complete, i.e., if the columns of the
        matrix all contain at least one non-zero entry.
        """

        return all(self._matrix.any(axis=0))

    def output(self):
        """
        Output the weight matrix.
        """

        return self._matrix

    def reset(self):
        """
        Reset the weight matrix object to its default state.
        """

        self._link_count = 0
        self._distance_count = 0
        self._matrix = np.empty(
            (self._number_of_links, self._width * self._height))
        self._distances = np.empty(
            (self._number_of_links, self._width * self._height))
        self._sensors = {}
class Weight_Matrix(object):
    def __init__(self, arguments, origin, size, snap_inside=False,
                 number_of_links=0):
        """
        Initialize the weight matrix object.

        The `arguments` is an `Arguments` object. The `origin` is a tuple of two
        coordinates in `(x, y)` form of the bottom left point of the network.
        `size` is a tuple of the same form, containing the width and height of
        the network.

        If `snap_inside` is `True`, then sensor locations inside the network are
        allowed, but snapped to the network boundary. Otherwise, they are
        silently excluded. If `number_of_links` is not `0`, then the weight
        matrix is prefilled with this number of rows, which may be useful in
        contexts where we know the number of measurements beforehand.
        """

        if isinstance(arguments, Arguments):
            settings = arguments.get_settings("reconstruction")
        else:
            raise TypeError("'arguments' must be an instance of Arguments")

        # Create the model object.
        import_manager = Import_Manager()
        model_class = settings.get("model_class")
        model_type = import_manager.load_class(model_class,
                                               relative_module="reconstruction")
        self._model = model_type(arguments)

        # Initialize variables for the matrix.
        self._distances = None
        self._matrix = None

        # Retrieve parameters.
        self._origin = origin
        self._width, self._height = size
        self._number_of_links = number_of_links

        # Create the snap to boundary object.
        self._snapper = Snap_To_Boundary(self._origin, self._width,
                                         self._height, snap_inside=snap_inside)

        # Create a grid for the space covered by the network. This represents a pixel
        # grid that we use to determine which pixels are intersected by a link. The
        # value 0.5 is used to obtain the center of each pixel.
        offset_x, offset_y = self._origin
        x = np.linspace(offset_x + 0.5, offset_x + self._width - 0.5, self._width)
        y = np.linspace(offset_y + 0.5, offset_y + self._height - 0.5, self._height)
        self._grid_x, self._grid_y = np.meshgrid(x, y)

        self.reset()

    def is_valid_point(self, point):
        """
        Check whether a given `point` is a valid sensor position, i.e., it is
        outside the network.
        """

        return self._snapper.is_outside(Point(point[0], point[1]))

    def update(self, source, destination):
        """
        Update the weight matrix with a measurement between a `source` and
        `destination` sensor, both given as a tuple of coordinates.
        Each successful update adds a new row to the matrix.
        This method returns a list of coordinate tuples for the two sensors
        in case the update was successful. Otherwise, `None` is returned.

        Refer to the following papers for the principles or code
        that this method is based on:
        - "Radio tomographic imaging with wireless networks" by
          Joey Wilson and Neal Patwari
        - "Algorithms and models for radio tomographic imaging"
          by Alyssa Milburn
        """

        # Snap the source and destination points to the boundaries of the network.
        snapped_points = self._snapper.execute(source, destination)
        if snapped_points is None:
            # If the points cannot be snapped, ignore the measurement.
            return None

        source, destination = snapped_points

        # Get the index of the source sensor. Add it if it does not exist.
        new_sensors = []
        try:
            source_index = self._sensors[source]
        except KeyError:
            source_index = len(self._sensors)
            self._sensors[source] = source_index
            new_sensors.append(source)

        # Get the index of the destination sensor. Add it if it does not exist.
        try:
            destination_index = self._sensors[destination]
        except KeyError:
            destination_index = len(self._sensors)
            self._sensors[destination] = destination_index
            new_sensors.append(destination)

        # Calculate the distance from a sensor to each center of a pixel on the
        # grid using the Pythagorean theorem. Do this only for new sensors.
        for sensor in new_sensors:
            distance = np.sqrt((self._grid_x - sensor[0]) ** 2 + (self._grid_y - sensor[1]) ** 2)
            if self._distance_count >= self._number_of_links:
                self._distances = np.vstack([self._distances, distance.flatten()])
            else:
                self._distances[self._distance_count, :] = distance.flatten()

            self._distance_count += 1

        # Update the weight matrix by adding a row for the new link. We use the
        # Pythagorean theorem for calculation of the link's length. The weight matrix
        # contains the weight of each pixel on the grid for each link. An ellipse
        # model is applied to determine which pixels have an influence on the measured
        # signal strength of a link. Pixels that have no influence have a weight of
        # zero. A higher weight implies a higher influence on the signal strength.
        # Pixels of short links have a higher weight than those of longer links.
        length = np.sqrt((destination[0] - source[0]) ** 2 + (destination[1] - source[1]) ** 2)
        if length == 0:
            # Source and destination are equal, which might happen after
            # snapping the points to the boundaries.
            return None

        row = self._model.assign(length, self._distances[source_index],
                                 self._distances[destination_index])
        if self._link_count >= self._number_of_links:
            self._matrix = np.vstack([self._matrix, row])
        else:
            self._matrix[self._link_count, :] = row

        self._link_count += 1

        return snapped_points

    def check(self):
        """
        Check if the weight matrix is complete, i.e., if the columns of the
        matrix all contain at least one non-zero entry.
        """

        return all(self._matrix.any(axis=0))

    def output(self):
        """
        Output the weight matrix.
        """

        return self._matrix

    def reset(self):
        """
        Reset the weight matrix object to its default state.
        """

        self._link_count = 0
        self._distance_count = 0
        self._matrix = np.empty((self._number_of_links, self._width * self._height))
        self._distances = np.empty((self._number_of_links, self._width * self._height))
        self._sensors = {}