Regarding finding peak values from vectors; how do I find only the max value and also write this in a loop with changing string variable names?

Hello,
I am trying to make my life easier- I have something like 380 sets of data that I really don't want to find the peaks of by hand, so I am trying to write a bit of code to automate this process. Here is what I have so far:
C3ax= [List of x values, a 1X1600 double vector]
C3ay= [Corresponding list of y values, a 1X1600 double vector]
%(I have about 84 of these vector pairs, from (C3ax, C3ay) to (G12ax,G12ay))
[pks, loc]=findpeaks(C3ay(1:200))
[XVal]=C3ax(loc)
[XVal;PkVal]
%I am searching for peaks only in a certain range, thus the (1:200) %I realize that if I change the starting location from "1" in the above line, I also have to add that value to loc in the second line
So this returns values of ans =
51.5625 53.1250
2.5302 1.0381
Which is correct, and sort of what I want (specifically only the 51.5625 value). So here are my questions:
1) Is there a way to tell the find peaks function that I only want the highest peak? I would specifically like it to return only the 51.5625,2.5302 pair, but I don't know the values I would be looking for until I find them (i.e, I can't set the max height to look for because I don't know what it is a priori).
2)I would like to be able to run this in a loop so that it does C3a through C12a, then D3a through D12a, etc, but I am not great at doing loops with string terms- ideally I could do for n=1:12 and have the names be C'n'a, but I don't know how to write that so that Matlab understands. Any advice? I tried this:
C1x7UnbakedY=[C3ay,C4ay,C5ay,C6ay]
C1x7UnbakedX=[C3ax,C4ax,C5ax,C6ax]
MaxFreq=60;
for n=1:4;
YVal=C1x7UnbakedY(n)
XVal=C1x7UnbakedY(n)
[PkVal,loc]=findpeaks(YVal(1:(MaxFreq/0.3125)))
[XVal]=XVal(loc)
[XVal;PkVal]
end
But that just returned a number for YVal and XVal instead of bringing in the entire vector.
Eventually I would like to have all of the XVal terms averaged for each letter trial, but I don't think I am far enough along to get into that yet. Thanks for the help!!!
Kaitlin

Réponses (1)

1) Is there a way to tell the find peaks function that I only want the highest peak?
Sure...
[pks, loc]=findpeaks(v,'npeaks',1','sortstr','descend');
doc findpeaks
2)I would like to be able to run this in a loop so that it does C3a through C12a, then D3a through D12a, etc, but I am not great at doing loops with string terms- ideally I could do for n=1:12 and have the names be C'n'a, but I don't know how to write that so that Matlab understands. Any advice? ...
Yeah, "don't do that!" :)
Use structure named fields or just a large array and the column indices instead rather than 'poofing' variables into the workplace...
See the FAQ at...
for "more better" ways.

8 commentaires

