diff --git a/modules/conop/pymod/export_processor.cc b/modules/conop/pymod/export_processor.cc
index 180da8f48363571c1c8465bb4f8f2b01271f900f..c9298c25de569fd882a28fbf1bf949739581be03 100644
--- a/modules/conop/pymod/export_processor.cc
+++ b/modules/conop/pymod/export_processor.cc
@@ -75,5 +75,6 @@ void export_processor() {
     .def("Copy", &WrappedProcessor::CopyDefault)
     .def("DoProcess", &WrappedProcessor::DoProcessDefault)
   ;
+  def("IsBondFeasible", &IsBondFeasible);
 }
 
diff --git a/modules/conop/src/processor.cc b/modules/conop/src/processor.cc
index e1a3e6b6607dd68491cdfbb99a5350190ce8156f..1e996b77ab0aeb8a7437eb55e91c2ea069106ce9 100644
--- a/modules/conop/src/processor.cc
+++ b/modules/conop/src/processor.cc
@@ -98,4 +98,88 @@ void AssignBackboneTorsions(mol::ResidueHandle prev,
   }
 } 
 
+void Processor::ProcessUnkResidue(DiagnosticsPtr diags,
+                                  mol::ResidueHandle res) const
+{
+  // Don't do anything if treatment is set to SILENT
+  if (this->GetUnkResidueTreatment() == CONOP_SILENT) {
+    return;
+  }
+  switch (this->GetUnkResidueTreatment()) {
+    case CONOP_WARN:
+      diags->AddDiag(DIAG_UNK_RESIDUE, "unknown residue %0")
+            .AddResidue(res);
+      break;
+    case CONOP_FATAL:
+      // FIXME: Implement a ConopError based on Diag...
+      break;
+    case CONOP_REMOVE_RESIDUE:
+    case CONOP_REMOVE:
+      diags->AddDiag(DIAG_UNK_RESIDUE, "removed unknown residue %0")
+           .AddResidue(res);
+      res.GetEntity().EditXCS().DeleteResidue(res);
+      return;
+    default:
+      assert(0 && "unhandled switch");
+  }
+}
+
+void Processor::ProcessUnkAtoms(DiagnosticsPtr diags,
+                                mol::AtomHandleList unks) const
+{
+  // Don't do anything if treatment is set to SILENT
+  if (this->GetUnkAtomTreatment() == CONOP_SILENT) {
+    return;
+  }
+ 
+  assert(!unks.empty() && "empty unk list");
+  mol::XCSEditor edi = unks.front().GetEntity().EditXCS();
+  for (mol::AtomHandleList::iterator 
+       i = unks.begin(), e = unks.end(); i != e; ++i) {
+    switch (this->GetUnkAtomTreatment()) {
+      case CONOP_REMOVE_ATOM:
+      case CONOP_REMOVE:
+        edi.DeleteAtom(*i);
+        diags->AddDiag(DIAG_UNK_ATOM, "removed unknown atom %0 from residue %1")
+             .AddString(i->GetName()).AddResidue(i->GetResidue());
+        break;
+      case CONOP_WARN:
+        diags->AddDiag(DIAG_UNK_ATOM, "residue %0 contains unknown atom %1")
+             .AddResidue(i->GetResidue()).AddString(i->GetName());
+        break;
+      case CONOP_FATAL:
+        // FIXME: Implement a ConopError based on Diag...
+        break;
+      case CONOP_REMOVE_RESIDUE:
+        diags->AddDiag(DIAG_UNK_ATOM, "removed residue %0 with unknown atom %1")
+             .AddString(i->GetResidue().GetQualifiedName())
+             .AddString(i->GetName());
+        edi.DeleteResidue(i->GetResidue());
+        return;
+      default:
+        assert(0 && "unhandled switch");
+    }
+  }
+}
+
+bool IsBondFeasible(const mol::AtomHandle& atom_a,
+                    const mol::AtomHandle& atom_b)
+{
+  Real radii=0.0;
+  if (atom_a.GetRadius()>0.0) {
+    radii=atom_a.GetRadius();
+  } else {
+    return false;
+  }
+  if (atom_b.GetRadius()>0.0) {
+    radii+=atom_b.GetRadius();
+  } else {
+    return false;
+  } 
+  Real len=geom::Length2(atom_a.GetPos()-atom_b.GetPos());
+  Real lower_bound=radii*radii*0.0625;
+  Real upper_bound=lower_bound*6.0;
+  return (len<=upper_bound && len>=lower_bound);
+}
+
 }}
