docs: def merge_units(self, unit_ids):
          '''This function merges two roots from the curation tree according to the given unit_ids. It creates a new unit_id and root
          that has the merged roots as children.
  
          Parameters
          ----------
          unit_ids: list
              The unit ids to be merged
          '''
          root_ids = []
          for i in range(len(self._roots)):
              root_id = self._roots[i].unit_id
              root_ids.append(root_id)
  
          indices_to_be_deleted = []
          if(set(unit_ids).issubset(set(root_ids)) and len(unit_ids) > 1):
              #Find all unique feature names and create all feature lists
              all_feature_names = []
              for unit_id in unit_ids:
                  feature_names = self.get_unit_spike_feature_names(unit_id)
                  all_feature_names.append(feature_names)
  
              shared_feature_names = set(all_feature_names[0])
              for feature_names in all_feature_names[1:]:
                  shared_feature_names.intersection_update(feature_names)
              shared_feature_names = list(shared_feature_names)
              shared_features = []
              for i in range(len(shared_feature_names)):
                  shared_features.append([])
  
              new_root_id = max(self._all_ids)+1
              self._all_ids.append(new_root_id)
              new_root = Unit(new_root_id)
              all_spike_trains = []
              for unit_id in unit_ids:
                  root_index = root_ids.index(unit_id)
                  new_root.add_child(self._roots[root_index])
                  all_spike_trains.append(self._roots[root_index].get_spike_train())
                  for i, feature_name in enumerate(shared_feature_names):
                      features = self.get_unit_spike_features(unit_id, feature_name)
                      shared_features[i].append(features)
                  del self._unit_features[unit_id]
                  self._roots[root_index].set_spike_train(np.asarray([])) #clear spiketrain
                  indices_to_be_deleted.append(root_index)
  
              all_spike_trains = np.concatenate(all_spike_trains)
              sort_indices = np.argsort(all_spike_trains)
              new_root.set_spike_train(np.asarray(all_spike_trains)[sort_indices])
              del all_spike_trains
              self._roots = [self._roots[i] for i,_ in enumerate(root_ids) if i not in indices_to_be_deleted]
              self._roots.append(new_root)
              for i, feature_name in enumerate(shared_feature_names):
                  self.set_unit_spike_features(new_root_id, feature_name, np.concatenate(shared_features[i])[sort_indices])
          else:
              raise ValueError(str(unit_ids) + " has one or more invalid unit ids")