|
1 | 1 | import logging |
2 | 2 | import os.path |
3 | | -from concurrent import futures |
4 | | -from multiprocessing import cpu_count |
5 | 3 |
|
6 | 4 | import mrcfile |
7 | 5 | import numpy as np |
@@ -246,44 +244,46 @@ def _images(self, indices): |
246 | 244 | # Log the indices in case needed to debug a crash |
247 | 245 | logger.debug(f"Indices: {indices}") |
248 | 246 |
|
249 | | - def load_single_mrcs(filepath, indices): |
250 | | - arr = mrcfile.open(filepath, mode="r", permissive=True).data |
251 | | - # if the stack only contains one image, arr will have shape (resolution, resolution) |
252 | | - # the code below reshapes it to (1, resolution, resolution) |
253 | | - if len(arr.shape) == 2: |
254 | | - arr = arr.reshape((1,) + arr.shape) |
| 247 | + def _load_single_mrcs(filepath, indices): |
| 248 | + """ |
| 249 | + Local utility to wrap up loading a slice of MRC data. |
| 250 | +
|
| 251 | + :param filepath: String filepath to MRC file. |
| 252 | + :param indices: Requested indices from STAR file. |
| 253 | + :return: Slice of array data (as mmap). |
| 254 | + """ |
255 | 255 | # __mrc_index is the 1-based index of the particle in the stack |
256 | | - data = arr[self._metadata["__mrc_index"][indices] - 1, :, :] |
| 256 | + mrc_indices = self._metadata["__mrc_index"][indices] - 1 |
257 | 257 |
|
258 | | - return indices, data |
| 258 | + with mrcfile.mmap(filepath, mode="r", permissive=True) as fh: |
| 259 | + arr = fh.data |
| 260 | + # if the stack only contains one image, arr will have shape (resolution, resolution) |
| 261 | + # the code below reshapes it to (1, resolution, resolution) |
| 262 | + if len(arr.shape) == 2: |
| 263 | + arr = arr.reshape((1,) + arr.shape) |
| 264 | + data = arr[mrc_indices, :, :] |
259 | 265 |
|
260 | | - n_workers = self.n_workers |
261 | | - if n_workers < 0: |
262 | | - n_workers = cpu_count() - 1 |
| 266 | + return data |
263 | 267 |
|
| 268 | + # Array to hold requested data |
264 | 269 | im = np.empty( |
265 | 270 | (len(indices), self._original_resolution, self._original_resolution), |
266 | 271 | dtype=self.dtype, |
267 | 272 | ) |
268 | 273 |
|
269 | | - filepaths, filepath_indices = np.unique( |
| 274 | + # Map all requested indices to a set of files and images per file. |
| 275 | + requested_filepaths, requested_filepath_indices = np.unique( |
270 | 276 | self._metadata["__mrc_filepath"], return_inverse=True |
271 | 277 | ) |
272 | | - n_workers = min(n_workers, len(filepaths)) |
273 | | - |
274 | | - with futures.ThreadPoolExecutor(n_workers) as executor: |
275 | | - to_do = [] |
276 | | - for i, filepath in enumerate(filepaths): |
277 | | - this_filepath_indices = np.where(filepath_indices == i)[0] |
278 | | - future = executor.submit( |
279 | | - load_single_mrcs, filepath, this_filepath_indices |
280 | | - ) |
281 | | - to_do.append(future) |
282 | 278 |
|
283 | | - for future in futures.as_completed(to_do): |
284 | | - data_indices, data = future.result() |
285 | | - for idx, d in enumerate(data_indices): |
286 | | - im[np.where(indices == d)] = data[idx, :, :] |
| 279 | + # Loop over the requested files and load (slice) the requested images per file. |
| 280 | + for _i, _filepath in enumerate(requested_filepaths): |
| 281 | + _filepath_indices = np.where(requested_filepath_indices == _i)[0] |
| 282 | + _data = _load_single_mrcs(_filepath, _filepath_indices) |
| 283 | + |
| 284 | + # Pack this files data contribution into `im` array. |
| 285 | + for idx, d in enumerate(_filepath_indices): |
| 286 | + im[np.where(indices == d)] = _data[idx, :, :] |
287 | 287 |
|
288 | 288 | logger.debug(f"Loading {len(indices)} images complete") |
289 | 289 |
|
|
0 commit comments