class_docstr: "
  Abstract class for calculating features for mol/protein complexes.
class_docstr_tok: ["``","Abstract","class","for","calculating","features","for","mol\/protein","complexes","."]
docstr: Calculate features for mol/protein complexes.
  Parameters
  ----------
  datapoints: Iterable[Tuple[str, str]]
      List of filenames (PDB, SDF, etc.) for ligand molecules and proteins.
      Each element should be a tuple of the form (ligand_filename,
      protein_filename).
  
  Returns
  -------
  features: np.ndarray
      Array of features
docstr_tok: ["Calculate","features","for","mol\/protein","complexes",".","Parameters","--","--","--","--","--","datapoints",":","Iterable","[","Tuple","[","str",",","str","]","]","List","of","filenames","(","PDB",",","SDF",",","etc",".",")","for","ligand","molecules","and","proteins",".","Each","element","should","be","a","tuple","of","the","form","(","ligand_filename",",","protein_filename",")",".","Returns","--","--","--","-","features",":","np.ndarray","Array","of","features"]
code: def featurize(
      self,
      datapoints: Optional[Iterable[Tuple[str, str]]] = None,
      log_every_n: int = 100,
      **kwargs,
  ) -> np.ndarray:
      """
      Calculate features for mol/protein complexes.
      Parameters
      ----------
      datapoints: Iterable[Tuple[str, str]]
          List of filenames (PDB, SDF, etc.) for ligand molecules and proteins.
          Each element should be a tuple of the form (ligand_filename,
          protein_filename).
  
      Returns
      -------
      features: np.ndarray
          Array of features
      """
  
      if "complexes" in kwargs:
          datapoints = kwargs.get("complexes")
          raise DeprecationWarning(
              'Complexes is being phased out as a parameter, please pass "datapoints" instead.'
          )
      if not isinstance(datapoints, Iterable):
          datapoints = [cast(Tuple[str, str], datapoints)]
      features, failures, successes = [], [], []
      for idx, point in enumerate(datapoints):
          if idx % log_every_n == 0:
              logger.info("Featurizing datapoint %i" % idx)
          try:
              features.append(self._featurize(point, **kwargs))
              successes.append(idx)
          except:
              logger.warning(
                  "Failed to featurize datapoint %i. Appending empty array."
                  % idx
              )
              features.append(np.zeros(1))
              failures.append(idx)
  
      # Find a successful featurization
      try:
          i = np.argmax([f.shape[0] for f in features])
          dtype = features[i].dtype
          shape = features[i].shape
          dummy_array = np.zeros(shape, dtype=dtype)
      except AttributeError:
          dummy_array = features[successes[0]]
  
      # Replace failed featurizations with appropriate array
      for idx in failures:
          features[idx] = dummy_array
  
      return np.asarray(features, dtype=object)
  
imports: import inspect
  import logging
  import numpy
  from typing import Any, Dict, Iterable, Optional, Tuple, Union, cast
  from deepchem.utils import get_print_threshold
  from deepchem.utils.typing import PymatgenStructure
label_desc: Use image node_id 1 for calling the ComplexFeaturizer obj's underlying member method code with example usage: obj.featurize(datapoints, log_every_n) and returns: np