code: def downsample(self, factor):
      
      if int(factor) != factor or factor < 1:
        raise ValueError("Argument `factor` must be a positive integer greater than or equal to 1. Got: <{}>({})", type(factor), factor)
  
      paths = self.interjoint_paths()
  
      for i, path in enumerate(paths):
        paths[i] = np.concatenate(
          (path[0::factor, :], path[-1:, :]) # preserve endpoints
        )
  
      ds_skel = PrecomputedSkeleton.simple_merge(
        [ PrecomputedSkeleton.from_path(path) for path in paths ]
      ).consolidate()
      ds_skel.id = self.id
  
      # TODO: I'm sure this could be sped up if need be.
      index = {}
      for i, vert in enumerate(self.vertices):
        vert = tuple(vert)
        index[vert] = i
  
      for i, vert in enumerate(ds_skel.vertices):
        vert = tuple(vert)
        ds_skel.radii[i] = self.radii[index[vert]]
        ds_skel.vertex_types[i] = self.vertex_types[index[vert]]
  
      return ds_skel
docs: Compute a downsampled version of the skeleton by striding while 
      preserving endpoints.
  
      factor: stride length for downsampling the saved skeleton paths.
  
      Returns: downsampled PrecomputedSkeleton