1010import re
1111
1212def _get_pyopenms ():
13- """Lazy import of pyOpenMS to avoid loading issues."""
13+ """Lazy import of pyOpenMS to avoid loading issues.
14+
15+ Returns:
16+ module: The pyopenms module.
17+
18+ """
1419 import pyopenms as poms
1520 return poms
1621
1722_mod_db_cache = None
1823
1924def _get_pyopenms_mod_db ():
20- """Lazy import and cached initialization of pyOpenMS ModificationsDB."""
25+ """Lazy import and cached initialization of pyOpenMS ModificationsDB.
26+
27+ Returns:
28+ ModificationsDB: The cached ModificationsDB instance.
29+
30+ """
2131 global _mod_db_cache
2232 if _mod_db_cache is None :
2333 poms = _get_pyopenms ()
@@ -46,8 +56,16 @@ class SequenceAnalysis:
4656
4757
4858def parse_square_bracket_modifications (sequence : str ) -> Tuple [str , str ]:
49- """
50- Parse peptide sequence with square bracket modifications and convert to pyOpenMS format.
59+ """Parse peptide sequence with square bracket modifications and convert to pyOpenMS format.
60+
61+ Args:
62+ sequence (str): The peptide sequence containing square bracket modifications.
63+
64+ Returns:
65+ Tuple[str, str]: A tuple containing (clean_sequence, modified_sequence).
66+ clean_sequence is the sequence without modifications.
67+ modified_sequence is the sequence converted to pyOpenMS format.
68+
5169 """
5270 poms = _get_pyopenms ()
5371 mod_db = _get_pyopenms_mod_db ()
@@ -58,7 +76,15 @@ def parse_square_bracket_modifications(sequence: str) -> Tuple[str, str]:
5876 sequence = sequence [1 :]
5977
6078 def convert_modification (mod_text ):
61- """Convert modification text to OpenMS format using ModificationsDB."""
79+ """Convert modification text to OpenMS format using ModificationsDB.
80+
81+ Args:
82+ mod_text (str): The modification text to convert.
83+
84+ Returns:
85+ str: The converted modification in OpenMS format.
86+
87+ """
6288 mod_text = mod_text .strip ()
6389
6490 # Check if it's a numeric mass delta (ProForma arbitrary mass shift)
@@ -137,8 +163,18 @@ def replace_aa_mod(match):
137163
138164
139165def validate_peptide_sequence_with_mods (sequence : str ) -> Tuple [bool , str , str , int ]:
140- """
141- Validate peptide sequence that may contain modifications and charge notation.
166+ """Validate peptide sequence that may contain modifications and charge notation.
167+
168+ Args:
169+ sequence (str): The peptide sequence to validate.
170+
171+ Returns:
172+ Tuple[bool, str, str, int]: A tuple containing (is_valid, clean_sequence, openms_sequence, charge_state).
173+ is_valid indicates if the sequence is valid.
174+ clean_sequence is the sequence without modifications.
175+ openms_sequence is the OpenMS-formatted sequence.
176+ charge_state is the detected charge state.
177+
142178 """
143179 try :
144180 clean_sequence , openms_sequence , charge_state = parse_sequence_with_mods_and_charge (sequence )
@@ -152,7 +188,17 @@ def validate_peptide_sequence_with_mods(sequence: str) -> Tuple[bool, str, str,
152188
153189
154190def validate_peptide_sequence (sequence : str ) -> tuple [bool , str ]:
155- """Validate peptide sequence contains only valid amino acids."""
191+ """Validate peptide sequence contains only valid amino acids.
192+
193+ Args:
194+ sequence (str): The peptide sequence to validate.
195+
196+ Returns:
197+ tuple[bool, str]: A tuple containing (is_valid, clean_sequence).
198+ is_valid indicates if the sequence contains only valid amino acids.
199+ clean_sequence is the sequence without modifications.
200+
201+ """
156202 try :
157203 clean_sequence , _ = parse_square_bracket_modifications (sequence )
158204
@@ -177,7 +223,16 @@ def validate_peptide_sequence(sequence: str) -> tuple[bool, str]:
177223
178224
179225def apply_modification (sequence : str , modification : str ) -> str :
180- """Apply the selected modification to the peptide sequence."""
226+ """Apply the selected modification to the peptide sequence.
227+
228+ Args:
229+ sequence (str): The peptide sequence to modify.
230+ modification (str): The modification to apply (e.g., "Oxidation (M)", "None").
231+
232+ Returns:
233+ str: The modified sequence in OpenMS format.
234+
235+ """
181236 if modification == "None" :
182237 return sequence
183238
@@ -214,14 +269,31 @@ def apply_modification(sequence: str, modification: str) -> str:
214269
215270
216271def calculate_peptide_mz (sequence : str , charge_state : int , modification : str = "None" ) -> Dict [str , Any ]:
217- """
218- Calculate the m/z ratio and related properties for a peptide.
219-
272+ """Calculate the m/z ratio and related properties for a peptide.
273+
220274 Args:
221- sequence: The peptide sequence. Can contain modifications in square brackets
222- and/or charge notation (e.g., "PEPTIDE/2", "M[Oxidation]PEPTIDE/3")
223- charge_state: The charge state - will be overridden if charge notation is found
224- modification: Additional modification to apply from dropdown
275+ sequence (str): The peptide sequence. Can contain modifications in square brackets
276+ and/or charge notation (e.g., "PEPTIDE/2", "M[Oxidation]PEPTIDE/3").
277+ charge_state (int): The charge state - will be overridden if charge notation is found.
278+ modification (str): Additional modification to apply from dropdown. Defaults to "None".
279+
280+ Returns:
281+ Dict[str, Any]: A dictionary containing calculation results including:
282+ - mz_ratio: The calculated m/z ratio
283+ - monoisotopic_mass: The monoisotopic mass in Da
284+ - molecular_formula: The molecular formula
285+ - original_sequence: The clean amino acid sequence
286+ - modified_sequence: The sequence with modifications
287+ - charge_state: The final charge state used
288+ - charge_source: Where the charge state came from
289+ - modification: The applied modification
290+ - sequence_length: Length of the sequence
291+ - aa_composition: Amino acid composition dictionary
292+ - success: Boolean indicating successful calculation
293+
294+ Raises:
295+ ValueError: If sequence is empty, charge state is invalid, or sequence contains invalid characters.
296+
225297 """
226298 if not sequence .strip ():
227299 raise ValueError ("Peptide sequence cannot be empty" )
@@ -311,7 +383,12 @@ def calculate_peptide_mz(sequence: str, charge_state: int, modification: str = "
311383
312384
313385def get_supported_modifications () -> list :
314- """Get a list of supported peptide modifications."""
386+ """Get a list of supported peptide modifications.
387+
388+ Returns:
389+ list: A list of supported modification names including "None".
390+
391+ """
315392 common_modifications = [
316393 "None" ,
317394 "Oxidation (M)" ,
@@ -326,7 +403,13 @@ def get_supported_modifications() -> list:
326403
327404
328405def get_modification_info () -> Dict [str , str ]:
329- """Get detailed information about supported modifications."""
406+ """Get detailed information about supported modifications.
407+
408+ Returns:
409+ Dict[str, str]: A dictionary mapping modification names to their detailed descriptions
410+ including mass delta and target information.
411+
412+ """
330413 poms = _get_pyopenms ()
331414 mod_db = _get_pyopenms_mod_db ()
332415 info_dict = {"None" : "No modification applied" }
@@ -383,7 +466,12 @@ def get_modification_info() -> Dict[str, str]:
383466
384467
385468def get_square_bracket_examples () -> Dict [str , str ]:
386- """Get examples of square bracket modification notation and charge notation."""
469+ """Get examples of square bracket modification notation and charge notation.
470+
471+ Returns:
472+ Dict[str, str]: A dictionary mapping example sequences to their descriptions.
473+
474+ """
387475 return {
388476 "M[Oxidation]PEPTIDE" : "Methionine oxidation at position 1" ,
389477 "PEPTIDEC[Carbamidomethyl]" : "Carbamidomethylated cysteine at C-terminus" ,
@@ -415,7 +503,15 @@ def get_square_bracket_examples() -> Dict[str, str]:
415503
416504
417505def validate_openms_sequence (sequence : str ) -> bool :
418- """Validate if a sequence string is compatible with pyOpenMS AASequence."""
506+ """Validate if a sequence string is compatible with pyOpenMS AASequence.
507+
508+ Args:
509+ sequence (str): The sequence string to validate.
510+
511+ Returns:
512+ bool: True if the sequence is compatible with pyOpenMS, False otherwise.
513+
514+ """
419515 try :
420516 poms = _get_pyopenms ()
421517 poms .AASequence .fromString (sequence )
@@ -425,9 +521,18 @@ def validate_openms_sequence(sequence: str) -> bool:
425521
426522
427523def parse_charge_notation (sequence : str ) -> Tuple [str , int ]:
428- """
429- Parse peptide sequence with charge notation and extract charge state.
524+ """Parse peptide sequence with charge notation and extract charge state.
525+
430526 Supports both /charge and trailing number formats.
527+
528+ Args:
529+ sequence (str): The peptide sequence that may contain charge notation.
530+
531+ Returns:
532+ Tuple[str, int]: A tuple containing (sequence_without_charge, charge_state).
533+ sequence_without_charge is the sequence with charge notation removed.
534+ charge_state is the extracted charge state (1 if none found).
535+
431536 """
432537 sequence = sequence .strip ()
433538
@@ -460,17 +565,35 @@ def parse_charge_notation(sequence: str) -> Tuple[str, int]:
460565
461566
462567def parse_sequence_with_mods_and_charge (sequence : str ) -> Tuple [str , str , int ]:
463- """Parse peptide sequence with both modifications and charge notation."""
568+ """Parse peptide sequence with both modifications and charge notation.
569+
570+ Args:
571+ sequence (str): The peptide sequence containing modifications and/or charge notation.
572+
573+ Returns:
574+ Tuple[str, str, int]: A tuple containing (clean_sequence, modified_sequence, charge_state).
575+ clean_sequence is the sequence without modifications.
576+ modified_sequence is the OpenMS-formatted sequence.
577+ charge_state is the extracted charge state.
578+
579+ """
464580 sequence_no_charge , charge_state = parse_charge_notation (sequence )
465581 clean_sequence , modified_sequence = parse_square_bracket_modifications (sequence_no_charge )
466582
467583 return clean_sequence , modified_sequence , charge_state
468584
469585
470586def detect_modification_from_sequence (sequence : str ) -> str :
471- """
472- Detect the primary modification type from a peptide sequence.
587+ """Detect the primary modification type from a peptide sequence.
588+
473589 Uses ModificationsDB for accurate mass delta matching.
590+
591+ Args:
592+ sequence (str): The peptide sequence to analyze for modifications.
593+
594+ Returns:
595+ str: The detected modification name matching dropdown options, or "None" if no modification detected.
596+
474597 """
475598 if not re .search (r'[\[\(]' , sequence ):
476599 return "None"
@@ -512,8 +635,15 @@ def detect_modification_from_sequence(sequence: str) -> str:
512635
513636
514637def _match_mass_delta_to_modification (mass_delta : float , tolerance : float = 0.01 ) -> str :
515- """
516- Match a mass delta to a known modification using ModificationsDB.
638+ """Match a mass delta to a known modification using ModificationsDB.
639+
640+ Args:
641+ mass_delta (float): The mass delta to match against known modifications.
642+ tolerance (float): Mass tolerance in Da for matching. Defaults to 0.01.
643+
644+ Returns:
645+ str: The dropdown modification name if found, "None" otherwise.
646+
517647 """
518648 try :
519649 mod_db = _get_pyopenms_mod_db ()
@@ -563,8 +693,17 @@ def _match_mass_delta_to_modification(mass_delta: float, tolerance: float = 0.01
563693
564694
565695def parse_proforma_sequence (sequence : str ) -> Tuple [str , str , bool ]:
566- """
567- Parse ProForma-style sequence, trying direct PyOpenMS parsing first.
696+ """Parse ProForma-style sequence, trying direct PyOpenMS parsing first.
697+
698+ Args:
699+ sequence (str): The ProForma-style peptide sequence to parse.
700+
701+ Returns:
702+ Tuple[str, str, bool]: A tuple containing (clean_sequence, converted_sequence, proforma_direct).
703+ clean_sequence is the sequence without modifications.
704+ converted_sequence is the converted or original sequence.
705+ proforma_direct indicates if direct PyOpenMS parsing was successful.
706+
568707 """
569708 sequence = sequence .strip ()
570709 if sequence .startswith ('.' ):
@@ -587,7 +726,22 @@ def parse_proforma_sequence(sequence: str) -> Tuple[str, str, bool]:
587726
588727
589728def analyze_peptide_sequence (sequence : str ) -> SequenceAnalysis :
590- """Unified sequence analysis function that detects modifications and charge state."""
729+ """Unified sequence analysis function that detects modifications and charge state.
730+
731+ Args:
732+ sequence (str): The peptide sequence to analyze.
733+
734+ Returns:
735+ SequenceAnalysis: A dataclass containing analysis results including:
736+ - modification: Detected modification name
737+ - modification_detected: Boolean indicating if modification was found
738+ - charge: Detected or default charge state
739+ - charge_detected: Boolean indicating if charge was found in sequence
740+ - is_valid: Boolean indicating if sequence is valid
741+ - clean_sequence: The sequence without modifications
742+ - error_message: Error message if validation failed
743+
744+ """
591745 analysis = SequenceAnalysis ()
592746
593747 if not sequence or not sequence .strip ():
@@ -624,10 +778,20 @@ def analyze_peptide_sequence(sequence: str) -> SequenceAnalysis:
624778
625779
626780def get_cached_modifications ():
627- """Get supported modifications list for caching"""
781+ """Get supported modifications list for caching.
782+
783+ Returns:
784+ list: A list of supported modification names from get_supported_modifications().
785+
786+ """
628787 return get_supported_modifications ()
629788
630789
631790def get_cached_examples ():
632- """Get square bracket examples for caching"""
791+ """Get square bracket examples for caching.
792+
793+ Returns:
794+ Dict[str, str]: A dictionary of example sequences and descriptions from get_square_bracket_examples().
795+
796+ """
633797 return get_square_bracket_examples ()
0 commit comments