Пример #1
0
    def test_level2bits(self):
        self.assertEqual(
            list(map(misc.level2bits, range(1, 20))),
            [1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5])

        # Test if an exception is raised for a value of n lower then 1
        with self.assertRaises(ValueError):
            misc.level2bits(0)
        with self.assertRaises(ValueError):
            misc.level2bits(-2)
Пример #2
0
    def test_level2bits(self):
        self.assertEqual(
            list(map(misc.level2bits, range(1, 20))),
            [1, 1, 2, 2, 3, 3, 3, 3, 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5])

        # Test if an exception is raised for a value of n lower then 1
        with self.assertRaises(ValueError):
            misc.level2bits(0)
        with self.assertRaises(ValueError):
            misc.level2bits(-2)
Пример #3
0
    def plotConstellation(self):  # pragma: no cover
        """Plot the constellation (in a scatter plot).
        """
        fig = plt.figure()
        ax = fig.add_subplot(1, 1, 1)  # one row, one column, first plot
        # circlePatch = patches.Circle((0,0),1)
        # circlePatch.set_fill(False)
        # ax.add_patch(circlePatch)
        ax.scatter(self.symbols.real, self.symbols.imag)

        ax.axis('equal')
        ax.grid()

        formatString = "{0:0=" + str(level2bits(self._M)) + "b} ({0})"

        index = 0
        for symbol in self.symbols:
            ax.text(
                symbol.real,  # Coordinate X
                symbol.imag + 0.03,  # Coordinate Y
                formatString.format(index, format_spec="0"),  # Text
                verticalalignment='bottom',  # From now on, text properties
                horizontalalignment='center')
            index += 1

        plt.show()
Пример #4
0
    def plotConstellation(self):  # pragma: no cover
        """Plot the constellation (in a scatter plot).
        """
        fig = plt.figure()
        ax = fig.add_subplot(1, 1, 1)  # one row, one column, first plot
        # circlePatch = patches.Circle((0,0),1)
        # circlePatch.set_fill(False)
        # ax.add_patch(circlePatch)
        ax.scatter(self.symbols.real, self.symbols.imag)

        ax.axis('equal')
        ax.grid()

        formatString = "{0:0=" + str(level2bits(self._M)) + "b} ({0})"

        index = 0
        for symbol in self.symbols:
            ax.text(
                symbol.real,  # Coordinate X
                symbol.imag + 0.03,  # Coordinate Y
                formatString.format(index, format_spec="0"),  # Text
                verticalalignment='bottom',  # From now on, text properties
                horizontalalignment='center')
            index += 1

        plt.show()
