This file is indexed.

/usr/share/mmass/mspy/parser_mgf.py is in mmass 5.5.0-5.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
# -------------------------------------------------------------------------
#     Copyright (C) 2005-2013 Martin Strohalm <www.mmass.org>

#     This program is free software; you can redistribute it and/or modify
#     it under the terms of the GNU General Public License as published by
#     the Free Software Foundation; either version 3 of the License, or
#     (at your option) any later version.

#     This program is distributed in the hope that it will be useful,
#     but WITHOUT ANY WARRANTY; without even the implied warranty of
#     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
#     GNU General Public License for more details.

#     Complete text of GNU GPL can be found in the file LICENSE.TXT in the
#     main directory of the program.
# -------------------------------------------------------------------------

# load libs
import re
import os.path
from copy import deepcopy

# load stopper
from mod_stopper import CHECK_FORCE_QUIT

# load objects
import obj_peak
import obj_peaklist
import obj_scan


# PARSE MGF DATA
# --------------

class parseMGF():
    """Parse data from MGF."""
    
    def __init__(self, path):
        self.path = path
        self._scans = None
        self._scanlist = None
        
        # check path
        if not os.path.exists(path):
            raise IOError, 'File not found! --> ' + self.path
    # ----
    
    
    def load(self):
        """Load all scans into memory."""
        self._parseData()
    # ----
    
    
    def info(self):
        """Get document info."""
        
        data = {
            'title': '',
            'operator': '',
            'contact': '',
            'institution': '',
            'date': '',
            'instrument': '',
            'notes': '',
        }
        
        return data
    # ----
    
    
    def scanlist(self):
        """Get list of all scans in the document."""
        
        # use preloaded data if available
        if self._scanlist:
            return self._scanlist
        
        # parse data
        self._parseData()
        
        return self._scanlist
    # ----
    
    
    def scan(self, scanID=None, dataType=None):
        """Get spectrum from document."""
        
        # parse file
        if not self._scans:
            self._parseData()
        
        # check data
        if not self._scans:
            return False
        
        # check selected scan
        if scanID in self._scans:
            data = self._scans[scanID]
        elif scanID == None:
            data = self._scans[0]
        
        # return scan
        return self._makeScan(data, dataType)
    # ----
    
    
    def _parseData(self):
        """Parse data."""
        
        # clear buffers
        self._scans = {}
        self._scanlist = None
        
        # open document
        try:
            document = file(self.path)
            rawData = document.readlines()
            document.close()
        except IOError:
            return False
        
        headerPattern = re.compile('^([A-Z]+)=(.+)')
        pointPattern = re.compile('[ \t]?')
        currentID = None
        
        # parse each line
        for line in rawData:
            line = line.strip()
            
            # discard comments
            if not line or line[0] in ('#', ';', '!', '/'):
                continue
            
            # append default scan
            if currentID == None or line == 'BEGIN IONS':
                currentID = len(self._scans)
                scan = {
                    'title': '',
                    'scanNumber': currentID,
                    'parentScanNumber': None,
                    'msLevel': None,
                    'pointsCount': 0,
                    'polarity': None,
                    'retentionTime': None,
                    'lowMZ': None,
                    'highMZ': None,
                    'basePeakMZ': None,
                    'basePeakIntensity': None,
                    'totIonCurrent': None,
                    'precursorMZ': None,
                    'precursorIntensity': None,
                    'precursorCharge': None,
                    'spectrumType': 'unknown',
                    'data': [],
                }
                self._scans[currentID] = scan
            
            # scan ended, use default scan
            if line == 'END IONS':
                currentID = 0
                continue
            
            # get header data
            parts = headerPattern.match(line)
            if parts:
                if parts.group(1) == 'TITLE':
                    self._scans[currentID]['title'] = parts.group(2).strip()
                elif parts.group(1) == 'PEPMASS':
                    try: self._scans[currentID]['precursorMZ'] = float(pointPattern.split(parts.group(2))[0])
                    except: pass
                elif parts.group(1) == 'CHARGE':
                    charge = parts.group(2).strip()
                    if charge[-1] in ('+', '-'):
                        charge = charge[-1]+charge[:-1]
                    try: self._scans[currentID]['precursorCharge'] = int(charge)
                    except: pass
                continue
            
            # append datapoint
            parts = pointPattern.split(line)
            if parts:
                point = [0,100.]
                try: point[0] = float(parts[0])
                except ValueError: continue
                try: point[1] = float(parts[1])
                except ValueError, IndexError: pass
                self._scans[currentID]['data'].append(point)
                self._scans[currentID]['pointsCount'] += 1
                continue
        
        # make scanlist
        if self._scans:
            self._scanlist = deepcopy(self._scans)
            for scanNumber in self._scanlist:
                del self._scanlist[scanNumber]['data']
    # ----
    
    
    def _makeScan(self, scanData, dataType):
        """Make scan object from raw data."""
        
        # parse data as peaklist (discrete points)
        if dataType == 'peaklist' or (dataType==None and len(scanData['data'])<3000):
            buff = []
            for point in scanData['data']:
                buff.append(obj_peak.peak(point[0], point[1]))
            scan = obj_scan.scan(peaklist=obj_peaklist.peaklist(buff))
        
        # parse data as spectrum (continuous line)
        else:
            scan = obj_scan.scan(profile=scanData['data'])
        
        # set metadata
        scan.title = scanData['title']
        scan.scanNumber = scanData['scanNumber']
        scan.parentScanNumber = scanData['parentScanNumber']
        scan.msLevel = scanData['msLevel']
        scan.polarity = scanData['polarity']
        scan.retentionTime = scanData['retentionTime']
        scan.totIonCurrent = scanData['totIonCurrent']
        scan.basePeakMZ = scanData['basePeakMZ']
        scan.basePeakIntensity = scanData['basePeakIntensity']
        scan.precursorMZ = scanData['precursorMZ']
        scan.precursorIntensity = scanData['precursorIntensity']
        scan.precursorCharge = scanData['precursorCharge']
        
        return scan
    # ----