code: def alignProcrustes(sources, rigid=False):
      
      group = vtk.vtkMultiBlockDataGroupFilter()
      for source in sources:
          if sources[0].N() != source.N():
              vc.printc("~times Procrustes error in align():", c=1)
              vc.printc(" sources have different nr of points", c=1)
              exit(0)
          group.AddInputData(source.polydata())
      procrustes = vtk.vtkProcrustesAlignmentFilter()
      procrustes.StartFromCentroidOn()
      procrustes.SetInputConnection(group.GetOutputPort())
      if rigid:
          procrustes.GetLandmarkTransform().SetModeToRigidBody()
      procrustes.Update()
  
      acts = []
      for i, s in enumerate(sources):
          poly = procrustes.GetOutput().GetBlock(i)
          actor = Actor(poly)
          actor.SetProperty(s.GetProperty())
          acts.append(actor)
      assem = Assembly(acts)
      assem.info["transform"] = procrustes.GetLandmarkTransform()
      return assem
docs: Return an ``Assembly`` of aligned source actors with
      the `Procrustes` algorithm. The output ``Assembly`` is normalized in size.
  
      `Procrustes` algorithm takes N set of points and aligns them in a least-squares sense
      to their mutual mean. The algorithm is iterated until convergence,
      as the mean must be recomputed after each alignment.
  
      :param bool rigid: if `True` scaling is disabled.
  
      .. hint:: |align3| |align3.py|_