code: def distribute(self, subjects, mask):
          
          if mask.ndim != 3:
              raise ValueError('mask should be a 3D array')
  
          for (idx, subj) in enumerate(subjects):
              if subj is not None:
                  if subj.ndim != 4:
                      raise ValueError('subjects[{}] must be 4D'.format(idx))
  
          self.mask = mask
          rank = self.comm.rank
  
          # Get/set ownership
          ownership = self._get_ownership(subjects)
          all_blocks = self._get_blocks(mask) if rank == 0 else None
          all_blocks = self.comm.bcast(all_blocks)
  
          # Divide data and mask
          splitsubj = [self._split_volume(s, all_blocks)
                       if s is not None else None
                       for s in subjects]
          submasks = self._split_volume(mask, all_blocks)
  
          # Scatter points, data, and mask
          self.blocks = self._scatter_list(all_blocks, 0)
          self.submasks = self._scatter_list(submasks,  0)
          self.subproblems = [self._scatter_list(s, ownership[s_idx])
                              for (s_idx, s) in enumerate(splitsubj)]
docs: Distribute data to MPI ranks
  
          Parameters
          ----------
  
          subjects : list of 4D arrays containing data for one or more subjects.
                Each entry of the list must be present on at most one rank,
                and the other ranks contain a "None" at this list location.
  
                For example, for 3 ranks you may lay out the data in the
                following manner:
  
                Rank 0: [Subj0, None, None]
                Rank 1: [None, Subj1, None]
                Rank 2: [None, None, Subj2]
  
                Or alternatively, you may lay out the data in this manner:
  
                Rank 0: [Subj0, Subj1, Subj2]
                Rank 1: [None, None, None]
                Rank 2: [None, None, None]
  
          mask: 3D array with "True" entries at active vertices