Author: Laszlo Kajan <lkajan@rostlab.org>
Description: command line argument for controlling iterative search
Forwarded: no
--- a/apps/concavity/concavity.C
+++ b/apps/concavity/concavity.C
@@ -113,6 +113,7 @@
 RNScalar exterior_ligand_sigma = 0;
 int pocket_threshold_type = 0; // 0=none, 1=absolute, 2=stddev, 3=percentile
 RNScalar pocket_threshold = 0;
+RNScalar thresh_rng_cutoff = 0;
 int cavity_rank_method = 0;
 int normalization_type = 0;
 int max_cavities = 0;
@@ -534,6 +535,9 @@
       else if (!strcmp(*argv, "-max_total_volume_as_fraction_of_protein")) { 
         argc--; argv++; max_total_volume_as_fraction_of_protein = atof(*argv); 
       }
+      else if (!strcmp(*argv, "-extraction_threshold_range_cutoff")) {
+        argc--; argv++; thresh_rng_cutoff = atof(*argv); 
+      }
 
       // Residue Mapping options
       else if (!strcmp(*argv, "-res_map_method")){
@@ -739,7 +743,7 @@
   // Extract pockets
   R3Grid *pocket_grid;
   if (strcmp(extraction_method, "none")) {
-    pocket_grid = ExtractPockets(pdb_file, grid, protein_atoms, ligand_atoms);
+    pocket_grid = ExtractPockets(pdb_file, grid, protein_atoms, ligand_atoms, thresh_rng_cutoff );
   } else {
     pocket_grid = grid;
   }
--- a/apps/concavity/pocket_extraction.C
+++ b/apps/concavity/pocket_extraction.C
@@ -939,7 +939,7 @@
 
 static void 
 MaskToTotalVolume(R3Grid *mask, RNScalar max_total_volume, 
-                  RNScalar min_cavity_radius, RNScalar min_cavity_volume, int max_cavities)
+                  RNScalar min_cavity_radius, RNScalar min_cavity_volume, int max_cavities, RNScalar __thresh_rng_cutoff )
 {
   // Start statistics
   RNTime start_time;
@@ -964,7 +964,12 @@
   R3Grid mask_copy(*mask);
 
   // Binary search for threshold that provides target volume
-  for (int i = 0; i < 100; i++) {
+  bool converged = false;
+  int i;
+  for (i = 0; i < 100; i++) {
+    // lkajan: if the max and min thresholds are close at the given cutoff, stop.
+    if( threshold_range.Diameter() < threshold_range.Max() * __thresh_rng_cutoff ) break;
+
     // Compute new guess for threshold
     // RNScalar t = (max_total_volume - volume_range.Min()) / (volume_range.Max() - volume_range.Min());
     // RNScalar threshold = threshold_range.Max() - t * (threshold_range.Max() - threshold_range.Min());
@@ -1010,6 +1015,7 @@
     }
     else {
       // Found target volume!
+      converged = true;
       break;
     }
   }
@@ -1029,6 +1035,8 @@
     printf("  Minimum cavity volume = %g\n", min_cavity_volume);
     printf("  Max cavities = %d\n", max_cavities);
     printf("  Grid threshold = %g\n", threshold_range.Mid());
+    printf("  Threshold range cutoff = %g\n", __thresh_rng_cutoff);
+    printf("  Iterations = %d %s\n", i, converged ? "(converged)" : "" );
     printf("  Cardinality = %d\n", mask->Cardinality());
     printf("  Volume = %g\n", mask->Volume());
     RNInterval grid_range = mask->Range();
@@ -1334,7 +1342,7 @@
 
 
 R3Grid * 
-ExtractPockets(PDBFile *file, R3Grid *grid, const RNArray<PDBAtom *> *protein_atoms, const RNArray<PDBAtom *> *ligand_atoms)
+ExtractPockets(PDBFile *file, R3Grid *grid, const RNArray<PDBAtom *> *protein_atoms, const RNArray<PDBAtom *> *ligand_atoms, RNScalar __thresh_rng_cutoff )
 {
   // Determine number of cavities
   if (max_cavities < 0) max_cavities = NumConnectedComponents(*ligand_atoms);
@@ -1388,7 +1396,7 @@
   // MaskToTotalVolume executes MaskToCavityRadius, MaskToCavityVolume, and MaskToLargestCavities
   if ((max_total_volume > 0) && (max_total_volume < RN_INFINITY)) {
     // Mask by total volume
-    MaskToTotalVolume(mask, max_total_volume, min_cavity_radius, min_cavity_volume, max_cavities);
+    MaskToTotalVolume(mask, max_total_volume, min_cavity_radius, min_cavity_volume, max_cavities, __thresh_rng_cutoff );
   }
   else if ((max_cavity_volume > 0) && (max_cavity_volume < RN_INFINITY)) {
     // Mask by cavity radius
--- a/apps/concavity/pocket_extraction.h
+++ b/apps/concavity/pocket_extraction.h
@@ -31,7 +31,7 @@
 // public pocket_extraction functions
 RNArray<PDBAtom *> * FindProteinAtoms(PDBFile *file);
 RNArray<PDBAtom *> * FindLigandAtoms(PDBFile *file, const char *ligand_name);
-R3Grid * ExtractPockets(PDBFile *file, R3Grid *grid, const RNArray<PDBAtom *> *protein_atoms, const RNArray<PDBAtom *> *ligand_atoms);
+R3Grid * ExtractPockets(PDBFile *file, R3Grid *grid, const RNArray<PDBAtom *> *protein_atoms, const RNArray<PDBAtom *> *ligand_atoms, RNScalar __thresh_rng_cutoff = 0 );
 
 
 
--- a/concavity.1.pod
+++ b/concavity.1.pod
@@ -107,6 +107,10 @@
 
 =item B<-extraction_method> I<search|topn|custom>
 
+=item B<-extraction_threshold_range_cutoff> I<FLOAT>
+
+Stop the iterative I<search> method when the diameter of the binary search window is less than B<-extraction_threshold_range_cutoff> * upper_threshold. Recommended value: I<1e-6>. Default: I<0>.
+
 =back
 
 =head2 Residue Mapping
