{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "Use cases of Axon python API\n",
    "============================\n",
    "\n",
    "Load Brainvisa\n",
    "--------------\n",
    "\n",
    "The following lines enable to load Brainvisa without the graphical user interface through a python script:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "import brainvisa.axon\n",
    "brainvisa.axon.initializeProcesses()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "deletable": true,
    "editable": true
   },
   "source": [
    "Call a process\n",
    "--------------\n",
    "\n",
    "The module [brainvisa.processes](python_bv_processing.html#module-brainvisa.processes) manages the processes, pipelines and their execution.\n",
    "\n",
    "The object [brainvisa.processes.ExecutionContext](python_bv_processing.html#brainvisa.processes.ExecutionContext) enables to start a Brainvisa process using the method [brainvisa.processes.ExecutionContext.runProcess](python_bv_processing.html#brainvisa.processes.ExecutionContext.runProcess).\n",
    "When Brainvisa is loaded, a default execution context exists and is returned by the function [brainvisa.processes.defaultContext](python_bv_processing.html#brainvisa.processes.defaultContext)\n",
    "\n",
    "The following example will run the process Threshold on an image:\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "deletable": true,
    "editable": true,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "import brainvisa.processes\n",
    "context = brainvisa.processes.defaultContext()\n",
    "\n",
    "# Just to get an example data for running the process\n",
    "from brainvisa.configuration.neuroConfig import getSharePath, bvShareDirectory\n",
    "import os\n",
    "example_data = os.path.join(getSharePath(), bvShareDirectory, \"anatomical_templates\", \"MNI152_T1_1mm_brain_mask.nii\")\n",
    "# creating a temporary file for the output\n",
    "output_data = context.temporary(\"NIFTI-1 image\")\n",
    "\n",
    "context.runProcess(\"threshold\", image_input=example_data, image_output=output_data, threshold1=100)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Select a step in a pipeline\n",
    "---------------------------\n",
    "\n",
    "In a pipeline, some steps may be optional and can be selected or unselected for execution. \n",
    "It is possible to select or unselect a step of a pipeline before running it through a python script. \n",
    "A pipeline is a process that have execution nodes. The method [brainvisa.processes.Process.executionNode](python_bv_processing.html#brainvisa.processes.Process.executionNode) returns an [brainvisa.processes.ExecutionNode](python_bv_processing.html#brainvisa.processes.ExecutionNode).\n",
    "The execution node of the pipeline contains child nodes, the name of these nodes can be obtained with the method [brainvisa.processes.ExecutionNode.childrenNames](python_bv_processing.html#brainvisa.processes.ExecutionNode.childrenNames).\n",
    "To get a specific child node, the method [brainvisa.processes.ExecutionNode.child](python_bv_processing.html#brainvisa.processes.ExecutionNode.child) can be used.\n",
    "\n",
    "The following examples gets an instance of the *convertOldDatabase* pipeline and unselects all its steps:\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "pipeline=brainvisa.processes.getProcessInstance(\"convertOldDatabase\")\n",
    "nodes=pipeline.executionNode()\n",
    "\n",
    "nodes.childrenNames()\n",
    "assert(nodes.childrenNames() == ['ConvertDatabase', 'CheckDatabase', 'CleanDatabase'])\n",
    "nodes.child(\"ConvertDatabase\").setSelected(0)\n",
    "assert(not nodes.child(\"ConvertDatabase\").isSelected())\n",
    "nodes.child(\"CheckDatabase\").setSelected(0)\n",
    "nodes.child(\"CleanDatabase\").setSelected(0)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The process instance can be given as a parameter for the [brainvisa.processes.ExecutionContext.runProcess](python_bv_processing.html#brainvisa.processes.ExecutionContext.runProcess) method instead of the process id.\n",
    "\n",
    "\n",
    "Query a database\n",
    "----------------\n",
    "\n",
    "At Brainvisa startup, an internal database and the database selected in the user's preferences are loaded. \n",
    "The list of databases ([brainvisa.data.sqlFSODatabase.SQLDatabases](python_bv_data.html#brainvisa.data.sqlFSODatabase.SQLDatabases)) is stored in the global variable [brainvisa.data.neuroHierarchy.databases](python_bv_data.html#brainvisa.data.neuroHierarchy.databases).\n",
    "Each database is an instance of the class [brainvisa.data.sqlFSODatabase.SQLDatabase](python_bv_data.html#brainvisa.data.sqlFSODatabase.SQLDatabases).\n",
    "Several methods enable to query a database or a list of databases. The results of queries are generally [brainvisa.data.neuroDiskItems.DiskItem](python_bv_data.html#brainvisa.data.neuroDiskItems.DiskItem) objects. A DiskItem represents data stored in files and indexed in a database with additionnal information.\n",
    "\n",
    "In the following example, a DiskItem is searched in the databases by filename:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "from brainvisa.data.neuroHierarchy import databases\n",
    "from brainvisa.data.neuroDiskItems import DiskItem\n",
    "\n",
    "item = databases.getDiskItemFromFileName(example_data)\n",
    "assert(isinstance(item, DiskItem))\n",
    "assert(str(item.type) == 'anatomical Mask Template')\n",
    "assert(str(item.format) == 'NIFTI-1 image')"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Here is a request for all DiskItems of type \"anatomical Template\" with the value of *Size* attribute being \"1 mm\":"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "items = databases.findDiskItems({\"_type\" : \"anatomical Template\", \"Size\": \"1 mm\"})\n",
    "assert(str(items).startswith('<generator object SQLDatabases.findDiskItems'))\n",
    "model_filename = next(items).fileName()\n",
    "assert(model_filename.startswith(os.path.join(getSharePath(), bvShareDirectory, \"anatomical_templates\")))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The object [brainvisa.data.readdiskitem.ReadDiskItem](python_bv_data.html#brainvisa.data.readdiskitem.ReadDiskItem) enables to search for an existing DiskItem in the databases using the method [ReadDiskItem.findValue](python_bv_data.html#brainvisa.data.readdiskitem.ReadDiskItem.findValue). If the request is not precise enought and several DiskItems match, the method returns *None*."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "from brainvisa.data.readdiskitem import ReadDiskItem\n",
    "from brainvisa.configuration import neuroConfig\n",
    "rd = ReadDiskItem(\"anatomical Template\", \"Aims readable volume formats\")\n",
    "template = rd.findValue({\"Size\" : \"2 mm\"})\n",
    "assert(template is None)\n",
    "template = rd.findValue({\"Size\" : \"2 mm\", \"skull_stripped\": \"no\", \n",
    "                         \"_database\": neuroConfig.dataPath[0].directory})\n",
    "assert(template is not None)\n",
    "assert(template.fileName().startswith(os.path.join(getSharePath(), bvShareDirectory, \"anatomical_templates\")))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "The object [brainvisa.data.writediskitem.WriteDiskItem](python_bv_data.html#brainvisa.data.writediskitem.WriteDiskItem) enables to create new DiskItems to write output data according to Brainvisa hierarchy of directories."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": false,
    "jupyter": {
     "outputs_hidden": false
    }
   },
   "outputs": [],
   "source": [
    "from brainvisa.data.writediskitem import WriteDiskItem\n",
    "wd = WriteDiskItem(\"Raw T1 MRI\", \"NIFTI-1 image\")\n",
    "item = wd.findValue({\"protocol\" : 'test', \"subject\" : \"mysubject\"})\n",
    "# nothe that item is not None only if one (and only one) user database has been setup."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "Quit Brainvisa\n",
    "--------------\n",
    "\n",
    "The function [brainvisa.axon.processes.cleanup](python_bv_processing.html#brainvisa.axon.processes.cleanup) should be called at the end of the script to quit properly Brainvisa."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "brainvisa.axon.cleanup()"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.0"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
