measuring and simulating the growth of a bacterial colony › labs › garcia › sites ›...

21
Measuring and simulating the growth of a bacterial colony Part I. Simulating exponential growth of a colony In Part I of this exercise, we'll simulate exponential growth and uncover its exponential functional form. Part II. Image segmentation to measure colony growth In Part II of this exercise, we will measure the growth of a bacterial colony from a series of images taken at 5 minute intervals. We will then compare our experimental results to those of our simulation. Part III. Finding the growth rate by chi-square fitting In Part III, we'll fit the data to get a best-estimate for the growth rate using chi-square minimization. Part I. Simulating exponential growth Here, we will simulate the growth of bacterial in order to reveal the exponential increase in cell number and compare it to the growth of our colony (Part II). We will then fit the data using chi-square minimization in order to get a best estimate for the colony's growth rate (Part III). Background If a cell doubles at a regular interval - e.g. splitting every 30 mins - growth follows the equation where is the number of cells at time t, and ris the growth rate in units of 1/min (the growth rate is related to how often the cells split in two). The above is a differential equation describing the rate of cell division. But to translate it into the number of cells in the colony at any given point in time, we're going to use a simple, but powerful, approach called Euler's method to simulate the change in the number of cells over time. Euler’s method is an algorithm for integrating the dynamics of a system given one or more differential equations describing the rate of change of system components (in our case cells), and an initial condition (how many cells we start with). Euler's method uses the slope of the tangent at time, t, to estimate the value of y at time . It follows the equation i.e. the rate of change, predicted at time t, multiplied by the length of the time step. More generally, for any given time, this is written as We're going to use the Euler method to find the numerical solution to the growth curve - i.e. to predict the number of cells that accumulate over time. We're first going to do this from a single cell; then we'll simulate 1

Upload: others

Post on 09-Jun-2020

2 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Measuring and simulating the growth of a bacterial colony › labs › garcia › sites › mcb.berkeley... · 2019-06-13 · Measuring and simulating the growth of a bacterial colony

Measuring and simulating the growth of a bacterial colony

Part I. Simulating exponential growth of a colony

In Part I of this exercise, we'll simulate exponential growth and uncover its exponential functional form.

Part II. Image segmentation to measure colony growth

In Part II of this exercise, we will measure the growth of a bacterial colony from a series of images taken at 5minute intervals. We will then compare our experimental results to those of our simulation.

Part III. Finding the growth rate by chi-square fitting

In Part III, we'll fit the data to get a best-estimate for the growth rate using chi-square minimization.

Part I. Simulating exponential growth

Here, we will simulate the growth of bacterial in order to reveal the exponential increase in cell number andcompare it to the growth of our colony (Part II). We will then fit the data using chi-square minimization inorder to get a best estimate for the colony's growth rate (Part III).

Background

If a cell doubles at a regular interval - e.g. splitting every 30 mins - growth follows the equation

where is the number of cells at time t, and ris the growth rate in units of 1/min (the growth rate is relatedto how often the cells split in two). The above is a differential equation describing the rate of cell division.But to translate it into the number of cells in the colony at any given point in time, we're going to use asimple, but powerful, approach called Euler's method to simulate the change in the number of cells overtime. Euler’s method is an algorithm for integrating the dynamics of a system given one or more differentialequations describing the rate of change of system components (in our case cells), and an initial condition(how many cells we start with).

Euler's method uses the slope of the tangent at time, t, to estimate the value of y at time . It follows theequation

i.e. the rate of change, predicted at time t, multiplied by the length of the time step. More generally, for anygiven time, this is written as

We're going to use the Euler method to find the numerical solution to the growth curve - i.e. to predict thenumber of cells that accumulate over time. We're first going to do this from a single cell; then we'll simulate

1

Page 2: Measuring and simulating the growth of a bacterial colony › labs › garcia › sites › mcb.berkeley... · 2019-06-13 · Measuring and simulating the growth of a bacterial colony

the growth of our actual colony growth and compare it to the growth rate we estimated from the imagingdata.

Running the simulation

