import scipy
import scipy.fftpack
import cmath
import math
import matplotlib.pyplot as plt
import numpy as np
from scipy import signal
from scipy.signal import freqs, iirfilter
xx = np.linspace(0, 1024, 1024) # диапазон значений x
byts = ([0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1])
ff = 64 # %Частота несущей
ns = np.sin(2 * np.pi * (x - 1) * ff / 1024) # несущая
y = ns * byts[round(int(x + 31) / 64)] # %сигнал
plt.plot(y)
Ошибка:
TypeError: only length-1 arrays can be converted to Python scalars
Как правильно нужно задать массив целых чисел х, чтобы не возникало данной ошибки?
Ответ
Разберёмся, почему возникает данная ошибка. Посмотрим на выражение:
round(int(x + 31) / 64)
x + 31 это массив длины 1024, а мы его приводим к int'у и непонятно, что должно получиться в результате. Python так и говорит:
TypeError: только массивы длины один могут быть приведены к скалярному типу (int это скалярный тип)
Уберём приведение к int'у:
y = ns * byts[round((x + 31) / 64)]
Ошибка пропадёт, но появится другая:
TypeError: type numpy.ndarray doesn't define __round__ method
Можно заменить round на np.round
y = ns * byts[np.round((x + 31) / 64)]
Мы получим другую ошибку
TypeError: only integer scalar arrays can be converted to a scalar index
Дело в том, что np.round((x + 31) / 64) это массив, с типом элементов float, а мы используем этот массив как массив индексов, а индексы могут быть только целыми. Нужно изменить тип элементов массива с помощью astype
y = ns * byts[np.round((x + 31) / 64).astype(int)]
Мы опять получим другую ошибку
TypeError: only integer scalar arrays can be converted to a scalar index
Дело в том, что byts это обычный массив, и через квадратные скобки нельзя обращаться с массивом индексов. Сделаем byts numpy-массивом:
byts = np.array([0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1])
Наша следующая ошибка
IndexError: index 16 is out of bounds for axis 1 with size 16
Возникает из-за того, что в конце массива np.round((x + 31) / 64 есть элементы, равные 16. Возможным решением будет изменение типа элементов массива x на int
x = np.linspace(0, 1023, 1024).astype(int)
и замена сложного выражения np.round((x + 31) / 64 на простое x // 64
y = ns * byts[x // 64] # %сигнал
Итоговый код:
import scipy
import scipy.fftpack
import cmath
import math
import matplotlib.pyplot as plt
import numpy as np
from scipy import signal
from scipy.signal import freqs, iirfilter
x = np.linspace(0, 1023, 1024).astype(int) # диапазон значений x
byts = np.array([0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1])
ff = 64 # %Частота несущей
ns = np.sin(2 * np.pi * (x - 1) * ff / 1024) # несущая
y = ns * byts[x // 64] # %сигнал
plt.plot(y)