Пример #5
0
    def _calculateGrayMappingIndexQAM(L):
        """
        Calculates the indexes that should be applied to the
        constellation created by _createConstellation in order to
        correspond to Gray mapping.

        Notice that the square M-QAM constellation is a matrix of dimension
        L x L, where L is the square root of M. Since the constellation was
        generated without taking into account the Gray mapping, then we
        need to reorder the generated constellation and this function
        calculates the indexes that can be applied to the original
        constellation in order to do exactly that.

        As an example, for the 16-QAM modulation the indexes can be
        organized (row order) in the matrix below

        ====  ======  ======  ======  ======
         /      00      01      11      10
        ====  ======  ======  ======  ======
         00    0000    0001    0011    0010
         01    0100    0101    0111    0110
         11    1100    1101    1111    1110
         10    1000    1001    1011    1010
        ====  ======  ======  ======  ======

        This is equivalent to concatenate a Gray mapping for the row with a
        Gray mapping for the column, and the corresponding indexes are
        [0, 1, 3, 2, 4, 5, 7, 6, 12, 13, 15, 14, 8, 9, 11, 10]

        Parameters
        ----------
        L : int
            Square root of the modulation cardinality (must be an integer).

        Returns
        -------
        indexes : np.ndarray
            indexes that should be applied to the constellation created by
            _createConstellation in order to correspond to Gray mapping

        """
        # Row vector with the column variation (second half of the index in
        # binary form)
        column = binary2gray(np.arange(0, L, dtype=int))

        # Column vector with the row variation
        #
        # Column vector with the row variation (first half of the index in
        # binary form)
        row = column.reshape(L, 1)
        columns = np.tile(column, (L, 1))
        rows = np.tile(row, (1, L))
        # Shift the first part by half the number of bits and sum with the
        # second part to form each element in the index matrix
        index_matrix = (rows << (level2bits(L**2) // 2)) + columns

        # Return the indexes as a vector (row order, which is the default
        # in numpy)
        return np.reshape(index_matrix, L**2)
Пример #6
0
    def _calculateGrayMappingIndexQAM(L):
        """
        Calculates the indexes that should be applied to the
        constellation created by _createConstellation in order to
        correspond to Gray mapping.

        Notice that the square M-QAM constellation is a matrix of dimension
        L x L, where L is the square root of M. Since the constellation was
        generated without taking into account the Gray mapping, then we
        need to reorder the generated constellation and this function
        calculates the indexes that can be applied to the original
        constellation in order to do exactly that.

        As an example, for the 16-QAM modulation the indexes can be
        organized (row order) in the matrix below

        .. aafig::
                  00     01     11     10
               +------+------+------+------+
            00 | 0000 | 0001 | 0011 | 0010 |
            01 | 0100 | 0101 | 0111 | 0110 |
            11 | 1100 | 1101 | 1111 | 1110 |
            10 | 1000 | 1001 | 1011 | 1010 |
               +------+------+------+------+

        This is equivalent to concatenate a Gray mapping for the row with a
        Gray mapping for the column, and the corresponding indexes are
        [0, 1, 3, 2, 4, 5, 7, 6, 12, 13, 15, 14, 8, 9, 11, 10]

        Parameters
        ----------
        L : int
            Square root of the modulation cardinality (must be an integer).

        Returns
        -------
        indexes : np.ndarray
            indexes that should be applied to the constellation created by
            _createConstellation in order to correspond to Gray mapping

        """
        # Row vector with the column variation (second half of the index in
        # binary form)
        column = binary2gray(np.arange(0, L, dtype=int))

        # Column vector with the row variation
        #
        # Column vector with the row variation (first half of the index in
        # binary form)
        row = column.reshape(L, 1)
        columns = np.tile(column, (L, 1))
        rows = np.tile(row, (1, L))
        # Shift the first part by half the number of bits and sum with the
        # second part to form each element in the index matrix
        index_matrix = (rows << (level2bits(L ** 2) // 2)) + columns

        # Return the indexes as a vector (row order, which is the default
        # in numpy)
        return np.reshape(index_matrix, L ** 2)
Пример #7
0
    def calcTheoreticalBER(self, SNR):
        """Calculates the theoretical (approximation) bit error rate for
        the M-PSK scheme using Gray coding.

        Parameters
        ----------
        SNR : float | np.ndarray
            Signal-to-noise-value (in dB).

        Returns
        -------
        BER : float | np.ndarray
            The theoretical bit error rate.
        """
        # $P_b = \frac{1}{k}P_s$
        # Number of bits per symbol
        k = level2bits(self._M)
        return 1.0 / k * self.calcTheoreticalSER(SNR)
Пример #8
0
    def calcTheoreticalBER(self, SNR):
        """Calculates the theoretical (approximation) bit error rate for
        the M-PSK scheme using Gray coding.

        Parameters
        ----------
        SNR : float | np.ndarray
            Signal-to-noise-value (in dB).

        Returns
        -------
        BER : float | np.ndarray
            The theoretical bit error rate.
        """
        # $P_b = \frac{1}{k}P_s$
        # Number of bits per symbol
        k = level2bits(self._M)
        return 1.0 / k * self.calcTheoreticalSER(SNR)
Пример #9
0
    def calcTheoreticalBER(self, SNR):
        """Calculates the theoretical (approximation) bit error rate for
        the QAM scheme.

        Parameters
        ----------
        SNR : float or array like
            Signal-to-noise-value (in dB).

        Returns
        -------
        BER : float or array like
            The theoretical bit error rate.
        """
        # For higher SNR values and gray mapping, each symbol error
        # corresponds to approximately a single bit error. The BER is then
        # given by the probability of error of a single carrier in the QAM
        # system divided by the number of bits transported in that carrier.
        k = level2bits(self._M)
        Psc = self._calcTheoreticalSingleCarrierErrorRate(SNR)
        ber = (2. * Psc) / k
        return ber
Пример #10
0
    def calcTheoreticalBER(self, SNR):
        """
        Calculates the theoretical (approximation) bit error rate for
        the QAM scheme.

        Parameters
        ----------
        SNR : float | np.ndarray
            Signal-to-noise-value (in dB).

        Returns
        -------
        BER : float | np.ndarray
            The theoretical bit error rate.
        """
        # For higher SNR values and gray mapping, each symbol error
        # corresponds to approximately a single bit error. The BER is then
        # given by the probability of error of a single carrier in the QAM
        # system divided by the number of bits transported in that carrier.
        k = level2bits(self._M)
        Psc = self._calcTheoreticalSingleCarrierErrorRate(SNR)
        ber = (2. * Psc) / k
        return ber