ENZYME_INHIBIT

Overview

The ENZYME_INHIBIT function fits enzyme inhibition kinetic models to experimental data, enabling researchers to characterize how inhibitors affect enzyme activity. Enzyme inhibitors are molecules that bind to enzymes and reduce their catalytic activity, playing critical roles in metabolic regulation, drug development, and toxicology. This implementation uses SciPy’s curve_fit function to perform non-linear least squares regression.

The function supports five distinct inhibition models based on Michaelis-Menten kinetics:

  • Competitive Inhibition: The inhibitor competes with the substrate for the active site. The apparent K_m increases while V_{max} remains unchanged. The rate equation is:
v = \frac{V_{max} \cdot [S]}{K_m \left(1 + \frac{[I]}{K_i}\right) + [S]}
  • Noncompetitive Inhibition (Classic): The inhibitor binds to a site distinct from the active site with equal affinity to both the free enzyme and enzyme-substrate complex, reducing V_{max} without affecting K_m.

  • Uncompetitive Inhibition: The inhibitor binds only to the enzyme-substrate complex, decreasing both V_{max} and K_m proportionally.

  • Mixed Mode Inhibition: A general case where the inhibitor binds to both the free enzyme and the enzyme-substrate complex with different affinities, characterized by the parameter \alpha.

  • Substrate Inhibition: At high substrate concentrations, excess substrate molecules inhibit the enzyme, causing the reaction rate to decrease after reaching a maximum.

Each model returns fitted parameters including V_{max} (maximum reaction velocity), K_m (Michaelis constant), and K_i (inhibition constant), along with standard errors when computable. For additional background on enzyme inhibition mechanisms, see the Wikipedia article on enzyme inhibitors.

This example function is provided as-is without any representation of accuracy.

Excel Usage

=ENZYME_INHIBIT(xdata, ydata, enz_inhibit_model)
  • xdata (list[list], required): The xdata value
  • ydata (list[list], required): The ydata value
  • enz_inhibit_model (str, required): The enz_inhibit_model value

Returns (list[list]): 2D list [param_names, fitted_values, std_errors], or error string.

Examples

Example 1: Demo case 1

Inputs:

enz_inhibit_model xdata ydata
competitive_inhibition_michaelis_menten 0.1 0.051514023715725374
1.3250000000000002 0.47300427068072515
2.5500000000000003 0.7663838108171507
3.7750000000000004 0.9657466193762992
5 1.1734681319279758

Excel formula:

=ENZYME_INHIBIT("competitive_inhibition_michaelis_menten", {0.1;1.3250000000000002;2.5500000000000003;3.7750000000000004;5}, {0.051514023715725374;0.47300427068072515;0.7663838108171507;0.9657466193762992;1.1734681319279758})

Expected output:

"non-error"

Example 2: Demo case 2

Inputs:

enz_inhibit_model xdata ydata
mixed_mode_inhibition_general 0.1 0.05083498195928943
1.3250000000000002 0.462697587064436
2.5500000000000003 0.7406127653487591
3.7750000000000004 0.9243170912219678
5 1.1139757686701859

Excel formula:

=ENZYME_INHIBIT("mixed_mode_inhibition_general", {0.1;1.3250000000000002;2.5500000000000003;3.7750000000000004;5}, {0.05083498195928943;0.462697587064436;0.7406127653487591;0.9243170912219678;1.1139757686701859})

Expected output:

"non-error"

Example 3: Demo case 3

Inputs:

enz_inhibit_model xdata ydata
noncompetitive_inhibition_classic 0.1 0.049783922530651364
1.3250000000000002 0.4457937803749305
2.5500000000000003 0.6994709356098026
3.7750000000000004 0.8597697563930553
5 1.0231947350421495

Excel formula:

=ENZYME_INHIBIT("noncompetitive_inhibition_classic", {0.1;1.3250000000000002;2.5500000000000003;3.7750000000000004;5}, {0.049783922530651364;0.4457937803749305;0.6994709356098026;0.8597697563930553;1.0231947350421495})

Expected output:

"non-error"

Example 4: Demo case 4

Inputs:

enz_inhibit_model xdata ydata
substrate_inhibition_high_conc 0.1 0.06135298887361882
1.3250000000000002 0.5397910520242316
2.5500000000000003 0.7994181121419677
3.7750000000000004 0.9157855619950286
5 0.9128767480792515

Excel formula:

=ENZYME_INHIBIT("substrate_inhibition_high_conc", {0.1;1.3250000000000002;2.5500000000000003;3.7750000000000004;5}, {0.06135298887361882;0.5397910520242316;0.7994181121419677;0.9157855619950286;0.9128767480792515})

Expected output:

"non-error"

Example 5: Demo case 5

Inputs:

enz_inhibit_model xdata ydata
uncompetitive_inhibition_es_complex 0.1 0.06301621986100231
1.3250000000000002 0.5264203933870522
2.5500000000000003 0.7747817997119162
3.7750000000000004 0.9106119748601035
5 1.0463971063632589

Excel formula:

=ENZYME_INHIBIT("uncompetitive_inhibition_es_complex", {0.1;1.3250000000000002;2.5500000000000003;3.7750000000000004;5}, {0.06301621986100231;0.5264203933870522;0.7747817997119162;0.9106119748601035;1.0463971063632589})

Expected output:

"non-error"

Python Code

import numpy as np
from scipy.optimize import curve_fit as scipy_curve_fit
import math

