-
Notifications
You must be signed in to change notification settings - Fork 2
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ED50 extrapolation is not where the curve intersects y=50 #1
Comments
Looking at the fit-curve on the plot, the curve itself doesn't flatten until above 100, and the lower limit is above 0. While the data might be normalised between 0 and 100, the fitted model isn't. The EC50 you are getting (67.3) is the correct one from the model, working from the data provided. If you wanted a model that was more normalised to 50% cell death being the 50% response in the model, you will need more data points to the right-hand side of the plot that flattens out the response at 100 - and more to the left that flattens it better around 0. See example below that uses your provided data (with some additional points below and above) that fits the model with an EC50 that better represents the "50 % Response". library(tidydrc)
#Make a data frame of dose-response results (response signifies pre-normalized %Cell Death values)
#As a ground truth, we have dose of 59.375 equals response of 50.000
mydr <- data.frame("dose"=c(7600, 3800, 1900,950,475,237.5,118.75,59.375,29.68,14.84,7.42,3.71, 1.855, 0.96, 0.45, 0.23),
"response"=c(99.50, 99.01, 98.38,96.267,93.300,91.1,53.56,50.000,44.2,24.1,15.5,9.01, 4.5, 2, 1, 0.5))
#Apply the LL.4 model to fit a log-logistic curve
mydr.LL4 <- tidydrc_model(mydr, dose, response, model=LL.4())
#Extract the EC50 value
mydr_EC50 <- as.data.frame(as.numeric(mydr.LL4[[4]][[1]][4,2]))
#Plot the curve
#ed50=TRUE plots a dashed black line according to the extrapolated EC50
#ground truth lines are in red. y-axis=50, and x-axis=59.375
tidydrc_plot(mydr.LL4,ed50=TRUE) +
scale_x_log10(labels=log10) +
xlab("Log10[concentration]")+
ylab("% Cell Death") +
geom_hline(aes(yintercept=50), linetype=1, color="red") +
geom_vline(aes(xintercept=59.375), linetype=1, color="red")+
geom_point(aes(x=dose, y=response), size=2.4, color="blue") +
geom_text(aes(x=10,y=100,label=paste0("Fitted_EC50: ",round(mydr_EC50,3)))) The problem is not in the package or the model - but the slightly-incomplete data that the model was working from. |
Thanks for this reply! Yes, I also found that when having a dataset whose lowest value is at 0 and whose highest is at 100 does capture a true EC50. The problem being that in real-world experiments this is not always going to be the case. In high-throughput settings experiments are usually limited by the total amount of doses that are achievable. The design is definitely to attempt the lowest concentration to approach zero (%cell death, for example) and the highest 100, but that certainly isn't always the case. That being said, if the proper controls were used for normalization it would not matter if the highest point was, say, 60%.
The EC50 is the concentration that kills 50% of the cells, not the concentration that is 50% of that specific drug's maximum effect. If no controls are used for normalization, there is no choice but to take 50% of the max. Sometimes the minimum and maximum responses are even (erroneously) set as the 0 and 100% constraints. Our example here represents something we see fairly frequently, and the true EC50 is not captured using this default method. It's not an issue of dataset completeness, but I guess probably one of 'take y=50? or take 1/2 max effect?' and I'm thinknig the answer would depend on whether the input is normalized or not. In most cases I don't think there would be much of a difference, but in cases like these I'll just continue to implement the little 'add-on' mentioned previously to make sure the 'most' accurate EC50 is captured. Thanks again, |
Hey Angel - Thanks for the great work on this package!
This issue relates to the ED50 calculation being off from where the curve intersects at y=50. Here, I use normalized data (constrained within 0-100) and attempt to extract an ED50 closer to the ground truth.
We can see the dashed line is off, calling the ec50 as 67.29, when we know it is 59.375
Could this be due to extrapolating 50% of the curves maximal effect, and not considering the constriants of 0-100 imposed by the pre-normalized data?
The new EC50 gets much closer.
Thoeretically, some datasets may have a response point closer to 50 than exists in the predicted values
Now we've achieved the ground truth. I realize that the likelihood of a single point in the observed data being closer to 50 than the best predicted value is pretty low, but merging both datasets and looking for the closest dose where response=50 seems to fix this. Either way, the two values aren't super different.
Best,
Charlie
The text was updated successfully, but these errors were encountered: