class_docstr: implementation of get_fragment and get_name to avoid repetitions
docstr: same pairs for self supervised learning
docstr_tok: ["same","pairs","for","self","supervised","learning"]
code: def unsupervised_preprocess(self, data_source_o, data_target_o):
      """
      same pairs for self supervised learning
      """
      len_col = 0
  
      while len_col < self.min_points:
          # choose only one data augmentation randomly in the ss_transform (usually a crop)
          if self.ss_transform is not None:
              n1 = np.random.randint(
                  0, len(self.ss_transform.transforms)
              )
              t1 = self.ss_transform.transforms[n1]
              n2 = np.random.randint(
                  0, len(self.ss_transform.transforms)
              )
              t2 = self.ss_transform.transforms[n2]
              data_source = t1(data_source_o.clone())
              data_target = t2(data_target_o.clone())
          else:
              data_source = data_source_o
              data_target = data_target_o
          pos = data_source.pos
          i = torch.randint(0, len(pos), (1,))
          size_block = (
              random.random()
              * (self.max_size_block - self.min_size_block)
              + self.min_size_block
          )
          point = pos[i].view(1, 3)
          ind, dist = ball_query(
              point, pos, radius=size_block, max_num=-1, mode=1
          )
          _, col = ind[dist[:, 0] > 0].t()
          ind_t, dist_t = ball_query(
              data_target.pos,
              pos[col],
              radius=self.max_dist_overlap,
              max_num=1,
              mode=1,
          )
          col_target, ind_col = ind_t[dist_t[:, 0] > 0].t()
          col = col[ind_col]
          new_pair = torch.stack((col, col_target)).T
          len_col = len(new_pair)
      return data_source, data_target, new_pair
  
imports: import numpy
  import os.path
  import random
  import torch
  import logging
  from torch_geometric.data import Data
  from torch_points_kernels.points_cpu import ball_query
  from functools import partial
  from torch_points3d.core.data_transform import MultiScaleTransform
  from torch_points3d.core.data_transform import PairTransform
  from torch_points3d.datasets.registration.pair import DensePairBatch
  from torch_points3d.utils.enums import ConvolutionFormat
  from torch_points3d.utils.config import ConvolutionFormatFactory
  from torch_points3d.datasets.registration.pair import PairMultiScaleBatch, PairBatch
  from torch_points3d.datasets.registration.pair import Pair, MultiScalePair
  from torch_points3d.datasets.registration.utils import tracked_matches
  from torch_points3d.datasets.registration.utils import compute_overlap_and_matches
  from torch_points3d.datasets.registration.utils import fps_sampling
  from torch_points3d.datasets.base_dataset import BaseDataset
  from torch_points3d.metrics.registration_tracker import PatchRegistrationTracker
  from torch_points3d.metrics.registration_tracker import FragmentRegistrationTracker
label_desc: Use image node_id 2 for calling the GeneralFragment obj's underlying member method code with example usage: obj.unsupervised_preprocess(data_source_o, data_target_o) and returns: data_source,  data_target,  new_pair