Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
00cf504
Refactor scripts to use .Renviron for credentials and add Shiny app
PMichaels-SC Apr 1, 2026
ebc2e63
Remove CLAUDE.md from git tracking
PMichaels-SC Apr 1, 2026
8a211d4
Reorganize repository: extract utilities and add progressive examples
PMichaels-SC Apr 1, 2026
5020e10
Clean up redundant files and generated outputs
PMichaels-SC Apr 1, 2026
9b2999c
Simplify examples structure and improve clarity
PMichaels-SC Apr 1, 2026
6270971
Consolidate documentation into single README
PMichaels-SC Apr 1, 2026
b1d7d5b
Add R installation to quick setup prerequisites
PMichaels-SC Apr 1, 2026
e18bbb1
Simplify authentication - use analysis key JWT directly
PMichaels-SC Apr 1, 2026
735fb31
Remove .Renviron.example - no longer needed
PMichaels-SC Apr 1, 2026
68047f3
Remove test_analysis_key_auth.R - no longer needed
PMichaels-SC Apr 1, 2026
2fb816e
Document dual authentication approach - JWT default with OAuth2 alter…
PMichaels-SC Apr 2, 2026
e1db7e4
Clarify analysis key structure in README
PMichaels-SC Apr 2, 2026
5fe289c
Add detailed instructions for obtaining analysis key
PMichaels-SC Apr 2, 2026
60e116b
Add sample data upload step to Quick Setup
PMichaels-SC Apr 2, 2026
907d1d8
Add clear section markers for switching between JWT and OAuth2
PMichaels-SC Apr 2, 2026
ffbf337
Simplify app.R authentication switching with USE_OAUTH2 flag
PMichaels-SC Apr 2, 2026
98bd584
Simplify get_dataframe.R authentication switching with USE_OAUTH2 flag
PMichaels-SC Apr 2, 2026
62e251e
Update README to reflect USE_OAUTH2 flag switching
PMichaels-SC Apr 2, 2026
b8e7e61
switch to default auth
PMichaels-SC Apr 2, 2026
99e6754
Fix variable name in results_analysis.R success summary
PMichaels-SC Apr 2, 2026
a9444fa
Standardize column names in sample data to match main workflow
PMichaels-SC Apr 2, 2026
ffc06aa
Add 48-hour IC50 analysis to all scripts
PMichaels-SC Apr 2, 2026
5389ab5
Use tmp/ directory for temporary files in results_analysis.R
PMichaels-SC Apr 2, 2026
eb9fb8b
Simplify tmp cleanup to delete entire directory
PMichaels-SC Apr 2, 2026
d88c8b3
Ensure fitted curve shows only line without markers
PMichaels-SC Apr 2, 2026
97fb81e
Add inherit=FALSE to fitted curve trace to prevent marker inheritance
PMichaels-SC Apr 2, 2026
6413a56
Use add_lines() with pipe operator for fitted curve
PMichaels-SC Apr 2, 2026
063de28
Revert to add_trace with explicit line mode for fitted curve
PMichaels-SC Apr 2, 2026
70e9667
Support multiple Benchling domain suffixes (benchling.com, bnchdev.or…
PMichaels-SC Apr 3, 2026
e16d987
Require full domain in .Renviron for OAuth2 to avoid confusion
PMichaels-SC Apr 3, 2026
5c1133e
Simplify OAuth2 config to use BENCHLING_DOMAIN instead of BENCHLING_T…
PMichaels-SC Apr 3, 2026
5e33acc
Simplify column names and use actual cell names from data
PMichaels-SC Apr 3, 2026
0e0aa1e
Fix column names to use dots instead of spaces
PMichaels-SC Apr 3, 2026
c7e6b41
Rename Cell column to Cell Name in CSV and code
PMichaels-SC Apr 3, 2026
c9f7e1d
Fix plotly fitted curve to show lines only without markers
PMichaels-SC Apr 3, 2026
b67d7e0
Add R Shiny to the app title so this is more obvious in a demonstration.
PMichaels-SC Apr 3, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
31 changes: 31 additions & 0 deletions .Renviron.example
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
################################################################################
# Benchling Authentication Configuration
################################################################################
#
# This file is ONLY needed if using Benchling App (OAuth2) authentication
# for long-running workflows. The default JWT approach doesn't need this.
#
# See README.md "Authentication Methods" section for when to use each approach.
#
################################################################################

# --------------------------------------------------------------------------
# Option 1: Analysis Key (JWT) - Default, no configuration needed!
# --------------------------------------------------------------------------
# The script prompts for your analysis key when you run it.
#
# OPTIONAL: Set this to avoid prompts (useful for automation)
# BENCHLING_ANALYSIS_KEY=ana_XXXXX:eyJhbGc...

# --------------------------------------------------------------------------
# Option 2: Benchling App (OAuth2) - For production/long workflows
# --------------------------------------------------------------------------
# Prerequisites:
# 1. Create Benchling App: https://docs.benchling.com/docs/getting-started-benchling-apps
# 2. Grant permissions: analyses, data-frames, files (read/write)
# 3. Set USE_OAUTH2 <- TRUE in get_dataframe.R (line 12) and app.R (line 17)
#
# Then set these values:
# BENCHLING_CLIENT_ID=your_client_id_here
# BENCHLING_CLIENT_SECRET=your_client_secret_here
# BENCHLING_DOMAIN=your_tenant.benchling.com
42 changes: 42 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# Credentials and Environment Variables
.Renviron
.Rprofile

# Project-specific Claude configuration
CLAUDE.md

# R Data files
*.RData
*.Rhistory
*.rda
*.rds

# Output files from examples
examples/local_test_output.html
examples/local_test_summary.csv
examples/*.html
examples/*.csv
# But keep the sample input data
!examples/sample_ic50_data.csv
examples/*_files/

# RStudio project files
.Rproj.user/
*.Rproj

# Shiny
rsconnect/
.shiny_app_cache/

# macOS
.DS_Store

# IDE
.vscode/
.idea/

# Temporary files
tmp/
*.tmp
*.bak
*~
22 changes: 0 additions & 22 deletions Mortality IC50.csv

This file was deleted.

281 changes: 268 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,20 +1,275 @@
# Sample Code - Working with Datasets Using R

A repository containing the sample scripts described in the [Working with Datasets Using R](https://docs.benchling.com/docs/working-with-datasets-using-r) developer guide.

Provided for educational purposes only; not for production use.

## Configuration and Setup
1. Create a [Benchling App](https://docs.benchling.com/docs/getting-started-benchling-apps)
2. Create a [Benchling Analysis](https://help.benchling.com/hc/en-us/articles/15298157390861-Creating-an-analysis)
3. Configure the sample script(s) with your tenant-specific variables
## Quick Setup

1. **Install R 4.5.3+** (if not already installed)
2. **Install dependencies:** `Rscript -e "renv::restore()"`
3. **Create Analysis:** [Create an analysis](https://help.benchling.com/hc/en-us/articles/15298157390861) in Benchling
4. **Upload Sample Data:** Attach `examples/sample_ic50_data.csv` as an input dataset to your analysis
- **Note:** In production usage, this would be an existing dataset or results table from your experiments
5. **Get Analysis Key:** In your analysis, click **"Connect with external tool"** β†’ **"Copy Analysis Key"**
6. **Run the workflow:** The script will prompt for your analysis key - that's it!

## Authentication Methods

This repository uses **Analysis Key (JWT) authentication** by default.

**Analysis Key Structure:** `ana_XXXXX:eyJhbGc...` (analysis_id + JWT token separated by colon)

### Analysis Key (JWT) - Default βœ…

**Best for:** Learning, demos, workflows under 10 minutes

- βœ… **Simple:** Just paste your analysis key
- βœ… **User-attributable:** Actions are tied to the person who generated the key
- ⚠️ **Expires after 10 minutes:** If your workflow takes longer, it will fail
- ⚠️ **Analysis-specific:** Each analysis has its own key

The JWT token (part after the colon) contains the authentication credentials and is used directly as the bearer token for API requests.

### Benchling App (OAuth2) - Alternative

**Best for:** Production systems, long-running workflows, processing multiple analyses

- βœ… **Permanent credentials:** No expiration
- βœ… **Reusable:** Works across all analyses
- ⚠️ **More setup:** Requires creating a Benchling App
- ⚠️ **App-attributable:** Actions are tied to the app, not a specific user

**Want to use App credentials?** Set `USE_OAUTH2 <- TRUE` at the top of `get_dataframe.R` (line 12) and/or `app.R` (line 17). See [Benchling Apps Guide](https://docs.benchling.com/docs/getting-started-benchling-apps) for setup.

πŸ“– **Detailed Setup Instructions** (click to expand)

### Prerequisites

- R 4.5.3+ installed
- Access to a Benchling tenant
- Access to Benchling Analyses feature

### Part 1: Create a Benchling Analysis

Analyses are where you'll attach input datasets and receive output results.

1. **Navigate to Analyses:**
- In Benchling, go to your project or notebook
- Click **"Create"** β†’ **"Analysis"**
2. **Configure Analysis:**
- **Name:** e.g., "IC50 Dose-Response Calculation"
- **Description:** Optional, explains what this analysis does
3. **Attach Input Dataset:**
- Click **"Add Input"** β†’ **"Dataset"**
- **For this example:** Upload `examples/sample_ic50_data.csv` from this repository
- **For production use:** Select an existing dataset or results table from your experiments
- **Required columns:**
- `Cell.Mortality.Concentration` - Drug concentration values
- `Cell.Mortality.Mortality.24h` - Mortality percentage at 24 hours
- `Cell.Line.Name` - Cell line identifier
**Example data format:**
4. **Get the Analysis Key:**
- In your analysis, click **"Connect with external tool"**
- In the popup window, click **"Copy Analysis Key"**
- Format looks like: `ana_XXXXXXXX:eyJhbGc...` (`analysis_id`:`JWT token`)
- **Note:** Analysis keys are specific to each analysis run and expire after 10 minutes

### Part 2: Install Dependencies

```bash
# Restore the renv environment (installs all packages)
Rscript -e "renv::restore()"

# Or install packages individually
Rscript -e "renv::install(c('httr', 'jsonlite', 'base64enc', 'drc', 'plotly', 'htmlwidgets', 'pracma'))"
```

**Note:** On macOS, you may need CMake first:

```bash
brew install cmake
```

### Part 3: Run the Workflow

⚠️ **Important:** Scripts must run **sequentially in the same R session** because `results_analysis.R` depends on variables from `get_dataframe.R`.

**Option A: RStudio (Recommended)**

```r
source('get_dataframe.R') # Will prompt: "Analysis Key: "
# Paste: ana_XXXXX:eyJhbGc...
ls() # Verify: df, subdomain, analysis_id, access_token, folder_id
head(df) # Check data loaded correctly
source('results_analysis.R')
```

**Option B: Script Based Execution in Interactive R Session**

```r
source('get_dataframe.R')
# Prompts for analysis key, paste it and press Enter
source('results_analysis.R')
```

**Option C: Non-Interactive (Command Line)**

```bash
export BENCHLING_ANALYSIS_KEY="ana_XXXXX:eyJhbGc..."
Rscript -e "source('get_dataframe.R'); source('results_analysis.R')"
```

**Option D: Shiny Web App (Easiest) from Interactive R Session**

```r
shiny::runApp("app.R")
# Enter your analysis key in the web interface
```

### Verify Success

The scripts print status codes as they run:

```
[1] "200" # Dataframe upload successful
[1] "200" # File upload successful
[1] "200" # Analysis update successful
```

Check your Analysis in Benchling - you should see:

- **Dataset:** `Mortality_IC50` - CSV with IC50 statistics
- **File:** `mortality_24h.html` - Interactive plot

### Common Issues

**Error: "HTTP 401 Unauthorized" or "Failed to authenticate"**

- Your analysis key JWT may have expired (check the `exp` field in the JWT)
- Generate a new analysis key from your Benchling analysis
- Ensure you copied the complete key (format: `ana_XXXXX:eyJhbGc...`)

**Error: "HTTP 404 Not Found"**

- `analysis_id` is incorrect
- Check the analysis ID in the Benchling URL
- Ensure the analysis exists and you have access

**Error: "Variables not found in results_analysis.R"**

- Must run `get_dataframe.R` first in the same R session
- Don't start a new R session between running the scripts

**Error: "Package not found"**

- Run `renv::restore()` to install all dependencies

**Error: "No input dataframes found"**

- Ensure you've attached an input dataset to your analysis in Benchling
- Dataset must have the required columns (see data format above)

### Data Flow

```
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Benchling Analysis β”‚
β”‚ Input Dataset (CSV) β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ get_dataframe.R β”‚
β”‚ 1. Authenticate β”‚
β”‚ 2. Fetch dataset β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β–Ό
Variables: df, subdomain,
analysis_id, access_token
β”‚
β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ results_analysis β”‚
β”‚ 1. Calculate IC50β”‚
β”‚ 2. Generate plot β”‚
β”‚ 3. Upload both β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”¬β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
β”‚
β–Ό
β”Œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
β”‚ Benchling Analysis β”‚
β”‚ Output: Mortality_IC50 (CSV) β”‚
β”‚ Output: mortality_24h.html (plot) β”‚
β””β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”˜
```

### Additional Resources

- [Benchling API Documentation](https://docs.benchling.com/docs/api-overview)
- [Benchling Apps Guide](https://docs.benchling.com/docs/getting-started-benchling-apps)
- [Benchling Analyses Guide](https://help.benchling.com/hc/en-us/articles/15298157390861)
- [Working with Datasets Using R](https://docs.benchling.com/docs/working-with-datasets-using-r)

## Local Testing πŸ§ͺ

Want to test IC50 calculations without connecting to Benchling? Use the local test script:

```r
# From project root:
source("examples/local_test.R")

# Or from examples directory:
setwd("examples")
source("local_test.R")
```

**What it does:**

- Loads dose-response data from `examples/sample_ic50_data.csv` (21 observations, 7 concentrations Γ— 3 replicates)
- Calculates IC50 using 4-parameter log-logistic model
- Uses utility functions from `utils.R`
- Creates interactive plotly visualization
- Generates results summary

**Output files:**

- `examples/local_test_output.html` - Interactive plot (open in browser)
- `examples/local_test_summary.csv` - Results table

**Prerequisites:** None! Works completely offline with sample data. Perfect for testing during development.

---

## Usage
* `get_dataframe.R` pulls the input dataset from a Benchling analysis and converts it into an R dataframe.
* `results_analysis.R` performs an IC50 calculation on a dataframe, creates a plot, and imports both
as outputs to a Benchling analysis.
* `Mortality IC50.csv` contains basic sample data of the form required by `results_analysis.R`

It's recommended to start by working with `get_dataframe.R` and `results_analysis.R` in order to familiarize
yourself with the principles involved. For best results, these should be run sequentially, since the latter expects
a dataframe to be imported. Once you're confident using the scripts and with the configuration in Benchling, the
techniques involved can be applied to more robust applications using tools like Rshiny.

### Main Script Files

- `get_dataframe.R` - Pulls input dataset from Benchling using analysis key
- `results_analysis.R` - Performs IC50 calculation, creates plot, and uploads to Benchling
- `app.R` - Full-featured Shiny web app with UI for IC50 analysis
- `utils.R` - Shared utility functions for IC50 calculation and plotting

### Full Workflow (Benchling Integration)

**Option 1: Shiny Web App (Easiest)**

```r
shiny::runApp("app.R") # Opens web interface
```

**Option 2: Command Line Scripts**

```r
source('get_dataframe.R') # Will prompt for analysis key
source('results_analysis.R')
```

⚠️ **Important:**

- Scripts must run sequentially in the same R session
- The script will prompt you for the analysis key
- Analysis keys contain JWT tokens that may expire - regenerate if needed

Once you're confident with the workflow, these techniques can be applied to more robust applications using tools like Shiny.
Loading