class_docstr: Localize hydrogen bonds between atoms in macromolecular complexes.
  
  Given a macromolecular complex made up of multiple
  constitutent molecules, compute hydrogen bonds between atoms
  in the macromolecular complex. For each atom, localize this
  hydrogen bond in the voxel in which it originated to create a
  local hydrogen bond array. Note that if atoms in two
  different voxels interact in a hydrogen bond, the interaction
  is double counted in both voxels.
  
  Let `voxels_per_edge = int(box_width/voxel_width)`.  Creates a
  tensor output of shape `(voxels_per_edge, voxels_per_edge,
  voxels_per_edge, 3)` (assuming the default for `distance_bins` which
  has 3 bins) for each macromolecular complex that counts the number
  of hydrogen bonds at each voxel.
class_docstr_tok: ["Localize","hydrogen","bonds","between","atoms","in","macromolecular","complexes",".","Given","a","macromolecular","complex","made","up","of","multiple","constitutent","molecules",",","compute","hydrogen","bonds","between","atoms","in","the","macromolecular","complex",".","For","each","atom",",","localize","this","hydrogen","bond","in","the","voxel","in","which","it","originated","to","create","a","local","hydrogen","bond","array",".","Note","that","if","atoms","in","two","different","voxels","interact","in","a","hydrogen","bond",",","the","interaction","is","double","counted","in","both","voxels",".","Let","`","voxels_per_edge","=","int","(","box_width\/voxel_width",")","`",".","Creates","a","tensor","output","of","shape","`","(","voxels_per_edge",",","voxels_per_edge",",","voxels_per_edge",",","3",")","`","(","assuming","the","default","for","`","distance_bins","`","which","has","3","bins",")","for","each","macromolecular","complex","that","counts","the","number","of","hydrogen","bonds","at","each","voxel","."]
docstr: Compute featurization for a single mol/protein complex
  
  Parameters
  ----------
  datapoint: Tuple[str, str]
      Filenames for molecule and protein.
code: def _featurize(self, datapoint, **kwargs):  # -> Optional[np.ndarray]:
      """
      Compute featurization for a single mol/protein complex
  
      Parameters
      ----------
      datapoint: Tuple[str, str]
          Filenames for molecule and protein.
      """
      if "complex" in kwargs:
          datapoint = kwargs.get("complex")
          raise DeprecationWarning(
              'Complex is being phased out as a parameter, please pass "datapoint" instead.'
          )
      try:
          fragments = rdkit_utils.load_complex(
              datapoint, add_hydrogens=False
          )
  
      except MoleculeLoadException:
          logger.warning(
              "This molecule cannot be loaded by Rdkit. Returning None"
          )
          return None
      pairwise_features = []
      # We compute pairwise contact fingerprints
      centroid = compute_contact_centroid(fragments, cutoff=self.cutoff)
      if self.reduce_to_contacts:
          fragments = reduce_molecular_complex_to_contacts(
              fragments, self.cutoff
          )
      for frag1_ind, frag2_ind in itertools.combinations(
          range(len(fragments)), 2
      ):
          frag1, frag2 = fragments[frag1_ind], fragments[frag2_ind]
          distances = compute_pairwise_distances(frag1[0], frag2[0])
          frag1_xyz = subtract_centroid(frag1[0], centroid)
          frag2_xyz = subtract_centroid(frag2[0], centroid)
          xyzs = [frag1_xyz, frag2_xyz]
          # rdks = [frag1[1], frag2[1]]
          pairwise_features.append(
              np.concatenate(
                  [
                      sum(
                          [
                              voxelize(
                                  convert_atom_pair_to_voxel,
                                  hash_function=None,
                                  box_width=self.box_width,
                                  voxel_width=self.voxel_width,
                                  coordinates=xyz,
                                  feature_list=hbond_list,
                                  nb_channel=1,
                              )
                              for xyz in xyzs
                          ]
                      )
                      for hbond_list in compute_hydrogen_bonds(
                          frag1,
                          frag2,
                          distances,
                          self.distance_bins,
                          self.angle_cutoffs,
                      )
                  ],
                  axis=-1,
              )
          )
      # Features are of shape (voxels_per_edge, voxels_per_edge, voxels_per_edge, 1) so we should concatenate on the last axis.
      return np.concatenate(pairwise_features, axis=-1)
  
imports: import itertools
  import logging
  import numpy
  from deepchem.utils import rdkit_utils
  from deepchem.feat import ComplexFeaturizer
  from deepchem.utils.voxel_utils import voxelize
  from deepchem.utils.voxel_utils import convert_atom_to_voxel
  from deepchem.utils.voxel_utils import convert_atom_pair_to_voxel
  from deepchem.utils.noncovalent_utils import compute_salt_bridges
  from deepchem.utils.noncovalent_utils import compute_binding_pocket_cation_pi
  from deepchem.utils.noncovalent_utils import compute_pi_stack
  from deepchem.utils.noncovalent_utils import compute_hydrogen_bonds
  from deepchem.utils.rdkit_utils import MoleculeLoadException
  from deepchem.utils.rdkit_utils import compute_contact_centroid
  from deepchem.utils.geometry_utils import compute_pairwise_distances
  from deepchem.utils.geometry_utils import subtract_centroid
  from deepchem.utils.fragment_utils import get_partial_charge
  from deepchem.utils.fragment_utils import reduce_molecular_complex_to_contacts
  from typing import List, Tuple, Optional
label_desc: Use image node_id 2 for calling the HydrogenBondVoxelizer obj's underlying member method code with example usage: obj._featurize(datapoint) and returns: np, None