class_docstr: EditableModule is a base class to enable classes that it inherits be
  converted to pure functions for higher order derivatives purpose.
  
  Usage
  -----
  To use this class, the user must implement the ``getparamnames`` method
  which returns a list of tensor names that affect the output of the method
  with name indicated in ``methodname``.
  
  Used in:
  
  - Classes of Density Functional Theory (DFT).
  
  - It can also be used in other classes that need to be converted to pure
    functions for higher order derivatives purpose.
  
  Examples
  --------
  >>> import torch
  >>> from deepchem.utils.differentiation_utils import EditableModule
  >>> class A(EditableModule):
  ...     def __init__(self, a):
  ...         self.b = a*a
  ...
  ...     def mult(self, x):
  ...         return self.b * x
  ...
  ...     def getparamnames(self, methodname, prefix=""):
  ...         if methodname == "mult":
  ...             return [prefix+"b"]
  ...         else:
  ...             raise KeyError()
  >>> a = torch.tensor(2.0).requires_grad_()
  >>> x = torch.tensor(0.4).requires_grad_()
  >>> alpha = A(a)
  >>> alpha.mult(x)
  tensor(1.6000, grad_fn=<MulBackward0>)
  >>> alpha.getparamnames("mult")
  ['b']
  >>> alpha.assertparams(alpha.mult, x)
  "mult" method check done
docstr: This function perform checks if the getparams on the method returns
  the correct tensors
  
  Parameters
  ----------
  method: Callable
      The method of this class to be tested
  
  Raises
  ------
  KeyError
      If the method does not return the correct tensors.
docstr_tok: ["This","function","perform","checks","if","the","getparams","on","the","method","returns","the","correct","tensors","Parameters","--","--","--","--","--","method",":","Callable","The","method","of","this","class","to","be","tested","Raises","--","--","--","KeyError","If","the","method","does","not","return","the","correct","tensors","."]
code: def __assert_get_correct_params(self, method, *args, **kwargs):
      """This function perform checks if the getparams on the method returns
      the correct tensors
  
      Parameters
      ----------
      method: Callable
          The method of this class to be tested
  
      Raises
      ------
      KeyError
          If the method does not return the correct tensors.
  
      """
  
      methodname = method.__name__
      clsname = method.__self__.__class__.__name__
  
      # get all tensor parameters in the object
      all_params, all_names = _get_tensors(self)
  
      def _get_tensor_name(param):
          for i in range(len(all_params)):
              if id(all_params[i]) == id(param):
                  return all_names[i]
          return None
  
      # get the parameter tensors used in the operation and the tensors specified by the developer
      oper_names, oper_params = self.__list_operating_params(
          method, *args, **kwargs
      )
      user_names = self.getparamnames(method.__name__)
      user_params = [get_attr(self, name) for name in user_names]
      user_params_id = [id(p) for p in user_params]
      oper_params_id = [id(p) for p in oper_params]
      user_params_id_set = set(user_params_id)
      oper_params_id_set = set(oper_params_id)
  
      # check if the userparams contains non-tensor
      for i in range(len(user_params)):
          param = user_params[i]
          if (not isinstance(param, torch.Tensor)) or (
              isinstance(param, torch.Tensor)
              and param.dtype not in torch_float_type
          ):
              msg = (
                  "Parameter %s is a non-floating point tensor"
                  % user_names[i]
              )
              raise KeyError(msg)
  
      # check if there are missing parameters (present in operating params, but not in the user params)
      missing_names = []
      for i in range(len(oper_names)):
          if oper_params_id[i] not in user_params_id_set:
              # if oper_names[i] not in user_names:
              missing_names.append(oper_names[i])
      # if there are missing parameters, give a warning (because the program
      # can still run correctly, e.g. missing parameters are parameters that
      # are never set to require grad)
      if len(missing_names) > 0:
          msg = "getparams for %s.%s does not include: %s" % (
              clsname,
              methodname,
              ", ".join(missing_names),
          )
          warnings.warn(msg, stacklevel=3)
  
      # check if there are excessive parameters (present in the user params, but not in the operating params)
      excess_names = []
      for i in range(len(user_names)):
          if user_params_id[i] not in oper_params_id_set:
              # if user_names[i] not in oper_names:
              excess_names.append(user_names[i])
      # if there are excess parameters, give warnings
      if len(excess_names) > 0:
          msg = "getparams for %s.%s has excess parameters: %s" % (
              clsname,
              methodname,
              ", ".join(excess_names),
          )
          warnings.warn(msg, stacklevel=3)
  
imports: import inspect
  import warnings
  from abc import abstractmethod
  import copy
  import torch
  from typing import Sequence, Union, Dict, List, Callable, Any
  from deepchem.utils.attribute_utils import get_attr, set_attr, del_attr
label_desc: Use image node_id 10 for calling the EditableModule obj's underlying member method code with example usage: obj.__assert_get_correct_params(method) and returns: None, all_names