def enzyme_inhibit(xdata, ydata, enz_inhibit_model):
    """
    Fits enzyme_inhibit models to data using scipy.optimize.curve_fit. See https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.curve_fit.html for details.

    See: https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.curve_fit.html

    This example function is provided as-is without any representation of accuracy.

    Args:
        xdata (list[list]): The xdata value
        ydata (list[list]): The ydata value
        enz_inhibit_model (str): The enz_inhibit_model value Valid options: Competitive Inhibition Michaelis Menten, Mixed Mode Inhibition General, Noncompetitive Inhibition Classic, Substrate Inhibition High Conc, Uncompetitive Inhibition Es Complex.

    Returns:
        list[list]: 2D list [param_names, fitted_values, std_errors], or error string.
    """
    def _validate_data(xdata, ydata):
        """Validate and convert both xdata and ydata to numpy arrays."""
        for name, arg in [("xdata", xdata), ("ydata", ydata)]:
            if not isinstance(arg, list) or len(arg) < 2:
                raise ValueError(f"{name}: must be a 2D list with at least two rows")
            vals = []
            for i, row in enumerate(arg):
                if not isinstance(row, list) or len(row) == 0:
                    raise ValueError(f"{name} row {i}: must be a non-empty list")
                try:
                    vals.append(float(row[0]))
                except Exception:
                    raise ValueError(f"{name} row {i}: non-numeric value")
            if name == "xdata":
                x_arr = np.asarray(vals, dtype=np.float64)
            else:
                y_arr = np.asarray(vals, dtype=np.float64)

        if x_arr.shape[0] != y_arr.shape[0]:
            raise ValueError("xdata and ydata must have the same number of rows")
        return x_arr, y_arr

    # Model definitions dictionary
    models = {
        'competitive_inhibition_michaelis_menten': {
            'params': ['Vmax', 'Km', 'Ki', 'Ic'],
            'model': lambda x, Vmax, Km, Ki, Ic: (Vmax * x) / (Km * (1.0 + Ic / Ki) + x),
            'guess': lambda xa, ya: (float(np.max(ya)), float(np.median(xa)), 1.0, float(np.mean(xa))),
            'bounds': ([0.0, 0.0, 0.0, -np.inf], np.inf),
        },
        'mixed_mode_inhibition_general': {
            'params': ['Vmax', 'Km', 'Ki', 'Alpha', 'Ic'],
            'model': lambda x, Vmax, Km, Ki, Alpha, Ic: (Vmax * x / (1.0 + Ic / (Alpha * Ki))) / (x + (Km * (1.0 + Ic / Ki)) / (1.0 + Ic / (Alpha * Ki))),
            'guess': lambda xa, ya: (float(np.max(ya)), float(np.median(xa)), 1.0, 1.0, float(np.mean(xa))),
            'bounds': ([0.0, 0.0, 0.0, 0.0, -np.inf], np.inf),
        },
        'noncompetitive_inhibition_classic': {
            'params': ['Vmax', 'Km', 'Ki', 'Ic'],
            'model': lambda x, Vmax, Km, Ki, Ic: Vmax * x / ((1.0 + Ic / Ki) * (Km + x)),
            'guess': lambda xa, ya: (float(np.max(ya)), float(np.median(xa)), 1.0, float(np.mean(xa))),
            'bounds': ([0.0, 0.0, 0.0, -np.inf], np.inf),
        },
        'substrate_inhibition_high_conc': {
            'params': ['Vmax', 'Km', 'Ki'],
            'model': lambda x, Vmax, Km, Ki: Vmax * x / (Km + x * (1.0 + x / Ki)),
            'guess': lambda xa, ya: (float(np.max(ya)), float(np.median(xa)), 1.0),
            'bounds': (0.0, np.inf),
        },
        'uncompetitive_inhibition_es_complex': {
            'params': ['Vmax', 'Km', 'Kia', 'Ic'],
            'model': lambda x, Vmax, Km, Kia, Ic: Vmax * x / ((1.0 + Ic / Kia) * (Km / (1.0 + Ic / Kia) + x)),
            'guess': lambda xa, ya: (float(np.max(ya)), float(np.median(xa)), 1.0, float(np.mean(xa))),
            'bounds': ([0.0, 0.0, 0.0, -np.inf], np.inf),
        }
    }

    # Validate model parameter
    if enz_inhibit_model not in models:
        return f"Invalid model: {str(enz_inhibit_model)}. Valid models are: {', '.join(models.keys())}"

    model_info = models[enz_inhibit_model]

    # Validate and convert input data
    try:
        x_arr, y_arr = _validate_data(xdata, ydata)
    except ValueError as e:
        return f"Invalid input: {e}"

    # Perform curve fitting
    try:
        p0 = model_info['guess'](x_arr, y_arr)
        bounds = model_info.get('bounds', (-np.inf, np.inf))
        if bounds == (-np.inf, np.inf):
            popt, pcov = scipy_curve_fit(model_info['model'], x_arr, y_arr, p0=p0, maxfev=10000)
        else:
            popt, pcov = scipy_curve_fit(model_info['model'], x_arr, y_arr, p0=p0, bounds=bounds, maxfev=10000)

        fitted_vals = [float(v) for v in popt]
        for v in fitted_vals:
            if math.isnan(v) or math.isinf(v):
                return "Fitting produced invalid numeric values (NaN or inf)."
    except ValueError as e:
        return f"Initial guess error: {e}"
    except Exception as e:
        return f"curve_fit error: {e}"

    # Calculate standard errors
    std_errors = None
    try:
        if pcov is not None and np.isfinite(pcov).all():
            std_errors = [float(v) for v in np.sqrt(np.diag(pcov))]
    except Exception:
        pass

    return [model_info['params'], fitted_vals, std_errors] if std_errors else [model_info['params'], fitted_vals]

Online Calculator