LDH Cytotoxicity Assay Analysis App
User Guide
1. Overview
This Shiny application automates the analysis of Lactate Dehydrogenase (LDH) cytotoxicity assay data. It processes raw 96-well plate reader data to calculate, analyze, and visualize percent cytotoxicity, culminating in a publication-ready interactive plot and a downloadable report.
This version includes several powerful features for flexibility and reproducibility:
- Dynamic Control Assignment: Assign your custom group names to control functions directly in the app.
- Group-Specific Normalization: Supports experiments where treatment groups have their own dedicated maximum lysis controls.
- Interactive Plots: Hover over data points to see their exact values.
- Dynamic Interpretation: The "Assumption Checks" and "Interpretation Guide" tabs provide feedback tailored to your specific results.
- Full Reproducibility: Download the processed data or a complete HTML report of the entire analysis.
2. How to Use the Application
Step 1: Prepare Your Input Files
You need two .csv
files: a plate layout file and a raw absorbance file.
A. Plate Layout File (e.g., layout.csv
)
This file maps the contents of each well.
- The file must not have row names (e.g., A, B, C...). The app adds these automatically.
- The first row is treated as the column header (e.g., 1, 2, 3...).
- The cells should contain your custom group names.
Important: Naming Convention for Per-Treatment Controls
To link an experimental group to its specific maximum lysis control, you must name the control using a consistent prefix. The default is Tritonx100-
.
For a treatment group named DrugA
, its corresponding max lysis control must be named Tritonx100-DrugA
. The text that comes after the prefix must match exactly.
Example layout.csv
:
1,2,3,4,5,6
empty,empty,empty,Vehicle,Vehicle,Vehicle
empty,empty,empty,DrugA,DrugA,DrugA
untreated,untreated,untreated,Tritonx100-Vehicle,Tritonx100-Vehicle,Tritonx100-Vehicle
untreated,untreated,untreated,Tritonx100-DrugA,Tritonx100-DrugA,Tritonx100-DrugA
...
B. Raw Absorbance File (e.g., absorbance.csv
)
This file contains the raw optical density (OD) readings from the plate reader.
- The file must not have any headers or row names.
- Data must be in an alternating row format: the first row for 490 nm, the second for 680 nm (background), the third for 490 nm, and so on.
Step 2: Upload Files & Define Controls
In the sidebar, upload your two files. After uploading the layout, dynamic dropdowns will appear. Use these to configure your analysis:
- Define Calculation Controls:
- Spontaneous Lysis: Select the group name for your untreated cells.
- Max Lysis Prefix: Confirm or change the prefix used to identify max lysis groups.
- Blank: Select the group name for your media-only wells.
- Define Analysis Settings:
- Comparison Control: Select the group that will serve as the baseline for statistical comparisons (e.g., a "Vehicle" or "DMSO" control).
- Statistical Test Method: Choose "Automatic Selection" to let the app decide between ANOVA and Kruskal-Wallis based on assumption checks, or manually override the choice.
Step 3: Execute and Export
Click the "Run Analysis" button to process the data. Once complete, you can download the final processed data from the "Processed Data Preview" tab or download a complete HTML report using the "Download Report" button.
3. Interpreting the Output Tabs
- Summary & Plot: Displays the main interactive boxplot. Hover over points to see values. The plot includes significance brackets comparing treatments to your selected control.
- Detailed Statistics: Provides tables for the overall (omnibus) test and the detailed pairwise (post-hoc) comparisons.
- Processed Data Preview: Shows an interactive table of the final calculated data. Verify your results here and download the data as a CSV.
- Assumption Checks: A dynamic guide that explains the tests for normality and equal variances, interprets your data's results, and shows why a particular statistical test was chosen.
- Interpretation Guide: A dynamic guide that explains your specific omnibus and post-hoc test results, using an example from your data to make it clear.
4. Methodology
The app calculates percent cytotoxicity using the formula:
$$ \text{Cytotoxicity (\%)} = \frac{(\text{Corrected OD}_{\text{Experimental}} - \text{Mean OD}_{\text{Spontaneous}})}{(\text{Mean OD}_{\text{Maximum}} - \text{Mean OD}_{\text{Spontaneous}})} \times 100 $$
Where Corrected OD = OD490nm - OD680nm. The Mean ODMaximum is calculated specifically for each treatment "family", ensuring accurate normalization.
Code Logic Documentation
This section outlines the internal workings of the server
function.
1. Dynamic UI Rendering
Reactive expressions read the unique group names from the uploaded layout file. A series of renderUI
functions then use this list to populate the choices in the sidebar dropdowns, making the entire interface adapt to the user's data.
2. The Main Analysis Pipeline (eventReactive
)
The core logic is wrapped in an eventReactive()
, which executes only when the "Run Analysis" button is clicked.
- Input Validation: The app first checks if all required files and inputs are present. It then uses
validate()
and need()
to perform a series of checks (e.g., is the file a valid CSV? Do the selected controls exist in the data?) and provides user-friendly error messages if a check fails.
- Data Processing: Raw absorbance data is background-corrected (490nm - 680nm). The layout and absorbance data are tidied and merged into a single data frame.
- Group-Specific Normalization: This is a key feature. A "treatment family" ID is created for each well by removing the user-defined max lysis prefix. The app then calculates a unique mean maximum lysis absorbance for each family and joins this value back to the main dataset. This ensures every well is normalized against its specific maximum lysis control.
- Final Calculation & Filtering: The cytotoxicity formula is applied. All control groups (blank, spontaneous, and max lysis) are then filtered out, leaving a clean dataset for analysis. The
group
column is re-factored to ensure filtered-out groups do not appear on the plot axis.
- Statistical Analysis: Assumption checks (Shapiro-Wilk, Levene's) are performed. Based on these results or the user's choice, the appropriate path (ANOVA or Kruskal-Wallis) is taken.
- Plot Generation: An interactive plot is built using
ggplot2
and ggiraph
. Tooltips are added to the data points, and significance bars are generated using ggpubr
.
- Return Results: All generated objects (the plot, tables, p-values, processed data, etc.) are collected into a single list and returned by the reactive expression.
3. Output Rendering and Downloads
The final part of the server consists of render functions (renderGirafe
, renderDataTable
, renderUI
) and download handlers (downloadHandler
). Each of these functions accesses the required item from the analysis_results()
list and displays it in the UI or prepares it for download.