## selection.debug_function() — test code self-consistency

`debug_function(residue_span_range=(0, 99999), debug_function_cutoff=(0.01, 0.001, 0.1), detailed_debugging=False, schedule_scale=None, edat=None)`

Output:
  n_exceed

> This command checks the self-consistency of the code for the objective function and its derivatives by calculating and comparing numeric and analytical derivatives. All the parameters influencing the evaluation of the molecular pdf are also relevant (see selection.energy()). The derivative is reported if both the absolute difference and the fractional difference between the two kinds of evaluations exceed debug_function_cutoff[0] and debug_function_cutoff[1], respectively. This command returns n_exceed, the number of such reported differences.

> The scaling factors for the physical restraint types are given by schedule_scale. This allows some restraints to be turned off (scaled to zero) for the purpose of this test, if required.

> When detailed_debugging is `True`, the analytic and numeric derivatives of each restraint with respect to atomic positions are also compared for the atoms ‘violated’ by the whole molecular pdf. The absolute cutoff for writing out the discrepancies is scaled by debug_function_cutoff[2]; the relative cutoff remains the same as before.

Example: examples/scoring/debug_function.py

      # Example for: selection.debug_function()

      # This will use the MODELLER automodel class to construct homology
      # restraints for 1fas. It will then use model.debug_function() to test
      # the source code for the function and derivatives calculation
      # by comparing analytical and numerical first derivatives (note that
      # automodel is a derived class of model, so all 'model' methods will work
      # on 'automodel'). Some discrepancies may be reported but ignore them here.

      from modeller import *
      from modeller.automodel import *    # Load the automodel class

      log.verbose()
      env = environ()
      env.io.atom_files_directory = ['../atom_files']

      a = automodel(env, alnfile = 'debug_function.ali',
                    knowns  = ('2ctx', '2nbt'), sequence = '1fas')
      a.spline_on_site = False
      a.make(exit_stage=1)

      # Test on all atoms
      atmsel = selection(a)

      # To assign 0 weights to restraints whose numerical derivatives
      # code does not work (i.e., splines for angles and dihedrals):
      scal = physical.values(default=1.0, lennard_jones=0, coulomb=0, h_bond=0,
                             phi_dihedral=0, psi_dihedral=0, omega_dihedral=0,
                             chi1_dihedral=0, chi2_dihedral=0, chi3_dihedral=0,
                             chi4_dihedral=0, disulfide_angle=0,
                             disulfide_dihedral=0, chi5_dihedral=0)
      atmsel.energy(output='SHORT', schedule_scale=scal)
      atmsel.debug_function(debug_function_cutoff=(15.00, 0.10, 0.1),
                            detailed_debugging=True, schedule_scale=scal)