code: def morgan_fingerprint(
      df: pd.DataFrame,
      mols_column_name: str,
      radius: int = 3,
      nbits: int = 2048,
      kind: Literal["counts", "bits"] = "counts",
  ) -> pd.DataFrame:
      """Convert a column of RDKIT Mol objects into Morgan Fingerprints.
  
      Returns a new dataframe without any of the original data. This is
      intentional, as Morgan fingerprints are usually high-dimensional
      features.
  
      This method does not mutate the original DataFrame.
  
      Examples:
          Functional usage
  
          >>> import pandas as pd
          >>> import janitor.chemistry
          >>> df = pd.DataFrame({"smiles": ["O=C=O", "CCC(=O)O"]})
  
          - For "counts" kind
  
          >>> morgans = janitor.chemistry.morgan_fingerprint(
          ...     df=df.smiles2mol('smiles', 'mols'),
          ...     mols_column_name='mols',
          ...     radius=3,      # Defaults to 3
          ...     nbits=2048,    # Defaults to 2048
          ...     kind='counts'  # Defaults to "counts"
          ... )
          >>> set(morgans.iloc[0])
          {0.0, 1.0, 2.0}
  
          - For "bits" kind
  
          >>> morgans = janitor.chemistry.morgan_fingerprint(
          ...     df=df.smiles2mol('smiles', 'mols'),
          ...     mols_column_name='mols',
          ...     radius=3,      # Defaults to 3
          ...     nbits=2048,    # Defaults to 2048
          ...     kind='bits'    # Defaults to "counts"
          ...  )
          >>> set(morgans.iloc[0])
          {0.0, 1.0}
  
          Method chaining usage
  
          >>> import pandas as pd
          >>> import janitor.chemistry
          >>> df = pd.DataFrame({"smiles": ["O=C=O", "CCC(=O)O"]})
  
          - For "counts" kind
  
          >>> morgans = (
          ...     df.smiles2mol('smiles', 'mols')
          ...     .morgan_fingerprint(
          ...         mols_column_name='mols',
          ...         radius=3,      # Defaults to 3
          ...         nbits=2048,    # Defaults to 2048
          ...         kind='counts'  # Defaults to "counts"
          ...     )
          ... )
          >>> set(morgans.iloc[0])
          {0.0, 1.0, 2.0}
  
          - For "bits" kind
  
          >>> morgans = (
          ...     df
          ...     .smiles2mol('smiles', 'mols')
          ...     .morgan_fingerprint(
          ...         mols_column_name='mols',
          ...         radius=3,    # Defaults to 3
          ...         nbits=2048,  # Defaults to 2048
          ...         kind='bits'  # Defaults to "counts"
          ...     )
          ... )
          >>> set(morgans.iloc[0])
          {0.0, 1.0}
  
          If you wish to join the morgan fingerprints back into the original
          dataframe, this can be accomplished by doing a `join`,
          because the indices are preserved:
  
          >>> joined = df.join(morgans)
          >>> len(joined.columns)
          2050
  
      Args:
          df: A pandas DataFrame.
          mols_column_name: The name of the column that has the RDKIT
              mol objects
          radius: Radius of Morgan fingerprints.
          nbits: The length of the fingerprints.
          kind: Whether to return counts or bits.
  
      Raises:
          ValueError: If `kind` is not one of `"counts"` or `"bits"`.
  
      Returns:
          A new pandas DataFrame of Morgan fingerprints.
      """
      acceptable_kinds = ["counts", "bits"]
      if kind not in acceptable_kinds:
          raise ValueError(f"`kind` must be one of {acceptable_kinds}")
  
      if kind == "bits":
          fps = [
              GetMorganFingerprintAsBitVect(
                  m, radius, nbits, useChirality=True
              )
              for m in df[mols_column_name]
          ]
      elif kind == "counts":
          fps = [
              GetHashedMorganFingerprint(
                  m, radius, nbits, useChirality=True
              )
              for m in df[mols_column_name]
          ]
  
      np_fps = []
      for fp in fps:
          arr = np.zeros((1,))
          DataStructs.ConvertToNumpyArray(fp, arr)
          np_fps.append(arr)
      np_fps = np.vstack(np_fps)
      fpdf = pd.DataFrame(np_fps)
      fpdf.index = df.index
      return fpdf
  
file_path: pyjanitor/janitor/chemistry.py
imports: from typing import Hashable, Literal, Optional
  import numpy
  import pandas
  import pandas_flavor
  from .utils import deprecated_alias, import_message
label_desc: Use image node_id 2 for calling a global function with example usage: morgan_fingerprint(df, mols_column_name, radius, nbits, kind) and returns: fpdf