Как да семплирате повторно с interp1 в Matlab, когато входните вектори са с различна дължина

Имам две променливи в .mat файл тук: https://www.yousendit.com/download/UW13UGhVQXA4NVVQWWNUQw

testz е вектор на кумулативното разстояние (в метри, монотонно и редовно нарастващо)

testSDT е вектор на интегрирано (кумулативно) време за пътуване на звукова вълна (в милисекунди), генерирано с помощта на вектора на разстоянието и вектора на скоростите (има междинна стъпка за създаване на интервални времена за пътуване)

Тъй като скоростта е непрекъснато променлива функция, получените интервални времена на пътуване, а също и интегрираните времена на пътуване не са цели числа и са променливи по големина

Това, което искам, е да семплира отново вектора на разстоянието на редовни интервали от време (напр. 1 ms, 2 ms, ..., n ms)

Това, което го прави трудно е, че максималното време за пътуване, 994.6659, е по-малко от броя на пробите в 2-та вектора, следователно не е лесно да се използва interp1. т.е.:

X=testSDT -> 1680 проби

Y=testz -> 1680 проби

XI=[1:1:994] -> 994 проби

Това е кодът, който измислих. Това е работещ код и според мен не е много лош.

%% Initial chores
M=fix(max(testSDT));
L=(1:1:M);     

%% Create indices
% this loops finds the samples in the integrated travel time vector
% that are closest to integer milliseconds and their sample number
for i=1:M
  [cl(i) ind(i)] = min(abs(testSDT-L(i)));
  nearest(i) = testSDT(ind(i)); 
end

%% Remove duplicates
% this is necessary to remove duplicates in the index vector (happens in this test). 
% For example: 2.5 ms would be the closest to both 2 ms and 2 ms
[clsst,ia,ic] = unique(nearest);
idx=(ind(ia));

%% Interpolation
% this uses the index vectors to resample the depth vectors at
% integer times
newz=interp1(clsst,testz(idx),[1:1:length(idx)],'cubic')';

Доколкото виждам, има един проблем с този код: разчитам на вектора idx като мой XI за интерполация. Вектор idx е 1 проба по-къс от вектор ind (един дубликат беше премахнат).

Следователно новите ми времена ще спрат с една милисекунда. Това е много малък проблем и дубликат е малко вероятно, но се чудя дали някой може да се сети за заобиколно решение или за различен начин да се подходи към проблема като цяло.

Благодаря ти


person MyCarta    schedule 01.01.2013    source източник


Отговори (1)


Ако ви разбирам правилно, искате да екстраполирате до тази допълнителна точка. можете да направите това по много начини, единият е да добавите тази допълнителна точка към реда interp1. Ако имате някаква функция, която очаквате да следва вашите данни, можете да я използвате, като я приспособите към данните и след това получите тази допълнителна точка или с инструмент като fnxtr.

Но имам проблем да разбера какво искате поради начина, по който сте използвали линията. Третият аргумент, който използвате, [1:1:length(idx)], е просто серията [1 2 3 ...], обикновено при интерполиране се използва някакъв вектор x_i от интересни точки, макар че се съмнявам, че вашите интересни точки са серии от цели числа 1:length(idx) , това, което искате, е само [1:length(idx) xi], където xi е тази допълнителна стойност на точката по оста x.

РЕДАКТИРАНЕ:

Вместо цикъла просто създавайте матрични форми от L и testSDT, тогава матричната операция е малко по-бърза при извършване на min(abs(...:

  MM=ones(numel(testSDT),1)*L;
  TT=testSDT*ones(1,numel(L));
  [cl ind]=(min(abs(TT-MM)));
  nearest=testSDT(ind);
person bla    schedule 01.01.2013
comment
Благодаря, Натан. Целта е да се получат стойности на разстоянието в редовно време (на всяка милисекунда). Това се оказва същото като 1:1:length(idx). Ако се интересувах от повторно семплиране на всеки 10 милисекунди, тогава точките ми на интерес щяха да бъдат в 1:10:length(idx). Това е типично за предвиденото приложение, което е показване на отразени сеизмични данни (където разстоянието е дълбочина). Относно екстраполацията: така че мога просто да използвам опцията за екстраполация в interp1, нали? Бихте ли подходили към цялостния проблем по различен начин - т.е. някакъв начин да свършите цялата работа по-ефективно? - person MyCarta; 02.01.2013
comment
mmmmmh сега като се замисля, ако използвам [1:length(idx) xi] като трети аргумент, тогава той отново е по-дълъг от първия и втория аргумент clsst и testz(idx)? - person MyCarta; 02.01.2013
comment
какво не е достатъчно ефективно във вашия код? Вероятно бих могъл да го направя малко по-бърз, но ми се струва приличен... можете да премахнете for цикъла, но с неотдавнашния JIT (matlabtips.com/matlab-is-no-longer-slow-at-for-loops), обзалагам се, че няма не променя производителността... - person bla; 02.01.2013
comment
третият аргумент не е необходимо да е с еднаква дължина, той е скаларен, векторен или многоизмерен масив, doc interp1 и вижте... - person bla; 02.01.2013
comment
това е вярно. Добре, напълно си прав. Тук в Норвегия е късно през нощта и сигурно съм уморен. Преди да напиша първите 2 клетки от кода, имах този проблем с първия и втория аргумент с различна дължина. Ето защо написах това като начало. Благодаря за обратната връзка относно моя код. Ще маркирам отговора ви като приет. - person MyCarta; 02.01.2013
comment
Здравей Натан, опитвам се от няколко дни, но не мога да измисля векторизирана версия на foor loop. Някакви предположения? Бих могъл да го задам като нов въпрос, предполагам... - person MyCarta; 06.01.2013
comment
WOW, благодаря! Ще го пробвам и ще потърся отново numel, който рядко използвам. - person MyCarta; 06.01.2013