Package csb :: Package bio :: Package io :: Module cs |
[frames] | no frames]

# Source Code for Module csb.bio.io.cs

      1  """
      2  Simple NMR STAR chemical shift readers.
      3  """
      4
      5  from csb.bio.nmr import ChemShiftInfo
      6
      7
      8 -class ChemShiftFormatError(ValueError):
      9      pass
     10
     11
     12 -class ChemShiftReader(object):
     13      """
     14      Simple NMR STAR v2 chemical shift reader.
     15
     16      @note: This is not a full-fledged, semantic NMR STAR parser. It handles
     17             only the chemical shift table.
     18      """
     19
     20      FRAME = 'save_assigned_chemical_shifts'
     21
     22      RANK = '_Residue_seq_code'
     23      RESIDUE = '_Residue_label'
     24      ATOM = '_Atom_name'
     25      ELEMENT = '_Atom_type'
     26      SHIFT = '_Chem_shift_value'
     27
     28      @staticmethod
     29 -    def create(frame=FRAME, version=2):
     30          """
     31          Parser factory: create a new parser, given a saveframe name
     32          and format verison.
     33
     34          @param frame: name of the saveframe to read
     35          @type frame: str
     36          @param version: NMR STAR format version
     37          @type version: int
     38
     39          @return: an instance of any L{ChemShiftReader} class
     40          @rtype: L{ChemShiftReader}
     41          """
     42
     43          if version == 3:
     44              return ChemShift3Reader(frame=frame)
     45          elif version == 2:
     46              return ChemShiftReader(frame=frame)
     47          else:
     48              raise ValueError('Unknown NMR-STAR version')
     49
     50      @staticmethod
     51 -    def guess(file, frame=FRAME):
     52          """
     53          Parser factory: try to guess the correct NMR STAR version from a given
     54          file and create an appropriate parser.
     55
     56          @param file: NMR STAR path and file name
     57          @type file: str
     58          @param frame: name of the saveframe to read
     59          @type frame: str
     60
     61          @return: an instance of any L{ChemShiftReader} class
     62          @rtype: L{ChemShiftReader}
     63
     64          @raise ChemShiftFormatError: on failure to determine the NMR STAR version
     65          """
     66
     67          with open(file) as cs:
     68              content = cs.read()
     69
     70              if not content.strip():
     71                  return ChemShiftReader.create()
     72              elif ChemShift3Reader.SHIFT3 in content:
     73                  return ChemShiftReader.create(frame, version=3)
     74              elif ChemShiftReader.SHIFT in content:
     75                  return ChemShiftReader.create(frame, version=2)
     76              else:
     77                  raise ChemShiftFormatError("Can't guess NMR-STAR version")
     78
     79 -    def __init__(self, frame=FRAME):
     80          self._frame = frame
     81
     82 -    def read_file(self, filename):
     83          """
     84          Parse the specified file.
     85
     86          @param filename: file path and name
     87          @type filename: str
     88
     89          @rtype: tuple of L{ChemShiftInfo}
     90          """
     91          with open(filename) as input:
     92              return self.read_shifts(input.read())
     93
     94 -    def read_shifts(self, star_table):
     95          """
     96          Parse a given NMR STAR chemical shift table.
     97
     98          @param star_table: NMR STAR chemical shift table
     99          @type star_table: str
    100
    101          @rtype: tuple of L{ChemShiftInfo}
    102          @raise ChemShiftFormatError: on parse error
    103          """
    104
    105          shifts = []
    106
    107          init = False
    108          in_shifts = False
    109          fields = []
    110          lines = iter(star_table.splitlines())
    111
    112          if self._frame in star_table:
    113              self._scroll(lines, self._frame)
    114
    115
    116          for l in lines:
    117              ls = l.strip()
    118
    119              if not in_shifts:
    120
    121                  if ls == 'loop_':
    122                      assert in_shifts is False and not fields and init is False
    123                      init = True
    124                      continue
    125
    126                  elif init and ls.startswith('_'):
    127                      assert in_shifts is False
    128                      fields.append(l.strip())
    129                      continue
    130
    131                  elif init and not ls:
    132                      if len(fields) < 1:
    133                          raise ChemShiftFormatError("No fields found in the CS table")
    134                      in_shifts = True
    135                      continue
    136
    137              else:
    138
    139                  if ls == 'stop_':
    140                      break
    141
    142                  elif ls.startswith('#'):
    143                      continue
    144
    145                  elif ls:
    146                      values = l.split()
    147                      if len(values) < len(fields):
    148                          raise ChemShiftFormatError("Insufficient number of values: {0}".format(l))
    149                      data = dict(zip(fields, values))
    150
    151                      shifts.append(self._create_shift(data))
    152
    153          return tuple(shifts)
    154
    155 -    def _scroll(self, iterator, field):
    156
    157          for line in iterator:
    158              if line.lstrip().startswith(field):
    159                  break
    160
    161 -    def _create_shift(self, data):
    162
    163          try:
    164              position = int(data[ChemShiftReader.RANK])
    165              residue = data[ChemShiftReader.RESIDUE]
    166              name = data[ChemShiftReader.ATOM]
    167              element = data[ChemShiftReader.ELEMENT]
    168              shift = float(data[ChemShiftReader.SHIFT])
    169
    170          except KeyError as ke:
    171              raise ChemShiftFormatError("Required field {0} not found".format(str(ke)))
    172          except ValueError as ve:
    173              raise ChemShiftFormatError("Can't parse value: {0}".format(str(ve)))
    174
    175          return ChemShiftInfo(position, residue, name, element, shift)
    176
    177
    178 -class ChemShift3Reader(ChemShiftReader):
    179      """
    180      Simple NMR STAR v3 chemical shift reader.
    181
    182      @note: This is not a full-fledged, semantic NMR STAR parser. It handles
    183             only the chemical shift table.
    184      """
    185
    186      RANK3 = '_Atom_chem_shift.Seq_ID'
    187      RESIDUE3 = '_Atom_chem_shift.Comp_ID'
    188      ATOM3 = '_Atom_chem_shift.Atom_ID'
    189      ELEMENT3 = '_Atom_chem_shift.Atom_type'
    190      SHIFT3 = '_Atom_chem_shift.Val'
    191
    192 -    def _create_shift(self, data):
    193
    194          try:
    195              position = data[ChemShift3Reader.RANK3]
    196              residue = data[ChemShift3Reader.RESIDUE3]
    197              name = data[ChemShift3Reader.ATOM3]
    198              element = data[ChemShift3Reader.ELEMENT3]
    199              shift = data[ChemShift3Reader.SHIFT3]
    200
    201          except KeyError as ke:
    202              raise ChemShiftFormatError("Required field {0} not found".format(str(ke)))
    203          except ValueError as ve:
    204              raise ChemShiftFormatError("Can't parse value: {0}".format(str(ve)))
    205
    206          return ChemShiftInfo(position, residue, name, element, shift)
    207