Package: pycivet
pycivetPython bindings for CIVET binaries liketransform_objectsandmincdefrag.Abstractpycivetis a helper library which provides a Python API that wraps
CIVET binaries with object-oriented syntax.
Intermediate files are written to temporary locations and cached.ExamplesConsider this bash script:temp1=$(mktemp--suffix=.mnc)temp2=$(mktemp)mincresample-quiet-doublemask.mnc$temp1mincblur-quiet-fwhm$temp1$temp2mv"${temp2}_blur.mnc"blurred_mask.mnc
rm$temp1The equivalent usingpycivet:fromcivet.mincimportMaskMask("wm.right.mnc").resamplef64().mincblur(fwhm=3).save("blurred_mask.mnc")This Perl code snippet frommarching_cubes.plcan be expressed in Python as such:https://github.com/aces/surface-extraction/blob/7c9c5987a2f8f5fdeb8d3fd15f2f9b636401d9a1/scripts/marching_cubes.pl.in#L125-L134fromcivetimportstarting_modelsstarting_models.WHITE_MODEL_320.flip_x().slide_right().save('./output.obj')InstallationIt is recommended you install this package in a container image, e.g.FROMdocker.io/fnndsc/mni-conda-base:civet2.1.1-python3.10.2RUNpipinstallpycivetMotivationTypically, bioinformatics and neuroinformatics pipelines such asCIVETandFreeSurferare comprised of
many binary programs and a script incshorperlwhich glues together
those binary programs and their intermediate results. These scripts
look something like:do_somethinginput.mnc/tmp/1.mnc
another_thing/tmp/1.mnc/tmp/2.mnc
create_thing/tmp/3.mnc
many_thing/tmp/2.mnc/tmp/3.mnc/tmp/4.mnc
...We propose that the readability and maintainability of such scripts can be
improved using modern programming language features such as type hints.
These advantages would enable to faster development and with fewer bugs.pycivetexplores this concept with CIVET subroutines.Featurespycivetis an object-oriented Python API to CIVET binaries.Intermediate FilesIntermediate files are used to pass results between subroutines.
This chore is handled transparently by thepycivet.memoizationsubmodule.Consider this excerpt frommarching_cubes.pl:&run("param2xfm","-scales",-1,1,1,"${tmpdir}/flip.xfm");&run("transform_objects",$ICBM_white_model,"${tmpdir}/flip.xfm",$initial_model);unlink("${tmpdir}/flip.xfm");&run("param2xfm","-translation",25,0,0,"${tmpdir}/slide_right.xfm");&run("transform_objects",$initial_model,"${tmpdir}/slide_right.xfm",$initial_model);unlink("${tmpdir}/slide_right.xfm");Usingpycivetwe can express the code more concisely:fromcivet.objimportSurfaceSurface('input.obj').flip_x().translate_x(25).save('./output.obj')MemoizationRepeated calls on the same object are cached. This is primarily
for the sake of internal code quality, but it can also be taken
advantage of externally:fromcivet.memoizationimportSessionfromcivet.objimportSurfacewithSession()ass:surf=Surface('input.obj')s.save(surf.flip_x(),'flipped.obj')s.save(surf.flip_x().slide_right(),'flipped_and_slid.obj')In the example above, the following subroutine commands are cached:param2xfm -scales -1 1 1 flip.xfmtransform_objects input.obj flip.xfm flipped.objLazinessOnly results which are needed (bysave) are computed.fromcivet.objimportSurfacesurf=Surface('input.obj')surf.slide_right()# does nothingsurf.slide_left().save('left.obj')# runs param2xfm, transform_objects, ...TypingOnly methods relevant to an object's type are available to be called on
that object. For instance, an object representing a.objsurface file
would have the methodsflip_x()andtranslate_x(n), and an object
representing a.mncvolume would have the methodsminccalc_u8(...)andmincdefrag(...)defined, but you cannot callSurface('input.obj').mincdefrag(1, 19).
Subroutines and their usage are discoverable through autocomplete features
of an IDE that supports type-hints.