Code Porting¶
The PhotosynQ platform provides numerous measurement protocols for use with MultispeQ devices. Each protocol contains JSON-encoded instructions that define how the MultispeQ performs measurements and can be used directly without modification.
However, analyzing the data stream returned by MultispeQ devices requires custom scripts or macros. Since the PhotosynQ platform uses JavaScript for data analysis, these scripts must be converted to Python for use in Python-based workflows.
Beyond standard JavaScript functions, PhotosynQ provides specialized helper functions for common operations and mathematical computations not available in JavaScript’s native Math object. When porting code to Python, these helper functions can typically be replaced with native Python functions or established libraries like NumPy and SciPy.
The following reference lists will assist in converting JavaScript analysis code to Python, particularly when working with PhotosynQ’s custom helper functions.
Array Functions¶
MultispeQ devices record fluorescence and absorbance traces as one-dimensional arrays of numerical values. When measurements involve multiple LEDs, the recorded data from all LEDs is combined into a single array where values cycle through each LED in sequence. For example, if LEDs 1, 2, and 3 are used during measurement, the resulting trace array follows the pattern [1,2,3,1,2,3,…], with each position representing data from the corresponding LED.
The functions listed below simplify the process of extracting individual LED traces from these combined arrays. For additional details on trace data structure and analysis, consult the PhotosynQ Help documentation.
JavaScript |
Python |
Description |
---|---|---|
|
|
Extract every n-th element from an array. |
|
|
Generate an array of arithmetic progressions. numpy.arange |
|
|
Generate a progression and transform numbers. (e.g. x² ) |
|
|
This function transforms an array of [x, y] pairs into an object with an array of x and an array of y values. zip |
|
|
This function transforms two lists into one list of x,y pairs |
Mathmatical Functions¶
JavaScript |
Python |
Description |
---|---|---|
|
|
Returns the natural logarithm (base E) of a number numpy.log |
|
|
Returns the logarithm (base 10) of a number numpy.log10 |
|
|
Get the maximum value from an array of numbers numpy.max |
|
|
Calculate the mean from an array of numbers numpy.mean |
|
|
Calculate the median from an array of numbers numpy.median |
|
|
Get the minimum value from an array of numbers numpy.min |
|
|
Round a given number (float) to a set number of decimals numpy.round |
|
|
Calculate the standard error from an array of numbers |
|
|
Calculate the standard deviation (population) from an array of numbers numpy.std |
|
|
Calculate the standard deviation (sample) from an array of numbers numpy.std |
|
|
Calculate the sum from an array of numbers numpy.sum |
|
|
Calculate the variance from an array of numbers numpy.var |
Regression Functions¶
Language |
Code |
---|---|
JavaScript |
MathEXPINVREG( [ [x1,y1], [x2,y2], ..., [xn,yn] ] );
|
Python |
import numpy as np
from scipy.optimize import curve_fit
def exponential_decay(x, A, t, asymptote):
"""Exponential decay function: y = A * exp(x * t) + asymptote"""
return A * np.exp(x * t) + asymptote
# Fit the curve
popt, pcov = curve_fit(exponential_decay, x_data, y_data,
p0=[1.0, -0.1, 0.0]) # Initial parameter guesses
A, t, asymptote = popt
# Generate fitted points
y_fitted = exponential_decay(x_data, A, t, asymptote)
# Calculate R-squared
ss_res = np.sum((y_data - y_fitted) ** 2)
ss_tot = np.sum((y_data - np.mean(y_data)) ** 2)
r_squared = 1 - (ss_res / ss_tot)
# Results equivalent to your JS function
results = {
'parameters': [A, t, asymptote],
'fitted_points': list(zip(x_data, y_fitted)),
'r_squared': r_squared,
'lifetime': -1/t,
'slope': -A * t
}
|
Language |
Code |
---|---|
JavaScript |
MathLINREG([x1, x2, ..., xn], [y1, y2, ..., yn]);
|
Python |
scipy import stats
slope, intercept, r_value, p_value, std_err = stats.linregress(x, y)
|
Language |
Code |
---|---|
JavaScript |
MathMULTREG( [
[ [x1,y1], [x2,y2], ..., [xn,yn] ],
[ [x1,y1], [x2,y2], ..., [xn,yn] ]
]);
|
Python |
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.metrics import r2_score
# Extract features (X) and target (y)
X = np.array([[point[i] for i in range(len(point)-1)] for point in input_raw])
y = np.array([point[-1] for point in input_raw])
# Fit the model
model = LinearRegression()
model.fit(X, y)
# Get predictions
y_pred = model.predict(X)
# Results equivalent to your JS function
results = {
'rsquared': model.score(X, y), # or r2_score(y, y_pred)
'slopes': [model.intercept_] + model.coef_.tolist(), # [intercept, coef1, coef2, ...]
'points': [X.T.tolist(), y_pred.tolist()] # [features, predictions]
}
|
Language |
Code |
---|---|
JavaScript |
MathPOLYREG( [
[ [x1,y1], [x2,y2], ..., [xn,yn] ],
[ [x1,y1], [x2,y2], ..., [xn,yn] ]
], degree );
|
Python |
import numpy as np
# Fit polynomial of specified degree
coefficients = np.polyfit(x_data, y_data, degree)
# Generate fitted points
y_fitted = np.polyval(coefficients, x_data)
# Calculate error (mean squared error)
error = np.sum((y_fitted - y_data) ** 2) / (len(y_data) - 1)
# Results equivalent to your JS function
results = {
'slopes': coefficients.tolist(), # [a_n, a_(n-1), ..., a_1, a_0]
'points': list(zip(x_data, y_fitted)),
'error': error
}
|
Language |
Code |
---|---|
JavaScript Source |
NonLinearRegression(
[
[x1, y1],
[x2, y2],
...,
[xn, yn]
],
{
equation: "b + a * e(- x / c)",
initial: [a, b, c]
}
);
|
Python scipy.optimize.curve_fit |
from scipy.optimize import curve_fit
def exp_func(x, a, b, c):
return b + a * np.exp(-x / c)
try:
# Fit the data
popt, pcov = curve_fit(exp_func, x, y, p0=[1, 1, 1])
a, b, c = popt
...
except Exception as e:
pass # Or handle the error as needed
|
Trace Transformation¶
If you have two traces of equal length or a trace and a number, the helper function TransformTrace allows to transform a given trace (array) based on the second input (array or number) and the provided function.
// Two arrays
TransformTrace("function", array_1, array_2);
// One array and one number
TransformTrace("function", array_1, number);
Using Python this can be achieved using native code or the numpy module. The code provided shows examples based on the functions available in JavaScript.
Function |
Python Equivalent |
Description |
---|---|---|
add or + |
|
Add array or number to array |
subtract or - |
|
Subtract array or number from array |
multiply or * |
|
Multiply array with array or number |
divide or / |
|
Divide array by array or number |
normToMin |
|
Normalize to minimum |
normToMax |
|
Normalize to maximum |
normToRange |
|
Normalize to the min/max range of the array |
normToIdx |
|
Normalize to number found at a specific position (index) in array |
normToVal |
|
Normalize to defined value |
ma |
|
Smoothing using a moving average with a selectable window size |
sgf |
|
Smoothing using a Savitzky-Golay Filter SciPy.signal |
abs |
|
Calculate the absorbance using the first value as I0 or a defined I0 |
Data Lookup¶
Function to look up data from sub protocols are implemented in this library and can be used the same way as their JavaScript equivalent.
They are part of the jii_multispeq.analysis.basic
module.
## import the analysis module
import jii_multispeq.analysis as analysis
data = analysis.GetIndexByLabel()
## import a specific function (similar to JavaScript code)
import jii_multispeq.analysis.GetIndexByLabel as GetIndexByLabel
data = GetIndexByLabel()
Function |
Description |
---|---|
Generate a protocol lookup table for a protocol set |
|
Returns the protocol from within the protocol set matching the provided label |
|
Find the positions for protocols within a protocol set matching the provided label |
Native JavaScript Math Functions¶
The native JavaScript Math Object provides methods for mathematical constants that can be used with Macros on the PhotosynQ platform and don’t require any additional import of libraries or functions. See JavaScript Math for available methods and constants.
// Math Object as used in a PhotosynQ Macro
Math.<name>
Native JavaScript Functions¶
Native JavaScript functions to manipulate arrays and their Python equivalent.
JavaScript |
Python |
Description |
---|---|---|
|
|
Copy part of an array |
Notifications¶
The functions info("Message" , output)
, warning("Message" , output)
, and danger("Message" , output)
add messages to the output of the macro by category. Currently they are not supported and can be replaced by print("Message")
to output issues.