Package: python-chrisclient
A python client for the ChRIS API.Quick OverviewThis repository contains various python scripts and modules that provide a rich client
experience for interacting with aCUBEbackend instance. Interaction is either via
the command line interface (CLI) or through a Python programmatic interface using
relevant modules.OverviewAt time of writing (early 2022), three scripts/modules are in production:a general CUBE clienta more specific plugin search utilitya more specific plugin run schedule utilityInstallationUse thePyPI, Luke!pipinstall-Upython-chrisclientGeneral CUBE client usagePython programmatic interfaceInstantiate the client:fromchrisclientimportclientcl=client.Client('http://localhost:8000/api/v1/','cube','cube1234')Upload and create a new plugin (only works for ChRIS admins):cl_admin=client.Client('http://localhost:8000/api/v1/','chris','chris1234')response=cl_admin.admin_upload_plugin('host,moc','~/simpledsapp.json')Get plugins given search parameters:search_params={'name':'pl-dircopy'}response=cl.get_plugins(search_params)Get a plugin by id:plugin_id=1response=cl.get_plugin_by_id(plugin_id)Get a plugin’s parameters:plugin_id=1response=cl.get_plugin_parameters(plugin_id,{'limit':50,'offset':0})These retrieving operations are supported for all other high level resources such as
feeds, pipelines, plugin instances and workflows.Get a pipeline’s default parameters and nodes data structure and then run a workflow
from the pipeline:pipeline_id=2# attempt to fetch all parameters in a single request by setting a very high limitresponse=cl.get_pipeline_default_parameters(pipeline_id,{'limit':100,'offset':0})nodes=cl.compute_workflow_nodes_info(response['data'])response=cl.create_workflow(pipeline_id,{'previous_plugin_inst_id':1,'nodes_info':json.dumps(nodes)})Please visit thewikifor more information about the client’s API and examples.Standalone CLI client toolList plugins:chrisclient-ucube-pcube1234http://localhost:8000/api/v1/listpluginoffset==0limit==2--verboseList pipelines:chrisclient-ucube-pcube1234http://localhost:8000/api/v1/listpipeline--verboseList plugin instances:chrisclient-ucube-pcube1234http://localhost:8000/api/v1/listplugininstanceoffset==0limit==1Upload and create plugin (only works for ChRIS admins):chrisclient-uchris-pchris1234http://localhost:8000/api/v1/addplugin--computenameshost,moc--fname~/simpledsapp.jsonCreate plugin instance (run plugin):chrisclient-ucube-pcube1234http://localhost:8000/api/v1/addplugininstance--pluginid3--instancedata'{"previous_id": 1, "dir": "home/cube/uploads"}'Create pipeline:chrisclient-ucube-pcube1234http://localhost:8000/api/v1/addpipeline--pipelinedata'{"name": "Pipeline1", "plugin_tree": "[{\"plugin_id\": 2, \"previous_index\": null}, {\"plugin_id\": 2, \"previous_index\": 0}]"}'Create workflow (run pipeline):chrisclient-ucube-pcube1234http://localhost:8000/api/v1/addworkflow--pipelineid2--workflowdata'{"previous_plugin_inst_id": 1, "nodes_info": "[{\"piping_id\": 3, \"compute_resource_name\": \"host\"}, {\"piping_id\": 4, \"compute_resource_name\": \"host\"}, {\"piping_id\": 5, \"compute_resource_name\": \"host\"}]"}'SearchNote that in the instructions below, the details of aCUBEinstance are passed in a JSON structure
using the--onCUBEflag. In many cases you might only want to pass the address of aCUBEinstance.
For this purpose, the--onCUBEaddresscan be used that will only set the address and keep other default
information intact.The plugin space (pluginidand plugininstance id) in aCUBEinstance can be searched using thechrispl-searchscript. This returns information either in tabular text form or a richer JSON payload. Thesearch.pymodule is of course suitable for inclusion into other scripts/projects.Search ExamplesFind the pluginIDgiven anamesubstring search termA common use case of the search script is to return the plugin ID for a plugin name substring:chrispl-search--forid,name\--usingname=surfer\--onCUBE'{
                    "protocol":     "http",
                    "port":         "8000",
                    "address":      "%HOSTIP",
                    "user":         "chris",
                    "password":     "chris1234"}'(note the aboveonCUBEspecification assumes an instance on thelocalhost. The special construction,%HOSTIP(if specified) will be replaced by the actual IP of the host machine. This construct is useful in some cases where the stringlocalhostmight have issues on proxied networks.)The above call will return the pluginidas well as the complete name for all plugins that have a substring ofsurferin theirname:(searchSubstr:name=surfer)id 12  name pl-freesurfer_pp(searchSubstr:name=surfer)id 11  name pl-fastsurfer_inferenceFind a list of all plugins registered to aCUBEinstancechrispl-search--forname,id,type\--usingname=''\--onCUBE'{
                    "protocol":     "http",
                    "port":         "8000",
                    "address":      "%HOSTIP",
                    "user":         "chris",
                    "password":     "chris1234"}'will return(searchSubstr:name=)name pl-pfdo_med2img           id 17  type ds(searchSubstr:name=)name pl-pfdo_mgz2img           id 16  type ds(searchSubstr:name=)name pl-mgz2lut_report         id 15  type ds(searchSubstr:name=)name pl-z2labelmap             id 13  type ds(searchSubstr:name=)name pl-freesurfer_pp          id 12  type ds(searchSubstr:name=)name pl-fastsurfer_inference   id 11  type ds(searchSubstr:name=)name pl-fshack                 id 10  type ds(searchSubstr:name=)name pl-mpcs                   id 9   type ds(searchSubstr:name=)name pl-pfdicom_tagsub         id 8   type ds(searchSubstr:name=)name pl-pfdicom_tagextract     id 7   type ds(searchSubstr:name=)name pl-s3push                 id 6   type ds(searchSubstr:name=)name pl-dsdircopy              id 5   type ds(searchSubstr:name=)name pl-s3retrieve             id 3   type ds(searchSubstr:name=)name pl-simpledsapp            id 2   type ds(searchSubstr:name=)name pl-lungct                 id 18  type fs(searchSubstr:name=)name pl-mri10yr06mo01da_normal id 14  type fs(searchSubstr:name=)name pl-dircopy                id 4   type fs(searchSubstr:name=)name pl-simplefsapp            id 1   type fsSearch plugininstancesThe actual space of executed plugin instances can also be searched. For instance, find theinstance IDsof all plugins with name substringsurferand list theirstatus. Note that to search theinstancespace, the--acrossplugininstancesis specified:chrispl-search--forid,status,plugin_name\--usingplugin_name=surfer\--acrossplugininstances\--onCUBE'{
                    "protocol":     "http",
                    "port":         "8000",
                    "address":      "%HOSTIP",
                    "user":         "chris",
                    "password":     "chris1234"}'which will return something similar to:(searchSubstr:plugin_name=surfer)id 12 status finishedSuccessfully  plugin_name pl-freesurfer_pp(searchSubstr:plugin_name=surfer)id 11 status finishedSuccessfully  plugin_name pl-freesurfer_pp(searchSubstr:plugin_name=surfer)id 10 status finishedSuccessfully  plugin_name pl-freesurfer_pp(searchSubstr:plugin_name=surfer)id 9  status finishedSuccessfully  plugin_name pl-freesurfer_ppSearch pluginfilesThe actual list of file data associated with the outputs of a plugin instance can also be searched. For instance, search for the names of files by looking for thefnameacrossfilesusingplugin_inst_idof9:chrispl-search--forfname\--usingplugin_inst_id=9\--acrossfiles\--onCUBEaddressmegalodon.localwhich will return something similar to:(searchSubstr:plugin_inst_id=9)fname chris/feed_9/pl-lungct_9/data/PatientF.dcm(searchSubstr:plugin_inst_id=9)fname chris/feed_9/pl-lungct_9/data/PatientE.dcm(searchSubstr:plugin_inst_id=9)fname chris/feed_9/pl-lungct_9/data/PatientD.dcm(searchSubstr:plugin_inst_id=9)fname chris/feed_9/pl-lungct_9/data/PatientC.dcm(searchSubstr:plugin_inst_id=9)fname chris/feed_9/pl-lungct_9/data/PatientB.dcm(searchSubstr:plugin_inst_id=9)fname chris/feed_9/pl-lungct_9/data/PatientA.dcm(searchSubstr:plugin_inst_id=9)fname chris/feed_9/pl-lungct_9/data/jobStatusSummary.json(searchSubstr:plugin_inst_id=9)fname chris/feed_9/pl-lungct_9/data/jobStatus.json(searchSubstr:plugin_inst_id=9)fname chris/feed_9/pl-lungct_9/data/input.meta.json(searchSubstr:plugin_inst_id=9)fname chris/feed_9/pl-lungct_9/data/ex-covid.dcm(searchSubstr:plugin_inst_id=9)fname chris/feed_9/pl-lungct_9/data/ex-covid-ct.dcm(searchSubstr:plugin_inst_id=9)fname chris/feed_9/pl-lungct_9/data/0006.dcm(searchSubstr:plugin_inst_id=9)fname chris/feed_9/pl-lungct_9/data/0005.dcm(searchSubstr:plugin_inst_id=9)fname chris/feed_9/pl-lungct_9/data/0004.dcm(searchSubstr:plugin_inst_id=9)fname chris/feed_9/pl-lungct_9/data/0003.dcm(searchSubstr:plugin_inst_id=9)fname chris/feed_9/pl-lungct_9/data/0002.dcm(searchSubstr:plugin_inst_id=9)fname chris/feed_9/pl-lungct_9/data/0001.dcm(searchSubstr:plugin_inst_id=9)fname chris/feed_9/pl-lungct_9/data/0000.dcmSearch plugin downloadablefile resourcesA list of web accessible locations to downloadable files can be found by searching acrosslinksfor afile_resourceassociated with a givenplugin_inst_id=9(with an example ofonCUBEaddressandonCUBEport:chrispl-search--forfile_resource\--usingplugin_inst_id=9\--acrosslinks\--onCUBEaddresslocalhost\--onCUBEport8333which will return something similar to:(searchSubstr:plugin_inst_id=9)file_resource http://localhost:8333/api/v1/files/157/PatientF.dcm(searchSubstr:plugin_inst_id=9)file_resource http://localhost:8333/api/v1/files/156/PatientE.dcm(searchSubstr:plugin_inst_id=9)file_resource http://localhost:8333/api/v1/files/155/PatientD.dcm(searchSubstr:plugin_inst_id=9)file_resource http://localhost:8333/api/v1/files/154/PatientC.dcm(searchSubstr:plugin_inst_id=9)file_resource http://localhost:8333/api/v1/files/153/PatientB.dcm(searchSubstr:plugin_inst_id=9)file_resource http://localhost:8333/api/v1/files/152/PatientA.dcm(searchSubstr:plugin_inst_id=9)file_resource http://localhost:8333/api/v1/files/162/jobStatusSummary.json(searchSubstr:plugin_inst_id=9)file_resource http://localhost:8333/api/v1/files/161/jobStatus.json(searchSubstr:plugin_inst_id=9)file_resource http://localhost:8333/api/v1/files/160/input.meta.json(searchSubstr:plugin_inst_id=9)file_resource http://localhost:8333/api/v1/files/159/ex-covid.dcm(searchSubstr:plugin_inst_id=9)file_resource http://localhost:8333/api/v1/files/158/ex-covid-ct.dcm(searchSubstr:plugin_inst_id=9)file_resource http://localhost:8333/api/v1/files/151/0006.dcm(searchSubstr:plugin_inst_id=9)file_resource http://localhost:8333/api/v1/files/150/0005.dcm(searchSubstr:plugin_inst_id=9)file_resource http://localhost:8333/api/v1/files/149/0004.dcm(searchSubstr:plugin_inst_id=9)file_resource http://localhost:8333/api/v1/files/148/0003.dcm(searchSubstr:plugin_inst_id=9)file_resource http://localhost:8333/api/v1/files/147/0002.dcm(searchSubstr:plugin_inst_id=9)file_resource http://localhost:8333/api/v1/files/146/0001.dcm(searchSubstr:plugin_inst_id=9)file_resource http://localhost:8333/api/v1/files/145/0000.dcmSearch the space ofparametersfor a plugin idTo get a list of CLI flags, internal name, and help string associated with plugin id 8chrispl-search  --for flag,name,help                \
                --using plugin_id=8                 \
                --across parameters                 \
                --onCUBEaddress localhost --onCUBEport 8333(searchSubstr:plugin_id=8)flag --subjectDir            name subjectDir             help directory (relative to <inputDir>) of subjects to process(searchSubstr:plugin_id=8)flag --in_name               name iname                  help name of the input (raw) file to process (default: brain.mgz)(searchSubstr:plugin_id=8)flag --out_name              name oname                  help name of the output segmented file(searchSubstr:plugin_id=8)flag --order                 name order                  help interpolation order(searchSubstr:plugin_id=8)flag --subject               name subject                help subject(s) to process. This expression is globbed.(searchSubstr:plugin_id=8)flag --log                   name logfile                help name of logfile (default: deep-seg.log)(searchSubstr:plugin_id=8)flag --network_sagittal_path name network_sagittal_path  help path to pre-trained sagittal network weights(searchSubstr:plugin_id=8)flag --network_coronal_path  name network_coronal_path   help path to pre-trained coronal network weights(searchSubstr:plugin_id=8)flag --network_axial_path    name network_axial_path     help path to pre-trained axial network weights(searchSubstr:plugin_id=8)flag --clean                 name cleanup                help if specified, clean up segmentation(searchSubstr:plugin_id=8)flag --no_cuda               name no_cuda                help if specified, do not use GPU(searchSubstr:plugin_id=8)flag --batch_size            name batch_size             help batch size for inference (default: 8(searchSubstr:plugin_id=8)flag --simple_run            name simple_run             help simplified run: only analyze one subject(searchSubstr:plugin_id=8)flag --run_parallel          name run_parallel           help if specified, allows for execute on multiple GPUs(searchSubstr:plugin_id=8)flag --copyInputImage        name copyInputImage         help if specified, copy input file to output dir.Sub filter a parameter space for a single CLI and return the name to POST to CUBEDetermine the internal value to POST to CUBE for a given plugin CLI flag: (note this is anexactflag / string search – thus flag filters must have leading ‘–’ where appropriate):chrispl-search      --for flag,name                     \
                    --using plugin_id=8                 \
                    --across parameters                 \
                    --filterFor " --in_name,--out_name" \
                    --onCUBEaddress localhost --onCUBEport 8333(searchSubstr:plugin_id=8)flag --in_name               name iname(searchSubstr:plugin_id=8)flag --out_name              name onameRunPlugins can be run/scheduled on a CUBE instance using thechrispl-runscript. The CLI parameters are broadly similar tochrispl-searchwith some semantic changes more pertinent to the run call – theforsearch is fixed to the pluginidand the search--pluginSpecbecomes the--usingCLI.Run ExamplesRun an FS plugin,pl-mri10yr06mo01da_normalchrispl-run --plugin name=pl-mri10yr06mo01da_normal \
            --onCUBE '{
                "protocol":     "http",
                "port":         "8000",
                "address":      "%HOSTIP",
                "user":         "chris",
                "password":     "chris1234"}'This plugin does not require any specific CLI args when run in the default state. Once posted to CUBE, a string is returned to the shell:(name=pl-mri10yr06mo01da_normal)id 14Indicating that the plugin instance ID of the plugin inCUBEis14(for example).For convenience, let’s set:CUBE='{
    "protocol":     "http",
    "port":         "8000",
    "address":      "%HOSTIP",
    "user":         "chris",
    "password":     "chris1234"
}'This return construct lends itself easily to scripting:ROOTNODE=$(./chrispl-run --plugin name=pl-mri10yr06mo01da_normal --onCUBE "$CUBE" | awk '{print $3}')or with some formatting:ROOTNODE=$(
    chrispl-run --plugin name=pl-mri10yr06mo01da_normal     \
                --onCUBE="$CUBE"                            |
                     awk '{print $3}'
)Run a DS plugin,pl-freesurfer_pp, that builds on the previous nodeIn this manner, a workflow can be constructed. First construct the arguments for the next plugin:ARGS="                              \
--ageSpec=10-06-01;                 \
--copySpec=sag,cor,tra,stats,3D;    \
--previous_id=$ROOTNODE             \
"and now schedule the run:chrispl-run --plugin name="pl-freesurfer_pp"    \
            --args="$ARGS"                      \
            --onCUBE="$CUBE"which will return:(name=pl-freesurfer_pp)id 19As before, this can be captured and used for subsequent chaining:FSNODE=$(
    chrispl-run --plugin name=pl-freesurfer_pp  \
                --args="$ARGS"                  \
                --onCUBE="$CUBE"                |
                     awk '{print $3}'
)Additional ReadingConsult the ChRIS_docsworkflowdirectory for examples of workflows built using these tools.-30-