My first Shiny app: fitting sigmoid curves

Since the grad school I have been using R for data analysis and (mainly) for preparation of nice plots. As with LaTeX, it was a pretty steep learning curve. But after a year or so I managed to become comfortable with writing a new script for each new experiment. After some time, however, I started feeling that it wasn’t enough. Many experiments were almost identical, so breeding 99%-similar scripts didn’t seem to be an efficient way of handling data. That’s when I first started to think about making ‘reusable’ apps for specific purposes.

Fortunately, the community of software developers is very helpful and supportive. To the point where they write software that helps less skillful folks (like me) to create their own apps easier. Shiny is one of such frameworks. I chose it because it is fully R-based and natively integrated with RStudio. OK, enough introduction! Without further delay, let me introduce you my dose-response fitting web-application. Below I’ll explain what it does and how to use it.

What it does?

The main and only function of the app is to fit the dose-response data points to the sigmoid curve and estimate EC50 values as well as other parameters of the model (equation 1).
E = E_{min} + \frac{E_{max} - E_{min}}{1 + \left( \frac{EC_{50}}{[L]} \right)^{n}}\hfill (1)

As a bonus you can download the plot with data and fitted curve as a bitmap or vector image.

How to use it?

I tried to make interface intuitive and the analysis step-wise. The main page has three tabs. The 1st one is for initial data input. The 2nd is for actual fitting and model adjustments if needed. The 3rd tab is for downloading fitting results. Below are the steps to follow:

  1. First you need a file with data (heres a sample). Accepted format is .csv, which stands for ‘comma separated values’. You can convert any MS Excel spreadsheet in this format. As a minimum, you’ll need two columns: one with dose values and the other with responses.
    1. if your table doesn’t have a header, uncheck ‘Header’ box. But it’s a good idea to have one for obvious reasons.
    2. you can upload tab- or semicolon-separated file and choose corresponding radio-button  in the upper panel for the app to read the data file.
    3. If the text values in uploaded data table have quotation marks, select correct type of quotes, otherwise go with default
  2. Once the file is uploaded and properly read, you’ll see the input data table in the lower panel. To finish data input for fitting, select the X-axis (dose) and Y-axis (response). If the concentrations are provided not in mol/L (M), select correct units from the drop-down menu.
    1. Non-SI units are not supported. You may, however, go ahead and keep ‘M’ as dose units for whatever you use, just remember that EC50 values will be in the same units.
  3. After X and Y axes are selected you may switch to the 2nd tab. In the top left corner there is a dummy ‘Model plot’, which shows all the model parameters for fitting. If you want to split the data points into groups (e.g., for different compounds), select a column in the ‘Group’ drop-down list. If your data file has error values and you want to see them in the plot, select a proper column from ‘Error bar’ list.
  4. Fitting process is interactive, so once X and Y are selected and you switch to the 2nd tab, you’ll see all the data points and a fitted curve in the lower panel. If ‘Group’ is selected, the plot will be split into facets per number of groups in the data table. Each group will have its own fitted curve. You can manipulate appearance of the plot via radio-buttons and checkbox to the right from the plot area. You may also download the resulting plot by setting dimensions, resolution, and format.
  5. You can also choose to fix some (up to three) parameters for fitting. E.g., if you have data normalized to positive and negative control, it would make sense to set ‘Top’ and ‘Bottom’ parameters to 100 and 0%, respectively. Fitting curves are automatically updated when parameters changed. If you wan to change back to free parameters, just delete the value in a corresponding cell.
    1. if X and Y were not selected, you’ll get an error ‘subscript out of bound’ instead of the data plot when switching to the 2nd tab.
    2. Sometimes the fitting function will fail to converge if model parameters are fixed at too unrealistic values.
  6. Finally when satisfied with the model fit, you may switch to the 3rd tab and download the fitting results. The resulting data table will list label for the selected groups (if any), model parameter with their Estimated values and Standard Error of fitting, as well as t-values and p-values for quantitative estimation of how well the data points fit to the selected model.

So give it a try and let me know if there are any problems. Just a few more words. Since it’s a free account, the app is limited to 25 hours of running time per month. If the demand will exceed this limit I’ll start to think about a workaround.


Of course, for me to be able to build something like this many people had to write awesome easy-to-use R packages and tutorials. So bunch of thanks are going to creators of R, Rstudio, Shiny, ggplot2, dplyr, plyr, drc, reshape2, and svglite. Another chunk of acknowledgments are for contributors of stack overflow and R-bloggers.


Author: Slava Bernat

I did my PhD in medicinal chemistry/chemical biology of G protein-coupled receptors and then explored some chemical biology of non-coding RNA as a postdoc. Currently I'm working in a small biotech company in San-Francisco Bay area as a research chemist. I'm writing about science, which catches my attention in rss feed reader and some random thoughts or tutorials.

2 thoughts on “My first Shiny app: fitting sigmoid curves”

  1. this is really cool that you could make it and post for everyone! However what is the difference with the standard soft like Graphpad Prizm, SigmaPlot, Origin?

    1. As far as I know, there’s no difference in fitting algorithm with SigmaPlot and Origin. The latest issue of Prizm has more sophisticated way of calculating 95%CI for fitted parameters, so it’s one of my next goals – to get to the guts of fitting itself. Apart from that, the main difference is in the license and price.

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

profiting from randomness

R-statistics blog

Statistics with R, and open source stuff (software, data, community)

Colorblind Chemistry

The blog of Marshall Brennan, PhD

ACS Careers Blog

Career advice from the American Chemical Society

Lab Without Benches

Career skills for scientists


forcing molecules to behave


mostly science

Org Prep Daily

synthetic procedures I tried and liked

Sussex Drug Discovery Centre

Medicinal, Chemistry and Biochemistry blog from the Sussex Drug Discovery Centre

Practical Fragments

mostly science

Chemical connections

...chemistry & other curiosities

Just Like Cooking

mostly science

%d bloggers like this: