def lsq6_pipeline(options): # TODO could also allow pluggable pipeline parts e.g. LSQ6 could be substituted out for the modified LSQ6 # for the kidney tips, etc... output_dir = options.application.output_directory pipeline_name = options.application.pipeline_name # TODO this is tedious and annoyingly similar to the registration chain and MBM ... lsq6_dir = os.path.join(output_dir, pipeline_name + "_lsq6") imgs = get_imgs(options.application) s = Stages() # FIXME: why do we have to call registration_targets *outside* of lsq6_nuc_inorm? is it just because of the extra # options required? targets = s.defer( registration_targets(lsq6_conf=options.lsq6, app_conf=options.application, reg_conf=options.registration, first_input_file=imgs[0].path)) # TODO this is quite tedious and duplicates stuff in the registration chain ... resolution = (options.registration.resolution or get_resolution_from_file( targets.registration_standard.path)) # This must happen after calling registration_targets otherwise it will resample to options.registration.resolution options.registration = options.registration.replace(resolution=resolution) lsq6_result = s.defer( lsq6_nuc_inorm(imgs=imgs, resolution=resolution, registration_targets=targets, lsq6_dir=lsq6_dir, lsq6_options=options.lsq6)) return Result(stages=s, output=lsq6_result)
def asymmetry_pipeline(options): output_dir = options.application.output_directory pipeline_name = options.application.pipeline_name processed_dir = os.path.join(output_dir, pipeline_name + "_processed") s = Stages() #imgs_ = [MincAtom(f, pipeline_sub_dir=processed_dir) for f in options.application.files] imgs_ = get_imgs(options.application) check_MINC_input_files([img.path for img in imgs_]) imgs = pd.Series(imgs_, index=[img.filename_wo_ext for img in imgs_]) flipped_imgs = imgs.apply(lambda img: s.defer(volflip(img)) ) # TODO add flags to control flip axis ... # TODO ugly - MincAtom API should allow this somehow without mutation (also, how to pass into `volflip`, etc.?) for f_i in flipped_imgs: f_i.output_sub_dir += "_flipped" check_MINC_input_files(imgs.apply(lambda img: img.path)) grouped_files_df = pd.DataFrame({ 'file': pd.concat([imgs, flipped_imgs]) }).assign(group=lambda df: df.index) two_level_result = s.defer(two_level(grouped_files_df, options=options)) return Result(stages=s, output=two_level_result)
def asymmetry_pipeline(options): output_dir = options.application.output_directory pipeline_name = options.application.pipeline_name processed_dir = os.path.join(output_dir, pipeline_name + "_processed") s = Stages() #imgs_ = [MincAtom(f, pipeline_sub_dir=processed_dir) for f in options.application.files] imgs_ = get_imgs(options.application) check_MINC_input_files([img.path for img in imgs_]) imgs = pd.Series(imgs_, index=[img.filename_wo_ext for img in imgs_]) flipped_imgs = imgs.apply(lambda img: s.defer(volflip(img))) # TODO add flags to control flip axis ... # TODO ugly - MincAtom API should allow this somehow without mutation (also, how to pass into `volflip`, etc.?) for f_i in flipped_imgs: f_i.output_sub_dir += "_flipped" check_MINC_input_files(imgs.apply(lambda img: img.path)) grouped_files_df = pd.DataFrame({'file' : pd.concat([imgs, flipped_imgs])}).assign(group=lambda df: df.index) two_level_result = s.defer(two_level(grouped_files_df, options=options)) return Result(stages=s, output=two_level_result)
def lsq6_pipeline(options): # TODO could also allow pluggable pipeline parts e.g. LSQ6 could be substituted out for the modified LSQ6 # for the kidney tips, etc... output_dir = options.application.output_directory pipeline_name = options.application.pipeline_name # TODO this is tedious and annoyingly similar to the registration chain and MBM ... lsq6_dir = os.path.join(output_dir, pipeline_name + "_lsq6") processed_dir = os.path.join(output_dir, pipeline_name + "_processed") imgs = get_imgs(options.application) s = Stages() # TODO this is quite tedious and duplicates stuff in the registration chain ... resolution = (options.registration.resolution or get_resolution_from_file( s.defer(registration_targets(lsq6_conf=options.lsq6, app_conf=options.application, reg_conf=options.registration)).registration_standard.path)) # FIXME: why do we have to call registration_targets *outside* of lsq6_nuc_inorm? is it just because of the extra # options required? targets = s.defer(registration_targets(lsq6_conf=options.lsq6, app_conf=options.application, reg_conf=options.registration, first_input_file=imgs[0])) # This must happen after calling registration_targets otherwise it will resample to options.registration.resolution options.registration = options.registration.replace(resolution=resolution) lsq6_result = s.defer(lsq6_nuc_inorm(imgs=imgs, resolution=resolution, registration_targets=targets, lsq6_dir=lsq6_dir, lsq6_options=options.lsq6)) return Result(stages=s, output=lsq6_result)
def NLIN_pipeline(options): # if options.application.files is None: # raise ValueError("Please, some files! (or try '--help')") # TODO make a util procedure for this output_dir = options.application.output_directory pipeline_name = options.application.pipeline_name # TODO this is tedious and annoyingly similar to the registration chain and MBM and LSQ6 ... processed_dir = os.path.join(output_dir, pipeline_name + "_processed") nlin_dir = os.path.join(output_dir, pipeline_name + "_nlin") resolution = (options.registration.resolution # TODO does using the finest resolution here make sense? or min([get_resolution_from_file(f) for f in options.application.files])) imgs = get_imgs(options.application) # imgs = [MincAtom(f, pipeline_sub_dir=processed_dir) for f in options.application.files] # determine NLIN settings by overriding defaults with # any settings present in protocol file, if it exists # could add a hook to print a message announcing completion, output files, # add more stages here to make a CSV initial_target_mask = MincAtom(options.nlin.target_mask) if options.nlin.target_mask else None initial_target = MincAtom(options.nlin.target, mask=initial_target_mask) full_hierarchy = get_nonlinear_configuration_from_options(nlin_protocol=options.nlin.nlin_protocol, reg_method=options.nlin.reg_method, file_resolution=resolution) s = Stages() nlin_result = s.defer(nlin_build_model(imgs, initial_target=initial_target, conf=full_hierarchy, nlin_dir=nlin_dir)) # TODO return these? inverted_xfms = [s.defer(invert_xfmhandler(xfm)) for xfm in nlin_result.output] if options.stats.calc_stats: # TODO: put the stats part behind a flag ... determinants = [s.defer(determinants_at_fwhms( xfm=inv_xfm, inv_xfm=xfm, blur_fwhms=options.stats.stats_kernels)) for xfm, inv_xfm in zip(nlin_result.output, inverted_xfms)] return Result(stages=s, output=Namespace(nlin_xfms=nlin_result, avg_img=nlin_result.avg_img, determinants=determinants)) else: # there's no consistency in what gets returned, yikes ... return Result(stages=s, output=Namespace(nlin_xfms=nlin_result, avg_img=nlin_result.avg_img))
def stage_embryos_pipeline(options): s = Stages() imgs = get_imgs(options.application) rough_volume_imgs = get_volume_estimate(imgs) imgs_and_rough_volume = pd.DataFrame({"mincatom" : imgs, "rough_volume" : pd.Series(rough_volume_imgs, dtype=float)}) check_MINC_input_files([img.path for img in imgs]) output_directory = options.application.output_directory output_sub_dir = os.path.join(output_directory, options.application.pipeline_name + "_4D_atlas") time_points_in_4D_atlas = instances_in_4D_atlas_from_csv(options.staging.staging.csv_4D, output_sub_dir) # we can use the resolution of one of the time points in the 4D atlas # for all the registrations that will be run. resolution = get_resolution_from_file(time_points_in_4D_atlas.loc[0]["mincatom"].orig_path) print(options.staging.lsq12) lsq12_conf = get_linear_configuration_from_options(options.staging.lsq12, transform_type=LinearTransType.lsq12, file_resolution=resolution) nlin_component = get_nonlinear_component(options.staging.nlin.reg_method) # match each of the embryos individually for i in range(imgs_and_rough_volume.shape[0]): s.defer(match_embryo_to_4D_atlas(imgs_and_rough_volume.loc[i], time_points_in_4D_atlas, lsq6_conf=options.staging.lsq6, lsq12_conf=lsq12_conf, nlin_module=nlin_component, resolution=resolution, nlin_options=options.staging.nlin)) return Result(stages=s, output=None)
def mbm_pipeline(options: MBMConf): s = Stages() imgs = get_imgs(options.application) check_MINC_input_files([img.path for img in imgs]) output_dir = options.application.output_directory mbm_result = s.defer( mbm(imgs=imgs, options=options, prefix=options.application.pipeline_name, output_dir=output_dir)) if options.mbm.common_space.do_common_space_registration: s.defer(common_space(mbm_result, options)) # create useful CSVs (note the files listed therein won't yet exist ...): transforms = (mbm_result.xfms.assign( native_file=lambda df: df.rigid_xfm.apply(lambda x: x.source), lsq6_file=lambda df: df.lsq12_nlin_xfm.apply(lambda x: x.source), lsq6_mask_file=lambda df: df.lsq12_nlin_xfm.apply( lambda x: x.source.mask if x.source.mask else ""), nlin_file=lambda df: df.lsq12_nlin_xfm.apply(lambda x: x.resampled), nlin_mask_file=lambda df: df.lsq12_nlin_xfm.apply( lambda x: x.resampled.mask if x.resampled.mask else ""), common_space_file=lambda df: df.xfm_to_common.apply(lambda x: x. resampled) if options.mbm.common_space.do_common_space_registration else None ).applymap(maybe_deref_path).drop( ["common_space_file"] if not options.mbm.common_space.do_common_space_registration else [], axis=1)) transforms.to_csv("transforms.csv", index=False) determinants = (mbm_result.determinants.drop( ["full_det", "nlin_det"], axis=1).applymap(maybe_deref_path)) determinants.to_csv("determinants.csv", index=False) analysis = (transforms.merge(determinants, left_on="lsq12_nlin_xfm", right_on="inv_xfm", how='inner').drop(["xfm", "inv_xfm"], axis=1)) if options.mbm.segmentation.run_maget: maget_df = pd.DataFrame( data={ 'label_file': [result.labels.path for result in mbm_result.maget_result], 'native_file': [result.orig_path for result in mbm_result.maget_result] }) analysis = analysis.merge(maget_df, on="native_file") if options.application.files: analysis.to_csv("analysis.csv", index=False) elif options.application.csv_file: csv_file = ( pd.read_csv(options.application.csv_file).assign( native_file=lambda df: df.file.apply( # TODO this is duplicating the logic in get_imgs - fix lambda fp: os.path.join( os.path.dirname(options.application.csv_file), fp) if not options.application.csv_paths_relative_to_wd else fp ).apply(os.path.normpath))) csv_file.merge(analysis, on="native_file").to_csv("analysis.csv", index=False) # # TODO moved here from inside `mbm` for now ... does this make most sense? # if options.mbm.segmentation.run_maget: # import copy # maget_options = copy.deepcopy(options) #Namespace(maget=options) # #maget_options # #maget_options.maget = maget_options.mbm # #maget_options.execution = options.execution # #maget_options.application = options.application # maget_options.application.output_directory = os.path.join(options.application.output_directory, "segmentation") # maget_options.maget = options.mbm.maget # # fixup_maget_options(maget_options=maget_options.maget, # nlin_options=maget_options.mbm.nlin, # lsq12_options=maget_options.mbm.lsq12) # del maget_options.mbm # # # #def with_new_output_dir(img : MincAtom): # #img = copy.copy(img) # #img.pipeline_sub_dir = img.pipeline_sub_dir + img.output_dir # #img. # #return img.newname_with_suffix(suffix="", subdir="segmentation") # # s.defer(maget([xfm.resampled for _ix, xfm in mbm_result.xfms.rigid_xfm.iteritems()], # options=maget_options, # prefix="%s_MAGeT" % prefix, # output_dir=os.path.join(options.application.output_directory, prefix + "_processed"))) return Result(stages=s, output=mbm_result)
def NLIN_pipeline(options): output_dir = options.application.output_directory pipeline_name = options.application.pipeline_name # TODO this is tedious and annoyingly similar to the registration chain and MBM and LSQ6 ... processed_dir = os.path.join(output_dir, pipeline_name + "_processed") nlin_dir = os.path.join(output_dir, pipeline_name + "_nlin") resolution = ( options.registration. resolution # TODO does using the finest resolution here make sense? or min( [get_resolution_from_file(f) for f in options.application.files])) imgs = get_imgs(options.application) initial_target_mask = MincAtom( options.nlin.target_mask) if options.nlin.target_mask else None initial_target = MincAtom(options.nlin.target, mask=initial_target_mask) nlin_module = get_nonlinear_component(reg_method=options.nlin.reg_method) nlin_build_model_component = get_model_building_procedure( options.nlin.reg_strategy, reg_module=nlin_module) nlin_conf = (nlin_build_model_component.parse_build_model_protocol( options.nlin.nlin_protocol, resolution=resolution) if options.nlin.nlin_protocol is not None else nlin_build_model_component.get_default_build_model_conf( resolution=resolution)) s = Stages() nlin_result = s.defer( nlin_build_model_component.build_model( imgs=imgs, initial_target=initial_target, conf=nlin_conf, nlin_dir=nlin_dir, use_robust_averaging=options.nlin.use_robust_averaging, nlin_prefix="")) inverted_xfms = [ s.defer(invert_xfmhandler(xfm)) for xfm in nlin_result.output ] if options.stats.calc_stats: determinants = s.defer( determinants_at_fwhms(xfms=inverted_xfms, inv_xfms=nlin_result.output, blur_fwhms=options.stats.stats_kernels)) return Result(stages=s, output=Namespace(nlin_xfms=nlin_result, avg_img=nlin_result.avg_img, determinants=determinants)) else: # there's no consistency in what gets returned, yikes ... return Result(stages=s, output=Namespace(nlin_xfms=nlin_result, avg_img=nlin_result.avg_img))