You are now following this question
- You will see updates in your followed content feed.
- You may receive emails, depending on your communication preferences.
how to make nan turn into 0 in array
2 views (last 30 days)
Show older comments
Naufal Arfani
on 17 Jan 2021
Hello all,
im working in simulink with findpeaks and I have the code as below, for the condition if u ~ = 0 it works well, so the else condition is in the condition if u == 0,
but then there is a nan value outside u ~ = 0 so you need to add elseif,
but when I tried with isnan (u) it couldn't detect that he was nan and I wanted to change it to all 0 values
so that there is an error as shown below,
can anyone help me find out where it went wrong thank you very much
function [dist,peak2,locs2] = fcn(u)
locs = zeros(size(u));
pks = zeros(size(u));
if u ~= 0
[pks,locs] = findpeaks(u);
elseif isnan(u)
locs(size(u))= 0;
pks(size(u)) = 0;
else
locs(size(u))= 0;
pks(size(u)) = 0;
end
a = locs(2)- locs(1);
b = pks(1);
c = locs(1);
dist = a;
peak2 = b;
locs2 = c;
35 Comments
Athrey Ranjith Krishnanunni
on 17 Jan 2021
Edited: Athrey Ranjith Krishnanunni
on 17 Jan 2021
Hard to tell without knowing u exactly, but it looks like there's only one peak in it, so locs returns a scalar, and you're trying to index into its second element, which is what throws the error.
What is an example value of u?
Naufal Arfani
on 17 Jan 2021
oh excuse me, @ARK
u are the fft value of the induction motor output sine signal, then I used nfft 1000 and this is single side fft so it becomes [1x500],
if there is a misalignment then there are several peaks that are read by findpeaks, but when aligned the values all turn to NaN and findpeaks becomes an error that's why I want to change it to 0 only
Athrey Ranjith Krishnanunni
on 17 Jan 2021
>>when I tried with isnan (u) it couldn't detect that he was nan and I wanted to change it to all 0 values
>>the values all turn to NaN and findpeaks becomes an error that's why I want to change it to 0 only
Are you trying to change the values of u that are NaN into 0? If so, what you need is
u(isnan(u)) = 0
Also, the line that throws the error according to your screenshot doesn't match any of the lines in the function that you have given. It would help to have the exact error message.
dpb
on 17 Jan 2021
"if there is a misalignment then there are several peaks that are read by findpeaks, but when aligned the values all turn to NaN..."
That sounds like you've mucked up something before you even get this far...but we have no way to try to help debug your code without data and enough code to be able to reproduce the problem.
As ARK above notes, nothing in the post matches up with the error; it's a snipe hunt/wild goose chase at the moment.
Also NB: that the if(x) keyword/function only returns TRUE if all(x) for whatever is expression x is true. If there are any elements in isnan(u) that are NOT NaN, then the elseif clause as written above will never be executed.
I would suggest besides fixing these errors pointed out that using the debugger to step through the code to see what it is doing and why it doesn't match expectation would be faster than us trying to debug remotely bits and pieces...
Naufal Arfani
on 18 Jan 2021
Edited: Naufal Arfani
on 18 Jan 2021
I can't explain my current condition correctly.
I tried with u (isnan (u)) = 0 but it still got an error because then the condition for the array locs became [1-1] so I couldn't use a = locs (4) - locs (3), just like the above error
how do i solve this then? I'm sorry but I really need your help
I want to attach my simulink but can't because this is a project I'm sorry
this is after i used u (isnan (u)) = 0 but still no work
Athrey Ranjith Krishnanunni
on 18 Jan 2021
@Naufal Arfani maybe upload a screenshot of a similar model by isolating only the erring block. Because without that, I'm left with suggestions like
locs(isnan(u)) = 0;
pks(isnan(u)) = 0;
purely based on guesses.
I suppose you could also try
elseif any(isnan(u))
Naufal Arfani
on 18 Jan 2021
it turns out that the NaN value comes after from the findpeaks output instead of the findpeaks input because I checked from out.simout before entering findpeaks and it has a value maybe because findpeaks can't find the peak so it becomes NaN or empty
and this is screenshot of my work
Naufal Arfani
on 18 Jan 2021
I have tried this code but it still doesn't work
function [dist,peak2,locs2] = fcn(u)
locs = zeros(size(u));
pks = zeros(size(u));
if u ~= 0
[pks,locs] = findpeaks(u);
else
locs(size(u))= 0;
pks(size(u)) = 0;
end
locs(isnan(u)) = 0;
pks(isnan(u)) = 0;
a = locs(2)- locs(1);
b = pks(1);
c = locs(1);
dist = a;
peak2 = b;
locs2 = c;
Athrey Ranjith Krishnanunni
on 18 Jan 2021
What does the function FFTSHIFT do?
Naufal Arfani
on 18 Jan 2021
it contains the code for single side fft. I haven't just changed the name
function y = fcn(u)
L = 1000; % Length of signal
P2 = abs(u/L);
P1 = P2(1:L/2+1);
P1(2:end-1) = 2*P1(2:end-1);
y = P1;
Naufal Arfani
on 18 Jan 2021
Edited: Naufal Arfani
on 18 Jan 2021
Athrey Ranjith Krishnanunni
on 18 Jan 2021
So I just ran the code
u = logspace(1,0); % vector of decreasing values, similar to OP's output from FFTSHIFT
[pks,locs] = findpeaks(u);
It returned pks and locs as empty arrrays (no NaN), so I'm completely stumped.
@Naufal Arfani if you are sure that your input to the findpeaks function is completely fine, why don't you just write
function [dist,peak2,locs2] = fcn(u)
[pks,locs] = findpeaks(u);
if isempty(pks)
pks = zeros(size(u));
locs = zeros(size(u));
end
dist = locs(2)- locs(1);
peak2 = pks(1);
locs2 = locs(1);
Athrey Ranjith Krishnanunni
on 18 Jan 2021
Well, I can't open that .slx file (it's R2019b and mine is R2018b), but I did notice that (according to your error message), you only got the error in Peak Detection1, so maybe see what is different in that branch, when compared to the one that contains Peak Detection.
dpb
on 18 Jan 2021
Edited: dpb
on 18 Jan 2021
I don't have Simulink at all, so can't do anything there, but have you done the suggestion before to use debugger and step through what is going on that is unexpected?
The Q? would seem to be "What is the source of u and why is it not something of the expected form that findpeaks would work on without trouble?"
Instead of trying to patch up something that is broke afterwards and keep on going, why not find out why/where it broke and keep that from happening? It wouldn't seem that there's anything meaningful to be gained at the point you're at now, anyway; you're just trying to cover up a problem.
But, again, if the error is in some other piece of code as Naufal above notes, then again it doesn't do any good to post something different than that and it still begs the question of what is u,specifically?
Attach a .mat file that contains variable u at the point that you have the problem; then at least somebody can try to duplicate the behavior of findpeaks and see what it is that is being passed to your function.
If the problem is simply one that there is a possibility that there are no peaks in the input vector and that is still a viable case, then the problem is you just need to write code to handle the case of the return value from findpeaks being the empty set. The sample code above would be one possibility; what the model should do in that case we can't tell; only you can have any idea about what that might mean and what to do next if the case arises.
Naufal Arfani
on 18 Jan 2021
forgive me if my explanation is not understood by you, @dpb
u is a discrete input from fast fourier transform from the output of an induction motor, where if there is no misalignment, the value will decrease so that findpeaks cannot detect it because there is no peak,
but I am confused why the value becomes NaN and not zero, so I just want how to make the result zero
so there is no error in locs (4) - locs (3) above because it only reads [1-1] the value only
thank you very much for your attention and one more time i say sorry because make a trouble for you all
Naufal Arfani
on 18 Jan 2021
I'm sorry I forgot to ask what version do you have,@ARK
here I have changed it to r2018b version if you can help me I will really appreciate it
please help me, my hope is just only in here
dpb
on 18 Jan 2021
Edited: dpb
on 18 Jan 2021
The explanation and understanding is not really the problem -- the problem is you're fixated on the wrong way to try to fix the issue and not heeding the advice you're being given but continuing down the same rabbit hole after Alice.
If, indeed, you can legitimately have a case where u is a decreasing function with no peaks, then as the other poster indicated, findpeaks will return an empty set, NOT NaN. Also,
>> pks=findpeaks(u)
pks =
-2.78
14.50
20.23
>> pks=findpeaks(sort(u))
pks =
0×1 empty double column vector
>> pks=findpeaks(nan(10,1))
pks =
0×1 empty double column vector
>>
illustrates that findpeaks won't return a NaN even if the full input array into it is NaN; it still outputs the empty vector.
Fix the problem at that point by catching the empty return from findpeaks and substitute what you want; NaNs will be coming from some later operation on that null set, not from findpeaks
function [dist,peak2,locs2] = fcn(u)
assert(all(isfinite(u),'all'),'U contains NaN elements in Function fcn. Aborting')
[pks,locs] = findpeaks(u);
if isempty(pks)
pks = zeros(size(u));
locs = zeros(size(u));
end
dist = locs(2)- locs(1);
peak2 = pks(1);
locs2 = locs(1);
end
was provided for you above by Nauful; it appears to be a perfectly valid way to work around the problem in this function other than perhaps unexpected array sizes since the original returns 2-vectors. The problem then is your code that calls this function has to know how to appropriately deal with zeros everywhere in the returned vectors.
I've added an assert clause to let you know if you've already corrupted u before getting to this point; if it shows up, then you need to look further upstream as to what's caused it.
It's quite probable that subsequent math operations are then creating the NaN -- we don't know that and can't tell from here, but if you have the case above and do something with the zero vectors that results in a division of 0/0, then the NaN will show up there.
To avoid doing that, my recommendation would be to NOT return an array of 0 for these variables but the empty vectors that are the result from findpeaks for the given case and then branch in the calling routine based on isempty(dist). At that point if there are no peaks, there's no point in calling any code that will presume there are. This will entirely eliminate the problem of trying to special-case what to do with 0 values for peaks and locations.
Again, all we can do at this point is advise you to use the function above or something similar instead of your initial proposed one and then use defensive programming to avoid introducing a NaN later. But this code will not be the culprit.
My proposed routine along these lines would look more like
function [dist,peak,loc] = fcn(u)
assert(all(isfinite(u),'all'),'U contains NaN elements in Function fcn. Aborting')
dist=[]; peak=[]; loc=[]; % initialize to empty elements
[pks,locs] = findpeaks(u);
if isempty(pks), return; end % No peaks, return empty as indicator flag
assert(numel(pks)>1,'Findpeaks Only One Peak in Function fcn. Aborting')
dist=locs(2)-locs(1);
peak=pks(1);
loc=locs(1);
end
Naufal Arfani
on 19 Jan 2021
I'm sorry once again if my explanation and understanding are still not what you want, but after I use your code I get an error like this
and then if from my understanding why then locs (2) and so on cannot appear, it has already been explained by you with the example you gave, namely the condition of the value all decreased so that it becomes 1x0 empty, that is why locs (2) etc. cannot appear in value resulting in an error, therefore why then I want how to do it to be 1x3 but with a value of 0 all if there is no peak
from where then I always say that the output of findpeaks is NaN, I got this from the same modeling with the code as below by changing the edit data and checking the variable size with a size of 500
function [pks,locs] = fcn(u)
[pks,locs] = findpeaks(u);
and from there then I saw the output of simout 8 and simout and got the results as below
this is the content of simout 8 which I said is decreasing input
and this is the simout result which is the peak of the findpeaks result
Therefore, with my current understanding, I still think that before entering locs (2) -locs (1) the condition of the findpeaks output has changed from 1x0 empty to 1x500 with a value of 0 if there is no peak so that the locs value (2) is 0 and locs (1) is 0 and becomes locs (2) -locs (1) is 0 not only 1x0 empty where the value of locs (2) etc. has no value
Naufal Arfani
on 19 Jan 2021
@ARKthen can you try my simulink with the r2018b version that I sent?
dpb
on 19 Jan 2021
Edited: dpb
on 19 Jan 2021
"I still think that before entering locs (2) -locs (1) the condition of the findpeaks output has changed from 1x0 empty to 1x500..."
Your conclusion above is wrong; MATLAB did precisely what you (well what I told you to :) ) told it to do. SIMULINK did the rest when that turned out to be wrong in trying to keep going despite the mismatch before it finally did give up the ghost.
The SIMULINK error message says it all:
"Inferred size for data 'dist' is empty..."
so clearly the MATLAB portion did what it was programmed to do.
That there is something other than that and that the model continued on shows that it was/is SIMULINK that created information to fill the best it could from somewhere -- but that wasn't the MATLAB function that did it.
The moral here is that you have to read the error messages very carefully and parse precisely what the text says; you can't just jump to a conclusion of what you think may have happened. That can lead to drawing the wrong conclusion as you had done early on in trying to fix a NaN inside the function where there simply could be no NaN generated in that context. It was that impasse earlier in our conversation that led to the frustration expressed last night about not heeding advice that couldn't get you to accept the function wasn't/isn't doing any such thing. That's why posting the exact and complete error message in context was so helpful; need to always do that.
Now we need to find out just what it is that your subsequent blocks do expect and if they know enough to deal with the zero return vector.
dpb
on 19 Jan 2021
OH. Or is the 2D array showing the 1D result from each timestep of the model so each row is a timestep? That would explain the array vs vector anomaly.
I also notice the Simulink error message goes on to say "Fix the indicated errors or explicitly specify the sizes..." which does imply you could tell the model how big a variable is being returned.
From that it appears that the solution to the problem would be something more on the order of
function [dist,peak,loc] = fcn(u)
% findpeaks for input vector u and return three vector of
% [distance between first two peaks, first peak magnitude, first peak location]
% if no peaks found, returns zero for all three output variables
assert(all(isfinite(u),'all'),'U contains NaN elements in Function fcn. Aborting')
dist=0; peak=0; loc=0; % initialize to zero
[pks,locs] = findpeaks(u);
if isempty(pks), return; end % No peaks, return empty as indicator flag
assert(numel(pks)>1,'Findpeaks Only One Peak in Function fcn. Aborting')
dist=locs(2)-locs(1);
peak=pks(1);
loc=locs(1);
end
See if that improves the situation any.
I would also then recommend to tell SIMULINK that the block output does return precisely three values wherever in the input it is that that is done although the above should resolve the anomaly.
If the above assumption about what the pictures are showing is correct about rows being timesteps, I'm thinking this may solve your problem.
Of course, your model still has to know what to do with the anomolous case of all zeros for peaks...
Naufal Arfani
on 20 Jan 2021
Edited: Naufal Arfani
on 20 Jan 2021
thank you very much for your generosity in explaining everything, but I still later got this error is it just a little more or something like? @dpb
or should the writing be in the form of a comment?
Athrey Ranjith Krishnanunni
on 20 Jan 2021
@Naufal Arfani there are undefined variables in the file you uploaded, e.g. Bm, Ts, JL, etc. so I can't run it. But I did go through all the comments here, and looks like @dpb was able to solve your problem. The latest error that you have is because of this line
assert(numel(pks)>1,'Findpeaks Only One Peak in Function fcn. Aborting')
in the code, which means pks is neither empty nor has more than 1 element, i.e. it is a scalar, which happened because there was only one peak. If simulation weren't terminated at this point, the next line
dist = locs(2) - locs(1);
will certainly not work because there is no locs(2), so it is up to you how you want to handle this scenario.
dpb
on 20 Jan 2021
Edited: dpb
on 20 Jan 2021
Well, that's something that isn't supposed to be able to happen by your description -- there are supposed to be either two or more or none -- what is the case of only one?
You can try to go on by fixing up the routine to also return the 0 vector or whatever else would seem appropriate at that point; only you can really know what that might mean -- if anything.
But you can't just turn the assert into a comment because there is no value for loc(2) from which to compute a distance...at least without making some other change in the routine.
The brute force way to just let things keep on running would be to
function [dist,peak,loc] = fcn(u)
% findpeaks for input vector u and return three vector of
% [distance between first two peaks, first peak magnitude, first peak location]
% if no peaks found, returns zero for all three output variables
assert(all(isfinite(u),'all'),'U contains NaN elements in Function fcn. Aborting')
dist=0; peak=0; loc=0; % initialize to zero
[pks,locs] = findpeaks(u);
if isempty(pks), return; end % No peaks, return zeros as indicator flag
peak=pks(1);
loc=locs(1);
if numel(pks)<2 % One peak only, dist == 0 returned
disp('Findpeaks Only One Peak in Function fcn. Warning')
return;
end
dist=locs(2)-locs(1);
end
Naufal Arfani
on 20 Jan 2021
Edited: Naufal Arfani
on 20 Jan 2021
thank you for coming back to help me, @ARK
yes I know because there is no peak, therefore findpeaks becomes 1x0 empty, therefore locs (2) etc. have no value,
That's why the choice in my opinion is whether we can then add elements to the array after it's done in findpeaks but I was blocked by an error Dimension 1 is fixed on the left-hand side but varies on the right ([1 x 1] ~= [:? x 1])
and also for the missing element, I gave it but maybe you haven't downloaded it yet, I will give it back, if then you can run please check where the error lies
the problem was that I tried to change it to locs (1) but it couldn't because the value was empty as if you read in the description of findpeaks in mathworks it says if there is no peak then the value becomes empty
Athrey Ranjith Krishnanunni
on 20 Jan 2021
My bad, I'd forgotten that there was another file that you had uploaded. Yes, I was able to run it (not to completion, my laptop heated up so I had to stop the simulation; your signals have a length of 3,009,288).
I'm not quite sure where your original problem of NaN was coming from, though I suspect it has to do with your very small time-step (it must have created some close-to-singular matrices somewhere).
But now I know where the "cannot determine sizes" errors all came from. Turns out, the MATLAB function block in Simulink has some restrictions, as Walter Roberson has said here:
"The MATLAB Function block generates efficient embeddable code based on an analysis that determines the size, class, and complexity of each variable. This analysis imposes the following restrictions:
- The first assignment to a variable defines its, size, class, and complexity.
- You cannot reassign variable properties after the initial assignment except when using variable-size data or reusing variables in the code for different purposes.
When the code was edited such that the first assignment to pks and locs was from findpeaks, Simulink was unable to determine what size it would have, and so interpreted it to be variable-size with no upper bound (:?), as oppposed to when it was being initially defined as pks = zeros(size(u)) (like you had done) or 0 like dpb did.
This is apparently what happens with all(isfinite(u)) as well.
What finally made it work was to modify dpb's code as
function [dist,peak,loc] = fcn(u)
% findpeaks for input vector u and return three vector of
% [distance between first two peaks, first peak magnitude, first peak location]
% if no peaks found, returns zero for all three output variables
% assert(all(isfinite(u),'all'),'U contains NaN elements in Function fcn. Aborting')
dist=0; peak=0; loc=0; % initialize to zero
[pks,locs] = findpeaks(u);
if isempty(pks), return; end % No peaks, return zeros as indicator flag
peak=pks(1);
loc=locs(1);
if numel(pks)<2 % One peak only, dist == 0 returned
disp('Findpeaks Only One Peak in Function fcn. Warning')
return;
end
dist=locs(2)-locs(1);
end
Naufal Arfani
on 20 Jan 2021
Naufal Arfani
on 20 Jan 2021
and maybe you can try it @ARK
by changing the alpha block in my simulink by changing the initial value and final value to 1 or 5 as a condition where there is a misalignment, well there I need peak 3 and peak 4, can I get that then?
earlier I tried and error by saying again that the array is 1-1 sorry once again I still have things that are stuck
Naufal Arfani
on 20 Jan 2021
and if you want to know where do I get the value of nan in the output peak and locs findpeaks from this simulink by checking the simout value @ARK
dpb
on 20 Jan 2021
Edited: dpb
on 20 Jan 2021
"why on peak detection 1 and peak detection 2 the value of the peak and locs is not 0 like in peak detection and peak detection 3?"
You have to determine what you want/should return -- it is all up to you to determine and code what the function does with the various scenarios.
As the comment earlier above states, SIMULINK puts some limits on what can be returned for variable sizes from a MATLAB function; we don't know what your simulation groundrules should be; only you can determine that.
In the code above, if there are no peaks it's pretty clear there's nothing to return; if there are two or more it follows your initial code of returning the distance between the first two and the location, magnitude of the first.(*)
One peak wasn't supposed to be a possibility according to your first description so I started out with the error to let you know your model had failed in that regards; then you said you wanted to also try to go on anyways with that condition. So, I changed the code to return the one peak magnitude and location, but clearly there is no distance between peaks in that case so it's zero.
Perhaps it and the other case of zeros SHOULD be NaN so it's clear there was no solution. That's again a design decision on your end.
(*) Nota Bene: As written, the function returns information for the first two peaks found immaterial of how many were present. There could have been 104, we don't know; all we know is there were at least two, none, or only one. Anything more takes more logic to check...
dpb
on 20 Jan 2021
Edited: dpb
on 20 Jan 2021
", well there I need peak 3 and peak 4, can I get that then? "
If you want to return something about more peaks than two, you'll have to write the routine to test that you have however many there are that are needed and handle it.
But, you'll then also have to deal with the issue of how many outputs you can return to stay inside the limitations of SIMULINK outlined above, your routine will have to output the same number of outputs for all cases and have some way to know when it's supposed to output what.
Also, your model will have to have somehow to know what to do with the different cases.
Without knowing anything at all about whatever it is that you're simulating, I'd suspect that perhaps you really need to have findpeaks be more astute in the peaks it finds and returns based on charateristics of the input waveform...if there are sidepeaks or echos or something that is causing the determination of different numbers being detected the simple "find 'em all" default inputs may not be most appropriate.
But, those are all parts of your research/model-building; we can help you with the mechanics of making something run; we can't do much about whether there's any meaning in the results or not.
Naufal Arfani
on 21 Jan 2021
Thank you very much for the suggestion @dpb
I will try with the code before mine that I have that has successfully detected more than 1 peaks and combines it with code where there is no peak so that it can detect whether there is no peak or peak, although of course I still have a lot that I confused
dpb
on 21 Jan 2021
Edited: dpb
on 22 Jan 2021
Don't "just try" something; first sit down and design what it is that your application needs and expects on input and what the outputs are going to be, then write the code to do that.(*)
Remember that SIMULINK expects the same number of outputs all the time, every time unless you build a model that can switch between blocks depending upon what is returned.
As it is now, there's no place to return anything about more than two peaks as one set of location/magnitude values and a distance between that peak and another. If you add more, you have to do something about that...what is your call.
That's the thing -- what the function returns is totally arbitrary and up to you to decide what that should be and how many results are to be returned -- BUT: it has to have the same number every time and the model using those downstream has to know what they mean in order for it to make any sense. And only you know what any of it is supposed to mean and why there are a variable number of peaks and whether you're returning the correct ones each time the routine is called...as above, it's one thing to have something that runs; ensuring that it returns the correct answer is an entirely different issue.
The thing about the NaN is a complete red-herring -- the problem is/was totally one of the function not following the SIMULINK rules regarding the number of returned variables/signals being constant--so SIMULINK made up something for the missing ones.
(*) And, when you have done that, before running the simulation, test the MATLAB function thoroughly externally to ensure it behaves as you want it to with a sample of all of the types of input spectra the model will pass into it. Then, and only then, will you be able to know why you get what you get back instead of just throwing stuff blindly into a more-or-less black box and seeing what happens. Introduce some discipline and order into the process.
Athrey Ranjith Krishnanunni
on 22 Jan 2021
@Naufal Arfani I changed the alfa step input to have an initial value of 1 and final value of 5, and u does indeed have several peaks, but like dpb said, what to do with that information is not something I'd be able to tell you, because I don't know the physics of the system that you are simulating. That is not a programming problem and you'll probably have to figure that out on your own.
As to the other model that you attached for the NaN issue, it's in R2019b again. 😌
Answers (0)
See Also
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!An Error Occurred
Unable to complete the action because of changes made to the page. Reload the page to see its updated state.
Select a Web Site
Choose a web site to get translated content where available and see local events and offers. Based on your location, we recommend that you select: .
You can also select a web site from the following list
How to Get Best Site Performance
Select the China site (in Chinese or English) for best site performance. Other MathWorks country sites are not optimized for visits from your location.
Americas
- América Latina (Español)
- Canada (English)
- United States (English)
Europe
- Belgium (English)
- Denmark (English)
- Deutschland (Deutsch)
- España (Español)
- Finland (English)
- France (Français)
- Ireland (English)
- Italia (Italiano)
- Luxembourg (English)
- Netherlands (English)
- Norway (English)
- Österreich (Deutsch)
- Portugal (English)
- Sweden (English)
- Switzerland
- United Kingdom(English)
Asia Pacific
- Australia (English)
- India (English)
- New Zealand (English)
- ä¸å›½
- 日本Japanese (日本語)
- í•œêµKorean (í•œêµì–´)