|
27 | 27 | "mzFidelity", |
28 | 28 | ] |
29 | 29 |
|
| 30 | +KNOWN_METADATA_KEYS = [ |
| 31 | + "num_matched_ions", |
| 32 | + "tot_num_ions", |
| 33 | + "num_missed_cleavages", |
| 34 | +] |
| 35 | + |
30 | 36 |
|
31 | 37 | class PepXMLReader(ReaderBase): |
32 | 38 | """Reader for pepXML PSM files.""" |
@@ -127,47 +133,51 @@ def _parse_peptidoform( |
127 | 133 |
|
128 | 134 | def _parse_psm(self, spectrum_query: dict[str, Any], search_hit: dict[str, Any]) -> PSM: |
129 | 135 | """Parse pepXML PSM to PSM.""" |
130 | | - metadata = { |
131 | | - "num_matched_ions": str(search_hit["num_matched_ions"]), |
132 | | - "tot_num_ions": str(search_hit["tot_num_ions"]), |
133 | | - "num_missed_cleavages": str(search_hit["num_missed_cleavages"]), |
134 | | - } |
| 136 | + # Build metadata from optional search hit fields |
| 137 | + metadata = {key: str(search_hit[key]) for key in KNOWN_METADATA_KEYS if key in search_hit} |
| 138 | + |
| 139 | + # Add all search scores to metadata |
135 | 140 | metadata.update( |
136 | 141 | { |
137 | | - f"search_score_{key.lower()}": str(search_hit["search_score"][key]) |
138 | | - for key in search_hit["search_score"] |
| 142 | + f"search_score_{key.lower()}": str(value) |
| 143 | + for key, value in search_hit["search_score"].items() |
139 | 144 | } |
140 | 145 | ) |
141 | 146 |
|
| 147 | + # Build provenance data from optional spectrum query fields |
| 148 | + provenance_data = { |
| 149 | + k: str(v) |
| 150 | + for k, v in { |
| 151 | + "pepxml_index": spectrum_query.get("index"), |
| 152 | + "start_scan": spectrum_query.get("start_scan"), |
| 153 | + "end_scan": spectrum_query.get("end_scan"), |
| 154 | + }.items() |
| 155 | + if v is not None |
| 156 | + } |
| 157 | + |
142 | 158 | return PSM( |
143 | 159 | peptidoform=self._parse_peptidoform( |
144 | 160 | search_hit["peptide"], |
145 | 161 | search_hit["modifications"], |
146 | 162 | spectrum_query["assumed_charge"], |
147 | 163 | ), |
148 | | - spectrum_id=spectrum_query["spectrumNativeID"] |
149 | | - if "spectrumNativeID" in spectrum_query |
150 | | - else spectrum_query["spectrum"], |
| 164 | + spectrum_id=spectrum_query.get("spectrumNativeID", spectrum_query.get("spectrum")), |
151 | 165 | run=None, |
152 | 166 | collection=None, |
153 | 167 | spectrum=None, |
154 | 168 | is_decoy=None, |
155 | | - score=search_hit["search_score"][self.score_key], |
| 169 | + score=search_hit["search_score"].get(self.score_key, None), |
156 | 170 | qvalue=None, |
157 | 171 | pep=None, |
158 | 172 | precursor_mz=mass_to_mz( |
159 | 173 | spectrum_query["precursor_neutral_mass"], spectrum_query["assumed_charge"] |
160 | 174 | ), |
161 | 175 | retention_time=spectrum_query.get("retention_time_sec"), |
162 | 176 | ion_mobility=spectrum_query.get("ion_mobility"), |
163 | | - protein_list=[p["protein"] for p in search_hit["proteins"]], |
164 | | - rank=search_hit["hit_rank"], |
| 177 | + protein_list=[p["protein"] for p in search_hit.get("proteins", [])], |
| 178 | + rank=search_hit.get("hit_rank", None), |
165 | 179 | source=None, |
166 | | - provenance_data={ |
167 | | - "pepxml_index": str(spectrum_query["index"]), |
168 | | - "start_scan": str(spectrum_query["start_scan"]), |
169 | | - "end_scan": str(spectrum_query["end_scan"]), |
170 | | - }, |
| 180 | + provenance_data=provenance_data, |
171 | 181 | metadata=metadata, |
172 | 182 | rescoring_features={}, |
173 | 183 | ) |
0 commit comments