def get_tractography_plan(custom_tractography_bids_filters, tracking_params): tractography_tasks = with_name([ export_seed_mask, export_stop_mask, streamlines]) if custom_tractography_bids_filters is not None: tractography_tasks["streamlines_res"] = custom_tractography stop_mask = tracking_params['stop_mask'] if tracking_params["tracker"] == "pft": probseg_funcs = stop_mask.get_mask_getter() tractography_tasks["wm_res"] = pimms.calc("pve_wm")(probseg_funcs[0]) tractography_tasks["gm_res"] = pimms.calc("pve_gm")(probseg_funcs[1]) tractography_tasks["csf_res"] = pimms.calc("pve_csf")(probseg_funcs[2]) tractography_tasks["export_stop_mask_res"] = \ export_stop_mask_pft else: if isinstance(stop_mask, Definition): tractography_tasks["export_stop_mask_res"] =\ pimms.calc("stop_file")(as_file('_stop_mask.nii.gz')( stop_mask.get_mask_getter())) if isinstance(tracking_params['seed_mask'], Definition): tractography_tasks["export_seed_mask_res"] = pimms.calc("seed_file")( as_file('_seed_mask.nii.gz')( tracking_params['seed_mask'].get_mask_getter())) return pimms.plan(**tractography_tasks)
def build_model(model_name, force_exports=False): ''' sco.build_model(name) builds an SCO model according to the given name and returns it. Valid model names correspond to valid SCO plans; see the sco.sco_plans dict. The following options may be given: * force_exports (default: True) specifies whether exporting functions that included in the model should be automatically run when the model is built. If this is set to True then all standard exports will complete before the model is returned. ''' import sco.util, pimms if pimms.is_str(model_name): model_name = model_name.lower() _plans = model_data() if model_name not in _plans: raise ValueError('Unknown mode: %s' % model_name) mdl = _plans[model_name] dat = mdl.nodes if force_exports: dat = dat.set('require_exports', sco.util.require_exports) return pimms.plan(dat) elif pimms.is_plan(model_name): if force_exports: dat = model_name.nodes dat = dat.set('require_exports', sco.util.require_exports) return pimms.plan(dat) else: return model_name elif pimms.is_map(model_name): dat = model_name if force_exports: dat = dat.set('require_exports', sco.util.require_exports) return pimms.plan(dat) else: raise ValueError( 'Unrecognized object type given as first argument to to build_model' )
def get_mapping_plan(reg_subject, scalars, use_sls=False): mapping_tasks = with_name([ export_registered_b0, template_xform, export_rois, mapping, get_reg_subject]) # add custom scalars for scalar in scalars: if not isinstance(scalar, str): mapping_tasks["{scalar.name}_file_res"] =\ pimms.calc(f"{scalar.name}_file")(scalar.get_for_subses()) if use_sls: mapping_tasks["mapping_res"] = sls_mapping return pimms.plan(**mapping_tasks)
filenames.append(nyio.save(flnm, filemap[flnm])) return filenames return {'filemap': filemap, 'export_all_fn': export_all} atlas_plan_data = pyr.pmap({ 'init_worklog': calc_worklog, 'init_subject': calc_subject, 'init_atlases': calc_atlases, 'init_cortices': calc_cortices, 'atlas_properties': calc_atlas_projections, 'atlas_images': calc_images, 'filemap': calc_filemap }) atlas_plan = pimms.plan(atlas_plan_data) atlas_cmdline_abbrevs = { 'output_format': 'f', 'volume_format': 'F', 'atlases': 'a', 'overwrite': 'o', 'create_directory': 'c', 'subject_id': 's', 'hemis': 'H', 'output_path': 'o', 'volume_path': 'O', 'atlas_subject_id': 'r', 'image_template': 'i', 'surface_export': 's', 'volume_export': 'S',
#################################################################################################### # stimulus/__init__.py # The image module of the standard cortical observer. # By Noah C. Benson ''' The sco.stimulus module of the standard cortical observer library is responsible for processing the stimulus shown to the subject. Although this project was written for the purpose of the analysis of visual stimuli, there is no reason this must be the only kind of stimuli used. The stimulus module defines an abstract base class, StimulusBase, whose abstract methods define the interface for the module. When constructing an SCO pipeline, a StimulusBase object is required, and one may be obtained from the StimulusImage class or from a custom class that overloads the StimulusBase class. ''' import pyrsistent as pyr import pimms from .core import (calc_gamma_correction, import_stimuli, calc_images) # Make a function that's ready to be used as a module stimulus_plan_data = pyr.m(gamma_correction=calc_gamma_correction, import_stimuli=import_stimuli, images=calc_images) stimulus_plan = pimms.plan(stimulus_plan_data)
note('Constructing %s image...' % pname) img = subject.cortex_to_image(dat, method=mtd, dtype=dt) flnm = export(os.path.join(path, tag), img) files.append(flnm) return {'volume_files': tuple(files)} @pimms.calc('files') def accumulate_files(surface_files, volume_files): ''' accumulate_files is a calculator that just accumulates the exported files into a single tuple, files. ''' return {'files': (tuple(surface_files) + tuple(volume_files))} register_retinotopy_plan = pimms.plan(args=calc_arguments, retinotopy=calc_retinotopy, register=calc_registrations, surf_export=save_surface_files, vol_export=save_volume_files, accum_files=accumulate_files) def main(args): ''' register_retinotopy.main(args) can be given a list of arguments, such as sys.argv[1:]; these arguments may include any options and must include at least one subject id. All subjects whose ids are given are registered to a retinotopy model, and the resulting registration, as well as the predictions made by the model in the registration, are exported. ''' m = register_retinotopy_plan(args=args) # force completion files = m['files'] if len(files) > 0: return 0
These options are: * pRF_sigma_slope_by_label (sco.impl.benson17.pRF_sigma_slope_by_label_Kay2013) * compressive_constant_by_label (sco.impl.benson17.compressive_constant_by_label_Kay2013) * contrast_constant_by_label (sco.impl.benson17.contrast_constant_by_label_Kay2013) * modality ('surface') * max_eccentricity (12) * cpd_sensitivity_function (sco.impl.benson17.cpd_sensitivity) * saturation_constant (sco.impl.benson17.saturation_constant_Kay2013) * divisive_exponent (sco.impl.benson17.divisive_exponent_Kay2013) * gabor_orientations (8) ''' # the defaults are filled-in by virtue of being in the above argument list return True # The volume (default) calculation chain sco_plan_data = _pyr.pmap({ k: v for pd in [ sco.stimulus.stimulus_plan_data, sco.contrast.contrast_plan_data, sco.pRF.pRF_plan_data, sco.anatomy.anatomy_plan_data, sco.analysis.analysis_plan_data, sco.util.export_plan_data, { 'default_options': provide_default_options, 'divisive_normalization': calc_divisive_normalization } ] for (k, v) in pd.iteritems() }) sco_plan = _pimms.plan(sco_plan_data)
# If the output name is not provided, it is, by default, the # name of the function @pimms.calc def outer_normal_distribution_constant(standard_deviation): return 1.0 / (standard_deviation * np.sqrt(np.pi * 2)) @pimms.calc def inner_normal_distribution_constant(standard_deviation): return -0.5 / standard_deviation # Now we declare the calc plan: it's just the union of all these # calc functions, given in any order: normal_distribution = pimms.plan(variance=variance_from_stddev, cis=confidence_intervals, tests=check_normal_distribution_inputs, outer=outer_normal_distribution_constant, inner=inner_normal_distribution_constant) # This function accepts a normal_distribution object and returns # the probability density at a point def pdf(nd, x): a = nd['outer_normal_distribution_constant'] b = nd['inner_normal_distribution_constant'] mu = nd['mean'] return a * np.exp(b * (x - mu)**2)
#################################################################################################### # sco/analysis/__init__.py # Definition code for the analysis module of the sco library # by Noah C. Benson import pimms as _pimms import pyrsistent as _pyr from .core import (import_measurements, calc_prediction_analysis, calc_correspondence_maps, calc_correspondence_data) analysis_plan_data = _pyr.m(import_measurements=import_measurements, correspondence_maps=calc_correspondence_maps, correspondence_data=calc_correspondence_data, prediction_analysis=calc_prediction_analysis) analysis_plan = _pimms.plan(analysis_plan_data)
#################################################################################################### # contrast/__init__.py # The second-order contrast module of the standard cortical observer. # By Noah C. Benson ''' The sco.contrast module of the standard cortical observer library is responsible for calculating the first- and second-order contrast present in the normalized stimulus image array. ''' import pyrsistent as _pyr import pimms as _pimms from .core import (calc_contrast_constants, calc_compressive_constants, calc_gabor_spatial_frequencies, calc_oriented_contrast_images, calc_divisive_normalization, calc_pRF_contrasts, calc_gains, calc_compressive_nonlinearity) contrast_plan_data = _pyr.m( contrast_constants=calc_contrast_constants, compressive_constants=calc_compressive_constants, gabor_spatial_frequencies=calc_gabor_spatial_frequencies, oriented_contrast_images=calc_oriented_contrast_images, divisive_normalization=calc_divisive_normalization, pRF_contrasts=calc_pRF_contrasts, gains=calc_gains, compressive_nonlinearity=calc_compressive_nonlinearity) contrast_plan = _pimms.plan(contrast_plan_data)
# The anatomy module of the standard cortical observer. # By Noah C. Benson ''' The sco.anatomy module of the standard cortical observer library is responsible for importing and interpreting anatomical data from a subject and providing (and tracking) a list of parameters for each voxel. Additionally, the anatomy module includes utilities for writing out results as a FreeSurfer volume. The anatomy module defines an abstract base class, AnatomyBase, whose abstract methods define the interface for the module. When constructing an SCO pipeline, an AnatomyBase object is required, and one may be obtained from the StandardAnatomy class or from a custom class that overloads the AnatomyBase class. ''' import pyrsistent as _pyr import pimms as _pimms from .core import (import_freesurfer_subject, import_freesurfer_affine, import_benson14_retinotopy, import_measured_retinotopy, calc_retinotopy, calc_prediction_coordinates, export_predicted_responses) # Make a function that's ready to be used as a module anatomy_plan_data = _pyr.m(import_subject=import_freesurfer_subject, import_affine_tx=import_freesurfer_affine, import_measured=import_measured_retinotopy, import_benson14=import_benson14_retinotopy, retinotopy=calc_retinotopy, prediction_coordinates=calc_prediction_coordinates) anatomy_plan = _pimms.plan(anatomy_plan_data)
#################################################################################################### # sco/pRF/__init__.py # pRF-related calculations for the standard cortical observer library. # By Noah C. Benson ''' The sco.pRF module contains calculation plans for producing PRFSpec objects, which track the data for each pRF involved in the sco calculation and can extract and sum over regions from images. ''' import pyrsistent as pyr import pimms from .core import (calc_compressive_constants, calc_pRF_sigmas, calc_pRF_centers, calc_pRFs, PRFSpec) pRF_plan_data = pyr.m(compressive_constants=calc_compressive_constants, pRF_sigmas=calc_pRF_sigmas, pRF_centers=calc_pRF_centers, pRFs=calc_pRFs) pRF_plan = pimms.plan(pRF_plan_data)
def get_segmentation_plan(): segmentation_tasks = with_name([ get_scalar_dict, export_sl_counts, export_bundles, clean_bundles, segment, tract_profiles ]) return pimms.plan(**segmentation_tasks)
raise ValueError('Unexpected option given to lookup_labels; only null is accepted') if raise_q: try: res = [data_by_labels[lbl] for lbl in labels] except: raise ValueError('Not all labels found by lookup_labels and no null given') else: res = [data_by_labels[lbl] if lbl in data_by_labels else null for lbl in labels] return _pyr.pvector(res) export_plan_data = _pyr.m(export_predictions = export_predictions, export_analysis = export_analysis, export_report_images = export_report_images, export_vega = export_vega, exported_files = calc_exported_files) export_plan = _pimms.plan(export_plan_data) # Some additional handy functions def import_mri(filename, feature='data'): ''' import_mri(filename) yields a numpy array of the data imported from the given filename. The filename argument must be a string giving the name of a NifTI (*.nii or *.nii.gz) or MGH (*.mgh, *.mgz) file. The data is squeezed prior to being returned. import_mri(filename, feature) yields a specific feature of the object imported from filename; these features are given below. Features: * 'data' equivalent to import_mri(filename). * 'header' yields the header of the nibabel object representing the volume. * 'object' yields the nibabel object representing the volume.
return {'filemap': filemap, 'export_all_fn': export_all} retinotopy_plan_data = pyr.pmap({ 'init_worklog': calc_worklog, 'init_subject': calc_subject, 'init_hemispheres': calc_hemispheres, 'init_labels': calc_labels, 'init_retinotopy': calc_retinotopy, 'cleaning': calc_clean_maps, 'spotlight_cmag': calc_spotlight_cmag, 'radtan_cmag': calc_radtan_cmag, 'filemap': calc_filemap }) retinotopy_plan = pimms.plan(retinotopy_plan_data) retinotopy_cmdline_abbrevs = { 'output_format': 'f', 'overwrite': 'o', 'create_directory': 'c', 'hemispheres': 'H', 'labels': 'l', 'angles': 'a', 'eccens': 'e', 'weights': 'w', 'output_path': 'o', 'verbose': 'v' }
eccentricity=np.hypot(p['x'], p['y'])) # write cache and return if fls is not None: try: for (k, v) in six.iteritems(p): nyio.save(fls[k], v) except Exception as e: tup = (subject_id, native_hemi.chirality, type(e).__name__ + str(e.args)) warnings.warn( 'cache write failed for HCP retinotopy subject %s / %s: %s' % tup, RuntimeWarning) return p interpolate_native_properties = pimms.plan( {'native_properties': calc_native_properties}) @pimms.immutable class HCPRetinotopyDataset(Dataset): ''' neuropythy.data['hcp_retinotopy'] is a Dataset containing the publicly provided data from the Benson et al. (2018; DOI:10.1167/18.13.23) paper on the HCP 7T retinotopy dataset. For more information see the paper's OSF site (https://osf.io/bw9ec/) You do not have to explicitly configure anything in order to use this dataset: the default behavior is to use the the same cache directory as the 'hcp' dataset, meaning that your subject directories will gain 'retinotopy' subdirectories containing cached mgz files. These 'retinotopy' subdirectories exist at the same level as 'MNINonLinear' and 'T1w'. It is recommended that you interact with the data via the neuropythy.data['hcp'] dataset--this
def get_viz_plan(): viz_tasks = with_name([ plot_tract_profiles, viz_bundles, viz_indivBundle]) return pimms.plan(**viz_tasks)