OSDN Git Service

Ruby: Molecule#find_close_atoms is implemented.
authortoshinagata1964 <toshinagata1964@a2be9bc6-48de-4e38-9406-05402d4bc13c>
Mon, 31 Oct 2011 05:26:04 +0000 (05:26 +0000)
committertoshinagata1964 <toshinagata1964@a2be9bc6-48de-4e38-9406-05402d4bc13c>
Mon, 31 Oct 2011 05:26:04 +0000 (05:26 +0000)
git-svn-id: svn+ssh://svn.sourceforge.jp/svnroot/molby/trunk@148 a2be9bc6-48de-4e38-9406-05402d4bc13c

Documents/src/molby_rb/Molecule.html
MolLib/Molecule.c
MolLib/Molecule.h
MolLib/Ruby_bind/ruby_bind.c

index 4c974f1..512938d 100644 (file)
@@ -1138,6 +1138,19 @@ are not selected but are connected to any selected atoms are also included as du
 </div>
 </div>
 
+<div id="method-M000261" class="method-detail">
+<a name="find_close_atoms"></a>
+<div class="method-heading">
+<span class="method-name">find_close_atoms(atom, limit = 1.2)       &rarr; Array of Integers<br />
+</span>
+</div>
+<div class="method-description">
+<p>
+Find atoms that are within the threshold distance from the given atom. If limit is a positive number, the threshold distance is the sum of the vdw radii times limit. If limit is a negative number, its absolute value is used for the threshold distance in angstrom. If limit is not given, a default value of 1.2 is used. The number of the newly created bonds is returned. An array of atom indices is returned. If no atoms are found, an empty array is returned.
+</p>
+</div>
+</div>
+
 <div id="method-M000294" class="method-detail">
 <a name="M000294"></a>
 <div class="method-heading">
@@ -1259,10 +1272,7 @@ Copy the coordinates from the specified frame. If group is specified, then only
 </div>
 <div class="method-description">
 <p>
-Create bonds between atoms that are close enough,
-i.e. the interatomic distance is smaller than the sum of the vdw radii
-times the argument limit. Returns the number of the newly created bonds.
-This operation is undoable.
+Create bonds between atoms that are within the threshold distance. If limit is a positive number, the threshold distance is the sum of the vdw radii times limit. If limit is a negative number, its absolute value is used for the threshold distance in angstrom. If limit is not given, a default value of 1.2 is used. The number of the newly created bonds is returned. This operation is undoable.
 </p>
 </div>
 </div>
index 7b54835..fe175f9 100755 (executable)
@@ -5049,28 +5049,73 @@ MoleculeSearchImpropersAcrossAtomGroup(Molecule *mp, IntGroup *atomgroup)
        return sMoleculeSearchAcrossAtomGroup(mp->nimpropers, mp->impropers, 4, atomgroup, "impropers");
 }
 
+/*  Subroutine for MoleculeGuessBonds. It can be also used independently, but make sure that *outNbonds/*outBonds 
+    _correctly_ represents an array of two integers (as in mp->nbonds/mp->bonds).  */
+/*  Find atoms within the given "distance" from the given atom.  */
+/*  If limit is negative, its absolute value denotes the threshold distance in angstrom; otherwise,
+ the threshold distance is given by the sum of van der Waals radii times limit.  */
+/*  If triangle is non-zero, then only atoms with lower indexes than index are looked for.  */
+int
+MoleculeFindCloseAtoms(Molecule *mp, Int index, Double limit, Int *outNbonds, Int **outBonds, Int triangle)
+{
+       Int n1, n2, j, nlim, newbond[2];
+       Double a1, a2, alim;
+       Vector dr, r1, r2;
+       Atom *ap = ATOM_AT_INDEX(mp->atoms, index);
+       n1 = ap->atomicNumber;
+       if (n1 >= 0 && n1 < gCountElementParameters)
+               a1 = gElementParameters[n1].radius;
+       else a1 = gElementParameters[6].radius;
+       r1 = ap->r;
+       nlim = (triangle ? index : mp->natoms);
+       for (j = 0; j < nlim; j++) {
+               Atom *bp = ATOM_AT_INDEX(mp->atoms, j);
+               if (index == j)
+                       continue;
+               n2 = bp->atomicNumber;
+               if (n2 >= 0 && n2 < gCountElementParameters)
+                       a2 = gElementParameters[n2].radius;
+               else a2 = gElementParameters[6].radius;
+               r2 = bp->r;
+               VecSub(dr, r1, r2);
+               if (limit < 0)
+                       alim = -limit;
+               else
+                       alim = limit * (a1 + a2);
+               if (VecLength2(dr) < alim * alim) {
+                       newbond[0] = index;
+                       newbond[1] = j;
+                       /*      MoleculeAddBonds(mp, 1, newbonds); */
+                       AssignArray(outBonds, outNbonds, sizeof(Int) * 2, *outNbonds, newbond);
+               }
+       }
+       return 0;
+}
+
 /*  Guess the bonds from the coordinates  */
