MATLAB
syntax¶This script will introduce you to the syntax and various operations in the
MATLAB analysis language as well as introduce you to some image processing.
and sizing up E. coli. There are many different programming languages
(python
, C++
, java
, julia
, matlab
, etc.) that are all very useful for
scientists in every discipline. While we will use Matlab for this course,
We urge you to not subscribe to any language with religous fervor.
There are several options, buttons, and windows in the Matlab GUI. The two
most useful windows for you will the the editor (scripting window) and the
command window (>>
). The editor is where we will spend most of our time as
we write various scripts to perform analysis, simulations, and
calculations. However, the command window is good for testing small
snippets of code. The command window does not store your entries which is
why the editor window is so useful. To learn some of the Matlab syntax,
let's enter a few things into the command window.
1 + 1 % Should give us 2
2 * 8 % I believe this should be 16
exp(2) % This should be around 7.4
This are simple examples of basic operations one can do with Matlab. But at the same time, we can store values in memory as variables. Let's look at a simple example.
a = 10
Once a variable is defined we can do operations with it.
a * 4
And again save the output of these operations as a new variable.
b = a * 4
I'm sure you got the idea, but just for completeness I would add that you can do operations using only variables; for example
b + a * 5
Notice that every entry we have made so far has automatically been printed. We don't always want to see this, especially when we are generating huge tables or loading images. To suppress output, we simply need to add a semicolon (;
) to the end of the line.
c = a^100 % This will be printed
d = a^200; % This will NOT be printed
Another very useful feature from matlab is the ability of storing several entries into a single vector
or array
variable.
values = [0, 1, 1, 2, 3, 5, 8]; % Fibonacci sequence!
But what if I wanted to access let's say the 3rd element of this array? Well we can index the values on the array using parenthesis ()
.
values(3) % This should be a 1 since the third element of the array is 1
It is interesting to note that matlab stores everything as matrices by default. As a matter of fact the name MATLAB comes from MATrix LABoratory, not mathematics laboratory as people generally think. Our variable values
is actually a 1D matrix for example. We will exploit this feature a lot throughout the course.
There are several ways to generate arrays. A very useful one is to generate evenly spaced intervals. The syntax in matlab to generate this type of array is
begin:step_size:end
Let's look at a couple of examples
intervalOne = 1:1:10 % This will print numbers from 1 to 10 with spacing of 1
intervalTwo = 1:3:10 % This will print numbers from 1 to 10 with spacing of 3
Now that we have the basic syntax of Matlab down let's give it a test run on some real data.
In the following lines of code, we will use an image of a graticule to measure the distances between pixels of a camera. We will then use this value to place a scale bar on an image of cells, as should always be done in any scientific image.
We will begin by reading in the image of the graticule. Remember, an image is just data -- a simple two-dimensional array in which element corresponds to a pixel value.
% Change the working directory to where our data lives in case we are not there
cd('~/Documents/PhD/RPGroup-PBoC_github/mbl_pboc_2016/data/sizing_up_ecoli/')
% Read the image of the gradicule
gratIm = imread('Graticule100x.tif');
Let's take a look at the image to see what we are dealing with. For this we will use the function imshow
. Remember that an image is just a matrix with numbers. What imshow
does is simply assign a color to each of these numbers on a gray scale
imshow(gratIm);
Oh no! Our image appears to be only black! This is because the image is actually 12 bit, but is being displayed as a 16 bit image. There is information in those pixels, but they are simply being displayed on a different scale. We can rescale all of the pixels in this image as follows.
imshow(gratIm, []) % This should be a rescaled image.
Much better. This image shows a graticule -- a microscopic ruler. Each major division on this image is 10 microns apart. If we consider this image as an array, we see that if we were to go across a given row of the image, there would be a periodic oscillation in pixel values. Dark values would correspond to the ticks in the graticules while the white spaces would correspond to the spaces. Using this, let's extract the pixel value information for a single row in the image. Let's figure out what the size of the image is.
whos gratIm;
This tells us that the image is 982x1311
. To access to a row of values we need to learn how to index 2D arrays.
If you recall we saw that by using parenthesis ()
and a number we could access to any element on a 1D array. For a 2D array we use the same syntax except that we have (row, column)
in order to indicate the position in both dimensions of the array.
gratIm(444, 123)
If we now want to access an entire row of this matrix we can use a semicolon in the column
entry to indicate we want all of the entries from this row. Let's extract for example row 491.
lineProfile = gratIm(491, :);
We'll plot it against the length of the $x$ axis of the image.
But how can we obtain the length of the this axis? It is never a good practice to hard code numbers like this. In other words you wouldn't want to copy and paste the number that we obtained from printing whos gratIm
. That is why matlab has a full suite of useful functions such as length
that can be use for this.
Whenever you have a question about a function (or really anything in general) Google will be by far your best friend to answer those questions.
x = 1:1:length(lineProfile); % A vector from 1 to the length of the
%line_profile taking steps of 1.
plot(x, lineProfile, 'r-'); %Plot the line_profile in red.
% Every good plot should have labeled axis.
xlabel('x position');
ylabel('pixel value');
Just by zooming in on the image, we can see that there is a valley in the pixel value at about pixel number 100 and another at 250. This means that by our crude estimate, the disance between pixels is as follows
crudeIPDist = 10 / 150; % microns / pixel
which is about 66 nm. This is actually a pretty good measure. If we want to be a little more creative, we can use mouse clicks to record the positions of the valleys and take the difference between those. Let's give that a shot.
For this we will use the super useful function ginput
. ginput
stands for graphical input
and what it allows us is to click on any image in order to register the $x-y$ position of our clicks.
When creating this tutorial I cannot click directly on the image since the printed image is not an interactive object. But I did the following steps while working on the matlab terminal.
% With the lineProfile plot open I used this function
clicks = ginput(2); % This will register the x-y position of 2 clicks
% Then I click on two continous lines.
% The first column is the x-coordinate and the second is the y-coordinate.
% Taking the difference of the first two will give us the distance.
diff_clicks = clicks(2,1) - clicks(1,1);
click_ip_dist = 10 / diff_clicks;
Now I will violate our principle of never hard coding any number on a script. But this is a necessary violation only because I am not working directly on the matlab terminal.
clickIpDist = 0.0646;
This interpixel distance is about the same as we got by our crude estimate. Now that we have an idea of what the distance between pixels is, we can apply a scale bar to our image. Let's load it up.
cellIm = imread('Ecoli100x.tif');
Let's look at the image for fun
imshow(cellIm, []); % remember to rescale the pixel values!
Using the same procedure as we just did with ginput
determine the length of one of these bacteria. I will again hard code the numbers I obtained by doing the clicking directly on the matlab terminal.
cellClicks = [558.0000 402.0000; 532.0000 356.0000];
Note: The semicolon (;
) that I used in the middle of the array indicates matlab the end of a row in a 2D array.
Now how can we compute from these clicks the length of the bacteria if we only have x-y positions? You guessed it! Pythagoras taught us how to do this.
cellLenghtPix = sqrt((cellClicks(1, 1) - cellClicks(2, 1))^2 + ...
(cellClicks(1, 2) - cellClicks(2, 2))^2);
Now we can simply multiply the conversion factor between inter pixel distances and microns in order to obtain the length in microns.
cellLengthMicron = clickIpDist * cellLenghtPix % um
Not too bad! Let's put a 10 micron scale bar on our image. We can do that by changing a row of pixels 10 microns long on the image all to black.
% Obtain the number of pixels equivalent to 10 microns
scaleBarLength = 10 / clickIpDist;
% Generate a copy of the image where we will burn in the scale bar
imScaleBar = cellIm; %Copy the image
% Change the value of the pixels that will become the scale bar to zero
imScaleBar(950:970, 20:20 + round(scaleBarLength)) = 0;
imshow(imScaleBar, [])
Now this picture is ready for publication! You would just need to explain in the caption that the scale bar was set to 10 $\mu$m.
You can save this modified image using the following command
saveas(gcf, 'Ecoli_with_scalebar.tif'); %gcf = get current figure.