Source code for alphadia.libtransform.multiplex
import logging
from functools import reduce
from alphabase.constants.modification import MOD_DF
from alphabase.spectral_library.base import SpecLibBase
from alphadia.libtransform.base import ProcessingStep
logger = logging.getLogger()
[docs]
class MultiplexLibrary(ProcessingStep):
[docs]
def __init__(self, multiplex_mapping: list, input_channel: str | int | None = None):
"""Initialize the MultiplexLibrary step."""
self._multiplex_mapping = self._create_multiplex_mapping(multiplex_mapping)
self._input_channel = input_channel
@staticmethod
def _create_multiplex_mapping(multiplex_mapping: list) -> dict:
"""Create a dictionary from the multiplex mapping list."""
mapping = {}
for list_item in multiplex_mapping:
mapping[list_item["channel_name"]] = list_item["modifications"]
return mapping
[docs]
def validate(self, input: SpecLibBase) -> bool:
"""Validate the input object. It is expected that the input is a SpecLibBase object."""
valid = True
valid &= isinstance(input, SpecLibBase)
# check if all modifications are valid
for _, channel_multiplex_mapping in self._multiplex_mapping.items():
for key, value in channel_multiplex_mapping.items():
for mod in [key, value]:
if mod not in MOD_DF.index:
logger.error(f"Modification {mod} not found in input library")
valid = False
if "channel" in input.precursor_df.columns:
channel_unique = input.precursor_df["channel"].unique()
if self._input_channel not in channel_unique:
logger.error(
f"Input library does not contain channel {self._input_channel}"
)
valid = False
if (len(channel_unique) > 1) and (self._input_channel is None):
logger.error(
f"Input library contains multiple channels {channel_unique}. Please specify a channel."
)
valid = False
return valid
[docs]
def forward(self, input: SpecLibBase) -> SpecLibBase:
"""Apply the MultiplexLibrary step to the input object."""
if "channel" in input.precursor_df.columns:
input.precursor_df = input.precursor_df[
input.precursor_df["channel"] == self._input_channel
]
channel_lib_list = []
for channel, channel_mod_translations in self._multiplex_mapping.items():
logger.info(f"Multiplexing library for channel {channel}")
channel_lib = input.copy()
for original_mod, channel_mod in channel_mod_translations.items():
channel_lib._precursor_df["mods"] = channel_lib._precursor_df[
"mods"
].str.replace(original_mod, channel_mod)
channel_lib._precursor_df["channel"] = channel
channel_lib.calc_fragment_mz_df()
channel_lib_list.append(channel_lib)
def apply_func(x, y):
x.append(y)
return x
speclib = reduce(lambda x, y: apply_func(x, y), channel_lib_list)
speclib.remove_unused_fragments()
return speclib