class_docstr: Class for doing data splits based on the butina clustering of a bulk tanimoto
  fingerprint matrix.
class_docstr_tok: ["Class","for","doing","data","splits","based","on","the","butina","clustering","of","a","bulk","tanimoto","fingerprint","matrix","."]
docstr: Splits internal compounds into train and validation based on the butina
  clustering algorithm. This splitting algorithm has an O(N^2) run time, where N
  is the number of elements in the dataset. The dataset is expected to be a classification
  dataset.
  
  This algorithm is designed to generate validation data that are novel chemotypes.
  
  Note that this function entirely disregards the ratios for frac_train, frac_valid,
  and frac_test. Furthermore, it does not generate a test set, only a train and valid set.
  
  Setting a small cutoff value will generate smaller, finer clusters of high similarity,
  whereas setting a large cutoff value will generate larger, coarser clusters of low similarity.
docstr_tok: ["Splits","internal","compounds","into","train","and","validation","based","on","the","butina","clustering","algorithm",".","This","splitting","algorithm","has","an","O","(","N^2",")","run","time",",","where","N","is","the","number","of","elements","in","the","dataset",".","The","dataset","is","expected","to","be","a","classification","dataset",".","This","algorithm","is","designed","to","generate","validation","data","that","are","novel","chemotypes",".","Note","that","this","function","entirely","disregards","the","ratios","for","frac_train",",","frac_valid",",","and","frac_test",".","Furthermore",",","it","does","not","generate","a","test","set",",","only","a","train","and","valid","set",".","Setting","a","small","cutoff","value","will","generate","smaller",",","finer","clusters","of","high","similarity",",","whereas","setting","a","large","cutoff","value","will","generate","larger",",","coarser","clusters","of","low","similarity","."]
code: def split(
      self,
      dataset,
      frac_train=None,
      frac_valid=None,
      frac_test=None,
      log_every_n=1000,
      cutoff=0.18,
  ):
      """
      Splits internal compounds into train and validation based on the butina
      clustering algorithm. This splitting algorithm has an O(N^2) run time, where N
      is the number of elements in the dataset. The dataset is expected to be a classification
      dataset.
  
      This algorithm is designed to generate validation data that are novel chemotypes.
  
      Note that this function entirely disregards the ratios for frac_train, frac_valid,
      and frac_test. Furthermore, it does not generate a test set, only a train and valid set.
  
      Setting a small cutoff value will generate smaller, finer clusters of high similarity,
      whereas setting a large cutoff value will generate larger, coarser clusters of low similarity.
      """
      print("Performing butina clustering with cutoff of", cutoff)
      mols = []
      for ind, smiles in enumerate(dataset.ids):
          mols.append(Chem.MolFromSmiles(smiles))
      n_mols = len(mols)
      fps = [
          AllChem.GetMorganFingerprintAsBitVect(x, 2, 1024)
          for x in mols
      ]
  
      scaffold_sets = ClusterFps(fps, cutoff=cutoff)
      scaffold_sets = sorted(scaffold_sets, key=lambda x: -len(x))
  
      ys = dataset.y
      valid_inds = []
      for c_idx, cluster in enumerate(scaffold_sets):
          # for m_idx in cluster:
          valid_inds.extend(cluster)
          # continue until we find an active in all the tasks, otherwise we can't
          # compute a meaningful AUC
          # TODO (ytz): really, we want at least one active and inactive in both scenarios.
          # TODO (Ytz): for regression tasks we'd stop after only one cluster.
          active_populations = np.sum(ys[valid_inds], axis=0)
          if np.all(active_populations):
              print(
                  "# of actives per task in valid:", active_populations
              )
              print("Total # of validation points:", len(valid_inds))
              break
  
      train_inds = list(
          itertools.chain.from_iterable(scaffold_sets[c_idx + 1 :])
      )
      test_inds = []
  
      return train_inds, valid_inds, []
  
imports: from __future__ import print_function
  from __future__ import division
  from __future__ import unicode_literals
  import tempfile
  import numpy
  import itertools
  from rdkit import Chem
  from rdkit import DataStructs
  from rdkit.Chem import AllChem
  from rdkit.ML.Cluster import Butina
  import deepchem
  from deepchem.data import DiskDataset
  from deepchem.utils import ScaffoldGenerator
  from deepchem.utils.save import log
  from deepchem.data import NumpyDataset
  from deepchem.utils.save import load_data
label_desc: Use image node_id 1 for calling the ButinaSplitter obj's underlying member method code with example usage: obj.split(dataset, frac_train, frac_valid, frac_test, log_every_n, cutoff) and returns: train_inds,  valid_inds,  list