diff --git a/modules/conop/src/processor.hh b/modules/conop/src/processor.hh
index 0fdaee40dba0ce591e445f6882ee10004e7b7005..79406e72e6803109855b90eb3c90b4189ae8cce1 100644
--- a/modules/conop/src/processor.hh
+++ b/modules/conop/src/processor.hh
@@ -53,6 +53,10 @@ protected:
                                mol::EntityHandle ent) const { return true; }  
   virtual bool EndProcessing(DiagnosticsPtr diags, 
                              mol::EntityHandle ent) const { return true; }
+  void ProcessUnkResidue(DiagnosticsPtr diags,
+                         mol::ResidueHandle res) const;
+  void ProcessUnkAtoms(DiagnosticsPtr diags,
+                       mol::AtomHandleList unks) const;
 public:
   Processor(): strict_hydrogens_(false), check_bond_feasibility_(false),
     assign_torsions_(false), connect_(true), unk_atom_treatment_(CONOP_WARN),
@@ -132,6 +136,8 @@ void DLLEXPORT_OST_CONOP AssignBackboneTorsions(mol::ResidueHandle prev,
                                                 mol::ResidueHandle res, 
                                                 mol::ResidueHandle next);
 
+bool DLLEXPORT_OST_CONOP IsBondFeasible(const mol::AtomHandle&, 
+                                        const mol::AtomHandle&);
 }}
 
 #endif
diff --git a/modules/conop/src/rule_based.cc b/modules/conop/src/rule_based.cc
index 224b11024058375c5c33fab1b229b5cff954913a..98018f29f3a2cf1c3a0d56c7fb967078e09c4c3c 100644
--- a/modules/conop/src/rule_based.cc
+++ b/modules/conop/src/rule_based.cc
@@ -35,69 +35,6 @@ struct OrdinalAtomComp {
   }
 };
 
-void RuleBasedProcessor::ProcessUnkResidue(DiagnosticsPtr diags,
-                                           mol::ResidueHandle res) const
-{
-  // Don't do anything if treatment is set to SILENT
-  if (this->GetUnkResidueTreatment() == CONOP_SILENT) {
-    return;
-  }
-  switch (this->GetUnkResidueTreatment()) {
-    case CONOP_WARN:
-      diags->AddDiag(DIAG_UNK_RESIDUE, "unknown residue %0")
-            .AddResidue(res);
-      break;
-    case CONOP_FATAL:
-      // FIXME: Implement a ConopError based on Diag...
-      break;
-    case CONOP_REMOVE_RESIDUE:
-    case CONOP_REMOVE:
-      diags->AddDiag(DIAG_UNK_RESIDUE, "removed unknown residue %0")
-           .AddResidue(res);
-      res.GetEntity().EditXCS().DeleteResidue(res);
-      return;
-    default:
-      assert(0 && "unhandled switch");
-  }
-}
-
-void RuleBasedProcessor::ProcessUnkAtoms(DiagnosticsPtr diags,
-                                         mol::AtomHandleList unks) const
-{
-  // Don't do anything if treatment is set to SILENT
-  if (this->GetUnkAtomTreatment() == CONOP_SILENT) {
-    return;
-  }
- 
-  assert(!unks.empty() && "empty unk list");
-  mol::XCSEditor edi = unks.front().GetEntity().EditXCS();
-  for (mol::AtomHandleList::iterator 
-       i = unks.begin(), e = unks.end(); i != e; ++i) {
-    switch (this->GetUnkAtomTreatment()) {
-      case CONOP_REMOVE_ATOM:
-      case CONOP_REMOVE:
-        edi.DeleteAtom(*i);
-        diags->AddDiag(DIAG_UNK_ATOM, "removed unknown atom %0 from residue %1")
-             .AddString(i->GetName()).AddResidue(i->GetResidue());
-        break;
-      case CONOP_WARN:
-        diags->AddDiag(DIAG_UNK_ATOM, "residue %0 contains unknown atom %1")
-             .AddResidue(i->GetResidue()).AddString(i->GetName());
-        break;
-      case CONOP_FATAL:
-        // FIXME: Implement a ConopError based on Diag...
-        break;
-      case CONOP_REMOVE_RESIDUE:
-        diags->AddDiag(DIAG_UNK_ATOM, "removed residue %0 with unknown atom %1")
-             .AddString(i->GetResidue().GetQualifiedName())
-             .AddString(i->GetName());
-        edi.DeleteResidue(i->GetResidue());
-        return;
-      default:
-        assert(0 && "unhandled switch");
-    }
-  }
-}
 
 void RuleBasedProcessor::DoProcess(DiagnosticsPtr diags, 
                                    mol::EntityHandle ent) const
