| 799 | return assemblies, unique |
| 800 | |
| 801 | def assemble(self, chunk_size=1, n_processes=None): |
| 802 | self.assemblies = dict() |
| 803 | self.unique = dict() |
| 804 | # Spawning (rather than forking) multiple processes does not |
| 805 | # work nicely with the GUI or interactive sessions. |
| 806 | # In that case, we fall back to the serial assembly. |
| 807 | if chunk_size == 0 or multiprocessing.get_start_method() == "spawn": |
| 808 | for i, data_dict in enumerate(tqdm(self)): |
| 809 | assemblies, unique = self._assemble(data_dict, i) |
| 810 | if assemblies: |
| 811 | self.assemblies[i] = assemblies |
| 812 | if unique is not None: |
| 813 | self.unique[i] = unique |
| 814 | else: |
| 815 | global wrapped # Hack to make the function pickable |
| 816 | |
| 817 | def wrapped(i): |
| 818 | return i, self._assemble(self[i], i) |
| 819 | |
| 820 | n_frames = len(self.metadata["imnames"]) |
| 821 | with multiprocessing.Pool(n_processes) as p: |
| 822 | with tqdm(total=n_frames) as pbar: |
| 823 | for i, (assemblies, unique) in p.imap_unordered(wrapped, range(n_frames), chunksize=chunk_size): |
| 824 | if assemblies: |
| 825 | self.assemblies[i] = assemblies |
| 826 | if unique is not None: |
| 827 | self.unique[i] = unique |
| 828 | pbar.update() |
| 829 | |
| 830 | def from_pickle(self, pickle_path): |
| 831 | with open(pickle_path, "rb") as file: |