def append(self, restraint): # pylint: disable=W0221 'Add a restraint to list.' restraint.id = self.currentId restraint.parent = self # being able to go from restraint to restraint list is important. NTlist.append(self, restraint) self._idDict[restraint.id] = restraint self.currentId += 1
def append(self, item): # pylint: disable=W0221 'Append' # if not hasattr(self, 'currentId'): # for deepcopy # self.currentId = 0 item.id = self.currentId item.parent = self # being able to go from restraint to restraint list is important. NTlist.append(self, item) self._idDict[item.id] = item self.currentId += 1
def getColumn(self, columnIndex): """Get a column (trivial!) Return None on error """ if columnIndex < 0 or columnIndex > self.colSize: return None result = NTlist() for row in self: result.append(row[columnIndex]) return result
def getColumn( self, columnIndex ): """Get a column (trivial!) Return None on error """ if columnIndex < 0 or columnIndex > self.colSize: return None result = NTlist() for row in self: result.append( row[columnIndex] ) return result
def residuesWithProperties(self, *properties): """ Return a NTlist instance with residueDefs that have properties """ result = NTlist() if self.hasProperties(*properties): result.append(self) # end if return result
def column( self, cName ): """Return list of values of column cName or None on error """ if cName not in self: return None col = NTlist() for row in self: col.append( row[cName] ) #end for return col
def atomsWithProperties(self, *properties): """ Return a NTlist instance with self if it has properties """ result = NTlist() if len(properties) == 0: return result if self.hasProperties(*properties): result.append(self) # end if return result
def getDiagonal(self): """ Get the diagonal of a square NTlistOfLists return NTlist instance or None on error """ if self.rowSize != self.colSize: nTerror('NTlistOflists.getDiagonal: unequal number of rows (%d) and collumns (%d)', self.rowSize, self.colSize) return None result = NTlist() for i in range(self.rowSize): result.append(self[i][i]) #end for return result
def average(atm): """Average value of atom with those of assigned neighbors""" if atm.has_key('deltaAverage'): del(atm['deltaAverage']) values = NTlist() for a in [atm] + atm.topology(): if 'delta' in a and not fpconst.isNaN(a['delta']): #print '>>', a, a.delta values.append(a.delta) #end if #end for #print '>>', atm, values if len(values) > 0: atm.deltaAverage, sd, n = values.average()
def residuesWithProperties(self, *properties): """ Return a NTlist instance with residueDefs that have properties """ result = NTlist() if len(properties) == 0: return result for residue in self.residues: if residue.hasProperties(*properties): result.append(residue) # end if # end for return result
def atomsWithProperties(self, *properties): """ Return a NTlist instance with atomDefs that have properties """ result = NTlist() if len(properties) == 0: return result for atm in self.allAtomDefs(): if atm.hasProperties(*properties): result.append(atm) # end if # end for return result
def atomsWithProperties(self, *properties): """ Return a NTlist instance with atomDefs that have All properties """ result = NTlist() if not len(properties): return result for atm in self.subNodes(depth=1): if atm.hasProperties(*properties): result.append(atm) # end if # end for return result
def getDiagonal(self): """ Get the diagonal of a square NTlistOfLists return NTlist instance or None on error """ if self.rowSize != self.colSize: nTerror( 'NTlistOflists.getDiagonal: unequal number of rows (%d) and collumns (%d)', self.rowSize, self.colSize) return None result = NTlist() for i in range(self.rowSize): result.append(self[i][i]) #end for return result
def calibrateShifts(project): """ Idea: use dCa, dCb dCa: H: +3.5 S: -1.5 (centre: 1.0, spread 5.0 ppm) dCb: S: +3.0 H: -0.5 (centre: 1.25 spread 3.5 ppm) 0.7(dCa-1.0) + (dCb-1.25) should be zero 0.7dCa + dCb - 1.95 should be zero """ diffs = NTlist() for res in project.molecule.allResidues(): if 'CA' in res and res.CA.isAssigned() and \ 'CB' in res and res.CB.isAssigned(): dCa = res.CA.shift() - res.CA.db.shift.average dCb = res.CB.shift() - res.CB.db.shift.average diff = 0.7*dCa+dCb-1.95 diffs.append(diff) #end for return diffs
def to3StateDssp(strNTList): """Personal communications JFD with Rob Hooft and Gert Vriend. 3, H -> H B, E -> S space, S, G, T -> coil (represented by ' ') See namesake method in procheck class. """ result = NTlist() for c in strNTList: n = DSSP_C if c == '3' or c == 'H': n = DSSP_H # end if elif c == 'B' or c == 'E': n = DSSP_S # end if result.append(n) return result
def to3StateDssp( strNTList ): """Personal communications JFD with Rob Hooft and Gert Vriend. 3, H -> H B, E -> S space, S, G, T -> coil (represented by ' ') See namesake method in procheck class. """ result = NTlist() for c in strNTList: n = DSSP_C if c == '3' or c == 'H': n = DSSP_H # end if elif c == 'B' or c == 'E': n = DSSP_S # end if result.append( n ) return result
def generatePDBfiles( projects ): # Get the closestToMean models, superpose, export to PDB file closestToMean = NTlist() for p in projects.entries[0:3]: cl = p.molecule.rmsd.closestToMean #print p.molecule.ensemble[cl].format() closestToMean.append( p.molecule.ensemble[cl] ) for m in closestToMean[1:]: #print m.format() _r = m.superpose(closestToMean[0]) #print '>', m.format() #print '>', r # Export for p in projects: cl = p.molecule.rmsd.closestToMean #print 'saving model>', p.molecule.ensemble[cl].format() p.molecule.toPDB( projects.path(p.name+'.pdb'), model=cl) return closestToMean
def calculatePairWisePhiPsiRmsd( mol1, mol2, ranges='auto' ): """ Calculate a pairwise angular Phi,Psi rmsd between the models of mol1 and mol2 return result NTlistOfLists, pairwise1, pairwise2, pairwise12 tuple """ fitResidues1 = mol1.setResiduesFromRanges(ranges) models1 = PhiPsiLists( mol1, fitResidues1 ) fitResidues2 = mol2.setResiduesFromRanges(ranges) models2 = PhiPsiLists( mol2, fitResidues2 ) #print '>', ranges, models1, models2 l1 = len(models1) l2 = len(models2) if l1 == 0 or len(models1[0]) == 0 or l2 == 0 or len(models2[0]) == 0: nTdebug(">calculatePairWisePhiPsiRmsd> returning None, %s %s %s", l1, l2, ranges) return None, None, None, None models = models1 + models2 result = NTlistOfLists(len(models), len(models), 0.0) #nTmessage( '==> Calculating dihedral pairwise rmsds' ) for i in range(len(models)): for j in range(i+1, len(models)): #print '>>', i,j r = models[i].calculateRMSD( models[j] ) if r == None: nTdebug('calculatePairWisePhiPsiRmsd: error for %s and %s', models[i], models[j]) return None, None, None, None else: result[i][j] = r result[j][i] = r #end for #end for pairwise1 = NTlist() for i in range(l1): for j in range(i+1, l1): pairwise1.append(result[i][j]) # print '1>', i,j pairwise2 = NTlist() for i in range(l1, l1+l2): for j in range(i+1, l1+l2): pairwise2.append(result[i][j]) # print '2>', i,j pairwise12 = NTlist() for i in range(l1): for j in range(l1, l1+l2): pairwise12.append(result[i][j]) # print '12>', i,j # print len(pairwise1), len(pairwise2), len(pairwise12) return ( result, pairwise1.average2(fmt='%6.2f +- %5.2f'),pairwise2.average2(fmt='%6.2f +- %5.2f'), pairwise12.average2(fmt='%6.2f +- %5.2f') )
def calculatePairWiseRmsd( mol1, mol2, ranges=None ): """Calculate pairwise rmsd between mol1 and mol2 Optionally use ranges for the fitting """ #Use ranges routines to define fitAtoms ed fitResidues1 = mol1.setResiduesFromRanges(ranges) mol1.selectFitAtoms( fitResidues1, backboneOnly=True, includeProtons = False ) fitResidues2 = mol2.setResiduesFromRanges(ranges) mol2.selectFitAtoms( fitResidues2, backboneOnly=True, includeProtons = False ) # mol2.superpose( ranges ) l1 = len(mol1.ensemble) l2 = len(mol2.ensemble) if ( l1 == 0 or len(mol1.ensemble[0].fitCoordinates) == 0 or l2 == 0 or len(mol2.ensemble[0].fitCoordinates) == 0 or len(mol1.ensemble[0].fitCoordinates) != len(mol2.ensemble[0].fitCoordinates) ): nTdebug( ">calculatePairWiseRmsd> returning None, %s %s %s" , l1, l2, ranges) return None, None, None, None models = mol1.ensemble + mol2.ensemble result = NTlistOfLists(len(models), len(models), 0.0) nTmessage('==> Calculating pairwise rmsds %s %s', mol1, mol2) for i in range(len(models)): for j in range(i+1, len(models)): result[i][j] = models[i].superpose( models[j] ) result[j][i] = result[i][j] #end for #end for pairwise1 = NTlist() for i in range(l1): for j in range(i+1, l1): pairwise1.append(result[i][j]) # print '1>', i,j pairwise2 = NTlist() for i in range(l1, l1+l2): for j in range(i+1, l1+l2): pairwise2.append(result[i][j]) # print '2>', i,j pairwise12 = NTlist() for i in range(l1): for j in range(l1, l1+l2): pairwise12.append(result[i][j]) # print '12>', i,j # print len(pairwise1), len(pairwise2), len(pairwise12) return ( result, pairwise1.average2(fmt='%6.2f +- %5.2f'),pairwise2.average2(fmt='%6.2f +- %5.2f'), pairwise12.average2(fmt='%6.2f +- %5.2f'))
def to3StatePC( strNTList ): """Exactly the same as Procheck postscript plots was attempted. S,B,h,e,t, ,None--> space character E --> S H G --> H Note that CING and Procheck_NMR does not draw an 'h' to a H and e to S. Procheck description: The secondary structure plot shows a schematic representation of the Kabsch & Sander (1983) secondary structure assignments. The key just below the picture shows which structure is which. Beta strands are taken to include all residues with a Kabsch & Sander assignment of E, helices corresponds to both H and G assignments, while everything else is taken to be random coil. PyMOL description: With PyMOL, heavy emphasis is placed on cartoon aesthetics, and so both hydrogen bonding patterns and backbone geometry are used in the assignment process. Depending upon the local context, helix and strand assignments are made based on geometry, hydrogen bonding, or both. This command will generate results which differ slightly from DSSP and other programs. Most deviations occur in borderline or transition regions. Generally speaking, PyMOL is more strict, thus assigning fewer helix/sheet residues, except for partially distorted helices, which PyMOL tends to tolerate. """ result = NTlist() for c in strNTList: if c == 'E': n = 'S' elif c == 'H' or c == 'G': n = 'H' else: n = ' ' result.append( n ) return result
def getRanges( projects, cutoff = 1.7 ): """ Get the ranges from phi, phi order parameters using all members of projects As suggested by Aleandre in CASD-NMR meeting """ resList1 = NTlist() resList2 = NTlist() for res in projects.entries[0].molecule.allResidues(): phi = NTlist() # list for all phi values psi = NTlist() # list for all psi values #print '>>>', res if res.has_key('PHI') and res.has_key('PSI'): for p in projects: if projects.moleculeMap.has_key(res) and projects.moleculeMap[res].has_key((p.name, p.molecule.name)): currentRes = projects.moleculeMap[res][(p.name, p.molecule.name)] #print p,currentRes if currentRes.has_key('PHI'): phi.append(*currentRes['PHI']) if currentRes.has_key('PSI'): psi.append(*currentRes['PSI']) #end if #end for phi.cAverage() psi.cAverage() use1 = 0 if (2.0 - res.PHI.cv - res.PSI.cv > cutoff): use1 = 1 use2 = 0 if (2.0 - phi.cv - psi.cv > cutoff): use2 = 1 #printf('%-35s %-35s %6.2f %1d %6.2f %6.2f %6.2f %1d %2d\n', # res.PHI, res.PSI, 2.0 - res.PHI.cv - res.PSI.cv, use1, # phi.cv, psi.cv, 2.0 - phi.cv - psi.cv, use2, use1-use2 # ) if use1: resList1.append(res.resNum) if use2: resList2.append(res.resNum) #end if #end for return list2asci(resList1), list2asci(resList2)
def calcQshift(project): """Calculate per residue Q factors between assignment and shiftx results """ if project is None: nTmessage("calcQshift: no project defined") return None # end if if not project.molecule: nTmessage("calcQshift: no molecule defined") return None # end if nTdetail("==> Calculating Q-factors for chemical shift") for res in project.molecule.allResidues(): atms = res.allAtoms() bb = NTlist() heavy = NTlist() protons = NTlist() for a in atms: if a.isBackbone(): bb.append(a) if a.isProton(): protons.append(a) else: heavy.append(a) # end for result = project.validationData.getResult(res, constants.SHIFTX_KEY, QshiftxResult()) if result is None: nTmessage("calcQshift: error setting QshiftResult for residue %s", res) return None # end if result[QshiftxResult.ALL_ATOMS] = _calcQshift(project, atms) result[QshiftxResult.BACKBONE] = _calcQshift(project, bb) result[QshiftxResult.HEAVY_ATOMS] = _calcQshift(project, heavy) result[QshiftxResult.PROTONS] = _calcQshift(project, protons) # LEGACY qshiftDict = legacyQshiftDict() for k in [QshiftxResult.ALL_ATOMS, QshiftxResult.BACKBONE, QshiftxResult.HEAVY_ATOMS, QshiftxResult.PROTONS]: qshiftDict[k] = result[k] qshiftDict["residue"] = res res.Qshift = qshiftDict
class NmrPipeTable( NTdict ): """ NmrPipeTable class implemented as NTdict of NTdict's, i.e. element (row-0, INDEX) indexed as tab[0].INDEX or tab[0]['INDEX'] tab = NmrPipeTable() # Empty table tab = NmrPipeTable( 'tabFile' ) # table from tabFile METHODS: addColumn( name, fmt = "%s", default=None ): Add column 'name' to table; set values to 'default' hideColumn( *cNames ) Hide column(s) cNames showColumn( *cNames ) Show columns cNames addRow( **kwds ): Add row to table, optional kwds can be used to set values readFile( tabFile ): Read table from tabFile write( stream=sys.stdout ): Write table to stream writeFile( tabFile) : Open tabFile, write table and close tabFile """ def __init__( self, tabFile=None, **kwds ): NTdict.__init__( self, __CLASS__ = 'nmrPipeTab', **kwds ) self.setdefault('noneIndicator', '-') # character to identify the None value self.columnDefs = NTlist() # list of column definitions, implemented # as NTdict self.rows = NTlist() self.nrows = 0 self.remarks = NTlist() self.data = NTdict() self.tabFile = tabFile if tabFile: self.readFile( tabFile ) #end if #end def def format(self): # pylint: disable=W0221 return sprintf( '''=== NmrPipeTable "%s" === columns: %s nrows: %d''', self.tabFile, self.columnDefs.zap('name'), self.nrows ) def addRow( self, **kwds ): """ Add row to table, optional kwds can be used to set values """ row = NmrPipeTabRow( table=self, id=self.nrows, **kwds ) self[ self.nrows ] = row self.rows.append( row ) self.nrows += 1 return row #end def def addColumn( self, name, fmt = "%s", default=None ): """ Add column 'name' to table; set values to 'default' return columnDef, or None on error """ if name in self: nTerror('NmrPipeTable.addColumn: column "%s" already exists\n', name ) return None #end if col = NTdict( name=name, fmt=fmt, id=len(self.columnDefs), hide=False, __FORMAT__ = '%(name)s' ) self.columnDefs.append( col ) self[name] = col for row in self: row[name] = default #end for return col #end def def column( self, cName ): """Return list of values of column cName or None on error """ if cName not in self: return None col = NTlist() for row in self: col.append( row[cName] ) #end for return col #end def def hideColumn( self, *cNames ): """ Hide column(s) cNames """ for c in cNames: if not c in self: nTerror('NmrPipeTable.hideColumn: column "%s" not defined\n', c) else: self[c].hide = True #end if #end for #end def def showColumn( self, *cNames ): """ Show column(s) cNames """ for c in cNames: if not c in self: nTerror('NmrPipeTable.showColumn: column "%s" not defined\n', c) else: self[c].hide = False #end if #end for #end def def readFile( self, tabFile ): """ Read table from tabFile """ # nTmessage('Reading nmrPipe table file %s', tabFile ) #end if for line in AwkLike( tabFile, minNF = 1, commentString = '#' ): if ( line.dollar[1] == 'REMARK' and line.NF > 1 ): self.remarks.append( line.dollar[2:] ) elif ( line.dollar[1] == 'VARS' ): for v in line.dollar[2:]: self.addColumn( name=v ) #end for elif ( line.dollar[1] == 'FORMAT' ): i = 0 for f in line.dollar[2:]: self.columnDefs[i].fmt=f i += 1 #end for elif ( line.dollar[1] == 'DATA' and line.NF > 3 ): self.data[line.dollar[2]] = line.dollar[3:] elif ( line.NF == len( self.columnDefs ) ): row = self.addRow() for i in range( 0, line.NF ): col = self.columnDefs[i] if (line.dollar[i+1] == self.noneIndicator): row[col.name] = None else: # derive conversion function from fmt field if (col.fmt[-1:] in ['f','e','E','g','G']): func = float elif (col.fmt[-1:] in ['d','o','x','X']): func = int else: func = str #end if row[ col.name ] = func( line.dollar[i+1] ) #endif #end for else: pass #end if #end for self.tabFile = tabFile #end def def write( self, stream=sys.stdout): """ Write tab to stream """ for r in self.remarks: fprintf( stream, 'REMARK %s\n', r ) #end for fprintf( stream, '\n' ) for d,v in self.data.iteritems(): fprintf( stream, 'DATA %s %s\n', d, v ) # Note: only ONE space between DATA and identifier!!! #end for fprintf( stream, '\n' ) fprintf( stream, 'VARS ' ) for c in self.columnDefs: if not c.hide: fprintf( stream, '%s ', c.name ) #end for fprintf( stream, '\n' ) fprintf( stream, 'FORMAT ' ) for c in self.columnDefs: if not c.hide: fprintf( stream, '%s ', c.fmt ) #end for fprintf( stream, '\n' ) fprintf( stream, '\n' ) for row in self: fprintf( stream, '%s\n', row ) #end for #end def def writeFile( self, tabFile) : """ Write table to tabFile. Return True on error """ fp = open( tabFile, 'w' ) if fp is None: nTerror('NmrPipeTable.writeFile: error opening "%s"', tabFile) return True self.write( fp ) fp.close() # nTdebug('==> Written nmrPipe table file "%s"', tabFile ) return False #end def #iteration overrides: loop over row indices or rows def keys( self ): return range( 0, self.nrows ) #end def def __iter__( self ): for row in self.rows: yield row
class ROGscore(NTdict): """ Red orange green with comments. """ ROG_COMMENT_NO_COOR = 'No coordinates' ROG_COMMENT_POOR_ASSIGNMENT = 'Poor assignment' MAX_TO_REPORT_IN_POPUP = 5 mapColorString2Int = {constants.COLOR_GREEN: 0, constants.COLOR_ORANGE : 1, constants.COLOR_RED : 2} mapColorInt2String2 = {0:constants.COLOR_GREEN, 1:constants.COLOR_ORANGE, 2: constants.COLOR_RED} def __init__(self): NTdict.__init__(self, __CLASS__ = 'ROGscore', __FORMAT__ = "ROGscore '%(colorLabel)s' %(colorCommentList)s" ) # Explicitly showing instance attributes here in init. self.colorLabel = constants.COLOR_GREEN # Elements in this list are tuples of (color, comment). self.colorCommentList = NTlist() def __str__(self): # return str(self.colorLabel) return self.colorLabel def reset(self): self.colorLabel = constants.COLOR_GREEN self.colorCommentList = NTlist() def isCritiqued(self): if self.colorLabel != constants.COLOR_GREEN: return True else: return False def rogInt(self): """Integer value for fast lookup in db""" return self.mapColorString2Int[ self.colorLabel ] def rogString(self): """String value for easy lookup in db""" return self.colorLabel def isRed(self): return self.colorLabel == constants.COLOR_RED def isOrange(self): return self.colorLabel == constants.COLOR_ORANGE # Thanks to a tip from http://morecavalier.com/index.php?whom=Articles%2FMultiline+TITLES+for+Firefox # Can be aligned to left using a better .css. def addHTMLkeywords(self, kw): pass ##GWV 20 August: problem with this in tables and links # if not self.isCritiqued(): # return # if self.colorCommentList: # ln = len( self.colorCommentList ) # subList = self.colorCommentList # if ln > self.MAX_TO_REPORT_IN_POPUP: # subList = self.colorCommentList[:self.MAX_TO_REPORT_IN_POPUP] # kw[ 'cavtitle' ] = '\n'.join( subList ) # if ln > self.MAX_TO_REPORT_IN_POPUP: # kw[ 'cavtitle' ] += '\nand so on for %d comments in total' % ln # kw[ 'onmousemove' ] = 'SetCavTimer(event);' # kw[ 'onmouseout' ] = "CancelCavTimer(event);" def createHtmlForComments(self, dst): if not self.isCritiqued(): return refExists = False if refExists: dst('ul' , closeTag=False) for color,comment in self.colorCommentList: kw = {'href':''} kw['class'] = color dst('li' , closeTag=False) dst('a' , comment, **kw) dst('li' , openTag=False) dst('ul', openTag=False) else: dst('ul', closeTag=False) for color,comment in self.colorCommentList: kw = {'color':color} dst('li' , closeTag=False) dst('font' , comment, **kw) dst('li' , openTag=False) dst('ul', openTag=False) def createHtmlColorForString(self, dst, str): """ Add the given str to the destination in a color reflecting the rog score. Because the text needs to be encapsulated in a tag; the italics def is always used. """ kw = {'style': 'font-style: italic'} if self.isCritiqued(): color = constants.COLOR_ORANGE if self.isRed(): color = constants.COLOR_RED kw['color'] = color dst('font' , str, **kw) def setMaxColor(self, colorLabel, comment=None): """priority: red, orange, green. The so called ROG score. The comment is optional and will only be appended when the color label is at least as severe as the current one. The less severe levels of comments used to be wiped out but not any more; see issue 153. Only ORANGE and RED levels can add comments. Parameter comment may also be a list of comments. """ # if not o.has_key( 'colorLabel' ):# NTlist doesn't have 'has_key'. # if not hasattr(o,'colorLabel'): # o.colorLabel = COLOR_GREEN if colorLabel == constants.COLOR_GREEN: return # certain to stay at or upgrade to given color. if colorLabel == constants.COLOR_RED or (colorLabel == constants.COLOR_ORANGE and self.colorLabel != constants.COLOR_RED): self.colorLabel = colorLabel if not comment: return if isinstance(comment, list): for commentSingle in comment: commentTuple = (colorLabel, commentSingle ) self.colorCommentList.append( commentTuple )# grow list with potentially multiple comments. else: commentTuple = (colorLabel, comment ) self.colorCommentList.append(commentTuple) self.colorCommentList.removeDuplicates() # Keep comments for red and orange together. NTsort( self.colorCommentList, 0, inplace=True) #end def def getColorCommentText(self): resultTxtList = [] for element in self.colorCommentList: resultTxtList.append(repr(element)) return '\n'.join(resultTxtList)
def patchProperties(self): """Patch the properties list """ props = NTlist( self.name, self.residueDef.name, self.residueDef.commonName, self.residueDef.shortName, self.spinType, *self.properties ) # Append these defs so we will always have them. If they were already present, they will be removed again below. if isProton(self): props.append("isProton", "proton") else: props.append("isNotProton", "notproton") # end if if isCarbon(self): props.append("isCarbon", "carbon") else: props.append("isNotCarbon", "notcarbon") # end if if isNitrogen(self): props.append("isNitrogen", "nitrogen") else: props.append("isNotNitrogen", "notnitrogen") # end if if isSulfur(self): props.append("isSulfur", "isSulphur", "sulfur", "sulphur") else: props.append("isNotSulfur", "isNotSulphur", "notsulfur", "notsulphur") # end if if isBackbone(self): props.append("isBackbone", "backbone") else: props.append("isSidechain", "sidechain") # endif if isAromatic(self): props.append("isAromatic", "aromatic") else: props.append("isNotAromatic", "notaromatic") # end if if isMethyl(self): props.append("isMethyl", "methyl") else: props.append("isNotMethyl", "notmethyl") # end if if isMethylProton(self): props.append("isMethylProton", "methylproton") else: props.append("isNotMethylProton", "notmethylproton") # end if if isMethylene(self): props.append("isMethylene", "methylene") else: props.append("isNotMethylene", "notmethylene") # end if if isMethyleneProton(self): props.append("isMethyleneProton", "methyleneproton") else: props.append("isNotMethyleneProton", "notmethyleneproton") # end if if isPseudoAtom(self): props.append("isPseudoAtom", "pseudoatom") else: props.append("isNotPseudoAtom", "notpseudoatom") # end if if hasPseudoAtom(self): props.append("hasPseudoAtom", "haspseudoatom") else: props.append("hasNoPseudoAtom", "hasnopseudoatom") # end if # Remove the duplicates; copy is much quicker then in-place props.removeDuplicates() props2 = [] for prop in props: if not prop in props2: props2.append(prop) # end if # end for self.properties = props2
def append( self, *dihedrals ): c = CircularVector( *dihedrals ) NTlist.append(self, c)