/* abstree.c * RasMol2 Molecular Graphics * Roger Sayle, August 1995 * Version 2.6 */ #include "rasmol.h" #ifdef IBMPC #include #endif #ifndef sun386 #include #endif #include #include #include #include #define ABSTREE #include "molecule.h" #include "abstree.h" #define ExprPool 16 #define SetPool 4 typedef struct _SymEntry { struct _SymEntry __far *lft; struct _SymEntry __far *rgt; AtomSet __far *defn; char *ident; } SymEntry; static SymEntry __far *SymbolTable; static SymEntry __far *FreeEntry; static AtomSet __far *FreeSet; static Expr *FreeExpr; static Expr FalseExpr; static Expr TrueExpr; /* Macros for commonly used loops */ #define ForEachAtom for(chain=Database->clist;chain;chain=chain->cnext) \ for(group=chain->glist;group;group=group->gnext) \ for(aptr=group->alist;aptr;aptr=aptr->anext) #define BitAcidic 0x001 #define BitAliphatic 0x002 #define BitAromatic 0x004 #define BitBasic 0x008 #define BitBuried 0x010 #define BitCyclic 0x020 #define BitHydrophobic 0x040 #define BitMedium 0x080 #define BitNeutral 0x100 #define BitSmall 0x200 #define BitCharged 0x009 #define BitNotLarge 0x280 /* Acyclic = !Cyclic */ /* Large = !Medium && !Small */ /* Polar = !Hydrophobic */ /* Surface = !Buried */ #define AminoCodeMax 28 static char *AminoCode = "AGLSVTKDINEPRFQYHCMWBZPPACGTX"; static int AminoProp[] = { /*ALA*/ BitAliphatic | BitBuried | BitHydrophobic | BitNeutral | BitSmall, /*GLY*/ BitAliphatic | BitHydrophobic | BitNeutral | BitSmall, /*LEU*/ BitAliphatic | BitBuried | BitHydrophobic | BitNeutral, /*SER*/ BitNeutral | BitSmall, /*VAL*/ BitAliphatic | BitBuried | BitHydrophobic | BitMedium | BitNeutral, /*THR*/ BitMedium | BitNeutral, /*LYS*/ BitBasic, /*ASP*/ BitAcidic | BitMedium, /*ILE*/ BitAliphatic | BitBuried | BitHydrophobic | BitNeutral, /*ASN*/ BitMedium | BitNeutral, /*GLU*/ BitAcidic, /*PRO*/ BitCyclic | BitHydrophobic | BitMedium | BitNeutral, /*ARG*/ BitBasic, /*PHE*/ BitAromatic | BitBuried | BitCyclic | BitHydrophobic | BitNeutral, /*GLN*/ BitNeutral, /*TYR*/ BitAromatic | BitCyclic | BitNeutral, /*HIS*/ BitAromatic | BitBasic | BitCyclic | BitNeutral, /*CYS*/ BitBuried | BitMedium | BitNeutral, /*MET*/ BitBuried | BitHydrophobic | BitNeutral, /*TRP*/ BitAromatic | BitBuried | BitCyclic | BitHydrophobic | BitNeutral, /*ASX*/ BitMedium | BitNeutral, /*GLX*/ BitNeutral, /*PCA*/ BitCyclic | BitHydrophobic | BitMedium | BitNeutral, /*HYP*/ BitCyclic | BitMedium | BitNeutral }; static void FatalExprError(ptr) char *ptr; { char buffer[80]; sprintf(buffer,"Expression Error: %s!",ptr); RasMolFatalExit(buffer); } #ifdef FUNCPROTO /* Function Prototypes */ static AtomSet __far *SetInsert( AtomSet __far*, Atom __far* ); static int IsWithinRadius( AtomSet __far*, Long ); static int IsSetMember( AtomSet __far* ); #endif static AtomSet __far *SetInsert( ptr, item ) AtomSet __far *ptr; Atom __far *item; { register AtomSet __far *temp; register int i; if( ptr && (ptr->countdata[ptr->count] = item; ptr->count++; return( ptr ); } if( !FreeSet ) { temp = (AtomSet __far*)_fmalloc( SetPool*sizeof(AtomSet) ); if( !temp ) FatalExprError("Memory allocation failed"); for( i=1; inext = FreeSet; FreeSet = temp++; } } else { temp = FreeSet; FreeSet = temp->next; } temp->data[0] = item; temp->next = ptr; temp->count = 1; return( temp ); } static int IsWithinRadius( ptr, limit ) AtomSet __far *ptr; Long limit; { register Atom __far *aptr; register Long dx,dy,dz; register Long dist; register int i; while( ptr ) { for( i=0; icount; i++ ) { aptr = ptr->data[i]; dx = QAtom->xorg-aptr->xorg; if( (dist=dx*dx)>limit ) continue; dy = QAtom->yorg-aptr->yorg; if( (dist+=dy*dy)>limit ) continue; dz = QAtom->zorg-aptr->zorg; if( (dist+=dz*dz)>limit ) continue; return( True ); } ptr = ptr->next; } return( False ); } static int IsSetMember( ptr ) AtomSet __far *ptr; { register int i; while( ptr ) { for( i=0; icount; i++ ) if( ptr->data[i] == QAtom ) return( True ); ptr = ptr->next; } return( False ); } void DeleteAtomSet( ptr ) AtomSet __far *ptr; { register AtomSet __far *temp; if( ptr ) { temp = ptr; while( temp->next ) temp = temp->next; temp->next = FreeSet; FreeSet = ptr; } } Expr *AllocateNode() { register Expr *ptr; register int i; if( !FreeExpr ) { ptr = (Expr*)malloc( ExprPool*sizeof(Expr) ); if( !ptr ) FatalExprError("Memory allocation failed"); for( i=1; irgt.ptr = FreeExpr; FreeExpr = ptr++; } } else { ptr = FreeExpr; FreeExpr = ptr->rgt.ptr; } ptr->rgt.ptr = NULL; ptr->lft.ptr = NULL; return( ptr ); } void DeAllocateExpr( expr ) Expr *expr; { if( !expr ) return; if( (expr == &FalseExpr) || (expr == &TrueExpr) ) return; if( expr->type!=OpWithin ) { if( !(expr->type&(OpLftProp|OpLftVal)) ) DeAllocateExpr( expr->lft.ptr ); if( !(expr->type&(OpRgtProp|OpRgtVal)) ) DeAllocateExpr( expr->rgt.ptr ); } else DeleteAtomSet( expr->rgt.set ); expr->rgt.ptr = FreeExpr; FreeExpr = expr; } int GetElemNumber( group, aptr ) Group __far *group; Atom __far *aptr; { register char ch1,ch2; register char *ptr; ptr = ElemDesc[aptr->refno]; if( IsNADGroup(group->refno) || IsCOAGroup(group->refno) ) { /* Exceptions to Brookhaven Atom Naming! */ ch1 = ' '; } else { ch1 = ptr[0]; /* Handle HG, HD etc.. in Amino Acids! */ if( (ch1=='H') && IsProtein(group->refno) ) return( 1 ); } ch2 = ptr[1]; switch( ch1 ) { case(' '): switch( ch2 ) { case('B'): return( 5 ); case('C'): return( 6 ); case('D'): return( 1 ); case('F'): return( 9 ); case('H'): return( 1 ); case('I'): return( 53 ); case('K'): return( 19 ); case('L'): return( 1 ); case('N'): return( 7 ); case('O'): return( 8 ); case('P'): return( 15 ); case('S'): return( 16 ); case('U'): return( 92 ); case('V'): return( 23 ); case('W'): return( 74 ); case('Y'): return( 39 ); } break; case('A'): switch( ch2 ) { case('C'): return( 89 ); case('G'): return( 47 ); case('L'): return( 13 ); case('M'): return( 95 ); case('R'): return( 18 ); case('S'): return( 33 ); case('T'): return( 85 ); case('U'): return( 79 ); } break; case('B'): switch( ch2 ) { case('A'): return( 56 ); case('E'): return( 4 ); case('I'): return( 83 ); case('K'): return( 97 ); case('R'): return( 35 ); } break; case('C'): switch( ch2 ) { case('A'): return( 20 ); case('D'): return( 48 ); case('E'): return( 58 ); case('F'): return( 98 ); case('L'): return( 17 ); case('M'): return( 96 ); case('O'): return( 27 ); case('R'): return( 24 ); case('S'): return( 55 ); case('U'): return( 29 ); } break; case('D'): if( ch2=='Y' ) return( 66 ); break; case('E'): if( ch2=='R' ) { return( 68 ); } else if( ch2=='S' ) { return( 99 ); } else if( ch2=='U' ) return( 63 ); break; case('F'): if( ch2=='E' ) { return( 26 ); } else if( ch2=='M' ) { return( 100 ); } else if( ch2=='R' ) return( 87 ); break; case('G'): if( ch2=='A' ) { return( 31 ); } else if( ch2=='D' ) { return( 64 ); } else if( ch2=='E' ) return( 32 ); break; case('H'): if( ch2=='E' ) { return( 2 ); } else if( ch2=='F' ) { return( 72 ); } else if( ch2=='G' ) { return( 80 ); } else if( ch2=='O' ) return( 67 ); break; case('I'): if( ch2=='N' ) { return( 49 ); } else if( ch2=='R' ) return( 77 ); break; case('K'): if( ch2=='R' ) return( 36 ); break; case('L'): if( ch2=='A' ) { return( 57 ); } else if( ch2=='I' ) { return( 3 ); } else if( (ch2=='R') || (ch2=='W') ) { return( 103 ); } else if( ch2=='U' ) return( 71 ); break; case('M'): if( ch2=='D' ) { return( 101 ); } else if( ch2=='G' ) { return( 12 ); } else if( ch2=='N' ) { return( 25 ); } else if( ch2=='O' ) return( 42 ); break; case('N'): switch( ch2 ) { case('A'): return( 11 ); case('B'): return( 41 ); case('D'): return( 60 ); case('E'): return( 10 ); case('I'): return( 28 ); case('O'): return( 102 ); case('P'): return( 93 ); } break; case('O'): if( ch2=='S' ) return( 76 ); break; case('P'): switch( ch2 ) { case('A'): return( 91 ); case('B'): return( 82 ); case('D'): return( 46 ); case('M'): return( 61 ); case('O'): return( 84 ); case('R'): return( 59 ); case('T'): return( 78 ); case('U'): return( 94 ); } break; case('R'): switch( ch2 ) { case('A'): return( 88 ); case('B'): return( 37 ); case('E'): return( 75 ); case('H'): return( 45 ); case('N'): return( 86 ); case('U'): return( 44 ); } break; case('S'): switch( ch2 ) { case('B'): return( 51 ); case('C'): return( 21 ); case('E'): return( 34 ); case('I'): return( 14 ); case('M'): return( 62 ); case('N'): return( 50 ); case('R'): return( 38 ); } break; case('T'): switch( ch2 ) { case('A'): return( 73 ); case('B'): return( 65 ); case('C'): return( 43 ); case('E'): return( 52 ); case('H'): return( 90 ); case('I'): return( 22 ); case('L'): return( 81 ); case('M'): return( 69 ); } break; case('X'): if( ch2=='E' ) return( 54 ); break; case('Y'): if( ch2=='B' ) return( 70 ); break; case('Z'): if( ch2=='N' ) { return( 30 ); } else if( ch2=='R' ) return( 40 ); break; } if( (ch1>='0') && (ch1<='9') ) if( (ch2=='H') || (ch2=='D') ) return( 1 ); /* Hydrogen */ return( 0 ); } int ElemVDWRadius( elem ) int elem; { if( !HasHydrogen ) switch( elem ) { case( 6 ): return( VDWCarbon ); case( 7 ): return( VDWNitrogen ); case( 8 ): return( VDWOxygen ); case( 16 ): return( VDWSulphur ); } return( Element[elem].vdwrad ); } static int EvaluateProperty( prop ) int prop; { switch( prop ) { case( PropIdent ): return( QAtom->serno ); case( PropXCord ): return( (int)QAtom->xorg ); case( PropYCord ): return( (int)QAtom->yorg ); case( PropZCord ): return( (int)QAtom->zorg ); case( PropTemp ): return( QAtom->temp ); case( PropName ): return( QAtom->refno ); case( PropResId ): return( QGroup->serno ); case( PropResName ): return( QGroup->refno ); case( PropChain ): return( QChain->ident ); case( PropSelect ): return( QAtom->flag&SelectFlag ); case( PropElemNo ): return( QAtom->elemno ); case( PropModel ): return( QChain->model ); case( PropRad ): if( QAtom->flag&SphereFlag ) { return( QAtom->radius ); } else return( 0 ); /* Predicates stored in flags */ case( PredBonded ): return( !(QAtom->flag&NonBondFlag) ); case( PredHydrogen ): return( QAtom->flag&HydrogenFlag ); case( PredHetero ): return( QAtom->flag&HeteroFlag ); case( PredCystine ): return( QGroup->flag&CystineFlag ); case( PredHelix ): return( QGroup->struc&HelixFlag ); case( PredSheet ): return( QGroup->struc&SheetFlag ); case( PredTurn ): return( QGroup->struc&TurnFlag ); /* Residue type predicates */ case( PredDNA ): return( IsDNA(QGroup->refno) ); case( PredRNA ): return( IsRNA(QGroup->refno) ); case( PredNucleic ): return( IsNucleo(QGroup->refno) ); case( PredProtein ): return( IsProtein(QGroup->refno) ); case( PredAmino ): return( IsAmino(QGroup->refno) ); case( PredWater ): return( IsWater(QGroup->refno) ); case( PredSolvent ): return( IsSolvent(QGroup->refno) ); case( PredIon ): return( IsIon(QGroup->refno) ); /* General Predicates */ case( PredAlpha ): return( IsAmino(QGroup->refno) && IsAlphaCarbon(QAtom->refno) ); case( PredMainChain ): return( (IsAmino(QGroup->refno) && IsAminoBackbone(QAtom->refno)) || (IsNucleo(QGroup->refno) && IsNucleicBackbone(QAtom->refno)) ); case( PredSidechain ): return( IsAmino(QGroup->refno) && !IsAminoBackbone(QAtom->refno) ); case( PredLigand ): return( (QAtom->flag&HeteroFlag) && !IsSolvent(QGroup->refno) ); /* Nucleic Acid Classifications */ case( PredAT ): return( IsAdenine(QGroup->refno) || IsThymine(QGroup->refno) ); case( PredCG ): return( IsCytosine(QGroup->refno) || IsGuanine(QGroup->refno) ); case( PredPyrimidine ): return( IsPyrimidine(QGroup->refno) ); case( PredPurine ): return( IsPurine(QGroup->refno) ); /* Amino Acid Classifications */ case( PredAcidic ): return( IsAmino(QGroup->refno) && AminoProp[QGroup->refno]&BitAcidic ); case( PredAcyclic ): return( IsAmino(QGroup->refno) && !(AminoProp[QGroup->refno]&BitCyclic) ); case( PredAliphatic ): return( IsAmino(QGroup->refno) && AminoProp[QGroup->refno]&BitAliphatic ); case( PredAromatic ): return( IsAmino(QGroup->refno) && AminoProp[QGroup->refno]&BitAromatic ); case( PredBasic ): return( IsAmino(QGroup->refno) && AminoProp[QGroup->refno]&BitBasic ); case( PredBuried ): return( IsAmino(QGroup->refno) && AminoProp[QGroup->refno]&BitBuried ); case( PredCharged ): return( IsAmino(QGroup->refno) && AminoProp[QGroup->refno]&BitCharged ); case( PredCyclic ): return( IsAmino(QGroup->refno) && AminoProp[QGroup->refno]&BitCyclic ); case( PredHydrophobic ): return( IsAmino(QGroup->refno) && AminoProp[QGroup->refno]&BitHydrophobic ); case( PredLarge ): return( IsAmino(QGroup->refno) && !(AminoProp[QGroup->refno]&BitNotLarge) ); case( PredMedium ): return( IsAmino(QGroup->refno) && AminoProp[QGroup->refno]&BitMedium ); case( PredNeutral ): return( IsAmino(QGroup->refno) && AminoProp[QGroup->refno]&BitNeutral ); case( PredPolar ): return( IsAmino(QGroup->refno) && !(AminoProp[QGroup->refno]&BitHydrophobic) ); case( PredSmall ): return( IsAmino(QGroup->refno) && AminoProp[QGroup->refno]&BitSmall ); case( PredSurface ): return( IsAmino(QGroup->refno) && !(AminoProp[QGroup->refno]&BitBuried) ); } return( True ); } int EvaluateExpr( expr ) Expr *expr; { register int lft, rgt; if( !expr ) return( True ); if( expr->type==OpWithin ) { if( expr->lft.limit ) { return( IsWithinRadius(expr->rgt.set,expr->lft.limit) ); } else return( IsSetMember(expr->rgt.set) ); } else if( expr->type==OpMember ) return( IsSetMember(expr->rgt.set) ); if( expr->type & OpLftVal ) { lft = expr->lft.val; } else if( expr->type & OpLftProp ) { lft = EvaluateProperty( expr->lft.val ); } else lft = EvaluateExpr( expr->lft.ptr ); if( OpCode(expr)==OpConst ) return( lft ); if( (OpCode(expr)==OpAnd) && !lft ) return( False ); if( (OpCode(expr)==OpOr) && lft ) return( True ); if( OpCode(expr)==OpNot ) return( !lft ); if( expr->type & OpRgtVal ) { rgt = expr->rgt.val; } else if( expr->type & OpRgtProp ) { rgt = EvaluateProperty( expr->rgt.val ); } else rgt = EvaluateExpr( expr->rgt.ptr ); switch( OpCode(expr) ) { case(OpOr): case(OpAnd): return( rgt ); case(OpLess): return( lftrgt ); case(OpEqual): return( lft==rgt ); case(OpNotEq): return( lft!=rgt ); case(OpLessEq): return( lft<=rgt ); case(OpMoreEq): return( lft>=rgt ); } return( True ); } AtomSet __far *BuildAtomSet( expr ) Expr *expr; { register AtomSet __far *ptr; ptr = (AtomSet __far*)0; if( Database ) for( QChain=Database->clist; QChain; QChain=QChain->cnext ) for( QGroup=QChain->glist; QGroup; QGroup=QGroup->gnext ) for( QAtom=QGroup->alist; QAtom; QAtom=QAtom->anext ) if( EvaluateExpr(expr) ) ptr = SetInsert( ptr, QAtom ); return( ptr ); } int DefineSetExpr( ident, expr ) char *ident; Expr *expr; { register SymEntry __far * __far *prev; register SymEntry __far *ptr; register AtomSet __far *set; register int result; result = True; prev = &SymbolTable; while( *prev ) { ptr = *prev; result = strcmp(ident,ptr->ident); if( !result ) break; /* Entry Exists! */ prev = (result<0)? &(ptr->lft) : &(ptr->rgt); } if( result ) { if( FreeEntry ) { ptr = FreeEntry; FreeEntry = ptr->rgt; } else /* Allocate SymEntry! */ { ptr = (SymEntry __far*)_fmalloc(sizeof(SymEntry)); if( !ptr ) return( False ); } *prev = ptr; ptr->ident = ident; ptr->defn = (void __far*)0; ptr->lft = (void __far*)0; ptr->rgt = (void __far*)0; } else free(ident); if( expr ) { set = BuildAtomSet(expr); if( ptr->defn ) DeleteAtomSet(ptr->defn); DeAllocateExpr(expr); ptr->defn = set; } else ptr->defn = (void __far*)0; return( True ); } Expr *LookUpSetExpr( ident ) char *ident; { register SymEntry __far *ptr; register Expr *expr; register int result; result = True; ptr = SymbolTable; while( ptr ) { result = strcmp(ident,ptr->ident); if( !result ) break; /* Entry Exists! */ ptr = (result<0)? ptr->lft : ptr->rgt; } if( !result ) { expr = AllocateNode(); expr->type = OpMember; expr->rgt.set = ptr->defn; } else expr = (Expr*)0; return( expr ); } static int ElemCompare( ident, elem ) char *ident, *elem; { while( *elem ) if( *elem++ != *ident++ ) return( False ); /* Handle Plurals */ if( (ident[0]=='S') && !ident[1] ) return( (elem[-1]!='S') && (elem[-1]!='Y') ); return( !*ident ); } Expr *LookUpElement( ident ) char *ident; { register Expr *expr; register int elem; for( elem=1; elemtype = OpEqual|OpLftProp|OpRgtVal; expr->lft.val = PropElemNo; expr->rgt.val = elem; } else expr = (Expr*)0; return( expr ); } static int MatchWildName( src, dst, size, len ) char *src, *dst; int size, len; { register int i, left; left = size; while( *dst==' ' ) { dst++; left--; } for( i=0; itype = OpEqual | OpLftProp | OpRgtVal; tmp1->lft.val = PropResName; tmp1->rgt.val = j; tmp2 = AllocateNode(); tmp2->type = OpOr; tmp2->lft.ptr = tmp1; tmp2->rgt.ptr = wild; wild = tmp2; } QueryExpr = wild; } else ch = *ptr++; /* Parse Residue Number */ if( ch != '*' ) { if( ch == '-' ) { ch = *ptr++; neg = True; } else neg = False; if( isdigit(ch) ) { i = ch-'0'; while( isdigit(*ptr) ) i = 10*i + (*ptr++)-'0'; tmp1 = AllocateNode(); tmp1->type = OpEqual | OpLftProp | OpRgtVal; tmp1->rgt.val = neg? -i : i; tmp1->lft.val = PropResId; if( QueryExpr != &TrueExpr ) { tmp2 = AllocateNode(); tmp2->type = OpAnd; tmp2->rgt.ptr = QueryExpr; tmp2->lft.ptr = tmp1; QueryExpr = tmp2; } else QueryExpr = tmp1; ch = *ptr++; } else if( neg ) return( False ); } else ch = *ptr++; } /* Parse Chain Ident */ if( ch==':' ) ch = *ptr++; if( isalnum(ch) ) { ch = ToUpper(ch); tmp1 = AllocateNode(); tmp1->type = OpEqual | OpLftProp | OpRgtVal; tmp1->lft.val = PropChain; tmp1->rgt.val = ch; if( QueryExpr != &TrueExpr ) { tmp2 = AllocateNode(); tmp2->type = OpAnd; tmp2->rgt.ptr = QueryExpr; tmp2->lft.ptr = tmp1; QueryExpr = tmp2; } else QueryExpr = tmp1; ch = *ptr++; } else if( (ch=='?') || (ch=='%') || (ch=='*') ) ch = *ptr++; /* Parse Model Number */ if( ch == ':' ) { ch = *ptr++; if( isdigit(ch) ) { i = ch-'0'; while( isdigit(*ptr) ) i = 10*i + (*ptr++)-'0'; tmp1 = AllocateNode(); tmp1->type = OpEqual | OpLftProp | OpRgtVal; tmp1->lft.val = PropModel; tmp1->rgt.val = i; if( QueryExpr != &TrueExpr ) { tmp2 = AllocateNode(); tmp2->type = OpAnd; tmp2->rgt.ptr = QueryExpr; tmp2->lft.ptr = tmp1; QueryExpr = tmp2; } else QueryExpr = tmp1; ch = *ptr++; } else return( False ); } /* Parse Atom Name */ if( ch == '.' ) { ch = *ptr++; if( ch!='*' ) { for( i=0; i<4; i++ ) if( isalnum(ch) || ch=='\'' || ch=='*' ) { NameBuf[i] = ToUpper(ch); ch = *ptr++; } else if( (ch=='?') || (ch=='%') || (ch=='#') ) { NameBuf[i] = '?'; ch = *ptr++; } else break; if( !i ) return( False ); wild = &FalseExpr; for( j=0; jtype = OpEqual | OpLftProp | OpRgtVal; tmp1->lft.val = PropName; tmp1->rgt.val = j; tmp2 = AllocateNode(); tmp2->type = OpOr; tmp2->lft.ptr = tmp1; tmp2->rgt.ptr = wild; wild = tmp2; } if( (QueryExpr == &TrueExpr) || (wild == &FalseExpr) ) { DeAllocateExpr(QueryExpr); QueryExpr=wild; } else { tmp1 = AllocateNode(); tmp1->type = OpAnd; tmp1->lft.ptr = QueryExpr; tmp1->rgt.ptr = wild; QueryExpr = tmp1; } } else ch = *ptr++; } *orig = --ptr; return( !ch || isspace(ch) || ispunct(ch) ); } static char *FormatInteger( ptr, value ) char *ptr; int value; { auto char buffer[10]; register char *tmp; if( value<0 ) { value = -value; *ptr++ = '-'; } if( value>9 ) { tmp = buffer; while( value>9 ) { *tmp++ = (value%10) + '0'; value /= 10; } *ptr++ = value + '0'; do { tmp--; *ptr++ = *tmp; } while( tmp != buffer ); } else *ptr++ = value + '0'; return( ptr ); } void FormatLabel( chain, group, aptr, label, ptr ) Chain __far *chain; Group __far *group; Atom __far *aptr; char *label, *ptr; { register char ch; register int i,j; while( *label ) { ch = *label++; if( ch=='%' ) { ch = *label++; if( isupper(ch) ) ch = tolower(ch); switch( ch ) { case('a'): /* Atom Name */ i = aptr->refno; for( j=0; j<4; j++ ) if( ElemDesc[i][j]!=' ' ) *ptr++ = ElemDesc[i][j]; break; case('b'): /* Temperature/B-factor */ case('t'): ptr = FormatInteger(ptr,aptr->temp); break; case('c'): /* Chain Identifier */ case('s'): *ptr++ = chain->ident; break; case('e'): /* Element Type */ i = aptr->elemno; *ptr++ = Element[i].symbol[0]; if( Element[i].symbol[1]!=' ' ) *ptr++ = Element[i].symbol[1]; break; case('i'): /* Atom Number */ ptr = FormatInteger(ptr,aptr->serno); break; case('m'): /* Amino (Nucliec) Acid Code */ if( group->refno <= AminoCodeMax ) { *ptr++ = AminoCode[group->refno]; } else *ptr++ = '?'; break; case('n'): /* Residue Name */ i = group->refno; for( j=0; j<3; j++ ) if( Residue[i][j]!=' ' ) *ptr++ = Residue[i][j]; break; case('r'): /* Residue Number */ ptr = FormatInteger(ptr,group->serno); break; case('%'): *ptr++ = '%'; break; } } else if( (ch>=' ') && (ch<='~') ) *ptr++ = ch; } *ptr = '\0'; } #ifdef FUNCPROTO /* Function Prototypes */ static void DeleteSymEntry( SymEntry __far* ); #endif static void DeleteSymEntry( ptr ) SymEntry __far *ptr; { if( ptr->lft ) DeleteSymEntry( ptr->lft ); if( ptr->rgt ) DeleteSymEntry( ptr->rgt ); if( ptr->defn ) DeleteAtomSet( ptr->defn ); free( ptr->ident ); ptr->rgt = FreeEntry; FreeEntry = ptr; } void ResetSymbolTable() { if( SymbolTable ) { DeleteSymEntry(SymbolTable); SymbolTable = (void __far*)0; } } double CalcDistance( atm1, atm2 ) Atom __far *atm1; Atom __far *atm2; { register Long dx,dy,dz; register double dist2; dx = atm1->xorg - atm2->xorg; dy = atm1->yorg - atm2->yorg; dz = atm1->zorg - atm2->zorg; if( dx || dy || dz ) { dist2 = dx*dx + dy*dy + dz*dz; return( sqrt(dist2)/250.0 ); } else return( 0.0 ); } double CalcAngle( atm1, atm2, atm3 ) Atom __far *atm1; Atom __far *atm2; Atom __far *atm3; { register double ulen2,vlen2; register double ux,uy,uz; register double vx,vy,vz; register double temp; ux = atm1->xorg - atm2->xorg; uy = atm1->yorg - atm2->yorg; uz = atm1->zorg - atm2->zorg; if( !ux && !uy && !uz ) return( 0.0 ); ulen2 = ux*ux + uy*uy + uz*uz; vx = atm3->xorg - atm2->xorg; vy = atm3->yorg - atm2->yorg; vz = atm3->zorg - atm2->zorg; if( !vx && !vy && !vz ) return( 0.0 ); vlen2 = vx*vx + vy*vy + vz*vz; temp = (ux*vx + uy*vy + uz*vz)/sqrt(ulen2*vlen2); return( Rad2Deg*acos(temp) ); } double CalcTorsion( atm1, atm2, atm3, atm4 ) Atom __far *atm1; Atom __far *atm2; Atom __far *atm3; Atom __far *atm4; { register double ax, ay, az; register double bx, by, bz; register double cx, cy, cz; register double c12,c13,c23; register double s12,s23; register double cossq,sgn,om; register double cosom,sinom; register double len; ax = atm2->xorg - atm1->xorg; ay = atm2->yorg - atm1->yorg; az = atm2->zorg - atm1->zorg; if( !ax && !ay && !az ) return( 0.0 ); bx = atm3->xorg - atm2->xorg; by = atm3->yorg - atm2->yorg; bz = atm3->zorg - atm2->zorg; if( !bx && !by && !bz ) return( 0.0 ); cx = atm4->xorg - atm3->xorg; cy = atm4->yorg - atm3->yorg; cz = atm4->zorg - atm3->zorg; if( !cx && !cy && !cz ) return( 0.0 ); #ifdef INVERT ay = -ay; by = -by; cy = -cy; az = -az; bz = -bz; cz = -cz; #else az = -az; bz = -bz; cz = -cz; #endif len = sqrt(ax*ax + ay*ay + az*az); ax /= len; ay /= len; az /= len; len = sqrt(bx*bx + by*by + bz*bz); bx /= len; by /= len; bz /= len; len = sqrt(cx*cx + cy*cy + cz*cz); cx /= len; cy /= len; cz /= len; c12 = ax*bx + ay*by + az*bz; c13 = ax*cx + ay*cy + az*cz; c23 = bx*cx + by*cy + bz*cz; s12 = sqrt(1.0-c12*c12); s23 = sqrt(1.0-c23*c23); cosom = (c12*c23-c13)/(s12*s23); cossq = cosom*cosom; if( cossq >= 1.0 ) { if( cosom < 0.0 ) { return( 180.0 ); } else return( 0.0 ); } sinom = sqrt(1.0-cossq); om = Rad2Deg*atan2(sinom,cosom); sgn = ax*((by*cz)-(bz*cy)); sgn += ay*((bz*cx)-(bx*cz)); sgn += az*((bx*cy)-(by*cx)); return( (sgn<0)? -om : om ); } #ifndef ABSTREE double CalcDihedral( atm1, atm2, atm3, atm4 ) Atom __far *atm1; Atom __far *atm2; Atom __far *atm3; Atom __far *atm4; { return( 180.0 - CalcTorsion(atm1,atm2,atm3,atm4) ); } /* Note: curr == prev->gnext! */ double CalcPhiAngle( prev, curr ) Group __far *prev; Group __far *curr; { Atom __far *prevc; Atom __far *currca; Atom __far *currc; Atom __far *currn; if( !(prevc = FindGroupAtom(prev,2)) ) return( 360.0 ); if( !(currca = FindGroupAtom(curr,1)) ) return( 360.0 ); if( !(currc = FindGroupAtom(curr,2)) ) return( 360.0 ); if( !(currn = FindGroupAtom(curr,0)) ) return( 360.0 ); return( CalcDihedral(prevc,currn,currca,currc) ); } /* Note: next == curr->gnext! */ double CalcPsiAngle( curr, next ) Group __far *curr; Group __far *next; { Atom __far *nextn; Atom __far *currca; Atom __far *currc; Atom __far *currn; if( !(nextn = FindGroupAtom(next,0)) ) return( 360.0 ); if( !(currca = FindGroupAtom(curr,1)) ) return( 360.0 ); if( !(currc = FindGroupAtom(curr,2)) ) return( 360.0 ); if( !(currn = FindGroupAtom(curr,0)) ) return( 360.0 ); return( CalcDihedral(currn,currca,currc,nextn) ); } #endif void InitialiseAbstree() { FalseExpr.type = OpConst | OpLftVal | OpRgtVal; FalseExpr.rgt.val = FalseExpr.lft.val = 0; TrueExpr.type = OpConst | OpLftVal | OpRgtVal; TrueExpr.rgt.val = TrueExpr.lft.val = 1; QChain = (void __far*)0; QGroup = (void __far*)0; QAtom = (void __far*)0; SymbolTable = (void __far*)0; FreeEntry = (void __far*)0; FreeSet = (void __far*)0; FreeExpr = NULL; }