I need this in my Biology class ... using MATLAB! - matlab

I'm trying to monitor the average temperature in a fabrication every hour to ensure quality control. How can I write a script that looks at the temperature inside the plant as a function of time, and outputs the times when the temperature drops below 10 degrees Celsius and when the temperature is above 80 degrees Celsius. My script should say when the temperature is out of the boundary and what the temperature is. I wanna Use the following data:
Temperature = [-15 -5 5 15 24 33 42 51 59 66 73 79 85 90 78]
The first measurement is made at 5am, the last measurement is made at 7pm. I wanna display the time in a 24 hour system instead of a 12 hour system.

It looks like you'll need to loop through the elements of the Temperature vector and find which ones are either below 10 degrees OR above 80 degrees. In a traditional programming language you would use a FOR loop to go through the elements of an array or vector, but generally in MATLAB you want to avoid FOR loops if you can and instead take advantage of MATLAB's vectorization, because it's much faster.
You'll want to look into the FIND function (type 'help find' into the console for more information). But, for example if I had a vector:
A = [0 1 2 1 2 1 1 0];
And used
find(A==0)
The output would be a vector of the indices of A where the element is equal to 0:
[1 8]
I could similarly do:
find(A==1 & A==0)
And I would get
[1 2 4 6 7 8]
This is useful because while traditionally you access the elements of a vector with an index, you can access the elements of a vector in MATLAB with another vector. For example:
>> A = [-10 4 -2 3];
>> ind = [2 3];
>> A(ind)
ans =
4 -2
MATLAB also makes the syntax a bit easier, because you can use the following shortcut instead of explicitly using the FIND function:
>> A = [-10 4 -2 3];
>> A( A<-5 | A>3)
ans =
-10 4
Which would be the same as using the FIND function:
>> A(find(A<-5 | A>3))
ans =
-10 4
I hope this helps. Sorry for the long post. It takes some time to get used to MATLAB's vectorized way of writing code, but once you do get used to it, you'll find it's very useful for computation.

You could crate a 'time' vector like this:
time = 5:1:19;

Related

Finding repeating pairs of specific numbers within column (Matlab)

I'm stuck on this probably very trivial problem.
I have a matrix like this (just much larger):
A = [1 3 4 8 10 12 14 17 19; 5 30 90 30 50 70 5 30 5]'
I'm now looking for pairs of specific numbers in A(:, 2). For example, I'd like to find all 30s that are preceded by 5s in A(:, 2) and extract the corresponding row in A(:, 1).
So I'd like to end up, in this example, with B = [3, 17];
How can I do that in Matlab? Any help much appreciated.
You can run:
num_wanted=30;
num_previous=5;
is_match=[ false; A(1:end-1,2)==num_previous & A(2:end,2)==num_wanted ]; %the first element cannot be a match
A(is_match,1).',

Matlab figure and truncating data

xlim command changes the axis limit of the figure.
How can i also limit data that is contained by the figure?
Apparently, even though xlim is applied data is still there.
Example: let's say i have a data set of 5000 elements. but only 1500 elements are shown in a figure. when i save this figure, it will still contain data that is not shown in the figure.
The answer may be particularly useful for people working with matlab2tikz.
Yes, the data are still there. To remove data, use something like this:
>> plot(1:10,(1:10).^2); % just an example
>> h = get(gca,'Children');
>> x = get(h,'XData')
x =
1 2 3 4 5 6 7 8 9 10
>> y = get(h,'YData')
y =
1 4 9 16 25 36 49 64 81 100
>> set(h,'XData',x(2:5), 'YData',y(2:5))
>> set(h,'XData',x(2:5), 'YData',y(2:5))

index of first greater than during two array comparison

