Skip to content

Commit 06cd2b5

Browse files
committed
Add components for custom-code-in-automation-designer
1 parent 62f1df1 commit 06cd2b5

File tree

8 files changed

+9264
-3
lines changed

8 files changed

+9264
-3
lines changed

README.md

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
# Benchling App Python Examples
1+
# Benchling Python Examples
22

3-
The `examples/` directory contains Benchling App samples written by Benchling.
3+
A collection of Python reference examples for the Benchling platform.
44

55
## chem-sync-local-flask
66

@@ -19,4 +19,23 @@ in a local development environment running [Flask](https://flask.palletsprojects
1919
* User Feedback via [App Status](https://docs.benchling.com/docs/introduction-to-app-status)
2020
* Data Mapping via [App Config](https://docs.benchling.com/docs/app-configuration)
2121
* Receiving and verifying [Webhooks](https://docs.benchling.com/docs/getting-started-with-webhooks)
22-
* Creating [molecule custom entities](https://benchling.com/api/reference#/Molecules/createMolecule)
22+
* Creating [molecule custom entities](https://benchling.com/api/reference#/Molecules/createMolecule)
23+
24+
## Custom Code in Automation Designer
25+
This project contains example snippets of code that can be utilized in a Custom Code step of the Benchling Automation Designer with Benchling Analysis.
26+
27+
![image info](./examples/custom-code-in-automation-designer/snippets/plot-chromatogram/docs/Example_Chromatogram_Plot.gif)
28+
29+
## Overview
30+
These examples demonstrate how to extend Benchling's native capabilities using Python scripts within the Automation Designer context. They cover common use cases such as data visualization, file handling, and complex data transformations.
31+
32+
## Key Capabilities
33+
The code examples included in this directory cover the following functionalities:
34+
35+
- Visualizations: Create custom charts, graphs, and annotations (e.g., chromatograms).
36+
37+
- File Parsing: Logic to read and parse various file formats.
38+
39+
- File Creation: Generate new files, such as instruction lists for laboratory instruments.
40+
41+
- Data Transformation: Apply transformations, merge/join datasets, and perform complex calculations on data.
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
# Custom Code in Automation Designer
2+
This repository contains Python snippets compatible with the Custom Code feature in Automation Designer. This feature allows users to execute Python logic directly within Benchling Analysis.
3+
4+
![image info](./snippets/plot-chromatogram/docs/Example_Chromatogram_Plot.gif)
5+
6+
## Overview
7+
These examples demonstrate how to extend Benchling's native capabilities using Python scripts within the Automation Designer context. They cover common use cases such as data visualization, file handling, and complex data transformations.
8+
9+
## Key Capabilities
10+
The code examples included in this directory cover the following functionalities:
11+
12+
- Visualizations: Create custom charts, graphs, and annotations (e.g., chromatograms).
13+
14+
- File Parsing: Logic to read and parse various file formats.
15+
16+
- File Creation: Generate new files, such as instruction lists for laboratory instruments.
17+
18+
- Data Transformation: Apply transformations, merge/join datasets, and perform complex calculations on data.
19+
20+
## Dependencies
21+
See [requirements.txt](./requirements.txt) for the specific library versions used in these examples.
22+
23+
## Constraints & Limitations
24+
When adapting these examples for your tenant, please note the current beta limitations:
25+
26+
- Runtime Limit: Execution is limited to 15 minutes per run.
27+
28+
- No Network Access: The environment does not support general network access.
29+
30+
- Fixed Packages: You cannot install custom libraries (e.g., via `pip`). You are limited to the pre-installed packages listed above
31+
32+
- No API Access: The Benchling SDK/API is not currently supported within the execution environment.
33+
34+
- Bring your own Container: BYOC is not supported; code runs in the standard Benchling runtime environment
35+
36+
- Lifecycle Management: The feature does not currently support native GitHub integration or versioning within the UI.
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
allotropy==0.1.111
2+
lmfit==1.2.0
3+
numpy==2.2.4
4+
openpyxl==3.1.5
5+
pandas==2.2.3
6+
plotly==5.22.0
7+
pyarrow==19.0.1
8+
pydantic==1.10.21
9+
scikit-learn==1.6.1
10+
scipy==1.15.2
11+
statsmodels==0.14.4
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
2+
"""
3+
Supported packages:
4+
5+
allotropy
6+
benchling-sdk
7+
numpy
8+
openpyxl
9+
pandas
10+
plotly
11+
pyarrow
12+
pydantic
13+
scikit-learn
14+
scipy
15+
statsmodels
16+
"""
17+
from io import BytesIO
18+
import pandas as pd
19+
from typing import NamedTuple
20+
import plotly.graph_objects as go
21+
from scipy.signal import find_peaks
22+
23+
class IOData(NamedTuple):
24+
name: str
25+
data: BytesIO | pd.DataFrame | go.Figure
26+
27+
def custom_code(inputs: list[IOData], **kwargs) -> list[IOData]:
28+
df = inputs[0].data
29+
# Extract the relevant data series and convert them to floats
30+
absorbance_data = df['absorbance (mAU)'].astype(float)
31+
retention_volume_data = df['retention volume (mL)'].astype(float)
32+
33+
# Find peaks in the absorbance data.
34+
# We set a `height` threshold to ignore baseline noise.
35+
# A good starting point is 10% of the max absorbance.
36+
min_height = absorbance_data.max() * 0.10
37+
peak_indices, _ = find_peaks(absorbance_data, height=min_height)
38+
39+
# Set a default range in case no peaks are found
40+
x_axis_range = None
41+
42+
# Check if at least one peak was detected
43+
if len(peak_indices) > 0:
44+
# Get the retention volumes for the first and last detected peaks
45+
first_peak_x = retention_volume_data.iloc[peak_indices[0]]
46+
last_peak_x = retention_volume_data.iloc[peak_indices[-1]]
47+
48+
# Define the padding you want on each side
49+
padding = 150
50+
51+
# Calculate the new x-axis range
52+
x_min = first_peak_x - padding
53+
x_max = last_peak_x + padding
54+
55+
x_axis_range = [x_min, x_max]
56+
fig = go.Figure()
57+
58+
# Add Absorbance Trace
59+
fig.add_trace(go.Scatter(
60+
x=df['retention volume (mL)'],
61+
y=df['absorbance (mAU)'],
62+
name="Absorbance (mAU)",
63+
line=dict(color='royalblue'),
64+
yaxis="y1"
65+
))
66+
67+
# Add other traces (pH, Conc. B)
68+
fig.add_trace(go.Scatter(
69+
x=df['retention volume (mL)'], y=df['pH (pH)'],
70+
name="pH", line=dict(color='crimson', dash='dash'), yaxis="y2"
71+
))
72+
fig.add_trace(go.Scatter(
73+
x=df['retention volume (mL)'], y=df['temperature (degC)'],
74+
name="Temperature (degC)", line=dict(color='green', dash='dot'), yaxis="y3"
75+
))
76+
77+
# --- Layout Definition ---
78+
fig.update_layout(
79+
title_text="Chromatogram with Abs, pH, Temperature Traces",
80+
xaxis_title="Retention Volume (mL)",
81+
plot_bgcolor='white',
82+
legend_title="Traces",
83+
xaxis=dict(domain=[0.1, 0.88]),
84+
yaxis=dict(
85+
title="<b>Absorbance (mAU)</b>",
86+
tickfont=dict(color="royalblue"),
87+
color="royalblue"
88+
),
89+
yaxis2=dict(
90+
title="<b>pH</b>",
91+
tickfont=dict(color="crimson"), color="crimson",
92+
anchor="x", overlaying="y", side="right"
93+
),
94+
yaxis3=dict(
95+
title="<b>Temperature (degC)</b>",
96+
tickfont=dict(color="green"), color="green",
97+
anchor="free", overlaying="y", side="right", position=0.92
98+
)
99+
)
100+
101+
return [IOData(name="Chromatogram_New", data=fig)]
4.81 MB
Loading

0 commit comments

Comments
 (0)