+/*  If limit is negative, its absolute value denotes the threshold distance in angstrom; otherwise,
+    the threshold distance is given by the sum of van der Waals radii times limit.  */
 int
 MoleculeGuessBonds(Molecule *mp, Double limit, Int *outNbonds, Int **outBonds)
 {
-       int i, j, n1, n2;
-       Int nbonds, *bonds;
+       Int nbonds, *bonds, i, newbond[2];
+/*     int i, j, n1, n2;
        Atom *ap, *bp;
        Vector r1, r2, dr;
        Double a1, a2, alim;
        Int newbond[2];
-       ElementPar *p = gElementParameters;
+       ElementPar *p = gElementParameters; */
        nbonds = 0;
        bonds = NULL;
        for (i = 0; i < mp->natoms; i++) {
+               MoleculeFindCloseAtoms(mp, i, limit, &nbonds, &bonds, 1);
+               /*
                ap = ATOM_AT_INDEX(mp->atoms, i);
                n1 = ap->atomicNumber;
                if (n1 >= 0 && n1 < gCountElementParameters)
                        a1 = p[n1].radius;
                else a1 = p[6].radius;
                r1 = ap->r;
-       /*      if (mp->is_xtal_coord)
-                       TransformVec(&r1, mp->cell->tr, &r1); */
                for (j = 0; j < i; j++) {
                        bp = ATOM_AT_INDEX(mp->atoms, j);
                        n2 = bp->atomicNumber;
@@ -5078,17 +5123,18 @@ MoleculeGuessBonds(Molecule *mp, Double limit, Int *outNbonds, Int **outBonds)
                                a2 = p[n2].radius;
                        else a2 = p[6].radius;
                        r2 = bp->r;
-               /*      if (mp->is_xtal_coord)
-                               TransformVec(&r2, mp->cell->tr, &r2); */
                        VecSub(dr, r1, r2);
-                       alim = limit * (a1 + a2);
+                       if (limit < 0)
+                               alim = -limit;
+                       else
+                               alim = limit * (a1 + a2);
                        if (VecLength2(dr) < alim * alim) {
                                newbond[0] = i;
                                newbond[1] = j;
-                       /*      MoleculeAddBonds(mp, 1, newbonds); */
                                AssignArray(&bonds, &nbonds, sizeof(Int) * 2, nbonds, newbond);
                        }
                }
+               */
        }
        if (nbonds > 0) {
                newbond[0] = kInvalidIndex;
index aa6d6f0..81e6035 100755 (executable)
@@ -417,6 +417,7 @@ int MoleculeLookupAtomInResidue(Molecule *mp, int n1, int resno);
 int MoleculeAnalyzeAtomName(const char *s, char *resName, int *resSeq, char *atomName);
 int MoleculeAtomIndexFromString(Molecule *mp, const char *s);
 
+int MoleculeFindCloseAtoms(Molecule *mp, Int index, Double limit, Int *outNbonds, Int **outBonds, Int triangle);
 int MoleculeGuessBonds(Molecule *mp, Double limit, Int *outNbonds, Int **outBonds);
 int MoleculeAreAtomsConnected(Molecule *mp, int n1, int n2);
 int MoleculeRebuildTablesFromConnects(Molecule *mp);
index d1043e8..380943b 100644 (file)
@@ -6157,11 +6157,48 @@ s_Molecule_RenumberAtoms(VALUE self, VALUE array)
 
 /*
  *  call-seq:
+ *     find_close_atoms(atom, limit = 1.2)       -> array of Integers (atom indices)
+ *
+ *  Find atoms that are within the threshold distance from the given atom.
+ *  If limit is a positive number, the threshold distance is the sum of the vdw radii times limit.
+ *  If limit is a negative number, its absolute value is used for the threshold distance in angstrom.
+ *  If limit is not given, a default value of 1.2 is used.
+ *  An array of atom indices is returned. If no atoms are found, an empty array is returned.
+ */
+static VALUE
+s_Molecule_FindCloseAtoms(int argc, VALUE *argv, VALUE self)
+{
+    Molecule *mol;
+       VALUE aval, limval;
+       double limit;
+       Int n1, nbonds, *bonds;
+    Data_Get_Struct(self, Molecule, mol);
+       rb_scan_args(argc, argv, "11", &aval, &limval);
+       n1 = s_Molecule_AtomIndexFromValue(mol, aval);
+       if (limval == Qnil)
+               limit = 1.2;
+       else
+               limit = NUM2DBL(rb_Float(limval));
+       nbonds = 0;  /*  This initialization is necessary: see comments in MoleculeFindCloseAtoms()  */
+       bonds = NULL;
+       MoleculeFindCloseAtoms(mol, n1, limit, &nbonds, &bonds, 0);
+       aval = rb_ary_new();
+       if (nbonds > 0) {
+               for (n1 = 0; n1 < nbonds; n1++)
+                       rb_ary_push(aval, INT2NUM(bonds[n1 * 2 + 1]));
+               free(bonds);
+       }
+       return aval;
+}
+
+/*
+ *  call-seq:
  *     guess_bonds(limit = 1.2)       -> Integer
  *
- *  Create bonds between atoms that are 'close enough', i.e. the interatomic distance is
- *  smaller than the sum of the vdw radii times the argument 'limit'. If limit is not
- *  given, a default value of 1.2 is used.
+ *  Create bonds between atoms that are within the threshold distance.
+ *  If limit is a positive number, the threshold distance is the sum of the vdw radii times limit.
+ *  If limit is a negative number, its absolute value is used for the threshold distance in angstrom.
+ *  If limit is not given, a default value of 1.2 is used.
  *  The number of the newly created bonds is returned.
  *  This operation is undoable.
  */
@@ -8278,6 +8315,7 @@ Init_Molby(void)
        rb_define_method(rb_cMolecule, "assign_residue", s_Molecule_AssignResidue, 2);
        rb_define_method(rb_cMolecule, "offset_residue", s_Molecule_OffsetResidue, 2);
        rb_define_method(rb_cMolecule, "renumber_atoms", s_Molecule_RenumberAtoms, 1);
+       rb_define_method(rb_cMolecule, "find_close_atoms", s_Molecule_FindCloseAtoms, -1);
        rb_define_method(rb_cMolecule, "guess_bonds", s_Molecule_GuessBonds, -1);
        rb_define_method(rb_cMolecule, "selection", s_Molecule_Selection, 0);
        rb_define_method(rb_cMolecule, "selection=", s_Molecule_SetSelection, 1);