Example #1
0
def reader(file, stripHydrogens=1):
    lines = collector(file)

    while 1:
        try:
            fields = {}
            name = lines.next().strip()
            userLine = lines.next().strip()
            comment = lines.next().strip()
            molinfo = lines.next()
            numAtoms, numBonds = int(molinfo[0:3]), int(molinfo[3:6])

            atoms = []   # this is the full list of atoms
            _atoms = []  # this is the (potentially stripped list
                         # of atoms.  I.e. no hydrogens.)
            i = 0
            for index in range(numAtoms):
                line = lines.next()
                x,y,z,symbol,mass,charge,stereo,hcount,hcount_fixed = parse_atom(line)
                if symbol == "H" and stripHydrogens:
                    atoms.append(None)
                else:
                    atom = Atom()
                    atoms.append(atom)
                    _atoms.append(atom)
                    atom.set_symbol(symbol)# = symbol
                    atom.explicit_hcount = hcount
                    atom.charge = charge
                    atom._line = line
                    atom.x = x
                    atom.y = y
                    atom.z = z
                    if hcount_fixed:
                        print "hcount fixed"
                        atom.fixed_hcount = 1 # oops, we shouldn't use this
                        atom.has_explicit_hcount = True
                    if mass:
                        atom.weight = atom.mass + mass

                    atom.index = i
                    i = i + 1

            bonds = []
            for index in range(numBonds):
                line = lines.next()
                a1, a2, bondtype, stereo, remainder = parse_bond(line)
                symbol, bondorder, bondtype, fixed = BOND_SYMBOL[bondtype]

                atom1, atom2 = atoms[a1], atoms[a2]
                
                if atom1 is not None and atom2 is not None:
                    h1, h2 = atom1.handle, atom2.handle
                    bond = Bond(symbol, bondorder, bondtype, fixed)
                    bonds.append(bond)
                    bond._line = remainder
                    bond.index = index
                    bond.atoms = [atom1, atom2]
                    try:
                        bond.stereo = BOND_LOOKUP_STEREO[bondtype-1][stereo]
                    except KeyError:
                        raise MolReaderError("An SD record cannot have a bondtype of %s and a stereo value of %s"%(bondtype, stereo))
                    except IndexError:
                        print "*"*44
                        print line
                        print "bondtype, stereo", bondtype, stero
                        raise
                        
                    atom1.bonds.append(bond)
                    atom2.bonds.append(bond)
                    atom1.oatoms.append(atom2)
                    atom2.oatoms.append(atom1)
                    if atom1.symbol == "H": atom2.explicit_hcount += 1
                    if atom2.symbol == "H": atom1.explicit_hcount += 1
                else:
                    if atom1 is None and atom2 is not None:
                        atom2.explicit_hcount += 1
                    elif atom2 is None and atom1 is not None:
                        atom1.explicit_hcount += 1
                        
            ##############################################################
            # read the mprops if necessary
            line = lines.next().strip()
            while 1:
                if line and line[0:6] == "M  END":
                    line = lines.next().strip()
                    break
                elif line == "M  CHG":
                    groups = line[6:].split()[1:]
                    index = 0
                    while index < len(groups):
                        atomIndex = int(groups[index]) - 1
                        atom = self.atoms[atomIndex]
                        charge = int(groups[index+1])
                        self.atoms[atomIndex].charge = charge
                        index += 2
                    line = lines.next().strip()
                elif line and line[0] == ">":
                    break
                elif line[0:4] == "$$$$":
                    break
                line = lines.next().strip()
                # What about end of mol?

            #############################################################
            # read the fields if necessary
            
            while line != "$$$$":
                if line and line[0] == ">":
                    res = FIELDPATTERN.match(line)
                    if res: field, potentialID = res.groups()
                    else:
                        res = ALTFIELDPATTERN.match(line)
                        if res:
                            field = res.groups()[0]
                            potentialID = None
                        else:
                            field, potentialID = None, None
                            
                    if name is None: name = potentialID

                    if field:
                        data = []
                        line = lines.next().strip()
                        while line and line != "$$$$":
                            data.append(line)
                            line = lines.next().strip()
                            
                        fields[field] = os.linesep.join(data)
                    
                line = lines.next().strip()
            mol = Molecule(_atoms, bonds)
            mol.name = name
            mol.fields = fields
            mol.name = name
            yield mol, lines.dump(), None
            
        except StopIteration:
            break
        except Exception:
            line = lines.current.strip()
            
            while line[0:4] != "$$$$":
                line = lines.next().strip()                
                
            stdout, stderr = sys.stdout, sys.stderr
            sys.stdout = sys.stderr = io = StringIO()
            traceback.print_exc()
            sys.stdout = stdout
            sys.stderr = stderr
            yield None, lines.dump(), io.getvalue()