You can fit an
ELISA curve using free
software called R.
The 4 parameter model is:
y = (a-d)/[1+(x/c)^b]+d
You can solve for x:
x = c ((-a + y)/(d - y))^(1/b)
x is log concentrations, y is OD
signal read from your instrument.
Get your
data into a dataframe and take the log of the
concentration (R code in red):
############ Clears All Data ############
rm(list=ls())
############# Data input ##############
#input the data
stdcrvdata<-data.frame(conc=c(3,10,30,100,300,1000,3000,10000,30000), OD=c(.2,.22,.41,.75,1.07,1.18,1.2,1.27,1.29))
stdcrvdata$logconc <-log10(stdcrvdata$conc)
plot(stdcrvdata$logconc, stdcrvdata$OD, main="log standard curve", xlab="x=log(conc)", ylab="y=OD")
When you plot the
data you can see the top of the curve which equals parameter a and the bottom is parameter d. The inflection point on the curve is parameter c and b is the degree of curvature. Use these values for seeding your parameters in the next step. Play with the equation in excel to see what changing the numbers does.
Next step is the non-linear fit, the seeded/starting parameters are in start=list(). If you pick bad ones your fit will fail. I am using cc instead of c because I think c is a reserved letter (not sure).
############### fit the data ###############
fit <- nls(OD ~ d+(a-d)/(1+(logconc/cc)^b), data=stdcrvdata, start=list(d=0.2, a=1.5, cc=2, b=-11), trace=TRUE)
summary(fit)
Then lets plot the fit. Look at your original plot and find the lowest and highest x values you want to use. We make a list of numbers (mine go from .5 to 4.5)
############### Plot the results ###############
#this lets you graph your calculated equations nice and pretty
x <- seq(.5,4.5, length=100)
y <- (coef(fit)["d"]+(coef(fit)["a"]-coef(fit)["d"])/(1+(x/coef(fit)["cc"])^coef(fit)["b"]))
Then add a red line showing your fit to your already generated plot
lines(x,y, lty="dotted", col="red")
Next we have our unknowns, you can take the parameters calculated from R and use the equations in excel, or this is the R code.
Using the equation above and the parameters determined from fitting our model (stored in the object fit) we input our measured OD data into a dataframe called samples. Then we solve using the equation, convert the calculated log concentration to concentration and our answer is returned to us. The write.table outputs our data in a .csv format for inputting into excel.
############# Calculate unknowns #############
samples<-data.frame(OD=c(.27,.19,1.2))
samples$loganswer<-coef(fit)["cc"]*(((-1*coef(fit)["a"]+samples$OD)/(coef(fit)["d"]-samples$OD))^(1/coef(fit)["b"]))
samples$conc <- 10^samples$loganswer
samples
write.table(samples,file="mydata.csv",sep=",")
Finally, a little bit of checking, we plot our calculated data on our chart (in blue):
lines(samples$loganswer,samples$OD, type="points", col="blue")
Note that one of my samples (0.19) didn't return a value. This is because an OD of 0.19 lies outside of the curve I calculated.
Some problems that can occur:
You are dividing by zero somewhere, move your numbers around ie take the log and add 10.
stdcrvdata$logconcplus <-stdcrvdata$logconc + 10
You are taking the square root of a negative number - for example when solving for OD's where they lie outside the curve you have generated (i.e. bottom parameter = d = 2 and you are trying to calculate the concentration when an OD = 1.9). In my example I have one of these points and the result is NaN (a complex number).
You don't have enough data points, this will cause a fail in the curve fitting.
You need to pick better seeding/starting values for parameters.
########## cross posting #########
Please feel free to cross post this solution to other forums. R is a free program that anyone can download and run and does all the statistics that is necessary. The solution might be more difficult to implement but in the end can be easily automated and you know - free. Always free. When you move labs it's still free.