Inspect the example Magnet rules file pkx1.sea:
begin {printf("ID DockScore HBD127 HBD129 HBA129 HBD133 Arom Dist\n")};
#Hanneke's first definitions
define HDon "[$([N,O;!H0]),$(N(C)(C)C)]";
define HAcc "[$(O~*),$([n;X2])]";
# Note that HB definitions below use the "notdef" function to ensure each HB is only counted once
# (in case either the donor or acceptor has more than one atom connected to it, the selections
# match more than once, which would lead to counting the same HB more than once
{smarts("[$HDon]~*")},{residues(127) smarts("[$HAcc]~*")}
{notdef(l1,r1,"H")&&dist(l1,r1)>2.4&&dist(l1,r1)<=3.3&&angle(l2,l1,r1)>80
&&angle(l2,l1,r1)<180&&angle(l1,r1,r2)>80
&&angle(l1,r1,r2)<180}
{accept(l1,r1,"H",dist(l1,r1));
set(VHBD127,VHBD127+1)};
{smarts("[$HDon]~*")},{residues(129) smarts("[$HAcc]~*")}
{notdef(l1,r1,"H")&&dist(l1,r1)>2.4&&dist(l1,r1)<3.3&&angle(l2,l1,r1)>80
&&angle(l2,l1,r1)<180&&angle(l1,r1,r2)>80
&&angle(l1,r1,r2)<180}
{accept(l1,r1,"H",dist(l1,r1));
set(VHBD129,VHBD129+1)};
{smarts("[$HAcc]~*")},{residues(129) smarts("[$HDon]~*")}
{notdef(l1,r1,"H")&&dist(l1,r1)>2.4&&dist(l1,r1)<3.3&&angle(l2,l1,r1)>80
&&angle(l2,l1,r1)<180&&angle(l1,r1,r2)>80
&&angle(l1,r1,r2)<180}
{accept(l1,r1,"H",dist(l1,r1));
set(VHBA129,VHBA129+1)};
{smarts("[$HDon]~*")},{residues(133) atnames("OE1","OE2")}
{notdef(l1,r1,"H")&&dist(l1,r1)>2.4&&dist(l1,r1)<3.3&&angle(l2,l1,r1)>80
&&angle(l2,l1,r1)<180&&angle(l1,r1,r2)>80
&&angle(l1,r1,r2)<180}
{accept(l1,r1,"H",dist(l1,r1));
set(VHBD133,VHBD133+1)};
# pocket occupancy by checking distance to a centroid with fixed XYZ coordinates
{smarts("[a]")},{}
{pointdist(l1,73.11,33.80,42.69)<2.0}
{set(VArom,VArom+1)};
# pocket occupancy by checking distance ranges to 3 protein atoms
{smarts("[a]")},{residues(126)atnames("CA")}
{notdef(l1,r1,"D")&&dist(l1,r1)<9.6&&dist(l1,r1)>5.6}
{accept(l1,r1,"D",1);setrealatomprop(l1,"nbc",getrealatomprop(l1,"nbc")+1)};
{smarts("[a]")},{residues(128)atnames("CA")}
{notdef(l1,r1,"D")&&dist(l1,r1)<6.8&&dist(l1,r1)>2.8}
{accept(l1,r1,"D",1);setrealatomprop(l1,"nbc",getrealatomprop(l1,"nbc")+1)};
{smarts("[a]")},{residues(333)atnames("CA")}
{notdef(l1,r1,"D")&&dist(l1,r1)<10.5&&dist(l1,r1)>6.5}
{accept(l1,r1,"D",1);setrealatomprop(l1,"nbc",getrealatomprop(l1,"nbc")+1)};
{all()},{}
{getrealatomprop(l1,"nbc")==3}
{set(VDist,VDist+1)};
{},{} {VHBD127>0||VHBD129>0||VHBA129>0||VHBD133>0||VArom>0||VDist>0||VVDW>0}
{printf("%s %s %.0f %.0f %.0f %.0f %.0f %.0f\n",getid(1),getmolprop(l,"dockscore"),
VHBD127,VHBD129,VHBA129,VHBD133,VArom,VDist)};The first line specifies the header for the final output file.
The second text block defines HydrogenBond (HB) donors and acceptors, using SMARTS language.
The next 4 text blocks look for HB donors and acceptors to the 2 hinge domain residues, numbers 127 and 129, and another active site residue, number 133. Note that these rules look for any donors or acceptors in residues 127 and 129, but specify the sidechain carbonyl oxygens specifically for the HB to residue 133.
The following text block looks for aromatic atoms close to the center of a purine ring when it is docked into the homology model. The purine ring center is defined by X,Y,Z coordinates (73.11, 33.80, 42.69), and the pdb-file of this docked purine is bare_purine.pdb
An alternative way of looking for aromatic atoms in the pocket filled by the ATP-purine ring is shown in the next text block where distance ranges to 3 protein atoms lining the pocket are used to determine whether an aromatic atom is in the pocket.
A third way to check pocket occupancy would be something like:
# pocket occupancy by testing VDW contact with residues lining the pocket
{smarts("[a]")},{residues(126,127,128,129,76,63,55,333,179,189,110)}
{dist(l1,r1)<1.1*vdw(l1,r1)&&getrealatomprop(l1,"vdw")<1}
{set(VVDW,VVDW+1);setrealatomprop(l1,"vdw",1)};
where all the residues lining the pocket are named in the protein selection phrase. For the current target, this rule is not very discriminatory.
Variables are used in Magnet to count the number of features. In the example, VHBD127 is a variable counting the number of HB donors to residue #127, and VArom is a variable counting the number of aromatic atoms within 2A of the center of the docked purine ring. In the header line, I print just the name that I want to see later, like HBD127. For magnet, any variable has to start with a "V", like VHBD127.
The last text block specifies which poses are to be output (ones with at least one positive count for one of the features), and which variables to output. The getid(1) call specifies that the structure name, augmented with a pose number, will be output.
Check the SEA manual for a full description of the SEA language and all its options.
Tip for adding new HB features to an existing rules file: copy the text block for another HB feature and edit that. Make sure you add an entry for this feature in the header line and that you include it in the output (last printf statement).