def extract_image_set(image_files, out_dir, date, age, plate_params, ignore_previous=False): """Find wells in a set of scanner images and extract each well into a separate image for further processing. Parameters: image_files: list of paths to a set of images. out_dir: path to write out the extracted images and metadata. date: date object referring to image scan date age: age in days of the worms in these images plate_params: configuration information for extracting wells from the plates. This must be a parameter dictionary suitable to pass to extract_wells.extract_wells() ignore_previous: if False, and stored results already exist, skip processing """ out_dir = pathlib.Path(out_dir) metadata = out_dir / 'metadata.pickle' if metadata.exists() and not ignore_previous: return images = [] print('extracting images for {}'.format(out_dir)) well_mask = freeimage.read(str(out_dir.parent / 'well_mask.png')) > 0 for image_file in image_files: image = freeimage.read(image_file) if image.dtype == numpy.uint16: image = (image >> 8).astype(numpy.uint8) images.append(image) well_names, well_images, well_centroids = extract_wells.extract_wells(images, well_mask, **plate_params) well_dir = util.get_dir(out_dir / 'well_images') for well_name, well_image_set in zip(well_names, well_images): for i, image in enumerate(well_image_set): freeimage.write(image, str(well_dir/well_name)+'-{}.png'.format(i)) util.dump(metadata, date=date, age=age, well_names=well_names, well_centroids=well_centroids)
def process_image_dir(in_dir, out_dir, age_at_first_scan, name_params, plate_params, score_params, re_extract=False, re_score=False, max_workers=None): """Extract well images from scanned plate images and score worm movement. Parameters: in_dir: path to directory of scanned images. out_dir: path to write out the extracted images and metadata. age_at_first_scan: age in days of the first image scan in in_dir name_params: information for finding image dates from file names: a dict with keys 'image_glob', 'date_regex', and 'date_format', as per extract_well_images() plate_params: configuration information for extracting wells from the plates. This must be a parameter dictionary suitable to pass to extract_wells.extract_wells() score_params: configuration information for scoring wells for movement. This must be a parameter dictionary suitable to pass to score_wells.score_wells() re_extract: if True, don't skip well-image extraction even if there are existing images. re_score: if True, don't skip scoring well images even if there are existing scores. re_extract implies re_score. If the former is True, scoring will be re-done even if re_score is False. max_workers: maximum number of image-extraction jobs to run in parallel. If None, then use all CPUs that the machine has. For debugging, use 1. Returns: whether any of the jobs caused an error. """ out_dir = util.get_dir(out_dir) image_sets = parse_inputs(in_dir, **name_params) dates = sorted(image_sets.keys()) make_well_mask(out_dir, image_sets[dates[0]][0], ignore_previous=re_extract) # maks mask from first image on first day -- least junk-filled runner = BackgroundRunner(max_workers) if re_extract: re_score = True for date in dates: out_dir_for_date = out_dir / date.isoformat() age = (date - dates[0]).days + age_at_first_scan image_files = image_sets[date] runner.submit(process_image_set, image_files, out_dir_for_date, date, age, plate_params, score_params, re_extract, re_score) results, was_error, error_indices, cancelled_indices = runner.wait() for i in error_indices: print("Error processing images for date {}:".format(dates[i])) print(results[i]) if not was_error: aggregate_scores(out_dir) return was_error