Разворачивание всего в одном направлении

Вчера я задал аналогичный вопрос о том, как избежать «скачков» данных при использовании atan2d. Функция работает в диапазоне от -180 до 180, например:

Единичный круг с atan2d

Когда число превышает 180, оно переходит прямо к -180, что делает линейные графики очень уродливыми и не интуитивно понятными читать. Было предложено использовать unwrap, чтобы исправить это, что, как я думал, и произошло. Однако сегодня я столкнулся с графиком, который выглядит так:

График со странным переводом.

Прыжок фиксируется, но на его месте линия переводится вверх. Если вы начертите эти три линии, они будут очень близки, как и должно быть (-180 и 180 остаются на том же месте, как и на графике atan2d). Я хочу, чтобы мой график отражал то, как на самом деле выглядят углы - очень близко друг к другу.

По запросу Дэвида К., вот код, который я использую для вычисления угла для одной из линий. rec,ret — это упорядоченный набор координат, а recx и recy — их значения x и y соответственно. Затем я наношу результат theta_r на обычную фигуру.

for i=1:length(recx)
    dy(i,1)=((recy(i)-rety(i)));
    dx(i,1)=((recx(i)-retx(i)));
    sloperight(i,1)=(dy(i)/dx(i));
    theta_r(i,1)=atan2d(dy(i),dx(i));

end
theta_r = 180/pi * unwrap(theta_r * pi/180);

Мой вопрос

Как я могу сделать так, чтобы функция развертывания разворачивалась только в одном направлении (сделайте все углы по часовой стрелке на круге или против часовой стрелки), а не разворачивалась в ближайшем направлении? Или я должен использовать что-то другое, кроме unwrap, чтобы график выглядел хорошо?


person user3845377    schedule 17.07.2014    source источник
comment
Возможно, будет проще понять проблему, если вы опубликуете код MATLAB, который построил график (включая часть, в которой используется unwrap). Из документации кажется, что unwrap устранит переходы в одномерном массиве, но не устранит, например, переходы между столбцами двумерного массива.   -  person David K    schedule 17.07.2014


Ответы (2)


Вот мысль: выберите одно из значений в вашем наборе данных, например, первое значение в первой «строке» данных. Установите angle0 на это значение и для каждого массива данных A сделайте «скорректированную» копию A следующим образом: wrapTo180(A - angle0) + angle0 и нанесите на график новые данные.

Просто убедитесь, что вы используете одно и то же значение angle0 для всех данных, которые вы наносите на один график.

У этого подхода могут быть свои проблемы с некоторыми наборами данных (например, если углы постепенно увеличиваются в достаточно широком диапазоне, этот подход будет производить «скачки», которых нет в исходных данных), но поскольку вы знаете данные все сгруппированы вокруг одного углового значения (по модулю 360 градусов), это должно быть в порядке для вашего графика.

person David K    schedule 17.07.2014

Я оставил этот вопрос открытым, когда оставил свой компьютер, и тем самым сегодня утром заучил себя.

Ниже приведен код, чтобы применить ответ Дэвида К. на практике. Используйте предоставленное случайное начальное число, чтобы гарантировать достойный пример. Закомментируйте эту строку, чтобы каждый раз видеть разные примеры.

%Seed maintenance
%    This seed seems to demonstrate the desired behavior. Comment this out
%    to see multiple examples
rng(523205203)

%Parameters
N = 500;
commonRate = 10;
independentRate = 2;
nSeries = 4;

%Some random data
common = randn(N*2,1)*commonRate;
independent = randn(N*2,nSeries)*independentRate;

%Build up some interesting data series
data = cumsum(bsxfun(@plus,common, independent), 1);
data = data((N+1):end, :);

%Setup observed data, observing modulated data
observedData = mod(data, 360)-180;

%Utility functions
%    Basic unwrapping, in deg
unwrap_deg            = @(x) unwrap(x/180*pi)*180/pi;           
%    Unwrapping, using an arbitrary offset, in deg
unwrapToValue_deg     = @(x, value) unwrap_deg(x-value)+value;  
%    Basic unwrapping, in dim 1, after adjusting columns based on row 1
equalizeAndUnwrap_deg = @(x) unwrap_deg(...
    bsxfun(@plus, ...
    unwrapToValue_deg(x(1,:),x(1,1)) - x(1,:), ...   %Per column, add the difference ebtween row 1 and the unwrapped row 1
    observedData)...    
    );

%Use functions to correct observred data
unwrappedObservedData = unwrap_deg(observedData);
equalizedUnwrappedObservedData = equalizeAndUnwrap_deg(observedData);

%Plot
figure(2932323)
subplot(311)
plot(observedData,'.')
subplot(312)
plot(unwrappedObservedData,'.')
subplot(313)
plot(equalizedUnwrappedObservedData,'.')
person Pursuit    schedule 18.07.2014