In order to do this, we need to commit to model parameters (the growth rate and the starting number ofcells) and a set of parameters for the simulation (the time step we'll use, and the total time that we run thesimulation for). As we will discuss below, our results should depend on our model parameters, but theyshould be independent of our simultion parameters.

Let's start with the model parameters

r = 1/30; % Growth rate in min^-1N0 = 1; % Initial condition: number of cells at time point 0

Now, we need to think about our simulation parameters. One critical choice to make here is that of the timestep . How long should it be? For example, if you were simulating the movement of the Earth around theSun, would you choose a time step of one year or one day? Clearly, we would choose the latter. This isbecause we want our time step to be much smaller than the time scale of the system, which in this case if theEarth's orbital period. In the case of our simulation, our only time scale is given by

1/r

ans = 30

Such that we should our time interval should be smaller than 30 minutes. With this in mind, lets define thesimulation parameters

dT = 5; % Time step in minutes (the shorter this is compared to the doubling time, the better we will approximate the growth curve).TotalSteps = 50; % Total number of time steps

Note that we also defined TotalSteps, which tells Matlab how long to simulate growth for. In order to showthe consequences fo picking the wrong , we'll also define a long time step

dTlong = 45; % To see why this matters, we'll compare to when we use a longer timestep

Let's compute the number of cells at the first timepoint manually. The equation above enables us to calculatethe number of cells at the first time point (N1) as a function of the number of cells at the previous timepoint(N0), the growth rate (r) and the length of time for which we run the clock before counting the cells (dT).

N1 = N0 + N0* r * dT

N1 = 1.1667

Now we'll do the same thing for all the subsequent timepoints.

First we need to initialise an array, N, into which we'll save the number of cells at each step. The first entry inthis array is going to be the number of cells at t=0

2

Page 3: Measuring and simulating the growth of a bacterial colony › labs › garcia › sites › mcb.berkeley... · 2019-06-13 · Measuring and simulating the growth of a bacterial colony

N(1) = N0;

We will also define an array for a simulation with the long time step given by

Nlong(1) = N0; % array recording the number of cells when using a longer time step (the starting number of cells is still the same though)

In order to automate this process, we will use a for-loop. This is a very handy function that is described indetail in Matlab Tutorial 2: Working with for-loops. In short, let's say I want to multiply every numberbetween 1 and 10 by 2. I can do this using a for-loop as follows

for Counter=1:10 Counter*2end

ans = 2ans = 4ans = 6ans = 8ans = 10ans = 12ans = 14ans = 16ans = 18ans = 20

Here, 1:10 defines a range of numbers spaced by one

1:10

ans = 1×10 1 2 3 4 5 6 7 8 9 10

For every iteration fo the for-loop the variable Counter acquires a value between 1 and 10. Then, for eachof these iterations, the for-loop executes the instructions inside of it. In this case, to multiply the particularvalue Counter has adopted by 2.

Let's now use will now use a for loop to record the number of cells at all subsequent timepoints (rememberthat the first time point was already defined by our initial condition)

for i = 2:TotalSteps % remember that the first entry is already filled! % Use the above equation to calculate the number of cells at time i N(i) = N(i-1) + r * N(i-1) * dT; Nlong(i) = Nlong(i-1) + r * Nlong(i-1) * dTlong; % Generate a time vector to plot this data against TimeVectSim(i) = (i-1)*dT; TimeVectSimLong(i) = (i-1)*dTlong; end

3

Page 4: Measuring and simulating the growth of a bacterial colony › labs › garcia › sites › mcb.berkeley... · 2019-06-13 · Measuring and simulating the growth of a bacterial colony

Plotting the results of the simulation

plot(TimeVectSim, N)xlabel('Time (mins)')ylabel('Number of cells')

If this is truly an exponential then if we plot it on a log-scale on the y-axis we should see a straight line. Wecan do this using the semilogy command. Let's compare the two simulations that used different timesteps.

semilogy(TimeVectSim,N)hold on % In order to plot the simulation with the longer timestep on the same plot, use the 'hold on' commandsemilogy(TimeVectSimLong,Nlong)xlabel('Time (mins)')ylabel('Number of cells')legend('Time step = 5 mins', 'Time step = 45 mins') % Add a legend to the plot hold off % To prevent subsequent graphs being plotted on these same axes

4

Page 5: Measuring and simulating the growth of a bacterial colony › labs › garcia › sites › mcb.berkeley... · 2019-06-13 · Measuring and simulating the growth of a bacterial colony

You can see from the plot that the longer timestep produces a lower estimate for the number of cells in acolony than does the shorter timestep. In order to make sure that your choice of a time step of 5 minutesis correct, you should re-run the simulation with an even smaller time step and verify that the results don'tchange. Despite its simplicity, we will use this powerful Euler method again and again when we solvedifferential equations.

Part II. Image segmentation to measure colony growth

Segmenting an image

In order to measure the size of the bacterial colony we need to segment each image. First let's do this for asingle image in order to find a suitable threshold to use.

Open any colony image using the imread function. The images are contained in the folderColonyGrowthData (which should be in your current folder); therefore we must tell matlab to navigate there.

image = imread('ColonyGrowthData/colony_growth_25.tif');imshow(image) % Display the image

5

Page 6: Measuring and simulating the growth of a bacterial colony › labs › garcia › sites › mcb.berkeley... · 2019-06-13 · Measuring and simulating the growth of a bacterial colony

Explore the pixel values using the "Inspect pixel values" tool in imtool(image) in order to manually find asuitable threshold for segmentation. This is the second icon from the left on the tool bar in imtool. You willnotice that cells have brigher pixel values because they are fluroescently labeled, and that a threshold ofaround 100 could be use to separate cells from the background.

What does it mean to draw a threshold? In order to illustrate this, let's invoke a simple example of a vectorgiven by

a=[2,4,1,6,4,3];

Let's draw a threshold of 3 over this vector. The idea is to select those elements in the vector that have avalue larger than 3.

a>3

ans = 1×6 logical array 0 1 0 1 1 0

Note how Maltab went through each element of the vector a and asked "are you larger than 3?". If true, thenMatlab returned a 1, and otherwise it returned a 0. As an image is just a matrix of pixel values, we can applythis same concept to draw a threshold on the image and segment the colony by doing

threshold = 100;

6

Page 7: Measuring and simulating the growth of a bacterial colony › labs › garcia › sites › mcb.berkeley... · 2019-06-13 · Measuring and simulating the growth of a bacterial colony

ImThresh = image > threshold;

Let's see who well our choice of threshold did at segmenting the colony.

imshow(ImThresh)

Not too bad! Once again, the result is ImThresh, which is a logical array - i.e. each pixel that's over thethreshold = 1 and the rest = 0. This means that you can find the area of the colony by summing up all thevalues in ImThresh. To make this possible, we introduce the sum command, which sums all elements of avector. For example, let look once again at our vector a

sum(a)

ans = 20

It is important to note how sum works on a matrix such as our image. Let's make a small matrix called b

b=[1,2,3;4,5,6;7,8,9]

b = 3×3 1 2 3 4 5 6 7 8 9

7

Page 8: Measuring and simulating the growth of a bacterial colony › labs › garcia › sites › mcb.berkeley... · 2019-06-13 · Measuring and simulating the growth of a bacterial colony

If I apply sum to b I get

sum(b)

ans = 1×3 12 15 18

which is the sum over all columns. If I apply sum once more I get

sum(sum(b))

ans = 45

Which is the sum of all elements within the matrix.

Calculating the colony size for all images

Now we know how to find the area for one image, we can do this automatically for all the images using a for-loop.

First make a list of all the names of the images to run through. We can do this using dir.

FileList = dir('ColonyGrowthData/*.tif');

The asterisk is called a wildcard. It instructs Matlab to find all files ending with what comes after it. Also, notethat Matlab doesn't care about the use of "/" vs. "\". Let's take a look at FileList

FileList

FileList = 37×1 struct array with fields: name folder date bytes isdir datenum

FileList is a "structure array". This is a data type that can contain multiple fields, and where eachfield can contain different types of information. For example, the name field will have the file name whichis a string (text), while the bytes field will contain a number corresponding to the size of each file. Notethat FileList has 37 elements, each one corresponding to one frame in our movie. If we want to pull all theinformation corresponding to file number 12, we do

FileList(12)

ans = struct with fields: name: 'colony_growth_11.tif' folder: 'C:\Users\herna\Documents\Courses\TeachingCode\Ecoli\Colony Growth\ColonyGrowthData' date: '15-Jun-2016 08:59:40' bytes: 148783 isdir: 0

8

Page 9: Measuring and simulating the growth of a bacterial colony › labs › garcia › sites › mcb.berkeley... · 2019-06-13 · Measuring and simulating the growth of a bacterial colony

datenum: 7.3650e+05

If you want to get a specific field such as the file name, you have to do

FileList(12).name

ans = 'colony_growth_11.tif'

If I want to load that image, however, I need to specify more than the file name. I also need to tellMatlab where the file is (what folder it's in). As a result, I need to concatenate a string corresponding to thefolder with the string for the file name. Strings are concatenated as follows

a='Hel'

a = 'Hel'

b='lo'

b = 'lo'

[a,b]

ans = 'Hello'

Such that for our file we need to do

['ColonyGrowth/',FileList(12).name]

ans = 'ColonyGrowth/colony_growth_11.tif'

Now, we are ready to analyze these images. First, we pre-allocate an array in which to store all the areas aswe calculate them

Area = zeros(1,length(FileList)); % This is a preallocated array of zeros % We'll do the same for the time at which each image was takenTimeInterval = 5; % the interval between image acquisitions (in minutes)TimeVect = []; % this is another way to preallocate an array

Now loop through all the images, opening each, segmenting them using the threshold we defined above, andfinding the area of the colony

for i = 1:length(FileList) image = imread(['ColonyGrowthData/',FileList(i).name]);

9

Page 10: Measuring and simulating the growth of a bacterial colony › labs › garcia › sites › mcb.berkeley... · 2019-06-13 · Measuring and simulating the growth of a bacterial colony

ImThresh = image > threshold; Area(i) = sum(sum(ImThresh)); % sum over the columns and the rows to find the total area TimeVect(i) = TimeInterval*(i-1); %this gives us the time at which each area is measuredend

Evaluating our movie segmentation

How well did we do? In order to check this, let's show a movie of our segmentedsnapshots. IMPORTANT: Live-scripts don't work well with movies just yet. As a result we need to copythe following lines of code to the command window and execute them there. You can do this by justcopying and pasting, or by selecting the code below, right clicking, and selecting "Evaluate selectionin Command Window". In the for-loop below, we just copied the lines that perform the segmentation fromthe plot above. In addition, we added figure(1) which forces all images to be displayed in the same figureand for that figure to be brought to the front of the desktop. Finally, we also added drawnow, an uninterestingbut necessary command that forces Matlab to display one image before moving on to the next one.

for i = 1:length(FileList) image = imread(['ColonyGrowthData/',FileList(i).name]); ImThresh = image > threshold; figure(1) imshow(ImThresh) drawnowend

10

Page 11: Measuring and simulating the growth of a bacterial colony › labs › garcia › sites › mcb.berkeley... · 2019-06-13 · Measuring and simulating the growth of a bacterial colony

We see that we did pretty well in the later time points of the movie, but that the segmentation captured someextra "noise" in the earlier time points. Let's see below how this all affects our plot of colony size vs. time.

Plotting colony growth

plot(TimeVect,Area, '.') % '.' causes the data to be plotted as points rather than a continuous linexlabel('Time (mins)')ylabel('Colony Area (pixels^2)')title('Colony Growth')

11

Page 12: Measuring and simulating the growth of a bacterial colony › labs › garcia › sites › mcb.berkeley... · 2019-06-13 · Measuring and simulating the growth of a bacterial colony

This plot shows what looks like exponential growth. To get a better sense of this we can plot our data on alog scale on the y-axis using semilogy. In this representation of the data, exponential growth will appear asa straight line.

semilogy(TimeVect,Area, '.') xlabel('Time (mins)')ylabel('Colony Area (pixels^2`)')title('Colony Growth (log scale)')

12

Page 13: Measuring and simulating the growth of a bacterial colony › labs › garcia › sites › mcb.berkeley... · 2019-06-13 · Measuring and simulating the growth of a bacterial colony

Not too bad! We expected, the first time points weren't great, but the segmentation improved dramaticallyafter 40 minutes. From the linear plot, we can estimate the doubling rate by eye. For example, the colony hada size of 4000 pixels at 105 min, and a size fo 8000 pixels at 140 min. This would correspond to a doublingrate of approximatelly 35 min and a growth rate given by

1/35*log(2)

ans = 0.0198

per minute. We can now performed a move informed estimate using chi-square minimization in Part III.

Part III. Chi-square minimisation to find the best fit value for the growthrate

Introduction to the Chi-square statistic

What we want to do is to estimate the value of r, the growth rate, that best describes the data we have (thegrowth of the bacterial colony) under a given model - the model of exponential growth. In other words, we'retrying to find the most representative value of the growth rate.

13

Page 14: Measuring and simulating the growth of a bacterial colony › labs › garcia › sites › mcb.berkeley... · 2019-06-13 · Measuring and simulating the growth of a bacterial colony

But what do we mean by "best describes" the data? Let's think about an imaginary set of data in which x andy are linearly correlated (below). We can draw a line through this data, , where a is the slope, whichis the parameter we want to estimate.

Intuitively, we can imagine that the best estimate of a is the value where the difference of each data point andthe line resulting from our model is the smallest. These values are the residuals.

If we assume that the error in this data is Gaussian distrubuted - i.e. that there are no outliers - then we canuse the statistic to compute the sum of the squares of the residuals for a range of values of a, and thenfind where this sum is at its minimum.

The equation for this is:

Here, is the ith datapoint, is the predicted value of y, given a specific value of a, and is the

variance of the data.

In our specific case, it is

14

Page 15: Measuring and simulating the growth of a bacterial colony › labs › garcia › sites › mcb.berkeley... · 2019-06-13 · Measuring and simulating the growth of a bacterial colony

where N is the simulated colony area, given value for the growth rate, r, and Area is the actual area of thecolony that we measured in Part I. We can ignore here as we will asssume that all data points have the

same error.

Note that Matlab has built-in functions that will perform this fitting for you - see for instancethe lsqnonlin function. But it is always important to understand how such functions actually work, which iswhy we have gone about it manually here.

Fitting the data to find the best-fit growth rate

In Part II we measured the area of the bacterial colony over time, which we stored in the variable Area. Wealso recorded the time from the start of the image series at which each frame was taken, which we storedas TimeVect. When we plotted the area over time (repeated below as a reminder!), we saw that the initial tenor so data points do not lie on a straight line when plotted on a semi-log scale.

semilogy(TimeVect,Area,'.k')xlabel('Time (min)')ylabel('Colony Area (pixels^2)')

This means that the measured colony area is not growing exponentially during those first timepoints - i.e.that an exponential model of growth does not accurately describe these data. In the subsequent anaylsisbelow, we are therefore going to restrict ourselves to fitting just the portion of the data that appear to reflect

15

Page 16: Measuring and simulating the growth of a bacterial colony › labs › garcia › sites › mcb.berkeley... · 2019-06-13 · Measuring and simulating the growth of a bacterial colony

exponential growth - that is, the data from timepoint 10 onwards. We can select the range of the data wewant to use as follows:

Area(10:end); % If you remove the ; this will print out just the values of Area from timepoint 10 onwards.

Let's plot the full range of data compared to the filtered range

semilogy(TimeVect,Area,'.k')hold onsemilogy(TimeVect(10:end),Area(10:end),'or')hold offxlabel('Time (min)')ylabel('Colony Area (pixels^2)')legend('All Data','Filtered Data')

Calculate the error between data and prediction for one value of r

To find the best-fit value of the growth rate, we need to define a range of growth rates over which to searchfor the one that best describes the data. We know that bacteria divide around once every 30 mins - that is,there is one doubling event every 30 minutes. This translates into a growth rate, of ln(2)/30, which is ~0.02. So it seems reasonable to sample a range of growth rates around this value:

16

Page 17: Measuring and simulating the growth of a bacterial colony › labs › garcia › sites › mcb.berkeley... · 2019-06-13 · Measuring and simulating the growth of a bacterial colony

rRange = 0.01:0.00001:0.03; % start : increment : end

What we want to do is find the difference between our data and the colony size predicted by simulatingexponential growth with different growth rates. We'll then find the growth rate at which the error is smallest,and this will be the best fit rate. We'll demonstrate this first using one test value for the growth rate from theabove range - we'll pick 0.02.

rTest = 0.02;

Before we can compare the data to our simulation of exponential growth, we need to calculate the area of thecolony using this test value of

Above, we did this using the Euler method, by looping through this equation for each time point

The analytical solution to that equation is

where is the number of cells at t = 0 (i.e. the initial condition). We're going to use this equation to find the

number of cells at each timepoint, .

As we saw above, in order to simulate the growth of the colony, we need to specify an initial condition;because we're using just timepoints 10 and onwards, the initial condition is the area of the bacterial colony atthe 10th timepoint.

StartPoint = 10; % time point 10, at 50 mins into the timecourse

Let's redefine our data set such that it begin at StartPoint.

Data = Area(StartPoint:end); % Define the range of the data you will use, for simplicity's sakeInitialCondition = Data(1); Time = TimeInterval*(0:length(Data)-1); % Time vector for fitting (TimeInterval is 5 mins - defined earlier)

Now we're going to employ the chi^2 equation (see above) to calculate the difference between our data andthe prediction based on a growth rate of 0.02.

theoryTest = InitialCondition * exp(rTest* Time);chiSqTest = sum((theoryTest-Data).^2)

chiSqTest = 4.2272e+07

Finally, let's see how well our fit does

semilogy(Time,Data,'k.') % our datahold onTimeVectFit = Time + 10*TimeInterval; % because we only data from timepoint 10 (50 mins), % we need to start our time vector at 50 mins for plotting (frame 10 * 5 min intervals)semilogy(Time,InitialCondition*exp(rTest*Time), 'r') % best fit linehold off

17

Page 18: Measuring and simulating the growth of a bacterial colony › labs › garcia › sites › mcb.berkeley... · 2019-06-13 · Measuring and simulating the growth of a bacterial colony

xlabel('time starting from time point 10 (mins)')ylabel('colony Area (pixels^2)')legend('data', 'guess')

This was a pretty good first guess! We'll now estimate the best growrth rate by minimizing chi-square.

Calculate the statistic for all values of r

Repeat the above, now looping through all values of r in rRange to compute the statistic for each one.

for i = 1:length(rRange) Theory = InitialCondition * exp(rRange(i)*Time); chiSq(i) = sum((Theory - Data).^2);end % Plot the chi-square for each value of rsemilogy(rRange, chiSq, 'o')xlabel('Growth rate, r (mins^-1)')ylabel('\chi^2 statistic')title('\chi^2 for a range of growth rates')

18

Page 19: Measuring and simulating the growth of a bacterial colony › labs › garcia › sites › mcb.berkeley... · 2019-06-13 · Measuring and simulating the growth of a bacterial colony

We can see that there's a minimum! (Remember, the smaller the sum of the squared residuals, the better).By zooming in on the minimum and using the data cursor, we can estimate by eye the best-fit value of r.We'll define this as rFit.

rFit = 0.0186; % best fit growth rate, estimated by eye

You could also look for the minimum using the funtion min. This corresponds to a doubling time of

DoublingTime = log(2)/rFit

DoublingTime = 37.2660

It looks like the doubling rate is on the order of 37 minutes, which is close to our expectation of the doublingrate for E.coli of ~30 mins.

Let's now calculate the predicted growth curve, given the rFit we obtained. To do so we'll use the differentialequation for exponential growth; remember, we are using only the datapoints from t = 10, and that must bereflected in this prediction.

bestFit = InitialCondition*exp(rFit*Time);

19

Page 20: Measuring and simulating the growth of a bacterial colony › labs › garcia › sites › mcb.berkeley... · 2019-06-13 · Measuring and simulating the growth of a bacterial colony

Plot the best fit of our data

semilogy(TimeVect,Area,'k.') % our datahold on TimeVectFit = Time + 10 * TimeInterval; % because we only data from timepoint 10 (50 mins), % we need to start our time vector at 50 mins for plotting (frame 10 * 5 min intervals)semilogy(TimeVectFit,bestFit, 'r') % best fit linehold offxlabel('Time (mins)')ylabel('Colony Area (pixels^2)')legend('Data', 'Fit')

In conclusion

In this tutorial, we have

• Segmented images to quantify colony growth• Simulated exponential growth of a colony• Used chi-squared minimisation to find the growth rate that best describes our data, given the

assumption of exponential growth

20

Page 21: Measuring and simulating the growth of a bacterial colony › labs › garcia › sites › mcb.berkeley... · 2019-06-13 · Measuring and simulating the growth of a bacterial colony

In the final section, we defined a range of r over which to calculate the statistic. We zoomed in onthe minimum in order to choose by hand a value of r that appeared to minimise the sum of the squaredresiduals. This is useful for demonstrating how minimisation works from a pedagogical standpoint, butthere are two immediate issues with the approach.

• We only searched over a range of r's that we specified using linspace. If we were to choose morevalues of r, we would get a more precise estimate of the minimum.

• We were only trying to fit one parameter in a simple function. Fitting for two or more parameters getsmuch more complicated with the statistic, and you may end up with multiple local minima thatcould lead you to mis-identify the best-fit parameter value.

For these reasons, it's best to use a more complex algorithm to fit parameters. A common non-linearregression approach is the Levenberg-Marquardt algorithm. In Matlab, the lsqnonlin function usesessentially this algorithm.

21