def _idw_interpolate(sensor_data, target_grid_len):
     '''
     Args:
         sensor_data -- np.2darray -- Rx data from a single Tx
         target_grid_len -- int -- the target grid length for the Rx
     Return:
         np.1darray -- interpolated, shape = target_grid_len**2
     '''
     pre_gl = len(sensor_data)
     factor = int(target_grid_len / pre_gl)
     interpolate = np.zeros((target_grid_len, target_grid_len))
     for new_x in range(target_grid_len):
         for new_y in range(target_grid_len):
             if new_x % factor == 0 and new_y % factor == 0 and sensor_data[
                     new_x // factor][
                         new_y // factor] != 0:  # don't need to interpolate
                 interpolate[new_x][new_y] = sensor_data[new_x //
                                                         factor][new_y //
                                                                 factor]
             else:
                 v_x, v_y = new_x / factor, new_y / factor  # virtual point in the coarse grid
                 points = []  # pick some points from the coarse grid
                 edge = int(8 / factor)
                 for pre_x in range(math.floor(v_x - edge),
                                    math.ceil(v_x + 1) + edge):
                     if pre_x < 0 or pre_x >= pre_gl:  # the x range
                         continue
                     for pre_y in range(math.floor(v_y - edge),
                                        math.ceil(v_y + 1) + edge):
                         if pre_y >= 0 and pre_y < pre_gl and sensor_data[
                                 pre_x][pre_y] != 0:
                             points.append((pre_x, pre_y,
                                            distance((v_x, v_y),
                                                     (pre_x, pre_y))))
                 points = sorted(points,
                                 key=lambda tup: tup[2])  # sort by distance
                 threshold = min(MultiIntepolate.NEIGHBOUR_NUM, len(points))
                 weights = np.zeros(threshold)
                 for i in range(threshold):
                     point = points[i]
                     dist = distance((v_x, v_y), point)
                     weights[i] = (
                         1. / dist
                     )**2  # inverse weighted distance or inverse weighted square
                 weights /= np.sum(weights)  # normalize them
                 idw = 0
                 for i in range(threshold):
                     w = weights[i]
                     pre_rss = sensor_data[points[i][0]][points[i][1]]
                     idw += w * pre_rss
                 interpolate[new_x][new_y] = idw
     return interpolate.reshape(target_grid_len * target_grid_len)
Beispiel #2
0
def _interpolate_idw(pre_inter, factor):
    '''Fix one transmitters, interpolate the sensors
    Args:
        pre_inter -- np.1darray -- pre interpolated, shape = pre_gl*pre_gl
        factor    -- int
    Return:
        np.1darray -- interpolated, shape = gre_gl*gre_gl*factor*factor
    '''
    pre_gl = int(math.sqrt(
        len(pre_inter)))  # previous grid length (coarse grid)
    pre_inter = pre_inter.reshape((pre_gl, pre_gl))
    new_gl = pre_gl * factor  # new grid length (find grid)
    inter = np.zeros((new_gl, new_gl))
    for new_x in range(new_gl):
        for new_y in range(new_gl):
            if new_x % factor == 0 and new_y % factor == 0:  # don't need to interpolate
                inter[new_x][new_y] = pre_inter[new_x // factor][new_y //
                                                                 factor]
            else:
                v_x, v_y = float(new_x) / factor, float(
                    new_y
                ) / factor  # virtual point in the coarse grid / real point in the fine grid
                # pick some close points from the coarse grid
                points = []
                for pre_x in range(math.floor(v_x - 1),
                                   math.ceil(v_x + 1) + 1):
                    for pre_y in range(math.floor(v_y - 1),
                                       math.ceil(v_y + 1) + 1):
                        if pre_x >= 0 and pre_x < pre_gl and pre_y >= 0 and pre_y < pre_gl:
                            points.append((pre_x, pre_y,
                                           distance((v_x, v_y),
                                                    (pre_x, pre_y))))
                points = sorted(points,
                                key=lambda tup: tup[2])  # sort by distance
                threshold = min(NEIGHBOR_NUM, len(points))
                weights = np.zeros(threshold)
                for i in range(threshold):
                    point = points[i]
                    dist = distance((v_x, v_y), point)
                    weights[i] = (
                        1. / dist
                    )**2  # inverse weighted distance or inverse weighted square
                weights /= np.sum(weights)  # normalize them
                idw = 0
                for i in range(threshold):
                    w = weights[i]
                    pre_rss = pre_inter[points[i][0]][points[i][1]]
                    idw += w * pre_rss
                inter[new_x][new_y] = idw
    return inter.reshape(new_gl * new_gl)
Beispiel #3
0
 def get_log10_weight(to_tx_dists, tx, rx0):
     '''get the weights from project_dists
     Args:
         project_dists  -- np.1darray
         tx -- (float, float)
         rx0 -- (float, float)  -- location to be interpolated
     Return:
         np.1darray
     '''
     for i, dist in enumerate(to_tx_dists):
         if dist == 0:
             to_tx_dists[
                 i] = IpsnInterpolate.ILDW_DIST  # this value can tweak
     log10_dist_to_tx = np.log10(to_tx_dists)
     reference_dist = np.log10(distance(tx, rx0))
     log10_dist_to_rx0 = log10_dist_to_tx - reference_dist
     log10_dist_to_rx0 = np.absolute(log10_dist_to_rx0)
     weight = np.zeros(len(log10_dist_to_rx0))
     for i, dist in enumerate(log10_dist_to_rx0):
         if dist > 0:
             weight[i] = (1. / dist)
     maxx = max(weight)
     for i, w in enumerate(weight):
         if w == 0:
             weight[i] = 2 * maxx if maxx > 0 else 1
     return weight
Beispiel #4
0
 def find_d0_pd0(self, num=4):
     '''find some largest RSS, average them as the P(d0) and d0
     Args:
         num (int): 
     '''
     means = []
     dic = defaultdict(list)
     for i in range(len(self.locations)):
         for j in range(len(self.locations)):
             if i == j:
                 continue
             dist = distance(self.locations[i], self.locations[j])
             dic[dist].append((i, j, self.means[i, j]))
             means.append(self.means[i][j])
     # X, Y = [], []
     threshold = sorted(np.array(means))[-num]
     d0, pd0 = [], []
     for key, vals in sorted(
             dic.items()):  # distance --> [ (loc1, loc2) ...]
         for val in vals:
             i, j, mean = val
             if mean >= threshold:
                 d0.append(key)
                 pd0.append(mean)
                 if len(d0) == num:
                     return np.array(d0).mean(), np.array(pd0).mean()
Beispiel #5
0
 def _ildw(self, tx_data, tx_1dindex):
     '''Interpolate one Tx
     Args:
         tx_data -- np.1darray  -- contains zeros values
     Return:
         tx_data -- np.1darray  -- the zero values are filled up
     '''
     tx = (tx_1dindex // self.full_grid_len, tx_1dindex % self.full_grid_len
           )  # ildw requires the location of the transmitter
     grid_pathloss = tx_data.reshape(self.full_grid_len, self.full_grid_len)
     grid_interpolate = np.copy(grid_pathloss)
     # find the zero elements and impute them
     for x in range(grid_pathloss.shape[0]):
         for y in range(grid_pathloss.shape[1]):
             if grid_pathloss[x][
                     y] != 0.0:  # skip the ones that don't need to interpolate
                 continue
             points = []
             d = self.range
             for i in range(x - d, x + d + 1):
                 for j in range(y - d, y + d + 1):
                     if i < 0 or i >= grid_pathloss.shape[
                             0] or j < 0 or j >= grid_pathloss.shape[1]:
                         continue
                     if grid_pathloss[i][
                             j] == 0.0:  # only use the known point to interpolate
                         continue
                     dist = distance((x, y), (i, j))
                     points.append((i, j, dist))
             points = sorted(points, key=lambda tup: tup[2])
             threshold = min(IpsnInterpolate.NEIGHBOR_NUM, len(points))
             weights = np.zeros(threshold)
             dist_to_tx = np.zeros(threshold)
             for i in range(threshold):
                 nei = (points[i][0], points[i][1])
                 dist_to_tx[i] = distance(tx, nei)
             rx0 = (x, y)
             weights = IpsnInterpolate.get_log10_weight(dist_to_tx, tx, rx0)
             weights /= np.sum(weights)
             idw_pathloss = 0
             for i in range(threshold):
                 w = weights[i]
                 rss = grid_pathloss[points[i][0]][points[i][1]]
                 idw_pathloss += w * rss
             grid_interpolate[x][y] = idw_pathloss
     return grid_interpolate.reshape(self.full_grid_len *
                                     self.full_grid_len)
    def combine_sensor_data(self):
        '''Combine sensor data from multiply granularity. each granularity has full data in 1 dimension (from the SPLAT!)
        '''
        grid_lens = sorted(TxMultiGran.RX_CELL_LEN.keys())  # [5, 10, 20]

        if len(grid_lens) != len(Global.GRAN_LEVEL):
            print((self.x, self.y),
                  'length of grid_lens and granularity level doesn\'t match !')
            return

        # map granularity level to grid length         # {1200 --> 5, 400 --> 10, 0 --> 20}
        gran_level2grid_len = {}
        for gran_level, grid_len in zip(reversed(Global.GRAN_LEVEL),
                                        grid_lens):
            gran_level2grid_len[gran_level] = grid_len

        # map grid length to ratio. the ratio of finest_rx_grid_len to different grid_len
        finest_rx_grid_len = grid_lens[-1]
        grid_len2ratio = {}
        for grid_len in grid_lens:
            grid_len2ratio[grid_len] = int(
                finest_rx_grid_len / grid_len)  # {5 --> 4, 10 --> 2, 20 --> 1}

        self.sensor_data = np.zeros(
            (finest_rx_grid_len, finest_rx_grid_len))  # fill up this array

        t_x = self.x * grid_len2ratio[TxMultiGran.TX_GRID_LEN]
        t_y = self.y * grid_len2ratio[TxMultiGran.TX_GRID_LEN]
        for x in range(finest_rx_grid_len):
            for y in range(finest_rx_grid_len):
                dist = distance((x, y), (t_x, t_y)) * TxMultiGran.RX_CELL_LEN[
                    finest_rx_grid_len]  # distance in meters
                gran_level = self.get_gran_level(Global.GRAN_LEVEL, dist)
                grid_len = gran_level2grid_len[gran_level]
                ratio = grid_len2ratio[grid_len]
                if x % ratio == 0 and y % ratio == 0:  # granularity control by this ratio
                    if TxMultiGran.TX_GRID_LEN == grid_lens[0]:
                        # when the Tx granularity equals to the lowest Rx granularity
                        gran_data = self.granularity_data[grid_len]
                        gran_grid_len = int(math.sqrt(len(gran_data)))
                        index = x // ratio * gran_grid_len + y // ratio
                        self.sensor_data[x][y] = gran_data[index]
                    else:
                        # when the Tx granularity not equal to the lowest Rx granularity, only use the finest granularity
                        gran_data = self.granularity_data[finest_rx_grid_len]
                        gran_grid_len = int(math.sqrt(len(gran_data)))
                        index = x * gran_grid_len + y
                        self.sensor_data[x][y] = gran_data[index]

        if self.debug:
            num_wireless_link = np.count_nonzero(self.sensor_data)
            TxMultiGran.NUM_WIRELESS_LINK += num_wireless_link
            print('Tx = ({}, {})'.format(self.x, self.y),
                  '; number of wireless links to sensors', num_wireless_link,
                  '; Total = {}'.format(TxMultiGran.NUM_WIRELESS_LINK))
Beispiel #7
0
 def predict(self, tx, rx):
     '''Predice the receiver's RSS at rx, when the transmitter is at tx
     Args:
         tx (tuple(float, float))
         rx (tuple(float, float))
     '''
     dist = distance(tx, rx)
     tx = Point(tx[0], tx[1])
     rx = Point(rx[0], rx[1])
     nW = self.wall.count_intersect(tx, rx)
     nW = nW if nW <= self.C else self.C
     # offset = 0
     # if dist < 2 and nW == 0:
     #     offset = 6.37
     return self.p_d0 - 10 * self.n * math.log10(
         dist / self.d0) - nW * self.waf + self.intercept
Beispiel #8
0
    def compute_errors(self, inter_data, dist_close, dist_far):
        '''Compute the interpolation errors
        Args:
            inter_data  -- np.2darray
            dist_close  -- int
            dist_far    -- int -- distance threshold between tx and rx
            coarse_gran -- int
        '''
        grid_is_inter = np.zeros(
            (self.full_grid_len, self.full_grid_len)
        )  # the places for sensors in coarse grid, no interpolation happening
        for x in self.index:
            for y in self.index:
                grid_is_inter[x, y] = 1.
        size = len(inter_data)
        errors_all = []  # errors for all tx-rx
        errors_close = []  # errors for tx-rx with small distance
        errors_far = []  # errors for tx-rx with large distance
        for i in range(size):
            tx = (i // self.full_grid_len, i % self.full_grid_len)
            for j in range(size):
                rx = (j // self.full_grid_len, j % self.full_grid_len)
                if grid_is_inter[rx[0]][rx[1]] == 1. or i == j:
                    continue
                error = inter_data[i][j] - self.full_data[i][j]
                dist = distance(tx, rx)
                if dist < dist_close:
                    errors_close.append(error)
                elif dist > dist_far:
                    errors_far.append(error)
                errors_all.append(error)
        mean_error = np.mean(errors_all)
        mean_absolute_error = np.mean(np.absolute(errors_all))
        mean_error_close = np.mean(errors_close)
        mean_absolute_error_close = np.mean(np.absolute(errors_close))
        mean_error_far = np.mean(errors_far)
        mean_absolute_error_far = np.mean(np.absolute(errors_far))
        std = np.std(np.absolute(errors_all))
        std_close = np.std(np.absolute(errors_close))
        std_far = np.std(np.absolute(errors_far))

        return Output(None, mean_error, mean_absolute_error, mean_error_close, mean_absolute_error_close, \
                      mean_error_far, mean_absolute_error_far, std, std_close, std_far)
Beispiel #9
0
 def _idw(self, tx_data):
     '''Interpolate one Tx
     Args:
         tx_data -- np.1darray  -- contains zeros values
     Return:
         tx_data -- np.1darray  -- the zero values are filled up
     '''
     grid_pathloss = tx_data.reshape(self.full_grid_len, self.full_grid_len)
     grid_interpolate = np.copy(grid_pathloss)
     # find the zero elements and impute them
     for x in range(grid_pathloss.shape[0]):
         for y in range(grid_pathloss.shape[1]):
             if grid_pathloss[x][
                     y] != 0.0:  # skip the ones that don't need to interpolate
                 continue
             points = []
             d = self.range
             for i in range(x - d, x + d + 1):
                 for j in range(y - d, y + d + 1):
                     if i < 0 or i >= grid_pathloss.shape[
                             0] or j < 0 or j >= grid_pathloss.shape[1]:
                         continue
                     if grid_pathloss[i][
                             j] == 0.0:  # only use the known point to interpolate
                         continue
                     dist = distance((x, y), (i, j))
                     points.append((i, j, dist))
             points = sorted(points, key=lambda tup: tup[2])
             threshold = min(IpsnInterpolate.NEIGHBOR_NUM, len(points))
             weights = np.zeros(threshold)
             for i in range(threshold):
                 dist = points[i][2]
                 weights[i] = (1. / dist)**IpsnInterpolate.IDW_EXPONENT
             weights /= np.sum(weights)
             idw_pathloss = 0
             for i in range(threshold):
                 w = weights[i]
                 rss = grid_pathloss[points[i][0]][points[i][1]]
                 idw_pathloss += w * rss
             grid_interpolate[x][y] = idw_pathloss
     return grid_interpolate.reshape(self.full_grid_len *
                                     self.full_grid_len)
Beispiel #10
0
def main0():
    '''Read the Utah data, location transform
    '''
    means, stds, locations, wall = read_utah_data(path='dataUtah')

    lt = LocationTransform(locations, cell_len=1)

    print(means)
    print(stds)
    print(locations)
    print(wall)
    print(lt)

    errors = []
    for real_loc in lt.real_location:
        gridcell = lt.real_2_gridcell(real_loc)
        real_loc2 = lt.gridcell_2_real(gridcell)
        error = distance(real_loc, real_loc2)
        errors.append(error)
        print('({:5.2f}, {:5.2f}) -> ({:2d}, {:2d}) -> ({:5.2f}, {:5.2f}); error = {:3.2f}'.format(real_loc[0], real_loc[1], gridcell[0], gridcell[1], real_loc2[0], real_loc2[1], error))
    plot_cdf(errors)
Beispiel #11
0
    def regresssion_n_waf(self):
        '''Do a regression to get the n and waf
        '''
        X, y = [], []
        for i in range(len(self.locations)):
            for j in range(len(self.locations)):
                if i == j:
                    continue
                dist = distance(self.locations[i], self.locations[j])
                tx = Point(self.locations[i][0], self.locations[i][1])
                rx = Point(self.locations[j][0], self.locations[j][1])
                nW = self.wall.count_intersect(tx, rx)
                nW = nW if nW <= self.C else self.C
                y.append(self.means[i][j] - self.p_d0)
                # y.append(self.means[i][j])
                X.append([math.log10(dist / self.d0), nW])
                # X.append([math.log10(dist), nW])

        reg = LinearRegression(fit_intercept=True).fit(X, y)
        print('Regression score:', reg.score(X, y))
        return reg.coef_[0], reg.coef_[1], reg.intercept_
Beispiel #12
0
def main1():
    mean, stds, locations, wall = read_utah_data()
    # print(mean)
    # print(stds)
    # print(locations)
    lt = LocationTransform(locations, cell_len=1)
    # print(lt)

    num = len(mean)
    with open('dataUtah/means.txt', 'w') as f:
        for i in range(num):
            for j in range(num):
                f.write('{:6.2f} '.format(mean[i][j]))
            f.write('\n')
    with open('dataUtah/stds.txt', 'w') as f:
        for std in stds:
            f.write('{:.3f}\n'.format(std))
    with open('dataUtah/locations.txt', 'w') as f:
        for i in range(num):
            cell = lt.grid_location[i]
            real_loc = lt.real_location[i]
            f.write('{:3d} - '.format(cell[0] * lt.grid_len + cell[1]))
            f.write('({:2d}, {:2d}) - '.format(cell[0], cell[1]))
            f.write('({:7.4f}, {:7.4f})\n'.format(real_loc[0], real_loc[1]))

    errors = []
    for real_loc in lt.real_location:
        gridcell = lt.real_2_gridcell(real_loc)
        real_loc2 = lt.gridcell_2_real(gridcell)
        error = distance(real_loc, real_loc2)
        errors.append(error)
        print(
            '({:5.2f}, {:5.2f}) -> ({:2d}, {:2d}) -> ({:5.2f}, {:5.2f}); error = {:3.2f}'
            .format(real_loc[0], real_loc[1], gridcell[0], gridcell[1],
                    real_loc2[0], real_loc2[1], error))
    plot_cdf(errors)
Beispiel #13
0
    def correct(self):
        X, Y = [], []
        for i in range(len(self.locations)):
            for j in range(len(self.locations)):
                if i == j:
                    continue
                dist = distance(self.locations[i], self.locations[j])
                tx = Point(self.locations[i][0], self.locations[i][1])
                rx = Point(self.locations[j][0], self.locations[j][1])
                nW = self.wall.count_intersect(tx, rx)
                nW = nW if nW <= self.C else self.C
                X.append(dist)
                Y.append(self.means[i][j] + nW * self.waf)
                # Y.append(self.means[i][j])

        plt.rcParams['font.size'] = 20
        plt.figure(figsize=(10, 10))
        plt.scatter(np.log10(X), Y)
        # plt.scatter(X, Y)
        plt.title('Wall Correction')
        plt.xlabel('Log Distance (m)')
        plt.ylabel('RSS (dBm)')
        plt.ylim([-85, -30])
        plt.savefig('visualize/RSS-logdist-wallcorrect.png')
Beispiel #14
0
 def _idw_interpolate_2(pre_inter, target_grid_len, tx, tx_pl):
     '''Fix one transmitters, interpolate the sensors
     Args:
         pre_inter       -- np.1darray -- pre interpolated, shape = pre_gl*pre_gl
         target_grid_len -- int -- the Tx that needs to interpolate Rx
         factor          -- int
     Return:
         np.1darray -- interpolated, shape = gre_gl*gre_gl*factor*factor
     '''
     pre_gl = int(math.sqrt(
         len(pre_inter)))  # previous grid length (coarse grid)
     pre_inter = pre_inter.reshape((pre_gl, pre_gl))
     factor = int(target_grid_len / pre_gl)
     tx_x, tx_y = tx // target_grid_len, tx % target_grid_len
     inter = np.zeros((target_grid_len, target_grid_len))
     for new_x in range(target_grid_len):
         for new_y in range(target_grid_len):
             if new_x % factor == 0 and new_y % factor == 0:  # don't need to interpolate
                 inter[new_x][new_y] = pre_inter[new_x // factor][new_y //
                                                                  factor]
             else:
                 v_x, v_y = float(new_x) / factor, float(
                     new_y
                 ) / factor  # virtual point in the coarse grid / real point in the fine grid
                 # pick some close points from the coarse grid
                 points = []
                 for pre_x in range(math.floor(v_x - 1),
                                    math.ceil(v_x + 1) + 1):
                     for pre_y in range(math.floor(v_y - 1),
                                        math.ceil(v_y + 1) + 1):
                         if pre_x >= 0 and pre_x < pre_gl and pre_y >= 0 and pre_y < pre_gl:
                             points.append(
                                 (pre_x, pre_y,
                                  distance((v_x, v_y), (pre_x, pre_y)))
                             )  # the distance between the virtual Rx in the coarse grid and coarse Rx
                 dist_to_tx_fine = distance(
                     (new_x, new_y),
                     (tx_x, tx_y))  # distance in the fine grid
                 if dist_to_tx_fine < 4:
                     dist_to_tx_coarse = distance(
                         (v_x, v_y), (tx_x / factor, tx_y / factor))
                     points.append(
                         (tx_x / factor, tx_y / factor, dist_to_tx_coarse)
                     )  # the additional Rx at the same location as the Tx
                 points = sorted(points,
                                 key=lambda tup: tup[2])  # sort by distance
                 threshold = min(MultiIntepolate.NEIGHBOUR_NUM, len(points))
                 weights = np.zeros(threshold)
                 for i in range(threshold):
                     point = points[i]
                     dist = distance((v_x, v_y), point)
                     dist = 0.01 if dist == 0.0 else dist
                     weights[i] = (
                         1. / dist
                     )**2  # inverse weighted distance or inverse weighted square
                 weights /= np.sum(weights)  # normalize them
                 idw = 0
                 for i in range(threshold):
                     w = weights[i]
                     try:
                         pre_rss = pre_inter[points[i][0]][points[i][1]]
                     except:
                         pre_rss = tx_pl  # the additional Rx at the same location as the Tx
                     idw += w * pre_rss
                 inter[new_x][new_y] = idw
     return inter.reshape(target_grid_len * target_grid_len)