Well, not quite- when I use 'npeaks' and 'sortstr' together, it always does the npeaks=1 first, so it truncates the list first, BEFORE looking for the maximum value. That's what I tried originally, sorry I didn't mention that. Another idea? I guess I can just use sortstr and take only the first value.
Also, the problem with the large array method is that I want to use pieces of pieces of the individual vectors. Can you tell me how to call just a portion of the vector of an array? See the following:
So I start by making my arrays, keeping in mind that these are vectors of data- I tried the 'C3ax' form too, but it wouldn't link the C3ax' name with the C3ax string of data:
CSection1x7UnbakedX={C3ax,C4ax,C5ax,C6ax}
CSection1x7UnbakedY={C3ay,C4ay,C5ay,C6ay}
MaxFreq=60;
for n=1:4 [PkVal(n),loc(n)]=findpeaks(CSection1x7UnbakedY([n:n,1(MaxFreq/0.3125)]),'sortstr','descend');
[XVal(n)]=CSection1x7UnbakedX(loc);
[XVal(n),PkVal(n)]
end
Running that just gives me this:
CSection1x7UnbakedX =
Columns 1 through 3
[1x1600 double] [1x1600 double] [1x1600 double]
Column 4
[1x1600 double]
CSection1x7UnbakedY =
Columns 1 through 3
[1x1600 double] [1x1600 double] [1x1600 double]
Column 4
[1x1600 double]
??? Index exceeds matrix dimensions.
So what am I doing wrong???
"Well, not quite- when I use 'npeaks' and 'sortstr' together, it always does the npeaks=1 first, so it truncates the list first, BEFORE looking for the maximum value. ..."
That doesn't happen here--
>> y
y =
Columns 1 through 18
9 3 17 5 6 4 7 20 14 16 19 2 8 13 12 1 18 15
Columns 19 through 20
10 11
>> [p,i]=findpeaks(y,'npeaks',1,'sortstr','descend')
p =
20
i =
8
>> [p,i]=findpeaks(y,'npeaks',1)
p =
17
i =
3
>>
The combination finds the '20' the N==1 the first 17 as expected.
What release are you using? This is R2012b.
"Also, the problem with the large array method is that I want to use pieces of pieces of the individual vectors. Can you tell me how to call just a portion of the vector of an array? ..."
Don't quite follow what is the problem but for any array x you just use colon addressing w/ (perhaps dynamic) indices to return the portion of interest.
v=x(1:1000); % first 1000 locations
[p,ix]=findpeaks(x,'npeaks',1,'sortstr','descend');
v=x(ix+1:end); % the rest after the location of the largest peak
% iterate in groups of N
N=1000;
i1=1;
i2=N;
for iloop=1:length(x)/N
v=x(i1:i2);
% do something w/ v here
...
i1=i2+1;
i2=i2+N;
end
Alternatively w/o the intermediate variable...
for iloop=1:length(x)/N
result_vector=some_function(x(i1:i2));
...
i1=i2+1;
i2=i2+N;
end
There are ways to vectorize the above at least partially, too...
Does that help?
The first thing is to load the data into a more convenient form to address it than by a bunch of variable names w/ funky letter/number combinations.
Hi,
I am using 2010a, so I guess they must have fixed the npeaks thing with a newer release. I just worked around that by calling only the first entry, so no big deal there.
No, what you have there for the loop doesn't help yet. I really need to get the loop working with vectors that already exist- what you have there looks like I still have to rename every data set manually (i.e. your v=x(1:1000) part), which is partly what I am trying to avoid. In the three lines of code below, B3ax and B3ay are already existing vectors of 1x1600 entries, of which I want entries 256-416 (for example).
[PkVal1,loc1]=findpeaks(B3ay((256):(416)),'sortstr','descend');
[XVal1]=B3ax((256)+loc1-1);
Unbaked1=[XVal1(1);PkVal1(1)]
So I can make an array out of the Cna vectors like this: CAllx=[C3ax,C4ax,C5ax] CAlly=[C3ay,C4ay,C5ay]
and I can call out one row at a time like this: MinFreq=80; MaxFreq=130; CAlly=[C3ay;C4ay;C5ay]; CAllx=[C3ax;C4ax;C5ax];
[PkVal,loc1]=findpeaks(CAlly(1,((MinFreq1/0.3125):(MaxFreq/0.3125))),'sortstr','descend');
[XVal1]=CAllx(1,(MinFreq1/0.3125)+loc1(1)-1);
Unbaked1=[XVal1;PkVal1(1)]
And that gives me: Unbaked1 =
124.0625
-20.5539
Hooray, just what I want. So now, all I want it to do is run through each ROW in that CAll array using a loop!
And then I think it should work something like this: for n=1:3
[PkVal,loc1]=findpeaks(BAlly(n,((MinFreq1/0.3125):(MaxFreq1/0.3125))),'sortstr','descend');
[XVal1]=BAllx(1,(MinFreq1/0.3125)+loc1(1)-1);
Unbaked1=[XVal1;PkVal1(1)]
end
which gives me this: Unbaked1 =
124.0625
-20.5539
Unbaked1 =
123.1250
-20.5539
Unbaked1 =
122.5000
-20.5539
Which is good, so all I have left is- what do I put as the indices to get those into a single matrix??? Thank you!!!
I'd again revert to how is the data being loaded and why do you have so many variables of all these names to begin with?
"...I really need to get the loop working with vectors that already exist- what you have there looks like I still have to rename every data set manually (i.e. your v=x(1:1000) part), which is partly what I am trying to avoid. In the three lines of code below, B3ax and B3ay are already existing vectors of 1x1600 entries, of which I want entries 256-416 (for example).
[PkVal1,loc1]=findpeaks(B3ay((256):(416)),'sortstr','descend');"
I'd prefer to step back a step and work on that to simplify everything else going forward. I couldn't follow just where your point of confusion was; the examples were just examples of subsets of an existing variable using colon addressing. I wasn't at all suggesting renaming manually.
[PkVal1,loc1]=findpeaks(B3ay(256:416),'sortstr','descend');"
For a little less obfuscation in reading you can eliminate the internal pairs of paren's in the addressing above.
Would you consider posting a new thread in the newsgroups to followup on this with an example of your loading the data so can see how it is to work on the naming thingie?
I find this forum extremely difficult to respond in with any detail what with the trouble in formatting code and the tiny window to write in and the lack of proper quoting, etc., etc., etc., ...
Hi,
First off, thanks so much for your continued response to this, I really appreciate it. The data is actually frequency response functions for a variety of cables that I had to keep track of the type of cable, whether it had undergone bakeout, which section, etc, etc, so I had to keep the identifiers on the data so I can compare things appropriately. The letter indicates which section, the number which trial, the lowercase letter which run, and then x or y for frequency or magnitude value. And then I have each of those for 4 different types of cables. Lots of data = lots of fun, right? Sure...
I can certainly move this to newsgroups, but I have not used that before, so give me a minute or two to find it... thanks!
Oh, and the data is loaded from Polytec vibrometer software- it is values read from a laser vibrometer and put into Matlab vectors, I have old software so there is no other way to bring it in that I know of.
Ok, found it- I will put this up with further details after I have dinner. Thanks!
Saw ya' over on cs-sm...awaiting your response over there on starting w/ the data itself and let's see about getting it into Matlab in a more suitable form for automagic processing...after that, stuff should become "piece o'cake"... :)

Connectez-vous pour commenter.

Produits

Question posée :

K
K
le 26 Juin 2013

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by