I have two arrays threshold and values.
threshold=[10 22 97]
values=[99 23 77 11 8 10]
I want to output idx such that threshold(idx-1)<values(i)<=threshold(idx). That is for the above example output will be
output=[4 3 3 2 1 1]
The naive code that can produce above output will be
output=ones(1,length(values))*(length(values)+1);
for i=1:length(values)
for j=1:length(threshold)
if(values(i)>threshold(j))
output(i)=j;
end
end
end
Is there a simple way of doing it. I want to avoid loops.
You can use histc command, with a slight adjustment of threshold array
>> threshold=[-inf 10 22 97 inf];
>> values=[99 23 77 11 8 10];
>> [~, output] = histc( values, threshold+.1 )
output =
4 3 3 2 1 1
The modification of threshold is due to "less-than"/"less-than-equal" type of comparison for bin boundary decisions.
No loops often means you'll gain speed by increasing peak memory. Try this:
threshold = [10 22 97];
values = [99 23 77 11 8 10];
%// Do ALL comparisons
A = sum(bsxfun(#gt, values.', threshold));
%// Find the indices and the ones before
R = max(1, [A; A-1]);
%// The array you want
R(:).'
If you run out of memory, just use the loop, but then with a find replacing the inner loop.
Loops aren't all that bad, you know (if you have MATLAB > R2008). In theory, the solution above shouldn't even be faster than a loop with find, but oh well...profiling is key :)

Matlab - Sum of surrounding elements

I want to calculate the sum of the elements surrounding a given element in a matrix. So far, I have written these lines of code:
for i=1:m,
rij(1:n)=0
for j=1:n,
alive = tijdelijk(i-1,j)+tijdelijk(i+1,j)+tijdelijk(i-1,j-1)+tijdelijk(i+1,j-1)+tijdelijk(i,j+1)+tijdelijk(i,j-1)+tijdelijk(i-1,j+1)+tijdelijk(i+1,j+1)
This results in an error because, for example, i-1 becomes zero for i=1. Anyone got an idea how to do this without getting this error?
You can sum the elements via filtering. conv2 can be used for this manner.
Let me give an example. I create a sample matrix
>> A = reshape(1:20, 4, 5)
A =
1 5 9 13 17
2 6 10 14 18
3 7 11 15 19
4 8 12 16 20
Then, I create a filter. The filter is like a mask where you put the center on the current cell and the locations corresponding to the 1's on the filter are summed. For eight-connected neighbor case, the filter should be as follows:
>> B = [1 1 1; 1 0 1; 1 1 1]
B =
1 1 1
1 0 1
1 1 1
Then, you simply convolve the matrix with this small matrix.
>> conv2(A, B, 'same')
ans =
13 28 48 68 45
22 48 80 112 78
27 56 88 120 83
18 37 57 77 50
If you want four-connected neighbors, you can make the corners of your filter 0. Similarly, you can design any filter for your purpose, such as for averaging all neighbors instead of summing them.
For details, please see the convolution article in Wikipedia.
Two possibilities : change the limits of the loops to i=k:(m-k) and j=k:(n-k) or use blkproc
ex :
compute the 2-D DCT of each 8-by-8 block
I = imread('cameraman.tif');
fun = #dct2;
J = blkproc(I,[8 8],fun);
imagesc(J), colormap(hot)
There are lots of things you can do at the edges. Which you do depends very specifically on your problem and is different from usage case to usage case. Typical things to do:
If (i-1) or (i+1) is out of range, then just ignore that element. This is equivalent to zero padding the matrix with zeros around the outside and adjusting the loop limits accordingly
Wrap around the edges. In other words, for an MxN matrix, if (i-1) takes you to 0 then instead of taking element (i-1, j) = (0, j) you take element (M, j).
Since your code mentions "your teacher" I'd guess that you can ask what should happen at the edges (or working it out in a sensible manner may well be part of the task!!).

Matlab How to easily loop round array

Hi i'm looking for a way to take a slice of an array from the near the end to near the beginning. I know I could do this in two parts, then add them, but it seems like such a commonly desired operation I thought matlab probably already has it built in but I couldn't find any information in my search.
To clarify I would like to be able to say:
y = 1:10
y(-3:3) or y(8:3)
returns:
8 9 10 1 2 3
Thanks in advance.
there actually is a way to do it (without splitting it up in a concatenation of the negative and positive part of indices): use the modulo operator on your desired range:
>> y = 1:10;
>> y(mod([-3:3]-1,numel(y))+1)
ans =
7 8 9 10 1 2 3
This result consists of 7 numbers (opposing your desired [8 9 10 1 2 3]), which is logical because -3:3 actually spans 7 numbers.
The number 0 would correspond to y(end) with this method, -1 would correspond to y(end-1), etc.
You can try this:
y = 1:10;
n = 3;
y([end-n+1:end 1:n]);
This returns
ans =
8 9 10 1 2 3