@@ -163,7 +100,7 @@ void RuleBasedProcessor::ConnectResidues(mol::ResidueHandle rh,
     mol::AtomHandle n=next.FindAtom("N");
     // Give subclasses a chance to give us their opinions on the feasibility of
     // the peptide bond.
-    if (c.IsValid() && n.IsValid() && this->IsBondFeasible(c, n)) {
+    if (c.IsValid() && n.IsValid() && IsBondFeasible(c, n)) {
       e.Connect(c, n, 1);
       rh.SetIsProtein(true);
       next.SetIsProtein(true);
@@ -171,7 +108,7 @@ void RuleBasedProcessor::ConnectResidues(mol::ResidueHandle rh,
   } else if (rh.IsNucleotideLinking() && next.IsNucleotideLinking()) {
     mol::AtomHandle c=rh.FindAtom("O3'");
     mol::AtomHandle n=next.FindAtom("P");
-    if (c.IsValid() && n.IsValid() && this->IsBondFeasible(c, n)) {
+    if (c.IsValid() && n.IsValid() && IsBondFeasible(c, n)) {
       e.Connect(c, n, 1);
     }
   }
@@ -231,7 +168,7 @@ void RuleBasedProcessor::ConnectAtomsOfResidue(mol::ResidueHandle rh,
           }
           e.Connect(a1, a2, bond.order);
         } else { 
-          if (this->IsBondFeasible(a1, a2)) {
+          if (IsBondFeasible(a1, a2)) {
             if (this->GetStrictHydrogens() && (a1.GetElement()=="H" || 
                                                a2.GetElement()=="D")) {
               continue;
@@ -243,25 +180,6 @@ void RuleBasedProcessor::ConnectAtomsOfResidue(mol::ResidueHandle rh,
   }
 }
 
-bool RuleBasedProcessor::IsBondFeasible(const mol::AtomHandle& atom_a,
-                                    const mol::AtomHandle& atom_b) const
-{
-  Real radii=0.0;
-  if (atom_a.GetRadius()>0.0) {
-    radii=atom_a.GetRadius();
-  } else {
-    return false;
-  }
-  if (atom_b.GetRadius()>0.0) {
-    radii+=atom_b.GetRadius();
-  } else {
-    return false;
-  } 
-  Real len=geom::Length2(atom_a.GetPos()-atom_b.GetPos());
-  Real lower_bound=radii*radii*0.0625;
-  Real upper_bound=lower_bound*6.0;
-  return (len<=upper_bound && len>=lower_bound);
-}
 
 void RuleBasedProcessor::ReorderAtoms(mol::ResidueHandle residue, 
                                       CompoundPtr compound) const
diff --git a/modules/conop/src/rule_based.hh b/modules/conop/src/rule_based.hh
index f014fe9d5fd6b9d4b9e02a050d3405bc688b9ec0..2b857398e3caa3d57ceda1397816b2c010b1148d 100644
--- a/modules/conop/src/rule_based.hh
+++ b/modules/conop/src/rule_based.hh
@@ -54,16 +54,11 @@ protected:
   virtual void DoProcess(DiagnosticsPtr diags, 
                          mol::EntityHandle ent) const;
 private:
-  void ProcessUnkResidue(DiagnosticsPtr diags,
-                         mol::ResidueHandle res) const;
-  void ProcessUnkAtoms(DiagnosticsPtr diags,
-                       mol::AtomHandleList unks) const;
   bool HasUnknownAtoms(mol::ResidueHandle residue, CompoundPtr compound) const;
   void ReorderAtoms(mol::ResidueHandle residue, CompoundPtr compound) const;
   void FillResidueProps(mol::ResidueHandle residue, CompoundPtr compound) const;
   void ConnectAtomsOfResidue(mol::ResidueHandle residue, CompoundPtr compound) const;
   void ConnectResidues(mol::ResidueHandle residue, mol::ResidueHandle next) const;
-  bool IsBondFeasible(const mol::AtomHandle&, const mol::AtomHandle&) const;
   mol::AtomHandle LocateAtom(const mol::AtomHandleList&, int ordinal) const;
   CompoundLibPtr lib_;
   bool fix_element_;