"""
Utility functions for IM2Deep package.
This module provides utility functions for converting between different
mobility measurements and configuration settings for multi-conformer models.
Functions:
im2ccs: Convert ion mobility to collisional cross section
ccs2im: Convert collisional cross section to ion mobility
Constants:
multi_config: Configuration dictionary for multi-conformer model
MULTI_BACKBONE_PATH: Path to the multi-conformer model backbone
"""
from __future__ import annotations
import logging
import numpy as np
from im2deep.constants import (
MASS_GAS_N2,
SUMMARY_CONSTANT,
T_DIFF,
TEMP,
)
LOGGER = logging.getLogger(__name__)
[docs]
def im2ccs(
reverse_im: float | np.ndarray,
mz: float | np.ndarray,
charge: int | np.ndarray,
mass_gas: float = MASS_GAS_N2,
temp: float = TEMP,
t_diff: float = T_DIFF,
) -> float | np.ndarray:
r"""
Convert reduced ion mobility to collisional cross section.
This function converts reduced ion mobility (1/K0) values to collisional
cross section (CCS) using the Mason-Schamp equation. The conversion is
temperature and gas-dependent.
Parameters
----------
reverse_im : float or array-like
Reduced ion mobility (1/K0) in V⋅s/cm².
mz : float or array-like
Precursor m/z ratio.
charge : int or array-like
Precursor charge state.
mass_gas : float, optional
Mass of drift gas in atomic mass units. Default is 28.013 (N₂).
temp : float, optional
Temperature in Celsius. Default is 31.85°C
t_diff : float, optional
Temperature conversion factor (°C to K). Default is 273.15.
Returns
-------
float or np.ndarray
Collisional cross section in Ų (square Angstroms).
Notes
-----
The conversion uses the Mason-Schamp equation:
.. math::
\Omega = \frac{C \cdot z}{\sqrt{\mu \cdot T} \cdot K_0}
where :math:`\Omega` is the CCS, :math:`C` is a summary constant (18509.8632163405),
:math:`z` is the charge, :math:`\mu` is the reduced mass, :math:`T` is the temperature
in Kelvin, and :math:`K_0` is the reduced ion mobility.
References
----------
Adapted from `theGreatHerrLebert/ionmob <https://doi.org/10.1093/bioinformatics/btad486>`_.
Examples
--------
>>> im2ccs(0.7, 500.0, 2)
425.3
>>> # For arrays
>>> import numpy as np
>>> ims = np.array([0.7, 0.8, 0.9])
>>> mzs = np.array([500.0, 600.0, 700.0])
>>> charges = np.array([2, 2, 3])
>>> ccs_values = im2ccs(ims, mzs, charges)
"""
# Validate inputs
if np.any(reverse_im <= 0):
raise ValueError("Reduced ion mobility must be positive")
if np.any(mz <= 0):
raise ValueError("m/z must be positive")
if np.any(charge <= 0):
raise ValueError("Charge must be positive")
if mass_gas <= 0:
raise ValueError("Gas mass must be positive")
if temp <= -t_diff:
raise ValueError("Temperature must be above absolute zero")
reduced_mass = (mz * charge * mass_gas) / (mz * charge + mass_gas)
return (SUMMARY_CONSTANT * charge) / (np.sqrt(reduced_mass * (temp + t_diff)) * 1 / reverse_im)
[docs]
def ccs2im(
ccs: float | np.ndarray,
mz: float | np.ndarray,
charge: int | np.ndarray,
mass_gas: float = MASS_GAS_N2,
temp: float = TEMP,
t_diff: float = T_DIFF,
) -> float | np.ndarray:
r"""
Convert collisional cross section to reduced ion mobility.
This function converts collisional cross section (CCS) values to reduced
ion mobility (1/K0) using the inverse of the Mason-Schamp equation.
Parameters
----------
ccs : float or array-like
Collisional cross section in Ų (square Angstroms).
mz : float or array-like
Precursor m/z ratio.
charge : int or array-like
Precursor charge state.
mass_gas : float, optional
Mass of drift gas in atomic mass units. Default is 28.013 (N₂).
temp : float, optional
Temperature in Celsius. Default is 31.85°C (typical for TIMS).
t_diff : float, optional
Temperature conversion factor (°C to K). Default is 273.15.
Returns
-------
float or np.ndarray
Reduced ion mobility (1/K0) in V⋅s/cm².
Notes
-----
The conversion uses the inverse Mason-Schamp equation:
.. math::
\frac{1}{K_0} = \frac{\sqrt{\mu \cdot T} \cdot \Omega}{C \cdot z}
where :math:`\Omega` is the CCS, :math:`C` is a summary constant (18509.8632163405),
:math:`z` is the charge, :math:`\mu` is the reduced mass, and :math:`T` is the temperature
in Kelvin.
References
----------
Adapted from `theGreatHerrLebert/ionmob <https://doi.org/10.1093/bioinformatics/btad486>`_.
Examples
--------
>>> ccs2im(425.3, 500.0, 2)
0.7
>>> # For arrays
>>> import numpy as np
>>> ccs_values = np.array([425.3, 510.2, 680.5])
>>> mzs = np.array([500.0, 600.0, 700.0])
>>> charges = np.array([2, 2, 3])
>>> ims = ccs2im(ccs_values, mzs, charges)
"""
# Validate inputs
if np.any(ccs <= 0):
raise ValueError("CCS must be positive")
if np.any(mz <= 0):
raise ValueError("m/z must be positive")
if np.any(charge <= 0):
raise ValueError("Charge must be positive")
if mass_gas <= 0:
raise ValueError("Gas mass must be positive")
if temp <= -t_diff:
raise ValueError("Temperature must be above absolute zero")
reduced_mass = (mz * charge * mass_gas) / (mz * charge + mass_gas)
return ((np.sqrt(reduced_mass * (temp + t_diff))) * ccs) / (SUMMARY_CONSTANT * charge)