docstr: Returns mapping of sites from input to this object
  
  Pymatgen molecule_matcher does not work unfortunately as it needs to be
  a reasonably physical molecule.
  Here, the graph is constructed by connecting the nearest neighbor, and
  isomorphism is performed to find matches, then kabsch algorithm is
  performed to make sure it is a match. NetworkX is used for portability.
  
  Parameters
  ----------
  
  env : Dict[str, Any]
      dictionary that contains information of local environment of a
      site in datum. See _get_SiteEnvironments definition in the class
      _SiteEnvironments for what this variable should be.
  
  Returns
  -------
  dict : Dict[int, int]
      Atom mapping from Primitive cell to data point.
docstr_tok: ["Returns","mapping","of","sites","from","input","to","this","object","Pymatgen","molecule_matcher","does","not","work","unfortunately","as","it","needs","to","be","a","reasonably","physical","molecule",".","Here",",","the","graph","is","constructed","by","connecting","the","nearest","neighbor",",","and","isomorphism","is","performed","to","find","matches",",","then","kabsch","algorithm","is","performed","to","make","sure","it","is","a","match",".","NetworkX","is","used","for","portability",".","Parameters","--","--","--","--","--","env",":","Dict","[","str",",","Any","]","dictionary","that","contains","information","of","local","environment","of","a","site","in","datum",".","See","_get_SiteEnvironments","definition","in","the","class","_SiteEnvironments","for","what","this","variable","should","be",".","Returns","--","--","--","-","dict",":","Dict","[","int",",","int","]","Atom","mapping","from","Primitive","cell","to","data","point","."]
code: def get_mapping(self, env: Dict[str, Any]) -> Dict[int, int]:
      """
      Returns mapping of sites from input to this object
  
      Pymatgen molecule_matcher does not work unfortunately as it needs to be
      a reasonably physical molecule.
      Here, the graph is constructed by connecting the nearest neighbor, and
      isomorphism is performed to find matches, then kabsch algorithm is
      performed to make sure it is a match. NetworkX is used for portability.
  
      Parameters
      ----------
  
      env : Dict[str, Any]
          dictionary that contains information of local environment of a
          site in datum. See _get_SiteEnvironments definition in the class
          _SiteEnvironments for what this variable should be.
  
      Returns
      -------
      dict : Dict[int, int]
          Atom mapping from Primitive cell to data point.
      """
      try:
          import networkx.algorithms.isomorphism as iso
      except:
          raise ImportError(
              "This class requires networkx to be installed."
          )
      # construct graph
  
      G = self._construct_graph(env["pos"], env["sitetypes"])
      if len(self.G.nodes) != len(G.nodes):
          s = "Number of nodes is not equal.\n"
          raise ValueError(s)
      elif len(self.G.edges) != len(G.edges):
          logging.warning(
              "Expected the number of edges to be equal",
              len(self.G.edges),
              len(G.edges),
          )
          s = "Number of edges is not equal.\n"
          s += "- Is the data point's cell a redefined lattice of primitive cell?\n"
          s += "- If relaxed structure is used, you may want to check structure or increase Gatol\n"
          raise ValueError(s)
      GM = iso.GraphMatcher(self.G, G, self._nm, self._em)
      # Gets the isomorphic mapping. Also the most time consuming part of the code
      ams = list(GM.isomorphisms_iter())
  
      if not ams:
          s = "No isomorphism found.\n"
          s += "- Is the data point's cell a redefined lattice of primitive cell?\n"
          s += "- If relaxed structure is used, you may want to check structure or increase rtol\n"
          raise ValueError(s)
  
      rmsd = []
      for am in ams:  # Loop over isomorphism
          # reconstruct graph after alinging point order
          xyz = np.zeros((len(self.pos), 3))
          for i in am:
              xyz[i, :] = env["pos"][am[i], :]
          rotation, _ = Rotation.align_vectors(self.pos, xyz)
          R = rotation.as_matrix()
          # RMSD
          rmsd.append(
              np.sqrt(
                  np.mean(
                      np.linalg.norm(np.dot(self.pos, R) - xyz, axis=1)
                      ** 2
                  )
              )
          )
      mini = np.argmin(rmsd)
      minrmsd = rmsd[mini]
      if minrmsd < self.tol:
          return ams[mini]
      else:
          s = "No isomorphism found.\n"
          s += "-Consider increasing neighbor finding tolerance"
          raise ValueError(s)
  
imports: import numpy
  import logging
  from deepchem.feat import MaterialStructureFeaturizer
  from collections import defaultdict
  from typing import List, Dict, Tuple, DefaultDict, Any
  from deepchem.utils.typing import PymatgenStructure
  from deepchem.feat.graph_data import GraphData
  from scipy.spatial.distance import pdist, squareform, cdist
  from scipy.spatial.transform import Rotation
label_desc: Use image node_id 3 for calling the _SiteEnvironment obj's underlying member method code with example usage: obj.get_mapping(env) and returns: ams