How to create a %of time vs %of area plot

Dear all,
I have the matrix A(1000x1000x120) which represents noise levels arranged as (longitude x latitude x time).
I want now to create a plot like the following one:
This plot represents the percentage of time that a specific noise level is exceeded in a percentage of area.
Can you give me some ideias how this can be done?
Thank you in advance,
RD

 Accepted Answer

There are a lot of missing details from your question that would need to be filled-in before someone can provide a good answer.
  1. How are you calculating area? You have latitude and longitude, and distance (and thus area) is not linear with latitude and longitude. You didn't indicate that you had a separate matrix that stores the actual latitude and longitude values. Does that mean you are OK assuming that a 1x1 square in latitude/longitude is a uniform area or do you want to take into account the actual latitude and longitude values? To do the latter, you likely will need the Mapping Toolbox to do the correct area calculations.
  2. Are your 1000x1000 locations a uniform grid of locations, or are they a random collection of 1 million data points. In other words, can you simply count the number of values above the noise threshold to get an approximation of area, or do you need to take into account that some data points represent larger areas than others?
  3. I assume you are interested in what percentage of time a single point exceeds the noise threshold, but that isn't specified. Imagine an ambulance driving down the street as the single source of noise, and the volume of the ambulance is such that it causes an area equal to 10% of your test area to exceed the threshold. At any one point in time the same area will exceed the noise threshold (10%), but that area will move, so one specific location may only exceed the noise threshold for a short time window. In that example, your graph could have a single point at 10% area for 100% of the time. Or, because the ambulance is moving, it could have a single point at 10% area at a much lower %time because any specific location only exceeded the threshold for a short time. I assume you want the later, not the former.
Making some assumptions, here is one idea:
I start with some random data, assuming a uniform grid of points, such that each data point represents a uniform amount of area. I have no idea what scale you are working on, so I'll just assume 0 to 1, and I'll pick an arbitrary threshold of 0.5.
noise = rand(1000,1000,120);
threshold = 0.5;
Now I want to find out what data values exceed the threshold. That is easy:
tooNoisy = noise >= threshold;
That gives a logical matrix (true/false) indicating whether each location exceeded the threshold at each point in time. Now I want to find out for how much time each point exceeded the threshold, so I'll simply sum in the third dimension, and convert into a percentage:
n = size(tooNoisy,3);
timeAboveThreshold = sum(tooNoisy,3)*100/n;
Now you want to find out how many points had each different timeAboveThreshold. There are a variety of ways to do this in MATLAB. My personal favorite is accumarray, but a lot of people find accumarray challinging to use, so instead I'll use histcounts. In addition, because you have 120 time points, you can have up to 120 unique values in your timeAboveThreshold matrix, so I'm just going to treat each unique value as distinct. If you had more time values, you may want to adjust the bin sizes, or let histcounts pick the bins for you.
% Create "edges" that surround each unique value.
centers = 100*(0:n)/n;
edges = 100*(-0.5:(n+0.5))/n;
N = histcounts(timeAboveThreshold(:),edges);
Now, assuming each data point represents a uniform area, you need to divide by the number of data points to get to percentage of area.
percentArea = N./(size(tooNoisy,1).*size(tooNoisy,2));
area(centers, percentArea)
hold on
plot(centers, percentArea, 'r*')
Of course, this is random fabricated data, so a bell-curve seems just about right.

6 Comments

Hello Benjamin, and first of all thank you for your help.
I will try to answer to your questions:
1) 1x1 square in latitude/longitude is a uniform area;
2) my 1000x1000 locations is a uniform grid of locations;
3) I'm interested in what percentage of time a the whole area points exceed the noise threshold
I think that the difference in the point 3) makes necessary some changes in the last two portions of code you described but I don't know how to change it.
Thank you,
The best I get so far is this:
which is clearly wrong.
This is my code:
threshold = 150; %limite maximo de ruido
percentageofareavector=[];
for i=1:120
tooNoisy = noise(:,:,i) >= threshold;
soma=sum(sum(tooNoisy)); %soma dos valores que excedem o limiar definido
totalnumberofpoints=(size(tooNoisy,1).*size(tooNoisy,2));
percentageofarea=soma*100/totalnumberofpoints;
percentageofareavector=[percentageofareavector percentageofarea];
end
timevector=1:size(noise,3);
percentageoftime=timevector*100/size(noise,3);
figure; area(percentageoftime, percentageofareavector);
xlabel('% of time'); ylabel('% of area');
title(['% of time vs % of area ', num2str(threshold),'dB is exceeded']);
What am I doing wrong?
Thank you in advance.
I think the issue is in how you are calculating the percentage of time.
timevector=1:size(noise,3);
percentageoftime=timevector*100/size(noise,3);
The first element of percentageoftime is being aligned with the first element of percentageofareavector. The first element of percentageoftime is 1/120, which isn't quite right, and doesn't necessary belong with the first element of percentageofareavector.
I'm pretty sure what you want to do is effectively bin the data in percentageofareavector. For example, based on your plot I it looks like the values within percentageofareavector range from about 15 to around 28. If you divide that into 5 bins, lets say 15 to 18, 18 to 21, 21 to 24, 24 to 27, and 27 to 30. It looks like there is only 1 value between 15 and 18, so that is 1 time out of 120, or 0.8% of the time. There looks like around 6 values between 21 and 24, so that would be 6 times out of 120, or 5% of the time.
You can do this calculation quite easily with histcounts, so I think what you want is something like this:
figure
[N,edges] = histcounts(percentageofareavector);
percentageoftime = N*100/120;
areacenters = (edges(1:end-1)+edges(2:end))/2;
area(percentageoftime, areacenters);
xlabel('% of time'); ylabel('% of area');
title(['% of time vs % of area ', num2str(threshold),'dB is exceeded']);
Also, note that your for loop can be condensed pretty easily into vectorized code by simply specifying which dimensions to sum over when you call the sum function, then calling squeeze to remove singleton dimensions:
tooNoisy = noise >= threshold;
soma=squeeze(sum(sum(tooNoisy,1),2));
Instead of squeeze, you can also try shiftdim:
tooNoisy = noise >= threshold;
soma = shiftdim(sum(sum(a,1),2),1));
Thank you once again Bejamin,
It seems better now
However I was expecting a different result taking into consideration the noise map I showed previously. The big yellow area in the noise map represents the area where the noise is higher than 180. For that reason it seems to me that the % of area is very little.
What do you think?
Thank you!
I don't recall seeing any noise map anywhere on this thread (and I don't see anything big and yellow on this post). But, regardless, I don't have your raw data, so I think the rest is up to you to analyze.
Thank you Benjamin!

Sign in to comment.

More Answers (0)

Categories

Products

Community Treasure Hunt

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

Start Hunting!