class_docstr: Small variation of S3DISOriginalFused that allows random sampling of spheres 
  within an Area during training and validation. Spheres have a radius of 2m. If sample_per_epoch is not specified, spheres
  are taken on a 2m grid.
  
  http://buildingparser.stanford.edu/dataset.html
  
  Parameters
  ----------
  root: str
      path to the directory where the data will be saved
  test_area: int
      number between 1 and 6 that denotes the area used for testing
  train: bool
      Is this a train split or not
  pre_collate_transform:
      Transforms to be applied before the data is assembled into samples (apply fusing here for example)
  keep_instance: bool
      set to True if you wish to keep instance data
  sample_per_epoch
      Number of spheres that are randomly sampled at each epoch (-1 for fixed grid)
  radius
      radius of each sphere
  pre_transform
  transform
  pre_filter
class_docstr_tok: ["Small","variation","of","S3DISOriginalFused","that","allows","random","sampling","of","spheres","within","an","Area","during","training","and","validation",".","Spheres","have","a","radius","of","2m",".","If","sample_per_epoch","is","not","specified",",","spheres","are","taken","on","a","2m","grid",".","http",":","\/\/buildingparser.stanford.edu\/dataset.html","Parameters","--","--","--","--","--","root",":","str","path","to","the","directory","where","the","data","will","be","saved","test_area",":","int","number","between","1","and","6","that","denotes","the","area","used","for","testing","train",":","bool","Is","this","a","train","split","or","not","pre_collate_transform",":","Transforms","to","be","applied","before","the","data","is","assembled","into","samples","(","apply","fusing","here","for","example",")","keep_instance",":","bool","set","to","True","if","you","wish","to","keep","instance","data","sample_per_epoch","Number","of","spheres","that","are","randomly","sampled","at","each","epoch","(","-1","for","fixed","grid",")","radius","radius","of","each","sphere","pre_transform","transform","pre_filter"]
code: def _get_random(self):
      # Random spheres biased towards getting more low frequency classes
      chosen_label = np.random.choice(
          self._labels, p=self._label_counts
      )
      valid_centres = self._centres_for_sampling[
          self._centres_for_sampling[:, 4] == chosen_label
      ]
      centre_idx = int(random.random() * (valid_centres.shape[0] - 1))
      centre = valid_centres[centre_idx]
      area_data = self._datas[centre[3].int()]
      sphere_sampler = cT.SphereSampling(
          self._radius, centre[:3], align_origin=False
      )
      return sphere_sampler(area_data)
  
imports: import os
  import os.path
  from itertools import repeat, product
  import numpy
  import h5py
  import torch
  import random
  import glob
  from plyfile import PlyData, PlyElement
  from torch_geometric.data import InMemoryDataset, Data, extract_zip, Dataset
  from torch_geometric.data.dataset import files_exist
  from torch_geometric.data import DataLoader
  from torch_geometric.datasets import S3DIS
  import torch_geometric.transforms
  import logging
  from sklearn.neighbors import NearestNeighbors, KDTree
  from tqdm.auto import tqdm
  import csv
  import pandas
  import pickle
  import gdown
  import shutil
  from torch_points3d.datasets.samplers import BalancedRandomSampler
  import torch_points3d.core.data_transform
  from torch_points3d.datasets.base_dataset import BaseDataset
label_desc: Use image node_id 7 for calling the S3DISSphere obj's underlying member method code with example usage: obj._get_random() and returns: sphere_sampler