diff --git a/.doctrees/api/api.doctree b/.doctrees/api/api.doctree index 93a1e9a33..26aa4a7e8 100644 Binary files a/.doctrees/api/api.doctree and b/.doctrees/api/api.doctree differ diff --git a/.doctrees/api/engine.doctree b/.doctrees/api/engine.doctree index e7c790cf1..691cb0cdd 100644 Binary files a/.doctrees/api/engine.doctree and b/.doctrees/api/engine.doctree differ diff --git a/.doctrees/api/index.doctree b/.doctrees/api/index.doctree index c5f9c2465..b55c242c3 100644 Binary files a/.doctrees/api/index.doctree and b/.doctrees/api/index.doctree differ diff --git a/.doctrees/api/process.doctree b/.doctrees/api/process.doctree index 75d3a2ee1..9b3cc2304 100644 Binary files a/.doctrees/api/process.doctree and b/.doctrees/api/process.doctree differ diff --git a/.doctrees/api/qt_apps.doctree b/.doctrees/api/qt_apps.doctree index c809c4da0..51424a823 100644 Binary files a/.doctrees/api/qt_apps.doctree and b/.doctrees/api/qt_apps.doctree differ diff --git a/.doctrees/api/qt_gui.doctree b/.doctrees/api/qt_gui.doctree index b68da2896..d1eaa5bb5 100644 Binary files a/.doctrees/api/qt_gui.doctree and b/.doctrees/api/qt_gui.doctree differ diff --git a/.doctrees/api/sphinxext.doctree b/.doctrees/api/sphinxext.doctree index 98831e732..944ac22c6 100644 Binary files a/.doctrees/api/sphinxext.doctree and b/.doctrees/api/sphinxext.doctree differ diff --git a/.doctrees/api/study_config.doctree b/.doctrees/api/study_config.doctree index 6e2639fc1..53c515444 100644 Binary files a/.doctrees/api/study_config.doctree and b/.doctrees/api/study_config.doctree differ diff --git a/.doctrees/api/subprocess.doctree b/.doctrees/api/subprocess.doctree index 62af0641c..0ddeaed91 100644 Binary files a/.doctrees/api/subprocess.doctree and b/.doctrees/api/subprocess.doctree differ diff --git a/.doctrees/environment.pickle b/.doctrees/environment.pickle index 6d3d17ece..37b3ae8a7 100644 Binary files a/.doctrees/environment.pickle and b/.doctrees/environment.pickle differ diff --git a/.doctrees/nbsphinx/tutorial/capsul_tutorial.ipynb b/.doctrees/nbsphinx/tutorial/capsul_tutorial.ipynb index e35e0193c..126a93b9d 100644 --- a/.doctrees/nbsphinx/tutorial/capsul_tutorial.ipynb +++ b/.doctrees/nbsphinx/tutorial/capsul_tutorial.ipynb @@ -53,10 +53,10 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:29.042845Z", - "iopub.status.busy": "2024-12-19T17:33:29.042630Z", - "iopub.status.idle": "2024-12-19T17:33:29.050346Z", - "shell.execute_reply": "2024-12-19T17:33:29.049733Z" + "iopub.execute_input": "2024-12-20T14:30:40.347179Z", + "iopub.status.busy": "2024-12-20T14:30:40.346750Z", + "iopub.status.idle": "2024-12-20T14:30:40.354913Z", + "shell.execute_reply": "2024-12-20T14:30:40.354403Z" } }, "outputs": [], @@ -82,10 +82,10 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:29.052466Z", - "iopub.status.busy": "2024-12-19T17:33:29.052089Z", - "iopub.status.idle": "2024-12-19T17:33:29.056127Z", - "shell.execute_reply": "2024-12-19T17:33:29.055521Z" + "iopub.execute_input": "2024-12-20T14:30:40.356963Z", + "iopub.status.busy": "2024-12-20T14:30:40.356596Z", + "iopub.status.idle": "2024-12-20T14:30:40.360735Z", + "shell.execute_reply": "2024-12-20T14:30:40.360063Z" } }, "outputs": [ @@ -124,26 +124,25 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:29.091409Z", - "iopub.status.busy": "2024-12-19T17:33:29.091210Z", - "iopub.status.idle": "2024-12-19T17:33:29.319491Z", - "shell.execute_reply": "2024-12-19T17:33:29.318916Z" + "iopub.execute_input": "2024-12-20T14:30:40.396758Z", + "iopub.status.busy": "2024-12-20T14:30:40.396279Z", + "iopub.status.idle": "2024-12-20T14:30:40.804646Z", + "shell.execute_reply": "2024-12-20T14:30:40.803964Z" } }, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "['f', 'ff', 'out']\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Process1 execution, f: 13.3 , ff: 132.6\n", - "Process result = 145.9\n" + "ename": "ModuleNotFoundError", + "evalue": "No module named 'populse_db.storage'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mModuleNotFoundError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[3], line 2\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;66;03m# Capsul import\u001b[39;00m\n\u001b[0;32m----> 2\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mapi\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Process\n\u001b[1;32m 4\u001b[0m \u001b[38;5;66;03m# Trait import\u001b[39;00m\n\u001b[1;32m 5\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mtraits\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mapi\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Float\n", + "File \u001b[0;32m~/work/capsul/capsul/capsul/api.py:41\u001b[0m\n\u001b[1;32m 39\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline_nodes\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Switch\n\u001b[1;32m 40\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline_nodes\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m OptionalOutputSwitch\n\u001b[0;32m---> 41\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mengine\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m capsul_engine\n\u001b[1;32m 42\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mengine\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m activate_configuration\n\u001b[1;32m 43\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mstudy_config\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mprocess_instance\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m get_process_instance\n", + "File \u001b[0;32m~/work/capsul/capsul/capsul/engine/__init__.py:36\u001b[0m\n\u001b[1;32m 33\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01msoma\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01msorted_dictionary\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m SortedDictionary\n\u001b[1;32m 34\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01msoma\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mutils\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mweak_proxy\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m get_ref\n\u001b[0;32m---> 36\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mdatabase_populse\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m PopulseDBEngine\n\u001b[1;32m 38\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01msettings\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Settings\n\u001b[1;32m 39\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mmodule\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m default_modules\n", + "File \u001b[0;32m~/work/capsul/capsul/capsul/engine/database_populse.py:6\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mos\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpath\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m \u001b[38;5;21;01mosp\u001b[39;00m\n\u001b[1;32m 4\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mengine\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mdatabase\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m DatabaseEngine\n\u001b[0;32m----> 6\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mpopulse_db\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mstorage\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Storage\n\u001b[1;32m 8\u001b[0m schemas \u001b[38;5;241m=\u001b[39m [\n\u001b[1;32m 9\u001b[0m {\n\u001b[1;32m 10\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mversion\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m1.0.0\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 39\u001b[0m },\n\u001b[1;32m 40\u001b[0m ]\n\u001b[1;32m 43\u001b[0m \u001b[38;5;28;01mclass\u001b[39;00m \u001b[38;5;21;01mPopulseDBEngine\u001b[39;00m(DatabaseEngine):\n", + "\u001b[0;31mModuleNotFoundError\u001b[0m: No module named 'populse_db.storage'" ] } ], @@ -185,13 +184,25 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:29.321517Z", - "iopub.status.busy": "2024-12-19T17:33:29.321265Z", - "iopub.status.idle": "2024-12-19T17:33:29.325582Z", - "shell.execute_reply": "2024-12-19T17:33:29.324972Z" + "iopub.execute_input": "2024-12-20T14:30:40.807086Z", + "iopub.status.busy": "2024-12-20T14:30:40.806581Z", + "iopub.status.idle": "2024-12-20T14:30:40.822795Z", + "shell.execute_reply": "2024-12-20T14:30:40.822199Z" } }, - "outputs": [], + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'Process' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[4], line 3\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mtraits\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mapi\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Str\n\u001b[0;32m----> 3\u001b[0m \u001b[38;5;28;01mclass\u001b[39;00m \u001b[38;5;21;01mProcess2\u001b[39;00m(\u001b[43mProcess\u001b[49m):\n\u001b[1;32m 5\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m__init__\u001b[39m(\u001b[38;5;28mself\u001b[39m):\n\u001b[1;32m 6\u001b[0m \u001b[38;5;28msuper\u001b[39m(Process2, \u001b[38;5;28mself\u001b[39m)\u001b[38;5;241m.\u001b[39m\u001b[38;5;21m__init__\u001b[39m()\n", + "\u001b[0;31mNameError\u001b[0m: name 'Process' is not defined" + ] + } + ], "source": [ "from traits.api import Str\n", "\n", @@ -226,13 +237,28 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:29.327689Z", - "iopub.status.busy": "2024-12-19T17:33:29.327353Z", - "iopub.status.idle": "2024-12-19T17:33:29.330853Z", - "shell.execute_reply": "2024-12-19T17:33:29.330245Z" + "iopub.execute_input": "2024-12-20T14:30:40.825075Z", + "iopub.status.busy": "2024-12-20T14:30:40.824718Z", + "iopub.status.idle": "2024-12-20T14:30:40.885610Z", + "shell.execute_reply": "2024-12-20T14:30:40.884985Z" } }, - "outputs": [], + "outputs": [ + { + "ename": "ModuleNotFoundError", + "evalue": "No module named 'populse_db.storage'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mModuleNotFoundError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[5], line 2\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mprocess\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mxml\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m xml_process\n\u001b[0;32m----> 2\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mapi\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m get_process_instance\n\u001b[1;32m 4\u001b[0m \u001b[38;5;129m@xml_process\u001b[39m(\u001b[38;5;124m'''\u001b[39m\n\u001b[1;32m 5\u001b[0m \u001b[38;5;124m\u001b[39m\n\u001b[1;32m 6\u001b[0m \u001b[38;5;124m \u001b[39m\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 10\u001b[0m \u001b[38;5;124m'''\u001b[39m)\n\u001b[1;32m 11\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21madd\u001b[39m(a, b):\n\u001b[1;32m 12\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m a \u001b[38;5;241m+\u001b[39m b\n", + "File \u001b[0;32m~/work/capsul/capsul/capsul/api.py:41\u001b[0m\n\u001b[1;32m 39\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline_nodes\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Switch\n\u001b[1;32m 40\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline_nodes\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m OptionalOutputSwitch\n\u001b[0;32m---> 41\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mengine\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m capsul_engine\n\u001b[1;32m 42\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mengine\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m activate_configuration\n\u001b[1;32m 43\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mstudy_config\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mprocess_instance\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m get_process_instance\n", + "File \u001b[0;32m~/work/capsul/capsul/capsul/engine/__init__.py:36\u001b[0m\n\u001b[1;32m 33\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01msoma\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01msorted_dictionary\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m SortedDictionary\n\u001b[1;32m 34\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01msoma\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mutils\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mweak_proxy\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m get_ref\n\u001b[0;32m---> 36\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mdatabase_populse\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m PopulseDBEngine\n\u001b[1;32m 38\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01msettings\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Settings\n\u001b[1;32m 39\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mmodule\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m default_modules\n", + "File \u001b[0;32m~/work/capsul/capsul/capsul/engine/database_populse.py:6\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mos\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpath\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m \u001b[38;5;21;01mosp\u001b[39;00m\n\u001b[1;32m 4\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mengine\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mdatabase\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m DatabaseEngine\n\u001b[0;32m----> 6\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mpopulse_db\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mstorage\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Storage\n\u001b[1;32m 8\u001b[0m schemas \u001b[38;5;241m=\u001b[39m [\n\u001b[1;32m 9\u001b[0m {\n\u001b[1;32m 10\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mversion\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m1.0.0\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 39\u001b[0m },\n\u001b[1;32m 40\u001b[0m ]\n\u001b[1;32m 43\u001b[0m \u001b[38;5;28;01mclass\u001b[39;00m \u001b[38;5;21;01mPopulseDBEngine\u001b[39;00m(DatabaseEngine):\n", + "\u001b[0;31mModuleNotFoundError\u001b[0m: No module named 'populse_db.storage'" + ] + } + ], "source": [ "from capsul.process.xml import xml_process\n", "from capsul.api import get_process_instance\n", @@ -268,13 +294,28 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:29.332831Z", - "iopub.status.busy": "2024-12-19T17:33:29.332477Z", - "iopub.status.idle": "2024-12-19T17:33:29.335949Z", - "shell.execute_reply": "2024-12-19T17:33:29.335354Z" + "iopub.execute_input": "2024-12-20T14:30:40.887851Z", + "iopub.status.busy": "2024-12-20T14:30:40.887448Z", + "iopub.status.idle": "2024-12-20T14:30:40.944369Z", + "shell.execute_reply": "2024-12-20T14:30:40.943830Z" } }, - "outputs": [], + "outputs": [ + { + "ename": "ModuleNotFoundError", + "evalue": "No module named 'populse_db.storage'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mModuleNotFoundError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[6], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mapi\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m get_process_instance\n\u001b[1;32m 3\u001b[0m process \u001b[38;5;241m=\u001b[39m get_process_instance(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m__main__.add\u001b[39m\u001b[38;5;124m'\u001b[39m)\n", + "File \u001b[0;32m~/work/capsul/capsul/capsul/api.py:41\u001b[0m\n\u001b[1;32m 39\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline_nodes\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Switch\n\u001b[1;32m 40\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline_nodes\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m OptionalOutputSwitch\n\u001b[0;32m---> 41\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mengine\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m capsul_engine\n\u001b[1;32m 42\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mengine\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m activate_configuration\n\u001b[1;32m 43\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mstudy_config\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mprocess_instance\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m get_process_instance\n", + "File \u001b[0;32m~/work/capsul/capsul/capsul/engine/__init__.py:36\u001b[0m\n\u001b[1;32m 33\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01msoma\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01msorted_dictionary\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m SortedDictionary\n\u001b[1;32m 34\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01msoma\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mutils\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mweak_proxy\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m get_ref\n\u001b[0;32m---> 36\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mdatabase_populse\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m PopulseDBEngine\n\u001b[1;32m 38\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01msettings\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Settings\n\u001b[1;32m 39\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mmodule\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m default_modules\n", + "File \u001b[0;32m~/work/capsul/capsul/capsul/engine/database_populse.py:6\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mos\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpath\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m \u001b[38;5;21;01mosp\u001b[39;00m\n\u001b[1;32m 4\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mengine\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mdatabase\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m DatabaseEngine\n\u001b[0;32m----> 6\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mpopulse_db\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mstorage\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Storage\n\u001b[1;32m 8\u001b[0m schemas \u001b[38;5;241m=\u001b[39m [\n\u001b[1;32m 9\u001b[0m {\n\u001b[1;32m 10\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mversion\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m1.0.0\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 39\u001b[0m },\n\u001b[1;32m 40\u001b[0m ]\n\u001b[1;32m 43\u001b[0m \u001b[38;5;28;01mclass\u001b[39;00m \u001b[38;5;21;01mPopulseDBEngine\u001b[39;00m(DatabaseEngine):\n", + "\u001b[0;31mModuleNotFoundError\u001b[0m: No module named 'populse_db.storage'" + ] + } + ], "source": [ "from capsul.api import get_process_instance\n", "\n", @@ -299,18 +340,22 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:29.338067Z", - "iopub.status.busy": "2024-12-19T17:33:29.337587Z", - "iopub.status.idle": "2024-12-19T17:33:29.342599Z", - "shell.execute_reply": "2024-12-19T17:33:29.341962Z" + "iopub.execute_input": "2024-12-20T14:30:40.946653Z", + "iopub.status.busy": "2024-12-20T14:30:40.946268Z", + "iopub.status.idle": "2024-12-20T14:30:40.960283Z", + "shell.execute_reply": "2024-12-20T14:30:40.959765Z" } }, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "40 + 2 = 42\n" + "ename": "NameError", + "evalue": "name 'process' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[7], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mprocess\u001b[49m\u001b[38;5;241m.\u001b[39ma \u001b[38;5;241m=\u001b[39m \u001b[38;5;241m40\u001b[39m\n\u001b[1;32m 2\u001b[0m process\u001b[38;5;241m.\u001b[39mb \u001b[38;5;241m=\u001b[39m \u001b[38;5;241m2\u001b[39m\n\u001b[1;32m 3\u001b[0m process()\n", + "\u001b[0;31mNameError\u001b[0m: name 'process' is not defined" ] } ], @@ -340,13 +385,25 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:29.344966Z", - "iopub.status.busy": "2024-12-19T17:33:29.344387Z", - "iopub.status.idle": "2024-12-19T17:33:29.349282Z", - "shell.execute_reply": "2024-12-19T17:33:29.348645Z" + "iopub.execute_input": "2024-12-20T14:30:40.962240Z", + "iopub.status.busy": "2024-12-20T14:30:40.961886Z", + "iopub.status.idle": "2024-12-20T14:30:40.976787Z", + "shell.execute_reply": "2024-12-20T14:30:40.976172Z" } }, - "outputs": [], + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'get_process_instance' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[8], line 13\u001b[0m\n\u001b[1;32m 10\u001b[0m f\u001b[38;5;241m.\u001b[39mwrite(\u001b[38;5;28mopen\u001b[39m(a)\u001b[38;5;241m.\u001b[39mread())\n\u001b[1;32m 11\u001b[0m f\u001b[38;5;241m.\u001b[39mwrite(\u001b[38;5;28mopen\u001b[39m(b)\u001b[38;5;241m.\u001b[39mread())\n\u001b[0;32m---> 13\u001b[0m process \u001b[38;5;241m=\u001b[39m \u001b[43mget_process_instance\u001b[49m(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m__main__.cat\u001b[39m\u001b[38;5;124m'\u001b[39m)\n", + "\u001b[0;31mNameError\u001b[0m: name 'get_process_instance' is not defined" + ] + } + ], "source": [ "@xml_process('''\n", "\n", @@ -386,13 +443,28 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:29.351109Z", - "iopub.status.busy": "2024-12-19T17:33:29.350915Z", - "iopub.status.idle": "2024-12-19T17:33:29.357738Z", - "shell.execute_reply": "2024-12-19T17:33:29.357094Z" + "iopub.execute_input": "2024-12-20T14:30:40.978942Z", + "iopub.status.busy": "2024-12-20T14:30:40.978561Z", + "iopub.status.idle": "2024-12-20T14:30:41.036510Z", + "shell.execute_reply": "2024-12-20T14:30:41.035833Z" } }, - "outputs": [], + "outputs": [ + { + "ename": "ModuleNotFoundError", + "evalue": "No module named 'populse_db.storage'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mModuleNotFoundError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[9], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mapi\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Pipeline\n\u001b[1;32m 3\u001b[0m \u001b[38;5;28;01mclass\u001b[39;00m \u001b[38;5;21;01mPipeline1\u001b[39;00m(Pipeline):\n\u001b[1;32m 5\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mpipeline_definition\u001b[39m(\u001b[38;5;28mself\u001b[39m):\n\u001b[1;32m 6\u001b[0m \u001b[38;5;66;03m# Create processes\u001b[39;00m\n", + "File \u001b[0;32m~/work/capsul/capsul/capsul/api.py:41\u001b[0m\n\u001b[1;32m 39\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline_nodes\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Switch\n\u001b[1;32m 40\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline_nodes\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m OptionalOutputSwitch\n\u001b[0;32m---> 41\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mengine\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m capsul_engine\n\u001b[1;32m 42\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mengine\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m activate_configuration\n\u001b[1;32m 43\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mstudy_config\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mprocess_instance\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m get_process_instance\n", + "File \u001b[0;32m~/work/capsul/capsul/capsul/engine/__init__.py:36\u001b[0m\n\u001b[1;32m 33\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01msoma\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01msorted_dictionary\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m SortedDictionary\n\u001b[1;32m 34\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01msoma\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mutils\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mweak_proxy\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m get_ref\n\u001b[0;32m---> 36\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mdatabase_populse\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m PopulseDBEngine\n\u001b[1;32m 38\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01msettings\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Settings\n\u001b[1;32m 39\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mmodule\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m default_modules\n", + "File \u001b[0;32m~/work/capsul/capsul/capsul/engine/database_populse.py:6\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mos\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpath\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m \u001b[38;5;21;01mosp\u001b[39;00m\n\u001b[1;32m 4\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mengine\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mdatabase\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m DatabaseEngine\n\u001b[0;32m----> 6\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mpopulse_db\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mstorage\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Storage\n\u001b[1;32m 8\u001b[0m schemas \u001b[38;5;241m=\u001b[39m [\n\u001b[1;32m 9\u001b[0m {\n\u001b[1;32m 10\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mversion\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m1.0.0\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 39\u001b[0m },\n\u001b[1;32m 40\u001b[0m ]\n\u001b[1;32m 43\u001b[0m \u001b[38;5;28;01mclass\u001b[39;00m \u001b[38;5;21;01mPopulseDBEngine\u001b[39;00m(DatabaseEngine):\n", + "\u001b[0;31mModuleNotFoundError\u001b[0m: No module named 'populse_db.storage'" + ] + } + ], "source": [ "from capsul.api import Pipeline\n", "\n", @@ -425,10 +497,10 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:29.359726Z", - "iopub.status.busy": "2024-12-19T17:33:29.359375Z", - "iopub.status.idle": "2024-12-19T17:33:29.363730Z", - "shell.execute_reply": "2024-12-19T17:33:29.363110Z" + "iopub.execute_input": "2024-12-20T14:30:41.038725Z", + "iopub.status.busy": "2024-12-20T14:30:41.038334Z", + "iopub.status.idle": "2024-12-20T14:30:41.042714Z", + "shell.execute_reply": "2024-12-20T14:30:41.042215Z" } }, "outputs": [], @@ -478,10 +550,10 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:29.365977Z", - "iopub.status.busy": "2024-12-19T17:33:29.365617Z", - "iopub.status.idle": "2024-12-19T17:33:29.369269Z", - "shell.execute_reply": "2024-12-19T17:33:29.368655Z" + "iopub.execute_input": "2024-12-20T14:30:41.044838Z", + "iopub.status.busy": "2024-12-20T14:30:41.044469Z", + "iopub.status.idle": "2024-12-20T14:30:41.047863Z", + "shell.execute_reply": "2024-12-20T14:30:41.047336Z" } }, "outputs": [], @@ -517,13 +589,25 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:29.371276Z", - "iopub.status.busy": "2024-12-19T17:33:29.370832Z", - "iopub.status.idle": "2024-12-19T17:33:29.374498Z", - "shell.execute_reply": "2024-12-19T17:33:29.373990Z" + "iopub.execute_input": "2024-12-20T14:30:41.050201Z", + "iopub.status.busy": "2024-12-20T14:30:41.049806Z", + "iopub.status.idle": "2024-12-20T14:30:41.067232Z", + "shell.execute_reply": "2024-12-20T14:30:41.066651Z" } }, - "outputs": [], + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'Pipeline' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[12], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28;01mclass\u001b[39;00m \u001b[38;5;21;01mPipeline2\u001b[39;00m(\u001b[43mPipeline\u001b[49m):\n\u001b[1;32m 3\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mpipeline_definition\u001b[39m(\u001b[38;5;28mself\u001b[39m):\n\u001b[1;32m 4\u001b[0m \u001b[38;5;66;03m# Create processes\u001b[39;00m\n\u001b[1;32m 5\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39madd_process(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mnode1\u001b[39m\u001b[38;5;124m\"\u001b[39m, Process1())\n", + "\u001b[0;31mNameError\u001b[0m: name 'Pipeline' is not defined" + ] + } + ], "source": [ "class Pipeline2(Pipeline):\n", "\n", @@ -545,13 +629,25 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:29.376413Z", - "iopub.status.busy": "2024-12-19T17:33:29.376055Z", - "iopub.status.idle": "2024-12-19T17:33:29.382033Z", - "shell.execute_reply": "2024-12-19T17:33:29.381366Z" + "iopub.execute_input": "2024-12-20T14:30:41.069167Z", + "iopub.status.busy": "2024-12-20T14:30:41.068829Z", + "iopub.status.idle": "2024-12-20T14:30:41.082628Z", + "shell.execute_reply": "2024-12-20T14:30:41.082024Z" } }, - "outputs": [], + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'Pipeline2' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[13], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m pipeline2 \u001b[38;5;241m=\u001b[39m \u001b[43mPipeline2\u001b[49m()\n\u001b[1;32m 2\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mglobals\u001b[39m()\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124muse_gui\u001b[39m\u001b[38;5;124m'\u001b[39m, \u001b[38;5;28;01mTrue\u001b[39;00m):\n\u001b[1;32m 3\u001b[0m view2 \u001b[38;5;241m=\u001b[39m PipelineDevelopperView(pipeline2)\n", + "\u001b[0;31mNameError\u001b[0m: name 'Pipeline2' is not defined" + ] + } + ], "source": [ "pipeline2 = Pipeline2()\n", "if globals().get('use_gui', True):\n", @@ -579,19 +675,22 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:29.384003Z", - "iopub.status.busy": "2024-12-19T17:33:29.383623Z", - "iopub.status.idle": "2024-12-19T17:33:29.395760Z", - "shell.execute_reply": "2024-12-19T17:33:29.395074Z" + "iopub.execute_input": "2024-12-20T14:30:41.084749Z", + "iopub.status.busy": "2024-12-20T14:30:41.084386Z", + "iopub.status.idle": "2024-12-20T14:30:41.097377Z", + "shell.execute_reply": "2024-12-20T14:30:41.096814Z" } }, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "Process2 execution, a: 0.000000, b: blop\n", - "Process1 execution, f: 13.2 , ff: 0.0\n" + "ename": "NameError", + "evalue": "name 'pipeline2' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[14], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mpipeline2\u001b[49m\u001b[38;5;241m.\u001b[39mf \u001b[38;5;241m=\u001b[39m \u001b[38;5;241m13.2\u001b[39m\n\u001b[1;32m 2\u001b[0m pipeline2\u001b[38;5;241m.\u001b[39mnode_string \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mblop\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 3\u001b[0m pipeline2()\n", + "\u001b[0;31mNameError\u001b[0m: name 'pipeline2' is not defined" ] } ], @@ -621,10 +720,10 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:29.398249Z", - "iopub.status.busy": "2024-12-19T17:33:29.397776Z", - "iopub.status.idle": "2024-12-19T17:33:29.402626Z", - "shell.execute_reply": "2024-12-19T17:33:29.402078Z" + "iopub.execute_input": "2024-12-20T14:30:41.099536Z", + "iopub.status.busy": "2024-12-20T14:30:41.099151Z", + "iopub.status.idle": "2024-12-20T14:30:41.103890Z", + "shell.execute_reply": "2024-12-20T14:30:41.103347Z" }, "scrolled": false }, @@ -693,51 +792,25 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:29.404612Z", - "iopub.status.busy": "2024-12-19T17:33:29.404162Z", - "iopub.status.idle": "2024-12-19T17:33:29.426893Z", - "shell.execute_reply": "2024-12-19T17:33:29.426350Z" + "iopub.execute_input": "2024-12-20T14:30:41.105990Z", + "iopub.status.busy": "2024-12-20T14:30:41.105615Z", + "iopub.status.idle": "2024-12-20T14:30:41.163336Z", + "shell.execute_reply": "2024-12-20T14:30:41.162770Z" } }, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "Auto Generated Pipeline Test\n", - "\n", - ".. note::\n", - "\n", - " * Type 'ProcessMeta.help()' for a full description of this process parameters.\n", - " * Type '.get_input_spec()' for a full description of this process input trait types.\n", - " * Type '.get_output_spec()' for a full description of this process output trait types.\n", - "\n", - "\n", - "Inputs\n", - "~~~~~~\n", - "\n", - "[Mandatory]\n", - "\n", - "nodes_activation: a legal value (['ControllerTrait'] - mandatory)\n", - " No description.\n", - "pdirectory: a string or os.PathLike object (['Directory'] - mandatory)\n", - " test\n", - "value: a float (['Float'] - mandatory)\n", - " test\n", - "enum: a string (['String'] - mandatory)\n", - " test\n", - "list_of_str: a legal value (['List_String'] - mandatory)\n", - " test\n", - "fname: a string or os.PathLike object (['File'] - mandatory)\n", - " test\n", - "\n", - "Outputs\n", - "~~~~~~~\n", - "\n", - "out1: a string (['String'] - mandatory)\n", - " test\n", - "\n" + "ename": "ModuleNotFoundError", + "evalue": "No module named 'populse_db.storage'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mModuleNotFoundError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[16], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mapi\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m get_process_instance\n\u001b[1;32m 3\u001b[0m xmlpipe \u001b[38;5;241m=\u001b[39m get_process_instance(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mcapsul.process.test.xml_pipeline\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 4\u001b[0m xmlpipe\u001b[38;5;241m.\u001b[39mhelp()\n", + "File \u001b[0;32m~/work/capsul/capsul/capsul/api.py:41\u001b[0m\n\u001b[1;32m 39\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline_nodes\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Switch\n\u001b[1;32m 40\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline_nodes\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m OptionalOutputSwitch\n\u001b[0;32m---> 41\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mengine\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m capsul_engine\n\u001b[1;32m 42\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mengine\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m activate_configuration\n\u001b[1;32m 43\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mstudy_config\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mprocess_instance\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m get_process_instance\n", + "File \u001b[0;32m~/work/capsul/capsul/capsul/engine/__init__.py:36\u001b[0m\n\u001b[1;32m 33\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01msoma\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01msorted_dictionary\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m SortedDictionary\n\u001b[1;32m 34\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01msoma\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mutils\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mweak_proxy\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m get_ref\n\u001b[0;32m---> 36\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mdatabase_populse\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m PopulseDBEngine\n\u001b[1;32m 38\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01msettings\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Settings\n\u001b[1;32m 39\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mmodule\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m default_modules\n", + "File \u001b[0;32m~/work/capsul/capsul/capsul/engine/database_populse.py:6\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mos\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpath\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m \u001b[38;5;21;01mosp\u001b[39;00m\n\u001b[1;32m 4\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mengine\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mdatabase\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m DatabaseEngine\n\u001b[0;32m----> 6\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mpopulse_db\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mstorage\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Storage\n\u001b[1;32m 8\u001b[0m schemas \u001b[38;5;241m=\u001b[39m [\n\u001b[1;32m 9\u001b[0m {\n\u001b[1;32m 10\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mversion\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m1.0.0\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 39\u001b[0m },\n\u001b[1;32m 40\u001b[0m ]\n\u001b[1;32m 43\u001b[0m \u001b[38;5;28;01mclass\u001b[39;00m \u001b[38;5;21;01mPopulseDBEngine\u001b[39;00m(DatabaseEngine):\n", + "\u001b[0;31mModuleNotFoundError\u001b[0m: No module named 'populse_db.storage'" ] } ], @@ -766,10 +839,10 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:29.428950Z", - "iopub.status.busy": "2024-12-19T17:33:29.428570Z", - "iopub.status.idle": "2024-12-19T17:33:29.432528Z", - "shell.execute_reply": "2024-12-19T17:33:29.431898Z" + "iopub.execute_input": "2024-12-20T14:30:41.165327Z", + "iopub.status.busy": "2024-12-20T14:30:41.165129Z", + "iopub.status.idle": "2024-12-20T14:30:41.169167Z", + "shell.execute_reply": "2024-12-20T14:30:41.168549Z" } }, "outputs": [], @@ -813,13 +886,25 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:29.434755Z", - "iopub.status.busy": "2024-12-19T17:33:29.434304Z", - "iopub.status.idle": "2024-12-19T17:33:29.438129Z", - "shell.execute_reply": "2024-12-19T17:33:29.437591Z" + "iopub.execute_input": "2024-12-20T14:30:41.171328Z", + "iopub.status.busy": "2024-12-20T14:30:41.170932Z", + "iopub.status.idle": "2024-12-20T14:30:41.186014Z", + "shell.execute_reply": "2024-12-20T14:30:41.185415Z" } }, - "outputs": [], + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'Pipeline' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[18], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28;01mclass\u001b[39;00m \u001b[38;5;21;01mPipeline3\u001b[39;00m(\u001b[43mPipeline\u001b[49m):\n\u001b[1;32m 3\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mpipeline_definition\u001b[39m(\u001b[38;5;28mself\u001b[39m):\n\u001b[1;32m 4\u001b[0m \u001b[38;5;66;03m# Create processes\u001b[39;00m\n\u001b[1;32m 5\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39madd_process(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mnode1\u001b[39m\u001b[38;5;124m\"\u001b[39m, Process1())\n", + "\u001b[0;31mNameError\u001b[0m: name 'Pipeline' is not defined" + ] + } + ], "source": [ "class Pipeline3(Pipeline):\n", " \n", @@ -841,13 +926,25 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:29.440181Z", - "iopub.status.busy": "2024-12-19T17:33:29.439808Z", - "iopub.status.idle": "2024-12-19T17:33:29.447085Z", - "shell.execute_reply": "2024-12-19T17:33:29.446568Z" + "iopub.execute_input": "2024-12-20T14:30:41.188029Z", + "iopub.status.busy": "2024-12-20T14:30:41.187675Z", + "iopub.status.idle": "2024-12-20T14:30:41.201968Z", + "shell.execute_reply": "2024-12-20T14:30:41.201309Z" } }, - "outputs": [], + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'Pipeline3' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[19], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m pipeline3 \u001b[38;5;241m=\u001b[39m \u001b[43mPipeline3\u001b[49m()\n\u001b[1;32m 2\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mglobals\u001b[39m()\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124muse_gui\u001b[39m\u001b[38;5;124m'\u001b[39m, \u001b[38;5;28;01mTrue\u001b[39;00m):\n\u001b[1;32m 3\u001b[0m view3 \u001b[38;5;241m=\u001b[39m PipelineDevelopperView(pipeline3, allow_open_controller\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m, show_sub_pipelines\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m)\n", + "\u001b[0;31mNameError\u001b[0m: name 'Pipeline3' is not defined" + ] + } + ], "source": [ "pipeline3 = Pipeline3()\n", "if globals().get('use_gui', True):\n", @@ -875,13 +972,25 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:29.448938Z", - "iopub.status.busy": "2024-12-19T17:33:29.448743Z", - "iopub.status.idle": "2024-12-19T17:33:29.452351Z", - "shell.execute_reply": "2024-12-19T17:33:29.451811Z" + "iopub.execute_input": "2024-12-20T14:30:41.204075Z", + "iopub.status.busy": "2024-12-20T14:30:41.203716Z", + "iopub.status.idle": "2024-12-20T14:30:41.217386Z", + "shell.execute_reply": "2024-12-20T14:30:41.216776Z" } }, - "outputs": [], + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'pipeline3' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[20], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mpipeline3\u001b[49m\u001b[38;5;241m.\u001b[39mswitch \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mcase2\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 3\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mglobals\u001b[39m()\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124muse_gui\u001b[39m\u001b[38;5;124m'\u001b[39m, \u001b[38;5;28;01mTrue\u001b[39;00m):\n\u001b[1;32m 4\u001b[0m view3\u001b[38;5;241m.\u001b[39mshow()\n", + "\u001b[0;31mNameError\u001b[0m: name 'pipeline3' is not defined" + ] + } + ], "source": [ "pipeline3.switch = \"case2\"\n", "\n", @@ -899,18 +1008,22 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:29.454122Z", - "iopub.status.busy": "2024-12-19T17:33:29.453920Z", - "iopub.status.idle": "2024-12-19T17:33:29.464340Z", - "shell.execute_reply": "2024-12-19T17:33:29.463668Z" + "iopub.execute_input": "2024-12-20T14:30:41.219344Z", + "iopub.status.busy": "2024-12-20T14:30:41.218970Z", + "iopub.status.idle": "2024-12-20T14:30:41.231766Z", + "shell.execute_reply": "2024-12-20T14:30:41.231130Z" } }, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "Process2 execution, a: 0.000000, b: yup\n" + "ename": "NameError", + "evalue": "name 'pipeline3' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[21], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mpipeline3\u001b[49m(b\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124myup\u001b[39m\u001b[38;5;124m'\u001b[39m)\n", + "\u001b[0;31mNameError\u001b[0m: name 'pipeline3' is not defined" ] } ], @@ -936,10 +1049,10 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:29.466647Z", - "iopub.status.busy": "2024-12-19T17:33:29.466225Z", - "iopub.status.idle": "2024-12-19T17:33:29.471144Z", - "shell.execute_reply": "2024-12-19T17:33:29.470616Z" + "iopub.execute_input": "2024-12-20T14:30:41.233918Z", + "iopub.status.busy": "2024-12-20T14:30:41.233552Z", + "iopub.status.idle": "2024-12-20T14:30:41.237934Z", + "shell.execute_reply": "2024-12-20T14:30:41.237309Z" } }, "outputs": [ @@ -1083,52 +1196,25 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:29.473243Z", - "iopub.status.busy": "2024-12-19T17:33:29.472811Z", - "iopub.status.idle": "2024-12-19T17:33:29.503406Z", - "shell.execute_reply": "2024-12-19T17:33:29.502895Z" + "iopub.execute_input": "2024-12-20T14:30:41.239966Z", + "iopub.status.busy": "2024-12-20T14:30:41.239616Z", + "iopub.status.idle": "2024-12-20T14:30:41.295298Z", + "shell.execute_reply": "2024-12-20T14:30:41.294722Z" } }, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "\n", - "\n", - "\n", - ".. note::\n", - "\n", - " * Type 'test_pipeline.help()' for a full description of this process parameters.\n", - " * Type '.get_input_spec()' for a full description of this process input trait types.\n", - " * Type '.get_output_spec()' for a full description of this process output trait types.\n", - "\n", - "\n", - "Inputs\n", - "~~~~~~\n", - "\n", - "[Mandatory]\n", - "\n", - "nodes_activation: a legal value (['ControllerTrait'] - mandatory)\n", - " No description.\n", - "input_image: a string or os.PathLike object (['File'] - mandatory)\n", - " Path of a NIFTI-1 image file.\n", - "select_method: a legal value (['Enum'] - mandatory)\n", - " No description.\n", - "\n", - "Outputs\n", - "~~~~~~~\n", - "\n", - "output_1: a string or os.PathLike object (['File (filename: output)']\n", - " - mandatory)\n", - " Output file name.\n", - "output_10: a string or os.PathLike object (['File (filename: output)']\n", - " - mandatory)\n", - " Output file name.\n", - "output_100: a string or os.PathLike object (['File (filename:\n", - " output)'] - mandatory)\n", - " Output file name.\n", - "\n" + "ename": "ModuleNotFoundError", + "evalue": "No module named 'populse_db.storage'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mModuleNotFoundError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[23], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mapi\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m get_process_instance\n\u001b[1;32m 3\u001b[0m xmlpipe \u001b[38;5;241m=\u001b[39m get_process_instance(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mcapsul.process.test.test_pipeline\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 4\u001b[0m xmlpipe\u001b[38;5;241m.\u001b[39mhelp()\n", + "File \u001b[0;32m~/work/capsul/capsul/capsul/api.py:41\u001b[0m\n\u001b[1;32m 39\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline_nodes\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Switch\n\u001b[1;32m 40\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline_nodes\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m OptionalOutputSwitch\n\u001b[0;32m---> 41\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mengine\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m capsul_engine\n\u001b[1;32m 42\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mengine\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m activate_configuration\n\u001b[1;32m 43\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mstudy_config\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mprocess_instance\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m get_process_instance\n", + "File \u001b[0;32m~/work/capsul/capsul/capsul/engine/__init__.py:36\u001b[0m\n\u001b[1;32m 33\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01msoma\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01msorted_dictionary\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m SortedDictionary\n\u001b[1;32m 34\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01msoma\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mutils\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mweak_proxy\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m get_ref\n\u001b[0;32m---> 36\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mdatabase_populse\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m PopulseDBEngine\n\u001b[1;32m 38\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01msettings\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Settings\n\u001b[1;32m 39\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mmodule\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m default_modules\n", + "File \u001b[0;32m~/work/capsul/capsul/capsul/engine/database_populse.py:6\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mos\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpath\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m \u001b[38;5;21;01mosp\u001b[39;00m\n\u001b[1;32m 4\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mengine\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mdatabase\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m DatabaseEngine\n\u001b[0;32m----> 6\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mpopulse_db\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mstorage\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Storage\n\u001b[1;32m 8\u001b[0m schemas \u001b[38;5;241m=\u001b[39m [\n\u001b[1;32m 9\u001b[0m {\n\u001b[1;32m 10\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mversion\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m1.0.0\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 39\u001b[0m },\n\u001b[1;32m 40\u001b[0m ]\n\u001b[1;32m 43\u001b[0m \u001b[38;5;28;01mclass\u001b[39;00m \u001b[38;5;21;01mPopulseDBEngine\u001b[39;00m(DatabaseEngine):\n", + "\u001b[0;31mModuleNotFoundError\u001b[0m: No module named 'populse_db.storage'" ] } ], @@ -1157,10 +1243,10 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:29.505195Z", - "iopub.status.busy": "2024-12-19T17:33:29.504999Z", - "iopub.status.idle": "2024-12-19T17:33:29.508781Z", - "shell.execute_reply": "2024-12-19T17:33:29.508275Z" + "iopub.execute_input": "2024-12-20T14:30:41.297453Z", + "iopub.status.busy": "2024-12-20T14:30:41.297062Z", + "iopub.status.idle": "2024-12-20T14:30:41.300936Z", + "shell.execute_reply": "2024-12-20T14:30:41.300434Z" } }, "outputs": [], @@ -1200,13 +1286,25 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:29.510803Z", - "iopub.status.busy": "2024-12-19T17:33:29.510490Z", - "iopub.status.idle": "2024-12-19T17:33:29.514904Z", - "shell.execute_reply": "2024-12-19T17:33:29.514282Z" + "iopub.execute_input": "2024-12-20T14:30:41.302817Z", + "iopub.status.busy": "2024-12-20T14:30:41.302632Z", + "iopub.status.idle": "2024-12-20T14:30:41.320043Z", + "shell.execute_reply": "2024-12-20T14:30:41.319412Z" } }, - "outputs": [], + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'Pipeline' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[25], line 17\u001b[0m\n\u001b[1;32m 9\u001b[0m \u001b[38;5;129m@xml_process\u001b[39m(\u001b[38;5;124m'''\u001b[39m\u001b[38;5;124m\u001b[39m\n\u001b[1;32m 10\u001b[0m \u001b[38;5;124m \u001b[39m\n\u001b[1;32m 11\u001b[0m \u001b[38;5;124m \u001b[39m\n\u001b[1;32m 12\u001b[0m \u001b[38;5;124m\u001b[39m\n\u001b[1;32m 13\u001b[0m \u001b[38;5;124m'''\u001b[39m)\n\u001b[1;32m 14\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21madd_12\u001b[39m(a):\n\u001b[1;32m 15\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m a \u001b[38;5;241m+\u001b[39m \u001b[38;5;241m12\u001b[39m\n\u001b[0;32m---> 17\u001b[0m \u001b[38;5;28;01mclass\u001b[39;00m \u001b[38;5;21;01mPipeline4\u001b[39;00m(\u001b[43mPipeline\u001b[49m):\n\u001b[1;32m 19\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mpipeline_definition\u001b[39m(\u001b[38;5;28mself\u001b[39m):\n\u001b[1;32m 20\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39madd_iterative_process(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124madd_12\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m'\u001b[39m\u001b[38;5;124m__main__.add_12\u001b[39m\u001b[38;5;124m'\u001b[39m, iterative_plugs\u001b[38;5;241m=\u001b[39m[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124ma\u001b[39m\u001b[38;5;124m'\u001b[39m, \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mb\u001b[39m\u001b[38;5;124m'\u001b[39m])\n", + "\u001b[0;31mNameError\u001b[0m: name 'Pipeline' is not defined" + ] + } + ], "source": [ "@xml_process('''\n", " \n", @@ -1240,13 +1338,25 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:29.517027Z", - "iopub.status.busy": "2024-12-19T17:33:29.516675Z", - "iopub.status.idle": "2024-12-19T17:33:29.523976Z", - "shell.execute_reply": "2024-12-19T17:33:29.523365Z" + "iopub.execute_input": "2024-12-20T14:30:41.322077Z", + "iopub.status.busy": "2024-12-20T14:30:41.321720Z", + "iopub.status.idle": "2024-12-20T14:30:41.336442Z", + "shell.execute_reply": "2024-12-20T14:30:41.335899Z" } }, - "outputs": [], + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'Pipeline4' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[26], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m pipeline4 \u001b[38;5;241m=\u001b[39m \u001b[43mPipeline4\u001b[49m()\n\u001b[1;32m 2\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mglobals\u001b[39m()\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124muse_gui\u001b[39m\u001b[38;5;124m'\u001b[39m, \u001b[38;5;28;01mTrue\u001b[39;00m):\n\u001b[1;32m 3\u001b[0m view4 \u001b[38;5;241m=\u001b[39m PipelineDevelopperView(pipeline4, allow_open_controller\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m, show_sub_pipelines\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m)\n", + "\u001b[0;31mNameError\u001b[0m: name 'Pipeline4' is not defined" + ] + } + ], "source": [ "pipeline4 = Pipeline4()\n", "if globals().get('use_gui', True):\n", @@ -1291,18 +1401,22 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:29.526223Z", - "iopub.status.busy": "2024-12-19T17:33:29.525843Z", - "iopub.status.idle": "2024-12-19T17:33:29.553274Z", - "shell.execute_reply": "2024-12-19T17:33:29.552754Z" + "iopub.execute_input": "2024-12-20T14:30:41.338654Z", + "iopub.status.busy": "2024-12-20T14:30:41.338266Z", + "iopub.status.idle": "2024-12-20T14:30:41.352472Z", + "shell.execute_reply": "2024-12-20T14:30:41.351899Z" } }, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "54.0\n" + "ename": "NameError", + "evalue": "name 'pipeline4' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[27], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mpipeline4\u001b[49m\u001b[38;5;241m.\u001b[39ma \u001b[38;5;241m=\u001b[39m [\u001b[38;5;241m4.2\u001b[39m, \u001b[38;5;241m6.8\u001b[39m, \u001b[38;5;241m7.\u001b[39m]\n\u001b[1;32m 2\u001b[0m pipeline4()\n\u001b[1;32m 3\u001b[0m \u001b[38;5;28mprint\u001b[39m(pipeline4\u001b[38;5;241m.\u001b[39maddition)\n", + "\u001b[0;31mNameError\u001b[0m: name 'pipeline4' is not defined" ] } ], @@ -1332,13 +1446,25 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:29.555280Z", - "iopub.status.busy": "2024-12-19T17:33:29.554896Z", - "iopub.status.idle": "2024-12-19T17:33:29.560422Z", - "shell.execute_reply": "2024-12-19T17:33:29.559900Z" + "iopub.execute_input": "2024-12-20T14:30:41.354522Z", + "iopub.status.busy": "2024-12-20T14:30:41.354165Z", + "iopub.status.idle": "2024-12-20T14:30:41.373631Z", + "shell.execute_reply": "2024-12-20T14:30:41.373015Z" } }, - "outputs": [], + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'Pipeline' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[28], line 21\u001b[0m\n\u001b[1;32m 18\u001b[0m \u001b[38;5;28;01mwith\u001b[39;00m \u001b[38;5;28mopen\u001b[39m(b, \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mw\u001b[39m\u001b[38;5;124m'\u001b[39m) \u001b[38;5;28;01mas\u001b[39;00m f:\n\u001b[1;32m 19\u001b[0m f\u001b[38;5;241m.\u001b[39mwrite(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;241m.\u001b[39mjoin([l\u001b[38;5;241m.\u001b[39mreplace(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m*\u001b[39m\u001b[38;5;124m'\u001b[39m, \u001b[38;5;124m'\u001b[39m\u001b[38;5;124m^\u001b[39m\u001b[38;5;124m'\u001b[39m) \u001b[38;5;28;01mfor\u001b[39;00m l \u001b[38;5;129;01min\u001b[39;00m lines]))\n\u001b[0;32m---> 21\u001b[0m \u001b[38;5;28;01mclass\u001b[39;00m \u001b[38;5;21;01mPipeline5\u001b[39;00m(\u001b[43mPipeline\u001b[49m):\n\u001b[1;32m 23\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mpipeline_definition\u001b[39m(\u001b[38;5;28mself\u001b[39m):\n\u001b[1;32m 24\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39madd_process(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mnode1\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m'\u001b[39m\u001b[38;5;124m__main__.node_first\u001b[39m\u001b[38;5;124m'\u001b[39m)\n", + "\u001b[0;31mNameError\u001b[0m: name 'Pipeline' is not defined" + ] + } + ], "source": [ "@xml_process('''\n", " \n", @@ -1377,13 +1503,25 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:29.562421Z", - "iopub.status.busy": "2024-12-19T17:33:29.562117Z", - "iopub.status.idle": "2024-12-19T17:33:29.568571Z", - "shell.execute_reply": "2024-12-19T17:33:29.568059Z" + "iopub.execute_input": "2024-12-20T14:30:41.375618Z", + "iopub.status.busy": "2024-12-20T14:30:41.375262Z", + "iopub.status.idle": "2024-12-20T14:30:41.389095Z", + "shell.execute_reply": "2024-12-20T14:30:41.388551Z" } }, - "outputs": [], + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'Pipeline5' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[29], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m pipeline5 \u001b[38;5;241m=\u001b[39m \u001b[43mPipeline5\u001b[49m()\n\u001b[1;32m 2\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mglobals\u001b[39m()\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124muse_gui\u001b[39m\u001b[38;5;124m'\u001b[39m, \u001b[38;5;28;01mTrue\u001b[39;00m):\n\u001b[1;32m 3\u001b[0m view5 \u001b[38;5;241m=\u001b[39m PipelineDevelopperView(pipeline5, allow_open_controller\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m, show_sub_pipelines\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m)\n", + "\u001b[0;31mNameError\u001b[0m: name 'Pipeline5' is not defined" + ] + } + ], "source": [ "pipeline5 = Pipeline5()\n", "if globals().get('use_gui', True):\n", @@ -1413,19 +1551,22 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:29.570517Z", - "iopub.status.busy": "2024-12-19T17:33:29.570206Z", - "iopub.status.idle": "2024-12-19T17:33:29.576652Z", - "shell.execute_reply": "2024-12-19T17:33:29.576145Z" + "iopub.execute_input": "2024-12-20T14:30:41.391042Z", + "iopub.status.busy": "2024-12-20T14:30:41.390678Z", + "iopub.status.idle": "2024-12-20T14:30:41.406158Z", + "shell.execute_reply": "2024-12-20T14:30:41.405559Z" } }, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "^ I ate 5 cakes this morning. ^\n", - "^ Let's eat 3 or 4 more. ^\n" + "ename": "NameError", + "evalue": "name 'pipeline5' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[30], line 5\u001b[0m\n\u001b[1;32m 3\u001b[0m intermediate \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m'\u001b[39m\u001b[38;5;124m/tmp/dummy_intermediate.txt\u001b[39m\u001b[38;5;124m'\u001b[39m\n\u001b[1;32m 4\u001b[0m \u001b[38;5;28mopen\u001b[39m(infile, \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mw\u001b[39m\u001b[38;5;124m'\u001b[39m)\u001b[38;5;241m.\u001b[39mwrite(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mI ate 5 cakes this morning.\u001b[39m\u001b[38;5;130;01m\\n\u001b[39;00m\u001b[38;5;124mLet\u001b[39m\u001b[38;5;130;01m\\'\u001b[39;00m\u001b[38;5;124ms eat 3 or 4 more.\u001b[39m\u001b[38;5;130;01m\\n\u001b[39;00m\u001b[38;5;124m'\u001b[39m)\n\u001b[0;32m----> 5\u001b[0m \u001b[43mpipeline5\u001b[49m\u001b[38;5;241m.\u001b[39minput \u001b[38;5;241m=\u001b[39m infile\n\u001b[1;32m 6\u001b[0m pipeline5\u001b[38;5;241m.\u001b[39mb \u001b[38;5;241m=\u001b[39m outfile\n\u001b[1;32m 7\u001b[0m pipeline5\u001b[38;5;241m.\u001b[39mintermediate \u001b[38;5;241m=\u001b[39m intermediate\n", + "\u001b[0;31mNameError\u001b[0m: name 'pipeline5' is not defined" ] } ], @@ -1449,13 +1590,25 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:29.578672Z", - "iopub.status.busy": "2024-12-19T17:33:29.578297Z", - "iopub.status.idle": "2024-12-19T17:33:29.581228Z", - "shell.execute_reply": "2024-12-19T17:33:29.580704Z" + "iopub.execute_input": "2024-12-20T14:30:41.408264Z", + "iopub.status.busy": "2024-12-20T14:30:41.407790Z", + "iopub.status.idle": "2024-12-20T14:30:41.420506Z", + "shell.execute_reply": "2024-12-20T14:30:41.419910Z" } }, - "outputs": [], + "outputs": [ + { + "ename": "FileNotFoundError", + "evalue": "[Errno 2] No such file or directory: '/tmp/dummy_modified.txt'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mFileNotFoundError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[31], line 2\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;66;03m# cleanup\u001b[39;00m\n\u001b[0;32m----> 2\u001b[0m \u001b[43mos\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43munlink\u001b[49m\u001b[43m(\u001b[49m\u001b[43moutfile\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 3\u001b[0m os\u001b[38;5;241m.\u001b[39munlink(intermediate)\n", + "\u001b[0;31mFileNotFoundError\u001b[0m: [Errno 2] No such file or directory: '/tmp/dummy_modified.txt'" + ] + } + ], "source": [ "# cleanup\n", "os.unlink(outfile)\n", @@ -1480,13 +1633,25 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:29.583163Z", - "iopub.status.busy": "2024-12-19T17:33:29.582864Z", - "iopub.status.idle": "2024-12-19T17:33:29.586714Z", - "shell.execute_reply": "2024-12-19T17:33:29.586205Z" + "iopub.execute_input": "2024-12-20T14:30:41.422657Z", + "iopub.status.busy": "2024-12-20T14:30:41.422302Z", + "iopub.status.idle": "2024-12-20T14:30:41.437212Z", + "shell.execute_reply": "2024-12-20T14:30:41.436611Z" } }, - "outputs": [], + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'Pipeline' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[32], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28;01mclass\u001b[39;00m \u001b[38;5;21;01mPipeline6\u001b[39;00m(\u001b[43mPipeline\u001b[49m):\n\u001b[1;32m 3\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21mpipeline_definition\u001b[39m(\u001b[38;5;28mself\u001b[39m):\n\u001b[1;32m 4\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39madd_process(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mnode1\u001b[39m\u001b[38;5;124m\"\u001b[39m, \u001b[38;5;124m'\u001b[39m\u001b[38;5;124m__main__.node_first\u001b[39m\u001b[38;5;124m'\u001b[39m)\n", + "\u001b[0;31mNameError\u001b[0m: name 'Pipeline' is not defined" + ] + } + ], "source": [ "class Pipeline6(Pipeline):\n", " \n", @@ -1507,13 +1672,25 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:29.588749Z", - "iopub.status.busy": "2024-12-19T17:33:29.588378Z", - "iopub.status.idle": "2024-12-19T17:33:29.595993Z", - "shell.execute_reply": "2024-12-19T17:33:29.595493Z" + "iopub.execute_input": "2024-12-20T14:30:41.439277Z", + "iopub.status.busy": "2024-12-20T14:30:41.438881Z", + "iopub.status.idle": "2024-12-20T14:30:41.453137Z", + "shell.execute_reply": "2024-12-20T14:30:41.452476Z" } }, - "outputs": [], + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'Pipeline6' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[33], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m pipeline6 \u001b[38;5;241m=\u001b[39m \u001b[43mPipeline6\u001b[49m()\n\u001b[1;32m 2\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mglobals\u001b[39m()\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124muse_gui\u001b[39m\u001b[38;5;124m'\u001b[39m, \u001b[38;5;28;01mTrue\u001b[39;00m):\n\u001b[1;32m 3\u001b[0m view6 \u001b[38;5;241m=\u001b[39m PipelineDevelopperView(pipeline6, allow_open_controller\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m, show_sub_pipelines\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m)\n", + "\u001b[0;31mNameError\u001b[0m: name 'Pipeline6' is not defined" + ] + } + ], "source": [ "pipeline6 = Pipeline6()\n", "if globals().get('use_gui', True):\n", @@ -1543,19 +1720,22 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:29.597905Z", - "iopub.status.busy": "2024-12-19T17:33:29.597694Z", - "iopub.status.idle": "2024-12-19T17:33:29.603844Z", - "shell.execute_reply": "2024-12-19T17:33:29.603308Z" + "iopub.execute_input": "2024-12-20T14:30:41.455321Z", + "iopub.status.busy": "2024-12-20T14:30:41.454877Z", + "iopub.status.idle": "2024-12-20T14:30:41.468080Z", + "shell.execute_reply": "2024-12-20T14:30:41.467572Z" } }, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "^ I ate 5 cakes this morning. ^\n", - "^ Let's eat 3 or 4 more. ^\n" + "ename": "NameError", + "evalue": "name 'pipeline6' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[34], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mpipeline6\u001b[49m\u001b[38;5;241m.\u001b[39minput \u001b[38;5;241m=\u001b[39m infile\n\u001b[1;32m 2\u001b[0m pipeline6\u001b[38;5;241m.\u001b[39mb \u001b[38;5;241m=\u001b[39m outfile\n\u001b[1;32m 3\u001b[0m pipeline6()\n", + "\u001b[0;31mNameError\u001b[0m: name 'pipeline6' is not defined" ] } ], @@ -1574,13 +1754,25 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:29.605833Z", - "iopub.status.busy": "2024-12-19T17:33:29.605429Z", - "iopub.status.idle": "2024-12-19T17:33:29.608437Z", - "shell.execute_reply": "2024-12-19T17:33:29.607906Z" + "iopub.execute_input": "2024-12-20T14:30:41.470095Z", + "iopub.status.busy": "2024-12-20T14:30:41.469738Z", + "iopub.status.idle": "2024-12-20T14:30:41.482373Z", + "shell.execute_reply": "2024-12-20T14:30:41.481859Z" } }, - "outputs": [], + "outputs": [ + { + "ename": "FileNotFoundError", + "evalue": "[Errno 2] No such file or directory: '/tmp/dummy_modified.txt'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mFileNotFoundError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[35], line 2\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;66;03m# cleanup\u001b[39;00m\n\u001b[0;32m----> 2\u001b[0m \u001b[43mos\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43munlink\u001b[49m\u001b[43m(\u001b[49m\u001b[43moutfile\u001b[49m\u001b[43m)\u001b[49m\n", + "\u001b[0;31mFileNotFoundError\u001b[0m: [Errno 2] No such file or directory: '/tmp/dummy_modified.txt'" + ] + } + ], "source": [ "# cleanup\n", "os.unlink(outfile)" @@ -1594,13 +1786,25 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:29.610410Z", - "iopub.status.busy": "2024-12-19T17:33:29.610063Z", - "iopub.status.idle": "2024-12-19T17:33:29.613310Z", - "shell.execute_reply": "2024-12-19T17:33:29.612683Z" + "iopub.execute_input": "2024-12-20T14:30:41.484260Z", + "iopub.status.busy": "2024-12-20T14:30:41.483915Z", + "iopub.status.idle": "2024-12-20T14:30:41.496550Z", + "shell.execute_reply": "2024-12-20T14:30:41.495946Z" } }, - "outputs": [], + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'pipeline6' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[36], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mpipeline6\u001b[49m\u001b[38;5;241m.\u001b[39mintermediate \u001b[38;5;241m=\u001b[39m intermediate\n", + "\u001b[0;31mNameError\u001b[0m: name 'pipeline6' is not defined" + ] + } + ], "source": [ "pipeline6.intermediate = intermediate" ] @@ -1613,10 +1817,10 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:29.615392Z", - "iopub.status.busy": "2024-12-19T17:33:29.615044Z", - "iopub.status.idle": "2024-12-19T17:33:29.618224Z", - "shell.execute_reply": "2024-12-19T17:33:29.617614Z" + "iopub.execute_input": "2024-12-20T14:30:41.498683Z", + "iopub.status.busy": "2024-12-20T14:30:41.498223Z", + "iopub.status.idle": "2024-12-20T14:30:41.501403Z", + "shell.execute_reply": "2024-12-20T14:30:41.500888Z" } }, "outputs": [], @@ -1647,19 +1851,22 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:29.620311Z", - "iopub.status.busy": "2024-12-19T17:33:29.619942Z", - "iopub.status.idle": "2024-12-19T17:33:29.625096Z", - "shell.execute_reply": "2024-12-19T17:33:29.624541Z" + "iopub.execute_input": "2024-12-20T14:30:41.503376Z", + "iopub.status.busy": "2024-12-20T14:30:41.503002Z", + "iopub.status.idle": "2024-12-20T14:30:41.515787Z", + "shell.execute_reply": "2024-12-20T14:30:41.515264Z" } }, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "* I ate 5 cakes this morning. *\n", - "* Let's eat 3 or 4 more. *\n" + "ename": "NameError", + "evalue": "name 'pipeline6' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[38], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mpipeline6\u001b[49m()\n\u001b[1;32m 2\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;28mopen\u001b[39m(intermediate)\u001b[38;5;241m.\u001b[39mread())\n", + "\u001b[0;31mNameError\u001b[0m: name 'pipeline6' is not defined" ] } ], @@ -1676,13 +1883,25 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:29.626947Z", - "iopub.status.busy": "2024-12-19T17:33:29.626598Z", - "iopub.status.idle": "2024-12-19T17:33:29.629845Z", - "shell.execute_reply": "2024-12-19T17:33:29.629231Z" + "iopub.execute_input": "2024-12-20T14:30:41.517634Z", + "iopub.status.busy": "2024-12-20T14:30:41.517438Z", + "iopub.status.idle": "2024-12-20T14:30:41.534432Z", + "shell.execute_reply": "2024-12-20T14:30:41.533898Z" } }, - "outputs": [], + "outputs": [ + { + "ename": "FileNotFoundError", + "evalue": "[Errno 2] No such file or directory: '/tmp/dummy_modified.txt'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mFileNotFoundError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[39], line 2\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;66;03m# cleanup\u001b[39;00m\n\u001b[0;32m----> 2\u001b[0m \u001b[43mos\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43munlink\u001b[49m\u001b[43m(\u001b[49m\u001b[43moutfile\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 3\u001b[0m os\u001b[38;5;241m.\u001b[39munlink(intermediate)\n\u001b[1;32m 4\u001b[0m os\u001b[38;5;241m.\u001b[39munlink(infile)\n", + "\u001b[0;31mFileNotFoundError\u001b[0m: [Errno 2] No such file or directory: '/tmp/dummy_modified.txt'" + ] + } + ], "source": [ "# cleanup\n", "os.unlink(outfile)\n", @@ -1732,61 +1951,25 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:29.631844Z", - "iopub.status.busy": "2024-12-19T17:33:29.631501Z", - "iopub.status.idle": "2024-12-19T17:33:29.684950Z", - "shell.execute_reply": "2024-12-19T17:33:29.684305Z" + "iopub.execute_input": "2024-12-20T14:30:41.536434Z", + "iopub.status.busy": "2024-12-20T14:30:41.536055Z", + "iopub.status.idle": "2024-12-20T14:30:41.594423Z", + "shell.execute_reply": "2024-12-20T14:30:41.593873Z" } }, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "create_output_directories : True\n", - "generate_logging : False\n", - "input_directory : \n", - "output_directory : \n", - "process_output_directory : False\n", - "study_name : \n", - "user_level : 0\n", - "afni_path : \n", - "use_afni : \n", - "ants_path : \n", - "use_ants : \n", - "fsl_config : \n", - "fsl_prefix : \n", - "use_fsl : \n", - "matlab_exec : \n", - "use_matlab : False\n", - "mrtrix_path : \n", - "use_mrtrix : \n", - "use_smart_caching : False\n", - "use_soma_workflow : False\n", - "somaworkflow_computing_resource : \n", - "somaworkflow_config_file : \n", - "somaworkflow_keep_failed_workflows : True\n", - "somaworkflow_keep_succeeded_workflows : False\n", - "somaworkflow_computing_resources_config : \n", - "spm_directory : \n", - "spm_standalone : \n", - "spm_version : \n", - "spm_exec : \n", - "spm_mcr_directory : \n", - "use_spm : \n", - "shared_directory : /opt/hostedtoolcache/Python/3.9.20/x64/lib/python3.9/site-packages/share/brainvisa-share-5.2\n", - "input_fom : \n", - "output_fom : \n", - "shared_fom : \n", - "volumes_format : \n", - "meshes_format : \n", - "auto_fom : True\n", - "fom_path : []\n", - "use_fom : True\n", - "attributes_schema_paths : ['capsul.attributes.completion_engine_factory']\n", - "attributes_schemas : {}\n", - "process_completion : builtin\n", - "path_completion : \n" + "ename": "ModuleNotFoundError", + "evalue": "No module named 'populse_db.storage'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mModuleNotFoundError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[40], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mapi\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m StudyConfig\n\u001b[1;32m 2\u001b[0m \u001b[38;5;66;03m# optional config modules, need not to be explicitly loaded\u001b[39;00m\n\u001b[1;32m 3\u001b[0m \u001b[38;5;66;03m# from capsul.study_config.config_modules.freesurfer_config import FreeSurferConfig\u001b[39;00m\n\u001b[1;32m 4\u001b[0m \u001b[38;5;66;03m# from capsul.study_config.config_modules.brainvisa_config import BrainVISAConfig\u001b[39;00m\n\u001b[1;32m 6\u001b[0m default_config \u001b[38;5;241m=\u001b[39m {\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124muse_soma_workflow\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;28;01mTrue\u001b[39;00m}\n", + "File \u001b[0;32m~/work/capsul/capsul/capsul/api.py:41\u001b[0m\n\u001b[1;32m 39\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline_nodes\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Switch\n\u001b[1;32m 40\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline_nodes\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m OptionalOutputSwitch\n\u001b[0;32m---> 41\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mengine\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m capsul_engine\n\u001b[1;32m 42\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mengine\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m activate_configuration\n\u001b[1;32m 43\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mstudy_config\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mprocess_instance\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m get_process_instance\n", + "File \u001b[0;32m~/work/capsul/capsul/capsul/engine/__init__.py:36\u001b[0m\n\u001b[1;32m 33\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01msoma\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01msorted_dictionary\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m SortedDictionary\n\u001b[1;32m 34\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01msoma\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mutils\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mweak_proxy\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m get_ref\n\u001b[0;32m---> 36\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mdatabase_populse\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m PopulseDBEngine\n\u001b[1;32m 38\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01msettings\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Settings\n\u001b[1;32m 39\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mmodule\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m default_modules\n", + "File \u001b[0;32m~/work/capsul/capsul/capsul/engine/database_populse.py:6\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mos\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpath\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m \u001b[38;5;21;01mosp\u001b[39;00m\n\u001b[1;32m 4\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mengine\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mdatabase\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m DatabaseEngine\n\u001b[0;32m----> 6\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mpopulse_db\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mstorage\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Storage\n\u001b[1;32m 8\u001b[0m schemas \u001b[38;5;241m=\u001b[39m [\n\u001b[1;32m 9\u001b[0m {\n\u001b[1;32m 10\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mversion\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m1.0.0\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 39\u001b[0m },\n\u001b[1;32m 40\u001b[0m ]\n\u001b[1;32m 43\u001b[0m \u001b[38;5;28;01mclass\u001b[39;00m \u001b[38;5;21;01mPopulseDBEngine\u001b[39;00m(DatabaseEngine):\n", + "\u001b[0;31mModuleNotFoundError\u001b[0m: No module named 'populse_db.storage'" ] } ], @@ -1823,45 +2006,25 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:29.687163Z", - "iopub.status.busy": "2024-12-19T17:33:29.686733Z", - "iopub.status.idle": "2024-12-19T17:33:29.708985Z", - "shell.execute_reply": "2024-12-19T17:33:29.708370Z" + "iopub.execute_input": "2024-12-20T14:30:41.596683Z", + "iopub.status.busy": "2024-12-20T14:30:41.596362Z", + "iopub.status.idle": "2024-12-20T14:30:41.654271Z", + "shell.execute_reply": "2024-12-20T14:30:41.653580Z" } }, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "Method to execute a process or a pipeline in a study configuration\n", - " environment.\n", - "\n", - " Depending on the studies_config settings, it may be a sequential run,\n", - " or a parallel run, which can involve remote execution (through soma-\n", - " workflow).\n", - "\n", - " Only pipeline nodes can be filtered on the 'execute_qc_nodes'\n", - " attribute.\n", - "\n", - " A valid output directory is expected to execute the process or the\n", - " pepeline without soma-workflow.\n", - "\n", - " Parameters\n", - " ----------\n", - " process_or_pipeline: Process or Pipeline instance (mandatory)\n", - " the process or pipeline we want to execute\n", - " output_directory: Directory name (optional)\n", - " the output directory to use for process execution. This replaces\n", - " self.output_directory but left it unchanged.\n", - " execute_qc_nodes: bool (optional, default False)\n", - " if True execute process nodes that are tagged as qualtity control\n", - " process nodes.\n", - " verbose: int\n", - " if different from zero, print console messages.\n", - " configuration_dict: dict (optional)\n", - " configuration dictionary\n", - " \n" + "ename": "ModuleNotFoundError", + "evalue": "No module named 'populse_db.storage'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mModuleNotFoundError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[41], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mapi\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m StudyConfig\n\u001b[1;32m 3\u001b[0m study_config \u001b[38;5;241m=\u001b[39m StudyConfig(\n\u001b[1;32m 4\u001b[0m modules\u001b[38;5;241m=\u001b[39m[\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mFSLConfig\u001b[39m\u001b[38;5;124m\"\u001b[39m],\n\u001b[1;32m 5\u001b[0m fsl_config\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m/etc/fsl/5.0/fsl.sh\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[1;32m 6\u001b[0m use_smart_caching\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mTrue\u001b[39;00m,\n\u001b[1;32m 7\u001b[0m output_directory\u001b[38;5;241m=\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m/tmp/capsul_demo\u001b[39m\u001b[38;5;124m\"\u001b[39m)\n\u001b[1;32m 8\u001b[0m \u001b[38;5;28mprint\u001b[39m(study_config\u001b[38;5;241m.\u001b[39mrun\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__doc__\u001b[39m)\n", + "File \u001b[0;32m~/work/capsul/capsul/capsul/api.py:41\u001b[0m\n\u001b[1;32m 39\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline_nodes\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Switch\n\u001b[1;32m 40\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline_nodes\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m OptionalOutputSwitch\n\u001b[0;32m---> 41\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mengine\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m capsul_engine\n\u001b[1;32m 42\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mengine\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m activate_configuration\n\u001b[1;32m 43\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mstudy_config\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mprocess_instance\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m get_process_instance\n", + "File \u001b[0;32m~/work/capsul/capsul/capsul/engine/__init__.py:36\u001b[0m\n\u001b[1;32m 33\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01msoma\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01msorted_dictionary\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m SortedDictionary\n\u001b[1;32m 34\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01msoma\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mutils\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mweak_proxy\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m get_ref\n\u001b[0;32m---> 36\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mdatabase_populse\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m PopulseDBEngine\n\u001b[1;32m 38\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01msettings\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Settings\n\u001b[1;32m 39\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mmodule\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m default_modules\n", + "File \u001b[0;32m~/work/capsul/capsul/capsul/engine/database_populse.py:6\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mos\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpath\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m \u001b[38;5;21;01mosp\u001b[39;00m\n\u001b[1;32m 4\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mengine\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mdatabase\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m DatabaseEngine\n\u001b[0;32m----> 6\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mpopulse_db\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mstorage\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Storage\n\u001b[1;32m 8\u001b[0m schemas \u001b[38;5;241m=\u001b[39m [\n\u001b[1;32m 9\u001b[0m {\n\u001b[1;32m 10\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mversion\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m1.0.0\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 39\u001b[0m },\n\u001b[1;32m 40\u001b[0m ]\n\u001b[1;32m 43\u001b[0m \u001b[38;5;28;01mclass\u001b[39;00m \u001b[38;5;21;01mPopulseDBEngine\u001b[39;00m(DatabaseEngine):\n", + "\u001b[0;31mModuleNotFoundError\u001b[0m: No module named 'populse_db.storage'" ] } ], @@ -1896,25 +2059,22 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:29.711319Z", - "iopub.status.busy": "2024-12-19T17:33:29.710955Z", - "iopub.status.idle": "2024-12-19T17:33:29.723188Z", - "shell.execute_reply": "2024-12-19T17:33:29.722490Z" + "iopub.execute_input": "2024-12-20T14:30:41.656402Z", + "iopub.status.busy": "2024-12-20T14:30:41.656195Z", + "iopub.status.idle": "2024-12-20T14:30:41.671628Z", + "shell.execute_reply": "2024-12-20T14:30:41.670772Z" } }, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "________________________________________________________________________________\n", - "[Process] Calling __main__.Process2...\n", - "__main__.Process2(b=blop)\n", - "Process2 execution, a: 0.000000, b: blop\n", - "________________________________________________________________________________\n", - "[Process] Calling __main__.Process1...\n", - "__main__.Process1(f=13.2, ff=0.0)\n", - "Process1 execution, f: 13.2 , ff: 0.0\n" + "ename": "NameError", + "evalue": "name 'study_config' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[42], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mstudy_config\u001b[49m\u001b[38;5;241m.\u001b[39mreset_process_counter()\n\u001b[1;32m 2\u001b[0m study_config\u001b[38;5;241m.\u001b[39mrun(pipeline2, verbose\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m1\u001b[39m)\n", + "\u001b[0;31mNameError\u001b[0m: name 'study_config' is not defined" ] } ], @@ -1947,13 +2107,25 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:29.725380Z", - "iopub.status.busy": "2024-12-19T17:33:29.724969Z", - "iopub.status.idle": "2024-12-19T17:33:29.732122Z", - "shell.execute_reply": "2024-12-19T17:33:29.731562Z" + "iopub.execute_input": "2024-12-20T14:30:41.674178Z", + "iopub.status.busy": "2024-12-20T14:30:41.673698Z", + "iopub.status.idle": "2024-12-20T14:30:41.696648Z", + "shell.execute_reply": "2024-12-20T14:30:41.696061Z" } }, - "outputs": [], + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'Process' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[43], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28;01mclass\u001b[39;00m \u001b[38;5;21;01mProcess1\u001b[39;00m(\u001b[43mProcess\u001b[49m):\n\u001b[1;32m 2\u001b[0m f \u001b[38;5;241m=\u001b[39m Float(output\u001b[38;5;241m=\u001b[39m\u001b[38;5;28;01mFalse\u001b[39;00m)\n\u001b[1;32m 4\u001b[0m \u001b[38;5;28;01mdef\u001b[39;00m \u001b[38;5;21m__init__\u001b[39m(\u001b[38;5;28mself\u001b[39m):\n", + "\u001b[0;31mNameError\u001b[0m: name 'Process' is not defined" + ] + } + ], "source": [ "class Process1(Process):\n", " f = Float(output=False)\n", @@ -1996,19 +2168,22 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:29.734161Z", - "iopub.status.busy": "2024-12-19T17:33:29.733782Z", - "iopub.status.idle": "2024-12-19T17:33:29.748980Z", - "shell.execute_reply": "2024-12-19T17:33:29.748444Z" + "iopub.execute_input": "2024-12-20T14:30:41.698819Z", + "iopub.status.busy": "2024-12-20T14:30:41.698449Z", + "iopub.status.idle": "2024-12-20T14:30:41.723396Z", + "shell.execute_reply": "2024-12-20T14:30:41.722746Z" } }, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "jobs: [, ]\n", - "dependencies: {(, )}\n" + "ename": "NameError", + "evalue": "name 'get_process_instance' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[44], line 3\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline_workflow\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m workflow_from_pipeline\n\u001b[0;32m----> 3\u001b[0m pipeline2 \u001b[38;5;241m=\u001b[39m \u001b[43mget_process_instance\u001b[49m(Pipeline2)\n\u001b[1;32m 4\u001b[0m workflow \u001b[38;5;241m=\u001b[39m workflow_from_pipeline(pipeline2)\n\u001b[1;32m 5\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mjobs:\u001b[39m\u001b[38;5;124m'\u001b[39m, workflow\u001b[38;5;241m.\u001b[39mjobs)\n", + "\u001b[0;31mNameError\u001b[0m: name 'get_process_instance' is not defined" ] } ], @@ -2039,43 +2214,23 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:29.751210Z", - "iopub.status.busy": "2024-12-19T17:33:29.750754Z", - "iopub.status.idle": "2024-12-19T17:33:32.813404Z", - "shell.execute_reply": "2024-12-19T17:33:32.812733Z" + "iopub.execute_input": "2024-12-20T14:30:41.725571Z", + "iopub.status.busy": "2024-12-20T14:30:41.725271Z", + "iopub.status.idle": "2024-12-20T14:30:41.740727Z", + "shell.execute_reply": "2024-12-20T14:30:41.740106Z" } }, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "soma-workflow starting in light mode\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "Workflow controller initialised\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "execution status: workflow_done\n" + "ename": "NameError", + "evalue": "name 'workflow' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[45], line 4\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01msoma_workflow\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m client \u001b[38;5;28;01mas\u001b[39;00m swclient\n\u001b[1;32m 3\u001b[0m \u001b[38;5;66;03m# save workflow to disk in json format\u001b[39;00m\n\u001b[0;32m----> 4\u001b[0m swclient\u001b[38;5;241m.\u001b[39mHelper\u001b[38;5;241m.\u001b[39mserialize(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m/tmp/pipeline2.workflow\u001b[39m\u001b[38;5;124m'\u001b[39m, \u001b[43mworkflow\u001b[49m)\n\u001b[1;32m 6\u001b[0m \u001b[38;5;66;03m# run locally via a workflow controller\u001b[39;00m\n\u001b[1;32m 7\u001b[0m wc \u001b[38;5;241m=\u001b[39m swclient\u001b[38;5;241m.\u001b[39mWorkflowController()\n", + "\u001b[0;31mNameError\u001b[0m: name 'workflow' is not defined" ] - }, - { - "data": { - "text/plain": [ - "True" - ] - }, - "execution_count": 45, - "metadata": {}, - "output_type": "execute_result" } ], "source": [ @@ -2110,13 +2265,25 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:32.815701Z", - "iopub.status.busy": "2024-12-19T17:33:32.815532Z", - "iopub.status.idle": "2024-12-19T17:33:32.818590Z", - "shell.execute_reply": "2024-12-19T17:33:32.818106Z" + "iopub.execute_input": "2024-12-20T14:30:41.742922Z", + "iopub.status.busy": "2024-12-20T14:30:41.742529Z", + "iopub.status.idle": "2024-12-20T14:30:41.755784Z", + "shell.execute_reply": "2024-12-20T14:30:41.755156Z" } }, - "outputs": [], + "outputs": [ + { + "ename": "FileNotFoundError", + "evalue": "[Errno 2] No such file or directory: '/tmp/pipeline2.workflow'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mFileNotFoundError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[46], line 2\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mos\u001b[39;00m\n\u001b[0;32m----> 2\u001b[0m \u001b[43mos\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43munlink\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43m/tmp/pipeline2.workflow\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m)\u001b[49m\n", + "\u001b[0;31mFileNotFoundError\u001b[0m: [Errno 2] No such file or directory: '/tmp/pipeline2.workflow'" + ] + } + ], "source": [ "import os\n", "os.unlink('/tmp/pipeline2.workflow')" @@ -2141,19 +2308,22 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:32.820689Z", - "iopub.status.busy": "2024-12-19T17:33:32.820240Z", - "iopub.status.idle": "2024-12-19T17:33:35.874562Z", - "shell.execute_reply": "2024-12-19T17:33:35.873577Z" + "iopub.execute_input": "2024-12-20T14:30:41.757872Z", + "iopub.status.busy": "2024-12-20T14:30:41.757508Z", + "iopub.status.idle": "2024-12-20T14:30:41.770733Z", + "shell.execute_reply": "2024-12-20T14:30:41.770222Z" } }, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "soma-workflow starting in light mode\n", - "Workflow controller initialised\n" + "ename": "NameError", + "evalue": "name 'StudyConfig' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[47], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m study_config \u001b[38;5;241m=\u001b[39m \u001b[43mStudyConfig\u001b[49m(modules\u001b[38;5;241m=\u001b[39m[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mSomaWorkflowConfig\u001b[39m\u001b[38;5;124m'\u001b[39m])\n\u001b[1;32m 2\u001b[0m study_config\u001b[38;5;241m.\u001b[39muse_soma_workflow \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[1;32m 3\u001b[0m study_config\u001b[38;5;241m.\u001b[39mrun(pipeline2)\n", + "\u001b[0;31mNameError\u001b[0m: name 'StudyConfig' is not defined" ] } ], @@ -2182,36 +2352,23 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:35.877251Z", - "iopub.status.busy": "2024-12-19T17:33:35.876880Z", - "iopub.status.idle": "2024-12-19T17:33:38.885695Z", - "shell.execute_reply": "2024-12-19T17:33:38.885106Z" + "iopub.execute_input": "2024-12-20T14:30:41.772705Z", + "iopub.status.busy": "2024-12-20T14:30:41.772329Z", + "iopub.status.idle": "2024-12-20T14:30:41.789038Z", + "shell.execute_reply": "2024-12-20T14:30:41.788527Z" } }, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "del WorkflowController\n" - ] - }, - { - "name": "stdout", - "output_type": "stream", - "text": [ - "workflow id: 3\n" + "ename": "NameError", + "evalue": "name 'study_config' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[48], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mstudy_config\u001b[49m\u001b[38;5;241m.\u001b[39msomaworkflow_keep_succeeded_workflows \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mTrue\u001b[39;00m\n\u001b[1;32m 2\u001b[0m wc \u001b[38;5;241m=\u001b[39m study_config\u001b[38;5;241m.\u001b[39mmodules[\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mSomaWorkflowConfig\u001b[39m\u001b[38;5;124m'\u001b[39m]\u001b[38;5;241m.\u001b[39mget_workflow_controller()\n\u001b[1;32m 3\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m wc \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;129;01mnot\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n", + "\u001b[0;31mNameError\u001b[0m: name 'study_config' is not defined" ] - }, - { - "data": { - "text/plain": [ - "True" - ] - }, - "execution_count": 48, - "metadata": {}, - "output_type": "execute_result" } ], "source": [ @@ -2255,18 +2412,25 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:38.887722Z", - "iopub.status.busy": "2024-12-19T17:33:38.887510Z", - "iopub.status.idle": "2024-12-19T17:33:38.891108Z", - "shell.execute_reply": "2024-12-19T17:33:38.890514Z" + "iopub.execute_input": "2024-12-20T14:30:41.791215Z", + "iopub.status.busy": "2024-12-20T14:30:41.790798Z", + "iopub.status.idle": "2024-12-20T14:30:41.880111Z", + "shell.execute_reply": "2024-12-20T14:30:41.879402Z" } }, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "['AFNIConfig', 'ANTSConfig', 'FSLConfig', 'MatlabConfig', 'MRTRIXConfig', 'SmartCachingConfig', 'SomaWorkflowConfig', 'SPMConfig']\n" + "ename": "ModuleNotFoundError", + "evalue": "No module named 'populse_db.storage'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mModuleNotFoundError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[49], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mapi\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m StudyConfig\n\u001b[1;32m 3\u001b[0m \u001b[38;5;28mprint\u001b[39m(StudyConfig\u001b[38;5;241m.\u001b[39mdefault_modules)\n", + "File \u001b[0;32m~/work/capsul/capsul/capsul/api.py:41\u001b[0m\n\u001b[1;32m 39\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline_nodes\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Switch\n\u001b[1;32m 40\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline_nodes\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m OptionalOutputSwitch\n\u001b[0;32m---> 41\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mengine\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m capsul_engine\n\u001b[1;32m 42\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mengine\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m activate_configuration\n\u001b[1;32m 43\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mstudy_config\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mprocess_instance\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m get_process_instance\n", + "File \u001b[0;32m~/work/capsul/capsul/capsul/engine/__init__.py:36\u001b[0m\n\u001b[1;32m 33\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01msoma\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01msorted_dictionary\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m SortedDictionary\n\u001b[1;32m 34\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01msoma\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mutils\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mweak_proxy\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m get_ref\n\u001b[0;32m---> 36\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mdatabase_populse\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m PopulseDBEngine\n\u001b[1;32m 38\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01msettings\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Settings\n\u001b[1;32m 39\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mmodule\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m default_modules\n", + "File \u001b[0;32m~/work/capsul/capsul/capsul/engine/database_populse.py:6\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mos\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpath\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m \u001b[38;5;21;01mosp\u001b[39;00m\n\u001b[1;32m 4\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mengine\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mdatabase\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m DatabaseEngine\n\u001b[0;32m----> 6\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mpopulse_db\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mstorage\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Storage\n\u001b[1;32m 8\u001b[0m schemas \u001b[38;5;241m=\u001b[39m [\n\u001b[1;32m 9\u001b[0m {\n\u001b[1;32m 10\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mversion\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m1.0.0\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 39\u001b[0m },\n\u001b[1;32m 40\u001b[0m ]\n\u001b[1;32m 43\u001b[0m \u001b[38;5;28;01mclass\u001b[39;00m \u001b[38;5;21;01mPopulseDBEngine\u001b[39;00m(DatabaseEngine):\n", + "\u001b[0;31mModuleNotFoundError\u001b[0m: No module named 'populse_db.storage'" ] } ], @@ -2294,13 +2458,25 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:38.893042Z", - "iopub.status.busy": "2024-12-19T17:33:38.892710Z", - "iopub.status.idle": "2024-12-19T17:33:38.928832Z", - "shell.execute_reply": "2024-12-19T17:33:38.928237Z" + "iopub.execute_input": "2024-12-20T14:30:41.882430Z", + "iopub.status.busy": "2024-12-20T14:30:41.882056Z", + "iopub.status.idle": "2024-12-20T14:30:41.896078Z", + "shell.execute_reply": "2024-12-20T14:30:41.895532Z" } }, - "outputs": [], + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'StudyConfig' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[50], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m study_config \u001b[38;5;241m=\u001b[39m \u001b[43mStudyConfig\u001b[49m(modules\u001b[38;5;241m=\u001b[39mStudyConfig\u001b[38;5;241m.\u001b[39mdefault_modules \u001b[38;5;241m+\u001b[39m [\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mBrainVISAConfig\u001b[39m\u001b[38;5;124m'\u001b[39m, \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mNipypeConfig\u001b[39m\u001b[38;5;124m'\u001b[39m])\n", + "\u001b[0;31mNameError\u001b[0m: name 'StudyConfig' is not defined" + ] + } + ], "source": [ "study_config = StudyConfig(modules=StudyConfig.default_modules + ['BrainVISAConfig', 'NipypeConfig'])" ] @@ -2342,18 +2518,25 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:38.931194Z", - "iopub.status.busy": "2024-12-19T17:33:38.930842Z", - "iopub.status.idle": "2024-12-19T17:33:38.968313Z", - "shell.execute_reply": "2024-12-19T17:33:38.967702Z" + "iopub.execute_input": "2024-12-20T14:30:41.898047Z", + "iopub.status.busy": "2024-12-20T14:30:41.897848Z", + "iopub.status.idle": "2024-12-20T14:30:41.964849Z", + "shell.execute_reply": "2024-12-20T14:30:41.964201Z" } }, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "FSL cannot be configured automatically: FSL command \"bet\" cannot be found in PATH\n" + "ename": "ModuleNotFoundError", + "evalue": "No module named 'populse_db.storage'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mModuleNotFoundError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[51], line 8\u001b[0m\n\u001b[1;32m 4\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mtempfile\u001b[39;00m\n\u001b[1;32m 6\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mtraits\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mapi\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m File, Undefined\n\u001b[0;32m----> 8\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mapi\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m StudyConfig, Process\n\u001b[1;32m 9\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01min_context\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m fsl\n\u001b[1;32m 11\u001b[0m \u001b[38;5;28;01mclass\u001b[39;00m \u001b[38;5;21;01mBet\u001b[39;00m(Process):\n", + "File \u001b[0;32m~/work/capsul/capsul/capsul/api.py:41\u001b[0m\n\u001b[1;32m 39\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline_nodes\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Switch\n\u001b[1;32m 40\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline_nodes\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m OptionalOutputSwitch\n\u001b[0;32m---> 41\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mengine\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m capsul_engine\n\u001b[1;32m 42\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mengine\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m activate_configuration\n\u001b[1;32m 43\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mstudy_config\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mprocess_instance\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m get_process_instance\n", + "File \u001b[0;32m~/work/capsul/capsul/capsul/engine/__init__.py:36\u001b[0m\n\u001b[1;32m 33\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01msoma\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01msorted_dictionary\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m SortedDictionary\n\u001b[1;32m 34\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01msoma\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mutils\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mweak_proxy\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m get_ref\n\u001b[0;32m---> 36\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mdatabase_populse\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m PopulseDBEngine\n\u001b[1;32m 38\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01msettings\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Settings\n\u001b[1;32m 39\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mmodule\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m default_modules\n", + "File \u001b[0;32m~/work/capsul/capsul/capsul/engine/database_populse.py:6\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mos\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpath\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m \u001b[38;5;21;01mosp\u001b[39;00m\n\u001b[1;32m 4\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mengine\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mdatabase\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m DatabaseEngine\n\u001b[0;32m----> 6\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mpopulse_db\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mstorage\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Storage\n\u001b[1;32m 8\u001b[0m schemas \u001b[38;5;241m=\u001b[39m [\n\u001b[1;32m 9\u001b[0m {\n\u001b[1;32m 10\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mversion\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m1.0.0\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 39\u001b[0m },\n\u001b[1;32m 40\u001b[0m ]\n\u001b[1;32m 43\u001b[0m \u001b[38;5;28;01mclass\u001b[39;00m \u001b[38;5;21;01mPopulseDBEngine\u001b[39;00m(DatabaseEngine):\n", + "\u001b[0;31mModuleNotFoundError\u001b[0m: No module named 'populse_db.storage'" ] } ], @@ -2428,18 +2611,25 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:38.970523Z", - "iopub.status.busy": "2024-12-19T17:33:38.970190Z", - "iopub.status.idle": "2024-12-19T17:33:39.001582Z", - "shell.execute_reply": "2024-12-19T17:33:39.000969Z" + "iopub.execute_input": "2024-12-20T14:30:41.966997Z", + "iopub.status.busy": "2024-12-20T14:30:41.966628Z", + "iopub.status.idle": "2024-12-20T14:30:42.025630Z", + "shell.execute_reply": "2024-12-20T14:30:42.025064Z" } }, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "NiPype is not present.\n" + "ename": "ModuleNotFoundError", + "evalue": "No module named 'populse_db.storage'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mModuleNotFoundError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[52], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mapi\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m StudyConfig, get_process_instance\n\u001b[1;32m 2\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01msoma\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpath\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m find_in_path\n\u001b[1;32m 4\u001b[0m study_config \u001b[38;5;241m=\u001b[39m StudyConfig(modules\u001b[38;5;241m=\u001b[39mStudyConfig\u001b[38;5;241m.\u001b[39mdefault_modules \u001b[38;5;241m+\u001b[39m [\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mNipypeConfig\u001b[39m\u001b[38;5;124m'\u001b[39m])\n", + "File \u001b[0;32m~/work/capsul/capsul/capsul/api.py:41\u001b[0m\n\u001b[1;32m 39\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline_nodes\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Switch\n\u001b[1;32m 40\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline_nodes\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m OptionalOutputSwitch\n\u001b[0;32m---> 41\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mengine\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m capsul_engine\n\u001b[1;32m 42\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mengine\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m activate_configuration\n\u001b[1;32m 43\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mstudy_config\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mprocess_instance\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m get_process_instance\n", + "File \u001b[0;32m~/work/capsul/capsul/capsul/engine/__init__.py:36\u001b[0m\n\u001b[1;32m 33\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01msoma\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01msorted_dictionary\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m SortedDictionary\n\u001b[1;32m 34\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01msoma\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mutils\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mweak_proxy\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m get_ref\n\u001b[0;32m---> 36\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mdatabase_populse\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m PopulseDBEngine\n\u001b[1;32m 38\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01msettings\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Settings\n\u001b[1;32m 39\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mmodule\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m default_modules\n", + "File \u001b[0;32m~/work/capsul/capsul/capsul/engine/database_populse.py:6\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mos\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpath\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m \u001b[38;5;21;01mosp\u001b[39;00m\n\u001b[1;32m 4\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mengine\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mdatabase\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m DatabaseEngine\n\u001b[0;32m----> 6\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mpopulse_db\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mstorage\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Storage\n\u001b[1;32m 8\u001b[0m schemas \u001b[38;5;241m=\u001b[39m [\n\u001b[1;32m 9\u001b[0m {\n\u001b[1;32m 10\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mversion\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m1.0.0\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 39\u001b[0m },\n\u001b[1;32m 40\u001b[0m ]\n\u001b[1;32m 43\u001b[0m \u001b[38;5;28;01mclass\u001b[39;00m \u001b[38;5;21;01mPopulseDBEngine\u001b[39;00m(DatabaseEngine):\n", + "\u001b[0;31mModuleNotFoundError\u001b[0m: No module named 'populse_db.storage'" ] } ], @@ -2479,13 +2669,25 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:39.003824Z", - "iopub.status.busy": "2024-12-19T17:33:39.003425Z", - "iopub.status.idle": "2024-12-19T17:33:39.006503Z", - "shell.execute_reply": "2024-12-19T17:33:39.005912Z" + "iopub.execute_input": "2024-12-20T14:30:42.027954Z", + "iopub.status.busy": "2024-12-20T14:30:42.027596Z", + "iopub.status.idle": "2024-12-20T14:30:42.041297Z", + "shell.execute_reply": "2024-12-20T14:30:42.040724Z" } }, - "outputs": [], + "outputs": [ + { + "ename": "NameError", + "evalue": "name 'betpipe' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[53], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[43mbetpipe\u001b[49m:\n\u001b[1;32m 2\u001b[0m study_config\u001b[38;5;241m.\u001b[39mreset_process_counter()\n\u001b[1;32m 3\u001b[0m study_config\u001b[38;5;241m.\u001b[39mrun(betpipe, verbose\u001b[38;5;241m=\u001b[39m\u001b[38;5;241m1\u001b[39m)\n", + "\u001b[0;31mNameError\u001b[0m: name 'betpipe' is not defined" + ] + } + ], "source": [ "if betpipe:\n", " study_config.reset_process_counter()\n", @@ -2512,13 +2714,34 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:39.008410Z", - "iopub.status.busy": "2024-12-19T17:33:39.008251Z", - "iopub.status.idle": "2024-12-19T17:33:39.024611Z", - "shell.execute_reply": "2024-12-19T17:33:39.024128Z" + "iopub.execute_input": "2024-12-20T14:30:42.043426Z", + "iopub.status.busy": "2024-12-20T14:30:42.043051Z", + "iopub.status.idle": "2024-12-20T14:30:42.316622Z", + "shell.execute_reply": "2024-12-20T14:30:42.315904Z" } }, - "outputs": [], + "outputs": [ + { + "ename": "RuntimeError", + "evalue": "ValueError: Invalid process_or_id argument. Got 'capsul.pipeline.test.test_pipeline.DummyProcess' and expect a Process instance/string description or an Interface instance/string description (in pipeline __main__.DemoPipeline when calling add_process('proc1', 'capsul.pipeline.test.test_pipeline.DummyProcess'))", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mValueError\u001b[0m Traceback (most recent call last)", + "File \u001b[0;32m~/work/capsul/capsul/capsul/pipeline/pipeline_construction.py:181\u001b[0m, in \u001b[0;36mConstructedPipeline.pipeline_definition\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 180\u001b[0m method \u001b[38;5;241m=\u001b[39m \u001b[38;5;28mgetattr\u001b[39m(\u001b[38;5;28mself\u001b[39m, method_name)\n\u001b[0;32m--> 181\u001b[0m \u001b[43mmethod\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 182\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m e:\n", + "File \u001b[0;32m~/work/capsul/capsul/capsul/pipeline/pipeline.py:502\u001b[0m, in \u001b[0;36mPipeline.add_process\u001b[0;34m(self, name, process, do_not_export, make_optional, inputs_to_copy, inputs_to_clean, skip_invalid, **kwargs)\u001b[0m\n\u001b[1;32m 501\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 502\u001b[0m process \u001b[38;5;241m=\u001b[39m \u001b[43mget_process_instance\u001b[49m\u001b[43m(\u001b[49m\u001b[43mprocess\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 503\u001b[0m \u001b[43m \u001b[49m\u001b[43mstudy_config\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mstudy_config\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 504\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 505\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m:\n", + "File \u001b[0;32m~/work/capsul/capsul/capsul/study_config/process_instance.py:165\u001b[0m, in \u001b[0;36mget_process_instance\u001b[0;34m(process_or_id, study_config, **kwargs)\u001b[0m\n\u001b[1;32m 164\u001b[0m study_cmod\u001b[38;5;241m.\u001b[39m_default_study_config \u001b[38;5;241m=\u001b[39m study_config\n\u001b[0;32m--> 165\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43m_get_process_instance\u001b[49m\u001b[43m(\u001b[49m\u001b[43mprocess_or_id\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mstudy_config\u001b[49m\u001b[38;5;241;43m=\u001b[39;49m\u001b[43mstudy_config\u001b[49m\u001b[43m,\u001b[49m\n\u001b[1;32m 166\u001b[0m \u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 167\u001b[0m \u001b[38;5;28;01mfinally\u001b[39;00m:\n", + "File \u001b[0;32m~/work/capsul/capsul/capsul/study_config/process_instance.py:418\u001b[0m, in \u001b[0;36m_get_process_instance\u001b[0;34m(process_or_id, study_config, **kwargs)\u001b[0m\n\u001b[1;32m 417\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m result \u001b[38;5;129;01mis\u001b[39;00m \u001b[38;5;28;01mNone\u001b[39;00m:\n\u001b[0;32m--> 418\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mInvalid process_or_id argument. \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 419\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mGot \u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;132;01m{0}\u001b[39;00m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m and expect a Process instance/string \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 420\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mdescription or an Interface instance/string \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 421\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mdescription\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;241m.\u001b[39mformat(process_or_id))\n\u001b[1;32m 423\u001b[0m \u001b[38;5;66;03m# Set the instance default parameters\u001b[39;00m\n", + "\u001b[0;31mValueError\u001b[0m: Invalid process_or_id argument. Got 'capsul.pipeline.test.test_pipeline.DummyProcess' and expect a Process instance/string description or an Interface instance/string description", + "\nDuring handling of the above exception, another exception occurred:\n", + "\u001b[0;31mRuntimeError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[54], line 60\u001b[0m\n\u001b[1;32m 3\u001b[0m xmlstr \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m'''\u001b[39m\u001b[38;5;124m\u001b[39m\n\u001b[1;32m 4\u001b[0m \u001b[38;5;124m \u001b[39m\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 56\u001b[0m \u001b[38;5;124m \u001b[39m\n\u001b[1;32m 57\u001b[0m \u001b[38;5;124m\u001b[39m\u001b[38;5;124m'''\u001b[39m\n\u001b[1;32m 59\u001b[0m DemoPipeline \u001b[38;5;241m=\u001b[39m create_xml_pipeline(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m__main__\u001b[39m\u001b[38;5;124m'\u001b[39m, \u001b[38;5;124m'\u001b[39m\u001b[38;5;124mDemoPipeline\u001b[39m\u001b[38;5;124m'\u001b[39m, xmlstr)\n\u001b[0;32m---> 60\u001b[0m pipeline \u001b[38;5;241m=\u001b[39m \u001b[43mDemoPipeline\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m~/work/capsul/capsul/capsul/pipeline/pipeline.py:258\u001b[0m, in \u001b[0;36mPipeline.__init__\u001b[0;34m(self, autoexport_nodes_parameters, **kwargs)\u001b[0m\n\u001b[1;32m 256\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_disable_update_nodes_and_plugs_activation \u001b[38;5;241m=\u001b[39m \u001b[38;5;241m1\u001b[39m\n\u001b[1;32m 257\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39m_must_update_nodes_and_plugs_activation \u001b[38;5;241m=\u001b[39m \u001b[38;5;28;01mFalse\u001b[39;00m\n\u001b[0;32m--> 258\u001b[0m \u001b[38;5;28;43mself\u001b[39;49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mpipeline_definition\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 260\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mworkflow_repr \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 261\u001b[0m \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mworkflow_list \u001b[38;5;241m=\u001b[39m []\n", + "File \u001b[0;32m~/work/capsul/capsul/capsul/pipeline/pipeline_construction.py:186\u001b[0m, in \u001b[0;36mConstructedPipeline.pipeline_definition\u001b[0;34m(self)\u001b[0m\n\u001b[1;32m 184\u001b[0m l\u001b[38;5;241m.\u001b[39mextend(\u001b[38;5;124m'\u001b[39m\u001b[38;5;132;01m%s\u001b[39;00m\u001b[38;5;124m=\u001b[39m\u001b[38;5;132;01m%s\u001b[39;00m\u001b[38;5;124m'\u001b[39m \u001b[38;5;241m%\u001b[39m (k, \u001b[38;5;28mrepr\u001b[39m(v)) \u001b[38;5;28;01mfor\u001b[39;00m k, v \u001b[38;5;129;01min\u001b[39;00m kwargs\u001b[38;5;241m.\u001b[39mitems())\n\u001b[1;32m 185\u001b[0m m \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m'\u001b[39m\u001b[38;5;132;01m%s\u001b[39;00m\u001b[38;5;124m(\u001b[39m\u001b[38;5;132;01m%s\u001b[39;00m\u001b[38;5;124m)\u001b[39m\u001b[38;5;124m'\u001b[39m \u001b[38;5;241m%\u001b[39m (method_name, \u001b[38;5;124m'\u001b[39m\u001b[38;5;124m, \u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;241m.\u001b[39mjoin(l))\n\u001b[0;32m--> 186\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mRuntimeError\u001b[39;00m(\u001b[38;5;124m'\u001b[39m\u001b[38;5;132;01m%s\u001b[39;00m\u001b[38;5;124m: \u001b[39m\u001b[38;5;132;01m%s\u001b[39;00m\u001b[38;5;124m (in pipeline \u001b[39m\u001b[38;5;132;01m%s\u001b[39;00m\u001b[38;5;124m when calling \u001b[39m\u001b[38;5;132;01m%s\u001b[39;00m\u001b[38;5;124m)\u001b[39m\u001b[38;5;124m'\u001b[39m \u001b[38;5;241m%\u001b[39m\n\u001b[1;32m 187\u001b[0m (e\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__class__\u001b[39m\u001b[38;5;241m.\u001b[39m\u001b[38;5;18m__name__\u001b[39m, \u001b[38;5;28mstr\u001b[39m(e), \u001b[38;5;28mself\u001b[39m\u001b[38;5;241m.\u001b[39mid, m))\n", + "\u001b[0;31mRuntimeError\u001b[0m: ValueError: Invalid process_or_id argument. Got 'capsul.pipeline.test.test_pipeline.DummyProcess' and expect a Process instance/string description or an Interface instance/string description (in pipeline __main__.DemoPipeline when calling add_process('proc1', 'capsul.pipeline.test.test_pipeline.DummyProcess'))" + ] + } + ], "source": [ "from capsul.pipeline.xml import create_xml_pipeline\n", "\n", @@ -2590,10 +2813,10 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:39.026665Z", - "iopub.status.busy": "2024-12-19T17:33:39.026331Z", - "iopub.status.idle": "2024-12-19T17:33:39.029850Z", - "shell.execute_reply": "2024-12-19T17:33:39.029236Z" + "iopub.execute_input": "2024-12-20T14:30:42.318966Z", + "iopub.status.busy": "2024-12-20T14:30:42.318468Z", + "iopub.status.idle": "2024-12-20T14:30:42.322063Z", + "shell.execute_reply": "2024-12-20T14:30:42.321558Z" } }, "outputs": [], @@ -2628,22 +2851,24 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:39.031650Z", - "iopub.status.busy": "2024-12-19T17:33:39.031503Z", - "iopub.status.idle": "2024-12-19T17:33:39.036828Z", - "shell.execute_reply": "2024-12-19T17:33:39.036327Z" + "iopub.execute_input": "2024-12-20T14:30:42.324081Z", + "iopub.status.busy": "2024-12-20T14:30:42.323731Z", + "iopub.status.idle": "2024-12-20T14:30:42.421122Z", + "shell.execute_reply": "2024-12-20T14:30:42.420420Z" } }, "outputs": [ { - "data": { - "text/plain": [ - "1035" - ] - }, - "execution_count": 56, - "metadata": {}, - "output_type": "execute_result" + "ename": "FileNotFoundError", + "evalue": "[Errno 2] No such file or directory: '/tmp/capsul_demo/demo_fom.json'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mFileNotFoundError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[56], line 41\u001b[0m\n\u001b[1;32m 39\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m: os\u001b[38;5;241m.\u001b[39mpath\u001b[38;5;241m.\u001b[39mmakedirs(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m/tmp/capsul_demo\u001b[39m\u001b[38;5;124m'\u001b[39m)\n\u001b[1;32m 40\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m: \u001b[38;5;28;01mpass\u001b[39;00m\n\u001b[0;32m---> 41\u001b[0m \u001b[38;5;28;43mopen\u001b[39;49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43m/tmp/capsul_demo/demo_fom.json\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43mw\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m)\u001b[49m\u001b[38;5;241m.\u001b[39mwrite(fom_content)\n", + "File \u001b[0;32m/opt/hostedtoolcache/Python/3.9.20/x64/lib/python3.9/site-packages/IPython/core/interactiveshell.py:310\u001b[0m, in \u001b[0;36m_modified_open\u001b[0;34m(file, *args, **kwargs)\u001b[0m\n\u001b[1;32m 303\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m file \u001b[38;5;129;01min\u001b[39;00m {\u001b[38;5;241m0\u001b[39m, \u001b[38;5;241m1\u001b[39m, \u001b[38;5;241m2\u001b[39m}:\n\u001b[1;32m 304\u001b[0m \u001b[38;5;28;01mraise\u001b[39;00m \u001b[38;5;167;01mValueError\u001b[39;00m(\n\u001b[1;32m 305\u001b[0m \u001b[38;5;124mf\u001b[39m\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mIPython won\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124mt let you open fd=\u001b[39m\u001b[38;5;132;01m{\u001b[39;00mfile\u001b[38;5;132;01m}\u001b[39;00m\u001b[38;5;124m by default \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 306\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mas it is likely to crash IPython. If you know what you are doing, \u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 307\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124myou can use builtins\u001b[39m\u001b[38;5;124m'\u001b[39m\u001b[38;5;124m open.\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 308\u001b[0m )\n\u001b[0;32m--> 310\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m \u001b[43mio_open\u001b[49m\u001b[43m(\u001b[49m\u001b[43mfile\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43margs\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[38;5;241;43m*\u001b[39;49m\u001b[43mkwargs\u001b[49m\u001b[43m)\u001b[49m\n", + "\u001b[0;31mFileNotFoundError\u001b[0m: [Errno 2] No such file or directory: '/tmp/capsul_demo/demo_fom.json'" + ] } ], "source": [ @@ -2709,18 +2934,25 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:39.038763Z", - "iopub.status.busy": "2024-12-19T17:33:39.038615Z", - "iopub.status.idle": "2024-12-19T17:33:39.128366Z", - "shell.execute_reply": "2024-12-19T17:33:39.127811Z" + "iopub.execute_input": "2024-12-20T14:30:42.423545Z", + "iopub.status.busy": "2024-12-20T14:30:42.423160Z", + "iopub.status.idle": "2024-12-20T14:30:42.490930Z", + "shell.execute_reply": "2024-12-20T14:30:42.490361Z" } }, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "completion engine type: FomProcessCompletionEngine\n" + "ename": "ModuleNotFoundError", + "evalue": "No module named 'populse_db.storage'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mModuleNotFoundError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[57], line 3\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01msys\u001b[39;00m\n\u001b[1;32m 2\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mos\u001b[39;00m\n\u001b[0;32m----> 3\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mapi\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m StudyConfig\n\u001b[1;32m 4\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mattributes\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mcompletion_engine\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m ProcessCompletionEngine\n\u001b[1;32m 5\u001b[0m \u001b[38;5;28;01mif\u001b[39;00m \u001b[38;5;28mglobals\u001b[39m()\u001b[38;5;241m.\u001b[39mget(\u001b[38;5;124m'\u001b[39m\u001b[38;5;124muse_gui\u001b[39m\u001b[38;5;124m'\u001b[39m, \u001b[38;5;28;01mTrue\u001b[39;00m):\n", + "File \u001b[0;32m~/work/capsul/capsul/capsul/api.py:41\u001b[0m\n\u001b[1;32m 39\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline_nodes\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Switch\n\u001b[1;32m 40\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpipeline_nodes\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m OptionalOutputSwitch\n\u001b[0;32m---> 41\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mengine\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m capsul_engine\n\u001b[1;32m 42\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mengine\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m activate_configuration\n\u001b[1;32m 43\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mstudy_config\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mprocess_instance\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m get_process_instance\n", + "File \u001b[0;32m~/work/capsul/capsul/capsul/engine/__init__.py:36\u001b[0m\n\u001b[1;32m 33\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01msoma\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01msorted_dictionary\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m SortedDictionary\n\u001b[1;32m 34\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01msoma\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mutils\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mweak_proxy\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m get_ref\n\u001b[0;32m---> 36\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mdatabase_populse\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m PopulseDBEngine\n\u001b[1;32m 38\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01msettings\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Settings\n\u001b[1;32m 39\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mmodule\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m default_modules\n", + "File \u001b[0;32m~/work/capsul/capsul/capsul/engine/database_populse.py:6\u001b[0m\n\u001b[1;32m 2\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mos\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mpath\u001b[39;00m \u001b[38;5;28;01mas\u001b[39;00m \u001b[38;5;21;01mosp\u001b[39;00m\n\u001b[1;32m 4\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mcapsul\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mengine\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mdatabase\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m DatabaseEngine\n\u001b[0;32m----> 6\u001b[0m \u001b[38;5;28;01mfrom\u001b[39;00m \u001b[38;5;21;01mpopulse_db\u001b[39;00m\u001b[38;5;21;01m.\u001b[39;00m\u001b[38;5;21;01mstorage\u001b[39;00m \u001b[38;5;28;01mimport\u001b[39;00m Storage\n\u001b[1;32m 8\u001b[0m schemas \u001b[38;5;241m=\u001b[39m [\n\u001b[1;32m 9\u001b[0m {\n\u001b[1;32m 10\u001b[0m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mversion\u001b[39m\u001b[38;5;124m\"\u001b[39m: \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124m1.0.0\u001b[39m\u001b[38;5;124m\"\u001b[39m,\n\u001b[0;32m (...)\u001b[0m\n\u001b[1;32m 39\u001b[0m },\n\u001b[1;32m 40\u001b[0m ]\n\u001b[1;32m 43\u001b[0m \u001b[38;5;28;01mclass\u001b[39;00m \u001b[38;5;21;01mPopulseDBEngine\u001b[39;00m(DatabaseEngine):\n", + "\u001b[0;31mModuleNotFoundError\u001b[0m: No module named 'populse_db.storage'" ] } ], @@ -2803,21 +3035,22 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:39.130569Z", - "iopub.status.busy": "2024-12-19T17:33:39.130253Z", - "iopub.status.idle": "2024-12-19T17:33:39.142720Z", - "shell.execute_reply": "2024-12-19T17:33:39.142170Z" + "iopub.execute_input": "2024-12-20T14:30:42.492928Z", + "iopub.status.busy": "2024-12-20T14:30:42.492703Z", + "iopub.status.idle": "2024-12-20T14:30:42.508454Z", + "shell.execute_reply": "2024-12-20T14:30:42.507681Z" } }, "outputs": [ { - "name": "stdout", - "output_type": "stream", - "text": [ - "switch proc_select2 value: proc3\n", - "output image_out5: /data/capsul_demo/subjects_irm2/out_image_irm2_3.nii.gz\n", - "switch proc_select2 value: proc4\n", - "output image_out5: /data/capsul_demo/subjects_irm2/out_image_irm2_4.nii.gz\n" + "ename": "NameError", + "evalue": "name 'mp' is not defined", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mNameError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[58], line 1\u001b[0m\n\u001b[0;32m----> 1\u001b[0m \u001b[43mmp\u001b[49m\u001b[38;5;241m.\u001b[39mproc_select2 \u001b[38;5;241m=\u001b[39m \u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mproc3\u001b[39m\u001b[38;5;124m\"\u001b[39m\n\u001b[1;32m 2\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124mswitch proc_select2 value:\u001b[39m\u001b[38;5;124m\"\u001b[39m, mp\u001b[38;5;241m.\u001b[39mproc_select2)\n\u001b[1;32m 3\u001b[0m \u001b[38;5;28mprint\u001b[39m(\u001b[38;5;124m\"\u001b[39m\u001b[38;5;124moutput image_out5:\u001b[39m\u001b[38;5;124m\"\u001b[39m, mp\u001b[38;5;241m.\u001b[39mimage_out5)\n", + "\u001b[0;31mNameError\u001b[0m: name 'mp' is not defined" ] } ], @@ -2851,13 +3084,27 @@ "deletable": true, "editable": true, "execution": { - "iopub.execute_input": "2024-12-19T17:33:39.144520Z", - "iopub.status.busy": "2024-12-19T17:33:39.144377Z", - "iopub.status.idle": "2024-12-19T17:33:39.147518Z", - "shell.execute_reply": "2024-12-19T17:33:39.147053Z" + "iopub.execute_input": "2024-12-20T14:30:42.511216Z", + "iopub.status.busy": "2024-12-20T14:30:42.510583Z", + "iopub.status.idle": "2024-12-20T14:30:42.663881Z", + "shell.execute_reply": "2024-12-20T14:30:42.663279Z" } }, - "outputs": [], + "outputs": [ + { + "ename": "FileNotFoundError", + "evalue": "[Errno 2] No such file or directory: '/tmp/capsul_demo'", + "output_type": "error", + "traceback": [ + "\u001b[0;31m---------------------------------------------------------------------------\u001b[0m", + "\u001b[0;31mFileNotFoundError\u001b[0m Traceback (most recent call last)", + "Cell \u001b[0;32mIn[59], line 2\u001b[0m\n\u001b[1;32m 1\u001b[0m \u001b[38;5;28;01mimport\u001b[39;00m \u001b[38;5;21;01mshutil\u001b[39;00m\n\u001b[0;32m----> 2\u001b[0m \u001b[43mshutil\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mrmtree\u001b[49m\u001b[43m(\u001b[49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[38;5;124;43m/tmp/capsul_demo\u001b[39;49m\u001b[38;5;124;43m'\u001b[39;49m\u001b[43m)\u001b[49m\n", + "File \u001b[0;32m/opt/hostedtoolcache/Python/3.9.20/x64/lib/python3.9/shutil.py:724\u001b[0m, in \u001b[0;36mrmtree\u001b[0;34m(path, ignore_errors, onerror)\u001b[0m\n\u001b[1;32m 722\u001b[0m orig_st \u001b[38;5;241m=\u001b[39m os\u001b[38;5;241m.\u001b[39mlstat(path)\n\u001b[1;32m 723\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m:\n\u001b[0;32m--> 724\u001b[0m \u001b[43monerror\u001b[49m\u001b[43m(\u001b[49m\u001b[43mos\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mlstat\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43mpath\u001b[49m\u001b[43m,\u001b[49m\u001b[43m \u001b[49m\u001b[43msys\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mexc_info\u001b[49m\u001b[43m(\u001b[49m\u001b[43m)\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 725\u001b[0m \u001b[38;5;28;01mreturn\u001b[39;00m\n\u001b[1;32m 726\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n", + "File \u001b[0;32m/opt/hostedtoolcache/Python/3.9.20/x64/lib/python3.9/shutil.py:722\u001b[0m, in \u001b[0;36mrmtree\u001b[0;34m(path, ignore_errors, onerror)\u001b[0m\n\u001b[1;32m 719\u001b[0m \u001b[38;5;66;03m# Note: To guard against symlink races, we use the standard\u001b[39;00m\n\u001b[1;32m 720\u001b[0m \u001b[38;5;66;03m# lstat()/open()/fstat() trick.\u001b[39;00m\n\u001b[1;32m 721\u001b[0m \u001b[38;5;28;01mtry\u001b[39;00m:\n\u001b[0;32m--> 722\u001b[0m orig_st \u001b[38;5;241m=\u001b[39m \u001b[43mos\u001b[49m\u001b[38;5;241;43m.\u001b[39;49m\u001b[43mlstat\u001b[49m\u001b[43m(\u001b[49m\u001b[43mpath\u001b[49m\u001b[43m)\u001b[49m\n\u001b[1;32m 723\u001b[0m \u001b[38;5;28;01mexcept\u001b[39;00m \u001b[38;5;167;01mException\u001b[39;00m:\n\u001b[1;32m 724\u001b[0m onerror(os\u001b[38;5;241m.\u001b[39mlstat, path, sys\u001b[38;5;241m.\u001b[39mexc_info())\n", + "\u001b[0;31mFileNotFoundError\u001b[0m: [Errno 2] No such file or directory: '/tmp/capsul_demo'" + ] + } + ], "source": [ "import shutil\n", "shutil.rmtree('/tmp/capsul_demo')" diff --git a/.doctrees/tutorial/capsul_tutorial.doctree b/.doctrees/tutorial/capsul_tutorial.doctree index 565e9e7cc..22bd0e312 100644 Binary files a/.doctrees/tutorial/capsul_tutorial.doctree and b/.doctrees/tutorial/capsul_tutorial.doctree differ diff --git a/_images/inheritance-0959fc6b30167b682322526ebee799e06fc6a66a.png b/_images/inheritance-0959fc6b30167b682322526ebee799e06fc6a66a.png deleted file mode 100644 index 297c0ca42..000000000 Binary files a/_images/inheritance-0959fc6b30167b682322526ebee799e06fc6a66a.png and /dev/null differ diff --git a/_images/inheritance-0959fc6b30167b682322526ebee799e06fc6a66a.png.map b/_images/inheritance-0959fc6b30167b682322526ebee799e06fc6a66a.png.map deleted file mode 100644 index 48b6f3776..000000000 --- a/_images/inheritance-0959fc6b30167b682322526ebee799e06fc6a66a.png.map +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/_images/inheritance-1c76ac13403834b6330b1cd12cd36f8794d5f655.png b/_images/inheritance-1c76ac13403834b6330b1cd12cd36f8794d5f655.png deleted file mode 100644 index f39a43b9e..000000000 Binary files a/_images/inheritance-1c76ac13403834b6330b1cd12cd36f8794d5f655.png and /dev/null differ diff --git a/_images/inheritance-1c76ac13403834b6330b1cd12cd36f8794d5f655.png.map b/_images/inheritance-1c76ac13403834b6330b1cd12cd36f8794d5f655.png.map deleted file mode 100644 index 976ac229d..000000000 --- a/_images/inheritance-1c76ac13403834b6330b1cd12cd36f8794d5f655.png.map +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/_images/inheritance-247231e14284be742c4fb61bec12cd51dc39a7c5.png b/_images/inheritance-247231e14284be742c4fb61bec12cd51dc39a7c5.png deleted file mode 100644 index 9265d0cce..000000000 Binary files a/_images/inheritance-247231e14284be742c4fb61bec12cd51dc39a7c5.png and /dev/null differ diff --git a/_images/inheritance-247231e14284be742c4fb61bec12cd51dc39a7c5.png.map b/_images/inheritance-247231e14284be742c4fb61bec12cd51dc39a7c5.png.map deleted file mode 100644 index 0e9f648f5..000000000 --- a/_images/inheritance-247231e14284be742c4fb61bec12cd51dc39a7c5.png.map +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/_images/inheritance-66047d19fa4223bea6ca58b453fd030115dd7f5e.png b/_images/inheritance-66047d19fa4223bea6ca58b453fd030115dd7f5e.png deleted file mode 100644 index 5e8bc39c7..000000000 Binary files a/_images/inheritance-66047d19fa4223bea6ca58b453fd030115dd7f5e.png and /dev/null differ diff --git a/_images/inheritance-66047d19fa4223bea6ca58b453fd030115dd7f5e.png.map b/_images/inheritance-66047d19fa4223bea6ca58b453fd030115dd7f5e.png.map deleted file mode 100644 index 8102cd2fa..000000000 --- a/_images/inheritance-66047d19fa4223bea6ca58b453fd030115dd7f5e.png.map +++ /dev/null @@ -1,16 +0,0 @@ - - - - - - - - - - - - - - - - diff --git a/_images/inheritance-779f649f3ecdc0c12213c361e1381c7b0d057c7f.png b/_images/inheritance-779f649f3ecdc0c12213c361e1381c7b0d057c7f.png deleted file mode 100644 index 53322448d..000000000 Binary files a/_images/inheritance-779f649f3ecdc0c12213c361e1381c7b0d057c7f.png and /dev/null differ diff --git a/_images/inheritance-779f649f3ecdc0c12213c361e1381c7b0d057c7f.png.map b/_images/inheritance-779f649f3ecdc0c12213c361e1381c7b0d057c7f.png.map deleted file mode 100644 index 49fe6890e..000000000 --- a/_images/inheritance-779f649f3ecdc0c12213c361e1381c7b0d057c7f.png.map +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - - - - - - - - - - - - diff --git a/_images/inheritance-dc30d2f7ae14461cfb6c6bb2f54c7001a1c512c6.png b/_images/inheritance-dc30d2f7ae14461cfb6c6bb2f54c7001a1c512c6.png deleted file mode 100644 index 5afbb3ee0..000000000 Binary files a/_images/inheritance-dc30d2f7ae14461cfb6c6bb2f54c7001a1c512c6.png and /dev/null differ diff --git a/_images/inheritance-dc30d2f7ae14461cfb6c6bb2f54c7001a1c512c6.png.map b/_images/inheritance-dc30d2f7ae14461cfb6c6bb2f54c7001a1c512c6.png.map deleted file mode 100644 index e3dc8b84d..000000000 --- a/_images/inheritance-dc30d2f7ae14461cfb6c6bb2f54c7001a1c512c6.png.map +++ /dev/null @@ -1,114 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/_images/inheritance-ee200181268e267f2c8d7f18fcd6a9541f7d7983.png b/_images/inheritance-ee200181268e267f2c8d7f18fcd6a9541f7d7983.png deleted file mode 100644 index 071287a68..000000000 Binary files a/_images/inheritance-ee200181268e267f2c8d7f18fcd6a9541f7d7983.png and /dev/null differ diff --git a/_images/inheritance-ee200181268e267f2c8d7f18fcd6a9541f7d7983.png.map b/_images/inheritance-ee200181268e267f2c8d7f18fcd6a9541f7d7983.png.map deleted file mode 100644 index 31309bba0..000000000 --- a/_images/inheritance-ee200181268e267f2c8d7f18fcd6a9541f7d7983.png.map +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/_modules/capsul/attributes/completion_engine_iteration.html b/_modules/capsul/attributes/completion_engine_iteration.html index ba7225a16..2bacb6cb9 100644 --- a/_modules/capsul/attributes/completion_engine_iteration.html +++ b/_modules/capsul/attributes/completion_engine_iteration.html @@ -373,6 +373,8 @@

Source code for capsul.attributes.completion_engine_iteration

print('assign iteration parameter', parameter, ':\n', e, file=sys.stderr) for parameter in parameters: + if parameter in iterative_parameters: + continue try: value = getattr(process.process, parameter) setattr(process, parameter, value) diff --git a/_modules/capsul/engine.html b/_modules/capsul/engine.html deleted file mode 100644 index ee593090f..000000000 --- a/_modules/capsul/engine.html +++ /dev/null @@ -1,798 +0,0 @@ - - - - - - - - CAPSUL — CAPSUL - Chain algorithm in pipelines and execute in many contexts - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - Capsul logo - - -
- - - - - -
-
-
-
- -

Source code for capsul.engine

-# -*- coding: utf-8 -*-
-'''
-This module defines the main API to interact with Capsul processes.
-In order to execute a process, it is mandatory to have an instance of
-:py:class:`CapsulEngine`. Such an instance can be created with factory
-:py:func:`capsul_engine`
-
-Classes
-=======
-:class:`CapsulEngine`
----------------------
-
-Functions
-=========
-:func:`database_factory`
-------------------------
-:func:`capsul_engine`
----------------------
-:func:`activate_configuration`
-------------------------------
-'''
-
-from __future__ import absolute_import
-from __future__ import print_function
-import importlib
-import json
-import os
-import os.path as osp
-import re
-import tempfile
-import subprocess
-import sys
-
-from traits.api import Dict, String, Undefined
-
-from soma.controller import Controller, controller_to_dict
-from soma.serialization import to_json, from_json
-from soma.sorted_dictionary import SortedDictionary
-from soma.utils.weak_proxy import get_ref
-
-from .database_json import JSONDBEngine
-from .database_populse import PopulseDBEngine
-
-from .settings import Settings
-from .module import default_modules
-from . import run
-from .run import WorkflowExecutionError
-
-# FIXME TODO: OBSOLETE
-
-#Questions about API/implementation:
-
-#* execution:
-  #* workflows are not exposed, they are running a possibly different pipeline (single process case), thus we need to keep track on it
-  #* logging / history / provenance, databasing
-  #* retrieving output files with transfers: when ? currently in wait(), should it be a separate method ? should it be asynchronous ?
-  #* setting output parameters: currently in wait(), should it be a separate method ?
-  #* disconnections / reconnections client / server
-  #* actually connect computing resource[s]
-#* settings / config:
-  #* see comments in settings.py
-  #* GUI and constraints on parameters ?
-  #* how to handle optional dependencies: ie nipype depends on spm if spm is installed / configured, otherwise we can run other nipype interfaces, but no spm ones
-  #* integrate soma-workflow config + CE.computing_resource
-
-
-
-[docs] -class CapsulEngine(Controller): - ''' - A CapsulEngine is the mandatory entry point of all software using Capsul. - It contains objects to store configuration and metadata, defines execution - environment(s) (possibly remote) and performs pipelines execution. - - A CapsulEngine must be created using capsul.engine.capsul_engine function. - For instance:: - - from capsul.engine import capsul_engine - ce = capsul_engine() - - Or:: - - from capsul.api import capsul_engine - ce = capsul_engine() - - By default, CapsulEngine only stores necessary configuration. But it may be - necessary to modify the Python environment globally to apply this - configuration. For instance, Nipype must be configured globally. If SPM is - configured in CapsulEngine, it is necessary to explicitly activate the - configuration in order to modify the global configuration of Nipype for - SPM. This activation is done by explicitly activating the execution - context of the capsul engine with the following code, inside a running - process:: - - from capsul.engine import capsul_engine, activate_configuration - ce = capsul_engine() - # Nipype is not configured here - config = capsul_engine.settings.select_configurations( - 'global', {'nipype': 'any'}) - activate_configuration(config) - # Nipype is configured here - - .. note:: - - CapsulEngine is the replacement of the older - :class:`~capsul.study_config.study_config.StudyConfig`, which is still - present in Capsul 2.2 for backward compatibility, but will disappear in - later versions. In Capsul 2.2 both objects exist, and are synchronized - internally, which means that a StudyConfig object will also create a - CapsulEngine, and the other way, and modifications in the StudyConfig - object will change the corresponding item in CapsulEngine and vice - versa. Functionalities of StudyConfig are moving internally to - CapsulEngine, StudyConfig being merely a wrapper. - - **Using CapsulEngine** - - It is used to store configuration variables, and to handle execution within - the configured context. The configuration has 2 independent axes: - configuration modules, which provide additional configuration variables, - and "environments" which typically represent computing resources. - - *Computing resources* - - Capsul is using :somaworkflow:`Soma-Workflow <index.html>` to run - processes, and is thus able to connect and execute on a remote computing - server. The remote computing resource may have a different configuration - from the client one (paths for software or data, available external - software etc). So configurations specific to different computing resources - should be handled in CapsulEngine. For this, the configuration section is - split into several configuration entries, one for each computing resource. - - As this is a little bit complex to handle at first, a "global" - configuration (what we call "environment") is used to maintain all common - configuration options. It is typically used to work on the local machine, - especially for users who only work locally. - - Configuration is stored in a database (either internal or persistent), - through the :class:`~capsul.engine.settings.Settings` object found in - ``CapsulEngine.settings``. - Access and modification of settings should occur within a session block - using ``with capsul_engine.settings as session``. See the - :class:`~capsul.engine.settings.Settings` class for details. - - :: - - >>> from capsul.api import capsul_engine - >>> ce = capsul_engine() - >>> config = ce.settings.select_configurations('global') - >>> config = ce.global_config - >>> print(config) - {'capsul_engine': {'uses': {'capsul.engine.module.fsl': 'ALL', - 'capsul.engine.module.matlab': 'ALL', - 'capsul.engine.module.spm': 'ALL'}}} - - Whenever a new computing resource is used, it can be added as a new - environment key to all configuration operations. - - Note that the settings store all possible configurations for all - environments (or computing resources), but are not "activated": this is - only done at runtime in specific process execution functions: each process - may need to select and use a different configuration from other ones, and - activate it individually. - - :class:`~capsul.process.process.Process` subclasses or instances may - provide their configuration requirements via their - :meth:`~capsul.process.process.Process.requirements` method. This method - returns a dictionary of request strings (one element per needed module) - that will be used to select one configuration amongst the available - settings entries of each required module. - - *configuration modules* - - The configuration is handled through a set of configuration modules. Each - is dedicated for a topic (for instance handling a specific external - software paths, or managing process parameters completion, etc). A module - adds a settings table in the database, with its own variables, and is able - to manage runtime configuration of programs, if needed, through its - ``activate_configurations`` function. Capsul comes with a - set of predefined modules: - :class:`~capsul.engine.module.attributes`, - :class:`~capsul.engine.module.axon`, - :class:`~capsul.engine.module.fom`, - :class:`~capsul.engine.module.fsl`, - :class:`~capsul.engine.module.matlab`, - :class:`~capsul.engine.module.spm` - - **Methods** - ''' - - def __init__(self, - database_location, - database, - require): - ''' - CapsulEngine.__init__(self, database_location, database, config=None) - - The CapsulEngine constructor should not be called directly. - Use :func:`capsul_engine` factory function instead. - ''' - super(CapsulEngine, self).__init__() - - self._settings = None - - self._database_location = database_location - self._database = database - - self._loaded_modules = set() - self.load_modules(require) - - from capsul.study_config.study_config import StudyConfig - self.study_config = StudyConfig(engine=self) - - self._metadata_engine = from_json(database.json_value('metadata_engine')) - - self._connected_resource = '' - - - @property - def settings(self): - if self._settings is None: - self._settings = Settings(self.database.db) - return self._settings - - @property - def database(self): - return self._database - - @property - def database_location(self): - return self._database_location - - - @property - def metadata_engine(self): - return self._metadata_engine - - @metadata_engine.setter - def metadata_engine(self, metadata_engine): - self._metadata_engine = metadata_engine - self.database.set_json_value('metadata_engine', - to_json(self._metadata_engine)) - -
-[docs] - def load_modules(self, require): - ''' - Call self.load_module for each required module. The list of modules - to load is located in self.modules (if it is None, - capsul.module.default_modules is used). - ''' - if require is None: - require = default_modules - - for module in require: - self.load_module(module)
- - -
-[docs] - def load_module(self, module_name): - ''' - Load a module if it has not already been loaded (is this case, - nothing is done) - - A module is a fully qualified name of a Python module (as accepted - by Python import statement). Such a module must define the two - following functions (and may define two others, see below): - - def load_module(capsul_engine, module_name): - def set_environ(config, environ): - - load_module of each module is called once before reading and applying - the configuration. It can be used to add traits to the CapsulEngine - in order to define the configuration options that are used by the - module. Values of these traits are automatically stored in - configuration in database when self.save() is used, and they are - retrieved from database before initializing modules. - - set_environ is called in the context of the processing (i.e. on - the, possibly remote, machine that runs the pipelines). It receives - the configuration as a JSON compatible dictionary (for instance a - CapsulEngine attribute `capsul_engine.spm.directory` would be - config['spm']['directory']). The function must modify the environ - dictionary to set the environment variables that must be defined - for pipeline configuration. These variables are typically used by - modules in capsul.in_context module to manage running external - software with appropriate configuration. - ''' - module_name = self.settings.module_name(module_name) - if module_name not in self._loaded_modules: - self._loaded_modules.add(module_name) - python_module = importlib.import_module(module_name) - init_settings = getattr(python_module, 'init_settings', None) - if init_settings is not None: - init_settings(self) - return True - return False
- - - # - # Method imported from self.database - # - - # TODO: take computing resource in account in the following methods - - def set_named_directory(self, name, path): - return self.database.set_named_directory(name, path) - - def named_directory(self, name): - return self.database.named_directory(name) - - def named_directories(self): - return self.database.set_named_directories() - - def set_json_value(self, name, json_value): - return self.database.set_json_value(name, json_value) - - def json_value(self, name): - return self.database.json_value(name) - - def set_path_metadata(self, path, metadata, named_directory=None): - return self.database.set_path_metadata(path, metadata, named_directory) - - def path_metadata(self, path, named_directory=None): - return self.database.set_path_metadata(path, named_directory) - -
-[docs] - def import_configs(self, environment, config_dict, cont_on_error=False): - ''' - Import config values from a dictionary as given by - :meth:`Settings.select_configurations`. - - Compared to :meth:`Settings.import_configs` this method (at - :class:`CapsulEngine` level) also loads the required modules. - ''' - modules = config_dict.get('capsul_engine', {}).get('uses', {}) - for module in modules: - self.load_module(module) - self.settings.import_configs(environment, config_dict, cont_on_error)
- - - # - # Processes and pipelines related methods - # -
-[docs] - def get_process_instance(self, process_or_id, **kwargs): - ''' - The only official way to get a process instance is to use this method. - For now, it simply calls self.study_config.get_process_instance - but it will change in the future. - ''' - instance = self.study_config.get_process_instance(process_or_id, - **kwargs) - return instance
- - -
-[docs] - def get_iteration_pipeline(self, pipeline_name, node_name, process_or_id, - iterative_plugs=None, do_not_export=None, - make_optional=None, **kwargs): - """ Create a pipeline with an iteration node iterating the given - process. - - Parameters - ---------- - pipeline_name: str - pipeline name - node_name: str - iteration node name in the pipeline - process_or_id: process description - as in :meth:`get_process_instance` - iterative_plugs: list (optional) - passed to :meth:`Pipeline.add_iterative_process` - do_not_export: list - passed to :meth:`Pipeline.add_iterative_process` - make_optional: list - passed to :meth:`Pipeline.add_iterative_process` - - Returns - ------- - pipeline: :class:`Pipeline` instance - """ - from capsul.pipeline.pipeline import Pipeline - - pipeline = Pipeline() - pipeline.name = pipeline_name - pipeline.set_study_config(get_ref(self.study_config)) - pipeline.add_iterative_process(node_name, process_or_id, - iterative_plugs, do_not_export, - **kwargs) - pipeline.autoexport_nodes_parameters(include_optional=True) - return pipeline
- - -
-[docs] - def start(self, process, workflow=None, history=True, get_pipeline=False, **kwargs): - ''' - Asynchronously start the execution of a process or pipeline in the - connected computing environment. Returns an identifier of - the process execution and can be used to get the status of the - execution or wait for its termination. - - TODO: - if history is True, an entry of the process execution is stored in - the database. The content of this entry is to be defined but it will - contain the process parameters (to restart the process) and will be - updated on process termination (for instance to store execution time - if possible). - - Parameters - ---------- - process: Process or Pipeline instance - workflow: Workflow instance (optional - if already defined before call) - history: bool (optional) - TODO: not implemented yet. - get_pipeline: bool (optional) - if True, start() will return a tuple (execution_id, pipeline). The - pipeline is normally the input pipeline (process) if it is actually - a pipeline. But if the input process is a "single process", it will - be inserted into a small pipeline for execution. This pipeline will - be the one actually run, and may be passed to :meth:`wait` to set - output parameters. - - Returns - ------- - execution_id: int - execution identifier (actually a soma-workflow id) - pipeline: Pipeline instance (optional) - only returned if get_pipeline is True. - ''' - return run.start(self, process, workflow, history, get_pipeline, **kwargs)
- - -
-[docs] - def connect(self, computing_resource): - ''' - Connect the capsul engine to a computing resource - ''' - self._connected_resource = computing_resource
- - - -
-[docs] - def connected_to(self): - ''' - Return the name of the computing resource this capsul engine is - connected to or None if it is not connected. - ''' - return self._connected_resource
- - -
-[docs] - def disconnect(self): - ''' - Disconnect from a computing resource. - ''' - self._connected_resource = None
- - -
-[docs] - def executions(self): - ''' - List the execution identifiers of all processes that have been started - but not disposed in the connected computing resource. Raises an - exception if the computing resource is not connected. - ''' - raise NotImplementedError()
- - -
-[docs] - def dispose(self, execution_id, conditional=False): - ''' - Update the database with the current state of a process execution and - free the resources used in the computing resource (i.e. remove the - workflow from SomaWorkflow). - - If ``conditional`` is set to True, then dispose is only done if the - configuration does not specify to keep succeeded / failed workflows. - ''' - run.dispose(self, execution_id, conditional=conditional)
- - -
-[docs] - def interrupt(self, execution_id): - ''' - Try to stop the execution of a process. Does not wait for the process - to be terminated. - ''' - return run.interrupt(self, execution_id)
- - -
-[docs] - def wait(self, execution_id, timeout=-1, pipeline=None): - ''' - Wait for the end of a process execution (either normal termination, - interruption or error). - ''' - return run.wait(self, execution_id, timeout=timeout, pipeline=pipeline)
- - -
-[docs] - def status(self, execution_id): - ''' - Return a simple value with the status of an execution (queued, - running, terminated, error, etc.) - ''' - return run.status(self, execution_id)
- - -
-[docs] - def detailed_information(self, execution_id): - ''' - Return complete (and possibly big) information about a process - execution. - ''' - return run.detailed_information(self, execution_id)
- - - def call(self, process, history=True, *kwargs): - return run.call(self, process, history=history, **kwargs) - - def check_call(self, process, history=True, **kwargs): - return run.check_call(self, process, history=history, **kwargs) - -
-[docs] - def raise_for_status(self, status, execution_id=None): - ''' - Raise an exception if a process execution failed - ''' - run.raise_for_status(self, status, execution_id)
-
- - - -_populsedb_url_re = re.compile(r'^\w+(\+\w+)?://(.*)') - - -
-[docs] -def database_factory(database_location): - ''' - Create a DatabaseEngine from its location string. This location can be - either a sqlite file path (ending with '.sqlite' or ':memory:' for an - in memory database for testing) or a populse_db URL, or None. - ''' - global _populsedb_url_re - - engine_directory = None - - if database_location is None: - database_location = ':memory:' - match = _populsedb_url_re.match(database_location) - if match: - path = match.groups(2) - _, path = osp.splitdrive(path) - if path.startswith(os.apth.sep): - engine_directory = osp.abspath(osp.dirname(path)) - populse_db = database_location - elif database_location.endswith('.sqlite'): - populse_db = 'sqlite:///%s' % database_location - engine_directory = osp.abspath(osp.dirname(database_location)) - elif database_location == ':memory:': - populse_db = 'sqlite:///:memory:' - else: - raise ValueError('Invalid database location: %s' % database_location) - - engine = PopulseDBEngine(populse_db) - if engine_directory: - engine.set_named_directory('capsul_engine', engine_directory) - return engine
- - -
-[docs] -def capsul_engine(database_location=None, require=None): - ''' - User facrory for creating capsul engines. - - If no database_location is given, it will default to an internal (in- - memory) database with no persistent settings or history values. - - Configuration is read from a dictionary stored in two database entries. - The first entry has the key 'global_config' (i.e. - database.json_value('global_config')), it contains the configuration - values that are shared by all processing engines. The second entry is - computing_config`. It contains a dictionary with one item per computing - resource where the key is the resource name and the value is configuration - values that are specific to this computing resource. - - Before initialization of the CapsulEngine, modules are loaded. The - list of loaded modules is searched in the 'modules' value in the - database (i.e. in database.json_value('modules')) ; if no list is - defined in the database, capsul.module.default_modules is used. - ''' - #if database_location is None: - #database_location = osp.expanduser('~/.config/capsul/capsul_engine.sqlite') - database = database_factory(database_location) - capsul_engine = CapsulEngine(database_location, database, require=require) - return capsul_engine
- - - -configurations = None -activated_modules = set() - -
-[docs] -def activate_configuration(selected_configurations): - ''' - Activate a selected configuration (set of modules) for runtime. - ''' - global configurations - - configurations = selected_configurations - modules = configurations.get('capsul_engine', {}).get('uses', {}).keys() - for m in modules: - activate_module(m)
- - -
-[docs] -def activate_module(module_name): - ''' - Activate a module configuration for runtime. This function is called by - activate_configuration() and assumes the global variable - ``capsul.engine.configurations`` is properly setup. - ''' - global activated_modules - - if module_name not in activated_modules: - activated_modules.add(module_name) - module = importlib.import_module(module_name) - check_configurations = getattr(module, 'check_configurations', None) - complete_configurations = getattr(module, 'complete_configurations', None) - if check_configurations: - error = check_configurations() - if error: - if complete_configurations: - complete_configurations() - error = check_configurations() - if error: - raise EnvironmentError(error) - activate_configurations = getattr(module, 'activate_configurations', None) - if activate_configurations: - activate_configurations()
- -
- -
-
-
-
- -
-
- - - - \ No newline at end of file diff --git a/_modules/capsul/engine/database.html b/_modules/capsul/engine/database.html index 477245555..03cc02125 100644 --- a/_modules/capsul/engine/database.html +++ b/_modules/capsul/engine/database.html @@ -93,8 +93,7 @@

Navigation

modules | - - +
@@ -106,12 +105,11 @@

Navigation

Source code for capsul.engine.database

 # -*- coding: utf-8 -*-
-from __future__ import absolute_import
 import os.path as osp
 
 
[docs] -class DatabaseEngine(object): +class DatabaseEngine: ''' A :py:class:`DatabaseEngine` is the base class for all engines allowing to store, retrieve and search metadata associated with @@ -279,7 +277,6 @@

Navigation

>modules | -
diff --git a/_modules/capsul/engine/database_json.html b/_modules/capsul/engine/database_json.html deleted file mode 100644 index db42d6494..000000000 --- a/_modules/capsul/engine/database_json.html +++ /dev/null @@ -1,244 +0,0 @@ - - - - - - - - CAPSUL — CAPSUL - Chain algorithm in pipelines and execute in many contexts - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - Capsul logo - - -
- - - - - -
-
-
-
- -

Source code for capsul.engine.database_json

-# -*- coding: utf-8 -*-
-from __future__ import absolute_import
-import os
-import os.path as osp
-import six
-import uuid
-import json
-
-from capsul.engine.database import DatabaseEngine
-
-
-[docs] -class JSONDBEngine(DatabaseEngine): - ''' - A JSON dictionary implementation of :py:class:`capsul.engine.database.DatabaseEngine` - ''' - def __init__(self, json_filename): - if json_filename is not None: - self.json_filename = osp.normpath(osp.abspath(json_filename)) - else: - self.json_filename = None - self.read_json() - - def read_json(self): - if self.json_filename is not None and osp.exists(self.json_filename): - self.json_dict = json.load(open(self.json_filename)) - self.modified = False - else: - self.json_dict = {} - self.modified = True - - def commit(self): - if self.modified and self.json_filename is not None: - parent = osp.dirname(self.json_filename) - if not osp.exists(parent): - os.makedirs(parent) - json.dump(self.json_dict, open(self.json_filename, 'w'), indent=2) - self.modified = False - - def rollback(self): - self.read_json() - - -
-[docs] - def set_named_directory(self, name, path): - if path: - path = osp.normpath(osp.abspath(path)) - self.json_dict.setdefault('named_directory', {})[name] = {'name': name, - 'path': path} - self.modified = True - else: - named_directory = self.json_dict.get('named_directory') - if named_directory is not None: - named_directory.pop(name, None) - self.modified = True
- - -
-[docs] - def named_directory(self, name): - return self.json_dict.get('named_directory', {}).get(name, {}).get('path')
- - -
-[docs] - def named_directories(self): - return self.json_dict.get('named_directory', {}).values()
- - - -
-[docs] - def set_json_value(self, name, json_value): - self.json_dict.setdefault('json_value', {})[name] = json_value - self.modified = True
- - -
-[docs] - def json_value(self, name): - return self.json_dict.get('json_value', {}).get(name)
- - - -
-[docs] - def set_path_metadata(self, path, metadata, named_directory=None): - metadata = self.check_path_metadata(path, metadata, named_directory) - path = metadata['path'] - named_directory = metadata['named_directory'] - self.json_dict.setdefault('path_metadata', {})[ - (named_directory, path)] = metadata - self.modified = True
- - - -
-[docs] - def path_metadata(self, path, named_directory=None): - named_directory, path = self.check_path(path, named_directory) - return self.json_dict.get('path_metadata', {}).get((named_directory, path))
-
- -
- -
-
-
-
- -
-
- - - - \ No newline at end of file diff --git a/_modules/capsul/engine/database_populse.html b/_modules/capsul/engine/database_populse.html deleted file mode 100644 index 618ea2ace..000000000 --- a/_modules/capsul/engine/database_populse.html +++ /dev/null @@ -1,323 +0,0 @@ - - - - - - - - CAPSUL — CAPSUL - Chain algorithm in pipelines and execute in many contexts - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - Capsul logo - - -
- - - - - -
-
-
-
- -

Source code for capsul.engine.database_populse

-# -*- coding: utf-8 -*-
-from __future__ import absolute_import
-import os.path as osp
-import six
-import uuid
-
-from capsul.engine.database import DatabaseEngine
-
-from populse_db.database import Database
-
-
-
-[docs] -class PopulseDBEngine(DatabaseEngine): - def __init__(self, database_engine): - self.db = Database(database_engine) - with self.db as dbs: - if not dbs.get_collection('path_metadata'): - # Create the schema if it does not exist - dbs.add_collection('named_directory', 'name') - dbs.add_field('named_directory', 'path', 'string') - - dbs.add_collection('json_value', 'name') - dbs.add_field('json_value', 'value', 'json') - - dbs.add_collection('path_metadata', 'path') - dbs.add_field('path_metadata', 'named_directory', 'string', - description='Reference to a base directory whose ' - 'path is stored in named_directory collection') - #self.dbs = self.db.__enter__() - - - def __del__(self): - self.close() - - - def close(self): - #self.db.__exit__(None, None, None) - self.db = None - #self.dbs = None - - - def commit(self): - #self.dbs.save_modifications() - with self.db as dbs: - dbs.save_modifications() - - def rollback(self): - #self.dbs.unsave_modifications() - with self.db as dbs: - dbs.unsave_modifications() - -
-[docs] - def set_named_directory(self, name, path): - if path: - path = osp.normpath(osp.abspath(path)) - #doc = self.dbs.get_document('named_directory', name) - #if doc is None: - #if path: - #doc = {'name': name, - #'path': path} - #self.dbs.add_document('named_directory', doc) - #else: - #if path: - #self.dbs.set_value('named_directory', name, 'path', path) - #else: - #self.dbs.remove_document('named_directory', name) - with self.db as dbs: - doc = dbs.get_document('named_directory', name) - if doc is None: - if path: - doc = {'name': name, - 'path': path} - dbs.add_document('named_directory', doc) - else: - if path: - dbs.set_value('named_directory', name, 'path', path) - else: - dbs.remove_document('named_directory', name)
- - -
-[docs] - def named_directory(self, name): - #return self.dbs.get_value('named_directory', name, 'path') - with self.db as dbs: - return dbs.get_value('named_directory', name, 'path')
- - -
-[docs] - def named_directories(self): - #return self.dbs.filter_documents('named_directory', 'all') - with self.db as dbs: - return dbs.filter_documents('named_directory', 'all')
- - -
-[docs] - def set_json_value(self, name, json_value): - #doc = self.dbs.get_document('json_value', name) - #json_dict = {'value': json_value} - #if doc is None: - #doc = {'name': name, - #'json_dict': json_dict - #} - #self.dbs.add_document('json_value', doc) - #else: - #self.dbs.set_value('json_value', name, 'json_dict', json_dict) - with self.db as dbs: - doc = dbs.get_document('json_value', name) - json_dict = {'value': json_value} - if doc is None: - doc = {'name': name, - 'json_dict': json_dict - } - dbs.add_document('json_value', doc) - else: - dbs.set_value('json_value', name, 'json_dict', json_dict)
- - -
-[docs] - def json_value(self, name): - #doc = self.dbs.get_document('json_value', name) - #if doc: - #return doc['json_dict']['value'] - #return None - with self.db as dbs: - doc = dbs.get_document('json_value', name) - if doc: - return doc['json_dict']['value'] - return None
- - -
-[docs] - def set_path_metadata(self, path, metadata): - named_directory = metadata.get('named_directory') - if named_directory: - base_path = self.named_directory('capsul_engine') - if base_path: - if not path.startswith(named_directory): - raise ValueError('Path "%s" is defined as relative to named directory %s but it does not start with "%s"' % (path, named_directory, base_path)) - path = path[len(base_path)+1:] - else: - if osp.isabs(path): - raise ValueError('Cannot determine relative path for "%s" because its base named directory "%s" is unknown' % (path, named_directory)) - else: - if osp.isabs(path): - for nd in self.named_directories(): - if path.startswith(nd.path): - named_directory = nd.name() - path = path[len(nd.path)+1] - break - else: - named_directory = None - else: - # capsul_engine is the default named directory for relative paths - named_directory = 'capsul_engine' - - doc = metadata.copy() - doc['path'] = path - if named_directory: - doc['named_directory'] = named_directory - with self.db as dbs: - dbs.add_document('path_metadata', doc)
- - - -
-[docs] - def path_metadata(self, path): - if osp.isabs(path): - for nd in self.named_directories(): - if path.startswith(nd.path): - path = path[len(nd.path)+1:] - break - with self.db as dbs: - return dbs.get_document('path_metadata', path)
-
- -
- -
-
-
-
- -
-
- - - - \ No newline at end of file diff --git a/_modules/capsul/engine/module/attributes.html b/_modules/capsul/engine/module/attributes.html deleted file mode 100644 index 47bdd0ff5..000000000 --- a/_modules/capsul/engine/module/attributes.html +++ /dev/null @@ -1,317 +0,0 @@ - - - - - - - - CAPSUL — CAPSUL - Chain algorithm in pipelines and execute in many contexts - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - Capsul logo - - -
- - - - - -
-
-
-
- -

Source code for capsul.engine.module.attributes

-# -*- coding: utf-8 -*-
-'''
-Attributes completion config module
-
-'''
-
-from __future__ import absolute_import
-
-import os
-import six
-from capsul.attributes.attributes_factory import AttributesFactory
-from capsul.attributes.attributes_schema import AttributesSchema, \
-    ProcessAttributes
-from capsul.attributes.completion_engine \
-    import ProcessCompletionEngineFactory, PathCompletionEngineFactory
-from capsul.engine import settings
-import capsul.engine
-import os.path as osp
-from functools import partial
-import weakref
-
-
-def init_settings(capsul_engine):
-    default_paths = ['capsul.attributes.completion_engine_factory']
-
-    init_att = {
-        'attributes_schema_paths': default_paths,
-        'attributes_schemas': {},
-        'process_completion': 'builtin',
-        capsul_engine.settings.config_id_field: 'attributes',
-    }
-
-    with capsul_engine.settings as session:
-        session.ensure_module_fields('attributes',
-            [dict(name='attributes_schema_paths',
-                  type='list_string',
-                  description='attributes shchemas modules names'),
-             dict(name='attributes_schemas',
-                  type='json',
-                  description='attributes shchemas names'),
-             dict(name='process_completion',
-                  type='string',
-                  description='process completion model name'),
-             dict(name='path_completion',
-                  type='string',
-                  description='path completion model name'),
-            ])
-        config = session.config('attributes', 'global')
-        if not config:
-            session.new_config('attributes', 'global', init_att)
-
-    if not hasattr(capsul_engine, '_modules_data'):
-        capsul_engine._modules_data = {}
-    data = capsul_engine._modules_data.setdefault('attributes', {})
-    factory = AttributesFactory()
-    data['attributes_factory'] = factory
-
-    factory.class_types['schema'] = AttributesSchema
-    factory.class_types['process_completion'] \
-        = ProcessCompletionEngineFactory
-    factory.class_types['path_completion'] \
-        = PathCompletionEngineFactory
-    factory.class_types['process_attributes'] \
-        = ProcessAttributes
-
-    factory.module_path = default_paths
-    capsul_engine.settings.module_notifiers.setdefault(
-        'capsul.engine.module.attributes', []).append(
-            partial(_sync_attributes_factory, weakref.proxy(capsul_engine)))
-
-    # link with StudyConfig
-    if hasattr(capsul_engine, 'study_config') \
-            and 'AttributesConfig' not in capsul_engine.study_config.modules:
-        scmod = capsul_engine.study_config.load_module('AttributesConfig', {})
-        scmod.initialize_module()
-        scmod.initialize_callbacks()
-
-#def check_configurations():
-    #'''
-    #Checks if the activated configuration is valid to use BrainVisa and returns
-    #an error message if there is an error or None if everything is good.
-    #'''
-    #return None
-
-#def complete_configurations():
-    #'''
-    #Try to automatically set or complete the capsul.engine.configurations for
-    #the attributes module.
-    #'''
-    #config = capsul.engine.configurations
-    #config = config.setdefault('attributes', {})
-    #attributes_schema_paths = config.get('attributes_schema_paths', None)
-    #if attributes_schema_paths is None:
-        #config['attributes_schema_paths'] \
-            #= ['capsul.attributes.completion_engine_factory']
-    #attributes_schemas = config.get('attributes_schemas', None)
-    #if attributes_schemas is None:
-        #config['attributes_schemas'] = {}
-
-
-def _sync_attributes_factory(capsul_engine, param=None, value=None):
-    factory = capsul_engine._modules_data['attributes']['attributes_factory']
-    with capsul_engine.settings as session:
-        config = session.config('attributes', 'global')
-        if config:
-            factory.module_path = config.attributes_schema_paths
-
-
-
-[docs] -def edition_widget(engine, environment, config_id='attributes'): - ''' Edition GUI for attributes config - see - :class:`~capsul.qt_gui.widgets.settings_editor.SettingsEditor` - ''' - from soma.qt_gui.controller_widget import ScrollControllerWidget - from soma.controller import Controller - import types - import traits.api as traits - - def validate_config(widget): - widget.update_controller() - controller = widget.controller_widget.controller - with widget.engine.settings as session: - conf = session.config(config_id, widget.environment) - values = {'config_id': config_id} - values['attributes_schema_paths'] \ - = controller.attributes_schema_paths - values['attributes_schemas'] = controller.attributes_schemas - values['process_completion'] = controller.process_completion - if controller.process_completion is traits.Undefined: - values['process_completion'] = None - values['path_completion'] = controller.path_completion - if controller.path_completion is traits.Undefined: - values['path_completion'] = None - if conf is None: - session.new_config(config_id, widget.environment, values) - else: - for k in ('attributes_schema_paths', 'attributes_schemas', - 'process_completion', 'path_completion'): - setattr(conf, k, values[k]) - - controller = Controller() - controller.add_trait( - 'attributes_schema_paths', - traits.List(traits.Str(), desc='attributes shchemas modules names')) - controller.add_trait( - 'attributes_schemas', - traits.DictStrStr(desc='attributes shchemas names')) - controller.add_trait( - 'process_completion', - traits.Str(desc='process completion model name')) - controller.add_trait( - 'path_completion', - traits.Str(desc='path completion model name', - optional=True)) - - conf = engine.settings.select_configurations( - environment, {'attributes': 'any'}) - if conf: - aconf = conf.get( - 'capsul.engine.module.attributes', {}) - controller.attributes_schema_paths = aconf.get( - 'attributes_schema_paths', []) - controller.attributes_schemas = aconf.get( - 'attributes_schemas', {}) - controller.process_completion = aconf.get( - 'process_completion', 'builtin') - controller.path_completion = aconf.get( - 'path_completion', traits.Undefined) - - widget = ScrollControllerWidget(controller, live=True) - widget.engine = engine - widget.environment = environment - widget.accept = types.MethodType(validate_config, widget) - - return widget
- -
- -
-
-
-
- -
-
- - - - \ No newline at end of file diff --git a/_modules/capsul/engine/module/axon.html b/_modules/capsul/engine/module/axon.html deleted file mode 100644 index e3c0f0a72..000000000 --- a/_modules/capsul/engine/module/axon.html +++ /dev/null @@ -1,298 +0,0 @@ - - - - - - - - CAPSUL — CAPSUL - Chain algorithm in pipelines and execute in many contexts - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - Capsul logo - - -
- - - - - -
-
-
-
- -

Source code for capsul.engine.module.axon

-# -*- coding: utf-8 -*-
-
-'''
-Configuration module which links with `Axon <http://brainvisa.info/axon/user_doc>`_
-'''
-
-from __future__ import absolute_import
-import os
-import six
-import capsul.engine
-import os.path as osp
-
-
-def init_settings(capsul_engine):
-    with capsul_engine.settings as settings:
-        settings.ensure_module_fields('axon',
-            [dict(name='shared_directory',
-                type='string',
-                description=
-                    'Directory where BrainVisa shared data is installed'),
-             dict(name='user_level',
-                  type='int',
-                  description=
-                      '0: basic, 1: advanced, 2: expert, or more. '
-                      'used to display or hide some advanced features or '
-                      'process parameters that would be confusing to a novice '
-                      'user'),
-            ])
-
-    with capsul_engine.settings as session:
-        config = session.config('axon', 'global')
-        if not config:
-            from soma import config as soma_config
-            shared_dir = soma_config.BRAINVISA_SHARE
-
-            values = {capsul_engine.settings.config_id_field: 'axon',
-                      'shared_directory': shared_dir, 'user_level': 0}
-            session.new_config('axon', 'global', values)
-
-    # link with StudyConfig
-    if hasattr(capsul_engine, 'study_config'):
-        if 'BrainVISAConfig' not in capsul_engine.study_config.modules:
-            scmod = capsul_engine.study_config.load_module(
-                'BrainVISAConfig', {})
-            scmod.initialize_module()
-            scmod.initialize_callbacks()
-        else:
-            scmod = capsul_engine.study_config.modules['BrainVISAConfig']
-            scmod.sync_to_engine()
-
-
-[docs] -def check_configurations(): - ''' - Checks if the activated configuration is valid to use BrainVisa and returns - an error message if there is an error or None if everything is good. - ''' - shared_dir = capsul.engine.configurations.get( - 'axon', {}).get('shared_directory', '') - if not shared_dir: - return 'Axon shared_directory is not found' - return None
- - - -
-[docs] -def check_notably_invalid_config(conf): - ''' - Checks if the given module config is obviously invalid, for instance if a mandatory path is not filled - - Returns - ------- - invalid: list - list of invalid config keys - ''' - invalid = [] - for k in ('shared_directory', ): - if getattr(conf, k, None) is None: - invalid.append(k) - return invalid
- - - -
-[docs] -def complete_configurations(): - ''' - Try to automatically set or complete the capsul.engine.configurations for - Axon. - ''' - config = capsul.engine.configurations - config = config.setdefault('axon', {}) - shared_dir = config.get('shared_directory', None) - if shared_dir is None: - from soma import config as soma_config - shared_dir = soma_config.BRAINVISA_SHARE - if shared_dir: - config['shared_directory'] = shared_dir
- - - -
-[docs] -def edition_widget(engine, environment, config_id='axon'): - ''' Edition GUI for axon config - see - :class:`~capsul.qt_gui.widgets.settings_editor.SettingsEditor` - ''' - from soma.qt_gui.controller_widget import ScrollControllerWidget - from soma.controller import Controller - import types - import traits.api as traits - - def validate_config(widget): - widget.update_controller() - controller = widget.controller_widget.controller - with widget.engine.settings as session: - conf = session.config(config_id, widget.environment) - values = {'config_id': config_id, - 'user_level': controller.user_level} - if controller.shared_directory in (None, traits.Undefined, ''): - values['shared_directory'] = None - else: - values['shared_directory'] = controller.shared_directory - if conf is None: - session.new_config(config_id, widget.environment, values) - else: - for k in ('shared_directory', 'user_level'): - setattr(conf, k, values[k]) - - controller = Controller() - controller.add_trait('shared_directory', - traits.Directory(desc='Directory where BrainVisa ' - 'shared data is installed')) - controller.add_trait( - 'user_level', - traits.Int(desc= - '0: basic, 1: advanced, 2: expert, or more. ' - 'used to display or hide some advanced features or ' - 'process parameters that would be confusing to a novice ' - 'user')) - - conf = engine.settings.select_configurations( - environment, {'axon': 'any'}) - if conf: - controller.shared_directory = conf.get( - 'capsul.engine.module.axon', {}).get('shared_directory', - traits.Undefined) - controller.user_level = conf.get( - 'capsul.engine.module.axon', {}).get('user_level', 0) - - widget = ScrollControllerWidget(controller, live=True) - widget.engine = engine - widget.environment = environment - widget.accept = types.MethodType(validate_config, widget) - - return widget
- -
- -
-
-
-
- -
-
- - - - \ No newline at end of file diff --git a/_modules/capsul/engine/module/fom.html b/_modules/capsul/engine/module/fom.html deleted file mode 100644 index 765c1191e..000000000 --- a/_modules/capsul/engine/module/fom.html +++ /dev/null @@ -1,538 +0,0 @@ - - - - - - - - CAPSUL — CAPSUL - Chain algorithm in pipelines and execute in many contexts - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - Capsul logo - - -
- - - - - -
-
-
-
- -

Source code for capsul.engine.module.fom

-# -*- coding: utf-8 -*-
-'''
-Config module for :mod:`File Organization models (FOMs) <capsul.attributes.fom_completion_engine>`
-
-Classes
-=======
-:class:`FomConfig`
-------------------
-'''
-
-from __future__ import absolute_import
-import os
-import six
-import traits.api as traits
-from soma.fom import AttributesToPaths, PathToAttributes
-from soma.application import Application
-from soma.sorted_dictionary import SortedDictionary
-import weakref
-import capsul.engine
-from functools import partial
-
-
-def init_settings(capsul_engine):
-    with capsul_engine.settings as session:
-        session.ensure_module_fields('fom',
-            [dict(name='input_fom', type='string', description='input FOM'),
-             dict(name='output_fom', type='string', description='output FOM'),
-             dict(name='shared_fom', type='string',
-                  description='shared data FOM'),
-             dict(name='volumes_format', type='string',
-                  description='Format used for volumes'),
-             dict(name='meshes_format', type='string',
-                  description='Format used for meshes'),
-             dict(name='auto_fom', type='boolean',
-                  description='Look in all FOMs when a process is not found '
-                  '(in addition to the standard share/foms). Note that '
-                  'auto_fom looks for the first FOM matching the process to '
-                  'get completion for, and does not handle ambiguities. '
-                  'Moreover it brings an overhead (typically 6-7 seconds) the '
-                  'first time it is used since it has to parse all available '
-                  'FOMs.'),
-             dict(name='fom_path', type='list_string',
-                  description='list of additional directories where to look '
-                  'for FOMs'),
-             # FIXME: until directories are included in another config module
-             dict(name='input_directory', type='string',
-                  description='input study data directory'),
-             dict(name='output_directory', type='string',
-                  description='output study data directory'),
-            ])
-
-    capsul_engine.load_module('capsul.engine.module.axon')
-    capsul_engine.load_module('capsul.engine.module.spm')
-    capsul_engine.load_module('capsul.engine.module.attributes')
-
-    with capsul_engine.settings as session:
-        config = session.config('fom', 'global')
-        if not config:
-            values = {capsul_engine.settings.config_id_field: 'fom',
-                      'auto_fom': True, 'fom_path': []}
-            session.new_config('fom', 'global', values)
-
-    if not hasattr(capsul_engine, '_modules_data'):
-        capsul_engine._modules_data = {}
-    store = capsul_engine._modules_data.setdefault('fom', {})
-    store['foms'] = {}
-    store['all_foms'] = SortedDictionary()
-    store['fom_atp'] = {'all': {}}
-    store['fom_pta'] = {'all': {}}
-
-    capsul_engine.settings.module_notifiers['capsul.engine.module.fom'] \
-        = [partial(fom_config_updated, weakref.proxy(capsul_engine), 'global')]
-    capsul_engine.settings.module_notifiers.setdefault(
-        'capsul.engine.module.axon', []).append(
-            partial(config_updated, weakref.proxy(capsul_engine), 'global'))
-    capsul_engine.settings.module_notifiers.setdefault(
-        'capsul.engine.module.spm', []).append(
-            partial(config_updated, weakref.proxy(capsul_engine), 'global'))
-
-    # link with StudyConfig
-    if hasattr(capsul_engine, 'study_config') \
-            and 'FomConfig' not in capsul_engine.study_config.modules:
-        scmod = capsul_engine.study_config.load_module('FomConfig', {})
-        scmod.initialize_module()
-        scmod.initialize_callbacks()
-
-    update_fom(capsul_engine, 'global')
-
-
-def config_dependencies(config):
-    return {'axon': 'any',
-            #'spm': 'any',
-            'attributes': 'any'}
-
-
-def config_updated(capsul_engine, environment, param=None, value=None):
-    if param in (None, 'directory', 'shared_directory'):
-        update_fom(capsul_engine, environment)
-
-
-def spm_config_updated(capsul_engine, environment, param=None, value=None):
-    if param in (None, 'directory'):
-        update_fom(capsul_engine, environment)
-
-
-def fom_config_updated(capsul_engine, environment='global',
-                       param=None, value=None):
-    if param in ('volumes_format', 'meshes_format'):
-        update_formats(capsul_engine, environment)
-        return
-
-    if param in ('fom_path', ):
-        reset_foms(capsul_engine, environment)
-        return
-
-    # otherwise use update_fom()
-    update_fom(capsul_engine, environment, param, value)
-
-
-
-[docs] -def update_fom(capsul_engine, environment='global', param=None, value=None): - '''Load configured FOMs and create FOM completion data - ''' - #print('***update_fom ***') - with capsul_engine.settings as session: - config = session.config('fom', environment) - if config is None: - return - - soma_app = Application('capsul', plugin_modules=['soma.fom']) - if 'soma.fom' not in soma_app.loaded_plugin_modules: - # WARNING: this is unsafe, may erase configured things, and - # probably not thread-safe. - soma_app.initialize() - - if config.fom_path: - fom_path = [p for p in config.fom_path - if p not in soma_app.fom_path] \ - + soma_app.fom_path - else: - fom_path = list(soma_app.fom_path) - - soma_app.fom_manager.paths = fom_path - soma_app.fom_manager.fom_files() - - store = capsul_engine._modules_data['fom'] - if config.auto_fom \ - and len(store['all_foms']) <= 3: - for schema in soma_app.fom_manager.fom_files(): - if schema not in store['all_foms']: - store['all_foms'][schema] = None # not loaded yet. - - foms = (('input', config.input_fom), - ('output', config.output_fom), - ('shared', config.shared_fom)) - for fom_type, fom_filename in foms: - if fom_filename not in ("", None, traits.Undefined): - fom = store['all_foms'].get(fom_filename) - if fom is None: - fom, atp, pta = load_fom(capsul_engine, fom_filename, - config, session, environment) - else: - atp = store['fom_atp']['all'][fom_filename] - pta = store['fom_pta']['all'][fom_filename] - store['foms'][fom_type] = fom - store['fom_atp'][fom_type] = atp - store['fom_pta'][fom_type] = pta - - # update directories - directories = {} - spm = session.config('spm', environment) - if spm: - directories['spm'] = spm.directory - axon = session.config('axon', environment) - if axon: - directories['shared'] = axon.shared_directory - directories['input'] = config.input_directory - directories['output'] = config.output_directory - - for atp in store['fom_atp']['all'].values(): - atp.directories = directories - - # backward compatibility for StudyConfig - capsul_engine.study_config.modules_data.foms = store['foms'] - capsul_engine.study_config.modules_data.all_foms = store['all_foms'] - capsul_engine.study_config.modules_data.fom_atp = store['fom_atp'] - capsul_engine.study_config.modules_data.fom_pta = store['fom_pta']
- - - -def update_formats(capsul_engine, environment): - with capsul_engine.settings as session: - config = session.config('fom', environment) - if config is None: - return - - directories = {} - spm = session.config('spm', environment) - if spm: - directories['spm'] = spm.directory - axon = session.config('axon', environment) - if axon: - directories['shared'] = axon.shared_directory - directories['input'] = config.input_directory - directories['output'] = config.output_directory - - fields = config._dbs.get_fields_names(config._collection) - formats = tuple(getattr(config, key) \ - for key in fields \ - if key.endswith('_format') \ - and getattr(config, key) is not None) - - store = capsul_engine._modules_data['fom'] - - for schema, fom in store['all_foms'].items(): - if fom is None: - continue - - atp = AttributesToPaths( - fom, - selection={}, - directories=directories, - preferred_formats=set((formats))) - old_atp = store['fom_atp']['all'].get(schema) - store['fom_atp']['all'][schema] = atp - if old_atp is not None: - for t in ('input', 'output', 'shared'): - if store['fom_atp'].get(t) is old_atp: - store['fom_atp'][t] = atp - - -def load_fom(capsul_engine, schema, config, session, environment='global'): - #print('=== load fom', schema, '===') - #import time - #t0 = time.time() - soma_app = Application('capsul', plugin_modules=['soma.fom']) - if 'soma.fom' not in soma_app.loaded_plugin_modules: - # WARNING: this is unsafe, may erase configured things, and - # probably not thread-safe. - soma_app.initialize() - old_fom_path = soma_app.fom_path - if config.fom_path: - soma_app.fom_path = [six.ensure_str(p) for p in config.fom_path - if p not in soma_app.fom_path] \ - + soma_app.fom_path - else: - soma_app.fom_path = list(soma_app.fom_path) - fom = soma_app.fom_manager.load_foms(schema) - soma_app.fom_path = old_fom_path - store = capsul_engine._modules_data['fom'] - store['all_foms'][schema] = fom - - # Create FOM completion data - fields = config._dbs.get_fields_names(config._collection) - formats = tuple(getattr(config, key) \ - for key in fields \ - if key.endswith('_format') \ - and getattr(config, key) is not None) - - directories = {} - spm = session.config('spm', environment) - if spm: - directories['spm'] = spm.directory - axon = session.config('axon', environment) - if axon: - directories['shared'] = axon.shared_directory - directories['input'] = config.input_directory - directories['output'] = config.output_directory - - atp = AttributesToPaths( - fom, - selection={}, - directories=directories, - preferred_formats=set((formats))) - store['fom_atp']['all'][schema] = atp - pta = PathToAttributes(fom, selection={}) - store['fom_pta']['all'][schema] = pta - #print(' load fom done:', time.time() - t0, 's') - return fom, atp, pta - - -def reset_foms(capsul_engine, environment): - soma_app = Application('capsul', plugin_modules=['soma.fom']) - if 'soma.fom' not in soma_app.loaded_plugin_modules: - # WARNING: this is unsafe, may erase configured things, and - # probably not thread-safe. - soma_app.initialize() - soma_app.fom_manager.clear_cache() - update_fom(capsul_engine, environment) - - -
-[docs] -def edition_widget(engine, environment, config_id='fom'): - ''' Edition GUI for FOM config - see - :class:`~capsul.qt_gui.widgets.settings_editor.SettingsEditor` - ''' - from soma.qt_gui.controller_widget import ScrollControllerWidget - from soma.controller import Controller - import types - - def validate_config(widget): - widget.update_controller() - controller = widget.controller_widget.controller - with widget.engine.settings as session: - conf = session.config(config_id, widget.environment) - values = {'config_id': config_id} - for k in ('input_fom', 'output_fom', 'shared_fom', - 'volumes_format', 'meshes_format', 'auto_fom', - 'fom_path', 'input_directory', 'output_directory'): - value = getattr(controller, k) - if value is traits.Undefined: - if k in ('fom_path', ): - value = [] - else: - value = None - values[k] = value - if conf is None: - session.new_config(config_id, widget.environment, values) - else: - for k, value in values.items(): - if k == 'config_id': - continue - setattr(conf, k, values[k]) - - controller = Controller() - - controller.add_trait( - 'input_fom', - traits.Str(traits.Undefined, output=False, desc='input FOM')) - controller.add_trait( - 'output_fom', - traits.Str(traits.Undefined, output=False, desc='output FOM')) - controller.add_trait( - 'shared_fom', - traits.Str(traits.Undefined, output=False, desc='shared data FOM')) - controller.add_trait( - 'volumes_format', - traits.Str(traits.Undefined, output=False, desc='Format used for volumes')) - controller.add_trait( - 'meshes_format', - traits.Str(traits.Undefined, output=False, - desc='Format used for meshes')) - controller.add_trait( - 'auto_fom', - traits.Bool(True, output=False, - desc='Look in all FOMs when a process is not found (in ' - 'addition to the standard share/foms). Note that auto_fom ' - 'looks for the first FOM matching the process to get ' - 'completion for, and does not handle ambiguities. Moreover ' - 'it brings an overhead (typically 6-7 seconds) the first ' - 'time it is used since it has to parse all available FOMs.')) - controller.add_trait( - 'fom_path', - traits.List(traits.Directory(output=False), - desc='list of additional directories where to look for FOMs')) - # FIXME: until directories are included in another config module - controller.add_trait( - 'input_directory', - traits.Directory(traits.Undefined, output=False, - desc='input study data directory')) - controller.add_trait( - 'output_directory', - traits.Directory(traits.Undefined, output=False, - desc='output study data directory')) - - conf = engine.settings.select_configurations( - environment, {'fom': 'any'}) - if conf: - fconf = conf.get( - 'capsul.engine.module.fom', {}) - controller.input_fom = fconf.get( - 'input_fom', traits.Undefined) - controller.output_fom = fconf.get( - 'output_fom', traits.Undefined) - controller.shared_fom = fconf.get( - 'shared_fom', traits.Undefined) - controller.volumes_format= fconf.get( - 'volumes_format', traits.Undefined) - controller.meshes_format = fconf.get( - 'meshes_format', traits.Undefined) - controller.auto_fom = fconf.get( - 'auto_fom', traits.Undefined) - controller.fom_path = fconf.get( - 'fom_path', traits.Undefined) - controller.input_directory= fconf.get( - 'input_directory', traits.Undefined) - controller.output_directory = fconf.get( - 'output_directory', traits.Undefined) - - widget = ScrollControllerWidget(controller, live=True) - widget.engine = engine - widget.environment = environment - widget.accept = types.MethodType(validate_config, widget) - - return widget
- -
- -
-
-
-
- -
-
- - - - \ No newline at end of file diff --git a/_modules/capsul/engine/module/fsl.html b/_modules/capsul/engine/module/fsl.html deleted file mode 100644 index 8d36d7219..000000000 --- a/_modules/capsul/engine/module/fsl.html +++ /dev/null @@ -1,322 +0,0 @@ - - - - - - - - CAPSUL — CAPSUL - Chain algorithm in pipelines and execute in many contexts - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - Capsul logo - - -
- - - - - -
-
-
-
- -

Source code for capsul.engine.module.fsl

-# -*- coding: utf-8 -*-
-from __future__ import absolute_import
-
-import capsul.engine
-import os
-from soma.path import find_in_path
-import os.path as osp
-from capsul import engine
-import six
-
-
-def init_settings(capsul_engine):
-    with capsul_engine.settings as settings:
-        settings.ensure_module_fields('fsl',
-            [dict(name='directory',
-                type='string',
-                description='Directory where FSL is installed'),
-            dict(name='config',
-                type='string',
-                description='path of fsl.sh file'),
-            dict(name='prefix',
-                type='string',
-                description='Prefix to add to FSL commands')
-            ])
-
-        # init a single config
-        config = settings.config('fsl', 'global')
-        if not config:
-            settings.new_config('fsl', 'global',
-                                {capsul_engine.settings.config_id_field:
-                                    'fsl'})
-
-    
-
-[docs] -def check_configurations(): - ''' - Checks if the activated configuration is valid to run FSL and returns an - error message if there is an error or None if everything is good. - ''' - fsl_prefix = capsul.engine.configurations.get( - 'capsul.engine.module.fsl',{}).get('prefix', '') - fsl_config = capsul.engine.configurations.get( - 'capsul.engine.module.fsl',{}).get('config') - if not fsl_config: - if not find_in_path('%sbet' % fsl_prefix): - return 'FSL command "%sbet" cannot be found in PATH' % fsl_prefix - else: - if fsl_prefix: - return 'FSL configuration must either use config or prefix but not both' - if not osp.exists(fsl_config): - return 'File "%s" does not exist' % fsl_config - if not fsl_config.endswith('fsl.sh'): - return 'File "%s" is not a path to fsl.sh script' % fsl_config - return None
- - - -
-[docs] -def check_notably_invalid_config(conf): - ''' - Checks if the given module config is obviously invalid, for instance if a mandatory path is not filled - - Returns - ------- - invalid: list - list of invalid config keys - ''' - invalid = [] - for k in ('directory', 'config'): - if getattr(conf, k, None) is None: - invalid.append(k) - return invalid
- - - -
-[docs] -def complete_configurations(): - ''' - Try to automatically set or complete the capsul.engine.configurations for FSL. - ''' - config = capsul.engine.configurations - config = config.setdefault('capsul.engine.module.fsl', {}) - fsl_dir = config.get('directory', os.environ.get('FSLDIR')) - fsl_prefix = config.get('prefix', '') - if fsl_dir and not fsl_prefix: - # Try to set fsl_config from FSLDIR environment variable - fsl_config = '%s/etc/fslconf/fsl.sh' % fsl_dir - if osp.exists(fsl_config): - config['config'] = fsl_config - elif not fsl_prefix: - # Try to set fsl_prefix by searching fsl-*bet in PATH - bet = find_in_path('fsl*-bet') - if bet: - config['prefix'] = os.path.basename(bet)[:-3]
- - - -
-[docs] -def activate_configurations(): - ''' - Activate the FSL module (set env variables) from the global configurations, - in order to use them via :mod:`capsul.in_context.fsl` functions - ''' - conf = engine.configurations.get('capsul.engine.module.fsl', {}) - fsl_dir = conf.get('directory') - if fsl_dir: - os.environ['FSLDIR'] = six.ensure_str(fsl_dir) - elif 'FSLDIR' in os.environ: - del os.environ['FSLDIR'] - fsl_prefix = conf.get('prefix') - if fsl_prefix: - os.environ['FSL_PREFIX'] = six.ensure_str(fsl_prefix) - elif 'FSL_PREFIX' in os.environ: - del os.environ['FSL_PREFIX'] - fsl_conf = conf.get('config') - if fsl_conf: - os.environ['FSL_CONFIG'] = six.ensure_str(fsl_conf) - elif 'FSL_CONFIG' in os.environ: - del os.environ['FSL_CONFIG']
- - - -
-[docs] -def edition_widget(engine, environment, config_id='fsl'): - ''' Edition GUI for FSL config - see - :class:`~capsul.qt_gui.widgets.settings_editor.SettingsEditor` - ''' - from soma.qt_gui.controller_widget import ScrollControllerWidget - from soma.controller import Controller - import types - import traits.api as traits - - def validate_config(widget): - widget.update_controller() - controller = widget.controller_widget.controller - with widget.engine.settings as session: - conf = session.config(config_id, widget.environment) - values = {'config_id': config_id} - for k in ('directory', 'config', 'prefix'): - value = getattr(controller, k) - if value is traits.Undefined: - value = None - values[k] = value - if conf is None: - session.new_config(config_id, widget.environment, values) - else: - for k, value in values.items(): - if k == 'config_id': - continue - setattr(conf, k, values[k]) - - controller = Controller() - - controller.add_trait('directory', traits.Directory(traits.Undefined, - desc='Directory where FSL is installed')) - controller.add_trait('config', traits.File( - traits.Undefined, - output=False, - desc='Parameter to specify the fsl.sh path')) - controller.add_trait('prefix', traits.String(traits.Undefined, - desc='Prefix to add to FSL commands')) - - conf = engine.settings.select_configurations( - environment, {'fsl': 'any'}) - if conf: - fconf = conf.get('capsul.engine.module.fsl', {}) - controller.directory = fconf.get('directory', traits.Undefined) - controller.config = fconf.get('config', traits.Undefined) - controller.prefix = fconf.get('prefix', traits.Undefined) - - widget = ScrollControllerWidget(controller, live=True) - widget.engine = engine - widget.environment = environment - widget.accept = types.MethodType(validate_config, widget) - - return widget
- -
- -
-
-
-
- -
-
- - - - \ No newline at end of file diff --git a/_modules/capsul/engine/module/matlab.html b/_modules/capsul/engine/module/matlab.html deleted file mode 100644 index c0ea6910f..000000000 --- a/_modules/capsul/engine/module/matlab.html +++ /dev/null @@ -1,281 +0,0 @@ - - - - - - - - CAPSUL — CAPSUL - Chain algorithm in pipelines and execute in many contexts - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - Capsul logo - - -
- - - - - -
-
-
-
- -

Source code for capsul.engine.module.matlab

-# -*- coding: utf-8 -*-
-from __future__ import absolute_import
-
-import capsul.engine
-import os
-
-#from soma.controller import Controller
-#from traits.api import File, Undefined, Instance
-
-    
-def init_settings(capsul_engine):
-    with capsul_engine.settings as settings:
-        settings.ensure_module_fields('matlab',
-        [dict(name='executable',
-              type='string',
-              description='Full path of the matlab executable'),
-         dict(name='mcr_directory',
-              type='string',
-              description='Full path of the matlab MCR directory, for use '
-                  'with standalone binaries'),
-         ])
-
-
-
-[docs] -def check_configurations(): - ''' - Check if the activated configuration is valid for Matlab and return - an error message if there is an error or None if everything is good. - ''' - matlab_executable = capsul.engine.configurations.get( - 'capsul.engine.module.matlab', {}).get('executable') - mcr = capsul.engine.configurations.get( - 'capsul.engine.module.matlab', {}).get('mcr_directory') - if not matlab_executable and not mcr: - return \ - 'both matlab.executable and matlab.mcr_directory are not defined' - if matlab_executable and not os.path.exists(matlab_executable): - return 'Matlab executable is defined as "%s" but this path does not exist' % matlab_executable - return None
- - - -
-[docs] -def check_notably_invalid_config(conf): - ''' - Checks if the given module config is obviously invalid, for instance if a mandatory path is not filled - - Returns - ------- - invalid: list - list of invalid config keys - ''' - invalid = [] - for k in ('executable', 'mcr_directory'): - if getattr(conf, k, None) is None: - invalid.append(k) - if len(invalid) == 1: - # if one of the paths is filled, then it should be OK. - # however it may depend on uses (SPM standalone needs mcr_directory, - # for instance) - return [] - return invalid
- - - -
-[docs] -def edition_widget(engine, environment, config_id='matlab'): - ''' Edition GUI for matlab config - see - :class:`~capsul.qt_gui.widgets.settings_editor.SettingsEditor` - ''' - from soma.qt_gui.controller_widget import ScrollControllerWidget - from soma.controller import Controller - import types - import traits.api as traits - - def validate_config(widget): - widget.update_controller() - controller = widget.controller_widget.controller - with widget.engine.settings as session: - conf = session.config(config_id, widget.environment) - values = {'config_id': config_id} - if controller.executable in (None, traits.Undefined, ''): - values['executable'] = None - else: - values['executable'] = controller.executable - if controller.mcr_directory in (None, traits.Undefined, ''): - values['mcr_directory'] = None - else: - values['mcr_directory'] = controller.mcr_directory - if conf is None: - session.new_config(config_id, widget.environment, values) - else: - for k in ('executable', 'mcr_directory', ): - # don't check invalid files: they may be valid on a remote - # server - #if (k == 'mcr_directory' and - #values[k] and - #not os.path.isdir(values[k])): - #raise NotADirectoryError('\nMatlab mcr_directory ' - #'was not updated:\n{} is ' - #'not existing!'.format( - #values[k])) - #elif (k == 'executable' and - #values[k] and - #not os.path.isfile(values[k])): - #raise FileNotFoundError('\nMatlab executable ' - #'was not updated:\n{} is ' - #'not existing!'.format( - #values[k])) - #else: - setattr(conf, k, values[k]) - - controller = Controller() - controller.add_trait('executable', - traits.File(desc= - 'Full path of the matlab executable')) - controller.add_trait('mcr_directory', - traits.Directory(desc='Full path of the matlab MCR ' - 'directory, or use with standalone ' - 'binaries')) - - conf = engine.settings.select_configurations( - environment, {'matlab': 'any'}) - if conf: - controller.executable = conf.get( - 'capsul.engine.module.matlab', {}).get('executable', - traits.Undefined) - controller.mcr_directory = conf.get( - 'capsul.engine.module.matlab', {}).get('mcr_directory', - traits.Undefined) - - widget = ScrollControllerWidget(controller, live=True) - widget.engine = engine - widget.environment = environment - widget.accept = types.MethodType(validate_config, widget) - - return widget
- -
- -
-
-
-
- -
-
- - - - \ No newline at end of file diff --git a/_modules/capsul/engine/module/python.html b/_modules/capsul/engine/module/python.html deleted file mode 100644 index cf19b77ee..000000000 --- a/_modules/capsul/engine/module/python.html +++ /dev/null @@ -1,262 +0,0 @@ - - - - - - - - CAPSUL — CAPSUL - Chain algorithm in pipelines and execute in many contexts - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - Capsul logo - - -
- - - - - -
-
-
-
- -

Source code for capsul.engine.module.python

-# -*- coding: utf-8 -*-
-''' Python configuration module for CAPSUL
-
-This config module allows the customization of python executable and python path in process execution. It can (as every config module) assign specific config values for different environments (computing resources, typically).
-
-Python configuration is slightly different from other config modules in the way that it cannot be handled during execution inside a python library: python executable and modules path have to be setup before starting python and loading modules. So the config here sometimes has to be prepared from client side and hard-coded in the job to run.
-
-For this reason, what we call here "python jobs" have a special handling. "python jobs" are :class:`~capsul.process.process.Process` classes defining a :meth:`~capsul.process.process.Process._run_process` method, and not :meth:`~capsul.process.process.Process.get_commandline`. Processing are thus python functions or methods, and need the capsul library to run.
-
-Python jobs are handled in workflow building (:mod:`capsul.pipeline.pipeline_workflow`), and jobs on engine side should not have to bother about it.
-
-The python config module is not mandatory: if no specific configuration is needed, jobs are run using the python command from the path, following the client ``sys.executable`` short name (if the client runs ``/usr/bin/python3``, the engine will try to use ``python3`` from the ``PATH``.
-
-The python config module is used optionally (if there is a config, it is used, otherwise no error is produced), and automatically for all jobs: no need to declare it in jobs :meth:`~capsul.process.process.Process.requirements` method.
-
-Inside process execution, the module is otherwise handled like any other.
-'''
-
-from __future__ import absolute_import
-
-import capsul.engine
-import os
-import sys
-
-
-def init_settings(capsul_engine):
-    with capsul_engine.settings as settings:
-        settings.ensure_module_fields('python',
-        [dict(name='executable',
-              type='string',
-              description='Full path of the python executable'),
-        dict(name='path',
-              type='list_string',
-              description='paths to prepend to sys.path'),
-         ])
-
-
-
-[docs] -def activate_configurations(): - ''' - Activate the python module from the global configurations - ''' - py_conf = capsul.engine.configurations.get('capsul.engine.module.python') - if py_conf: - py_path = py_conf.get('path') - if py_path: - sys.path = py_path + [p for p in sys.path if p not in py_path]
- - -
-[docs] -def check_notably_invalid_config(conf): - ''' - Checks if the given module config is obviously invalid, for instance if a mandatory path is not filled - - Returns - ------- - invalid: list - list of invalid config keys - ''' - invalid = [] - for k in ('executable', ): - if getattr(conf, k, None) is None: - invalid.append(k) - return invalid
- - - -
-[docs] -def edition_widget(engine, environment, config_id='python'): - ''' Edition GUI for python config - see - :class:`~capsul.qt_gui.widgets.settings_editor.SettingsEditor` - ''' - from soma.qt_gui.qt_backend import Qt - from soma.qt_gui.controller_widget import ScrollControllerWidget - from soma.controller import Controller - import types - import traits.api as traits - - def validate_config(widget): - widget.update_controller() - controller = widget.controller_widget.controller - with widget.engine.settings as session: - conf = session.config(config_id, widget.environment) - values = {'config_id': config_id, - 'path': controller.path} - if controller.executable in (None, - traits.Undefined, ''): - values['executable'] = None - else: - values['executable'] = controller.executable - if conf is None: - session.new_config(config_id, widget.environment, values) - else: - for k in ('path', 'executable'): - setattr(conf, k, values[k]) - - controller = Controller() - controller.add_trait('executable', - traits.Str(desc='Full path of the python executable')) - controller.add_trait('path', - traits.List(traits.Directory(), [], - desc='paths to prepend to sys.path')) - - conf = engine.settings.select_configurations( - environment, {'python': 'any'}) - if conf: - controller.executable = conf.get( - 'capsul.engine.module.python', {}).get('executable', - traits.Undefined) - controller.path = conf.get( - 'capsul.engine.module.python', {}).get('path', []) - - widget = ScrollControllerWidget(controller, live=True) - widget.engine = engine - widget.environment = environment - widget.accept = types.MethodType(validate_config, widget) - - return widget
- -
- -
-
-
-
- -
-
- - - - \ No newline at end of file diff --git a/_modules/capsul/engine/module/spm.html b/_modules/capsul/engine/module/spm.html deleted file mode 100644 index 2768704eb..000000000 --- a/_modules/capsul/engine/module/spm.html +++ /dev/null @@ -1,419 +0,0 @@ - - - - - - - - CAPSUL — CAPSUL - Chain algorithm in pipelines and execute in many contexts - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - Capsul logo - - -
- - - - - -
-
-
-
- -

Source code for capsul.engine.module.spm

-# -*- coding: utf-8 -*-
-from __future__ import absolute_import
-
-from capsul import engine
-import os
-import six
-
-#import glob
-#import os.path as osp
-#import weakref
-##import subprocess # Only in case of matlab call (auto_configuration func)
-
-#from soma.controller import Controller
-#from traits.api import Directory, Undefined, Instance, String, Bool
-
-#from . import matlab
-    
-
-def init_settings(capsul_engine):
-    with capsul_engine.settings as settings:
-        settings.ensure_module_fields('spm',
-            [dict(name='directory',
-                type='string',
-                description='Directory where SPM is installed'),
-            dict(name='version',
-                type='string',
-                description='Version of SPM release (8 or 12)'),
-            dict(name='standalone',
-                type='boolean',
-                description='If this parameter is set to True, use the '
-                            'standalone SPM version, otherwise use Matlab.')
-            ])
-
-
-def config_dependencies(config):
-    return {'matlab': 'any'}
-
-#def set_environ(config, environ):
-    #spm_config = config.get('spm', {})
-    #use = spm_config.get('use')
-    #if  use is True or (use is None and 'directory' in spm_config):
-        #error_message = check_environ(environ)
-        #if error_message:
-            #complete_environ(config, environ)
-        #error_message = check_environ(environ)
-
-        #if error_message:
-            #raise EnvironmentError(error_message)
-
-    
-#def check_environ(environ):
-    #'''
-    #Check if the configuration is valid to run SPM and returns an error
-    #message if there is an error or None if everything is good.
-    #'''
-    #if not environ.get('SPM_DIRECTORY'):
-        #return 'SPM directory is not defined'
-    #if not environ.get('SPM_VERSION'):
-        #return 'SPM version is not defined (maybe %s is not a valid SPM directory)' % environ['SPM_DIRECTORY']
-    #if not environ.get('SPM_STANDALONE'):
-        #return 'No selection of SPM installation type : Standalone or Matlab'
-    #if not osp.isdir(environ['SPM_DIRECTORY']):
-        #return 'No valid SPM directory: %s' % environ['SPM_DIRECTORY']
-    #if environ['SPM_STANDALONE'] != 'yes':
-        #matlab_error = matlab.check_environ(environ)
-        #if matlab_error:
-            #return 'Matlab configuration must be valid for SPM: ' + matlab_error
-    #return None
-
-#def complete_environ(config, environ):
-    #'''
-    #Try to automatically complete environment for SPM
-    #'''
-    #spm_directory = config.get('spm', {}).get('directory')
-    #if spm_directory:
-        #environ['SPM_DIRECTORY'] = spm_directory
-        #mcr = glob.glob(osp.join(spm_directory, 'spm*_mcr'))
-        #if mcr:
-            #fileName = osp.basename(mcr[0])
-            #inc = 1
-
-            #while fileName[fileName.find('spm') + 3:
-                           #fileName.find('spm') + 3 + inc].isdigit():
-                #environ['SPM_VERSION'] = fileName[fileName.find('spm') + 3:
-                                                  #fileName.find('spm') + 3
-                                                                       #+ inc]
-                #inc+=1
-        
-            #environ['SPM_STANDALONE'] = 'yes'
-            
-        #else:
-            #environ['SPM_STANDALONE'] = 'no'
-            ## determine SPM version (currently 8 or 12)
-            #if osp.isdir(osp.join(spm_directory, 'toolbox', 'OldNorm')):
-                #environ['SPM_VERSION'] = '12'
-            #elif osp.isdir(osp.join(spm_directory, 'templates')):
-                #environ['SPM_VERSION'] = '8'
-            #else:
-                #environ.pop('SPM_VERSION', None)
-
-# For SPM with MATLAB license, if we want to get the SPM version from a system
-# call to matlab:.
-#            matlab_cmd = ('addpath("' + capsul_engine.spm.directory + '");'
-#                          ' [name, ~]=spm("Ver");'
-#                          ' fprintf(2, \"%s\", name(4:end));'
-#                          ' exit')
-#
-#            try:
-#                p = subprocess.Popen([capsul_engine.matlab.executable,
-#                                       '-nodisplay', '-nodesktop',
-#                                       '-nosplash', '-singleCompThread',
-#                                       '-batch', matlab_cmd],
-#                                     stdin=subprocess.PIPE,
-#                                     stdout=subprocess.PIPE,
-#                                     stderr=subprocess.PIPE)
-#                output, err = p.communicate()
-#                rc = p.returncode
-#
-#            except FileNotFoundError as e:
-#                print('\n {0}'.format(e))
-#                rc = 111
-#
-#            except Exception as e:
-#                print('\n {0}'.format(e))
-#                rc = 111
-#
-#            if (rc != 111) and (rc != 0):
-#                print(err)
-#
-#            if rc == 0:
-#                 capsul_engine.spm.version = err.decode("utf-8")
-#
-
-
-
-[docs] -def activate_configurations(): - ''' - Activate the SPM module (set env variables) from the global configurations, - in order to use them via :mod:`capsul.in_context.spm` functions - ''' - conf = engine.configurations.get('capsul.engine.module.spm', {}) - mlab_conf = engine.configurations.get('capsul.engine.module.matlab', {}) - spm_dir = conf.get('directory') - mcr_dir = mlab_conf.get('mcr_directory') - if spm_dir: - os.environ['SPM_DIRECTORY'] = six.ensure_str(spm_dir) - elif 'SPM_DIRECTORY' in os.environ: - del os.environ['SPM_DIRECTORY'] - spm_version = conf.get('version') - if spm_version: - os.environ['SPM_VERSION'] = six.ensure_str(spm_version) - elif 'SPM_VERSION' in os.environ: - del os.environ['SPM_VERSION'] - spm_standalone = conf.get('standalone') - if spm_standalone is not None: - os.environ['SPM_STANDALONE'] = 'yes' if spm_standalone else 'no' - if spm_standalone and mcr_dir: - os.environ['MCR_HOME'] = mcr_dir - elif 'SPM_STANDALONE' in os.environ: - del os.environ['SPM_STANDALONE']
- - - -
-[docs] -def check_notably_invalid_config(conf): - ''' - Checks if the given module config is obviously invalid, for instance if a mandatory path is not filled - - Returns - ------- - invalid: list - list of invalid config keys - ''' - invalid = [] - #for k in ('directory', 'version'): - # if getattr(conf, k, None) is None: - # invalid.append(k) - if getattr(conf, 'directory', None) is None: - invalid.append('directory') - return invalid
- - - -
-[docs] -def edition_widget(engine, environment, config_id='any'): - ''' Edition GUI for SPM config - see - :class:`~capsul.qt_gui.widgets.settings_editor.SettingsEditor` - ''' - from soma.qt_gui.controller_widget import ScrollControllerWidget - from soma.controller import Controller - import types - import traits.api as traits - - def validate_config(widget): - widget.update_controller() - controller = widget.controller_widget.controller - with widget.engine.settings as session: - values = {} - if controller.directory in (None, traits.Undefined, ''): - values['directory'] = None - else: - values['directory'] = controller.directory - values['standalone'] = controller.standalone - if controller.version in (None, traits.Undefined, ''): - values['version'] = None - else: - values['version'] = controller.version - id = 'spm%s%s' % (controller.version if - controller.version != traits.Undefined else '', - '-standalone' if controller.standalone else '') - values['config_id'] = id - query = 'config_id == "%s"' % id - conf = session.config('spm', widget.environment, selection=query) - if conf is None: - session.new_config('spm', widget.environment, values) - else: - for k in ('directory', 'standalone', 'version'): - if (k == 'directory' and - values[k] and - not os.path.isdir(values[k])): - raise NotADirectoryError('\nSPM directory was not ' - 'updated:\n{} is not ' - 'existing!'.format(values[k])) - else: - setattr(conf, k, values[k]) - if id != widget.config_id: - try: - session.remove_config('spm', widget.environment, - widget.config_id) - except Exception: - pass - widget.config_id = id - - controller = Controller() - controller.add_trait("directory", traits.Directory( - traits.Undefined, - output=False, - desc="Directory containing SPM.")) - controller.add_trait("standalone", traits.Bool( - False, - desc="If True, use the standalone version of SPM.")) - controller.add_trait('version', traits.Str( - traits.Undefined, output=False, - desc='Version string for SPM: "12", "8", etc.')) - - conf = None - if config_id == 'any': - conf = engine.settings.select_configurations( - environment, {'spm': 'any'}) - else: - try: - conf = engine.settings.select_configurations( - environment, {'spm': 'config_id=="%s"' % config_id}) - except Exception: - pass - if conf: - controller.directory = conf.get( - 'capsul.engine.module.spm', {}).get('directory', - traits.Undefined) - controller.standalone = conf.get( - 'capsul.engine.module.spm', {}).get('standalone', False) - controller.version = conf.get( - 'capsul.engine.module.spm', {}).get('version', traits.Undefined) - config_id = conf.get( - 'capsul.engine.module.spm', {}).get('config_id', config_id) - - # TODO handle several configs - - widget = ScrollControllerWidget(controller, live=True) - widget.engine = engine - widget.environment = environment - widget.config_id = config_id - widget.accept = types.MethodType(validate_config, widget) - - return widget
- -
- -
-
-
-
- -
-
- - - - \ No newline at end of file diff --git a/_modules/capsul/engine/run.html b/_modules/capsul/engine/run.html deleted file mode 100644 index 1a2748eea..000000000 --- a/_modules/capsul/engine/run.html +++ /dev/null @@ -1,546 +0,0 @@ - - - - - - - - CAPSUL — CAPSUL - Chain algorithm in pipelines and execute in many contexts - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - Capsul logo - - -
- - - - - -
-
-
-
- -

Source code for capsul.engine.run

-# -*- coding: utf-8 -*-
-
-'''
-Implementation of :class:`~capsul.engine.CapsulEngine` processing methods.
-They have been moved to this file for clarity.
-
-Running is always using `Soma-Workflow </~https://github.com/populse/soma-workflow/>`_.
-'''
-from __future__ import absolute_import
-from __future__ import print_function
-
-from capsul.pipeline.pipeline import Pipeline
-from capsul.pipeline.pipeline_nodes import ProcessNode
-from traits.api import Undefined
-import six
-import tempfile
-import os
-import io
-
-
-
-[docs] -class WorkflowExecutionError(Exception): - ''' - Exception class raised when a workflow execution fails. - It holds references to the - :class:`~soma_workflow.client.WorkflowController` and the workflow id - ''' - def __init__(self, controller, workflow_id, status=None, - workflow_kept=True, verbose=True): - wk = '' - wc = '' - precisions = '' - if workflow_kept: - wk = 'not ' - wc = ' from soma_workflow and must be deleted manually' - if workflow_kept: - self.controller = controller - self.workflow_id = workflow_id - if verbose: - import soma_workflow.client as swclient - - failed_jobs = swclient.Helper.list_failed_jobs( - workflow_id, controller) - precisions_list = ['\nFailed jobs: %s' % repr(failed_jobs)] - from soma_workflow import constants as swc - aborted_statuses = set( - [swc.EXIT_UNDETERMINED, - swc.EXIT_ABORTED, - swc.FINISHED_TERM_SIG, - swc.FINISHED_UNCLEAR_CONDITIONS, - swc.USER_KILLED]) - aborted_jobs = swclient.Helper.list_failed_jobs( - workflow_id, controller, include_statuses=aborted_statuses) - aborted_jobs = [job for job in aborted_jobs - if job not in failed_jobs] - precisions_list.append('Aborted/killed jobs: %s' - % repr(aborted_jobs)) - tmp1 = tempfile.mkstemp(prefix='capsul_swf_job_stdout') - tmp2 = tempfile.mkstemp(prefix='capsul_swf_job_stderr') - os.close(tmp1[0]) - os.close(tmp2[0]) - fileio = io.StringIO() - try: - controller.log_failed_workflow(workflow_id, file=fileio) - precisions_list.append(fileio.getvalue()) - - #jobs = failed_jobs + aborted_jobs - #cmds = controller.jobs(jobs) - #workflow = controller.workflow(workflow_id) - #for job_id in jobs: - #jinfo = cmds[job_id] - #if job_id in failed_jobs: - #has_run = True - #else: - #has_run = False - #status = controller.job_termination_status(job_id) - #controller.retrieve_job_stdouterr(job_id, tmp1[1], tmp2[1]) - #with open(tmp1[1]) as f: - #stdout = f.read() - #with open(tmp2[1]) as f: - #stderr = f.read() - #full_job = [j for j in workflow.jobs - #if workflow.job_mapping[j].job_id == job_id][0] - #precisions_list += [ - #'============================================', - #'---- failed job info ---', - #'* job: %d: %s' % (job_id, jinfo[0]), - #'* exit status: %s' % status[0], - #'* commandline:', - #jinfo[1], - #'* exit value: %s' % str(status[1]), - #'* term signal: %s' % str(status[2]), - #'---- env ----', - #repr(full_job.env), - #'---- configuration ----', - #repr(full_job.configuration), - #'---- stdout ----', - #stdout, - #'---- stderr ----', - #stderr, - ##'---- full host env ----', - ##repr(os.environ) - #] - finally: - if os.path.exists(tmp1[1]): - os.unlink(tmp1[1]) - if os.path.exists(tmp2[1]): - os.unlink(tmp2[1]) - precisions = '\n'.join(precisions_list) - - super(WorkflowExecutionError, self).__init__('Error during ' - 'workflow execution. Status=%s.\n' - 'The workflow has %sbeen removed%s. %s' - % (status, wk, wc, precisions))
- - - -
-[docs] -def start(engine, process, workflow=None, history=True, get_pipeline=False, **kwargs): - ''' - Asynchronously start the execution of a process or pipeline in the - connected computing environment. Returns an identifier of - the process execution and can be used to get the status of the - execution or wait for its termination. - - TODO: - if history is True, an entry of the process execution is stored in - the database. The content of this entry is to be defined but it will - contain the process parameters (to restart the process) and will be - updated on process termination (for instance to store execution time - if possible). - - Parameters - ---------- - engine: CapsulEngine - process: Process or Pipeline instance - workflow: Workflow instance (optional - if already defined before call) - history: bool (optional) - TODO: not implemented yet. - get_pipeline: bool (optional) - if True, start() will return a tuple (execution_id, pipeline). The - pipeline is normally the input pipeline (process) if it is actually - a pipeline. But if the input process is a "single process", it will - be inserted into a small pipeline for execution. This pipeline will - be the one actually run, and may be passed to :meth:`wait` to set - output parameters. - - Returns - ------- - execution_id: int - execution identifier (actually a soma-workflow id) - pipeline: Pipeline instance (optional) - only returned if get_pipeline is True. - ''' - - # set parameters values - for k, v in six.iteritems(kwargs): - setattr(process, k, v) - - missing = process.get_missing_mandatory_parameters() - if len(missing) != 0: - ptype = 'process' - if isinstance(process, Pipeline): - ptype = 'pipeline' - raise ValueError('In %s %s: missing mandatory parameters: %s' - % (ptype, process.name, - ', '.join(missing))) - - # Use soma workflow to execute the pipeline or process in parallel - # on the local machine - - # Create soma workflow pipeline - from capsul.pipeline.pipeline_workflow import workflow_from_pipeline - import soma_workflow.client as swclient - - swf_config = engine.settings.select_configurations( - 'global', {'somaworkflow': 'config_id=="somaworkflow"'}) - swm = engine.study_config.modules['SomaWorkflowConfig'] - swm.connect_resource(engine.connected_to()) - controller = swm.get_workflow_controller() - resource_id = swm.get_resource_id() - - resource_config_d = engine.settings.select_configurations( - resource_id, {'somaworkflow': 'config_id=="somaworkflow"'}) - resource_config = resource_config_d.get( - 'capsul.engine.module.somaworkflow', {}) - has_resource_config = ('capsul.engine.module.somaworkflow' - in resource_config_d) - - if has_resource_config: - environment = resource_id - else: - environment = 'global' - - if workflow is None: - workflow = workflow_from_pipeline(process, environment=environment) - - queue = getattr(resource_config, 'queue', None) - #if hasattr(engine.study_config.somaworkflow_computing_resources_config, - #resource_id): - #res_conf = getattr( - #engine.study_config.somaworkflow_computing_resources_config, - #resource_id) - #queue = res_conf.queue - #if queue is Undefined: - #queue = None - workflow_name = process.name - wf_id = controller.submit_workflow(workflow=workflow, name=workflow_name, - queue=queue) - swclient.Helper.transfer_input_files(wf_id, controller) - - if get_pipeline: - return wf_id, workflow.pipeline() - # else forget the pipeline - return wf_id
- - - -
-[docs] -def wait(engine, execution_id, timeout=-1, pipeline=None): - ''' - Wait for the end of a process execution (either normal termination, - interruption or error). - ''' - import soma_workflow.client as swclient - from soma_workflow import constants - - swm = engine.study_config.modules['SomaWorkflowConfig'] - swm.connect_resource(engine.connected_to()) - controller = swm.get_workflow_controller() - wf_id = execution_id - - controller.wait_workflow(wf_id, timeout=timeout) - workflow_status = controller.workflow_status(wf_id) - if workflow_status != constants.WORKFLOW_DONE: - # not finished - return workflow_status - - # get output values - if pipeline: - proc_map = {} - todo = [pipeline] - while todo: - process = todo.pop(0) - if isinstance(process, Pipeline): - todo += [n.process for n in process.nodes.values() - if n is not process.pipeline_node - and isinstance(n, ProcessNode)] - else: - proc_map[id(process)] = process - - eng_wf = controller.workflow(wf_id) - for job in eng_wf.jobs: - if job.has_outputs: - out_params = controller.get_job_output_params( - eng_wf.job_mapping[job].job_id) - if out_params: - process = proc_map.get(job.process_hash) - if process is None: - # iteration or non-process job - continue - for param in list(out_params.keys()): - if process.trait(param) is None: - del out_params[param] - try: - process.import_from_dict(out_params) - except Exception as e: - print('error while importing outputs in', process.name) - print('outputs:', out_params) - print(e) - - # TODO: should we transfer if the WF fails ? - swclient.Helper.transfer_output_files(wf_id, controller) - return status(engine, execution_id)
- - - -
-[docs] -def interrupt(engine, execution_id): - ''' - Try to stop the execution of a process. Does not wait for the process - to be terminated. - ''' - swm = engine.study_config.modules['SomaWorkflowConfig'] - swm.connect_resource(engine.connected_to()) - controller = swm.get_workflow_controller() - controller.stop_workflow(execution_id)
- - - -
-[docs] -def status(engine, execution_id): - ''' - Return a simple value with the status of an execution (queued, - running, terminated, error, etc.) - ''' - from soma_workflow import constants - - swm = engine.study_config.modules['SomaWorkflowConfig'] - swm.connect_resource(engine.connected_to()) - controller = swm.get_workflow_controller() - workflow_status = controller.workflow_status(execution_id) - if workflow_status == constants.WORKFLOW_DONE: - # finished, but in which state ? - elements_status = controller.workflow_elements_status(execution_id) - failed_jobs = [element for element in elements_status[0] - if element[1] == constants.FAILED - or (element[1] == constants.DONE and - (element[3][0] - not in (constants.FINISHED_REGULARLY, None) - or element[3][1] != 0))] - if len(failed_jobs) != 0: - workflow_status = 'workflow_failed' - - return workflow_status
- - - -
-[docs] -def detailed_information(engine, execution_id): - ''' - Return complete (and possibly big) information about a process - execution. - ''' - swm = engine.study_config.modules['SomaWorkflowConfig'] - swm.connect_resource(engine.connected_to()) - controller = swm.get_workflow_controller() - elements_status = controller.workflow_elements_status(execution_id) - - return elements_status
- - - -
-[docs] -def dispose(engine, execution_id, conditional=False): - ''' - Update the database with the current state of a process execution and - free the resources used in the computing resource (i.e. remove the - workflow from SomaWorkflow). - - If ``conditional`` is set to True, then dispose is only done if the - configuration does not specify to keep succeeded / failed workflows. - ''' - keep = False - if conditional: - if engine.study_config.somaworkflow_keep_succeeded_workflows: - keep = True - else: - keep = False - if engine.study_config.somaworkflow_keep_failed_workflows: - # must see it it failed or not - from soma_workflow import constants - - status = engine.status(execution_id) - if status != constants.WORKFLOW_DONE: - keep = True - if not keep: - swm = engine.study_config.modules['SomaWorkflowConfig'] - swm.connect_resource(engine.connected_to()) - controller = swm.get_workflow_controller() - controller.delete_workflow(execution_id)
- - # TODO: update engine DB - - -def call(engine, process, history=True, **kwargs): - eid, pipeline = engine.start(process, workflow=None, history=history, get_pipeline=True, - **kwargs) - status = engine.wait(eid, pipeline=pipeline) - engine.dispose(eid, conditional=True) - return status - - -def check_call(engine, process, history=True, **kwargs): - eid, pipeline = engine.start(process, workflow=None, history=history, get_pipeline=True, - **kwargs) - status = engine.wait(eid, pipeline=pipeline) - try: - engine.raise_for_status(status, eid) - finally: - engine.dispose(eid, conditional=True) - - -
-[docs] -def raise_for_status(engine, status, execution_id=None): - ''' - Raise an exception if a process execution failed - ''' - from soma_workflow import constants - - if status != constants.WORKFLOW_DONE: - swm = engine.study_config.modules['SomaWorkflowConfig'] - swm.connect_resource(engine.connected_to()) - controller = swm.get_workflow_controller() - raise WorkflowExecutionError( - controller, execution_id, status, - engine.study_config.somaworkflow_keep_failed_workflows)
- -
- -
-
-
-
- -
-
- - - - \ No newline at end of file diff --git a/_modules/capsul/engine/settings.html b/_modules/capsul/engine/settings.html deleted file mode 100644 index 64b5760d4..000000000 --- a/_modules/capsul/engine/settings.html +++ /dev/null @@ -1,727 +0,0 @@ - - - - - - - - CAPSUL — CAPSUL - Chain algorithm in pipelines and execute in many contexts - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - Capsul logo - - -
- - - - - -
-
-
-
- -

Source code for capsul.engine.settings

-# -*- coding: utf-8 -*-
-
-'''
-This module provides classes to store CapsulEngine settings for several execution environment and choose a configuration for a given execution environment. Setting management in Capsul has several features that makes it different from classical ways to deal with configuration:
-
-* CapsulEngine must be able to deal with several configurations for the same software. For instance, one can configure both SPM 8 and SPM 12 and choose later the one to use.
-* A single pipeline may use various configurations of a software. For instance a pipeline could compare the results of SPM 8 and SPM 12.
-* Settings definition must be modular. It must be possible to define possible settings values either in Capsul (for well known for instance) or in external modules that can be installed separately.
-* Capsul must deal with module dependencies. For instance the settings of SPM may depends on the settings of Matlab. But this dependency exists only if a non standalone SPM version is used. Therefore, dependencies between modules may depends on settings values.
-* CapsulEngine settings must provide the possibility to express a requirement on settings. For instance a process may require to have version of SPM greater or equal to 12.
-* The configuration of a module can be defined for a specific execution environment. Settings must allow to deal with several executions environments (e.g. a local machine and a computing cluster). Each environment may have a different configuration (for instance the SPM installation directory is not the same on the local computer and on a computing cluster).
-
-To implement all these features, it was necessary to have a settings storage system providing a query language to express requirements such as ``spm.version >= 12``. Populse_db was thus chosen as the storage and query system for settings. Some of the settings API choices have been influenced by populse_db API.
-
-CapsulEngine settings are organized in modules. Each module defines and documents the schema of values that can be set for its configuration. Typically, a module is dedicated to a software. For instance the module for SPM accepts confiurations containing a version (a string), an install directory (a string), a standalone/matlab flag (a boolean), etc. This schema is used to record configuration documents for the module. There can be several configuration documents per module. Each document corresponds to a full configuration of the module (for instance a document for SPM 8 configuration and another for SPM 12, or one for SPM 12 standalone and another for SPM 12 with matlab).
-
-Settings cannot be used directly to configure the execution of a software. It is necessary to first select a single configuration document for each module. This configurations selection step is done by the :meth:`Settings.select_configurations` method.
-
-'''
-
-#
-# Questions about settings
-# How to automatically build a GUI to input settings values ?
-# * default values
-# * mandatory / optional settings
-# * dependencies between settings
-#
-# all these were "simple" using Controllers but are in a way "too free" now,
-# and "too constrained" in another way (table columns: not dicts or structures)
-#
-# config modules might provide validation functions (check consistency,
-# completeness of config values), and maybe a Controller to build a GUI ?
-#
-# How to store additional data indirectly linked with settings values ?
-# Some modules were using objects shared through StudyConfig.modules_data
-# (or CapsulEngine).
-#
-# doc on modules activation / use ?
-#
-
-import importlib
-from uuid import uuid4
-import sys
-
-
-
-[docs] -class Settings: - ''' - Main class for the management of CapsulEngine settings. Since these - settings are always stored in a populse_db database, it is necessary to - activate a settings session in order to read or modify settings. This is - done by using a with clause:: - - from capsul.api import capsul_engine - - # Create a CapsulEngine - ce = capsul_engine() - with ce.settings as settings: - # Read or modify settings here - conf = settings.new_config('spm', 'global', - {'version': '12', 'standalone': True}) - # modify value - conf.directory = '/usr/local/spm12-standalone' - ''' - - global_environment = 'global' - collection_prefix = 'settings/' - environment_field = 'config_environment' - config_id_field = 'config_id' - - def __init__(self, populse_db): - ''' - Create a settings instance using the given populse_db instance - ''' - self.populse_db = populse_db - self.module_notifiers = {} - - def __enter__(self): - ''' - Starts a session to read or write settings - ''' - dbs = self.populse_db.__enter__() - return SettingsSession(dbs, module_notifiers=self.module_notifiers) - - def __exit__(self, *args): - self.populse_db.__exit__(*args) - -
-[docs] - @staticmethod - def module_name(module_name): - ''' - Return a complete module name (which must be a valid Python module - name) given a possibly abbreviated module name. This method must - be used whenever a module name is written by a user (for instance - in a configuration file. - This method add the prefix `'capsul.engine.module.'` if the module - name does not contain a dot. - ''' - if '.' not in module_name: - module_name = 'capsul.engine.module.' + module_name - return module_name
- - -
-[docs] - def select_configurations(self, environment, uses=None, - check_invalid_mods=False): - ''' - Select a configuration for a given environment. A configuration is - a dictionary whose keys are module names and values are - configuration documents. The returned set of configuration per module - can be activaded with `capsul.api.activate_configuration()`. - - The `uses` parameter determine which modules - must be included in the configuration. If not given, this method - considers all configurations for every module defined in settings. - This parameter is a dictionary whose keys are a module name and - values are populse_db queries used to select module. - - The environment parameter defines the execution environment in which - the configurations will be used. For each module, configurations are - filtered with the query. First, values are searched in the given - environment and, if no result is found, the `'global'` environment - (the value defined in `Settings.global_environment`) is used. - - If `check_invalid_mods` is True, then each selected config module is - checked for missing values and discarded if there are. - - example - ------- - To select a SPM version greater than 8 for an environment called - `'my_environment'` one could use the following code:: - - config = ce.select_configurations('my_environment', - uses={'spm': 'version > 8'}) - ''' - configurations = {} - with self as settings: - if uses is None: - uses = {} - for collection in (i.collection_name - for i in - settings._dbs.get_collections()): - if collection.startswith(Settings.collection_prefix): - module_name = \ - collection[len(Settings.collection_prefix):] - uses[module_name] = 'ALL' - uses_stack = list(uses.items()) - while uses_stack: - module, query = uses_stack.pop(-1) - # append environment to config_id if it is given in the filter - if 'config_id=="' in query: - i = query.index('config_id=="') - i = query.index('"', i+12) - query = '%s-%s%s' % (query[:i], environment, query[i:]) - - module = self.module_name(module) - if module in configurations: - continue - configurations.setdefault('capsul_engine', - {}).setdefault('uses', - {})[module] = query - selected_config = None - query_env = environment - full_query = '%s == "%s" AND (%s)' % ( - Settings.environment_field, environment, ( - 'ALL' if query == 'any' else query)) - collection = '%s%s' % (Settings.collection_prefix, module) - if settings._dbs.get_collection(collection): - docs = list(settings._dbs.filter_documents(collection, - full_query)) - else: - docs = [] - - if check_invalid_mods: - # filter out invalid configs - doc_t = docs - docs = [] - for doc in doc_t: - mod = sys.modules[module] - invalid = [] - if hasattr(mod, 'check_notably_invalid_config'): - invalid = mod.check_notably_invalid_config(doc) - if len(invalid) == 0: - docs.append(doc) - - if len(docs) == 1: - selected_config = docs[0] - elif len(docs) > 1: - if query == 'any': - selected_config = docs[0] - else: - raise EnvironmentError('Cannot create configurations ' - 'for environment "%s" because settings returned ' - '%d instances for module %s' % (environment, - len(docs), module)) - else: - full_query = '%s == "%s" AND (%s)' % (Settings.environment_field, - Settings.global_environment, - ('ALL' if query == 'any' - else query)) - query_env = Settings.global_environment - if settings._dbs.get_collection(collection): - docs = list(settings._dbs.filter_documents(collection, - full_query)) - else: - docs = [] - - if check_invalid_mods: - # filter out invalid configs - doc_t = docs - docs = [] - for doc in doc_t: - mod = sys.modules[module] - invalid = [] - if hasattr(mod, 'check_notably_invalid_config'): - invalid = mod.check_notably_invalid_config(doc) - if len(invalid) == 0: - docs.append(doc) - - if len(docs) == 1: - selected_config = docs[0] - elif len(docs) > 1: - if query == 'any': - selected_config = docs[0] - else: - raise EnvironmentError('Cannot create ' - 'configurations for environment "%s" because ' - 'global settings returned %d instances for ' - 'module %s' % (query_env, len(docs), module)) - if selected_config: - # Remove values that are None - items = getattr(selected_config, '_items', None) - if items is None: - # older populse_db 1.x - items = selected_config.items - selected_config = dict(items()) - if 'config_id' in selected_config: - selected_config['config_id'] \ - = selected_config['config_id'][ - :-len(query_env)-1] - for k, v in list(items()): - if v is None: - del selected_config[k] - configurations[module] = selected_config - python_module = importlib.import_module(module) - config_dependencies = getattr(python_module, - 'config_dependencies', - None) - if config_dependencies: - d = config_dependencies(selected_config) - if d: - uses_stack.extend( - [(Settings.module_name(k), v) - for k, v in d.items()]) - - return configurations
- - - def export_config_dict(self, environment=None): - conf = {} - if environment is None: - environment = self.get_all_environments() - elif isinstance(environment, str): - environment = [environment] - with self as session: - modules = [] - for collection in (i.collection_name - for i in - session._dbs.get_collections()): - if collection.startswith(Settings.collection_prefix): - module_name = \ - collection[len(Settings.collection_prefix):] - modules.append(module_name) - - for env in environment: - env_conf = {} - for module in modules: - mod_conf = {} - for config in session.configs(module, env): - id = '%s-%s' % (config._id, env) - doc = session._dbs.get_document( - session.collection_name(module), id) - items = dict(doc._items()) - if 'config_id' in items: - items['config_id'] \ - = items['config_id'][:-len(env)-1] - mod_conf[config._id] = items - if mod_conf: - env_conf[module] = mod_conf - - env_conf['capsul_engine'] = {'uses': {m: 'ALL' - for m in modules}} - - conf[env] = env_conf - - return conf - - -
-[docs] - def import_configs(self, environment, config_dict, cont_on_error=False): - ''' - Import config values from a dictionary as given by - :meth:`select_configurations`. - - Compared to :meth:`CapsulEngine.import_configs` this method (at - :class:`Settings` level) does not load the required modules. - ''' - modules = config_dict.get('capsul_engine', {}).get('uses', {}) - - with self as session: - for module in modules: - mod_dict = config_dict.get(module, {}) - if mod_dict: - if 'config_id' in mod_dict: - # select_configurations() shape: 1 config per module - mod_dict = {mod_dict['config_id']: mod_dict} - # otherwise several config are indexed by their config_id - for config_id, config in mod_dict.items(): - conf = session.config( - module, environment, 'config_id == "%s"' % - config_id) - try: - if conf: - values = {k: v for k, v in config.items() - if k not in ('config_id', - 'config_environment')} - conf.set_values(values) - else: - session.new_config(module, environment, config) - except Exception as e: - if not cont_on_error: - raise - print(e) - print('Capsul config import fails for ' - 'environment:', environment, ', module:', - module, ', config:', config, file=sys.stderr)
- - -
-[docs] - def get_all_environments(self): - ''' - Get all environment values in the database - ''' - with self as session: - return session.get_all_environments()
-
- - - -
-[docs] -class SettingsSession: - ''' - Settings use/modifiction session, returned by "with settings as session:" - ''' - - def __init__(self, populse_session, module_notifiers=None): - ''' - SettingsSession are created with Settings.__enter__ using a `with` - statement. - ''' - self._dbs = populse_session - if module_notifiers is None: - self.module_notifiers = {} - else: - self.module_notifiers = module_notifiers - -
-[docs] - @staticmethod - def collection_name(module): - ''' - Return the name of the populse_db collection corresponding to a - settings module. The result is the full name of the module - prefixed by Settings.collection_prefix (i.e. `'settings/'`). - ''' - module = Settings.module_name(module) - collection = '%s%s' % (Settings.collection_prefix, module) - return collection
- - -
-[docs] - def ensure_module_fields(self, module, fields): - ''' - Make sure that the given module exists in settings and create the given fields if they do not exist. `fields` is a list of dictionaries with three items: - - name: the name of the key - - type: the data type of the field (in populse_db format) - - description: the documentation of the field - ''' - collection = self.collection_name(module) - if self._dbs.get_collection(collection) is None: - self._dbs.add_collection(collection, Settings.config_id_field) - self._dbs.add_field(collection, - Settings.environment_field, - 'string', index=True) - for field in fields: - name = field['name'] - if self._dbs.get_field(collection, name) is None: - self._dbs.add_field(collection, name=name, - field_type=field['type'], - description=field['description']) - return collection
- - -
-[docs] - def new_config(self, module, environment, values): - ''' - Creates a new configuration document for a module in the given - environment. Values is a dictionary used to set values for the - document. The document mut have a unique string identifier in - the `Settings.config_id_field` (i.e. `'config_id'`), if None is - given in `values` a unique random value is created (with - `uuid.uuid4()`). - ''' - document = { - Settings.environment_field: environment} - document.update(values) - id = document.get(Settings.config_id_field) - if id is None: - id = str(uuid4()) - document[Settings.config_id_field] = '%s-%s' % (id, environment) - collection = self.collection_name(module) - self._dbs.add_document(collection, document) - config = SettingsConfig( - self._dbs, collection, id, environment, - notifiers=self.module_notifiers.get(Settings.module_name(module), - [])) - config.notify() - return config
- - -
-[docs] - def remove_config(self, module, environment, config_id): - ''' - Removes a configuration (document in the database) for a given module / - environment, identified by its `Settings.config_id_field` value. - ''' - collection = self.collection_name(module) - id = '%s-%s' % (config_id, environment) - self._dbs.remove_document(collection, id)
- - -
-[docs] - def configs(self, module, environment, selection=None): - ''' - Returns a generator that iterates over all configuration - documents created for the given module and environment. - ''' - collection = self.collection_name(module) - if self._dbs.get_collection(collection) is not None: - if selection: - if 'config_id' in selection: - x = selection.find('config_id') - x = selection.find('"', x + 9) - x = selection.find('"', x + 1) - selection = '%s-%s%s'% (selection[:x], environment, - selection[x:]) - full_query = '%s == "%s" AND (%s)' % ( - Settings.environment_field, environment, selection) - docs = self._dbs.filter_documents(collection, full_query) - else: - docs = self._dbs.filter_documents( - collection, - '%s=="%s"' % (Settings.environment_field, environment)) - for d in docs: - id = d[Settings.config_id_field] - id = id[:-len(environment)-1] - yield SettingsConfig( - self._dbs, collection, id, environment, - notifiers=self.module_notifiers.get(Settings.module_name( - module), []))
- - -
-[docs] - def config(self, module, environment, selection=None, any=True): - ''' - Selects configurations (like in :meth:`configs`) and ensures at most - one one is selected - - Parameters - ---------- - module: str - module name - environment: str - environment id ('global' etc) - selection: str (optional) - to select the configuration - any: bool (optional) - When more than one config is found, if ``any`` is True (default), - return any of them (the first one). If ``any`` is False, return - None. - - Returns - ------- - config: SettingsConfig instance or None - None if no matching config is found or more than one if any is - False - ''' - configs = list(self.configs(module, environment, selection)) - if len(configs) == 0: - return None - if len(configs) == 1 or any: - return configs[0] - return None
- - -
-[docs] - def get_all_environments(self): - ''' - Get all environment values in the database - ''' - # TODO FIXME - # this function uses low-level SQL requests on the sql engine of - # populse_db 2, because I don't know how to perform requests with the - # "DISTINCT" keyword using the high level requests language. It will - # not work using populse_db 1 nor using another (non-SQL) - # implementation of the database engine. - environments = set() - for collection in (i.collection_name - for i in self._dbs.get_collections()): - if collection.startswith(Settings.collection_prefix): - #collection = collection[len(Settings.collection_prefix):] - table = self._dbs.engine.collection_table[collection] - #full_query = '%s == "%s"' % ( - #Settings.environment_field, environment) - #docs = self._dbs.filter_documents(collection, full_query) - query = 'SELECT DISTINCT %s FROM "%s"' \ - % (Settings.environment_field, table) - res = self._dbs.engine.cursor.execute(query) - environments.update([r[0] for r in res]) - return environments
-
- - -class SettingsConfig: - def __init__(self, populse_session, collection, id, environment, - notifiers=[]): - super(SettingsConfig, self).__setattr__('_dbs', populse_session) - super(SettingsConfig, self).__setattr__('_collection', collection) - super(SettingsConfig, self).__setattr__('_environment', environment) - super(SettingsConfig, self).__setattr__('_id', id) - super(SettingsConfig, self).__setattr__('_notifiers', notifiers) - - def __setattr__(self, name, value): - id = '%s-%s' % (super(SettingsConfig, self).__getattribute__('_id'), - super(SettingsConfig, - self).__getattribute__('_environment')) - if getattr(self, name) != value: - self._dbs.set_value(self._collection, id, name, value) - # notify change for listeners - self.notify(name, value) - - def __getattr__(self, name): - if name in ('_id', '_environment'): - return super(SettingsConfig, self).__getattribute__(name) - value = self._dbs.get_value(self._collection, - '%s-%s' % (self._id, self._environment), - name) - if name == 'config_id': - return value[:-len(self._environment)-1] - return value - - def set_values(self, values): - id = '%s-%s' % (self._id, self._environment) - old = self._dbs.get_document(self._collection, id, - fields=values.keys(), as_list=True) - mod_values = {k: v for o, (k, v) in zip(old, values.items()) if o != v} - if mod_values: - self._dbs.set_values(self._collection, id, mod_values) - for name, value in mod_values.items(): - self.notify(name, value) - - def notify(self, name=None, value=None): - for notifier in self._notifiers: - notifier(name, value) - -
- -
-
-
-
- -
-
- - - - \ No newline at end of file diff --git a/_modules/capsul/process/runprocess.html b/_modules/capsul/process/runprocess.html deleted file mode 100644 index 4da3c0896..000000000 --- a/_modules/capsul/process/runprocess.html +++ /dev/null @@ -1,783 +0,0 @@ - - - - - - - - CAPSUL — CAPSUL - Chain algorithm in pipelines and execute in many contexts - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - Capsul logo - - -
- - - - - -
-
-
-
- -

Source code for capsul.process.runprocess

-# -*- coding: utf-8 -*-
-#
-#  This software and supporting documentation were developed by
-#      CEA/DSV/SHFJ and IFR 49
-#      4 place du General Leclerc
-#      91401 Orsay cedex
-#      France
-#
-# This software is governed by the CeCILL license version 2 under
-# French law and abiding by the rules of distribution of free software.
-# You can  use, modify and/or redistribute the software under the
-# terms of the CeCILL license version 2 as circulated by CEA, CNRS
-# and INRIA at the following URL "http://www.cecill.info".
-#
-# As a counterpart to the access to the source code and  rights to copy,
-# modify and redistribute granted by the license, users are provided only
-# with a limited warranty  and the software's author,  the holder of the
-# economic rights,  and the successive licensors  have only  limited
-# liability.
-#
-# In this respect, the user's attention is drawn to the risks associated
-# with loading,  using,  modifying and/or developing or reproducing the
-# software by the user in light of its specific status of free software,
-# that may mean  that it is complicated to manipulate,  and  that  also
-# therefore means  that it is reserved for developers  and  experienced
-# professionals having in-depth computer knowledge. Users are therefore
-# encouraged to load and test the software's suitability as regards their
-# requirements in conditions enabling the security of their systems and/or
-# data to be ensured and,  more generally, to use and operate it in the
-# same conditions as regards security.
-#
-# The fact that you are presently reading this means that you have had
-# knowledge of the CeCILL license version 2 and that you accept its terms.
-
-"""
-capsul.process.runprocess is not a real python module, but rather an executable script with commandline arguments and options parsing. It is provided as a module just to be easily called via the python command in a portable way::
-
-    python -m capsul.process.runprocess <process name> <process arguments>
-
-Classes
--------
-:class:`ProcessParamError`
-++++++++++++++++++++++++++
-
-Functions
----------
-:func:`set_process_param_from_str`
-++++++++++++++++++++++++++++++++++
-:func:`get_process_with_params`
-+++++++++++++++++++++++++++++++
-:func:`run_process_with_distribution`
-+++++++++++++++++++++++++++++++++++++
-:func:`convert_commandline_parameter`
-+++++++++++++++++++++++++++++++++++++
-:func:`main`
-++++++++++++
-
-
-"""
-
-from capsul.api import StudyConfig
-from capsul.api import capsul_engine
-from capsul.api import Pipeline
-from capsul.attributes.completion_engine import ProcessCompletionEngine
-import os
-import os.path as osp
-import logging
-import sys
-import re
-from optparse import OptionParser, OptionGroup
-from traits.api import Undefined, List
-import tempfile
-import subprocess
-try:
-    import yaml
-except ImportError:
-    yaml = None
-    import json
-import six
-
-# Define the logger
-logger = logging.getLogger(__name__)
-
-
-
-[docs] -class ProcessParamError(Exception): - ''' Exception used in the ``runprocess`` module - ''' - pass
- - - -
-[docs] -def set_process_param_from_str(process, k, arg): - """Set a process parameter from a string representation.""" - if '.' in k: - sub_node_name, k2 = k.split('.', 1) - sub_node = process.nodes.get(sub_node_name) - if sub_node is not None: - try: - return set_process_param_from_str(sub_node, k2, arg) - except KeyError: - sub_proc = getattr(sub_node, 'process', None) - if sub_proc is not None: - return set_process_param_from_str(sub_proc, k2, arg) - if not process.trait(k): - if hasattr(process, k): - # print('set non-trait value:', process, k, repr(arg)) - setattr(process, k, arg) - return - if hasattr(process, 'pipeline_node') \ - and hasattr(process.pipeline_node, k): - setattr(process.pipeline_node, k, arg) - return - raise ProcessParamError("Unknown parameter {0} for process {1}" - .format(k, process.name)) - try: - evaluate = process.trait(k).trait_type.evaluate - except AttributeError: - evaluate = None - # print('set_process_param_from_str:', process, k, repr(arg)) - if evaluate: - arg = evaluate(arg) - setattr(process, k, arg) - process.trait(k).forbid_completion = True - if isinstance(process, Pipeline): - process.propagate_metadata(process.pipeline_node, k, - {'forbid_completion': True})
- - - -
-[docs] -def get_process_with_params(process_name, study_config, iterated_params=[], - attributes={}, *args, **kwargs): - ''' Instantiate a process, or an iteration over processes, and fill in its - parameters. - - Parameters - ---------- - process_name: string - name (mosule and class) of the process to instantiate - study_config: StudyConfig instance - iterated_params: list (optional) - parameters names which should be iterated on. If this list is not - empty, an iteration process is built. All parameters values - corresponding to the selected names should be lists with the same size. - attributes: dict (optional) - dictionary of attributes for completion system. - *args: - sequential parameters for the process. In iteration, "normal" - parameters are set with the same value for all iterations, and iterated - parameters dispatch their values to each iteration. - **kwargs: - named parameters for the process. Same as above for iterations. - - Returns - ------- - process: Process instance - ''' - process = study_config.get_process_instance(process_name) - signature = process.user_traits() - params = list(signature.keys()) - - # check for iterations - if iterated_params: - - pipeline = study_config.get_process_instance(Pipeline) - pipeline.add_iterative_process('iteration', process, iterated_params) - pipeline.autoexport_nodes_parameters(include_optional=True) - process = pipeline - - # transform iterated attributes into lists if needed - for param, value in attributes.items(): - if not isinstance(value, list) and not isinstance(value, tuple): - attributes[param] = list([value]) - - for i, arg in enumerate(args): - set_process_param_from_str(process, params[i], arg) - for k, arg in six.iteritems(kwargs): - set_process_param_from_str(process, k, arg) - - completion_engine = ProcessCompletionEngine.get_completion_engine(process) - completion_engine.get_attribute_values().import_from_dict(attributes) - completion_engine.complete_parameters() - - return process
- - - -
-[docs] -def run_process_with_distribution( - study_config, process, use_soma_workflow=False, - resource_id=None, password=None, config=None, rsa_key_pass=None, - queue=None, input_file_processing=None, output_file_processing=None, - keep_workflow=False, keep_failed_workflow=False, - write_workflow_only=None): - ''' Run the given process, either sequentially or distributed through - Soma-Workflow. - - Parameters - ---------- - study_config: StudyConfig instance - process: Process instance - the process to execute (or pipeline, or iteration...) - use_soma_workflow: bool or None (default=None) - if False, run sequentially, otherwise use Soma-Workflow. Its - configuration has to be setup and valid for non-local execution, and - additional file transfer options may be used. - resource_id: string (default=None) - soma-workflow resource ID, defaults to localhost - password: string - password to access the remote computing resource. Do not specify it if - using a ssh key. - config: dict (optional) - Soma-Workflow config: Not used for now... - rsa_key_pass: string - RSA key password, for ssh key access - queue: string - Queue to use on the computing resource. If not specified, use the - default queue. - input_file_processing: brainvisa.workflow.ProcessToSomaWorkflow processing code - Input files processing: local_path (NO_FILE_PROCESSING), - transfer (FILE_TRANSFER), translate (SHARED_RESOURCE_PATH), - or translate_shared (BV_DB_SHARED_PATH). - output_file_processing: same as for input_file_processing - Output files processing: local_path (NO_FILE_PROCESSING), - transfer (FILE_TRANSFER), or translate (SHARED_RESOURCE_PATH). - The default is local_path. - keep_workflow: bool - keep the workflow in the computing resource database after execution. - By default it is removed. - keep_failed_workflow: bool - keep the workflow in the computing resource database after execution, - if it has failed. By default it is removed. - write_workflow_only: str - if specified, this is an output filename where the workflow file will - be written. The workflow will not be actually run, because int his - situation the user probably wants to use the workflow on his own. - ''' - if write_workflow_only: - use_soma_workflow = True - - if use_soma_workflow is not None: - study_config.use_soma_workflow = use_soma_workflow - - if study_config.use_soma_workflow: - - if write_workflow_only: - # Create soma workflow pipeline - from capsul.pipeline.pipeline_workflow \ - import workflow_from_pipeline - import soma_workflow.client as swclient - - workflow = workflow_from_pipeline(process) - swclient.Helper.serialize(write_workflow_only, workflow) - - return - - swm = study_config.modules['SomaWorkflowConfig'] - resource_id = swm.get_resource_id(resource_id, set_it=True) - if password is not None or rsa_key_pass is not None: - swm.set_computing_resource_password(resource_id, password, - rsa_key_pass) - if queue is not None: - if not hasattr( - study_config.somaworkflow_computing_resources_config, - resource_id): - setattr(study_config.somaworkflow_computing_resources_config, - resource_id, {}) - getattr(study_config.somaworkflow_computing_resources_config, - resource_id).queue = queue - - res = study_config.run(process) - return res
- - - -def convert_commandline_parameter(i): - if len(i) > 0 and ( i[0] in '[({' or i in ( 'None', 'True', 'False' ) ): - try: - res=eval(i) - except Exception: - res=i - else: - res = i - return res - - -# main -
-[docs] -def main(): - ''' Run the :mod:`capsul.process.runprocess` module as a commandline - ''' - - usage = '''Usage: python -m capsul [options] processname [arg1] [arg2] ... - [argx=valuex] [argy=valuey] ... - - Example:: - - python -m capsul threshold ~/data/irm.ima /tmp/th.nii threshold1=80 - - Named arguments (in the shape argx=valuex) may address sub-processes of a - pipeline, using the dot separator:: - - PrepareSubject.t1mri=/home/myself/mymri.nii - - For a more precise description, please look at the web documentation: - https://brainvisa.info/capsul/user_guide_tree/index.html - - Configuration: - - The ``--config`` option allows to pass a Capsul configuration file (a JSON - dict). If you have a configuration in Brainvisa/Axon and want to convert - it, use the following:: - - axon-runprocess capsul://capsul.engine.write_engine_config engine.json - - Then the file ``engine.json`` will be OK. - Alternatively, using "--config axon" will do this for you internally. - - It is possible to reach sub-process parameters in a pipeline by addressing - their node in the parent pipeline: - - python -m capsul morphologist.capsul.morphologist Renorm.enabled=False - ''' - - # Set up logging on stderr. This must be called before any logging takes - # place, to avoid "No handlers could be found for logger" errors. - logging.basicConfig() - - parser = OptionParser(description='Run a single CAPSUL process', - usage=usage) - group1 = OptionGroup( - parser, 'Config', - description='Processing configuration, database options') - group1.add_option('--studyconfig', dest='studyconfig', - help='load StudyConfig configuration from the given file (JSON)') - group1.add_option( - '--config', dest='config', - help='load Capsul engine configuration from the given file (JSON) ' - '(CapsulEngine shape, not Studyconfig -- use --studyconfig ' - 'otherwise). Using "--config axon" will run the conversion process in ' - 'Axon and import the config.') - group1.add_option('-i', '--input', dest='input_directory', - help='input data directory (if not specified in ' - 'studyconfig file). If not specified neither on the ' - 'commandline nor study configfile, taken as the same as ' - 'output.') - group1.add_option('-o', '--output', dest='output_directory', - help='output data directory (if not specified in ' - 'studyconfig file). If not specified neither on the ' - 'commandline nor study configfile, taken as the same as ' - 'input.') - group1.add_option('--if', '--input-fom', dest='input_fom', - default='morphologist-bids-1.0', - help='input FOM (File Organization Model). Decides ' - 'which files and direrctories layout for the input ' - 'data. Generally "morphologist-bids-1.0" or ' - '"morphologist-auto-nonoverlap-1.0". Default: ' - '"morphologist-bids-1.0"') - group1.add_option('--of', '--output-fom', dest='output_fom', - default='morphologist-bids-1.0', - help='input FOM (File Organization Model). Decides ' - 'which files and direrctories layout for the output ' - 'data. Generally "morphologist-bids-1.0" or ' - '"morphologist-auto-nonoverlap-1.0". Default: ' - '"morphologist-bids-1.0"') - group1.add_option('--params', dest='paramsfile', default=None, - help='specify a file containing commandline parameters. ' - 'The file will contain arguments for this commandline ' - '(argv): it is an alternative to providing them here. ' - 'It can be useful to reuse parameters, or when the ' - 'parameters are too long (in a large iteration, ' - 'typically). The file syntax is one line per parameter, ' - 'with no further parsing. It will be processed after ' - 'all the current commandline arguments, not right now ' - 'as the argument appears. But if a parameter has ' - 'already been set (via commandline), it will not be ' - 'replaced: first set arguments have priority. If the ' - 'params file itself contains a --params parameter, ' - 'then another file will be read afterwards, and so on.') - parser.add_option_group(group1) - - group2 = OptionGroup(parser, 'Processing', - description='Processing options, distributed execution') - group2.add_option('--swf', '--soma_workflow', dest='soma_workflow', - default=False, - action='store_true', - help='use soma_workflow. Soma-Workflow ' - 'configuration has to be setup and valid for non-local ' - 'execution, and additional file transfer options ' - 'may be used. The default is *not* to use SWF and ' - 'process mono-processor, sequential execution.') - group2.add_option('-r', '--resource_id', dest='resource_id', default=None, - help='soma-workflow resource ID, defaults to localhost') - group2.add_option('-w', '--write-workflow-only', dest='write_workflow', - default=None, - help='if specified, this is an output ' - 'filename where the workflow file will be written. The ' - 'workflow will not be actually run, because in this ' - 'situation the user probably wants to use the workflow ' - 'on his own.') - group2.add_option('-p', '--password', dest='password', default=None, - help='password to access the remote computing resource. ' - 'Do not specify it if using a ssh key') - group2.add_option('--rsa-pass', dest='rsa_key_pass', default=None, - help='RSA key password, for ssh key access') - group2.add_option('--queue', dest='queue', default=None, - help='Queue to use on the computing resource. If not ' - 'specified, use the default queue.') - #group2.add_option('--input-processing', dest='input_file_processing', - #default=None, help='Input files processing: local_path, ' - #'transfer, translate, or translate_shared. The default is ' - #'local_path if the computing resource is the localhost, or ' - #'translate_shared otherwise.') - #group2.add_option('--output-processing', dest='output_file_processing', - #default=None, help='Output files processing: local_path, ' - #'transfer, or translate. The default is local_path.') - group2.add_option('--keep-succeeded-workflow', dest='keep_succeded_workflow', - action='store_true', default=False, - help='keep the workflow in the computing resource ' - 'database after execution. By default it is removed.') - group2.add_option('--delete-failed-workflow', dest='delete_failed_workflow', - action='store_true', default=False, - help='delete the workflow in the computing resource ' - 'database after execution, if it has failed. By default ' - 'it is kept.') - parser.add_option_group(group2) - - group3 = OptionGroup(parser, 'Iteration', - description='Iteration') - group3.add_option('-I', '--iterate', dest='iterate_on', action='append', - help='Iterate the given process, iterating over the ' - 'given parameter(s). Multiple parameters may be ' - 'iterated jointly using several -I options. In the ' - 'process parameters, values are replaced by lists, all ' - 'iterated lists should have the same size.\n' - 'Ex:\n' - 'python -m capsul -I par_a -I par_c a_process ' - 'par_a="[1, 2]" par_b="something" ' - 'par_c="[\\"one\\", \\"two\\"]"') - parser.add_option_group(group3) - - group4 = OptionGroup(parser, 'Attributes completion') - group4.add_option('-a', '--attribute', dest='attributes', action='append', - default=[], - help='set completion (including FOM) attribute. ' - 'Syntax: attribute=value, value the same syntax as ' - 'process parameters (python syntax for lists, for ' - 'instance), with proper quotes if needed for shell ' - 'escaping.\n' - 'Ex: -a acquisition="default" ' - '-a subject=\'["s1", "s2"]\'') - parser.add_option_group(group4) - - group5 = OptionGroup(parser, 'Help', - description='Help and documentation options') - group5.add_option('--process-help', dest='process_help', - action='store_true', default=False, - help='display specified process help') - parser.add_option_group(group5) - - parser.disable_interspersed_args() - (options, args) = parser.parse_args() - - while options.paramsfile: - pfile = options.paramsfile - options.paramsfile = None - with open(pfile) as f: - new_argv = [l.strip() for l in f.readlines()] - new_options, new_args = parser.parse_args(new_argv) - for k, v in new_options.__dict__.items(): - if not getattr(options, k, None): - setattr(options, k, v) - args += new_args - - engine = capsul_engine() - engine.load_modules(['fom', 'axon']) - study_config = engine.study_config - - if options.config: - config_file = options.config - tmp = None - if options.config == 'axon': - tmp = tempfile.mkstemp(prefix='capsul_conf', suffix='.json') - os.close(tmp[0]) - cmd = ['axon-runprocess', - 'capsul://capsul.engine.write_engine_config', - tmp[1]] - subprocess.check_call(cmd) - config_file = tmp[1] - with open(config_file) as f: - if yaml: - conf = yaml.load(f, Loader=yaml.SafeLoader) - else: - conf = json.load(f) - if tmp: - os.unlink(tmp[1]) - for env, c in conf.items(): - engine.import_configs(env, c) - elif options.studyconfig: - with open(options.studyconfig) as f: - if yaml: - scdict = yaml.load(f, Loader=yaml.SafeLoader) - else: - scdict = json.load(f) - study_config.set_study_configuration(scdict) - engine = study_config.engine - else: - study_config = StudyConfig( - modules=StudyConfig.default_modules + ['FomConfig']) - study_config.read_configuration() - study_config.use_fom = True - engine = study_config.engine - - if options.input_directory: - study_config.input_directory = options.input_directory - if options.output_directory: - study_config.output_directory = options.output_directory - if study_config.output_directory in (None, Undefined, '') \ - and study_config.input_directory not in (None, Undefined, ''): - study_config.output_directory = study_config.input_directory - if study_config.input_directory in (None, Undefined, '') \ - and study_config.output_directory not in (None, Undefined, ''): - study_config.input_directory = study_config.output_directory - study_config.somaworkflow_keep_succeeded_workflows \ - = options.keep_succeded_workflow - study_config.somaworkflow_keep_failed_workflows \ - = not options.delete_failed_workflow - - with engine.settings as session: - config = session.config('fom', 'global') - if options.input_fom is not None: - config.input_fom = options.input_fom - if options.output_fom is not None: - config.output_fom = options.output_fom - - kwre = re.compile(r'([a-zA-Z_](\.?[a-zA-Z0-9_])*)\s*=\s*(.*)$') - - attributes = {} - for att in options.attributes: - m = kwre.match(att) - if m is None: - raise SyntaxError('syntax error in attribute definition: %s' % att) - attributes[m.group(1)] = convert_commandline_parameter(m.group(3)) - - args = tuple((convert_commandline_parameter(i) for i in args)) - kwargs = {} - todel = [] - for arg in args: - if isinstance(arg, six.string_types): - m = kwre.match(arg) - if m is not None: - kwargs[m.group(1)] = convert_commandline_parameter(m.group(3)) - todel.append(arg) - args = [arg for arg in args if arg not in todel] - - if not args: - parser.print_usage() - sys.exit(2) - - # get the main process - process_name = args[0] - args = args[1:] - - iterated = options.iterate_on - try: - process = get_process_with_params(process_name, study_config, iterated, - attributes, - *args, **kwargs) - except ProcessParamError as e: - print("error: {0}".format(e), file=sys.stderr) - sys.exit(1) - - if options.process_help: - process.help() - - print() - - completion_engine \ - = ProcessCompletionEngine.get_completion_engine(process) - attribs = completion_engine.get_attribute_values() - aval = attribs.export_to_dict() - print('Completion attributes:') - print('----------------------') - print() - print('(note: may differ depending on study config file contents, ' - 'completion rules (FOM)...)') - print() - - skipped = set(['generated_by_parameter', 'generated_by_process']) - for name, value in six.iteritems(aval): - if name in skipped: - continue - ttype = attribs.trait(name).trait_type.__class__.__name__ - if isinstance(attribs.trait(name).trait_type, List): - ttype += '(%s)' \ - % attribs.trait(name).inner_traits[ - 0].trait_type.__class__.__name__ - print('%s:' % name, ttype) - if value not in (None, Undefined): - print(' ', value) - - print() - del aval, attribs, completion_engine, process - sys.exit(0) - - resource_id = options.resource_id - password = options.password - rsa_key_pass = options.rsa_key_pass - queue = options.queue - file_processing = [] - - study_config.use_soma_workflow = options.soma_workflow - - if options.soma_workflow: - file_processing = [None, None] - - else: - file_processing = [None, None] - - res = run_process_with_distribution( - study_config, process, options.soma_workflow, resource_id=resource_id, - password=password, rsa_key_pass=rsa_key_pass, - queue=queue, input_file_processing=file_processing[0], - output_file_processing=file_processing[1], - write_workflow_only=options.write_workflow) - - # if there was no exception, we assume the process has succeeded. - # sys.exit(0) - # no error, do a dirty exit, but avoid cleanup crashes after the process - # has succeeded... - os._exit(0)
- - - # otherwise it has raised an exception, exit "normally" - - -if __name__ == '__main__': - main() -
- -
-
-
-
- -
-
- - - - \ No newline at end of file diff --git a/_modules/capsul/qt_apps/utils/find_pipelines.html b/_modules/capsul/qt_apps/utils/find_pipelines.html deleted file mode 100644 index d3cb16aa5..000000000 --- a/_modules/capsul/qt_apps/utils/find_pipelines.html +++ /dev/null @@ -1,349 +0,0 @@ - - - - - - - - CAPSUL — CAPSUL - Chain algorithm in pipelines and execute in many contexts - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - Capsul logo - - -
- - - - - -
-
-
-
- -

Source code for capsul.qt_apps.utils.find_pipelines

-# -*- coding: utf-8 -*-
-'''
-Functions
-=========
-:func:`find_pipelines_from_description`
----------------------------------------
-:func:`find_pipeline_and_process`
----------------------------------
-:func:`lists2dict`
-------------------
-'''
-
-# System import
-from __future__ import absolute_import
-import logging
-import traceback
-import os
-import json
-import sys
-from setuptools import find_packages
-from inspect import isclass
-
-# CAPSUL import
-from capsul.api import Pipeline
-from capsul.api import Process
-
-# Define the logger
-logger = logging.getLogger(__name__)
-
-
-
-[docs] -def find_pipelines_from_description(module_name, url=None): - """ Function that list all the pipeline of a module. - - Parameters - ---------- - module_name: str (mandatory) - the name of the module we want to go through in order to find all - pipeline classes. - url: str (optional) - the url to the module documentation. - - Returns - ------- - structured_pipelines: hierachic dict - each key is a sub module of the module. Leafs contain a list with - the url to the documentation. - pipelines: list - a list a pipeline string descriptions. - """ - # Try to import the module - try: - __import__(module_name) - except ImportError: - logger.error("Can't load module {0}".format(module_name)) - return {}, [] - - # Get the module path - module = sys.modules[module_name] - module_path = module.__path__[0] - - # Build the expected pipeline description file - description_file = os.path.join( - module_path, "{0}.capsul".format(module_name)) - - # Load the description file - if os.path.isfile(description_file): - with open(description_file) as json_file: - pipelines = json.load(json_file) - - # Organize the pipeline string description by module names - structured_pipelines = {} - lists2dict([x.split(".") for x in pipelines], url, structured_pipelines) - - return structured_pipelines, pipelines - - # No description found - else: - return {}, []
- - - -
-[docs] -def find_pipeline_and_process(module_name): - """ Function that return all the Pipeline and Process classes of a module. - - All the mdoule path are scanned recuresively. Any pipeline or process will - be added to the output. - - Parameters - ---------- - module_name: str (mandatory) - the name of the module we want to go through in order to find all - pipeline classes. - - Returns - ------- - output: dict - a dictionary with a list of pipeline and process string descriptions - found in the module. - """ - - # Try to import the module - try: - __import__(module_name) - except ImportError: - logger.error("Can't load module {0}".format(module_name)) - return {}, [] - - # Get the module path - module = sys.modules[module_name] - if hasattr(module, '__path__'): - module_path = module.__path__[0] - else: - module_path = os.path.dirname(module.__file__) - - # Use setuptools to go through the module - sub_modules = find_packages(where=module_path, exclude=("doc", )) - sub_modules = [module_name + "." + x for x in sub_modules] - sub_modules.insert(0, module_name) - logger.debug("Modules found with setuptools: '{0}'.".format(sub_modules)) - - # Shift - shift = len(module_name.split(".")) - - # Create a set with all pipelines and process - pip_and_proc = [set(), set()] - for sub_module in sub_modules: - # Get the sub module path - sub_module_path = os.path.join( - module_path, *sub_module.split(".")[shift:]) - - # List all the module in submodule path - sub_sub_module_names = [ - sub_module + "." + x[:-3] for x in os.listdir(sub_module_path) - if (x.endswith(".py") and not x.startswith("_"))] - - # Try to import the sub sub module - for sub_sub_module_name in sub_sub_module_names: - try: - __import__(sub_sub_module_name) - except ImportError: - exc_info = sys.exc_info() - logger.error("".join(traceback.format_exception(*exc_info))) - logger.error("Can't load module " - "{0}".format(sub_sub_module_name)) - continue - - # Get the module - sub_sub_module = sys.modules[sub_sub_module_name] - - # From all the tools, find Pipeline instance - for tool_name in dir(sub_sub_module): - if tool_name.startswith("_"): - continue - tool = getattr(sub_sub_module, tool_name) - # Check all the authorized derived class - parent_classes = [Pipeline, Process] - for cnt, parent_class in enumerate(parent_classes): - if (isclass(tool) and issubclass(tool, parent_class)) \ - and tool not in parent_classes: - pip_and_proc[cnt].add( - sub_sub_module_name + "." + tool_name) - break - # Format output - output = { - "pipeline_descs": list(pip_and_proc[0]), - "process_descs": list(pip_and_proc[1]) - } - - return output
- - - -
-[docs] -def lists2dict(list_of_pipeline_description, url, d): - """ Convert a list of split module names to a hierarchic dictionary with - list leafs that contain the url to the module documentation. - - Parameters - ---------- - list_of_pipeline_description: list of list of str (mandatory) - the split module names to organize by modules - url: str (mandatory) - the url to the module documentation - - Returns - ------- - d: hierachic dict - each key is a sub module of the module. Leafs contain a list with - the url to the documentation. - """ - # Go through all pipeline descriptions - for l in list_of_pipeline_description: - - # Reach a leaf (a pipeline) - if len(l) == 1: - d.setdefault(l[0], []).append(url or "") - - # Continue the recursion - else: - if not l[0] in d: - d[l[0]] = lists2dict([l[1:]], url, {}) - else: - d[l[0]].update(lists2dict([l[1:]], url, d[l[0]])) - - return d
- -
- -
-
-
-
- -
-
- - - - \ No newline at end of file diff --git a/_modules/capsul/qt_gui/board_widget.html b/_modules/capsul/qt_gui/board_widget.html deleted file mode 100644 index 390d0b0e1..000000000 --- a/_modules/capsul/qt_gui/board_widget.html +++ /dev/null @@ -1,414 +0,0 @@ - - - - - - - - CAPSUL — CAPSUL - Chain algorithm in pipelines and execute in many contexts - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - Capsul logo - - -
- - - - - -
-
-
-
- -

Source code for capsul.qt_gui.board_widget

-# -*- coding: utf-8 -*-
-'''
-Classes
-=======
-:class:`BoardWidget`
---------------------
-'''
-
-# System import
-from __future__ import absolute_import
-import logging
-import six
-
-# Define the logger
-logger = logging.getLogger(__name__)
-
-# Soma import
-from soma.qt_gui.qt_backend import QtGui, QtCore
-from soma.qt_gui.controller_widget import ControllerWidget
-
-# Capsul import
-from capsul.qt_gui.widgets.viewer_widget import ViewerWidget
-from capsul.api import Pipeline
-from capsul.pipeline.pipeline_nodes import Switch, PipelineNode
-
-
-
-[docs] -class BoardWidget(QtGui.QWidget): - """ Class that create a widget to visualize the controller status. - """ - - def __init__(self, controller, parent=None, name=None): - """ Method to initilaize the ControllerWidget class. - - Parameters - ---------- - controller: derived Controller instance (mandatory) - a class derived from the Controller class we want to parametrize - with a widget. - parent: QtGui.QWidget (optional, default None) - the controller widget parent widget. - name: (optional, default None) - the name of this controller widget - """ - # Inheritance - super(BoardWidget, self).__init__(parent) - - # Class parameters - self.controller = controller - - # If possible, set the widget name - if name: - self.setObjectName(name) - - # Create the layout of the board widget - # Three item layout: output_controller_widget - board_tree - viewer_tree - self._grid_layout = QtGui.QGridLayout() - self._grid_layout.setAlignment(QtCore.Qt.AlignTop) - self._grid_layout.setSpacing(3) - self._grid_layout.setContentsMargins(5, 5, 5, 5) - self.setLayout(self._grid_layout) - - # Create all the controls - self.create_output_widget() - self.create_viewer_tree() - self.create_board_tree() - - # Fill the grid layout - self._grid_layout.addWidget(self.board_tree, 0, 0, 1, 2) - self._grid_layout.addWidget(self.output_controller_widget, 1, 0, 1, 1) - self._grid_layout.addWidget(self.viewer_tree, 1, 1, 1, 1) - - # Create the board - self._fill_trees() - - ########################################################################### - # Methods - ########################################################################### - -
-[docs] - def create_output_widget(self): - """ Method to create the output controller widget built - from the class controller output traits - """ - self.output_controller_widget = ControllerWidget( - self.controller, parent=self, name="outputs", live=True, - hide_labels=False, select_controls="outputs") - self.output_controller_widget.setEnabled(False)
- - -
-[docs] - def create_viewer_tree(self): - """ Method to create a tree with two columns (pipeline name - viewers) - that will summarize all the available quality control nodes - """ - # Create the tree widget - self.viewer_tree = QtGui.QTreeWidget(parent=self) - - # Initialize the tree widget - self.viewer_tree.setColumnCount(2) - self.viewer_tree.headerItem().setText(0, "Pipeline Name") - self.viewer_tree.headerItem().setText(1, "Viewers")
- - -
-[docs] - def create_board_tree(self): - """ Method to create a tree with five columns (processings - status - - execution time - memory - logs) that will summarize all the available - quality control nodes - """ - # Create the tree widget - self.board_tree = QtGui.QTreeWidget(parent=self) - - # Initialize the tree widget - self.board_tree.setColumnCount(5) - self.board_tree.headerItem().setText(0, "Processings") - self.board_tree.headerItem().setText(1, "Status") - self.board_tree.headerItem().setText(2, "Execution Time") - self.board_tree.headerItem().setText(3, "Memory") - self.board_tree.headerItem().setText(4, "Logs")
- - - ########################################################################### - # Private methods - ########################################################################### - - def _title_for(self, title): - """ Method to tune a title name. - - Juste replace the '_' character by a blank ' '. - - Parameters - ---------- - title: str (mandatory) - the title name we want to tune. - - Returns - ------- - output: str - the tuned name - """ - return title.replace("_", " ") - - def _fill_trees(self): - """ Method to insert processing parameters in the class trees. - """ - # Generate structures that contain all viewers and all processings - # status - metainforamtion - viewers_struct = {} - processings_struct = [] - - # Go through all the controller (pipeline) nodes. - for node_name, node in six.iteritems(self.controller.nodes): - - # If the current node is a processing node - if node_name != "" and node.node_type != "view_node": - - # First browse the current node to get processings and viewers - process_nodes = [] - view_nodes = [] - self.browse_node( - node, process_nodes, view_nodes, self.controller) - - # Set process logs - #for process_node in process_nodes: - # widget = LogWidget(process_node) - # widget.setParent(root.treeWidget()) - # child.treeWidget().setItemWidget(child, 3, widget) - - # Fill the processing structure - for processing_node in process_nodes: - processings_struct.append({ - "name": processing_node.name, - "log": processing_node.process.log_file or "No log"}) - - # Fill the viewer structure - for viewer_node, pipeline in view_nodes: - - # Create a viewer widget (a simple press button) - widget = ViewerWidget(viewer_node.name, pipeline, None) - #self._study_config) - - # Store the widget in the corresponding structure - title = self._title_for(pipeline.name) - if title not in viewers_struct: - viewers_struct[title] = [] - viewers_struct[title].append(widget) - - - # If the current node is a viewer node - elif node.node_type == "view_node": - - # Create a viewer widget (a simple press button) - widget = ViewerWidget(node_name, self.controller, None) - #self._study_config) - - # Store the widget in the corresponding structure - title = self._title_for(self.controller.name) - if title not in viewers_struct: - viewers_struct[title] = [] - viewers_struct[title].append(widget) - - - # Fill the viewer tree widget - viewer_parent = self.viewer_tree.invisibleRootItem() - for pipeline_title, viewer_widgets in six.iteritems(viewers_struct): - - # Create a new tree item - viewer_child = QtGui.QTreeWidgetItem(viewer_parent) - viewer_child.setText(0, pipeline_title) - - # Set the viewer widgets in a layout - widget_layout = QtGui.QHBoxLayout() - widget_layout.setSpacing(0) - widget_layout.setSizeConstraint(QtGui.QLayout.SetMinimumSize) - widget_layout.setContentsMargins(0, 0, 0, 0) - widget_layout.addStretch(1) - for widget in viewer_widgets: - widget = QtGui.QToolButton() - widget_layout.addWidget(widget) - - # Set the final widget tree item - widget = QtGui.QWidget(viewer_child.treeWidget()) - widget.setLayout(widget_layout) - viewer_child.treeWidget().setItemWidget(viewer_child, 1, widget) - - # Fill the pboard tree widget - board_parent = self.board_tree.invisibleRootItem() - for process_info in processings_struct: - - # Create a new tree item - board_child = QtGui.QTreeWidgetItem(board_parent) - board_child.setText(0, process_info["name"]) - board_child.setText(4, process_info["log"]) - -
-[docs] - def browse_node(self, node, process_nodes, view_nodes, parent_pipeline): - """ Find view_node and leaf nodes, ie. Process nodes - - Parameters - ---------- - node: Node - a capsul node - process_nodes: Node - node of type processing_node - view_nodes: 2-uplet - contains the node of type view_node and the pipeline where this node - is defined - """ - # Skip Switch nodes - if not isinstance(node, Switch): - - # Browse recursively pipeline nodes - if (isinstance(node.process, Pipeline) and - node.node_type != "view_node"): - - pipeline = node.process - for sub_node in pipeline.nodes.values(): - if not isinstance(sub_node, PipelineNode): - self.browse_node(sub_node, process_nodes, view_nodes, - pipeline) - # Update the results according to the node type - else: - if node.node_type == "view_node": - view_nodes.append((node, parent_pipeline)) - else: - process_nodes.append(node)
-
- - - -
- -
-
-
-
- -
-
- - - - \ No newline at end of file diff --git a/_modules/capsul/qt_gui/widgets/activation_inspector.html b/_modules/capsul/qt_gui/widgets/activation_inspector.html deleted file mode 100644 index a0ffb3bbf..000000000 --- a/_modules/capsul/qt_gui/widgets/activation_inspector.html +++ /dev/null @@ -1,544 +0,0 @@ - - - - - - - - CAPSUL — CAPSUL - Chain algorithm in pipelines and execute in many contexts - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - Capsul logo - - -
- - - - - -
-
-
-
- -

Source code for capsul.qt_gui.widgets.activation_inspector

-# -*- coding: utf-8 -*-
-'''
-A tool to debug and inspect nodes activation / deactivation in a pipeline.
-
-Classes
-=======
-:class:`ActivationInspectorApp`
--------------------------------
-:class:`ActivationInspector`
-----------------------------
-'''
-
-# System import
-from __future__ import print_function
-from __future__ import absolute_import
-import os
-import re
-import logging
-import tempfile
-import six
-
-# Define the logger
-logger = logging.getLogger(__name__)
-
-# Soma import
-from soma.qt_gui import qt_backend
-from soma.qt_gui.qt_backend import QtGui
-from soma.qt_gui.controller_widget import ScrollControllerWidget
-
-# Capsul import
-from capsul.qt_apps.utils.application import Application
-import capsul.qt_apps.resources as resources
-from capsul.api import get_process_instance
-from capsul.qt_gui.widgets import PipelineDeveloperView
-from capsul.pipeline.pipeline_nodes import PipelineNode
-
-
-
-[docs] -class ActivationInspectorApp(Application): - """ ActivationInspector Application. - While developing a pipeline, nodes are connected through links. Nodes will be automatically activated or disabled depending on their connections (a mandatory link to a disabled node will disable the current one). - You will often wonder why a node will not be activated. This tool helps to determine when and why by "playing" activation rules sequences step-by-step and displaying nodes which activate or deactivate at each step. - """ - # Load some meta information - from capsul.info import __version__ as _version - from capsul.info import NAME as _application_name - from capsul.info import ORGANISATION as _organisation_name - - def __init__(self, pipeline_path, record_file=None, *args, **kwargs): - """ Method to initialize the ActivationInspectorApp class. - - Parameters - ---------- - pipeline_path: str (mandatory) - the name of the pipeline we want to load. - record_file: str (optional) - a file where the pipeline activation steps are stored. - """ - # Inhetritance - super(ActivationInspectorApp, self).__init__(*args, **kwargs) - - # Load the pipeline - self.pipeline = get_process_instance(pipeline_path) - - # Initialize the application - self.record_file = record_file - self.window = None - self.init_window() - -
-[docs] - def init_window(self): - """ Method to initialize the main window. - """ - # First set some meta information - self.setApplicationName(self._application_name) - self.setOrganizationName(self._organisation_name) - self.setApplicationVersion(self._version) - - # Get the user interface description from capsul resources - ui_file = os.path.join( - os.path.dirname(__file__), "activation_inspector.ui") - #ui_file = os.path.join(resources.__path__[0], "activation_inspector.ui") - - # Create and show the activation/pipeline/controller windows - self.pipeline_window = PipelineDeveloperView(self.pipeline, show_sub_pipelines=True) - self.controller_window = ScrollControllerWidget(self.pipeline,live=True) - self.activation_window = ActivationInspector( - self.pipeline, ui_file, self.record_file, - developper_view=self.pipeline_window) - self.pipeline_window.show() - self.activation_window.show() - self.controller_window.show() - - return True
-
- - -
-[docs] -class ActivationInspector(QtGui.QWidget): - """ A Widget to display the pipeline activation process step by step. - """ - def __init__(self, pipeline, ui_file=None, record_file=None, - developper_view=None, parent=None): - """ Initialize the ActivationInspector class. - - Parameters - ---------- - pipeline: capsul.Pipeline (mandatory) - the pipeline we want to inspect. - ui_file: str (optional) - the path to the qt user interface description file. - If not specified, it will find its standard one. - record_file: str (optional) - a file path where the activation steps are recorded. - If not specified (None), it will create a temporary file. - developper_view: PipelineDeveloperView (optional) - if specified it is possible to click on a plug to set a filter - pattern and to update the pipeline activation accordingly. - """ - # Inheritance: create the application - QtGui.QWidget.__init__(self, parent) - - # load the user interface window - if ui_file is None: - ui_file = os.path.join( - os.path.dirname(__file__), "activation_inspector.ui") - - self.ui = qt_backend.loadUi(ui_file) - - # Define dynamic controls - self.controls = { - QtGui.QListWidget: ["events"], - QtGui.QPushButton: ["btnUpdate", "next", "previous"], - QtGui.QLineEdit: ["pattern"] - } - - if record_file is None: - record_file_s = tempfile.mkstemp() - record_file = record_file_s[1] - os.close(record_file_s[0]) - print('temporary record file:', record_file) - class AutoDeleteFile(object): - def __init__(self, record_file): - self.record_file = record_file - def __del__(self): - try: - os.unlink(self.record_file) - except OSError: - pass - self._autodelete_record_file = AutoDeleteFile(record_file) - - # Add ui class parameter with the dynamic controls and initialize - # default values - self.add_controls_to_ui() - - # Store class parameters - self.pipeline = pipeline - self.record_file = record_file - self.developper_view = developper_view - - # Set the pipeline record file if folder exists - if os.path.isdir(os.path.dirname(self.record_file)): - self.pipeline._debug_activations = self.record_file - else: - raise ValueError( - "The record file '{0}' can't be created since the " - "base directory does not exist.".format(self.record_file)) - - # Execute the pipeline activation method - self.pipeline.update_nodes_and_plugs_activation() - - # Refresh the pipeline activation displayed list - self.refresh_activation_from_record() - - # Signals for window interface - self.ui.events.currentRowChanged.connect( - self.update_pipeline_activation) - self.ui.btnUpdate.clicked.connect( - self.refresh_activation_from_record) - self.ui.next.clicked.connect(self.find_next) - self.ui.previous.clicked.connect(self.find_previous) - - # Dynamically select a filter rule by clicking on the pipeline view - # plugs - if developper_view is not None: - developper_view.plug_clicked.connect(self.set_filter_pattern) - -
-[docs] - def show(self): - """ Shows the widget and its child widgets. - """ - self.ui.show()
- - -
-[docs] - def add_controls_to_ui(self): - """ Method to find dynamic controls - """ - # Error message template - error_message = "{0} has no attribute '{1}'" - - # Got through the class dynamic controls - for control_type, control_item in six.iteritems(self.controls): - - # Get the dynamic control name - for control_name in control_item: - - # Try to set the control value to the ui class parameter - try: - value = self.ui.findChild(control_type, control_name) - if value is None: - logger.error(error_message.format( - type(self.ui), control_name)) - setattr(self.ui, control_name, value) - except Exception: - logger.error(error_message.format( - type(self.ui), control_name))
- - - ########################################################################### - # Slots - ########################################################################### - -
-[docs] - def refresh_activation_from_record(self): - """ Method to display pipeline activation steps from the recorded file. - """ - # Open the last recorded activation file - with open(self.record_file) as openrecord: - - # Get the header of the file that contains the pipeline identifier - # of the recorded activation - record_pipeline_id = openrecord.readline().strip() - if record_pipeline_id != self.pipeline.id: - raise ValueError( - "'{0}' recorded activations for pipeline '{1}' but not for " - "'{2}'".format(self.record_file, record_pipeline_id, - self.pipeline.id)) - - # Clear the list where the recorded activation is displayed - self.ui.events.clear() - - # Parse the recorded activation file - - # > Store the activation stack step by step to dynamically replay - # the activation - self.activations = [] - current_activations = {} - - # > Go through all the activation steps - parser = re.compile(r"(\d+)([+-=])([^:]*)(:([a-zA-Z_0-9]+))?") - for activation_step in openrecord.readlines(): - - # > Parse the line - iteration, activation, node, x, plug = parser.match( - activation_step.strip()).groups() - plug = plug or "" - - # > Store the current activation stack - if activation == "+": - current_activations["{0}:{1}".format(node, plug)] = True - else: - del current_activations["{0}:{1}".format(node, plug)] - self.activations.append(current_activations.copy()) - - # > Add a line to the activation display - self.ui.events.addItem("{0}{1} {2}:{3}".format( - iteration, activation, node, plug)) - - # Select the last activation step so the pipeline will be - # in his final configuration - self.ui.events.setCurrentRow(self.ui.events.count() - 1)
- - -
-[docs] - def update_pipeline_activation(self, index): - """ Method that is used to replay the activation step by step. - - When a specific activation step is selected, the pipeline will reflect - the selected activation status - """ - # Get the activation associated to the 'index' stack level - activations = self.activations[index] - - # Update the pipeline activation to meet the current selection - for node in self.pipeline.all_nodes(): - - # Restore the plugs and nodes activations - node_name = node.full_name - for plug_name, plug in six.iteritems(node.plugs): - plug.activated = activations.get( - "{0}:{1}".format(node_name, plug_name), False) - node.activated = activations.get("{0}:".format(node_name), False) - - # Refresh views relying on plugs and nodes selection - for node in self.pipeline.all_nodes(): - if isinstance(node, PipelineNode): - node.process.selection_changed = True
- - -
-[docs] - def find_next(self): - """ Forward search for a pattern in the activation list. - - Returns - ------- - is_found: int - 1 if a match has been found, 0 otherwise. - """ - # Build the search pattern - pattern = re.compile(self.ui.pattern.text()) - - # Forward search - # > Get the next (n+1) activation row - next_activation_row = self.ui.events.currentRow() + 1 - # > Search recursively until a match is found - while next_activation_row < self.ui.events.count(): - if pattern.search(self.ui.events.item(next_activation_row).text()): - self.ui.events.setCurrentRow(next_activation_row) - return 1 - next_activation_row += 1 - - return 0
- - -
-[docs] - def find_previous(self): - """ Backward search for a pattern in the activation list. - - Returns - ------- - is_found: bool - True if a match has been found, False otherwise. - """ - # Build the search pattern - pattern = re.compile(self.ui.pattern.text()) - - # Backward search - # > Get the previous (n-1) activation row - previous_activation_row = self.ui.events.currentRow() - 1 - # > Search recursively until a match is found - while previous_activation_row > 0: - if pattern.search(self.ui.events.item(previous_activation_row).text()): - self.ui.events.setCurrentRow(previous_activation_row) - return 1 - previous_activation_row -= 1 - - return 0
- - -
-[docs] - def set_filter_pattern(self, filter_pattern): - """ Method that set a filter pattern. - - Try a forward search followed by a backward one. - - Parameters - ---------- - filter_pattern: str (mandatory) - the filter pattern we want to set. - """ - # Display the filter pattern - self.ui.pattern.setText(filter_pattern) - - # Try to select an item corresponding to the filter pattern - if not self.find_next(): - self.find_previous()
-
- - - -if __name__ == "__main__": - """ Command example: - >>> python activation_inspector.py -p funtk.connectivity.conn.Conn - -r ~/tmp/conn_activation.txt - """ - # Create a tool we can control easily - import sys - from optparse import OptionParser - - # Define activation inspector options - parser = OptionParser() - parser.add_option("-p", "--pipeline", - dest="pipeline_path", - help=("the pipeline path we want to investigate: " - "module1.module2.Pipeline.")) - parser.add_option("-r", "--record", - dest="record_file", - help="the file where the activation steps are recorded.") - (options, args) = parser.parse_args() - sys.argv = [] - - # Start the application - if QtGui.QApplication.instance() is None: - app = ActivationInspectorApp(options.pipeline_path, options.record_file) - sys.exit(app.exec_()) -
- -
-
-
-
- -
-
- - - - \ No newline at end of file diff --git a/_modules/capsul/qt_gui/widgets/attributed_process_widget.html b/_modules/capsul/qt_gui/widgets/attributed_process_widget.html deleted file mode 100644 index a264bf5b3..000000000 --- a/_modules/capsul/qt_gui/widgets/attributed_process_widget.html +++ /dev/null @@ -1,614 +0,0 @@ - - - - - - - - CAPSUL — CAPSUL - Chain algorithm in pipelines and execute in many contexts - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - Capsul logo - - -
- - - - - -
-
-
-
- -

Source code for capsul.qt_gui.widgets.attributed_process_widget

-# -*- coding: utf-8 -*-
-'''
-Process or pipeline parameters view with attributes handling.
-
-Classes
-=======
-:class:`AttributedProcessWidget`
---------------------------------
-'''
-
-from __future__ import print_function
-
-from __future__ import absolute_import
-import json
-import six
-from soma.qt_gui import qt_backend
-from soma.qt_gui.qt_backend import QtGui, QtCore
-from soma.controller import Controller
-from soma.qt_gui.controller_widget \
-    import ControllerWidget, ScrollControllerWidget
-from traits.api import File, HasTraits, Any, Directory, Undefined, List
-
-
-
-[docs] -class AttributedProcessWidget(QtGui.QWidget): - """Process interface with attributes completion handling""" - def __init__(self, attributed_process, enable_attr_from_filename=False, - enable_load_buttons=False, override_control_types=None, - separate_outputs=True, user_data=None, userlevel=0, - scroll=True): - """ - Parameters - ---------- - attributed_process: Process instance - process with attributes to be displayed - enable_attr_from_filename: bool (optional) - if enabled, it will be possible to specify an input filename to - build attributes from - override_control_types: dict (optional) - if given, this is a "factory" dict assigning new controller editor - types to some traits types in the parameters controller. - separate_outputs: bool - if True, inputs and outputs (traits with output=True set) will - be separated into two boxes. - user_data: any type (optional) - optional user data that can be accessed by individual control - editors - userlevel: int - the current user level: some traits may be marked with a non-zero userlevel, and will only be visible if the ControllerWidget userlevel is more than (or equal) the trait level. - scroll: bool - if True, the widget includes scrollbars in the parameters and - attributes sections when needed, otherwise it will be a fixed size - widget. - """ - super(AttributedProcessWidget, self).__init__() - self.setLayout(QtGui.QVBoxLayout()) - self.layout().setContentsMargins(0, 0, 0, 0) - self.attributed_process = attributed_process - self._show_completion = False - self.user_data = user_data - self.separate_outputs = separate_outputs - self._userlevel = userlevel - - process = attributed_process - completion_engine = getattr(process, 'completion_engine', None) - - if completion_engine is not None: - splitter = QtGui.QSplitter(QtCore.Qt.Vertical) - self.layout().addWidget(splitter) - spl_up = QtGui.QWidget() - spl_up.setLayout(QtGui.QVBoxLayout()) - splitter.addWidget(spl_up) - spl_down = QtGui.QWidget() - spl_down.setLayout(QtGui.QVBoxLayout()) - splitter.addWidget(spl_down) - else: - spl_up = self - spl_down = self - - filename_widget = None - if enable_attr_from_filename and completion_engine is not None: - c = Controller() - c.add_trait('attributes_from_input_filename', File(optional=True)) - filename_widget = ControllerWidget(c, live=True, - user_data=user_data) - spl_up.layout().addWidget(filename_widget) - self.input_filename_controller = c - c.on_trait_change(self.on_input_filename_changed, - 'attributes_from_input_filename', dispatch='ui') - filename_widget.setSizePolicy(QtGui.QSizePolicy.Expanding, - QtGui.QSizePolicy.Fixed) - - # groupbox area to show attributes - attrib_widget = QtGui.QGroupBox('Attributes:') - attrib_widget.setFlat(True) - attrib_widget.setAlignment(QtCore.Qt.AlignLeft) - attrib_widget.setLayout(QtGui.QVBoxLayout()) - self.attrib_widget = attrib_widget - spl_up.layout().addWidget(attrib_widget) - attrib_widget.setSizePolicy(QtGui.QSizePolicy.Expanding, - QtGui.QSizePolicy.Preferred) - - hlay = QtGui.QHBoxLayout() - spl_up.layout().addLayout(hlay) - # CheckBox to completion rules or not - self.checkbox_fom = QtGui.QCheckBox('Follow completion rules') - self.checkbox_fom.setChecked(True) - self.checkbox_fom.stateChanged.connect(self.on_use_fom_change) - hlay.addWidget(self.checkbox_fom) - - # Button Show/Hide completion - self.btn_show_completion = QtGui.QCheckBox('Show completion') - self.btn_show_completion.setSizePolicy(QtGui.QSizePolicy.Fixed, - QtGui.QSizePolicy.Fixed) - hlay.addWidget(self.btn_show_completion) - self.btn_show_completion.stateChanged.connect(self.on_show_completion) - - params = QtGui.QWidget() - playout = QtGui.QVBoxLayout() - params.setLayout(playout) - if scroll: - scroll_a = QtGui.QScrollArea() - scroll_a.setWidgetResizable(True) - scroll_a.setWidget(params) - spl_up.layout().addWidget(scroll_a) - scroll_a.setSizePolicy(QtGui.QSizePolicy.Preferred, - QtGui.QSizePolicy.Preferred) - params.setSizePolicy(QtGui.QSizePolicy.Expanding, - QtGui.QSizePolicy.Preferred) - CWidgetClass = ScrollControllerWidget - else: - spl_up.layout().addWidget(params) - CWidgetClass = ControllerWidget - - # groupbox area to show completion - if separate_outputs: - param_widget = QtGui.QGroupBox('Inputs:') - else: - param_widget = QtGui.QGroupBox('Parameters:') - param_widget.setFlat(True) - param_widget.setAlignment(QtCore.Qt.AlignLeft) - playout.addWidget(param_widget) - param_widget.setLayout(QtGui.QVBoxLayout()) - param_widget.setSizePolicy(QtGui.QSizePolicy.Expanding, - QtGui.QSizePolicy.Expanding) - if separate_outputs: - out_widget = QtGui.QGroupBox('Outputs:') - out_widget.setFlat(True) - out_widget.setAlignment(QtCore.Qt.AlignLeft) - playout.addWidget(out_widget) - out_widget.setLayout(QtGui.QVBoxLayout()) - out_widget.setSizePolicy(QtGui.QSizePolicy.Expanding, - QtGui.QSizePolicy.Expanding) - - # use concise shape for lists GUI - from soma.qt_gui.controls import OffscreenListControlWidget - control_types_a = {'List': OffscreenListControlWidget} - control_types_p = {'List': OffscreenListControlWidget} - if override_control_types: - control_types_p.update(override_control_types) - #ControllerWidget._defined_controls['List'] = OffscreenListControlWidget - - # Create controller widget for process and object_attribute - sel = None - if separate_outputs: - sel = 'inputs' - self.controller_widget = ControllerWidget(process, live=True, - parent=param_widget, override_control_types=control_types_p, - user_data=user_data, userlevel=userlevel, select_controls=sel) - if separate_outputs: - self.outputs_cwidget = ControllerWidget(process, live=True, - parent=out_widget, override_control_types=control_types_p, - user_data=user_data, userlevel=userlevel, - select_controls='outputs') - - show_ce = (completion_engine is not None - and len( - completion_engine.get_attribute_values().user_traits()) - != 0) - - if completion_engine is not None: - self.controller_widget2 = CWidgetClass( - completion_engine.get_attribute_values(), - live=True, parent=attrib_widget, - override_control_types=control_types_a, user_data=user_data, - userlevel=userlevel) - completion_engine.get_attribute_values().on_trait_change( - completion_engine.attributes_changed, 'anytrait') - else: - self.controller_widget2 = CWidgetClass( - Controller(), override_control_types=control_types_a, - user_data=user_data, userlevel=userlevel) - - # Set controller of attributes and controller of process for each - # corresponding area - param_widget.layout().addWidget(self.controller_widget) - if separate_outputs: - out_widget.layout().addWidget(self.outputs_cwidget) - attrib_widget.layout().addWidget(self.controller_widget2) - - if enable_load_buttons and completion_engine is not None: - io_lay = QtGui.QHBoxLayout() - self.layout().addLayout(io_lay) - self.btn_load_json = QtGui.QPushButton('Load attributes') - io_lay.addWidget(self.btn_load_json) - self.btn_load_json.clicked.connect(self.on_btn_load_json) - self.btn_save_json = QtGui.QPushButton('Save attributes') - io_lay.addWidget(self.btn_save_json) - self.btn_save_json.clicked.connect(self.on_btn_save_json) - - if not show_ce: - if filename_widget: - filename_widget.hide() - attrib_widget.hide() - self.checkbox_fom.hide() - self.btn_show_completion.hide() - if hasattr(self, 'btn_load_json'): - self.btn_load_json.hide() - self.btn_save_json.hide() - self.show_completion(True) # hide file parts - else: - self.show_completion(False) # hide file parts - - if completion_engine is not None: - completion_engine.on_trait_change( - self._completion_progress_changed, 'completion_progress', - dispatch='ui') - - def __del__(self): - completion_engine = getattr(self.attributed_process, - 'completion_engine', None) - if completion_engine is not None: - completion_engine.get_attribute_values().on_trait_change( - completion_engine.attributes_changed, 'anytrait', remove=True) - completion_engine.on_trait_change( - self._completion_progress_changed, 'completion_progress', - remove=True) - - @property - def userlevel(self): - return getattr(self, '_userlevel', 0) - - @userlevel.setter - def userlevel(self, value): - self._userlevel = value - cw = getattr(self, 'controller_widget', None) - if cw: - cw.userlevel = value - cw = getattr(self, 'outputs_cwidget', None) - if cw: - cw.userlevel = value - cw = getattr(self, 'controller_widget2', None) - if cw: - cw.userlevel = value - # re-hide file params if needed - self.show_completion(self._show_completion) - -
-[docs] - def on_input_filename_changed(self, text): - ''' - Input file path to guess completion attributes changed: update - attributes - ''' - completion_engine = getattr(self.attributed_process, - 'completion_engine', None) - if completion_engine is not None: - print('set attributes from path:', text) - try: - completion_engine.path_attributes(six.text_type(text)) - except ValueError as e: - print(e) - import traceback - traceback.print_stack()
- - - -
-[docs] - def on_btn_load_json(self): - """Load attributes from a json file""" - completion_engine = getattr(self.attributed_process, - 'completion_engine', None) - if completion_engine is None: - print('No completion engine with attributes in this process.') - return - # ask for a file name - filename = qt_backend.getOpenFileName( - self, 'Select a .json attributes file', '', - 'JSON files (*.json)') - if filename is None: - return - print('load', filename) - attributes = json.load(open(filename)) - print("loaded:", attributes) - completion_engine.get_attribute_values().import_from_dict(attributes)
- - -
-[docs] - def on_btn_save_json(self): - """Save attributes in a json file""" - completion_engine = getattr(self.attributed_process, - 'completion_engine', None) - if completion_engine is None: - print('No attributes in this process.') - return - # ask for a file name - filename = qt_backend.getSaveFileName( - self, 'Select a .json attributes file', '', - 'JSON files (*.json)') - if filename is None: - return - json.dump(completion_engine.get_attribute_values().export_to_dict(), - open(filename, 'w'))
- - -
-[docs] - def set_use_fom(self): - ''' - Setup the FOM doing its job - ''' - ret = QtGui.QMessageBox.critical(self, "Critical", - 'Going back to completion rules will reset all path files. ' - 'Are you sure?', - QtGui.QMessageBox.Ok, QtGui.QMessageBox.Cancel) - - if ret == QtGui.QMessageBox.Ok: - #reset attributes and trait of process - process = self.attributed_process - completion_engine = getattr(self.attributed_process, - 'completion_engine', None) - if completion_engine is None: - return - completion_engine.get_attribute_values().on_trait_change( - completion_engine.attributes_changed, 'anytrait') - try: - # WARNING: is it necessary to reset all this ? - # create_completion() will do the job anyway ? - #for name, trait in six.iteritems(process.user_traits()): - #if trait.is_trait_type(File) \ - #or trait.is_trait_type(Directory): - #setattr(process,name, Undefined) - completion_engine.complete_parameters() - - if hasattr(self, 'input_filename_controller') \ - and self.input_filename_controller. \ - attributes_from_input_filename \ - != '': - completion_engine.path_attributes( - self.input_filename_controller.attributes_from_input_filename) - except Exception as e: - print(e) - import traceback - traceback.print_stack() - self.attrib_widget.show() - - else: - # reset it in a timer callback, otherwise the checkbox state is not - # correctly recorded, and next time its state change will not - # trigger the on_use_fom_change slot. - QtCore.QTimer.singleShot(0, self._reset_fom_checkbox)
- - - - def _reset_fom_checkbox(self): - self.checkbox_fom.setChecked(False) - -
-[docs] - def on_use_fom_change(self, state): - ''' - Use completion checkbox callback - ''' - if state == QtCore.Qt.Checked: - self.set_use_fom() - else: - self.attrib_widget.hide() - completion_engine = getattr(self.attributed_process, - 'completion_engine', None) - if completion_engine is not None: - completion_engine.get_attribute_values().on_trait_change( - completion_engine.attributes_changed, 'anytrait', - remove=True) - self.btn_show_completion.setChecked(True)
- - -
-[docs] - def show_completion(self, visible=None): - ''' - Show or hide completion (File, Directory, or Any parameters) - - Parameters - ---------- - visible: bool (optional) - show/hide. If None, switch the current visibility state. - ''' - - if visible is None: - visible = not self._show_completion - self._show_completion = visible - cwidgets = [self.controller_widget] - if self.separate_outputs: - cwidgets.append(self.outputs_cwidget) - for controller_widget in cwidgets: - for control_name, control_groups in \ - six.iteritems( - controller_widget._controls): - for group, control in six.iteritems(control_groups): - trait, control_class, control_instance, control_label \ - = control - if not isinstance(trait.trait_type, - (File, Any, Directory)) \ - and (not isinstance(trait.trait_type, List) - or not isinstance( - trait.inner_traits[0].trait_type, - (File, Directory, Any))): - continue - if trait.forbid_completion: - # when completion is disable, parameters are always - # visible - is_visible = True - else: - hidden = trait.hidden \ - or (trait.userlevel is not None - and trait.userlevel > self.userlevel) - is_visible = visible and not hidden - control_instance.setVisible(is_visible) - if isinstance(control_label, tuple): - for cl in control_label: - cl.setVisible(is_visible) - else: - control_label.setVisible(is_visible) - for group, group_widget in six.iteritems( - controller_widget._groups): - if [x for x in group_widget.hideable_widget.children() - if isinstance(x, QtGui.QWidget) and not x.isHidden()]: - group_widget.show() - else: - group_widget.hide()
- - -
-[docs] - def on_show_completion(self, visible): - ''' - Toggle the visibility of paths parameters - ''' - self.show_completion(visible)
- - - def _completion_progress_changed(self, obj, name, old, new): - completion_engine = getattr(self.attributed_process, - 'completion_engine', None) - if completion_engine is not None: - if not hasattr(self, 'progressdialog'): - self.progressdialog = QtGui.QWidget() - self.layout().insertWidget(1, self.progressdialog) - layout = QtGui.QHBoxLayout() - self.progressdialog.setLayout(layout) - layout.addWidget(QtGui.QLabel('Completion progress:')) - self.progressbar = QtGui.QProgressBar() - layout.addWidget(self.progressbar) - self.progressbar.setRange(0, 100) - value = int(round(100 * completion_engine.completion_progress - / completion_engine.completion_progress_total)) - self.progressbar.setValue(value) - if value != 100: - self.progressdialog.show() - QtGui.qApp.processEvents() - else: - self.progressdialog.hide()
- -
- -
-
-
-
- -
-
- - - - \ No newline at end of file diff --git a/_modules/capsul/qt_gui/widgets/links_debugger.html b/_modules/capsul/qt_gui/widgets/links_debugger.html deleted file mode 100644 index 5947a6b91..000000000 --- a/_modules/capsul/qt_gui/widgets/links_debugger.html +++ /dev/null @@ -1,387 +0,0 @@ - - - - - - - - CAPSUL — CAPSUL - Chain algorithm in pipelines and execute in many contexts - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - Capsul logo - - -
- - - - - -
-
-
-
- -

Source code for capsul.qt_gui.widgets.links_debugger

-# -*- coding: utf-8 -*-
-'''
-Tool to debug and understand process / pipeline parameters links
-
-Classes
-=======
-:class:`CapsulLinkDebuggerView`
--------------------------------
-'''
-
-from __future__ import print_function
-
-# System import
-from __future__ import absolute_import
-import os
-import tempfile
-import re
-
-# Soma import
-from soma.qt_gui import qt_backend
-from soma.qt_gui.qt_backend import QtGui, QtCore
-
-
-
-[docs] -class CapsulLinkDebuggerView(QtGui.QWidget): - """ A Widget to display the links propagation when values are set in a - pipeline - """ - CAUSE = 1 - PLUG = 2 - PROPAGATE = 3 - VALUE = 4 - - def __init__(self, pipeline, ui_file=None, record_file=None, parent=None): - super(CapsulLinkDebuggerView, self).__init__(parent) - - # load the user interface window - if ui_file is None: - ui_file = os.path.join( - os.path.dirname(__file__), "links_debugger.ui") - - self.ui = qt_backend.loadUi(ui_file) - self.ui.help.hide() - self.ui.help.setParent(None) - self.help_geom = None - table_header = self.ui.links_table.horizontalHeader() - table_header.setResizeMode(QtGui.QHeaderView.ResizeToContents) - table_header_v = self.ui.links_table.verticalHeader() - table_header_v.setResizeMode(QtGui.QHeaderView.ResizeToContents) - - if record_file is None: - record_file_s = tempfile.mkstemp() - record_file = record_file_s[1] - os.close(record_file_s[0]) - print('temporary record file:', record_file) - class AutoDeleteFile(object): - def __init__(self, record_file): - self.record_file = record_file - def __del__(self): - try: - os.unlink(self.record_file) - except OSError: - pass - self._autodelete_record_file = AutoDeleteFile(record_file) - - self.record_file = record_file - self.pipeline = None - self.set_pipeline(pipeline) - self.update_links_view() - self.ui.links_table.cellClicked.connect(self.activateCell) - self.ui.actionPrevious.activated.connect(self.go_previous_line) - self.ui.actionNext.activated.connect(self.go_next_line) - self.ui.actionFollow.activated.connect(self.go_follow_link) - self.ui.actionRefresh.activated.connect(self.update_links_view) - self.ui.actionClear.activated.connect(self.clear_view) - self.ui.actionHelp.activated.connect(self.help) - - - def __del__(self): - self.release_pipeline() - -
-[docs] - def show(self): - """ Shows the widget and its child widgets. - """ - self.ui.show()
- - - def set_pipeline(self, pipeline): - if self.pipeline is not None: - self.release_pipeline() - self.pipeline = pipeline - pipeline.uninstall_links_debug_handler() - record_stream = pipeline.install_links_debug_handler( - log_file=open(self.record_file, 'w'), handler=None, prefix='') - self.record_stream = record_stream - - def release_pipeline(self): - if self.pipeline is not None: - self.pipeline.uninstall_links_debug_handler() - self.pipeline = None - - def update_links_view(self): - self.ui.links_table.clearContents() - self.ui.links_table.setRowCount(0) # IMPORTANT otherwise perf drops - table_header = self.ui.links_table.horizontalHeader() - table_header.setResizeMode(QtGui.QHeaderView.Interactive) - l = 0 - self.record_stream.flush() - f = open(self.record_file) - lines = f.readlines() - self.ui.links_table.setRowCount(len(lines)) - linkre = re.compile('^value link: from: ([^ ,]+) *to: ([^ ]+) *, value: ([^ ]+).*$') - links_orgs = {} - for line in lines: - match = linkre.match(line) - if match: - link_source = match.group(1) - link_dest = match.group(2) - plug_value = match.group(3) - self.ui.links_table.setItem( - l, 0, QtGui.QTableWidgetItem('%04d' % l)) - self.ui.links_table.setItem( - l, self.PLUG, QtGui.QTableWidgetItem(link_source)) - self.ui.links_table.setItem( - l, self.PROPAGATE, QtGui.QTableWidgetItem(link_dest)) - self.ui.links_table.setItem( - l, self.VALUE, QtGui.QTableWidgetItem(plug_value)) - links_orgs.setdefault(link_dest, []).append(l) - if link_source in links_orgs: - org = links_orgs[link_source][0] - self.ui.links_table.setItem( - l, self.CAUSE, - QtGui.QTableWidgetItem( - self.ui.links_table.item(org, 2))) - l += 1 - self.links_orgs = links_orgs - table_header.setResizeMode(QtGui.QHeaderView.ResizeToContents) - #table_header.setResizeMode(1, QtGui.QHeaderView.ResizeToContents) - #table_header.setResizeMode(2, QtGui.QHeaderView.ResizeToContents) - #table_header.setResizeMode(3, QtGui.QHeaderView.ResizeToContents) - #table_header.setResizeMode(4, QtGui.QHeaderView.ResizeToContents) - #table_header.setResizeMode(QtGui.QHeaderView.Interactive) - QtGui.qApp.processEvents() - #table_header.resizeSection(0, table_header.sectionSizeHint(0)) - #table_header.resizeSection(1, table_header.sectionSizeHint(1)) - #table_header.resizeSection(2, table_header.sectionSizeHint(2)) - #table_header.resizeSection(3, table_header.sectionSizeHint(3)) - #table_header.resizeSection(4, table_header.sectionSizeHint(4)) - table_header.setResizeMode(QtGui.QHeaderView.Interactive) - - def clear_view(self): - self.ui.links_table.clearContents() - self.ui.links_table.setRowCount(0) - self.record_stream.seek(0) - self.record_stream.truncate(0) - self.record_stream.flush() - - def activateCell(self, row, column): - if self.ui.links_table.item(row, column) is None: - return - if column == self.CAUSE: - self.go_previous(row) - elif column == self.PLUG: - self.highlight_plug(row) - elif column == self.PROPAGATE: - self.go_next(row) - elif column == self.VALUE: - self.highlight_value(row) - - def go_previous(self, row): - self.ui.links_table.clearSelection() - plug = self.ui.links_table.item(row, self.PLUG) - plug.setSelected(True) - self.ui.links_table.item(row, self.CAUSE).setSelected(True) - items = self.ui.links_table.findItems( - plug.text(), QtCore.Qt.MatchExactly) - for item in items: - if item.column() == self.PROPAGATE: - item.setSelected(True) - - def go_next(self, row): - self.ui.links_table.clearSelection() - next_item = self.ui.links_table.item(row, self.PROPAGATE) - if next_item: - next_item.setSelected(True) - items = self.ui.links_table.findItems( - next_item.text(), QtCore.Qt.MatchExactly) - for item in items: - if item.column() == self.PLUG and item.row() >= row: - item.setSelected(True) - - def highlight_plug(self, row): - self.ui.links_table.clearSelection() - plug = self.ui.links_table.item(row, self.PLUG) - if plug: - plug.setSelected(True) - items = self.ui.links_table.findItems( - plug.text(), QtCore.Qt.MatchExactly) - for item in items: - if item.column() in (self.CAUSE, self.PROPAGATE): - item.setSelected(True) - - def highlight_value(self, row): - self.ui.links_table.clearSelection() - value_item = self.ui.links_table.item(row, self.VALUE) - if value_item: - value_item.setSelected(True) - items = self.ui.links_table.findItems( - value_item.text(), QtCore.Qt.MatchExactly) - for item in items: - if item.column() == self.VALUE: - item.setSelected(True) - - def go_next_line(self): - row = self.ui.links_table.currentRow() + 1 - self.ui.links_table.setCurrentCell(row, self.PLUG) - self.highlight_plug(row) - - def go_previous_line(self): - row = self.ui.links_table.currentRow() - 1 - if row >= 0: - self.ui.links_table.setCurrentCell(row, self.PLUG) - self.highlight_plug(row) - - def go_follow_link(self): - row = self.ui.links_table.currentRow() - plug = self.ui.links_table.item(row, self.PROPAGATE) - if plug: - items = self.ui.links_table.findItems( - plug.text(), QtCore.Qt.MatchExactly) - for item in items: - if item.column() == self.PLUG and item.row() > row: - self.ui.links_table.setCurrentCell(item.row(), self.PLUG) - break - self.go_next(row) - - def help(self): - if self.help_geom is None or self.ui.help.isVisible(): - self.help_geom = self.ui.help.geometry() - set_geom = False - else: - set_geom = True - self.ui.help.setVisible(not self.ui.help.isVisible()) - if set_geom: - self.ui.help.setGeometry(self.help_geom)
- -
- -
-
-
-
- -
-
- - - - \ No newline at end of file diff --git a/_modules/capsul/qt_gui/widgets/pipeline_developer_view.html b/_modules/capsul/qt_gui/widgets/pipeline_developer_view.html deleted file mode 100644 index f211f7bfe..000000000 --- a/_modules/capsul/qt_gui/widgets/pipeline_developer_view.html +++ /dev/null @@ -1,5502 +0,0 @@ - - - - - - - - CAPSUL — CAPSUL - Chain algorithm in pipelines and execute in many contexts - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - Capsul logo - - -
- - - - - -
-
-
-
- -

Source code for capsul.qt_gui.widgets.pipeline_developer_view

-# -*- coding: utf-8 -*-
-'''
-A Pipeline structure viewer widget, which displays pipeline nodes as boxes and links as lines, and provides pipeline editor features.
-
-The only main class you should look at is the :class:`PipelineDeveloperView` widget, the remaining is internal infrastructure::
-
-    pv = PipelineDeveloperView(pipeline, allow_open_controller=True,
-                                enable_edition=True,show_sub_pipelines=True)
-    pv.show()
-
-Classes
-=======
-:class:`ColorType`
-------------------
-:class:`Plug`
--------------
-:class:`EmbeddedSubPipelineItem`
---------------------------------
-:class:`boxItem`
-----------------
-:class:`NodeGWidget`
---------------------
-:class:`HandleItem`
--------------------
-:class:`Link`
--------------
-:class:`PipelineScene`
-----------------------
-:class:`PipelineDeveloperView`
--------------------------------
-
-'''
-
-# System import
-import os
-from pprint import pprint
-import weakref
-import tempfile
-import soma.subprocess
-import shutil
-import importlib
-import sys
-import types
-import inspect
-import six
-import json
-import io
-import traceback
-import html
-
-# Capsul import
-from soma.qt_gui.qt_backend import QtCore, QtGui, Qt
-from soma.qt_gui.qt_backend.Qt import QMessageBox
-from soma.sorted_dictionary import SortedDictionary
-from capsul.api import Switch, PipelineNode, OptionalOutputSwitch
-from capsul.pipeline import pipeline_tools
-from capsul.api import Pipeline
-from capsul.api import Process
-from capsul.api import get_process_instance
-from capsul.pipeline.pipeline_nodes import Node, ProcessNode
-from soma.qt_gui.qt_backend.Qt import QGraphicsView
-from capsul.qt_gui.widgets.pipeline_file_warning_widget \
-    import PipelineFileWarningWidget
-import capsul.pipeline.xml as capsulxml
-from capsul.study_config import process_instance
-from capsul.pipeline.process_iteration import ProcessIteration
-from soma.controller import Controller
-from soma.utils.functiontools import SomaPartial
-from six.moves import range
-from six.moves import zip
-from soma.utils.weak_proxy import proxy_method
-
-from traits import api as traits
-
-from soma.qt_gui import qt_backend
-
-qt_backend.init_traitsui_handler()
-
-from soma.qt_gui.controller_widget import ScrollControllerWidget
-from capsul.qt_gui.widgets.attributed_process_widget \
-    import AttributedProcessWidget
-
-
-# -----------------------------------------------------------------------------
-# Globals and constants
-# -----------------------------------------------------------------------------
-
-GRAY_1 = QtGui.QColor.fromRgbF(0.7, 0.7, 0.8, 0.1)
-GRAY_2 = QtGui.QColor.fromRgbF(0.4, 0.4, 0.4, 1)
-LIGHT_GRAY_1 = QtGui.QColor.fromRgbF(0.2, 0.2, 0.2, 1)
-LIGHT_GRAY_2 = QtGui.QColor.fromRgbF(0.2, 0.2, 0.2, 1)
-
-# Colors for links and plugs
-
-ORANGE_1 = QtGui.QColor.fromRgb(220, 80, 20)
-ORANGE_2 = QtGui.QColor.fromRgb(220, 120, 20)
-BLUE_1 = QtGui.QColor.fromRgb(50, 150, 250)
-BLUE_2 = QtGui.QColor.fromRgb(50, 50, 250)
-PURPLE_2 = QtGui.QColor.fromRgb(200, 0, 200)
-RED_2 = QtGui.QColor.fromRgb(200, 0, 0)
-GREEN_2 = QtGui.QColor.fromRgb(0, 100, 0)
-BLACK_2 = QtGui.QColor.fromRgb(10, 10, 10)
-WHITE_2 = QtGui.QColor.fromRgb(255, 255, 255)
-
-ANTHRACITE_1 = QtGui.QColor.fromRgbF(0.05, 0.05, 0.05)
-LIGHT_ANTHRACITE_1 = QtGui.QColor.fromRgbF(0.25, 0.25, 0.25)
-
-
-# -----------------------------------------------------------------------------
-# Classes and functions
-# -----------------------------------------------------------------------------
-
-class ColorType(object):
-
-    def __init__(self):
-        pass
-
-    def colorLink(self, x):
-        if not isinstance(x, str):
-            # x is a trait
-            trait_type_str = x.trait_type.__class__.__name__
-            if x.output and x.input_filename is False:
-                trait_type_str = 'File_out'
-            x = trait_type_str
-        return {
-            'Str': PURPLE_2,
-            'Float': ORANGE_1,
-            'Int': BLUE_2,
-            'List': RED_2,
-            'File': ORANGE_2,
-            'File_out': GREEN_2,
-        }[x]
-
-
-
-[docs] -class Plug(QtGui.QGraphicsPolygonItem): - - def __init__(self, color, name, height, width, activated=True, - optional=False, parent=None): - super(Plug, self).__init__(parent) - self.name = name - # self.color = self._color(activated, optional) - self.color = color - if optional: - brush = QtGui.QBrush(QtCore.Qt.SolidPattern) - brush.setColor(self.color) - polygon = QtGui.QPolygonF([QtCore.QPointF(0, 0), - QtCore.QPointF(width / 1.5, 0), - QtCore.QPointF(width / 1.5, - (height - 5)), - QtCore.QPointF(0, (height - 5)) - ]) - # self.setPen(QtGui.QPen(QtCore.Qt.NoPen)) - else: - brush = QtGui.QBrush(QtCore.Qt.SolidPattern) - brush.setColor(self.color) - polygon = QtGui.QPolygonF([QtCore.QPointF(0, 0), - QtCore.QPointF( - width, (height - 5) / 2.0), - QtCore.QPointF(0, height - 5) - ]) - self.setPolygon(polygon) - self.setBrush(brush) - self.setZValue(3) - self.setAcceptedMouseButtons(QtCore.Qt.LeftButton) - - # def _color(self, activated, optional): - # if optional: - # if activated: - # color = QtCore.Qt.darkGreen - # else: - # color = QtGui.QColor('#BFDB91') - # else: - # if activated: - # color = QtCore.Qt.black - # else: - # color = QtCore.Qt.gray - # return color - - # def update_plug(self, activated, optional): - # color = self._color(activated, optional) - # brush = QtGui.QBrush(QtCore.Qt.SolidPattern) - # brush.setColor(color) - # self.setBrush(brush) - - def update_plug(self, color): - brush = QtGui.QBrush(QtCore.Qt.SolidPattern) - brush.setColor(color) - self.setBrush(brush) - - def get_plug_point(self): - point = QtCore.QPointF( - self.boundingRect().size().width() / 2.0, - self.boundingRect().size().height() / 2.0) - return self.mapToParent(point) - -
-[docs] - def mousePressEvent(self, event): - super(Plug, self).mousePressEvent(event) - if event.button() == QtCore.Qt.LeftButton: - self.scene().plug_clicked.emit(self.name) - event.accept() - elif event.button() == QtCore.Qt.RightButton: - # print('plug: right click') - self.scene().plug_right_clicked.emit(self.name) - event.accept()
-
- - - -
-[docs] -class EmbeddedSubPipelineItem(QtGui.QGraphicsProxyWidget): - ''' - QGraphicsItem containing a sub-pipeline view - ''' - - def __init__(self, sub_pipeline_wid): - super(EmbeddedSubPipelineItem, self).__init__() - old_height = sub_pipeline_wid.sizeHint().height() - sizegrip = QtGui.QSizeGrip(None) - new_height = old_height \ - + sub_pipeline_wid.horizontalScrollBar().height() - sub_pipeline_wid.setCornerWidget(sizegrip) - sub_pipeline_wid.setHorizontalScrollBarPolicy( - QtCore.Qt.ScrollBarAlwaysOn) - sub_pipeline_wid.resize(sub_pipeline_wid.sizeHint().width(), new_height) - self.setWidget(sub_pipeline_wid)
- - - -
-[docs] -class boxItem(QtGui.QGraphicsRectItem): - def __init__(self, parent=None): - super(boxItem, self).__init__(parent) - # self.setFlags(self.ItemIsFocusable) - self.penBox = 0; - self.name = "" - -
-[docs] - def focusInEvent(self, event): - self.setPen(QtGui.QPen(QtGui.QColor(150, 150, 250), 3, QtCore.Qt.DashDotLine)) - return QtGui.QGraphicsRectItem.focusInEvent(self, event)
- - -
-[docs] - def focusOutEvent(self, event): - self.setPen(self.penBox) - return QtGui.QGraphicsRectItem.focusOutEvent(self, event)
- - -
-[docs] - def keyPressEvent(self, event): - if event.key() == QtCore.Qt.Key_Delete: - self.scene()._node_keydelete_clicked(self) - event.accept() - else: - super(boxItem, self).keyPressEvent(event)
-
- - - -
-[docs] -class NodeGWidget(QtGui.QGraphicsItem): - def __init__(self, name, parameters, pipeline, - parent=None, process=None, sub_pipeline=None, - colored_parameters=True, - logical_view=False, labels=[], - show_opt_inputs=True, show_opt_outputs=True, - userlevel=0): - super(NodeGWidget, self).__init__(parent) - - self.infoActived = QtGui.QGraphicsTextItem('', self) - self.colType = ColorType() - self._userlevel = userlevel - - self.setFlags(self.ItemIsSelectable) - self.setCursor(Qt.QCursor(QtCore.Qt.PointingHandCursor)) - - self.style = 'default' - self.name = name - #print('GNode userlevel:', self.userlevel) - #print([(pname, param) for pname, param in six.iteritems(parameters) - #if not getattr(param, 'hidden', False) - #and (getattr(param, 'userlevel', None) is None - #or param.userlevel <= self.userlevel)] - if isinstance(process, ProcessNode): - controller = process.process - else: - controller = process - self.parameters = SortedDictionary() - for pname, param in six.iteritems(parameters): - show = True - if controller: - trait = controller.trait(pname) - if getattr(trait, 'hidden', False): - show = False - elif getattr(trait, 'userlevel', None) is not None: - if trait.userlevel > self.userlevel: - show = False - if show: - self.parameters[pname] = param - - self.setFlag(QtGui.QGraphicsItem.ItemIsMovable) - self.in_plugs = SortedDictionary() - self.in_params = {} - self.out_plugs = SortedDictionary() - self.out_params = {} - self.process = process - self.sub_pipeline = sub_pipeline - self.embedded_subpipeline = None - self.colored_parameters = colored_parameters - self.logical_view = logical_view - self.pipeline = pipeline - - # Added to choose to visualize optional parameters - self.show_opt_inputs = show_opt_inputs - self.show_opt_outputs = show_opt_outputs - - self.labels = [] - self.scene_labels = labels - self.label_items = [] - my_labels = [] - steps = getattr(pipeline, 'pipeline_steps', None) - if steps: - for step_name, step in six.iteritems(steps.user_traits()): - step_nodes = step.nodes - if name in step_nodes: - my_labels.append('step: %s' % step_name) - selects = pipeline.get_processes_selections() - for sel_plug in selects: - groups = pipeline.get_processes_selection_groups(sel_plug) - for group, nodes in six.iteritems(groups): - if name in nodes: - my_labels.append('select: %s' % sel_plug) - - for label in my_labels: - self._get_label(label) - - self._set_brush() - self.setAcceptedMouseButtons( - QtCore.Qt.LeftButton | QtCore.Qt.RightButton | QtCore.Qt.MiddleButton) - - self._build() - - self._update_param_timer = Qt.QTimer() - self._update_param_timer.setSingleShot(True) - self._update_param_timer.timeout.connect( - proxy_method(self, 'update_parameters_now')) - - if colored_parameters: - process.on_trait_change(self._repaint_parameter, dispatch='ui') - process.on_trait_change(self.update_parameters, 'user_traits_changed', - dispatch='ui') - - def __del__(self): - # print('NodeGWidget.__del__') - self._release() - # super(NodeGWidget, self).__del__() - - @property - def userlevel(self): - return self._userlevel - - @userlevel.setter - def userlevel(self, value): - self._userlevel = value - self.update_parameters() - - def _release(self): - # release internal connections / callbacks / references in order to - # allow deletion of self - self.process.on_trait_change(self.update_parameters, - 'user_traits_changed', remove=True) - if self.colored_parameters: - try: - self.process.on_trait_change(self._repaint_parameter, remove=True) - except Exception: - pass - self.colored_parameters = None - self.sizer = None - - def get_title(self): - if self.sub_pipeline is None: - return self.name - else: - return "[{0}]".format(self.name) - - def update_parameters(self): - self._update_param_timer.start(20) - - def update_parameters_now(self): - if isinstance(self.process, ProcessNode): - controller = self.process.process - else: - controller = self.process - self.parameters = SortedDictionary() - for pname, param in six.iteritems(self.process.user_traits()): - show = True - if self.name == 'inputs' and param.output: - continue - elif self.name == 'outputs' and not param.output: - continue - if controller: - trait = controller.trait(pname) - if getattr(trait, 'hidden', False): - show = False - elif getattr(trait, 'userlevel', None) is not None: - if trait.userlevel > self.userlevel: - show = False - if show: - self.parameters[pname] = param - - self.update_node() - -
-[docs] - def update_labels(self, labels): - ''' Update colored labels - ''' - self.labels = [] - for item in self.label_items: - item.deleteLater() # FIXME there should be another way ! - self.label_items = [] - for label in labels: - self._get_label(label) - self._create_label_marks()
- - - def _get_label(self, label, register=True): - class Label(object): - def __init__(self, label, color): - self.text = label - self.color = color - - for l in self.scene_labels: - if label == l.text: - if register and l not in self.labels: - self.labels.append(l) - return l - color = self.new_color(len(self.scene_labels)) - label_item = Label(label, color) - if register: - self.labels.append(label_item) - self.scene_labels.append(label_item) - return label_item - - def new_color(self, num): - colors = [[1, 0.3, 0.3], - [0.3, 1, 0.3], - [0.3, 0.3, 1], - [1, 1, 0], - [0, 1, 1], - [1, 0, 1], - [1, 1, 1], - [1, 0.7, 0], - [1, 0, 0.7], - [1, 0.7, 0.7], - [0.7, 1, 0], - [0., 1., 0.7], - [0.7, 1, 0.7], - [0.7, 0, 1], - [0., 0.7, 1], - [0.7, 0.7, 1], - [1, 1, 0.5], - [0.5, 1, 1], - [1, 0.5, 1]] - c = colors[num % len(colors)] - code = (int(c[0] * 255), int(c[1] * 255), int(c[2] * 255)) - return code - - def _repaint_parameter(self, param_name, new_value): - if self.logical_view or param_name not in self.parameters: - return - param_text = self._parameter_text(param_name) - param_item = self.in_params.get(param_name) - if param_item is None: - param_item = self.out_params[param_name] - if isinstance(param_item, QtGui.QGraphicsProxyWidget): - # colored parameters are widgets - param_item.widget().findChild( - QtGui.QLabel, 'label').setText(param_text) - else: - param_item.setHtml(param_text) - - def _build(self): - margin = 0 - self.title = QtGui.QGraphicsTextItem(self.get_title(), self) - # font = self.title.font() - font = QtGui.QFont("Times", 11, QtGui.QFont.Bold) - # font.setWeight(QtGui.QFont.Bold) - self.title.setFont(font) - self.title.setPos(margin, margin) - self.title.setZValue(2) - self.title.setDefaultTextColor(QtCore.Qt.white) - self.title.setParentItem(self) - - if self.logical_view: - self._build_logical_view_plugs() - else: - self._build_regular_view_plugs() - self._create_label_marks() - - ctr = self.contentsRect() - self.wmin = ctr.width() - self.hmin = ctr.height() - - font1 = QtGui.QFont("Times", 12, QtGui.QFont.Normal) - font1.setItalic(True) - self.infoActived.setFont(font1) - self.infoActived.setZValue(2) - self.infoActived.setDefaultTextColor(QtCore.Qt.red) - self.infoActived.setParentItem(self) - - self.box = boxItem(self) - self.box.setFlags(self.box.ItemIsFocusable) - self.box.setBrush(self.bg_brush) - self.box.setPen(QtGui.QPen(QtCore.Qt.NoPen)) - self.box.setZValue(-1) - self.box.penBox = self.box.pen() - self.box.name = self.name - self.box.setParentItem(self) - - self.sizer = HandleItem(self) - self.sizer.wmin = self.wmin - self.sizer.hmin = self.hmin - self.sizer.setPos(ctr.width(), ctr.height()) - self.sizer.posChangeCallbacks.append(proxy_method(self, 'changeSize')) - self.sizer.setFlag(self.sizer.ItemIsSelectable, True) - - self.box_title = QtGui.QGraphicsRectItem(self) - self.box_title.setBrush(self.title_brush) - self.box_title.setPen(QtGui.QPen(QtCore.Qt.NoPen)) - self.box_title.setZValue(1) - self.box_title.setParentItem(self) - - self.changeSize(ctr.width(), ctr.height()) - - def changeSize(self, w, h): - limit = False - factor_h = 35 - - if h < self.hmin: - h = self.hmin - limit = True - - if w < self.wmin: - w = self.wmin - limit = True - - winMax, woutMax = 0, 0 - - self.box.setRect(0.0, 0.0, w, h) - - self.box_title.setRect(0.0, 0.0, w, 30) - self.title.setPos(w / 2 - self.title.boundingRect().size().width() / 2, - 0) - self.infoActived.setPos( - w / 2 - self.infoActived.boundingRect().size().width() / 2, h + 2) - - # rect = self.title.mapRectToParent(self.title.boundingRect()) - # rect.setWidth(w) - # self.box_title.setRect(rect) - - y1 = h / (len(self.in_plugs) + 1) - dy = y1 - for inp in self.in_plugs: - self.in_plugs[inp].setPos(0, y1) - self.in_params[inp].setPos(self.in_plugs[inp].boundingRect().size().width(), y1) - if winMax < self.in_params[inp].boundingRect().size().width(): - winMax = self.in_params[inp].boundingRect().size().width() - y1 += dy - - y2 = h / (len(self.out_plugs) + 1) - dy = y2 - for outp in self.out_plugs: - self.out_plugs[outp].setPos(w, y2) - self.out_params[outp].setPos(w - self.out_params[outp].boundingRect().size().width() - 5, y2) - if woutMax < self.out_params[outp].boundingRect().size().width(): - woutMax = self.out_params[outp].boundingRect().size().width() - y2 += dy - - if w < winMax + woutMax + 15: - w = winMax + woutMax + 15 - self.updateSize(w, h) - #self.sizer.setPos(w, h) - self.wmin = w - - if limit: - self.sizer.setPos(w, h) - - self.update_labels([l.text for l in self.labels]) - - # if self.hmin < factor_h * len(self.in_plugs): - # self.hmin = factor_h * len(self.in_plugs) - # self.updateSize(w, self.hmin) - # if self.hmin < factor_h * len(self.out_plugs): - # self.hmin = factor_h * len(self.out_plugs) - # self.updateSize(w, self.hmin) - - def updateSize(self, w, h): - # print("wmin =",self.wmin,", w=",w) - if w<self.wmin: - w=self.wmin - margin = 20 - factor_h = 35.0 - h = factor_h * len(self.in_plugs)+margin - self.hmin=h - - if h < factor_h * len(self.out_plugs): - h = factor_h * len(self.out_plugs) + margin - self.hmin = h - self.sizer.hmin = h - self.changeSize(w, h + margin) - self.sizer.setPos(w, h + margin) - - - - def _colored_text_item(self, label, text=None, margin=2): - labelc = self._get_label(label, False) - color = labelc.color - if text is None: - text = label - # I can't make rounded borders with appropriate padding - # without using 2 QLabels. This is probably overkill. We could - # replace this code of we find a simpler way. - label_w = QtGui.QLabel('') - label_w.setStyleSheet("background: rgba(255, 255, 255, 0);") - lay = QtGui.QVBoxLayout() - lay.setContentsMargins(margin, margin, margin, margin) - label_w.setLayout(lay) - label2 = QtGui.QLabel(text) - label2.setObjectName('label') - label2.setStyleSheet( - "background: rgba({0}, {1}, {2}, 255); " - "border-radius: 7px; border: 0px solid; " - "padding: 1px;".format(*color)) - lay.addWidget(label2) - label_item = QtGui.QGraphicsProxyWidget(self) - label_item.setWidget(label_w) - return label_item - - def _build_regular_view_plugs(self): - margin = 5 - plug_width = 12 - pos = margin + margin + self.title.boundingRect().size().height() - pos0 = pos - if self.name == 'inputs': - selections = self.pipeline.get_processes_selections() - else: - selections = [] - - for in_param, pipeline_plug in six.iteritems(self.parameters): - output = (not pipeline_plug.output if self.name in ( - 'inputs', 'outputs') else pipeline_plug.output) - if output or (not self.show_opt_inputs and pipeline_plug.optional): - continue - param_text = self._parameter_text(in_param) - param_name = QtGui.QGraphicsTextItem(self) - param_name.setHtml(param_text) - - plug_name = '%s:%s' % (self.name, in_param) - - try: - # color = self.colorLink(trait_type_str) - color = self.colType.colorLink(self.process.trait(in_param)) - except Exception: - color = ORANGE_2 - - plug = Plug(color, plug_name, - param_name.boundingRect().size().height(), - plug_width, activated=pipeline_plug.activated, - optional=pipeline_plug.optional, parent=self) - param_name.setZValue(2) - plug.setPos(margin, pos) - param_name.setPos(plug.boundingRect().size().width() + margin, pos) - param_name.setParentItem(self) - plug.setParentItem(self) - self.in_plugs[in_param] = plug - self.in_params[in_param] = param_name - pos = pos + param_name.boundingRect().size().height() - - pos = pos0 - for out_param, pipeline_plug in six.iteritems(self.parameters): - output = (not pipeline_plug.output if self.name in ( - 'inputs', 'outputs') else pipeline_plug.output) - if not output or (not self.show_opt_outputs and pipeline_plug.optional): - continue - param_text = self._parameter_text(out_param) - if out_param in selections: - param_name = self._colored_text_item('select: ' + out_param, - param_text, 0) - else: - param_name = QtGui.QGraphicsTextItem(self) - param_name.setHtml(param_text) - - plug_name = '%s:%s' % (self.name, out_param) - - try: - # color = self.colorLink(trait_type_str) - color = self.colType.colorLink(self.process.trait(out_param)) - - except Exception: - color = ORANGE_2 - - plug = Plug(color, plug_name, - param_name.boundingRect().size().height(), - plug_width, activated=pipeline_plug.activated, - optional=pipeline_plug.optional, parent=self) - param_name.setZValue(2) - param_name.setPos(plug.boundingRect().size().width() + margin, pos) - plug.setPos(plug.boundingRect().size().width() + margin + - param_name.boundingRect().size().width() + margin, pos) - param_name.setParentItem(self) - plug.setParentItem(self) - self.out_plugs[out_param] = plug - self.out_params[out_param] = param_name - pos = pos + param_name.boundingRect().size().height() - - def change_input_view(self): - self.show_opt_inputs = not self.show_opt_inputs - - def change_output_view(self): - self.show_opt_outputs = not self.show_opt_outputs - - def _build_logical_view_plugs(self): - margin = 5 - plug_width = 12 - pos = margin + margin + self.title.boundingRect().size().height() - - has_input = False - has_output = False - - for in_param, pipeline_plug in six.iteritems(self.parameters): - output = (not pipeline_plug.output if self.name in ( - 'inputs', 'outputs') else pipeline_plug.output) - if output: - has_output = True - else: - has_input = True - if has_input and has_output: - break - - if has_input: - param_name = QtGui.QGraphicsTextItem(self) - param_name.setHtml('') - plug_name = '%s:inputs' % self.name - - color = QtCore.Qt.black - - plug = Plug(color, plug_name, - param_name.boundingRect().size().height(), - plug_width, activated=True, - optional=False, parent=self) - param_name.setZValue(2) - plug.setPos(margin, pos) - param_name.setPos(plug.boundingRect().size().width() + margin, pos) - param_name.setParentItem(self) - plug.setParentItem(self) - self.in_plugs['inputs'] = plug - self.in_params['inputs'] = param_name - - if has_output: - param_name = QtGui.QGraphicsTextItem(self) - param_name.setHtml('') - plug_name = '%s:outputs' % self.name - - color = QtCore.Qt.black - - plug = Plug(color, plug_name, - param_name.boundingRect().size().height(), - plug_width, activated=True, - optional=False, parent=self) - param_name.setZValue(2) - param_name.setPos(plug.boundingRect().size().width() + margin, pos) - plug.setPos(self.title.boundingRect().width() - - plug.boundingRect().width(), pos) - param_name.setParentItem(self) - plug.setParentItem(self) - self.out_plugs['outputs'] = plug - self.out_params['outputs'] = param_name - - def _create_label_marks(self): - labels = self.labels - if labels: - margin = 5 - plug_width = 12 - xpos = margin + plug_width - ypos = None - params = dict(self.in_params) - params.update(self.out_params) - child = None - for param in params.values(): - y = self.mapRectFromItem(param, param.boundingRect()).bottom() - if ypos is None or ypos < y: - ypos = y - child = param - #if ypos is None: - #ypos = margin * 2 + self.title.boundingRect().size().height() - if child is None: - child = self.childItems()[-1] - item_rect = self.mapRectFromItem(child, child.boundingRect()) - ypos = item_rect.bottom() - for label in labels: - color = label.color - text = label.text - label_item = self._colored_text_item(label.text, label.text) - label_item.setPos(xpos, ypos) - label_item.setParentItem(self) - self.label_items.append(label_item) - ypos = self.mapRectFromItem( - label_item, label_item.boundingRect()).bottom() - - def clear_plugs(self): - for plugs, params in ((self.in_plugs, self.in_params), - (self.out_plugs, self.out_params)): - for plug_name, plug in six.iteritems(plugs): - param_item = params[plug_name] - self.scene().removeItem(param_item) - self.scene().removeItem(plug) - self.in_params = {} - self.in_plugs = {} - self.out_params = {} - self.out_plugs = {} - - def updateInfoActived(self, state): - if state: - self.infoActived.setPlainText('') - else: - self.infoActived.setPlainText('disabled') - - def fonced_viewer(self, det): - if det: - # color=QtGui.QColor(150, 150, 250) - self.setOpacity(0.2) - else: - # color=self.color - self.setOpacity(1) - - # self._set_pen(self.active, self.weak, color) - - def _set_brush(self): - pipeline = self.pipeline - if self.name in ('inputs', 'outputs'): - node = pipeline.pipeline_node - else: - node = pipeline.nodes[self.name] - color_1, color_2, color_3, style = pipeline_tools.pipeline_node_colors( - pipeline, node) - self.style = style - color_1 = QtGui.QColor.fromRgbF(*color_1) - color_2 = QtGui.QColor.fromRgbF(*color_2) - # color_1 = ANTHRACITE_1 - # color_2 = LIGHT_ANTHRACITE_1 - gradient = QtGui.QLinearGradient(0, 0, 0, 50) - gradient.setColorAt(0, color_1) - gradient.setColorAt(1, color_2) - self.bg_brush = QtGui.QBrush(gradient) - - if node.activated: - # color_1 = GRAY_1 - # color_2 = GRAY_2 - self.updateInfoActived(True) - - else: - # color_1 = LIGHT_GRAY_1 - # color_2 = LIGHT_GRAY_2 - self.updateInfoActived(False) - - if node in pipeline.disabled_pipeline_steps_nodes(): - color_1 = self._color_disabled(color_1) - color_2 = self._color_disabled(color_2) - - gradient = QtGui.QLinearGradient(0, 2, 5, 100) - gradient.setColorAt(1, GRAY_1) - gradient.setColorAt(0, GRAY_2) - self.title_brush = QtGui.QBrush(LIGHT_GRAY_2) - - def _color_disabled(self, color): - target = [220, 240, 220] - new_color = QtGui.QColor(int((color.red() + target[0]) / 2), - int((color.green() + target[1]) / 2), - int((color.blue() + target[2]) / 2)) - return new_color - - def _create_parameter(self, param_name, pipeline_plug): - plug_width = 12 - margin = 5 - output = (not pipeline_plug.output if self.name in ( - 'inputs', 'outputs') else pipeline_plug.output) - if self.logical_view: - if output: - param_name = 'outputs' - else: - param_name = 'inputs' - param_text = self._parameter_text(param_name) - if self.name == 'inputs' and not self.logical_view \ - and 'select: ' + param_name in \ - [l.text for l in self.scene_labels]: - param_name_item = self._colored_text_item('select: ' + param_name, - param_text, 0) - else: - param_name_item = QtGui.QGraphicsTextItem(self) - param_name_item.setHtml(param_text) - plug_name = '%s:%s' % (self.name, param_name) - - color = QtCore.Qt.black - - plug = Plug(color, plug_name, - param_name_item.boundingRect().size().height(), - plug_width, activated=pipeline_plug.activated, - optional=pipeline_plug.optional, parent=self) - param_name_item.setZValue(2) - if output: - plugs = self.out_plugs - params = self.out_params - params_size = len(params) + len(self.in_params) - # FIXME: sub-pipeline size - xpos = plug.boundingRect().size().width() + margin - pxpos = plug.boundingRect().size().width() + margin * 2 \ - + param_name_item.boundingRect().size().width() - else: - plugs = self.in_plugs - params = self.in_params - params_size = len(params) - xpos = plug.boundingRect().size().width() + margin - pxpos = margin - if self.logical_view: - params_size = 0 - if output: - pxpos = self.title.boundingRect().width() \ - - plug.boundingRect().width() - pos = margin * 2 + self.title.boundingRect().size().height() \ - + param_name_item.boundingRect().size().height() * params_size - param_name_item.setPos(xpos, pos) - plug.setPos(pxpos, pos) - param_name_item.setParentItem(self) - plug.setParentItem(self) - plugs[param_name] = plug - params[param_name] = param_name_item - if output: - self._shift_params() - - self.updateSize(self.box.boundingRect().size().width(), self.box.boundingRect().size().height()) - self.sizer.setPos(self.box.boundingRect().size().width(), self.box.boundingRect().size().height()) - - # self.hmin=self.box.boundingRect().size().height() - - def _shift_params(self): - margin = 5 - if not self.in_params: - if not self.out_params: - param_item = None - else: - param_item = list(self.out_params.values())[0] - else: - param_item = list(self.in_params.values())[0] - ni = 0 - no = 0 - bottom_pos = 0 - if param_item: - for param_name, pipeline_plug in six.iteritems(self.parameters): - output = (not pipeline_plug.output if self.name in ( - 'inputs', 'outputs') else pipeline_plug.output) - if output: - # Added to choose to visualize optional parameters - if not pipeline_plug.optional or (self.show_opt_outputs and pipeline_plug.optional): - params = self.out_params - plugs = self.out_plugs - npos = no + len(self.in_params) - no += 1 - else: - continue - else: - # Added to choose to visualize optional parameters - if not pipeline_plug.optional or (self.show_opt_inputs and pipeline_plug.optional): - params = self.in_params - plugs = self.in_plugs - npos = ni - ni += 1 - else: - continue - pos = margin * 2 + self.title.boundingRect().size().height() \ - + param_item.boundingRect().size().height() * npos - new_param_item = params.get(param_name) - if new_param_item is None: - continue - param_item = new_param_item - plug = plugs[param_name] - ppos = param_item.pos() - param_item.setPos(ppos.x(), pos) - ppos = plug.pos() - plug.setPos(ppos.x(), pos) - pos += param_item.boundingRect().size().height() - bottom_pos = max(pos, bottom_pos) - if self.logical_view: - nparams = 1 - else: - nparams = len(self.in_params) + len(self.out_params) - pos = margin * 2 + self.title.boundingRect().size().height() \ - + param_item.boundingRect().size().height() * nparams - else: - pos = margin * 2 + self.title.boundingRect().size().height() - for label_item in self.label_items: - ppos = label_item.pos() - label_item.setPos(ppos.x(), pos) - pos += label_item.boundingRect().size().height() - - def _remove_parameter(self, param_name): - if param_name in self.in_params: - params = self.in_params - plugs = self.in_plugs - else: - params = self.out_params - plugs = self.out_plugs - param_item = params[param_name] - if self.scene(): - self.scene().removeItem(param_item) - plug = plugs[param_name] - if self.scene(): - self.scene().removeItem(plug) - del params[param_name] - del plugs[param_name] - self._shift_params() - - def _parameter_text(self, param_name): - if self.logical_view: - return '' - pipeline_plug = self.parameters[param_name] - # output = (not pipeline_plug.output if self.name in ( - # 'inputs', 'outputs') else pipeline_plug.output) - output = pipeline_plug.output - if output: - param_text = '<font color="#400000"><b>%s</b></font>' % param_name - else: - param_text = '<font color="#111111"><b>%s</b></font>' % param_name - try: - value = getattr(self.process, param_name) - except traits.TraitError: - value = traits.Undefined - if value is None or value is traits.Undefined or value == '': - param_text = '<em>%s</em>' % param_text - else: - trait = self.process.user_traits()[param_name] - if (isinstance(trait.trait_type, traits.File) \ - or isinstance(trait.trait_type, traits.Directory)) \ - and os.path.exists(value): - param_text = '<b>%s</b>' % param_text - return param_text - - def update_node(self): - # this is needed before the box is resized, otherwise some bad things - # may happen, especially segfaults... - self.prepareGeometryChange() - self._set_brush() - self.box_title.setBrush(self.title_brush) - self.box.setBrush(self.bg_brush) - for param, pipeline_plug in six.iteritems(self.parameters): - output = (not pipeline_plug.output if self.name in ( - 'inputs', 'outputs') else pipeline_plug.output) - if output: - plugs = self.out_plugs - params = self.out_params - if self.logical_view: - param = 'outputs' - else: - plugs = self.in_plugs - params = self.in_params - if self.logical_view: - param = 'inputs' - gplug = plugs.get(param) - if gplug is None: # new parameter ? - self._create_parameter(param, pipeline_plug) - gplug = plugs.get(param) - if not self.logical_view: - # gplug.update_plug(pipeline_plug.activated, - # pipeline_plug.optional) - - try: - # color = self.colorLink(trait_type_str) - color = self.colType.colorLink(self.process.trait(param)) - - except Exception: - color = ORANGE_2 - - gplug.update_plug(color) - - if isinstance(params[param], QtGui.QGraphicsProxyWidget): - # colored parameters are widgets - params[param].widget().findChild( - QtGui.QLabel, 'label').setText( - self._parameter_text(param)) - else: - params[param].setHtml(self._parameter_text(param)) - - if not self.logical_view: - # check removed params - to_remove = [] - - # Added to choose to visualize optional parameters - for param, pipeline_plug in six.iteritems(self.parameters): - output = (not pipeline_plug.output if self.name in ( - 'inputs', 'outputs') else pipeline_plug.output) - if output: - if pipeline_plug.optional and not self.show_opt_outputs: - to_remove.append(param) - else: - if pipeline_plug.optional and not self.show_opt_inputs : - to_remove.append(param) - - for param in self.in_params: - if param not in self.parameters: - to_remove.append(param) - for param in self.out_params: - if param not in self.parameters: - to_remove.append(param) - for param in to_remove: - self._remove_parameter(param) - - self._shift_params() - - # rect = self.title.mapRectToParent(self.title.boundingRect()) - # margin = 5 - # brect = self.boundingRect() - # brect.setWidth(brect.right() - margin) - # rect.setWidth(brect.width()) - # self.box_title.setRect(rect) - # self.box.setRect(self.boundingRect()) - - ################a dd by Irmage OM ############################################# - try : - dim = self.scene().dim.get(self.box.name) - if isinstance(dim, Qt.QPointF): - dim=(dim.x(),dim.y()) - - self.updateSize(dim[0],dim[1]) -# self.scene().dim[self.box.name] = (dim[0],dim[1]) -# print("update_node : self.scene().dim ",dim) - - except Exception: - dim = (self.box.boundingRect().size().width(), self.box.boundingRect().size().height()) - self.updateSize(dim[0],dim[1]) -# self.scene().dim[self.box.name] = (dim[0],dim[1]) -# print("update_node : boundingRect()") - ############################################################################## - - - def contentsRect(self): - brect = QtCore.QRectF(0, 0, 0, 0) - first = True - excluded = [] - for name in ('box', 'box_title'): - if hasattr(self, name): - excluded.append(getattr(self, name)) - for child in self.childItems(): - if not hasattr(child, 'isVisible'): - # we sometimes get some QObject here, I don't know who they are - continue - if not child.isVisible() or child in excluded: - continue - item_rect = self.mapRectFromItem(child, child.boundingRect()) - if first: - first = False - brect = item_rect - else: - if child is self.embedded_subpipeline: - margin = 5 - item_rect.setBottom(item_rect.bottom() + margin) - if item_rect.left() < brect.left(): - brect.setLeft(item_rect.left()) - if item_rect.top() < brect.top(): - brect.setTop(item_rect.top()) - if item_rect.right() > brect.right(): - brect.setRight(item_rect.right()) - if item_rect.bottom() > brect.bottom(): - brect.setBottom(item_rect.bottom()) - return brect - -
-[docs] - def boundingRect(self): - margin = 0 - brect = self.contentsRect() - if self.embedded_subpipeline and self.embedded_subpipeline.isVisible(): - margin = 5 - brect.setRight(brect.right()) - brect.setBottom(brect.bottom() + margin) - return brect
- - -
-[docs] - def paint(self, painter, option, widget=None): - pass
- - - def postscript(self, file_name): - printer = QtGui.QPrinter(QtGui.QPrinter.HighResolution) - printer.setOutputFormat(QtGui.QPrinter.PostScriptFormat) - printer.setOutputFileName(file_name) - # qreal xmargin = contentRect.width()*0.01; - # qreal ymargin = contentRect.height()*0.01; - # printer.setPaperSize(10*contentRect.size()*1.02,QPrinter::DevicePixel); - # printer.setPageMargins(xmargin,ymargin,xmargin,ymargin,QPrinter::DevicePixel); - painter = QtGui.QPainter() - painter.begin(printer) - painter.setPen(QtCore.Qt.blue) - painter.setFont(QtGui.QFont('Arial', 30)) - painter.drawText(0, 0, 'Ca marche !') - # render(&painter,QRectF(QPointF(0,0),10*contentRect.size()),contentRect); - painter.end() - - def resize_subpipeline_on_show(self): - margin = 5 - param_width = self.in_params_width() - pos = margin * 2 + self.title.boundingRect().size().height() - opos = param_width \ - + self.embedded_subpipeline.boundingRect().width() # + margin ? - for name, param in six.iteritems(self.out_params): - param.setPos(opos, param.pos().y()) - plug = self.out_plugs[name] - plug.setPos(opos + margin + param.boundingRect().size().width(), - plug.pos().y()) - # rect = self.box_title.boundingRect() - rect = self.box.boundingRect() - rect.setWidth(self.contentsRect().width()) - # self.box_title.setRect(rect) - self.box.setRect(self.boundingRect()) - - def resize_subpipeline_on_hide(self): - margin = 5 - for name, param in six.iteritems(self.out_params): - plug = self.out_plugs[name] - param.setPos(plug.boundingRect().width() + margin, param.pos().y()) - plug.setPos(plug.boundingRect().size().width() + margin + - param.boundingRect().size().width() + margin, plug.pos().y()) - # rect = self.box_title.boundingRect() - rect = self.box.boundingRect() - rect.setWidth(self.contentsRect().width()) - # self.box_title.setRect(rect) - self.box.setRect(self.boundingRect()) - - def in_params_width(self): - margin = 5 - width = 0 - pwidth = 0 - for param_name, param in six.iteritems(self.in_params): - if param.boundingRect().width() > width: - width = param.boundingRect().width() - if pwidth == 0: - plug = self.in_plugs[param_name] - pwidth = plug.boundingRect().width() - return width + margin + pwidth - - def out_params_width(self): - width = 0 - for param_name, param in six.iteritems(self.out_params): - if param.boundingRect().width() > width: - width = param.boundingRect().width() - return width - - def add_subpipeline_view( - self, - sub_pipeline, - allow_open_controller=True, - scale=None): - if self.embedded_subpipeline: - if self.embedded_subpipeline.isVisible(): - self.embedded_subpipeline.hide() - self.resize_subpipeline_on_hide() - else: - self.embedded_subpipeline.show() - self.resize_subpipeline_on_show() - else: - sub_view = PipelineDeveloperView( - sub_pipeline, - show_sub_pipelines=True, - allow_open_controller=allow_open_controller, - enable_edition=self.scene().edition_enabled(), - userlevel=self.userlevel) - if scale is not None: - sub_view.scale(scale, scale) - pwid = EmbeddedSubPipelineItem(sub_view) - sub_view._graphics_item = weakref.proxy(pwid) - margin = 5 - pos = margin * 2 + self.title.boundingRect().size().height() - pwid.setParentItem(self) - pwid.setPos(self.in_params_width(), pos) - self.embedded_subpipeline = pwid - self.resize_subpipeline_on_show() - self.setFiltersChildEvents(False) - pwid.geometryChanged.connect(self.resize_subpipeline_on_show) - -
-[docs] - def mouseDoubleClickEvent(self, event): - if self.sub_pipeline: - if isinstance(self.sub_pipeline, weakref.ProxyTypes): - # get the "real" object - process = self.sub_pipeline.__init__.__self__ - else: - process = self.sub_pipeline - self.scene().subpipeline_clicked.emit(self.name, process, - int(event.modifiers())) - event.accept() - else: - event.ignore()
- - -
-[docs] - def mousePressEvent(self, event): - item = self.scene().itemAt(event.scenePos(), Qt.QTransform()) - # print('NodeGWidget click, item:', item) - if isinstance(item, Plug): - item.mousePressEvent(event) - return - super(NodeGWidget, self).mousePressEvent(event) - if isinstance(self.process, weakref.ProxyTypes): - process = self.process.__init__.__self__ # get the "real" object - else: - process = self.process - if event.button() == QtCore.Qt.RightButton and process is not None: - self.scene().node_right_clicked.emit(self.name, process) - event.accept() - - if event.button() == QtCore.Qt.LeftButton and process is not None: - if isinstance(process, Process): - self.scene().process_clicked.emit(self.name, process) - else: - self.scene().node_clicked.emit(self.name, process) - - if event.button() == QtCore.Qt.LeftButton and event.modifiers() == QtCore.Qt.ControlModifier: - self.scene().node_clicked_ctrl.emit(self.name, process) - self.scene().clearSelection() - self.box.setSelected(True) - return QtGui.QGraphicsItem.mousePressEvent(self, event) - event.accept()
- - -
-[docs] - def keyPressEvent(self, event): - - super(NodeGWidget, self).keyPressEvent(event) - - if event.key() == QtCore.Qt.Key_Up: - self.setPos(self.x(), self.y() - 1) - if event.key() == QtCore.Qt.Key_Down: - self.setPos(self.x(), self.y() + 1) - if event.key() == QtCore.Qt.Key_Left: - self.setPos(self.x() - 1, self.y()) - if event.key() == QtCore.Qt.Key_Right: - self.setPos(self.x() + 1, self.y()) - - return QtGui.QGraphicsItem.keyPressEvent(self, event) - event.accept()
-
- - - -
-[docs] -class HandleItem(QtGui.QGraphicsRectItem): - """ A handle that can be moved by the mouse """ - - def __init__(self, parent=None): - super(HandleItem, self).__init__(Qt.QRectF(-10.0, -10.0, 10.0, 10.0), parent) - # self.setRect(Qt.QRectF(-4.0,-4.0,4.0,4.0)) - self.posChangeCallbacks = [] - self.setPen(QtGui.QPen(QtCore.Qt.NoPen)) - self.setBrush(QtGui.QBrush(QtCore.Qt.yellow)) - self.setFlag(self.ItemIsMovable, True) - self.setFlag(self.ItemSendsScenePositionChanges, True) - self.setCursor(QtGui.QCursor(QtCore.Qt.SizeFDiagCursor)) - self.wmin = 0.0 - self.hmin = 0.0 - self.hmax = 0.0 - - self.effectiveOpacity() - self.setOpacity(0.01) - -
-[docs] - def itemChange(self, change, value): - if change == self.ItemPositionChange: - self.x, self.y = value.x(), value.y() - if self.x < self.wmin: - self.x = self.wmin - if self.y < self.hmin: - self.y = self.hmin - # TODO: make this a signal? - # This cannot be a signal because this is not a QObject - for cb in self.posChangeCallbacks: - res = cb(self.x, self.y) - - if res: - self.x, self.y = res - if self.x < self.wmin: - self.x = self.wmin - if self.y < self.hmin: - self.y = self.hmin - - value = QtCore.QPointF(self.x, self.y) - # value = Qt.QPointF(x, y) #### ?? - self.hmax = value.y() - return value - # Call superclass method: - - return super(HandleItem, self).itemChange(change, value)
- - -
-[docs] - def mouseReleaseEvent(self, mouseEvent): - self.setSelected(False) - self.setPos(self.x, self.y) - return QtGui.QGraphicsRectItem.mouseReleaseEvent(self, mouseEvent)
-
- - - - - - - -
-[docs] -class PipelineScene(QtGui.QGraphicsScene): - # Signal emitted when a sub pipeline has to be open. - subpipeline_clicked = QtCore.Signal(str, Process, - QtCore.Qt.KeyboardModifiers) - # Signal emitted when a node box is clicked - process_clicked = QtCore.Signal(str, Process) - node_clicked = QtCore.Signal(str, Node) - # Signal emitted when a node box is clicked with ctrl - node_clicked_ctrl = QtCore.Signal(str, Process) - # Signal emitted when a switch box is clicked - switch_clicked = QtCore.Signal(str, Switch) - # Signal emitted when a node box is right-clicked - node_right_clicked = QtCore.Signal(str, Controller) - # Signal emitted when a plug is clicked - plug_clicked = QtCore.Signal(str) - # Signal emitted when a plug is clicked with the right mouse button - plug_right_clicked = QtCore.Signal(str) - # Signal emitted when a link is right-clicked - link_right_clicked = QtCore.Signal(str, str, str, str) - - link_keydelete_clicked = QtCore.Signal(str, str, str, str) - - node_keydelete_clicked = QtCore.Signal(str) - - def __init__(self, parent=None, userlevel=0): - super(PipelineScene, self).__init__(parent) - - self.gnodes = {} - self.glinks = {} - self._pos = 50 - self.pos = {} - self.dim = {} # add by Irmage OM for recorded dimension of Nodes - self.colored_parameters = True - self.logical_view = False - self._enable_edition = False - self.labels = [] - self._userlevel = userlevel - - # pen = QtGui.QPen(QtGui.QColor(250,100,0),2) - # self.l = QtCore.QLineF(-10,0,10,0) - # self.addLine(self.l,pen) - # self.l = QtCore.QLineF(0,-10,0,10) - # self.addLine(self.l,pen) - - self.colType = ColorType() - - self._update_pipeline_timer = Qt.QTimer() - self._update_pipeline_timer.setSingleShot(True) - self._update_pipeline_timer.timeout.connect( - proxy_method(self, 'update_pipeline_now')) - - - self.changed.connect(self.update_paths) - - def __del__(self): - # print('PipelineScene.__del__') - try: - self._release() - except RuntimeError: - pass # C++ object deleted, attributes are already destroyed - - def _release(self): - # print('PipelineScene._release') - if hasattr(self, 'pos'): - del self.pos - if hasattr(self, 'dim'): - del self.dim - if hasattr(self, 'labels'): - del self.labels - if hasattr(self, 'glinks'): - del self.glinks - if 'gnodes' in self.__dict__: - from soma.qt_gui.qt_backend import sip - gnode = None - for gnode in self.gnodes.values(): - gnode._release() - self.removeItem(gnode) - sip.transferback(gnode) - del gnode - del self.gnodes - - try: - self.changed.disconnect() - except TypeError: - pass # already done - - # force delete gnodes: needs to use gc.collect() - import gc - gc.collect() - - @property - def userlevel(self): - return self._userlevel - - @userlevel.setter - def userlevel(self, value): - if self._userlevel != value: - self._userlevel = value - for name, gnode in self.gnodes.items(): - gnode.userlevel = value - self.update_pipeline() - - def _add_node(self, name, gnode): - self.addItem(gnode) - - ################# add by Irmage OM #################### - dim = self.dim.get(name) -# print("_add_node : dim : ",dim," , type =",type(dim).__name__) - - if dim is not None: - if isinstance(dim, Qt.QPointF): - dim=(dim.x(),dim.y()) - - gnode.updateSize(dim[0],dim[1]) - #gnode.sizer.setPos(dim[0],dim[1]) - -# gnode.update_node() - - ###################################################### - - pos = self.pos.get(name) - if pos is None: - gnode.setPos(2 * self._pos, self._pos) - self._pos += 100 - else: - if not isinstance(pos, Qt.QPointF): - pos = Qt.QPointF(pos[0], pos[1]) - gnode.setPos(pos) - - self.gnodes[name] = gnode -# gnode.update_node() - - - #repositioning 'inputs' node - if name == 'inputs': - pos_left_most=(0,0) - for el in self.gnodes: - if el!='inputs' and el!='outputs': - if pos_left_most[0] > self.gnodes[el].pos().x(): - pos_left_most=(self.gnodes[el].pos().x(),self.gnodes[el].pos().y()) - xl = pos_left_most[0]-(2*self.gnodes[name].boundingRect().size().width()) - yl = pos_left_most[1] - self.gnodes[name].setPos(xl,yl) -# gnode.update_node() - - #repositioning 'outputs' node - if name == 'outputs': - pos_right_most=(0,0) - for el in self.gnodes: - if el!='inputs' and el!='outputs': - if pos_right_most[0] < self.gnodes[el].pos().x() + self.gnodes[el].boundingRect().size().width() : - pos_right_most=(self.gnodes[el].pos().x() + self.gnodes[el].boundingRect().size().width(),self.gnodes[el].pos().y()) - xl = pos_right_most[0]+self.gnodes[name].boundingRect().size().width() - yl = pos_right_most[1] - self.gnodes[name].setPos(xl,yl) -# gnode.update_node() - - ################" add by Irmage ############################################# - self.setSceneRect(QtCore.QRectF()) - #############################################################################_node_keydelete_clicked - - def add_node(self, node_name, node): - if not isinstance(node, ProcessNode): - process = node - if hasattr(node, 'process'): - process = node.process - if isinstance(node, PipelineNode): - sub_pipeline = process - elif process and isinstance(process, ProcessIteration): - sub_pipeline = process.process - else: - sub_pipeline = None - gnode = NodeGWidget( - node_name, node.plugs, self.pipeline, - sub_pipeline=sub_pipeline, process=process, - colored_parameters=self.colored_parameters, - logical_view=self.logical_view, labels=self.labels, - userlevel=self.userlevel) - self._add_node(node_name, gnode) - gnode.update_node() - return gnode - - def add_link(self, source, dest, active, weak): - # print("add link ", source, dest) - source_gnode_name, source_param = source - if not source_gnode_name: - source_gnode_name = 'inputs' - dest_gnode_name, dest_param = dest - if not dest_gnode_name: - dest_gnode_name = 'outputs' - if self.logical_view: - source_param = 'outputs' - dest_param = 'inputs' - try: - typeq = self.typeLink(source_gnode_name, source_param) - # color = self.colorLink(typeq) - color = self.colType.colorLink(typeq) - - except Exception: - color = ORANGE_2 - # verif=((str(dest_gnode_name), str(dest_param))) - # print(str(verif) in str(self.glinks.keys())) - source_dest = ((str(source_gnode_name), str(source_param)), - (str(dest_gnode_name), str(dest_param))) - if source_dest in self.glinks: - # already done - if self.logical_view: - # keep strongest link representation - glink = self.glinks[source_dest] - if active or glink.active: - active = True - if not weak or not glink.weak: - weak = False - if glink.weak != weak or glink.active != active: - glink.update_activation(active, weak, "current") - return # already done - source_gnode = self.gnodes[source_gnode_name] - dest_gnode = self.gnodes.get(dest_gnode_name) - - if dest_gnode is not None: - if dest_param in dest_gnode.in_plugs \ - and source_param in source_gnode.out_plugs: - glink = Link( - source_gnode.mapToScene( - source_gnode.out_plugs[source_param].get_plug_point()), - dest_gnode.mapToScene( - dest_gnode.in_plugs[dest_param].get_plug_point()), - active, weak, color) - self.glinks[source_dest] = glink - self.addItem(glink) - - def _remove_link(self, source_dest): - source, dest = source_dest - source_gnode_name, source_param = source - if not source_gnode_name: - source_gnode_name = 'inputs' - source_gnode = self.gnodes.get(source_gnode_name) - dest_gnode_name, dest_param = dest - if not dest_gnode_name: - dest_gnode_name = 'outputs' - if self.logical_view: - # is it useful ? - source_param = 'outputs' - dest_param = 'inputs' - dest_gnode = self.gnodes.get(dest_gnode_name) - new_source_dest = ((str(source_gnode_name), str(source_param)), - (str(dest_gnode_name), str(dest_param))) - glink = self.glinks.get(new_source_dest) - if glink is not None: - self.removeItem(glink) - del self.glinks[new_source_dest] - - def update_paths(self, regions=[]): - for name, i in six.iteritems(self.gnodes): - self.pos[i.name] = i.pos() - br = i.box.boundingRect() - self.dim[i.name] = (br.width(), br.height()) - - dropped = [] - for source_dest, glink in six.iteritems(self.glinks): - source, dest = source_dest - source_gnode_name, source_param = source - dest_gnode_name, dest_param = dest - source_gnode = self.gnodes[source_gnode_name] - dest_gnode = self.gnodes[dest_gnode_name] - if source_param not in source_gnode.out_plugs \ - or dest_param not in dest_gnode.in_plugs: - dropped.append(source_dest) - else: - glink.update(source_gnode.mapToScene( - source_gnode.out_plugs[source_param].get_plug_point()), - dest_gnode.mapToScene( - dest_gnode.in_plugs[dest_param].get_plug_point())) - for source_dest in dropped: - self._remove_link(source_dest) - - def set_pipeline(self, pipeline): - - self.pipeline = pipeline - - self.labels = [] - pipeline_inputs = SortedDictionary() - pipeline_outputs = SortedDictionary() - if pipeline is not None: - for name, plug in six.iteritems(pipeline.nodes[''].plugs): - if plug.output: - pipeline_outputs[name] = plug - else: - pipeline_inputs[name] = plug - if pipeline_inputs: - self._add_node( - 'inputs', NodeGWidget( - 'inputs', pipeline_inputs, pipeline, - process=pipeline, - colored_parameters=self.colored_parameters, - logical_view=self.logical_view, - userlevel=self.userlevel)) - for node_name, node in six.iteritems(pipeline.nodes): - if not node_name: - continue - self.add_node(node_name, node) - if pipeline_outputs: - self._add_node( - 'outputs', NodeGWidget( - 'outputs', pipeline_outputs, pipeline, - process=pipeline, - colored_parameters=self.colored_parameters, - logical_view=self.logical_view, - userlevel=self.userlevel)) - - for source_node_name, source_node in six.iteritems(pipeline.nodes): - for source_parameter, source_plug \ - in six.iteritems(source_node.plugs): - for (dest_node_name, dest_parameter, dest_node, dest_plug, - weak_link) in source_plug.links_to: - if dest_node is pipeline.nodes.get(dest_node_name): - self.add_link( - (source_node_name, source_parameter), - (dest_node_name, dest_parameter), - active=source_plug.activated \ - and dest_plug.activated, - weak=weak_link) - - def update_pipeline(self): - self._update_pipeline_timer.start(20) - - def update_pipeline_now(self): - if self.logical_view: - self._update_logical_pipeline() - else: - self._update_regular_pipeline() - - def _update_regular_pipeline(self): - # normal view - pipeline = self.pipeline - removed_nodes = [] - - # print(self.gnodes) - for node_name, gnode in six.iteritems(self.gnodes): - removed = False - if gnode.logical_view: - gnode.clear_plugs() - gnode.logical_view = False - if node_name in ('inputs', 'outputs'): - node = pipeline.nodes[''] - # in case traits have been added/removed - if node_name == 'inputs': - pipeline_inputs = SortedDictionary() - for name, plug in six.iteritems(node.plugs): - if not plug.output: - trait = node.get_trait(name) - if not trait.hidden \ - and (trait.userlevel is None - or trait.userlevel <= self.userlevel): - pipeline_inputs[name] = plug - gnode.parameters = pipeline_inputs - if len(gnode.parameters) == 0: - # no inputs: remove the gnode - removed_nodes.append(node_name) - removed = True - else: - pipeline_outputs = SortedDictionary() - for name, plug in six.iteritems(node.plugs): - if plug.output: - trait = node.get_trait(name) - if not trait.hidden \ - and (trait.userlevel is None - or trait.userlevel <= self.userlevel): - pipeline_outputs[name] = plug - gnode.parameters = pipeline_outputs - if len(gnode.parameters) == 0: - # no outputs: remove the gnode - removed_nodes.append(node_name) - removed = True - else: - node = pipeline.nodes.get(node_name) - if node is None: # removed node - removed_nodes.append(node_name) - removed = True - continue - if not removed: - gnode.active = node.activated - gnode.update_node() - - # handle removed nodes - for node_name in removed_nodes: - gnode = self.gnodes[node_name] - self.removeItem(gnode) - self.gnodes.pop(node_name, None) - self.dim.pop(node_name, None) - self.pos.pop(node_name, None) - from soma.qt_gui.qt_backend import sip - sip.transferback(gnode) - #import objgraph - #objgraph.show_backrefs(gnode) - del gnode - - # check for added nodes - added_nodes = [] - for node_name, node in six.iteritems(pipeline.nodes): - if node_name == '': - pipeline_inputs = SortedDictionary() - pipeline_outputs = SortedDictionary() - for name, plug in six.iteritems(node.plugs): - if plug.output: - pipeline_outputs[name] = plug - else: - pipeline_inputs[name] = plug - if pipeline_inputs and 'inputs' not in self.gnodes: - self._add_node( - 'inputs', NodeGWidget( - 'inputs', pipeline_inputs, pipeline, - process=pipeline, - colored_parameters=self.colored_parameters, - logical_view=self.logical_view, - userlevel=self.userlevel)) - if pipeline_outputs and 'outputs' not in self.gnodes: - self._add_node( - 'outputs', NodeGWidget( - 'outputs', pipeline_outputs, pipeline, - process=pipeline, - colored_parameters=self.colored_parameters, - logical_view=self.logical_view, - userlevel=self.userlevel)) - elif node_name not in self.gnodes: - process = None - if isinstance(node, Switch): - process = node - if hasattr(node, 'process'): - process = node.process - if isinstance(node, PipelineNode): - sub_pipeline = node.process - else: - sub_pipeline = None - self.add_node(node_name, node) - - # links - to_remove = [] - for source_dest, glink in six.iteritems(self.glinks): - source, dest = source_dest - source_node_name, source_param = source - dest_node_name, dest_param = dest - if source_node_name == 'inputs': - source_node_name = '' - if dest_node_name == 'outputs': - dest_node_name = '' - source_node = pipeline.nodes.get(source_node_name) - if source_node is None: - to_remove.append(source_dest) - continue - source_plug = source_node.plugs.get(source_param) - dest_node = pipeline.nodes.get(dest_node_name) - if dest_node is None: - to_remove.append(source_dest) - continue - dest_plug = dest_node.plugs.get(dest_param) - remove_glink = False - if source_plug is None or dest_plug is None: - # plug[s] removed - remove_glink = True - else: - active = source_plug.activated and dest_plug.activated - weak = [x[4] for x in source_plug.links_to \ - if x[:2] == (dest_node_name, dest_param)] - if len(weak) == 0: - # link removed - remove_glink = True - else: - weak = weak[0] - if remove_glink: - to_remove.append(source_dest) - else: - glink.update_activation(active, weak, "current") - for source_dest in to_remove: - self._remove_link(source_dest) - # check added links - for source_node_name, source_node in six.iteritems(pipeline.nodes): - for source_parameter, source_plug \ - in six.iteritems(source_node.plugs): - for (dest_node_name, dest_parameter, dest_node, dest_plug, - weak_link) in source_plug.links_to: - if dest_node is pipeline.nodes.get(dest_node_name): - self.add_link( - (source_node_name, source_parameter), - (dest_node_name, dest_parameter), - active=source_plug.activated \ - and dest_plug.activated, - weak=weak_link) - self._update_steps() - - def _update_steps(self): - pipeline = self.pipeline - if not hasattr(pipeline, 'pipeline_steps'): - return - steps = pipeline.pipeline_steps - if steps is None: - return - for node_name, node in six.iteritems(pipeline.nodes): - gnode = self.gnodes.get(node_name) - if gnode is None: - continue - labels = ['step: %s' % n for n in steps.user_traits() - if node_name in steps.trait(n).nodes] - #print('update step labels on', node_name, ':', labels) - gnode.update_labels(labels) - - def _update_logical_pipeline(self): - # update nodes plugs and links in logical view mode - pipeline = self.pipeline - # nodes state - removed_nodes = [] - for node_name, gnode in six.iteritems(self.gnodes): - if not gnode.logical_view: - gnode.clear_plugs() - gnode.logical_view = True - if node_name in ('inputs', 'outputs'): - node = pipeline.nodes[''] - else: - node = pipeline.nodes.get(node_name) - if node is None: # removed node - removed_nodes.append(node_name) - continue - gnode.active = node.activated - gnode.update_node() - - # handle removed nodes - for node_name in removed_nodes: - self.removeItem(self.gnodes[node_name]) - from soma.qt_gui.qt_backend import sip - sip.transferback(self.gnodes[node_name]) - del self.gnodes[node_name] - - # check for added nodes - added_nodes = [] - for node_name, node in six.iteritems(pipeline.nodes): - if node_name == '': - pipeline_inputs = SortedDictionary() - pipeline_outputs = SortedDictionary() - for name, plug in six.iteritems(node.plugs): - if plug.output: - pipeline_outputs['outputs'] = plug - else: - pipeline_inputs['inputs'] = plug - if pipeline_inputs and 'inputs' not in self.gnodes: - self._add_node( - 'inputs', NodeGWidget( - 'inputs', pipeline_inputs, pipeline, - process=pipeline, - colored_parameters=self.colored_parameters, - logical_view=self.logical_view, - userlevel=self.userlevel)) - if pipeline_outputs and 'outputs' not in self.gnodes: - self._add_node( - 'outputs', NodeGWidget( - 'outputs', pipeline_outputs, pipeline, - process=pipeline, - colored_parameters=self.colored_parameters, - logical_view=self.logical_view, - userlevel=self.userlevel)) - elif node_name not in self.gnodes: - process = None - if isinstance(node, Switch): - process = node - if hasattr(node, 'process'): - process = node.process - if isinstance(node, PipelineNode): - sub_pipeline = node.process - else: - sub_pipeline = None - self.add_node(node_name, node) - - # links - # delete all links - for source_dest, glink in six.iteritems(self.glinks): - self.removeItem(glink) - self.glinks = {} - # recreate links - for source_node_name, source_node in six.iteritems(pipeline.nodes): - for source_parameter, source_plug \ - in six.iteritems(source_node.plugs): - for (dest_node_name, dest_parameter, dest_node, dest_plug, - weak_link) in source_plug.links_to: - if dest_node is pipeline.nodes.get(dest_node_name): - self.add_link( - (source_node_name, source_parameter), - (dest_node_name, dest_parameter), - active=source_plug.activated \ - and dest_plug.activated, - weak=weak_link) - self._update_steps() - - def set_enable_edition(self, state=True): - self._enable_edition = state - - def edition_enabled(self): - return self._enable_edition - -
-[docs] - def keyPressEvent(self, event): - super(PipelineScene, self).keyPressEvent(event) - if not event.isAccepted(): - if event.key() == QtCore.Qt.Key_P: - # print position of boxes - event.accept() - pview = self.parent() - pview.print_node_positions() - elif event.key() == QtCore.Qt.Key_T: - for item in self.items(): - if isinstance(item, boxItem): - item.focusOutEvent(Qt.QFocusEvent(Qt.QEvent.FocusOut)) - # toggle logical / full view - pview = self.parent() - pview.switch_logical_view() - event.accept() - elif event.key() == QtCore.Qt.Key_A: - # auto-set nodes positions - pview = self.parent() - pview.auto_dot_node_positions()
- - - # elif Qt.QKeySequence(event.key()+int(event.modifiers())) == Qt.QKeySequence("Ctrl+Z"): - # self.undoTyping_clicked.emit() - - - - - @staticmethod - def get_instance_type_string(value): - if value is None: - return 'None' - if value is traits.Undefined: - return 'Undefined' - if isinstance(value, (list, traits.TraitListObject)): - return 'list' - return type(value).__name__ - - @staticmethod - def is_existing_path(value): - if value not in (None, traits.Undefined) \ - and type(value) in (str, six.text_type) and os.path.exists(value): - return True - return False - - @staticmethod - def html_doc(doc_text): - # TODO: sphinx transform - text = doc_text.replace('<', '&lt;') - text = text.replace('>', '&gt;') - return text - -
-[docs] - def plug_tooltip_text(self, node, name): - '''Tooltip text for a node plug - ''' - if node.name in ('inputs', 'outputs'): - proc = self.pipeline - splug = self.pipeline.pipeline_node.plugs[name] - else: - src = self.pipeline.nodes[node.name] - splug = src.plugs.get(name) - if not splug: - return None - proc = src - if hasattr(src, 'process'): - proc = src.process - if splug.output: - output = '<font color="#d00000">output</font>' - else: - output = '<font color="#00d000">input</font>' - if splug.enabled: - enabled = 'enabled' - else: - enabled = '<font color="#a0a0a0">disabled</font>' - if splug.activated: - activated = 'activated' - else: - activated = '<font color="#a0a0a0">inactive</font>' - if splug.optional: - optional = '<font color="#00d000">optional</font>' - else: - optional = 'mandatory' - value = getattr(proc, name) - trait = proc.user_traits()[name] - trait_type = trait.trait_type - trait_type_str = trait_type.__class__.__name__ - if trait.output and trait.input_filename is False: - trait_type_str += ', output filename' - typestr = ('%s (%s)' % (self.get_instance_type_string(value), - trait_type_str)).replace( - '<', '').replace('>', '') - msg = '''<h3>%s</h3> -<table cellspacing="6"> - <tr> - <td><b>Plug:</b></td> - <td>%s</td> - <td>%s</td> - <td>%s</td> - <td>%s</td> - </tr> -</table> -<table> - <tr> - <td><b>type:</b></td> - <td>%s</td> - </tr> - <tr> - <td><b>value:</b></td> - <td>%s</td> - </tr> -''' \ - % (name, output, optional, enabled, activated, typestr, - html.escape(str(value))) - if isinstance(trait_type, traits.File) \ - or isinstance(trait_type, traits.Directory) \ - or isinstance(trait_type, traits.Any): - if self.is_existing_path(value): - msg += ''' <tr> - <td></td> - <td>existing path</td> - </tr> -''' - elif not isinstance(trait_type, traits.Any): - msg += ''' <tr> - <td></td> - <td><font color="#a0a0a0">non-existing path</font></td> - </tr> -''' - msg += '</table>' - desc = trait.desc - if desc: - msg += '\n<h3>Description:</h3>\n' - msg += self.html_doc(desc) - return msg
- - - def node_tooltip_text(self, node): - process = node.process - msg = getattr(process, '__doc__', '') - # msg = self.html_doc(doc) - return msg - - def _parentgnode(self, item): - if qt_backend.get_qt_backend() != 'PyQt5': - return item.parentItem() - # in PyQt5 (certain versions at least, Ubuntu 16.04) parentItem() - # returns something inappropriate, having the wrong type - # QGraphicsVideoItem, probably a cast mistake, and which leads to - # a segfault, so we have to get it a different way. - nodes = [node for node in self.gnodes.values() - if item in node.childItems()] - if len(nodes) == 1: - return nodes[0] - -
-[docs] - def helpEvent(self, event): - ''' - Display tooltips on plugs and links - ''' - if self.logical_view: - event.setAccepted(False) - super(PipelineScene, self).helpEvent(event) - return - item = self.itemAt(event.scenePos(), Qt.QTransform()) - if isinstance(item, Link): - for source_dest, glink in six.iteritems(self.glinks): - if glink is item: - text = self.link_tooltip_text(source_dest) - item.setToolTip(text) - break - elif isinstance(item, Plug): - node = self._parentgnode(item) - found = False - for name, plug in six.iteritems(node.in_plugs): - if plug is item: - found = True - break - if not found: - for name, plug in six.iteritems(node.out_plugs): - if plug is item: - found = True - break - if found: - text = self.plug_tooltip_text(node, name) - item.setToolTip(text) - elif isinstance(item, QtGui.QGraphicsRectItem): - node = self._parentgnode(item) - if isinstance(node, NodeGWidget): - text = self.node_tooltip_text(node) - item.setToolTip(text) - elif isinstance(item, QtGui.QGraphicsProxyWidget): - # PROBLEM: tooltips in child graphics scenes seem not to popup. - # - # to force them we would have to translate the event position to - # the sub-scene position, and call the child scene helpEvent() - # method, with a custom event. - # However this is not possible, since QGraphicsSceneHelpEvent - # does not provide a public (nor even protected) constructor, and - # secondarily helpEvent() is protected. - event.setAccepted(False) - - super(PipelineScene, self).helpEvent(event)
- - - def remove_node(self, node_name): - print(self.gnodes) - gnode = self.gnodes.get(node_name) - if gnode is None: - # already done (possibly via a notification) - return - todel = set() - from soma.qt_gui.qt_backend import sip - for link, glink in six.iteritems(self.glinks): - if link[0][0] == node_name or link[1][0] == node_name: - self.removeItem(glink) - todel.add(link) - for link in todel: - del self.glinks[link] - self.removeItem(gnode) - sip.transferback(self.gnodes[node_name]) - del self.gnodes[node_name] - - def _link_right_clicked(self, link): - # find the link in list - # print('Scene._link_right_clicked:', link) - for source_dest, glink in six.iteritems(self.glinks): - if glink is link: - self.link_right_clicked.emit( - source_dest[0][0], source_dest[0][1], - source_dest[1][0], source_dest[1][1]) - break - - def _link_keydelete_clicked(self, link): - for source_dest, glink in six.iteritems(self.glinks): - if glink is link: - self.link_keydelete_clicked.emit( - source_dest[0][0], source_dest[0][1], - source_dest[1][0], source_dest[1][1]) - break - - def _node_keydelete_clicked(self, node): - self.node_keydelete_clicked.emit(node.name) - - def typeLink(self, name_node, name_plug): - - if name_node in ('inputs', 'outputs'): - proc = self.pipeline - splug = self.pipeline.pipeline_node.plugs[name_plug] - else: - src = self.pipeline.nodes[name_node] - splug = src.plugs[name_plug] - proc = src - if hasattr(src, 'process'): - proc = src.process - - value = getattr(proc, name_plug) - - trait = proc.user_traits()[name_plug] - trait_type = trait.trait_type - trait_type_str = str(trait_type) - trait_type_str = trait_type_str[: trait_type_str.find(' object ')] - trait_type_str = trait_type_str[trait_type_str.rfind('.') + 1:] - return trait_type_str
- - - -
-[docs] -class PipelineDeveloperView(QGraphicsView): - ''' - Pipeline representation as a graph, using boxes and arrows. - - Based on Qt QGraphicsView, this can be used as a Qt QWidget. - - Qt signals are emitted on a right click on a node box, and on a double - click on a sub-pipeline box, to allow handling at a higher level. Default - behaviors can be enabled using constructor parameters. - - Ctrl + double click opens sub-pipelines in embedded views inside their - parent box. - - Attributes - ---------- - subpipeline_clicked - node_right_clicked - process_clicked - node_clicked - node_clicked_ctrl - plug_clicked - plug_right_clicked - link_right_clicked - colored_parameters - scene - - Methods - ------- - __init__ - set_pipeline - is_logical_view - set_logical_view - zoom_in - zoom_out - openProcessController - add_embedded_subpipeline - onLoadSubPipelineClicked - onOpenProcessController - enableNode - enable_step - disable_preceding_steps - disable_following_steps - enable_preceding_steps - enable_following_steps - set_switch_value - disable_done_steps - enable_all_steps - check_files - auto_dot_node_positions - save_dot_image_ui - reset_initial_nodes_positions - window - ''' - subpipeline_clicked = QtCore.Signal(str, Process, - QtCore.Qt.KeyboardModifiers) - '''Signal emitted when a sub pipeline has to be open.''' - process_clicked = QtCore.Signal(str, Process) - node_clicked = QtCore.Signal(str, Node) - '''Signal emitted when a node box has to be open.''' - node_clicked_ctrl = QtCore.Signal(str, Process) - '''Signal emitted when a node box has to be in the foreground.''' - switch_clicked = QtCore.Signal(str, Switch) - '''Signal emitted when a switch box has to be open.''' - node_right_clicked = QtCore.Signal(str, Controller) - '''Signal emitted when a node box is right-clicked''' - plug_clicked = QtCore.Signal(str) - '''Signal emitted when a plug is clicked''' - plug_right_clicked = QtCore.Signal(str) - '''Signal emitted when a plug is right-clicked''' - link_right_clicked = QtCore.Signal(str, str, str, str) - '''Signal emitted when a link is right-clicked''' - edit_sub_pipeline = QtCore.Signal(Pipeline) - '''Signal emitted when a sub-pipeline has to be edited''' - open_filter = QtCore.Signal(str) - '''Signal emitted when an Input Filter has to be opened''' - export_to_db_scans = QtCore.Signal(str) - '''Signal emitted when an Input Filter has to be linked to database_scans''' - link_keydelete_clicked = QtCore.Signal(str, str, str, str) - node_keydelete_clicked = QtCore.Signal(str) - - scene = None - ''' - type: PipelineScene - - the main scene. - ''' - colored_parameters = True - ''' - If enabled (default), parameters in nodes boxes are displayed with color - codes representing their state, and the state of their values: output - parameters, empty values, existing files, non-existing files... - - When colored_parameters is set, however, callbacks have to be installed to - track changes in traits values, so this actually has an overhead. - When colored_parameters is used, the color code is as follows: - - * black pamameter name: input - * red parameter name: output - * italics parameter name: Undefined, None, or empty string value - * bold parameter name: existing file or directory name - * regular font parameter name: non-existing file, or non-file parameter type - * black plug: mandatory - * green plug: optional - * grey plug: mandatory, inactive - * light green plug: optional, inactive - * grey link: inactive - * orange link: active - * dotted line link: weak link - ''' - -
-[docs] - class ProcessNameEdit(Qt.QLineEdit): - ''' A specialized QLineEdit with completion for process name - ''' - def __init__(self, parent=None, - class_type_check=process_instance.is_process): - super(PipelineDeveloperView.ProcessNameEdit, - self).__init__(parent) - self.compl = QtGui.QCompleter([]) - self.setCompleter(self.compl) - self.textEdited.connect(self.on_text_edited) - self.py_cache = {} # cache for loaded python files - self.class_type_check = class_type_check - - @staticmethod - def _execfile(filename): - glob_dict = {} - exec(compile(open(filename, "rb").read(), filename, 'exec'), - glob_dict, glob_dict) - return glob_dict - - def load_py(self, filename): - if filename not in self.py_cache: - try: - self.py_cache[filename] = self._execfile(filename) - except Exception as e: - print('exception while executing file %s:' % filename, e) - return {} - return self.py_cache[filename] - - def get_processes_or_modules(self, filename): - file_dict = self.load_py(filename) - processes = [] - for name, item in six.iteritems(file_dict): - if self.class_type_check(item) or inspect.ismodule(item): - processes.append(name) - return processes - - def on_text_edited(self, text): - compl = set() - modpath = str(text).split('.') - current_mod = None - paths = [] - sel = set() - mod = None - if len(modpath) > 1: - current_mod = '.'.join(modpath[:-1]) - try: - mod = importlib.import_module(current_mod) - except ImportError: - mod = None - if mod: - if os.path.basename(mod.__file__).startswith( - '__init__.py'): - paths = [os.path.dirname(mod.__file__)] - # add process/pipeline objects in current_mod - procs = [item for k, item - in six.iteritems(mod.__dict__) - if self.class_type_check(item) - or inspect.ismodule(item)] - compl.update(['.'.join([current_mod, c.__name__]) - for c in procs]) - if not mod: - # no current module - # is it a path name ? - pathname, filename = os.path.split(str(text)) - if os.path.isdir(pathname): - # look for class in python file filename.py#classname - elements = filename.split('.py#') - if len(elements) == 2: - filename = elements[0] + '.py' - object_name = elements[1] - full_path = os.path.join(pathname, filename) - processes = self.get_processes_or_modules(full_path) - if object_name != '': - processes = [p for p in processes - if p.startswith(object_name)] - compl.update(['#'.join((full_path, p)) - for p in processes]) - else: - # look for matching xml files - for f in os.listdir(pathname): - if (f.endswith('.xml') or f.endswith('.json') - or os.path.isdir(os.path.join(pathname, - f))) \ - and f.startswith(filename): - compl.add(os.path.join(pathname, f)) - elif f.endswith('.py'): - compl.add(os.path.join(pathname, f)) - else: - paths = sys.path - for path in paths: - if path == '': - path = '.' - try: - for f in os.listdir(path): - if f.endswith('.py'): - sel.add(f[:-3]) - elif f.endswith('.pyc') or f.endswith('.pyo'): - sel.add(f[:-4]) - elif f.endswith('.xml') or f.endswith('.json'): - sel.add(f) - elif '.' not in f \ - and os.path.isdir(os.path.join( - path, f)): - sel.add(f) - except OSError: - pass - begin = modpath[-1] - cm = [] - if current_mod is not None: - cm = [current_mod] - compl.update(['.'.join(cm + [f]) for f in sel \ - if f.startswith(modpath[-1])]) - model = self.compl.model() - model.setStringList(list(compl))
- - -
-[docs] - def __init__(self, pipeline=None, parent=None, show_sub_pipelines=False, - allow_open_controller=False, logical_view=False, - enable_edition=False, userlevel=0): - '''PipelineDeveloperView - - Parameters - ---------- - pipeline: Pipeline (optional) - pipeline object to be displayed - If omitted an empty pipeline will be used, and edition mode will be - activated. - parent: QWidget (optional) - parent widget - show_sub_pipelines: bool (optional) - if set, sub-pipelines will appear as red/pink boxes and a double - click on one of them will open another window with the sub-pipeline - structure in it - allow_open_controller: bool (optional) - if set, a right click on any box will open another window with the - underlying node controller, allowing to see and edit parameters - values, switches states, etc. - logical_view: bool (optional) - if set, plugs and links between plugs are hidden, only links - between nodes are displayed. - enable_edition: bool (optional) - if set, pipeline edition features are available in GUI and menus: - adding process boxes, drawing links etc. If pipeline is not - specified, then edition will be activated anyway. - ''' - - super(PipelineDeveloperView, self).__init__(parent) - - # self.setAlignment(QtCore.Qt.AlignTop | QtCore.Qt.AlignLeft) - self.setAlignment(QtCore.Qt.AlignCenter) - self.centerOn(0,0) - - self.setRenderHints(Qt.QPainter.Antialiasing | Qt.QPainter.SmoothPixmapTransform) - self.setBackgroundBrush(QtGui.QColor(60, 60, 60)) - self.scene = None - self.colored_parameters = True - self._show_sub_pipelines = show_sub_pipelines - self._allow_open_controller = allow_open_controller - self._logical_view = logical_view - self._enable_edition = enable_edition - self._pipeline_filename = "" - self._restricted_edition = False - self.disable_overwrite = False - self._userlevel = userlevel - self.doc_browser = None - - self.set_pipeline(pipeline) - self._grab = False - self._grab_link = False - self.plug_clicked.connect(self._plug_clicked) - self.plug_right_clicked.connect(self._plug_right_clicked) - self.link_right_clicked.connect(self._link_clicked) - self.node_clicked_ctrl.connect(self._node_clicked_ctrl) - self.link_keydelete_clicked.connect(self._link_delete_clicked) - self.node_keydelete_clicked.connect(self._node_delete_clicked)
- - - def __del__(self): - # print('PipelineDeveloperView.__del__') - self.release_pipeline(delete=True) - # super(PipelineDeveloperView, self).__del__() - - @property - def userlevel(self): - return self._userlevel - - @userlevel.setter - def userlevel(self, value): - self._userlevel = value - if self.scene: - self.scene.userlevel = value - for widget in self.findChildren(QtGui.QWidget): - if hasattr(widget, 'userlevel'): - widget.userlevel = value - -
-[docs] - def ensure_pipeline(self, pipeline): - ''' - Check that we have a pipeline or a process - ''' - if pipeline is None: - pipeline = Pipeline() - enable_edition = True - - if not isinstance(pipeline, Pipeline): - if isinstance(pipeline, Process): - process = pipeline - pipeline = Pipeline() - pipeline.set_study_config(process.get_study_config()) - pipeline.add_process(process.name, process) - pipeline.autoexport_nodes_parameters() - pipeline.node_position["inputs"] = (0., 0.) - pipeline.node_position[process.name] = (300., 0.) - pipeline.node_position["outputs"] = (600., 0.) - # pipeline.scene_scale_factor = 0.5 - pipeline.node_dimension[process.name] = (300., 200.) #add by Irmage OM - else: - raise Exception("Expect a Pipeline or a Process, not a " - "'{0}'.".format(repr(pipeline))) - return pipeline
- - - def _set_pipeline(self, pipeline): - pos = {} - dim = {} - if self.scene: - pos = self.scene.pos - dim = self.scene.dim #add by Irmage OM - # pprint(dict((i, (j.x(), j.y())) for i, j in six.iteritems(pos))) - if hasattr(pipeline, 'node_position'): - for i, j in six.iteritems(pipeline.node_position): - if isinstance(j, QtCore.QPointF): - pos[i] = j - else: - pos[i] = QtCore.QPointF(*j) - - ############### add by Irmage OM ####################### - if hasattr(pipeline, 'node_dimension'): - for i, j in six.iteritems(pipeline.node_dimension): - if isinstance(j, QtCore.QPointF): - dim[i] = (j.x(), j.y()) - else: - dim[i] = j - -# print("_set_pipeline : ",pos," ; ",dim) - ####################################################### - self.release_pipeline() - self.scene.set_pipeline(pipeline) - self.scene.pos = pos - self.scene.dim = dim - if pipeline is not None: - self.setWindowTitle(pipeline.name) - # Try to initialize the scene scale factor - if hasattr(pipeline, "scene_scale_factor"): - self.scale( - pipeline.scene_scale_factor, pipeline.scene_scale_factor) - - self.reset_initial_nodes_positions() - - ################" add by Irmage ############################################# - self.fitInView(self.sceneRect(), QtCore.Qt.KeepAspectRatio) - ############################################################################# - - -
-[docs] - def set_pipeline(self, pipeline): - ''' - Assigns a new pipeline to the view. - ''' - pipeline = self.ensure_pipeline(pipeline) - self._set_pipeline(pipeline) - if pipeline is not None: - # Setup callback to update view when pipeline state is modified - pipeline.on_trait_change(self._reset_pipeline, 'selection_changed', - dispatch='ui') - pipeline.on_trait_change(self._reset_pipeline, - 'user_traits_changed', dispatch='ui') - if hasattr(pipeline, 'pipeline_steps'): - pipeline.pipeline_steps.on_trait_change( - self._reset_pipeline, dispatch='ui')
- - -
-[docs] - def release_pipeline(self, delete=False): - ''' - Releases the pipeline currently viewed (and remove the callbacks) - - If ``delete`` is set, this means the view is within deletion process - and a new scene should not be built - ''' - # Setup callback to update view when pipeline state is modified - from soma.qt_gui.qt_backend import sip - pipeline = None - if self.scene is not None and hasattr(self.scene, 'pipeline'): - pipeline = self.scene.pipeline - if pipeline is not None: - if hasattr(pipeline, 'pipeline_steps'): - pipeline.pipeline_steps.on_trait_change( - self._reset_pipeline, remove=True) - pipeline.on_trait_change(self._reset_pipeline, 'selection_changed', - remove=True) - pipeline.on_trait_change(self._reset_pipeline, - 'user_traits_changed', remove=True) - if sip.isdeleted(self): - # prevent 'C++ object has been deleted' error - return - self.setScene(None) - if self.scene: - # force destruction of scene internals now that the Qt object - # still exists - self.scene._release() - # the scene is not deleted after all refs are released, even - # after self.setScene(None). This is probably a bug in PyQt: - # the C++ layer keeps ownership of the scene, whereas it should - # not: the Qt doc specifies for QGraphicsView.setScene(): - # "The view does not take ownership of scene.", however in PyQt it - # does, and only releases it when the QGraphicsView is deleted. - # Thus we have to force it by hand: - from soma.qt_gui.qt_backend import sip - sip.transferback(self.scene) - self.scene = None - import gc - gc.collect() - if not delete and (pipeline is not None or self.scene is None): - self.scene = PipelineScene(self, userlevel=self.userlevel) - self.scene.set_enable_edition(self._enable_edition) - self.scene.logical_view = self._logical_view - self.scene.colored_parameters = self.colored_parameters - self.scene.subpipeline_clicked.connect(self.subpipeline_clicked) - self.scene.subpipeline_clicked.connect(self.onLoadSubPipelineClicked) - self.scene.process_clicked.connect(self._node_clicked) - self.scene.node_clicked.connect(self._node_clicked) - self.scene.node_clicked_ctrl.connect(self._node_clicked_ctrl) - self.scene.switch_clicked.connect(self.switch_clicked) - self.scene.node_right_clicked.connect(self.node_right_clicked) - self.scene.node_right_clicked.connect(self.onOpenProcessController) - self.scene.plug_clicked.connect(self.plug_clicked) - self.scene.plug_right_clicked.connect(self.plug_right_clicked) - self.scene.link_right_clicked.connect(self.link_right_clicked) - self.scene.link_keydelete_clicked.connect(self.link_keydelete_clicked) - self.scene.node_keydelete_clicked.connect(self.node_keydelete_clicked) - self.scene.pos = {} - self.scene.dim = {} - self.setWindowTitle('<no pipeline>') - self.setScene(self.scene)
- - -
-[docs] - def is_logical_view(self): - ''' - in logical view mode, plugs and links between plugs are hidden, only - links between nodes are displayed. - ''' - return self._logical_view
- - -
-[docs] - def set_logical_view(self, state): - ''' - in logical view mode, plugs and links between plugs are hidden, only - links between nodes are displayed. - - Parameters - ---------- - state: bool (mandatory) - to set/unset the logical view mode - ''' - self._logical_view = state - self._reset_pipeline()
- - - def _reset_pipeline(self): - # self._set_pipeline(pipeline) - self.scene.logical_view = self._logical_view - self.scene.update_pipeline() - -
-[docs] - def zoom_in(self): - ''' - Zoom the view in, applying a 1.2 zoom factor - ''' - scf = 1.2 - self.scale(scf, scf) - cur_pos = self.mapFromGlobal(Qt.QCursor.pos()) - c_pos = Qt.QPointF(self.width() / 2, self.height() / 2) - p = (cur_pos - c_pos) * (scf - 1.) - self.horizontalScrollBar().setValue( - self.horizontalScrollBar().value() + int(p.x())) - self.verticalScrollBar().setValue( - self.verticalScrollBar().value() + int(p.y()))
- - -
-[docs] - def zoom_out(self): - ''' - Zoom the view out, applying a 1/1.2 zool factor - ''' - scf = 1. / 1.2 - self.scale(scf, scf) - cur_pos = self.mapFromGlobal(Qt.QCursor.pos()) - c_pos = Qt.QPointF(self.width() / 2, self.height() / 2) - p = (cur_pos - c_pos) * (scf - 1.) - self.horizontalScrollBar().setValue( - self.horizontalScrollBar().value() + int(p.x())) - self.verticalScrollBar().setValue( - self.verticalScrollBar().value() + int(p.y()))
- - -
-[docs] - def edition_enabled(self): - ''' - Get the editable state - ''' - return self._enable_edition
- - -
-[docs] - def set_enable_edition(self, state=True): - ''' - Set the editable state. Edition allows to modify a pipeline: adding / - removing process boxes and switches, drawing links, etc. - ''' - self._enable_edition = state - self.scene.set_enable_edition(state)
- - -
-[docs] - def is_restricted_edition_mode(self): - ''' - Get the restricted mode status - - Returns - ------- - enabled: bool - ''' - return self._restricted_edition
- - -
-[docs] - def set_restricted_edition_mode(self, enabled): - ''' - Set the restricted edition mode. In restricted mode, some background - menu actions ("add process", "open node controller"...) are not - available. - - Parameters - ---------- - enabled: bool - ''' - self._restricted_edition = enabled
- - -
-[docs] - def wheelEvent(self, event): - done = False - if event.modifiers() == QtCore.Qt.ControlModifier: - item = self.itemAt(event.pos()) - if not isinstance(item, QtGui.QGraphicsProxyWidget): - done = True - if qt_backend.get_qt_backend() == 'PyQt5': - delta = event.angleDelta().y() - else: - delta = event.delta() - if delta < 0: - self.zoom_out() - else: - self.zoom_in() - event.accept() - if not done: - super(PipelineDeveloperView, self).wheelEvent(event)
- - -
-[docs] - def mousePressEvent(self, event): - super(PipelineDeveloperView, self).mousePressEvent(event) - if not event.isAccepted(): - if event.button() == QtCore.Qt.RightButton: - self.open_background_menu() - else: - self._grab = True - self._grabpos = event.pos() - - # print("background clicked") - - for source_dest, glink in six.iteritems(self.scene.glinks): - glink.fonced_viewer(False) - for node_name, gnode in six.iteritems(self.scene.gnodes): - gnode.fonced_viewer(False)
- - -
-[docs] - def mouseReleaseEvent(self, event): - self._grab = False - if self._grab_link: - event.accept() - try: - self._release_grab_link(event) - except Exception as e: - print("source to destination types are not compatible") - print(e) - - super(PipelineDeveloperView, self).mouseReleaseEvent(event) - self.scene.update()
- - -
-[docs] - def mouseMoveEvent(self, event): - if self._grab: - event.accept() - translation = event.pos() - self._grabpos - self._grabpos = event.pos() - self.horizontalScrollBar().setValue( - self.horizontalScrollBar().value() - int(translation.x())) - self.verticalScrollBar().setValue( - self.verticalScrollBar().value() - int(translation.y())) - elif self._grab_link: - self._move_grab_link(event) - event.accept() - else: - super(PipelineDeveloperView, self).mouseMoveEvent(event)
- - -
-[docs] - def dragEnterEvent(self, event): - """Event handler when the mouse enters the widget. - - :param event: event - """ - - if event.mimeData().hasFormat('component/name'): - event.accept()
- - -
-[docs] - def dragMoveEvent(self, event): - """Event handler when the mouse moves in the widget. - - :param event: event - """ - - if event.mimeData().hasFormat('component/name'): - event.accept()
- - -
-[docs] - def dropEvent(self, event): - """Event handler when something is dropped in the widget. - - :param event: event - - """ - - if event.mimeData().hasFormat('component/name'): - self.click_pos = QtGui.QCursor.pos() - path = bytes(event.mimeData().data('component/name')) - self.drop_process(path.decode('utf8'))
- - -
-[docs] - def drop_process(self, path): - """Find the dropped process in the system's paths. - - :param path: class's path (e.g. "nipype.interfaces.spm.Smooth") (str) - """ - - package_name, process_name = os.path.splitext(path) - process_name = process_name[1:] - __import__(package_name) - pkg = sys.modules[package_name] - for name, instance in sorted(list(pkg.__dict__.items())): - if name == process_name: - if issubclass(instance, Node): - # it's a node - try: - QtGui.QApplication.setOverrideCursor( - QtCore.Qt.WaitCursor) - self.add_named_node(None, instance) - QtGui.QApplication.restoreOverrideCursor() - return - except Exception as e: - print(e) - return - try: - process = get_process_instance(instance) - except Exception as e: - print(e) - return - else: - QtGui.QApplication.setOverrideCursor(QtCore.Qt.WaitCursor) - self.add_named_process(instance) - QtGui.QApplication.restoreOverrideCursor()
- - -
-[docs] - def add_embedded_subpipeline(self, subpipeline_name, scale=None): - ''' - Adds an embedded sub-pipeline inside its parent node. - ''' - gnode = self.scene.gnodes.get(str(subpipeline_name)) - if gnode is not None: - sub_pipeline \ - = self.scene.pipeline.nodes[str(subpipeline_name)].process - gnode.add_subpipeline_view( - sub_pipeline, self._allow_open_controller, scale=scale)
- - -
-[docs] - def onLoadSubPipelineClicked(self, node_name, sub_pipeline, modifiers): - """ Event to load a open a sub-pipeline view. - If ctrl is pressed the new view will be embedded in its parent node - box. - """ - if self._show_sub_pipelines: - if modifiers & QtCore.Qt.ControlModifier: - try: - self.add_embedded_subpipeline(node_name) - return - except KeyError: - print('node not found in:') - print(list(self.scene.gnodes.keys())) - sub_view = PipelineDeveloperView( - sub_pipeline, - show_sub_pipelines=self._show_sub_pipelines, - allow_open_controller=self._allow_open_controller, - enable_edition=self.edition_enabled(), - logical_view=self._logical_view, userlevel=self.userlevel) - # set self.window() as QObject parent (not QWidget parent) to - # prevent the sub_view to close/delete immediately - QtCore.QObject.setParent(sub_view, self.window()) - sub_view.setAttribute(QtCore.Qt.WA_DeleteOnClose) - sub_view.setWindowTitle(node_name) - sub_view.doc_browser = self - self.scene.update() - sub_view.show()
- - -
-[docs] - def window(self): - ''' - window() is overloaded from QWidget.window() to handle embedded views - cases. - A PipelineDeveloperView may be displayed inside a NodeGWidget. - In this case, we want to go up to the parent scene's window to the - "real" top window, where QWidget.window() will end in the current - graphics scene. - ''' - if hasattr(self, '_graphics_item'): - return self._graphics_item.scene().views()[0].window() - else: - return super(PipelineDeveloperView, self).window()
- - -
-[docs] - def onOpenProcessController(self, node_name, process): - """ Event to open a sub-process/sub-pipeline controller - """ - if self._allow_open_controller: - self.open_node_menu(node_name, process)
- - -
-[docs] - def openProcessController(self): - sub_view = QtGui.QScrollArea() - node_name = self.current_node_name - if node_name in ('inputs', 'outputs'): - node_name = '' - process = self.scene.pipeline.nodes[node_name] - if hasattr(process, 'process'): - process = process.process - # force instantiating a completion engine (since - # AttributedProcessWidget does not force it) - if hasattr(process, 'get_study_config'): # exclude custom nodes - engine = process.get_study_config().engine - from capsul.attributes.completion_engine \ - import ProcessCompletionEngine - ce = ProcessCompletionEngine.get_completion_engine(process) - - cwidget = AttributedProcessWidget( - process, enable_attr_from_filename=True, enable_load_buttons=True, - userlevel=self.userlevel) - sub_view.setWidget(cwidget) - sub_view.setWidgetResizable(True) - sub_view.setAttribute(QtCore.Qt.WA_DeleteOnClose) - sub_view.setWindowTitle(self.current_node_name) - # try to resize to a width that doesn't need an horizontal scrollbar - sub_view.resize( - cwidget.controller_widget.parent().parent().sizeHint().width(), - sub_view.sizeHint().height()) - sub_view.show() - # set self.window() as QObject parent (not QWidget parent) to - # prevent the sub_view to close/delete immediately - QtCore.QObject.setParent(sub_view, self.window())
- - -
-[docs] - def open_node_menu(self, node_name, process): - """ right-click popup menu for nodes - """ - node_name = six.text_type(node_name) # in case it is a QString - node_type = 'process' - if isinstance(process, OptionalOutputSwitch): - node_type = 'opt. output switch' - elif isinstance(process, Switch): - node_type = 'switch' - menu = QtGui.QMenu('Node: %s' % node_name, None) - title = menu.addAction('Node: %s (%s)' % (node_name, node_type)) - title.setEnabled(False) - menu.addSeparator() - - self.current_node_name = node_name - self.current_process = process - if node_name in ('inputs', 'outputs'): - node_name = '' - node = self.scene.pipeline.nodes[node_name] - - # Input_Filter - if process.name == "Input_Filter": - open_filter = menu.addAction('Open filter') - open_filter.triggered.connect(self.emit_open_filter) - - export_to_db_scans = menu.addAction('Export to database_scans') - export_to_db_scans.triggered.connect(self.emit_export_to_db_scans) - - menu.addSeparator() - - if not self._restricted_edition: - controller_action = QtGui.QAction('open node controller', menu) - controller_action.triggered.connect(self.openProcessController) - menu.addAction(controller_action) - - disable_action = QtGui.QAction('Enable/disable node', menu) - disable_action.setCheckable(True) - disable_action.setChecked(node.enabled) - disable_action.toggled.connect(self.enableNode) - menu.addAction(disable_action) - - steps = getattr(self.scene.pipeline, 'pipeline_steps', None) - if steps is not None: - my_steps = [step_name for step_name in steps.user_traits() - if node.name in steps.trait(step_name).nodes] - for step in my_steps: - step_action = menu.addAction('(enable) step: %s' % step) - step_action.setCheckable(True) - step_state = getattr(self.scene.pipeline.pipeline_steps, step) - step_action.setChecked(step_state) - step_action.toggled.connect(SomaPartial(self.enable_step, - step)) - if len(my_steps) != 0: - step = my_steps[0] - disable_prec = menu.addAction('Disable preceding steps') - disable_prec.triggered.connect(SomaPartial( - self.disable_preceding_steps, step)) - enable_prec = menu.addAction('Enable preceding steps') - enable_prec.triggered.connect(SomaPartial( - self.enable_preceding_steps, step)) - step = my_steps[-1] - disable_foll = menu.addAction('Disable following steps') - disable_foll.triggered.connect(SomaPartial( - self.disable_following_steps, step)) - enable_foll = menu.addAction('Enable following steps') - enable_foll.triggered.connect(SomaPartial( - self.enable_following_steps, step)) - - enable_all_action = menu.addAction('Enable all steps') - enable_all_action.triggered.connect(self.enable_all_steps) - disable_done_action = menu.addAction( - 'Disable steps with existing outputs') - disable_done_action.triggered.connect(self.disable_done_steps) - check_pipeline_action = menu.addAction( - 'Check input / output files') - check_pipeline_action.triggered.connect(self.check_files) - - if isinstance(node, Switch) \ - and not isinstance(node, OptionalOutputSwitch): - # allow to select switch value from the menu - submenu = menu.addMenu('Switch value') - agroup = QtGui.QActionGroup(submenu) - values = node.trait('switch').trait_type.values - value = node.switch - set_index = -1 - for item in values: - action = submenu.addAction(item) - action.setCheckable(True) - action.triggered.connect(SomaPartial( - self.set_switch_value, node, item)) - if item == value: - action.setChecked(True) - - if not self.get_doc_browser(create=False): - menu.addSeparator() - doc_action = menu.addAction('Show doc') - doc_action.triggered.connect(self.show_doc) - - if self.edition_enabled(): - menu.addSeparator() - del_node_action = menu.addAction('Delete node') - del_node_action.triggered.connect(self.del_node) - if node is not self.scene.pipeline.pipeline_node: - export_mandatory_plugs = menu.addAction( - 'Export unconnected mandatory plugs') - export_mandatory_plugs.triggered.connect( - self.export_node_unconnected_mandatory_plugs) - export_all_plugs = menu.addAction( - 'Export all unconnected plugs') - export_all_plugs.triggered.connect( - self.export_node_all_unconnected_plugs) - export_mandatory_inputs = menu.addAction( - 'Export unconnected mandatory inputs') - export_mandatory_inputs.triggered.connect( - self.export_node_unconnected_mandatory_inputs) - export_all_inputs = menu.addAction( - 'Export all unconnected inputs') - export_all_inputs.triggered.connect( - self.export_node_all_unconnected_inputs) - export_mandatory_outputs = menu.addAction( - 'Export unconnected mandatory outputs') - export_mandatory_outputs.triggered.connect( - self.export_node_unconnected_mandatory_outputs) - export_all_outputs = menu.addAction( - 'Export all unconnected outputs') - export_all_outputs.triggered.connect( - self.export_node_all_unconnected_outputs) - step = None - if steps is not None: - my_steps = [step_name for step_name in steps.user_traits() - if node.name in steps.trait(step_name).nodes] - if len(my_steps) == 1: - step = my_steps[0] - elif len(my_steps) >= 2: - step = repr(my_steps) - change_step = menu.addAction('change step: %s' % step) - change_step.triggered.connect(self._change_step) - - # Added to choose to visualize optional parameters - gnode = self.scene.gnodes[self.current_node_name] - - menu.addSeparator() - show_opt_inputs = menu.addAction( - 'Show optional inputs') - show_opt_inputs.setCheckable(True) - show_opt_inputs.triggered.connect( - self.show_optional_inputs - ) - if gnode.show_opt_inputs: - show_opt_inputs.setChecked(True) - - show_opt_outputs = menu.addAction( - 'Show optional outputs') - show_opt_outputs.setCheckable(True) - show_opt_outputs.triggered.connect( - self.show_optional_outputs - ) - if gnode.show_opt_outputs: - show_opt_outputs.setChecked(True) - - # Emit a signal to edit the node if it is a PipelineNode - if isinstance(node, PipelineNode): - menu.addSeparator() - edit_sub_pipeline = menu.addAction('Edit sub-pipeline') - edit_sub_pipeline.triggered.connect(self.emit_edit_sub_pipeline) - - menu.exec_(QtGui.QCursor.pos()) - del self.current_node_name - del self.current_process
- - - def emit_export_to_db_scans(self): - self.export_to_db_scans.emit(self.current_node_name) - - def emit_open_filter(self): - self.open_filter.emit(self.current_node_name) - - def emit_edit_sub_pipeline(self): - node = self.scene.pipeline.nodes[self.current_node_name] - sub_pipeline = node.process - if isinstance(sub_pipeline, weakref.ProxyTypes): - # get the "real" object - sub_pipeline = sub_pipeline.__init__.__self__ - self.edit_sub_pipeline.emit(sub_pipeline) - -
-[docs] - def show_optional_inputs(self): - ''' - Added to choose to visualize optional inputs. - ''' - - gnode = self.scene.gnodes[self.current_node_name] - connected_plugs = [] - - # print(self.current_node_name) - # print(gnode.in_plugs) - - # for source_dest, link in six.iteritems(self.scene.glinks): - # print(source_dest,",",self.current_node_name in str(source_dest)) - - - # The show_opt_inputs attribute is not changed yet - if gnode.show_opt_inputs: - # Verifying that the plugs are not connected to another node - for param, pipeline_plug in six.iteritems(gnode.parameters): - # print(param," : ",pipeline_plug.activated) - output = (not pipeline_plug.output if gnode.name in ( - 'inputs', 'outputs') else pipeline_plug.output) - if not output: - if pipeline_plug.optional and pipeline_plug.links_from and gnode.show_opt_inputs : - connected_plugs.append(param) - if connected_plugs: - if len(connected_plugs) == 1: - text = "Please remove links from this plug:\n" - else: - text = "Please remove links from these plugs:\n" - for plug_name in connected_plugs: - text += plug_name + ", " - text = text[:-2] + '.' - - msg = QMessageBox() - msg.setIcon(QMessageBox.Critical) - msg.setText(text) - msg.setWindowTitle("Error while changing the view of the node") - msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel) - msg.exec_() - return - - # Changing the show_opt_outputs attribute - gnode.change_input_view() - self.scene.update_pipeline()
- - -
-[docs] - def show_optional_outputs(self): - ''' - Added to choose to visualize optional outputs. - ''' - - gnode = self.scene.gnodes[self.current_node_name] - connected_plugs = [] - - # The show_opt_outputs attribute is not changed yet - if gnode.show_opt_outputs: - # Verifying that the plugs are not connected to another node - for param, pipeline_plug in six.iteritems(gnode.parameters): - output = (not pipeline_plug.output if gnode.name in ( - 'inputs', 'outputs') else pipeline_plug.output) - if output: - if pipeline_plug.optional and pipeline_plug.links_to and gnode.show_opt_outputs: - connected_plugs.append(param) - if connected_plugs: - if len(connected_plugs) == 1: - text = "Please remove links from this plug:\n" - else: - text = "Please remove links from these plugs:\n" - for plug_name in connected_plugs: - text += plug_name + ", " - text = text[:-2] + '.' - - msg = QMessageBox() - msg.setIcon(QMessageBox.Critical) - msg.setText(text) - msg.setWindowTitle("Error while changing the view of the node") - msg.setStandardButtons(QMessageBox.Ok | QMessageBox.Cancel) - msg.exec_() - return - - # Changing the show_opt_outputs attribute - gnode.change_output_view() - self.scene.update_pipeline()
- - -
-[docs] - def open_background_menu(self): - ''' - Open the right-click menu when triggered from the pipeline background. - ''' - self.click_pos = QtGui.QCursor.pos() - has_dot = shutil.which('dot') - menu = QtGui.QMenu('Pipeline level menu', None) - title = menu.addAction('Pipeline level menu') - title.setEnabled(False) - menu.addSeparator() - - if self.is_logical_view(): - logical_view = menu.addAction('Switch to regular parameters view') - else: - logical_view = menu.addAction('Switch to logical pipeline view') - logical_view.triggered.connect(self.switch_logical_view) - auto_node_pos = menu.addAction('Auto arrange nodes positions') - auto_node_pos.triggered.connect(self.auto_dot_node_positions) - if not has_dot: - auto_node_pos.setEnabled(False) - auto_node_pos.setText( - 'Auto arrange nodes positions (needs graphviz/dot tool ' - 'installed)') - init_node_pos = menu.addAction('Reset to initial nodes positions') - init_node_pos.triggered.connect(self.reset_initial_nodes_positions) - if not hasattr(self.scene.pipeline, 'node_position') \ - or len(self.scene.pipeline.node_position) == 0: - init_node_pos.setEnabled(False) - init_node_pos.setText( - 'Reset to initial nodes positions (none defined') - save_dot = menu.addAction('Save image of pipeline graph') - save_dot.triggered.connect(self.save_dot_image_ui) - if not has_dot: - save_dot.setEnabled(False) - save_dot.setText( - 'Save image of pipeline graph (needs graphviz/dot tool ' - 'installed)') - menu.addSeparator() - print_pos = menu.addAction('Print nodes positions') - print_pos.triggered.connect(self.print_node_positions) - - if self._enable_edition: - menu.addSeparator() - if not self._restricted_edition: - add_proc = menu.addAction('Add process in pipeline') - add_proc.triggered.connect(self.add_process) - add_switch = menu.addAction('Add switch in pipeline') - add_switch.triggered.connect(self.add_switch) - add_optional_output_switch = menu.addAction( - 'Add optional output switch in pipeline') - add_optional_output_switch.triggered.connect( - self.add_optional_output_switch) - add_iter_proc = menu.addAction('Add iterative process in pipeline') - add_iter_proc.triggered.connect(self.add_iterative_process) - add_node = menu.addAction('Add custom node in pipeline') - add_node.triggered.connect(self.add_node) - - menu.addSeparator() - export_mandatory_plugs = menu.addAction( - 'Export unconnected mandatory plugs') - export_mandatory_plugs.triggered.connect( - self.export_unconnected_mandatory_plugs) - export_all_plugs = menu.addAction( - 'Export all unconnected plugs') - export_all_plugs.triggered.connect( - self.export_all_unconnected_plugs) - export_mandatory_inputs = menu.addAction( - 'Export unconnected mandatory inputs') - export_mandatory_inputs.triggered.connect( - self.export_unconnected_mandatory_inputs) - export_all_inputs = menu.addAction( - 'Export all unconnected inputs') - export_all_inputs.triggered.connect( - self.export_all_unconnected_inputs) - export_mandatory_outputs = menu.addAction( - 'Export unconnected mandatory outputs') - export_mandatory_outputs.triggered.connect( - self.export_unconnected_mandatory_outputs) - export_all_outputs = menu.addAction( - 'Export all unconnected outputs') - export_all_outputs.triggered.connect( - self.export_all_unconnected_outputs) - prune = menu.addAction('Prune unused pipeline plugs') - prune.triggered.connect(self._prune_plugs) - - menu.addSeparator() - new_pipeline = menu.addAction('New pipeline (clear current)') - new_pipeline.triggered.connect(self.new_pipeline) - load_pipeline = menu.addAction('Load pipeline (clear current)') - load_pipeline.triggered.connect(self.load_pipeline) - save_parameters = menu.addAction('Save pipeline parameters') - save_parameters.triggered.connect(self.save_pipeline_parameters) - load_parameters = menu.addAction('Load pipeline parameters') - load_parameters.triggered.connect(self.load_pipeline_parameters) - - menu.addSeparator() - save = menu.addAction('Save pipeline') - save.triggered.connect(self.save_pipeline) - - menu.exec_(QtGui.QCursor.pos()) - del self.click_pos
- - -
-[docs] - def enableNode(self, checked): - if self.current_node_name in ['inputs', 'outputs']: - node_name = '' - else: - node_name = self.current_node_name - self.scene.pipeline.nodes[node_name].enabled = checked
- - -
-[docs] - def enable_step(self, step_name, state): - setattr(self.scene.pipeline.pipeline_steps, step_name, state)
- - -
-[docs] - def disable_preceding_steps(self, step_name, dummy): - # don't know why we get this additional dummy parameter (False) - steps = self.scene.pipeline.pipeline_steps - for step in steps.user_traits(): - if step == step_name: - break - setattr(steps, step, False)
- - -
-[docs] - def disable_following_steps(self, step_name, dummy): - steps = self.scene.pipeline.pipeline_steps - found = False - for step in steps.user_traits(): - if found: - setattr(steps, step, False) - elif step == step_name: - found = True
- - -
-[docs] - def enable_preceding_steps(self, step_name, dummy): - steps = self.scene.pipeline.pipeline_steps - for step in steps.user_traits(): - if step == step_name: - break - setattr(steps, step, True)
- - -
-[docs] - def enable_following_steps(self, step_name, dummy): - steps = self.scene.pipeline.pipeline_steps - found = False - for step in steps.user_traits(): - if found: - setattr(steps, step, True) - elif step == step_name: - found = True
- - -
-[docs] - def set_switch_value(self, switch, value, dummy): - switch.switch = value
- - -
-[docs] - def disable_done_steps(self): - pipeline_tools.disable_runtime_steps_with_existing_outputs( - self.scene.pipeline)
- - -
-[docs] - def enable_all_steps(self): - self.scene.pipeline.enable_all_pipeline_steps()
- - -
-[docs] - def check_files(self): - overwritten_outputs = pipeline_tools.nodes_with_existing_outputs( - self.scene.pipeline) - missing_inputs = pipeline_tools.nodes_with_missing_inputs( - self.scene.pipeline) - if len(overwritten_outputs) == 0 and len(missing_inputs) == 0: - QtGui.QMessageBox.information( - self, 'Pipeline ready', 'All input files are available. ' - 'No output file will be overwritten.') - else: - dialog = QtGui.QWidget() - layout = QtGui.QVBoxLayout(dialog) - warn_widget = PipelineFileWarningWidget( - missing_inputs, overwritten_outputs) - layout.addWidget(warn_widget) - hlay = QtGui.QHBoxLayout() - layout.addLayout(hlay) - hlay.addStretch() - ok = QtGui.QPushButton('OK') - self.ok_button = ok - hlay.addWidget(ok) - ok.clicked.connect(dialog.close) - dialog.show() - self._warn_files_widget = dialog
- - -
-[docs] - def auto_dot_node_positions(self): - ''' - Calculate pipeline nodes positions using graphviz/dot, and place the - pipeline view nodes accordingly. - ''' - scene = self.scene - scale = 67. # dpi - nodes_sizes = dict([(name, - (gnode.boundingRect().width(), - gnode.boundingRect().height())) - for name, gnode in six.iteritems(scene.gnodes)]) - dgraph = pipeline_tools.dot_graph_from_pipeline( - scene.pipeline, nodes_sizes=nodes_sizes) - tfile, tfile_name = tempfile.mkstemp() - os.close(tfile) - pipeline_tools.save_dot_graph(dgraph, tfile_name) - toutfile, toutfile_name = tempfile.mkstemp() - os.close(toutfile) - try: - cmd = ['dot', '-Tplain', '-o', toutfile_name, tfile_name] - try: - soma.subprocess.check_call(cmd) - except FileNotFoundError: - # dot is not installed in the PATH. Give up - return - - nodes_pos = self._read_dot_pos(toutfile_name) - - rects = dict([(name, node.boundingRect()) - for name, node in six.iteritems(scene.gnodes)]) - pos = dict([(name, (-rects[name].width() / 2 + pos[0] * scale, - -rects[name].height() / 2 - pos[1] * scale)) - for id, name, pos in nodes_pos]) - minx = min([x[0] for x in six.itervalues(pos)]) - miny = min([x[1] for x in six.itervalues(pos)]) - pos = dict([(name, (p[0] - minx, p[1] - miny)) - for name, p in six.iteritems(pos)]) - # print('pos:') - # print(pos) - scene.pos = pos - for node, position in six.iteritems(pos): - gnode = scene.gnodes[node] - if isinstance(position, Qt.QPointF): - gnode.setPos(position) - else: - gnode.setPos(*position) - - finally: - os.unlink(tfile_name) - os.unlink(toutfile_name)
- - - def _read_dot_pos(self, filename): - ''' - Read the nodes positions from a file generated by graphviz/dot, in - "plain" text format. - - Returns - ------- - nodes_pos: dict - keys are nodes IDs (names), and values are 2D positions - ''' - fileobj = open(filename) - nodes_pos = [] - if sys.version_info[0] >= 3: - file_iter = fileobj.readlines() - else: - file_iter = fileobj - for line in file_iter: - if line.startswith('node'): - line_els0 = line.split() - line_els = [] - for el in line_els0: - if el.startswith('"') and el.endswith('"'): - line_els.append(el[1:-1]) - else: - line_els.append(el) - id = line_els[1] - pos = tuple([float(x) for x in line_els[2:4]]) - name = line_els[6] - nodes_pos.append((id, name, pos)) - elif line.startswith('edge'): - break - return nodes_pos - -
-[docs] - def save_dot_image_ui(self): - ''' - Ask for a filename using the file dialog, and save a graphviz/dot - representation of the pipeline. - The pipeline representation follows the current visualization mode - ("regular" or "logical" with smaller boxes) with one link of a given - type (active, weak) between two given boxes: all parameters are not - represented. - ''' - file_dialog = QtGui.QFileDialog(filter='Images (*.png *.xpm *.jpg *.ps *.eps);; All (*)') - file_dialog.setDefaultSuffix('.png') - file_dialog.setFileMode(QtGui.QFileDialog.AnyFile) - file_dialog.setAcceptMode(QtGui.QFileDialog.AcceptSave) - if file_dialog.exec_(): - filename = file_dialog.selectedFiles() - - '''filename = QtGui.QFileDialog.getSaveFileName( - None, 'Save image of the pipeline', '', - 'Images (*.png *.xpm *.jpg *.ps *.eps);; All (*)')''' - if filename: - pipeline_tools.save_dot_image(self.scene.pipeline, filename[0])
- - -
-[docs] - def reset_initial_nodes_positions(self): - ''' - Set each pipeline node to its "saved" position, ie the one which may - be found in the "node_position" variable of the pipeline. - ''' - scene = self.scene - if scene.pipeline is None: - return - -# ############## add by Irmage OM ################### -# dim = getattr(scene.pipeline, 'node_dimension') -# if dim is not None: -# scene.dim = dim -# print() -# for node, dimension in six.iteritems(dim): -# gnode = scene.gnodes.get(node) -# if gnode is not None: -# if isinstance(dimension, QtCore.QPointF): -# dimension = (dim.x(),dim.y()) -# # else: -# # dimension = dim.width(),dim.height() -# gnode.update(0,0,*dimension) -# ##################################################### - - pos = getattr(scene.pipeline, 'node_position') - if pos is not None: - scene.pos = pos - for node, position in six.iteritems(pos): - gnode = scene.gnodes.get(node) - if gnode is not None: - if isinstance(position, QtCore.QPointF): - position = (position.x(), position.y()) - gnode.setPos(*position)
- - - - - def switch_logical_view(self): - self.set_logical_view(not self.is_logical_view()) - - def print_node_positions(self): - def conv_pos(p): - if isinstance(p, Qt.QPointF): - return (p.x(), p.y()) - return p - - posdict = dict([(key, conv_pos(value)) \ - for key, value in six.iteritems(self.scene.pos)]) - pprint(posdict) - - def del_node(self, node_name=None): - - pipeline = self.scene.pipeline - - if not node_name: - node_name = self.current_node_name - if node_name not in ('inputs', 'outputs'): - node = pipeline.nodes[node_name] - pipeline.remove_node(node_name) - elif node_name in self.scene.gnodes: - # delete all input or output export plugs in the pipeline - if node_name == 'inputs': - plugs = [name - for name, plug in - six.iteritems(pipeline.pipeline_node.plugs) - if not plug.output] - else: - plugs = [name - for name, plug in - six.iteritems(pipeline.pipeline_node.plugs) - if plug.output] - for plug in plugs: - self.scene.pipeline.remove_trait(plug) - - self.scene.pipeline.update_nodes_and_plugs_activation() - - def export_node_plugs(self, node_name, inputs=True, outputs=True, - optional=False): - pipeline = self.scene.pipeline - node = pipeline.nodes[node_name] - for parameter_name, plug in six.iteritems(node.plugs): - if parameter_name in ("nodes_activation", "selection_changed"): - continue - if (((node_name, parameter_name) not in pipeline.do_not_export and - ((outputs and plug.output and not plug.links_to) or - (inputs and not plug.output and not plug.links_from)) and - (optional or not node.get_trait(parameter_name).optional))): - pipeline.export_parameter(node_name, parameter_name) - - def export_plugs(self, inputs=True, outputs=True, optional=False): - for node_name in self.scene.pipeline.nodes: - if node_name != "": - self.export_node_plugs(node_name, inputs=inputs, - outputs=outputs, optional=optional) - - def export_node_unconnected_mandatory_plugs(self): - self.export_node_plugs(self.current_node_name) - - def export_node_all_unconnected_plugs(self): - self.export_node_plugs(self.current_node_name, optional=True) - - def export_node_unconnected_mandatory_inputs(self): - self.export_node_plugs( - self.current_node_name, inputs=True, outputs=False) - - def export_node_all_unconnected_inputs(self): - self.export_node_plugs( - self.current_node_name, inputs=True, outputs=False, optional=True) - - def export_node_unconnected_mandatory_outputs(self): - self.export_node_plugs( - self.current_node_name, inputs=False, outputs=True) - - def export_node_all_unconnected_outputs(self): - self.export_node_plugs( - self.current_node_name, inputs=False, outputs=True, optional=True) - - def export_unconnected_mandatory_plugs(self): - self.export_plugs() - - def export_all_unconnected_plugs(self): - self.export_plugs(optional=True) - - def export_unconnected_mandatory_inputs(self): - self.export_plugs(inputs=True, outputs=False) - - def export_all_unconnected_inputs(self): - self.export_plugs(inputs=True, outputs=False, optional=True) - - def export_unconnected_mandatory_outputs(self): - self.export_plugs(inputs=False, outputs=True) - - def export_all_unconnected_outputs(self): - self.export_plugs(inputs=False, outputs=True, optional=True) - - def _change_step(self): - node_name = self.current_node_name - node = self.scene.pipeline.nodes[node_name] - steps = getattr(self.scene.pipeline, 'pipeline_steps', None) - steps_defined = True - if steps is None: - steps = Controller() - steps_defined = False - - wid = Qt.QDialog() - wid.setModal(True) - lay = Qt.QVBoxLayout() - wid.setLayout(lay) - - listw = Qt.QListWidget() - listw.setSelectionMode(listw.MultiSelection) - lay.addWidget(listw) - n = 0 - for step in steps.user_traits(): - listw.addItem(step) - nodes = steps.trait(step).nodes - if node_name in nodes: - item = listw.item(n) - item.setSelected(True) - n += 1 - addlay = Qt.QHBoxLayout() - lay.addLayout(addlay) - addb = Qt.QPushButton('+') - addlay.addWidget(addb) - remb = Qt.QPushButton('-') - addlay.addWidget(remb) - - def add_clicked(): - d = Qt.QDialog() - d.setModal(True) - la = Qt.QHBoxLayout() - d.setLayout(la) - l = Qt.QLineEdit() - la.addWidget(l) - l.returnPressed.connect(d.accept) - r = d.exec_() - if r: - name = l.text() - if name not in steps.user_traits(): - n = listw.count() - listw.addItem(name) - listw.item(n).setSelected(True) - - def remove_clicked(): - selected = [] - for i in range(listw.count()): - item = listw.item(i) - if item.isSelected(): - selected.append((i, item.text())) - if len(selected) != 0: - r = Qt.QMessageBox.question( - wid, 'remove steps', - 'remove the following steps from the whole pipeline ?\n%s' - % repr([s[1] for s in selected])) - if r == Qt.QMessageBox.Yes: - for s in reversed(selected): - listw.takeItem(s[0]) - - def up_clicked(): - selected = [] - for i in range(listw.count()): - item = listw.item(i) - if item.isSelected(): - selected.append(i) - if len(selected) != 0 and selected[0] != 0: - for i in selected: - item = listw.takeItem(i) - listw.insertItem(i-1, item) - item.setSelected(True) - - def down_clicked(): - selected = [] - for i in range(listw.count()): - item = listw.item(i) - if item.isSelected(): - selected.append(i) - if len(selected) != 0 and selected[-1] != listw.count() - 1: - for i in reversed(selected): - item = listw.takeItem(i) - listw.insertItem(i + 1, item) - item.setSelected(True) - - addb.clicked.connect(add_clicked) - remb.clicked.connect(remove_clicked) - up = Qt.QPushButton('^') - addlay.addWidget(up) - down = Qt.QPushButton('v') - addlay.addWidget(down) - up.clicked.connect(up_clicked) - down.clicked.connect(down_clicked) - - oklay = Qt.QHBoxLayout() - lay.addLayout(oklay) - ok = Qt.QPushButton('OK') - oklay.addWidget(ok) - cancel = Qt.QPushButton('Cancel') - oklay.addWidget(cancel) - ok.clicked.connect(wid.accept) - cancel.clicked.connect(wid.reject) - - res = wid.exec_() - if res: - items = set() - sitems = [] - for i in range(listw.count()): - item = listw.item(i) - name = item.text() - sel = item.isSelected() - items.add(name) - sitems.append(name) - trait = steps.trait(name) - if sel: - if trait is None: - self.scene.pipeline.add_pipeline_step( - name, [node_name]) - steps = self.scene.pipeline.pipeline_steps - else: - nodes = steps.trait(name).nodes - if node_name not in nodes: - nodes.append(node_name) - elif trait is not None: - if node_name in trait.nodes: - trait.nodes.remove(node_name) - steps = list(steps.user_traits().keys()) - for step in steps: - if step not in items: - self.scene.pipeline.remove_pipeline_step(step) - # reorder traits if needed - steps = self.scene.pipeline.pipeline_steps - if list(steps.user_traits().keys()) != sitems: - values = [steps.trait(step).nodes for step in sitems] - for step in sitems: - steps.remove_trait(step) - for step, nodes in zip(sitems, values): - self.scene.pipeline.add_pipeline_step(step, nodes) - - self.scene.update_pipeline() - - -
-[docs] - class ProcessModuleInput(QtGui.QDialog): - def __init__(self, display_str='process module/name', - class_type_check=process_instance.is_process): - super(PipelineDeveloperView.ProcessModuleInput, self).__init__() - self.setWindowTitle('%s:' % display_str) - layout = QtGui.QGridLayout(self) - layout.addWidget(QtGui.QLabel('module/process:'), 0, 0) - self.proc_line = PipelineDeveloperView.ProcessNameEdit( - class_type_check=class_type_check) - layout.addWidget(self.proc_line, 0, 1) - layout.addWidget(QtGui.QLabel('node name'), 1, 0) - self.name_line = QtGui.QLineEdit() - layout.addWidget(self.name_line, 1, 1) - # hlay = QtGui.QHBoxLayout() - # layout.addLayout(hlay, 1, 1) - ok = QtGui.QPushButton('OK') - layout.addWidget(ok, 2, 0) - cancel = QtGui.QPushButton('Cancel') - layout.addWidget(cancel, 2, 1) - ok.clicked.connect(self.accept) - cancel.clicked.connect(self.reject)
- - -
-[docs] - def add_process(self): - ''' - Insert a process node in the pipeline. Asks for the process - module/name, and the node name before inserting. - ''' - - proc_name_gui = PipelineDeveloperView.ProcessModuleInput() - proc_name_gui.resize(800, proc_name_gui.sizeHint().height()) - - res = proc_name_gui.exec_() - if res: - proc_module = six.text_type(proc_name_gui.proc_line.text()) - node_name = str(proc_name_gui.name_line.text()) - self.add_named_process(proc_module, node_name)
- - - def add_named_process(self, proc_module, node_name=None): - pipeline = self.scene.pipeline - - if not node_name: - if isinstance(proc_module, six.string_types): - class_name = proc_module - else: - class_name = proc_module.__name__ - i = 1 - node_name = '%s_%d' % (class_name.lower(), i) - - while node_name in pipeline.nodes and i < 100: - i += 1 - node_name = '%s_%d' % (class_name.lower(), i) - - engine = pipeline.get_study_config().engine - try: - process = engine.get_process_instance(proc_module) - except Exception: - traceback.print_exc() - return - pipeline.add_process(node_name, process) - - node = pipeline.nodes[node_name] - gnode = self.scene.add_node(node_name, node) - gnode.setPos(self.mapToScene(self.mapFromGlobal(self.click_pos))) - - return process - -
-[docs] - def add_node(self): - ''' - Insert a custom node in the pipeline. Asks for the node - module/name, and the node name before inserting. - ''' - - def is_pipeline_node(item): - return item is not Node and isinstance(item, Node) - - node_name_gui = PipelineDeveloperView.ProcessModuleInput( - display_str='node module/name', class_type_check=is_pipeline_node) - node_name_gui.resize(800, node_name_gui.sizeHint().height()) - - res = node_name_gui.exec_() - if res: - node_module = six.text_type(node_name_gui.proc_line.text()) - node_name = str(node_name_gui.name_line.text()) - self.add_named_node(node_name, node_module)
- - - def add_named_node(self, node_name, node_module): - def configure_node(cls): - conf_controller = cls.configure_controller() - w = Qt.QDialog() - w.setWindowTitle('Custom node parameterization') - l = Qt.QVBoxLayout() - w.setLayout(l) - c = ScrollControllerWidget(conf_controller, live=True) - l.addWidget(c) - h = Qt.QHBoxLayout() - l.addLayout(h) - ok = Qt.QPushButton('OK') - h.addWidget(ok) - cancel = Qt.QPushButton('Cancel') - h.addWidget(cancel) - ok.clicked.connect(w.accept) - cancel.clicked.connect(w.reject) - res = w.exec_() - if res: - c.update_controller() - return conf_controller - else: - return None - - def get_node_instance(class_str, pipeline): - cls_and_name = process_instance.get_node_class(class_str) - if cls_and_name is None: - return None - name, cls = cls_and_name - if hasattr(cls, 'configure_controller'): - conf_controller = configure_node(cls) - if conf_controller is None: - return None # abort - else: - conf_controller = Controller() - if hasattr(cls, 'build_node'): - node = cls.build_node(pipeline, name, conf_controller) - else: - # probably bound to fail... - node = cls(pipeline, name, [], []) - return node - - pipeline = self.scene.pipeline - try: - node = get_node_instance(node_module, pipeline) - except Exception as e: - print(e) - return - if node is None: - return - - if not node_name and node: - class_name = node.__class__.__name__ - i = 1 - node_name = '%s_%d' % (class_name.lower(), i) - - while node_name in pipeline.nodes and i < 100: - i += 1 - node_name = '%s_%d' % (class_name.lower(), i) - - pipeline.nodes[node_name] = node - pipeline._set_subprocess_context_name(node, node_name) - - gnode = self.scene.add_node(node_name, node) - gnode.setPos(self.mapToScene(self.mapFromGlobal(self.click_pos))) - -
-[docs] - class IterativeProcessInput(ProcessModuleInput): - def __init__(self, engine): - super(PipelineDeveloperView.IterativeProcessInput, - self).__init__() - # hlay = Qt.QHBoxLayout() - # self.layout().addLayout(hlay) - lay = self.layout() - item = lay.itemAtPosition(2, 0) - widget = item.widget() - lay.removeItem(item) - lay.addWidget(widget, 3, 0) - item = lay.itemAtPosition(2, 1) - widget = item.widget() - lay.removeItem(item) - lay.addWidget(widget, 3, 1) - lay.addWidget(Qt.QLabel('iterative plugs:'), 2, 0) - self.plugs = Qt.QListWidget() - self.plugs.setEditTriggers(Qt.QListWidget.NoEditTriggers) - self.plugs.setSelectionMode(Qt.QListWidget.ExtendedSelection) - lay.addWidget(self.plugs, 2, 1) - self.proc_line.textChanged.connect(self.set_plugs) - # self.proc_line.editingFinished.connect(self.set_plugs) - self.engine = engine - - def set_plugs(self, text): - self.plugs.clear() - try: - process = self.engine.get_process_instance(text) - except Exception: - return - traits = list(process.user_traits().keys()) - self.plugs.addItems(traits) - - def iterative_plugs(self): - return [item.text() for item in self.plugs.selectedItems()]
- - -
-[docs] - def add_iterative_process(self): - ''' - Insert an iterative process node in the pipeline. Asks for the process - module/name, the node name, and iterative plugs before inserting. - ''' - pipeline = self.scene.pipeline - engine = pipeline.get_study_config().engine - proc_name_gui = PipelineDeveloperView.IterativeProcessInput(engine) - proc_name_gui.resize(800, proc_name_gui.sizeHint().height()) - - res = proc_name_gui.exec_() - if res: - proc_module = six.text_type(proc_name_gui.proc_line.text()) - node_name = str(proc_name_gui.name_line.text()) - try: - process = engine.get_process_instance( - six.text_type(proc_name_gui.proc_line.text())) - except Exception as e: - print(e) - return - iterative_plugs = proc_name_gui.iterative_plugs() - do_not_export = list(process.user_traits().keys()) - pipeline.add_iterative_process(node_name, process, iterative_plugs, - do_not_export=do_not_export) - - node = pipeline.nodes[node_name] - gnode = self.scene.add_node(node_name, node) - gnode.setPos(self.mapToScene(self.mapFromGlobal(self.click_pos)))
- - -
-[docs] - def add_switch(self): - ''' - Insert a switch node in the pipeline. Asks for the switch - inputs/outputs, and the node name before inserting. - ''' - - class SwitchInput(QtGui.QDialog): - def __init__(self): - super(SwitchInput, self).__init__() - self.setWindowTitle('switch parameters/name:') - layout = QtGui.QGridLayout(self) - layout.addWidget(QtGui.QLabel('inputs:'), 0, 0) - self.inputs_line = QtGui.QLineEdit() - layout.addWidget(self.inputs_line, 0, 1) - layout.addWidget(QtGui.QLabel('outputs:'), 1, 0) - self.outputs_line = QtGui.QLineEdit() - layout.addWidget(self.outputs_line, 1, 1) - layout.addWidget(QtGui.QLabel('node name'), 2, 0) - self.name_line = QtGui.QLineEdit() - layout.addWidget(self.name_line, 2, 1) - ok = QtGui.QPushButton('OK') - layout.addWidget(ok, 3, 0) - cancel = QtGui.QPushButton('Cancel') - layout.addWidget(cancel, 3, 1) - ok.clicked.connect(self.accept) - cancel.clicked.connect(self.reject) - - switch_name_gui = SwitchInput() - switch_name_gui.resize(600, switch_name_gui.sizeHint().height()) - - res = switch_name_gui.exec_() - if res: - pipeline = self.scene.pipeline - node_name = str(switch_name_gui.name_line.text()).strip() - inputs = str(switch_name_gui.inputs_line.text()).split() - outputs = str(switch_name_gui.outputs_line.text()).split() - pipeline.add_switch(node_name, inputs, outputs) - # add_switch triggers an update - gnode = self.scene.gnodes[node_name] - gnode.setPos(self.mapToScene(self.mapFromGlobal(self.click_pos)))
- - -
-[docs] - def add_optional_output_switch(self): - ''' - Insert an optional output switch node in the pipeline. Asks for the - switch inputs/outputs, and the node name before inserting. - ''' - - class SwitchInput(QtGui.QDialog): - def __init__(self): - super(SwitchInput, self).__init__() - self.setWindowTitle('switch parameters/name:') - layout = QtGui.QGridLayout(self) - layout.addWidget(QtGui.QLabel('input:'), 0, 0) - self.inputs_line = QtGui.QLineEdit() - layout.addWidget(self.inputs_line, 0, 1) - layout.addWidget(QtGui.QLabel('output:'), 1, 0) - self.outputs_line = QtGui.QLineEdit() - layout.addWidget(self.outputs_line, 1, 1) - layout.addWidget(QtGui.QLabel('node name'), 2, 0) - self.name_line = QtGui.QLineEdit() - layout.addWidget(self.name_line, 2, 1) - ok = QtGui.QPushButton('OK') - layout.addWidget(ok, 3, 0) - cancel = QtGui.QPushButton('Cancel') - layout.addWidget(cancel, 3, 1) - ok.clicked.connect(self.accept) - cancel.clicked.connect(self.reject) - - switch_name_gui = SwitchInput() - switch_name_gui.resize(600, switch_name_gui.sizeHint().height()) - - res = switch_name_gui.exec_() - if res: - pipeline = self.scene.pipeline - node_name = str(switch_name_gui.name_line.text()).strip() - input = str(switch_name_gui.inputs_line.text()).strip() - output = str(switch_name_gui.outputs_line.text()).strip() - if output == '' and node_name != '': - output = node_name - elif output != '' and node_name == '': - node_name = output - pipeline.add_optional_output_switch(node_name, input, output) - # add_optional_output_switch does *not* trigger an update - self._reset_pipeline() - gnode = self.scene.gnodes[node_name] - gnode.setPos(self.mapToScene(self.mapFromGlobal(self.click_pos)))
- - - def _plug_clicked(self, name): - if self.is_logical_view() or not self.edition_enabled(): - # in logival view, links are not editable since they do not reflect - # the details of reality - return - node_name, plug_name = str(name).split(':') - plug_name = str(plug_name) - gnode = self.scene.gnodes[node_name] - plug = gnode.out_plugs.get(plug_name) - - typeq = self.scene.typeLink(node_name, plug_name) - try: - # color = self.scene.colorLink(typeq) - color = self.scene.colType.colorLink(typeq) - - except Exception: - color = ORANGE_2 - if not plug: - return # probably an input plug - plug_pos = plug.mapToScene(plug.mapFromParent(plug.get_plug_point())) - self._grabpos = self.mapFromScene(plug_pos) - self._temp_link = Link( - plug_pos, - self.mapToScene(self.mapFromGlobal(QtGui.QCursor.pos())), - True, False, color) - self._temp_link.pen.setBrush(RED_2) - self.scene.addItem(self._temp_link) - - self._grab_link = True - self._grabbed_plug = (node_name, plug_name) - - def _move_grab_link(self, event): - pos = self.mapToScene(event.pos()) - self._temp_link.update(self.mapToScene(self._grabpos), pos) - - def _release_grab_link(self, event, ret=False): - max_square_dist = 100. - self._grab_link = False - # delete the temp link - self.scene.removeItem(self._temp_link) - del self._temp_link - pos = self.mapToScene(event.pos()) - item = self.scene.itemAt(pos, Qt.QTransform()) - plug = None - if isinstance(item, Link): - # look for its dest plug - plug = None - for source_dest, link in six.iteritems(self.scene.glinks): - if link is item: - plug = source_dest[1] - break - if plug is not None: - # check the plug is not too far from the drop point - gnode = self.scene.gnodes[plug[0]] - gplug = gnode.in_plugs[plug[1]] - plug_pos = gplug.mapToScene( - gplug.mapFromParent(gplug.get_plug_point())) - pdiff = plug_pos - pos - dist2 = pdiff.x() * pdiff.x() + pdiff.y() * pdiff.y() - if dist2 > max_square_dist: - plug = None - elif isinstance(item, Plug): - plug = str(item.name).split(':') - if plug is not None: - if self._grabbed_plug[0] not in ('', 'inputs'): - src = '%s.%s' % self._grabbed_plug - else: - src = self._grabbed_plug[1] - if plug[0] not in ('', 'outputs'): - dst = '%s.%s' % tuple(plug) - else: - dst = plug[1] - # if (src != dst) and ("inputs."+src != dst) and not self.isInputYet(dst) : - - if (src != dst) and ("inputs." + src != dst): - self.scene.pipeline.add_link('%s->%s' % (src, dst)) - self.scene.update_pipeline() - - if ret: - self._grabbed_plug = None - return '%s->%s' % (src, dst) - self._grabbed_plug = None - - # def isInputYet(self,dest):##################################################################### add by OM - # for listK in self.scene.glinks.keys(): - # if ( eval(str(eval(str(listK))[1]))[0]+"."+ eval(str(eval(str(listK))[1]))[1]==dest or eval(str(eval(str(listK))[1]))[0]+"."+ eval(str(eval(str(listK))[1]))[1]=="outputs."+dest): - # print("input '",dest, "' already used !!") - # return True - # return False - - def _node_delete_clicked(self, name_node): - self.current_node_name = name_node - self.del_node() - - - def _link_delete_clicked(self, src_node, src_plug, dst_node, dst_plug): - src_node = str(src_node) - src_plug = str(src_plug) - dst_node = str(dst_node) - dst_plug = str(dst_plug) - - # print(src_node,",",src_plug,",",dst_node,",",dst_plug) - - if self.is_logical_view() or not self.edition_enabled(): - # in logical view, links are not real links - return - if src_node in ('', 'inputs'): - src = src_plug - snode = self.scene.pipeline.pipeline_node - else: - src = '%s.%s' % (src_node, src_plug) - snode = self.scene.pipeline.nodes[src_node] - if dst_node in ('', 'outputs'): - dst = dst_plug - dnode = self.scene.pipeline.pipeline_node - else: - dst = '%s.%s' % (dst_node, dst_plug) - dnode = self.scene.pipeline.nodes[dst_node] - name = '%s->%s' % (src, dst) - self._current_link = name # (src_node, src_plug, dst_node, dst_plug) - self._del_link() - del self._current_link - - def _link_clicked(self, src_node, src_plug, dst_node, dst_plug): - src_node = str(src_node) - src_plug = str(src_plug) - dst_node = str(dst_node) - dst_plug = str(dst_plug) - if self.is_logical_view() or not self.edition_enabled(): - # in logical view, links are not real links - return - if src_node in ('', 'inputs'): - src = src_plug - snode = self.scene.pipeline.pipeline_node - else: - src = '%s.%s' % (src_node, src_plug) - snode = self.scene.pipeline.nodes[src_node] - if dst_node in ('', 'outputs'): - dst = dst_plug - dnode = self.scene.pipeline.pipeline_node - else: - dst = '%s.%s' % (dst_node, dst_plug) - dnode = self.scene.pipeline.nodes[dst_node] - name = '%s->%s' % (src, dst) - self._current_link = name # (src_node, src_plug, dst_node, dst_plug) - self._current_link_def = (src_node, src_plug, dst_node, dst_plug) - - menu = QtGui.QMenu('Link: %s' % name) - title = menu.addAction('Link: %s' % name) - title.setEnabled(False) - menu.addSeparator() - - weak = False - splug = snode.plugs[src_plug] - for link in splug.links_to: - if link[0] == dst_node and link[1] == dst_plug: - weak = link[4] - break - weak_action = menu.addAction('Weak link') - weak_action.setCheckable(True) - weak_action.setChecked(bool(weak)) - weak_action.toggled.connect(self._change_weak_link) - - menu.addSeparator() - del_link = menu.addAction('Delete link') - del_link.triggered.connect(self._del_link) - - menu.exec_(QtGui.QCursor.pos()) - del self._current_link - del self._current_link_def - - def get_doc_browser(self, create=False): - doc_browser = self.doc_browser - pv = self - proxy = False - while isinstance(doc_browser, PipelineDeveloperView): - # it's a proxy to a parent view - pv = doc_browser - doc_browser = pv.doc_browser - proxy = True - if doc_browser or not create: - return doc_browser - try: - # use the newer Qt5 QtWebEngine - from soma.qt_gui.qt_backend import QtWebEngine - from soma.qt_gui.qt_backend.QtWebEngineWidgets \ - import QWebEngineView, QWebEnginePage - use_webengine = True - except ImportError as e: - print('\n{}'.format(e)) - try: - from soma.qt_gui.qt_backend import QtWebKit - QWebEngineView = QtWebKit.QWebView - QWebPage = QtWebKit.QWebPage - QWebEnginePage = QWebPage - use_webengine = False - except ImportError as e: - print('\n{}\n\nThe process documentation cannot be ' - 'displayed ...'.format(e)) - return None - self._use_webengine = use_webengine - - class DocBrowser(QWebEngineView): - def __init__(self, pview, *args, **kwargs): - super(DocBrowser, self).__init__(*args, **kwargs) - self.setAttribute(Qt.Qt.WA_DeleteOnClose) - self.pview = pview - - def closeEvent(self, event): - self.pview.doc_browser = None - event.accept() - super(DocBrowser, self).closeEvent(event) - - doc_browser = DocBrowser(pv) # QWebEngineView() - pv.doc_browser = doc_browser - doc_browser.show() - - return doc_browser - - def _node_clicked(self, name, node): - self.show_node_doc(node) - if isinstance(node, Process): - self.process_clicked.emit(name, node) - else: - self.node_clicked.emit(name, node) - - @staticmethod - def get_node_html_doc(node): - doc_path = getattr(node, '_doc_path', None) - if doc_path and os.path.isabs(doc_path): - return doc_path - modname = node.__module__ - init_modname = modname - while True: - mod = sys.modules[modname] - mod_doc_path = getattr(mod, '_doc_path', None) - if mod_doc_path: - if doc_path: - return os.path.join(mod_doc_path, doc_path) - node_type = 'process' - if isinstance(node, Pipeline): - node_type = 'pipeline' - path = os.path.join( - mod_doc_path, node_type, - '%s.html' % '.'.join((node.__module__, - node.__class__.__name__))) - if os.path.exists(path) or path.startswith('http://') \ - or path.startswith('https://'): - return path - # try using the 1st sub-module - modsplit = init_modname.split('.') - if len(modsplit) >= 3: - path = os.path.join( - mod_doc_path, modsplit[1], node_type, - '%s.html' % '.'.join((node.__module__, - node.__class__.__name__))) - if os.path.exists(path) or path.startswith('http://') \ - or path.startswith('https://'): - return path - return None - s = modname.rsplit('.', 1) - if len(s) == 1: - break - modname = s[0] - - def show_doc(self, node_name=None): - pipeline = self.scene.pipeline - if not node_name: - node_name = self.current_node_name - if node_name in ('inputs', 'outputs'): - node = pipeline.pipeline_node - else: - node = pipeline.nodes[node_name] - if isinstance(node, ProcessNode): - node = node.process - doc_browser = self.get_doc_browser(create=True) - self.show_node_doc(node) - - def show_node_doc(self, node): - doc_browser = self.get_doc_browser() - if doc_browser: - doc_path = self.get_node_html_doc(node) - if doc_path: - if not doc_path.startswith('http://') \ - and not doc_path.startswith('https://') \ - and not doc_path.startswith('file://'): - doc_path = 'file://%s' % os.path.abspath(doc_path) - doc_browser.setUrl(Qt.QUrl(doc_path)) - else: - gethelp = getattr(node, 'get_help') - msg = None - if gethelp: - msg = node.get_help(returnhelp=True) - if not msg: - msg = node.getattr(node, '__doc__', None) - if msg: - doc_browser.setContent(Qt.QByteArray(msg.encode('utf-8')), - 'text/plain') - - def _node_clicked_ctrl(self, name, process): - - for source_dest, glink in six.iteritems(self.scene.glinks): - glink.fonced_viewer(False) - # print("source-dest ",source_dest) - if name not in str(source_dest): - glink.fonced_viewer(True) - # else: - # print(source_dest[0]) - for node_name, gnode in six.iteritems(self.scene.gnodes): - # print(" node_name",node_name) - gnode.fonced_viewer(False) - if name not in str(node_name): - gnode.fonced_viewer(True) - - def _change_weak_link(self, weak): - # src_node, src_plug, dst_node, dst_plug = self._current_link - link_def = self._current_link - self.scene.pipeline.remove_link(link_def) - self.scene.pipeline.add_link(link_def, weak_link=weak) - self.scene.update_pipeline() - - def _del_link(self): - print('\nRemoving the link: ', self._current_link) - src_node, src_plug, dst_node, dst_plug = self._current_link_def - link_def = self._current_link - pipeline = self.scene.pipeline - pipeline.remove_link(link_def) - if (src_node in ('', 'inputs') and - len(pipeline.pipeline_node.plugs[src_plug].links_to) == 0): - # remove orphan pipeline plug - pipeline.remove_trait(src_plug) - elif (dst_node in ('', 'outputs') and - len(pipeline.pipeline_node.plugs[dst_plug].links_from) == 0): - # remove orphan pipeline plug - pipeline.remove_trait(dst_plug) - self.scene.update_pipeline() - - def _plug_right_clicked(self, name): - - for node_name, gnode in six.iteritems(self.scene.gnodes): - if node_name in 'inputs': - self.inputYet = True - if node_name in 'outputs': - self.outputYet = False - - if self.is_logical_view() or not self.edition_enabled(): - # in logival view, links are not editable since they do not reflect - # the details of reality - return - node_name, plug_name = str(name).split(':') - plug_name = str(plug_name) - if node_name in ('inputs', 'outputs'): - node = self.scene.pipeline.pipeline_node - else: - node = self.scene.pipeline.nodes[node_name] - plug = node.plugs[plug_name] - output = plug.output - self._temp_node = node - self._temp_plug = plug - self._temp_plug_name = (node_name, plug_name) - - menu = QtGui.QMenu('Plug: %s' % name) - title = menu.addAction('Plug: %s' % name) - title.setEnabled(False) - menu.addSeparator() - - if node_name not in ('inputs', 'outputs'): - # not a main node: allow export - if output: - links = plug.links_to - else: - links = plug.links_from - existing = False - for link in links: - if link[0] == '': - existing = True - break - export_action = menu.addAction('export plug') - export_action.triggered.connect(self._export_plug) - if existing: - export_action.setEnabled(False) - if isinstance(node, ProcessNode) \ - and isinstance(node.process, ProcessIteration): - iter_action = menu.addAction('iterative plug') - iter_action.setCheckable(True) - iter_action.setChecked( - plug_name in node.process.iterative_parameters) - iter_action.toggled[bool].connect(self._change_iterative_plug) - - else: - del_plug = menu.addAction('Remove plug') - del_plug.triggered.connect(self._remove_plug) - edit_plug = menu.addAction('Rename / edit plug') - edit_plug.triggered.connect(self._edit_plug) - - protect_action = menu.addAction('protected') - protect_action.setCheckable(True) - protect_action.setChecked(node.is_parameter_protected(plug_name)) - protect_action.toggled[bool].connect(self._protect_plug) - complete_action = menu.addAction('completion enabled') - complete_action.setCheckable(True) - complete_action.setChecked( - not node.get_trait(plug_name).forbid_completion) - complete_action.toggled[bool].connect(self._enable_plug_completion) - - menu.exec_(QtGui.QCursor.pos()) - del self._temp_plug - del self._temp_plug_name - del self._temp_node - - class _PlugEdit(QtGui.QDialog): - def __init__(self, show_weak=True, parent=None): - super(PipelineDeveloperView._PlugEdit, self).__init__(parent) - layout = QtGui.QVBoxLayout(self) - hlay1 = QtGui.QHBoxLayout() - layout.addLayout(hlay1) - hlay1.addWidget(QtGui.QLabel('Plug name:')) - self.name_line = QtGui.QLineEdit() - hlay1.addWidget(self.name_line) - hlay2 = QtGui.QHBoxLayout() - layout.addLayout(hlay2) - self.optional = QtGui.QCheckBox('Optional') - hlay2.addWidget(self.optional) - if show_weak: - self.weak = QtGui.QCheckBox('Weak link') - hlay2.addWidget(self.weak) - hlay3 = QtGui.QHBoxLayout() - layout.addLayout(hlay3) - ok = QtGui.QPushButton('OK') - hlay3.addWidget(ok) - cancel = QtGui.QPushButton('Cancel') - hlay3.addWidget(cancel) - ok.clicked.connect(self.accept) - cancel.clicked.connect(self.reject) - - def _export_plug(self): - dial = self._PlugEdit() - dial.name_line.setText(self._temp_plug_name[1]) - dial.optional.setChecked(self._temp_plug.optional) - - res = dial.exec_() - if res: - # for node_name, gnode in six.iteritems(self.scene.gnodes): - # print("list Nodes",node_name) - try: - self.scene.pipeline.export_parameter( - self._temp_plug_name[0], self._temp_plug_name[1], - pipeline_parameter=str(dial.name_line.text()), - is_optional=dial.optional.isChecked(), - weak_link=dial.weak.isChecked()) - # print(str(dial.name_line.text())) - # self.scene.gnodes.changeHmin(15) - except Exception as e: - print('exception while export plug:', e) - pass - - self.scene.update_pipeline() - - def _change_iterative_plug(self, checked): - node = self._temp_node - node_name, name = self._temp_plug_name - node.process.change_iterative_plug(name, checked) - self.scene.update_pipeline() - - def _protect_plug(self, checked): - node = self._temp_node - node_name, name = self._temp_plug_name - node.protect_parameter(name, checked) - - def _enable_plug_completion(self, checked): - node = self._temp_node - node_name, name = self._temp_plug_name - node.get_trait(name).forbid_completion = not checked - - def _remove_plug(self): - - if self._temp_plug_name[0] in ('inputs', 'outputs'): - # print 'remove plug:', self._temp_plug_name[1] - #print('#' * 50) - #print(self._temp_plug_name) - #print(self._temp_plug) - #for trait_name, trait in self.scene.pipeline.traits().items(): - #print(trait_name, trait) - #if trait.handler is None: - #print('HANDLER IS NONE') - #else: - #print('HANDLER:', trait.handler) - #if trait.has_items: - #print("HANDLER HAS ITEMS") - - self.scene.pipeline.remove_trait(self._temp_plug_name[1]) - self.scene.update_pipeline() - - def _edit_plug(self): - dial = self._PlugEdit(show_weak=False) - dial.name_line.setText(self._temp_plug_name[1]) - dial.name_line.setEnabled(False) ## FIXME - dial.optional.setChecked(self._temp_plug.optional) - res = dial.exec_() - if res: - plug = self._temp_plug - plug.optional = dial.optional.isChecked() - - # print 'TODO.' - self.scene.update_pipeline() - - def _prune_plugs(self): - pipeline = self.scene.pipeline - pnode = pipeline.pipeline_node - to_del = [] - for plug_name, plug in six.iteritems(pnode.plugs): - if plug.output and len(plug.links_from) == 0: - to_del.append(plug_name) - elif not plug.output and len(plug.links_to) == 0: - to_del.append(plug_name) - for plug_name in to_del: - pipeline.remove_trait(plug_name) - self.scene.update_pipeline() - - def confirm_erase_pipeline(self): - if len(self.scene.pipeline.nodes) <= 1: - return True - confirm = Qt.QMessageBox.warning( - self, - 'New pipeline', - 'The current pipeline will be lost. Continue ?', - Qt.QMessageBox.Ok | Qt.QMessageBox.Cancel, - Qt.QMessageBox.Cancel) - if confirm != Qt.QMessageBox.Ok: - return False - return True - - def new_pipeline(self): - if not self.confirm_erase_pipeline(): - return - w = Qt.QDialog(self) - w.setModal(True) - w.setWindowTitle('Pipeline name') - l = Qt.QVBoxLayout() - w.setLayout(l) - le = Qt.QLineEdit() - l.addWidget(le) - l2 = Qt.QHBoxLayout() - l.addLayout(l2) - ok = Qt.QPushButton('OK') - l2.addWidget(ok) - cancel = Qt.QPushButton('Cancel') - l2.addWidget(cancel) - ok.clicked.connect(w.accept) - cancel.clicked.connect(w.reject) - le.returnPressed.connect(w.accept) - - res = w.exec_() - if res: - class_kwargs = { - '__module__': '__main__', - 'do_autoexport_nodes_parameters': False, - 'node_position': {}, - 'node_dimension': {} - } - name = le.text() - if type(name) is not str: # unicode ? - name = name.encode() - pipeline_class = type(name, (Pipeline,), class_kwargs) - pipeline = pipeline_class() - self.set_pipeline(pipeline) - self._pipeline_filename = '' - - def load_pipeline(self, filename='', load_pipeline=True): - class LoadProcessUi(Qt.QDialog): - def __init__(self, parent=None, old_filename=''): - super(LoadProcessUi, self).__init__(parent) - self.old_filename = old_filename - lay = Qt.QVBoxLayout() - self.setLayout(lay) - l2 = Qt.QHBoxLayout() - lay.addLayout(l2) - l2.addWidget(Qt.QLabel('Pipeline:')) - self.proc_edit = PipelineDeveloperView.ProcessNameEdit() - l2.addWidget(self.proc_edit) - self.loadbt = Qt.QPushButton('...') - l2.addWidget(self.loadbt) - l3 = Qt.QHBoxLayout() - lay.addLayout(l3) - ok = Qt.QPushButton('OK') - l3.addWidget(ok) - cancel = Qt.QPushButton('Cancel') - l3.addWidget(cancel) - ok.clicked.connect(self.accept) - cancel.clicked.connect(self.reject) - self.loadbt.clicked.connect(self.get_filename) - self.proc_edit.returnPressed.connect(self.accept) - - def get_filename(self): - filename = qt_backend.getOpenFileName( - None, 'Load the pipeline', self.old_filename, - 'Compatible files (*.xml *.json *.py);; All (*)') - if filename: - self.proc_edit.setText(filename) - - if not self.confirm_erase_pipeline(): - return - - if not filename: - old_filename = getattr(self, '_pipeline_filename', '') - dialog = LoadProcessUi(self, old_filename=old_filename) - dialog.setWindowTitle('Load pipeline') - dialog.setModal(True) - dialog.resize(800, dialog.sizeHint().height()) - res = dialog.exec_() - - if res: - filename = dialog.proc_edit.text() - - if filename: - if not load_pipeline: - return filename - else: - try: - if self.scene.pipeline: - # keep the same engine - engine = self.scene.pipeline.get_study_config().engine - pipeline = engine.get_process_instance(filename) - else: - pipeline = get_process_instance(filename) - except Exception as e: - print(e) - pipeline = None - if pipeline is not None: - self.set_pipeline(pipeline) - self._pipeline_filename = filename - return filename - -
-[docs] - def save_pipeline(self): - ''' - Ask for a filename using the file dialog, and save the pipeline as a - XML, JSON or python file. - ''' - pipeline = self.scene.pipeline - old_filename = getattr(self, '_pipeline_filename', '') - filename = qt_backend.getSaveFileName( - None, 'Save the pipeline', old_filename, - 'Compatible files (*.xml *.json *.py);; All (*)') - if filename: - posdict = {} - for key, value in six.iteritems(self.scene.pos): - if hasattr(value, 'x'): - posdict[key] = (value.x(), value.y()) - else: - posdict[key] = (value[0], value[1]) - dimdict = {} - for key, value in six.iteritems(self.scene.dim): - if hasattr(value, 'boundingRect'): - dimdict[key] = (value.boundingRect().width(), - value.boundingRect().height()) - else: - dimdict[key] = (value[0], value[1]) - - pipeline.node_dimension = dimdict - old_pos = pipeline.node_position - old_dim = pipeline.node_dimension - pipeline.node_position = posdict - pipeline_tools.save_pipeline(pipeline, filename) - self._pipeline_filename = six.text_type(filename) - pipeline.node_position = old_pos - pipeline.node_dimension = old_dim
- - - #def load_pipeline_parameters(self): - #""" - #Loading and setting pipeline parameters (inputs and outputs) from a Json file. - #""" - #pipeline = self.scene.pipeline - #filename = qt_backend.getOpenFileName( - #None, 'Load pipeline parameters', '', - #'Compatible files (*.json)') - - #pipeline_tools.load_pipeline_parameters(filename, pipeline) - - #def save_pipeline_parameters(self): - #""" - #Saving pipeline parameters (inputs and outputs) to a Json file. - #""" - #pipeline = self.scene.pipeline - #filename = qt_backend.getSaveFileName( - #None, 'Save pipeline parameters', '', - #'Compatible files (*.json)') - - #pipeline_tools.save_pipeline_parameters(filename, pipeline) - -
-[docs] - def load_pipeline_parameters(self, root_path=''): - """ - Loading and setting pipeline parameters (inputs and outputs) from a Json file. - :return: - """ - - def hinted_tuple_hook(obj): - - if '__tuple__' in obj: - return tuple(obj['items']) - - else: - return obj - - filename = qt_backend.getOpenFileName( - None, 'Load the pipeline parameters', root_path, - 'Compatible files (*.json)') - - if filename: - with io.open(filename, 'r', encoding='utf8') as fileJson: - dic = json.load(fileJson) - - dic = json.loads(dic, object_hook=hinted_tuple_hook) - - if "pipeline_parameters" not in list(dic.keys()): - raise KeyError('No "pipeline_parameters" key found in {0}.'.format(filename)) - - for trait_name, trait_value in dic["pipeline_parameters"].items(): - - if trait_name not in list(self.scene.pipeline.user_traits().keys()): - print('No "{0}" parameter in pipeline.'.format(trait_name)) - - try: - setattr(self.scene.pipeline, trait_name, trait_value) - - except traits.TraitError: - print("Error for the plug {0}".format(trait_name)) - - self.scene.pipeline.update_nodes_and_plugs_activation()
- - -
-[docs] - def save_pipeline_parameters(self): - """ - Saving pipeline parameters (inputs and outputs) to a Json file. - :return: - """ - - class MultiDimensionalArrayEncoder(json.JSONEncoder): - - def encode(self, obj): - - def hint_tuples(item): - - if isinstance(item, tuple): - return {'__tuple__': True, - 'items': [hint_tuples(e) for e in item]} - - if isinstance(item, list): - return [hint_tuples(e) for e in item] - - if isinstance(item, dict): - return dict((key, hint_tuples(value)) for key, value in - item.items()) - - else: - return item - - return super(MultiDimensionalArrayEncoder, self).encode( - hint_tuples(obj)) - - pipeline = self.scene.pipeline - - filename = qt_backend.getSaveFileName( - None, 'Save the pipeline parameters', '', - 'Compatible files (*.json)') - - if not filename: # save widget was cancelled by the user - return '' - - if os.path.splitext(filename)[1] == '': # which means no extension - filename += '.json' - - elif os.path.splitext(filename)[1] != '.json': - msg = QMessageBox() - msg.setIcon(QMessageBox.Warning) - msg.setText('The parameters must be saved in the ".json" format, ' - 'not the "{0}" format'.format( - os.path.splitext(filename)[1])) - msg.setWindowTitle("Warning") - msg.setStandardButtons(QMessageBox.Ok) - msg.buttonClicked.connect(msg.close) - msg.exec_() - self.save_pipeline_parameters() - return '' - - if os.path.exists(filename) and self.disable_overwrite: - msg = QMessageBox() - msg.setIcon(QMessageBox.Warning) - msg.setText('This file already exists, you do not have the ' - 'rights to overwrite it.') - msg.setWindowTitle("Warning") - msg.setStandardButtons(QMessageBox.Ok) - msg.buttonClicked.connect(msg.close) - msg.exec_() - self.save_pipeline_parameters() - return '' - - if filename: - from traits.api import Undefined - # Generating the dictionary - param_dic = {} - - for trait_name, trait in pipeline.user_traits().items(): - - if trait_name in ["nodes_activation"]: - continue - - value = getattr(pipeline, trait_name) - - if value is Undefined: - value = "" - - param_dic[trait_name] = value - - # In the future, more information may be added to this dictionary - dic = {} - dic["pipeline_parameters"] = param_dic - jsonstring = MultiDimensionalArrayEncoder().encode(dic) - - # Saving the dictionary in the Json file - if sys.version_info[0] >= 3: - with open(filename, 'w', encoding='utf8') as file: - json.dump(jsonstring, file) - else: - with open(filename, 'w') as file: - json.dump(jsonstring, file)
-
- -
- -
-
-
-
- -
-
- - - - \ No newline at end of file diff --git a/_modules/capsul/qt_gui/widgets/pipeline_file_warning_widget.html b/_modules/capsul/qt_gui/widgets/pipeline_file_warning_widget.html deleted file mode 100644 index 20c50cca7..000000000 --- a/_modules/capsul/qt_gui/widgets/pipeline_file_warning_widget.html +++ /dev/null @@ -1,262 +0,0 @@ - - - - - - - - CAPSUL — CAPSUL - Chain algorithm in pipelines and execute in many contexts - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - Capsul logo - - -
- - - - - -
-
-
-
- -

Source code for capsul.qt_gui.widgets.pipeline_file_warning_widget

-# -*- coding: utf-8 -*-
-'''
-GUI for pipeline file inputs/outputs checking
-
-Classes
-=======
-:class:`PipelineFileWarningWidget`
-----------------------------------
-'''
-
-# System import
-from __future__ import absolute_import
-import six
-from soma.qt_gui.qt_backend import QtCore, QtGui, Qt
-try:
-    import traits.api as traits
-except ImportError:
-    import enthought.traits.api as traits
-
-
-
-[docs] -class PipelineFileWarningWidget(Qt.QSplitter): - """ - This class is a GUI for pipeline file inputs/outputs checking. - - It allows to check if there are missing inputs which may prevent the - pipeline from running, or if there are already existing outputs which would - be overwritten if the pipeline runs. - - It will show warnings accordingly. - - The widget is built from the output of - :py:func:`capsul.pipeline_tools.nodes_with_missing_inputs` and - :py:func:`capsul.pipeline_tools.nodes_with_existing_outputs` - """ - - def __init__(self, missing_inputs, overwritten_outputs, parent=None): - super(PipelineFileWarningWidget, self).__init__( - QtCore.Qt.Vertical, parent) - """ - Builds the check widget. - - Parameters - ---------- - missing_inputs: mapping iterable (mandatory) - a dict node: (list of pairs (param_name, file_name)) - as output of - :py:func:`capsul.pipeline_tools.nodes_with_missing_inputs` - overwritten_outputs: mapping iterable (mandatory) - a dict node: (list of pairs (param_name, file_name)) - as output of - :py:func:`capsul.pipeline_tools.nodes_with_existing_outputs` - parent: QWidget (optional) - parent widget - """ - splitter = self - widget1 = QtGui.QWidget(splitter) - layout1 = QtGui.QVBoxLayout(widget1) - widget2 = QtGui.QWidget(splitter) - layout2 = QtGui.QVBoxLayout(widget2) - label = QtGui.QLabel() - layout1.addWidget(label) - - text = '<h1>Pipeline file parameters problems</h1>\n' - - if len(missing_inputs) == 0: - text += '<h2>Inputs: OK</h2>\n' \ - '<p>All input file are present.</p>\n' - label.setText(text) - else: - text += '<h2>Inputs: missing files</h2>\n' - label.setText(text) - - table = QtGui.QTableWidget() - layout1.addWidget(table) - table.setColumnCount(3) - sizes = [len(l) for node, l in six.iteritems(missing_inputs)] - table.setRowCount(sum(sizes)) - table.setHorizontalHeaderLabels( - ['node', 'parameter', 'filename']) - row = 0 - for node_name, items in six.iteritems(missing_inputs): - for param_name, file_name in items: - if not file_name or file_name is traits.Undefined: - file_name = '<temp. file>' - table.setItem(row, 0, QtGui.QTableWidgetItem(node_name)) - table.setItem(row, 1, - QtGui.QTableWidgetItem(param_name)) - table.setItem(row, 2, QtGui.QTableWidgetItem(file_name)) - row += 1 - table.setSortingEnabled(True) - table.resizeColumnsToContents() - - label_out = QtGui.QLabel() - layout2.addWidget(label_out) - if len(overwritten_outputs) == 0: - text = '<h2>Outputs: OK</h2>\n' \ - '<p>No output file will be overwritten.</p>\n' - label_out.setText(text) - else: - text = '<h2>Outputs: overwritten files</h2>\n' - label_out.setText(text) - - table = QtGui.QTableWidget() - layout2.addWidget(table) - table.setColumnCount(3) - sizes = [len(l) for node, l in six.iteritems(overwritten_outputs)] - table.setRowCount(sum(sizes)) - table.setHorizontalHeaderLabels( - ['node', 'parameter', 'filename']) - row = 0 - for node_name, items in six.iteritems(overwritten_outputs): - for param_name, file_name in items: - if not file_name or file_name is traits.Undefined: - file_name = '<temp. file>' - table.setItem(row, 0, QtGui.QTableWidgetItem(node_name)) - table.setItem(row, 1, - QtGui.QTableWidgetItem(param_name)) - table.setItem(row, 2, QtGui.QTableWidgetItem(file_name)) - row += 1 - table.setSortingEnabled(True) - table.resizeColumnsToContents()
- -
- -
-
-
-
- -
-
- - - - \ No newline at end of file diff --git a/_modules/capsul/qt_gui/widgets/pipeline_user_view.html b/_modules/capsul/qt_gui/widgets/pipeline_user_view.html deleted file mode 100644 index 708c56468..000000000 --- a/_modules/capsul/qt_gui/widgets/pipeline_user_view.html +++ /dev/null @@ -1,208 +0,0 @@ - - - - - - - - CAPSUL — CAPSUL - Chain algorithm in pipelines and execute in many contexts - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - Capsul logo - - -
- - - - - -
-
-
-
- -

Source code for capsul.qt_gui.widgets.pipeline_user_view

-# -*- coding: utf-8 -*-
-'''
-A widget to visualize a pipeline as a simple workflow
-
-Classes
-=======
-:class:`PipelineUserView`
--------------------------
-'''
-
-from __future__ import print_function
-
-# System import
-from __future__ import absolute_import
-import sys
-import tempfile
-from soma.subprocess import check_call
-
-# Soma import
-from soma.qt_gui.qt_backend import QtGui
-
-
-
-[docs] -class PipelineUserView(QtGui.QWidget): - """ A widget to visualize a pipeline as a simple workflow. - - Uses Graphviz `dot` tool. - """ - def __init__(self, pipeline): - """ Initialize the WorkflowViewer class - """ - # Inheritance - super(PipelineUserView, self).__init__() - - # Class attributets - self.pipeline = pipeline - - # Initialize the widget - layout = QtGui.QVBoxLayout(self) - self.label = QtGui.QLabel() - layout.addWidget(self.label) - #self.setLayout(layout) - - self.update() - -
-[docs] - def update(self): - image = tempfile.NamedTemporaryFile(suffix=".png") - dot = tempfile.NamedTemporaryFile(suffix=".png") - self.write(dot) - dot.flush() - check_call(["dot", "-Tpng", "-o", image.name, dot.name]) - self.pixmap = QtGui.QPixmap(image.name) # .scaledToHeight(600) - self.label.setPixmap(self.pixmap)
- - - def write(self, out=sys.stdout): - graph = self.pipeline.workflow_graph() - out.write('digraph workflow {\n'.encode()) - ids = {} - for n in graph._nodes: - id = str(len(ids)) - ids[n] = id - out.write((' %s [label="%s"];\n' % (id, n)).encode()) - for n, v in graph._links: - out.write((' %s -> %s;\n' % (ids[n], ids[v])).encode()) - out.write('}\n'.encode())
- -
- -
-
-
-
- -
-
- - - - \ No newline at end of file diff --git a/_modules/capsul/qt_gui/widgets/viewer_widget.html b/_modules/capsul/qt_gui/widgets/viewer_widget.html deleted file mode 100644 index 2323ad0ec..000000000 --- a/_modules/capsul/qt_gui/widgets/viewer_widget.html +++ /dev/null @@ -1,261 +0,0 @@ - - - - - - - - CAPSUL — CAPSUL - Chain algorithm in pipelines and execute in many contexts - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - Capsul logo - - -
- - - - - -
-
-
-
- -

Source code for capsul.qt_gui.widgets.viewer_widget

-# -*- coding: utf-8 -*-
-'''
-Result viewer
-
-Classes
-=======
-:class:`ViewerWidget`
----------------------
-'''
-
-# System import
-from __future__ import absolute_import
-import logging
-import os
-
-import six
-
-# Soma import
-from soma.controller.trait_utils import trait_ids
-import soma.subprocess
-from soma.qt_gui.qt_backend import QtGui, QtCore
-
-# Qt import
-try:
-    _fromUtf8 = QtCore.QString.fromUtf8
-except AttributeError:
-    _fromUtf8 = lambda s: s
-
-
-
-[docs] -class ViewerWidget(QtGui.QWidget): - """ View result class - """ - - def __init__(self, viewer_node_name, pipeline, study_config): - """ Method to initialize a ViewerWidget class. - - Parameters - ---------- - viewer_node_name: str - the name of the node containing the viewer process - pipeline: str - the full pipeline in order to get the viewer input trait values - since the viewer node is unactivated - """ - # Inheritance - super(ViewerWidget, self).__init__() - - # Default parameters - self.viewer_node_name = viewer_node_name - self.pipeline = pipeline - self.study_config = study_config - - # Build control - button = QtGui.QToolButton(self) - button.setSizePolicy(QtGui.QSizePolicy.Expanding, QtGui.QSizePolicy.Expanding) - button.setMinimumHeight(50) - icon = QtGui.QIcon() - icon.addPixmap(QtGui.QPixmap(_fromUtf8(":/icones/view_result")), - QtGui.QIcon.Normal, QtGui.QIcon.Off) - button.setIcon(icon) - button.clicked.connect(self.onCreateViewerClicked) - -
-[docs] - def onCreateViewerClicked(self): - """ Event to create the viewer - """ - # Get the viewer node and process - viewer_node = self.pipeline.nodes[self.viewer_node_name] - viewer_process = viewer_node.process - - # Propagate the parameters to the input viewer node - # And check if the viewer is active (ie dependencies - # are specified -> corresponding process have run) - is_viewer_active = True - for plug_name, plug in six.iteritems(viewer_node.plugs): - - if plug_name in ["nodes_activation", "selection_changed"]: - continue - - # Since it is a viewer node we normally have only inputs - for (source_node_name, source_plug_name, source_node, - source_plug, weak_link) in plug.links_from: - - # Get the source plug value and source trait - source_plug_value = getattr(source_node.process, - source_plug_name) - source_trait = source_node.process.trait(source_plug_name) - - # Check if the viewer is active: - # 1) the source_plug_value has been set - if source_plug_value == source_trait.handler.default_value: - is_viewer_active = False - break - # 2) if the plug is a file, the file exists - str_description = trait_ids(source_trait) - if (len(str_description) == 1 and - str_description[0] == "File" and - not os.path.isfile(source_plug_value)): - - is_viewer_active = False - break - - # Update destination trait - setattr(viewer_process, plug_name, source_plug_value) - - # Just stop the iterations if the status of the viewer - # is alreadu known - if not is_viewer_active: - break - - # Execute the viewer process using the defined study configuration - if is_viewer_active: - soma.subprocess.Popen(viewer_process.get_commandline()) - # self.study_config.run(viewer_process) - else: - logging.error("The viewer is not active yet, maybe " - "because the processings steps have not run or are " - "not finished.")
-
- -
- -
-
-
-
- -
-
- - - - \ No newline at end of file diff --git a/_modules/capsul/sphinxext/pipelinedocgen.html b/_modules/capsul/sphinxext/pipelinedocgen.html deleted file mode 100644 index 5dbc92393..000000000 --- a/_modules/capsul/sphinxext/pipelinedocgen.html +++ /dev/null @@ -1,520 +0,0 @@ - - - - - - - - CAPSUL — CAPSUL - Chain algorithm in pipelines and execute in many contexts - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - Capsul logo - - -
- - - - - -
-
-
-
- -

Source code for capsul.sphinxext.pipelinedocgen

-# -*- coding: utf-8 -*-
-from __future__ import print_function
-
-# System import
-from __future__ import absolute_import
-import os
-import logging
-import six
-from six.moves import range
-
-# Define logger
-logger = logging.getLogger(__file__)
-
-# Capsul import
-from capsul.api import get_process_instance
-
-
-
-[docs] -class PipelineHelpWriter(object): - """ Class for automatic generation of pipeline API documentations - in Sphinx-parsable reST format. - """ - - # Only separating first two levels - rst_section_levels = ['*', '=', '-', '~', '^'] - - def __init__(self, pipelines, rst_extension=".rst", short_names={}): - """ Initialize package for parsing - - Parameters - ---------- - pipelines : list (mandatory) - list of pipeline class - rst_extension : string (optional) - extension for reST files, default '.rst' - short_names : dict (optional) - translation dict for module/pipeline file names - """ - self.pipelines = sorted(pipelines) - self.rst_extension = rst_extension - self.short_names = short_names - -
-[docs] - def generate_api_doc(self, pipeline, schema): - """ Make autodoc documentation for a pipeline python module - - Parameters - ---------- - pipeline : string - python location of pipeline - e.g 'caps.fmri.PIPELINE' - schema : string - path to the pipeline representation image - - Returns - ------- - ad : string - contents of API doc - title : string - the fist line of the docstring - """ - # Fiest get the pipeline instance from its string description - pipeline_instance = get_process_instance(pipeline) - - # Get the header, ie. the first line of the docstring - # Default title is '' - header = pipeline_instance.__doc__ - title = "" - if header: - title = pipeline_instance.__doc__.splitlines()[0] - - # Add header to tell us that this documentation must not be edited - ad = ".. AUTO-GENERATED FILE -- DO NOT EDIT!\n\n" - - # Generate the page title: name of the pipeline - ad += ":orphan:\n\n" - - # Set the current module - currentmodule = ".".join(pipeline_instance.id.split(".")[:-1]) - ad += ".. currentmodule:: {0}\n\n".format(currentmodule) - - # Generate a bookmark (for cross references) - pipeline_name = pipeline_instance.__class__.__name__ - label = pipeline + ":" - ad += "\n.. _{0}\n\n".format(label) - - chap_title = pipeline - ad += (chap_title + "\n" + - self.rst_section_levels[1] * len(chap_title) + "\n\n") - - # Add a subtitle - ad += (pipeline_name + "\n" + - self.rst_section_levels[2] * len(pipeline_name) + "\n\n") - - # Then add the trait description - # It will generate two sections: input and output - ad += pipeline_instance.get_help(returnhelp=True, use_labels=True) - - # Add schema if generated - if schema: - schama_title = "Pipeline schema" - ad += ("\n" + schama_title + "\n" + - "~" * len(schama_title) + "\n\n") - ad += ".. image:: {0}\n".format(schema) - ad += " :height: 400px\n" - ad += " :align: center\n\n" - - return ad, title
- - -
-[docs] - def write_api_docs(self, outdir=None, returnrst=False): - """ Generate API reST files. - - Parameters - ---------- - outdir : string (optional, default None) - directory name in which to store files. - Automatic filenames are created for each module. - returnrst: bool (optional, default False) - if True return the rst string documentation, - otherwise write it to disk. - - Notes - ----- - Sets self.written_modules to list of written modules - """ - # Check output directory - if returnrst is False: - if not isinstance(outdir, six.string_types): - raise Exception("If 'returnrst' is False, need a valid output " - "directory.") - if not os.path.exists(outdir): - os.makedirs(outdir) - else: - rstdoc = {} - - # Generate reST API - written_modules = [] - for pipeline in self.pipelines: - - # Information message - logger.info("Processing pipeline '{0}'...".format(pipeline)) - - pipeline_short = self.get_short_name(pipeline) - # Check if an image representation of the pipeline exists - if returnrst is False: - schema = os.path.join(os.pardir, "schema", - pipeline_short + ".png") - if not os.path.isfile(os.path.join(outdir, schema)): - schema = None - else: - schema = None - - # Generate the rst string description - api_str, title_str = self.generate_api_doc(pipeline, schema) - if not api_str: - continue - - # Write to file - if returnrst is False: - outfile = os.path.join(outdir, - pipeline_short + self.rst_extension) - fileobj = open(outfile, "wt") - fileobj.write(api_str) - fileobj.close() - else: - rstdoc[pipeline] = api_str - - # Update the list of written modules - written_modules.append((title_str, pipeline)) - - # Update the class attribute containing the list of written modules - self.written_modules = written_modules - - if returnrst is True: - return rstdoc
- - -
-[docs] - def get_short_name(self, name): - """ - Get a short file name prefix for module/process in the - short_names dict. Used to build "reasonably short" path/file names. - """ - short_name = self.short_names.get(name) - if short_name: - return short_name - # look for a shorter name for the longest module prefix - modules = name.split(".") - for i in range(len(modules)-1, 0, -1): - path = '.'.join(modules[:i]) - short_path = self.short_names.get(path) - if short_path: - return '.'.join([short_path] + modules[i+1:]) - # not found - return name
- - -
-[docs] - def write_index(self, outdir, froot="index", relative_to=None, - rst_extension=".rst"): - """ Make a reST API index file from the list of written files - - Parameters - ---------- - outdir : string (mandatory) - directory to which to write generated index file - froot : string (optional) - root (filename without extension) of filename to write to - Defaults to 'index'. We add ``rst_extension``. - relative_to : string - path to which written filenames are relative. This - component of the written file path will be removed from - outdir, in the generated index. Default is None, meaning, - leave path as it is. - rst_extension : string (optional) - extension for reST files, default '.rst' - """ - # Check if some modules have been written - if self.written_modules is None: - raise ValueError('No modules written') - - # Get full index filename path - path = os.path.join(outdir, froot + rst_extension) - - # Path written into index is relative to rootpath - if relative_to is not None: - relpath = outdir.replace(relative_to + os.path.sep, "") - else: - relpath = outdir - print('relpath:', relpath) - - # Information message - logger.info("Writing index at location '{0}'...".format( - os.path.abspath(path))) - - # Edit the index file - idx = open(path, "wt") - w = idx.write - - # Add header to tell us that this documentation must not be edited - w(".. AUTO-GENERATED FILE -- DO NOT EDIT!\n\n") - - # Generate a table with all the generated modules - # module_name (link) + first docstring line - w(".. raw:: html\n\n") - - # Table definition - table = ["<!-- Block section -->"] - table.append("<table border='1' class='docutils' style='width:100%'>") - table.append("<colgroup><col width='25%'/><col width='75%'/>" - "</colgroup>") - table.append("<tbody valign='top'>") - - # Add all modules - for title_str, f in self.written_modules: - pipeline_short = self.get_short_name(f) - print('title_str:', title_str, ', f:', f) - relative_pipeline = ".".join(f.split(".")[2:]) - print('relative_pipeline:', relative_pipeline) - ref = os.path.join(relpath, pipeline_short + ".html") - print('ref:', ref) - table.append("<tr class='row-odd'>") - table.append( - "<td><a class='reference internal' href='{0}'>" - "<em>{1}</em></a></td>\n".format(ref, relative_pipeline)) - table.append("<td>{0}</td>".format(title_str)) - table.append("</tr>") - - # Close divs - table.append("</tbody>\n\n") - table.append("</table>") - - # Format the table - table_with_indent = [" " * 4 + line for line in table] - w("\n".join(table_with_indent)) - - # Close the file - idx.close()
- - -
-[docs] - def write_main_index(self, outdir, module_name, root_module_name, - froot="index", rst_extension=".rst", - have_usecases=True): - """ Make a reST API index file for the module - - Parameters - ---------- - outdir : string (mandatory) - Directory to which to write generated index file - module_name: str (mandatory) - The name of module from which we want to generate an index. - root_module_name: str (mandatory) - The python package name - froot : string (optional) - root (filename without extension) of filename to write to - Defaults to 'index'. We add ``rst_extension``. - rst_extension : string (optional) - Extension for reST files, default '.rst' - """ - # Get full index filename path - path = os.path.join(outdir, froot + rst_extension) - - # Information message - logger.info("Writing module '{0}' index at location '{1}'...".format( - module_name, os.path.abspath(path))) - - # Open the result index file - idx = open(path, "wt") - - # Stat writing - w = idx.write - - # Add header to tell us that this documentation must not be edited - w(".. AUTO-GENERATED FILE -- DO NOT EDIT!\n\n") - w(":orphan:\n\n") - - # Generate a title - chap_title = " ".join([x.capitalize() for x in module_name.split("_")]) - w(chap_title + "\n" + - self.rst_section_levels[0] * len(chap_title) + "\n\n") - - # Generate a markup - label = module_name - w(".. _{0}:\n\n".format(label)) - - # Page use cases - # # Generate a title - chap_title = ":mod:`{0}.{1}`: User Guide".format( - root_module_name, module_name) - w(chap_title + "\n" + - self.rst_section_levels[1] * len(chap_title) + "\n\n") - - if have_usecases: - # # Generate a markup - label = module_name + "_ug" - w(".. _{0}:\n\n".format(label)) - # # Some text description - w("Some live examples containing snippets of codes.\n\n") - # # Include user guide index - w(".. include:: use_cases/index%s\n\n" % rst_extension) - - # API page - # # Generate a title - chap_title = ":mod:`{0}.{1}`: API".format( - root_module_name, module_name) - w(chap_title + "\n" + - self.rst_section_levels[1] * len(chap_title) + "\n\n") - # # Generate a markup - label = module_name + "_api" - w(".. _{0}:\n\n".format(label)) - # # Some text description - w("The API of functions and classes, as given by the " - "docstrings.") - if have_usecases: - w(" For the *user guide* see the {0}_ug_ " - "section for further details.\n\n".format(module_name)) - else: - w("\n\n") - # # Include pipeline and buildingblock indexes - # ## Pipeline - chap_title = "Pipelines" - w(chap_title + "\n" + - self.rst_section_levels[2] * len(chap_title) + "\n\n") - w(".. include:: pipeline/index%s\n\n" % rst_extension) - # ## Buildingblocks - chap_title = "Buildingblocks" - w(chap_title + "\n" + - self.rst_section_levels[2] * len(chap_title) + "\n\n") - w(".. include:: process/index%s\n\n" % rst_extension) - - # Close file - idx.close()
-
- -
- -
-
-
-
- -
-
- - - - \ No newline at end of file diff --git a/_modules/capsul/study_config/config_modules/fom_config.html b/_modules/capsul/study_config/config_modules/fom_config.html deleted file mode 100644 index 2ea9f7417..000000000 --- a/_modules/capsul/study_config/config_modules/fom_config.html +++ /dev/null @@ -1,331 +0,0 @@ - - - - - - - - CAPSUL — CAPSUL - Chain algorithm in pipelines and execute in many contexts - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - Capsul logo - - -
- - - - - -
-
-
-
- -

Source code for capsul.study_config.config_modules.fom_config

-# -*- coding: utf-8 -*-
-'''
-Config module for :mod:`File Organization models (FOMs) <capsul.attributes.fom_completion_engine>`
-
-Classes
-=======
-:class:`FomConfig`
-------------------
-'''
-
-from __future__ import absolute_import
-import os
-import six
-from traits.api import Bool, Str, Undefined, List, Directory
-from soma.fom import AttributesToPaths, PathToAttributes
-from soma.application import Application
-from capsul.study_config.study_config import StudyConfigModule
-from capsul.engine import CapsulEngine
-
-
-
-[docs] -class FomConfig(StudyConfigModule): - '''FOM (File Organization Model) configuration module for StudyConfig - - .. note:: - :class:`~capsul.study_config.config_modules.fom_config.FomConfig` - needs :class:`~capsul.study_config.config_modules.brainvisa_config.BrainVISAConfig` - to be part of - :class:`~capsul.study_config.study_config.StudyConfig` modules. - - This module adds the following options (traits) in the - :class:`~capsul.study_config.study_config.StudyConfig` object: - - input_fom: str - input FOM - output_fom: str - output FOM - shared_fom: str - shared data FOM - volumes_format: str - Format used for volumes - meshes_format: str - Format used for meshes - auto_fom: bool (default: True) - Look in all FOMs when a process is not found. Note that auto_fom - looks for the first FOM matching the process to get - completion for, and does not handle ambiguities. Moreover - it brings an overhead (typically 6-7 seconds) the first - time it is used since it has to parse all available FOMs. - fom_path: list of directories - list of additional directories where to look for FOMs (in addition to - the standard share/foms) - use_fom: bool - Use File Organization Models for file parameters completion' - - *Methods:* - ''' - - dependencies = ['BrainVISAConfig', 'SPMConfig', 'AttributesConfig'] - - def __init__(self, study_config, configuration): - super(FomConfig, self).__init__(study_config, configuration) - self.study_config.add_trait('input_fom', Str(Undefined, output=False, - desc='input FOM', groups=['fom'])) - self.study_config.add_trait('output_fom', Str(Undefined, output=False, - desc='output FOM', groups=['fom'])) - self.study_config.add_trait('shared_fom', Str(Undefined, output=False, - desc='shared data FOM', groups=['fom'])) - self.study_config.add_trait('volumes_format', - Str(Undefined, output=False, - desc='Format used for volumes', groups=['fom'])) - self.study_config.add_trait('meshes_format', - Str(Undefined, output=False, - desc='Format used for meshes', groups=['fom'])) - self.study_config.add_trait( - 'auto_fom', - Bool(True, output=False, - desc='Look in all FOMs when a process is not found (in ' - 'addition to the standard share/foms). Note that auto_fom ' - 'looks for the first FOM matching the process to get ' - 'completion for, and does not handle ambiguities. Moreover ' - 'it brings an overhead (typically 6-7 seconds) the first ' - 'time it is used since it has to parse all available FOMs.', - groups=['fom'])) - self.study_config.add_trait( - 'fom_path', - List(Directory(output=False), - desc='list of additional directories where to look for FOMs', - groups=['fom'])) - self.study_config.add_trait('use_fom', Bool( - Undefined, - output=False, - desc='Use File Organization Models for file parameters ' - 'completion', - groups=['fom'])) - - # defaults - self.study_config.input_fom = "" - self.study_config.output_fom = "" - self.study_config.shared_fom = "" - self.study_config.modules_data.foms = {} - self.study_config.modules_data.fom_atp = {} - self.study_config.modules_data.fom_pta = {} - - -
-[docs] - def initialize_module(self): - if 'capsul.engine.module.fom' \ - not in self.study_config.engine._loaded_modules: - self.study_config.engine.load_module('capsul.engine.module.fom') - - if type(self.study_config.engine) is not CapsulEngine: - # engine is a proxy, thus we are initialized from a real - # CapsulEngine, which holds the reference values - self.sync_from_engine() - else: - self.sync_to_engine() - # 1st sync may have changed things - self.sync_from_engine()
- - -
-[docs] - def initialize_callbacks(self): - self.study_config.on_trait_change( - self.sync_to_engine, - ['input_directory', 'input_fom', 'meshes_format', - 'output_directory', 'output_fom', 'shared_fom', 'volumes_format', - 'auto_fom', 'fom_path', 'shared_directory']) - # WARNING ref to self in callback - self.study_config.engine.settings.module_notifiers[ - 'capsul.engine.module.fom'].append(self.sync_from_engine)
- - - - def sync_to_engine(self, param=None, value=None): - params = ['input_fom', 'meshes_format', 'output_fom', 'shared_fom', - 'volumes_format', 'input_directory', 'output_directory', - 'auto_fom', 'fom_path'] - - with self.study_config.engine.settings as session: - config = session.config('fom', 'global') - if config: - if param in params: - params = [param] - for p in params: - value = getattr(self.study_config, p) - if value is Undefined: - value = None - setattr(config, p, value) - else: - values = {} - for p in params: - value = getattr(self.study_config, p) - if value is Undefined: - value = None - values[p] = value - values[self.study_config.engine.settings.config_id_field] \ - = 'fom' - session.new_config('fom', 'global', values) - - - def sync_from_engine(self, param=None, value=None): - params = ['input_fom', 'meshes_format', 'output_fom', 'shared_fom', - 'volumes_format', 'input_directory', 'output_directory', - 'auto_fom', 'fom_path'] - if param is not None: - params = [param] - - with self.study_config.engine.settings as session: - config = session.config('fom', 'global') - if not config: - self.study_config.use_fom = False - return - for p in params: - # print('sync_from_engine:', p, type(p)) - value = getattr(config, p) - if value is None: - value = Undefined - setattr(self.study_config, p, value) - self.study_config.use_fom = True - - - def load_fom(self, schema): - with self.study_config.engine.settings as session: - config = session.config('fom', 'global') - if config: - from capsul.engine.module.fom import load_fom - return load_fom(self.study_config.engine, schema, config, - session, environment='global')
- -
- -
-
-
-
- -
-
- - - - \ No newline at end of file diff --git a/_modules/capsul/study_config/config_modules/freesurfer_config.html b/_modules/capsul/study_config/config_modules/freesurfer_config.html deleted file mode 100644 index 359497503..000000000 --- a/_modules/capsul/study_config/config_modules/freesurfer_config.html +++ /dev/null @@ -1,281 +0,0 @@ - - - - - - - - CAPSUL — CAPSUL - Chain algorithm in pipelines and execute in many contexts - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - Capsul logo - - -
- - - - - -
-
-
-
- -

Source code for capsul.study_config.config_modules.freesurfer_config

-# -*- coding: utf-8 -*-
-'''
-FreeSurfer configuration module
-
-Classes
-=======
-:class:`FreeSurferConfig`
--------------------------
-'''
-
-# System import
-from __future__ import absolute_import
-import os
-import six
-
-# Trait import
-from traits.api import File, Bool, Undefined, Directory
-
-# Capsul import
-from capsul.study_config.study_config import StudyConfigModule
-from capsul.engine import CapsulEngine
-
-
-
-[docs] -class FreeSurferConfig(StudyConfigModule): - """ Class to set up freesurfer configuration. - - Parse the 'SetUpFreeSurfer.sh' file and update dynamically the system - environment. - """ - def __init__(self, study_config, configuration): - """ Initilaize the FreeSurferConfig class. - - Parameters - ---------- - study_config: StudyConfig object - the study configuration we want to update in order to deal with - freesurfer functions. - """ - super(FreeSurferConfig, self).__init__(study_config, configuration) - self.study_config.add_trait("freesurfer_config", File( - Undefined, - desc="Path to 'FreeSurferEnv.sh'", groups=['freesurfer'])) - self.study_config.add_trait('freesurfer_subjectsdir', Directory( - Undefined, - desc='FreeSurfer subjects data directory', groups=['freesurfer'])) - self.study_config.add_trait("use_freesurfer", Bool( - False, - desc="If True, FreeSurfer configuration is set up on startup", - groups=['freesurfer'])) - -
-[docs] - def initialize_module(self): - """ Set up FSL environment variables according to current - configuration. - """ - if 'capsul.engine.module.freesurfer' \ - not in self.study_config.engine._loaded_modules: - self.study_config.engine.load_module( - 'capsul.engine.module.freesurfer') - if type(self.study_config.engine) is not CapsulEngine: - # engine is a proxy, thus we are initialized from a real - # CapsulEngine, which holds the reference values - self.sync_from_engine() - else: - self.sync_to_engine()
- - -
-[docs] - def initialize_callbacks(self): - self.study_config.on_trait_change( - self.sync_to_engine, - ['freesurfer_config', 'freesurfer_subjectsdir']) - # WARNING ref to self in callback - self.study_config.engine.settings.module_notifiers[ - 'capsul.engine.module.freesurfer'] = [self.sync_from_engine]
- - - def sync_to_engine(self, param=None, value=None): - if getattr(self, '_syncing', False): - # manage recursive calls - return - self._syncing = True - try: - if 'FreeSurferConfig' in self.study_config.modules \ - and 'capsul.engine.module.freesurfer' \ - in self.study_config.engine._loaded_modules: - with self.study_config.engine.settings as session: - cif = self.study_config.engine.settings.config_id_field - params = { - 'freesurfer_config': 'setup', - 'freesurfer_subjectsdir': 'subjects_dir', - } - config = session.config('freesurfer', 'global') - if config is None: - values = {cif: 'freesurfer'} - for param, ceparam in six.iteritems(params): - val = getattr(self.study_config, param) - if val is Undefined: - val = None - values[ceparam] = val - session.new_config('freesurfer', 'global', values) - else: - for param, ceparam in six.iteritems(params): - val = getattr(self.study_config, param) - if val is Undefined: - val = None - setattr(config, ceparam, val) - finally: - del self._syncing - - def sync_from_engine(self, param=None, value=None): - if getattr(self, '_syncing', False): - # manage recursive calls - return - self._syncing = True - try: - if 'FreeSurferConfig' in self.study_config.modules \ - and 'capsul.engine.module.freesurfer' \ - in self.study_config.engine._loaded_modules: - with self.study_config.engine.settings as session: - config = session.config('freesurfer', 'global') - if config: - params = { - 'freesurfer_config': 'setup', - 'freesurfer_subjectsdir': 'subjects_dir', - } - for param, ceparam in six.iteritems(params): - val = getattr(config, ceparam) - if val in (None, ''): - val = Undefined - setattr(self.study_config, param, val) - - if self.study_config.freesurfer_config: - self.study_config.use_freesurfer = True - else: - self.study_config.use_freesurfer = False - finally: - del self._syncing
- -
- -
-
-
-
- -
-
- - - - \ No newline at end of file diff --git a/_modules/capsul/study_config/config_modules/fsl_config.html b/_modules/capsul/study_config/config_modules/fsl_config.html deleted file mode 100644 index d24a90e15..000000000 --- a/_modules/capsul/study_config/config_modules/fsl_config.html +++ /dev/null @@ -1,303 +0,0 @@ - - - - - - - - CAPSUL — CAPSUL - Chain algorithm in pipelines and execute in many contexts - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - Capsul logo - - -
- - - - - -
-
-
-
- -

Source code for capsul.study_config.config_modules.fsl_config

-# -*- coding: utf-8 -*-
-'''
-FSL configuration module
-
-Classes
-=======
-:class:`FSLConfig`
-------------------
-'''
-
-from __future__ import absolute_import
-from traits.api import File, Bool, Undefined, String
-
-from capsul.study_config.study_config import StudyConfigModule
-from capsul.engine import CapsulEngine
-from capsul.subprocess.fsl import check_fsl_configuration
-import os.path as osp
-
-
-[docs] -class FSLConfig(StudyConfigModule): - ''' - `FSL <https://fsl.fmrib.ox.ac.uk/fsl/fslwiki>`_ configuration module - ''' - - def __init__(self, study_config, configuration): - super(FSLConfig, self).__init__(study_config, configuration) - self.study_config.add_trait('fsl_config', File( - Undefined, - output=False, - desc='Parameter to specify the fsl.sh path', groups=['fsl'])) - self.study_config.add_trait('fsl_prefix', String(Undefined, - desc='Prefix to add to FSL commands', groups=['fsl'])) - self.study_config.add_trait('use_fsl', Bool( - Undefined, - output=False, - desc='Parameter to tell that we need to configure FSL', - groups=['fsl'])) - - def __del__(self): - try: - self.study_config.engine.settings.module_notifiers.get( - 'capsul.engine.module.fsl', []).remove(self.sync_from_engine) - except (ValueError, ReferenceError): - pass - -
-[docs] - def initialize_module(self): - """ Set up FSL environment variables according to current - configuration. - """ - if 'capsul.engine.module.fsl' \ - not in self.study_config.engine._loaded_modules: - self.study_config.engine.load_module('capsul.engine.module.fsl') - if type(self.study_config.engine) is not CapsulEngine: - # engine is a proxy, thus we are initialized from a real - # CapsulEngine, which holds the reference values - self.sync_from_engine() - else: - self.sync_to_engine() - # this test aims to raise an exception in case of incorrect setting, - # complying to capsul 2.x behavior. - if self.study_config.use_fsl is True: - check_fsl_configuration(self.study_config)
- - -
-[docs] - def initialize_callbacks(self): - self.study_config.on_trait_change( - self.sync_to_engine, '[fsl_config, fsl_prefix, use_fsl]') - # WARNING ref to self in callback - self.study_config.engine.settings.module_notifiers[ - 'capsul.engine.module.fsl'] = [self.sync_from_engine]
- - - def sync_to_engine(self, param=None, value=None): - if getattr(self, '_syncing', False): - # manage recursive calls - return - self._syncing = True - try: - if 'FSLConfig' in self.study_config.modules \ - and 'capsul.engine.module.fsl' \ - in self.study_config.engine._loaded_modules: - with self.study_config.engine.settings as session: - cif = self.study_config.engine.settings.config_id_field - config = session.config('fsl', 'global') - fsl_conf = self.study_config.fsl_config - if fsl_conf is Undefined: - fsl_conf = None - fsl_dir = None - else: - fsl_dir = osp.dirname(fsl_conf) - if fsl_dir.endswith('/etc/fslconf'): - fsl_dir = osp.dirname(osp.dirname(fsl_dir)) - elif fsl_dir.endswith('/etc'): - fsl_dir = osp.dirname(fsl_dir) - if config is None: - session.new_config( - 'fsl', 'global', - {'directory': fsl_dir, - 'config': fsl_conf, - 'prefix': self.study_config.fsl_prefix - if self.study_config.fsl_prefix - is not Undefined - else None, - cif: 'fsl'}) - else: - tparam = {'fsl_config': 'config', - 'fsl_prefix': 'prefix'} - if param is not None: - if param not in ('use_fsl', ): - params = [param] - else: - params = [] - else: - params = ['fsl_config', 'fsl_prefix'] - defaults = {'prefix': None, 'config': None} - for p in params: - val = getattr(self.study_config, p) - ceparam = tparam[p] - if val is Undefined: - val = defaults.get(ceparam, None) - setattr(config, ceparam, val) - if 'fsl_config' in params: - config.directory = fsl_dir - del config - del session - finally: - del self._syncing - - def sync_from_engine(self, param=None, value=None): - if getattr(self, '_syncing', False): - # manage recursive calls - return - self._syncing = True - try: - if 'FSLConfig' in self.study_config.modules \ - and 'capsul.engine.module.fsl' \ - in self.study_config.engine._loaded_modules: - with self.study_config.engine.settings as session: - config = session.config('fsl', 'global') - if config: - directory = config.directory \ - if config.directory not in (None, '') \ - else Undefined - - self.study_config.fsl_config = config.config \ - if config.config is not None else Undefined - self.study_config.fsl_prefix = config.prefix \ - if config.prefix is not None else Undefined - if self.study_config.fsl_config not in ( - '', None, Undefined)\ - or self.study_config.fsl_prefix not in ( - '', None, Undefined): - self.study_config.use_fsl = True - else: - self.study_config.use_fsl = False - except ReferenceError: - pass - finally: - del self._syncing
- -
- -
-
-
-
- -
-
- - - - \ No newline at end of file diff --git a/_modules/capsul/study_config/config_modules/matlab_config.html b/_modules/capsul/study_config/config_modules/matlab_config.html deleted file mode 100644 index a3aaa6457..000000000 --- a/_modules/capsul/study_config/config_modules/matlab_config.html +++ /dev/null @@ -1,290 +0,0 @@ - - - - - - - - CAPSUL — CAPSUL - Chain algorithm in pipelines and execute in many contexts - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - Capsul logo - - -
- - - - - -
-
-
-
- -

Source code for capsul.study_config.config_modules.matlab_config

-# -*- coding: utf-8 -*-
-'''
-Matlab configuration module
-
-Classes
-=======
-:class:`MatlabConfig`
----------------------
-'''
-
-from __future__ import print_function
-
-from __future__ import absolute_import
-import os
-from traits.api import File, Undefined, Bool
-from capsul.study_config.study_config import StudyConfigModule
-from capsul.engine import CapsulEngine
-
-
-
-[docs] -class MatlabConfig(StudyConfigModule): - ''' - Matlab path configuration - ''' - - def __init__(self, study_config, configuration): - super(MatlabConfig, self).__init__(study_config, configuration) - self.study_config.add_trait('matlab_exec', File( - Undefined, - output=False, - desc='Matlab command path', - exists=True, - groups=['matlab'])) - self.study_config.add_trait("use_matlab", Bool( - Undefined, - desc="If True, Matlab configuration is set up on startup", - groups=['matlab'])) - -
-[docs] - def initialize_module(self): - """ Set up Matlab environment according to current configuration. - """ - if not self.study_config.matlab_exec and self.study_config.use_matlab: - # fix pathological config (appearing sometimes for an unknown reason) - self.study_config.use_matlab = Undefined - if 'capsul.engine.module.matlab' \ - not in self.study_config.engine._loaded_modules: - self.study_config.engine.load_module('capsul.engine.module.matlab') - - if type(self.study_config.engine) is not CapsulEngine: - # engine is a proxy, thus we are initialized from a real - # CapsulEngine, which holds the reference values - self.sync_from_engine() - else: - self.sync_to_engine() - - # the following should be moved to CapsulEngine module - if self.study_config.use_matlab is False: - # Configuration is explicitly asking not to use Matlab - return - - if self.study_config.use_matlab is Undefined: - # If use_matlab is not defined, Matlab configuration will - # be done if possible but there will be no error if it cannot be - # done. - force_configuration = False - else: - # If use_matlab is True configuration must be valid otherwise - # an EnvironmentError is raised - force_configuration = True - - if self.study_config.matlab_exec is Undefined: - # matlab_exec is not set, it will not be possible to activate - #Matlab - self.study_config.use_matlab = False - if force_configuration: - raise EnvironmentError('matlab_exec must be defined in order ' - 'to use Matlab') - return - - if not os.path.exists(self.study_config.matlab_exec): - self.study_config.use_matlab = False - if force_configuration: - raise EnvironmentError('"%s" does not exist. Matlab ' - 'configuration is not valid.' % \ - self.study_config.matlab_exec) - return
- - -
-[docs] - def initialize_callbacks(self): - self.study_config.on_trait_change(self.sync_to_engine, 'matlab_exec') - # WARNING ref to self in callback - self.study_config.engine.settings.module_notifiers[ - 'capsul.engine.module.matlab'] = [self.sync_from_engine]
- - - def sync_to_engine(self, param=None, value=None): - if param is not None: - tparam = {'matlab_exec': 'executable'} - ceparam = tparam.get(param) - else: - ceparam = 'executable' - value = self.study_config.matlab_exec - if value is Undefined: - value = None - if ceparam is not None: - with self.study_config.engine.settings as session: - config = session.config('matlab', 'global', any=True) - if config is None: - if (ceparam !='executable' - or self.study_config.matlab_exec - not in (None, Undefined, '')): - cif = self.study_config.engine.settings.config_id_field - matlab_exec = self.study_config.matlab_exec - if matlab_exec is Undefined: - matlab_exec = None - session.new_config( - 'matlab', 'global', - {'executable': matlab_exec, - cif: 'matlab'}) - else: - if value is Undefined: - value = None - setattr(config, ceparam, value) - - def sync_from_engine(self, param=None, value=None): - self.use_matlab = None # avoid transcient inconsistencies - if param is not None: - tparam = {'executable': 'matlab_exec'} - scparam = tparam.get(param) - if scparam is not None: - if value is None: - value = Undefined - setattr(self.study_config, scparam, value) - else: - if self.study_config.use_matlab: - # in case we reset matlab_exec to Undefined - self.study_config.use_matlab = Undefined - with self.study_config.engine.settings as session: - config = session.config('matlab', 'global', any=True) - if config: - matlab_exec = config.executable - if matlab_exec is None: - matlab_exec = Undefined - self.study_config.matlab_exec = matlab_exec - if self.study_config.matlab_exec not in (None, Undefined): - self.study_config.use_matlab = True
- -
- -
-
-
-
- -
-
- - - - \ No newline at end of file diff --git a/_modules/capsul/study_config/config_modules/nipype_config.html b/_modules/capsul/study_config/config_modules/nipype_config.html deleted file mode 100644 index dc1dccf3e..000000000 --- a/_modules/capsul/study_config/config_modules/nipype_config.html +++ /dev/null @@ -1,257 +0,0 @@ - - - - - - - - CAPSUL — CAPSUL - Chain algorithm in pipelines and execute in many contexts - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - Capsul logo - - -
- - - - - -
-
-
-
- -

Source code for capsul.study_config.config_modules.nipype_config

-# -*- coding: utf-8 -*-
-'''
-NiPype configuration module
-
-Classes
-=======
-:class:`NipypeConfig`
----------------------
-'''
-
-from __future__ import absolute_import
-
-import glob
-import os
-
-# TRAITS import
-from traits.api import Bool, Undefined, List, Directory
-
-# NIPYPE import
-try:
-    import nipype.interfaces.matlab as matlab
-    from nipype.interfaces import spm
-    has_nipype = True
-except ImportError:
-    has_nipype = False
-
-# CAPSUL import
-from capsul.study_config.study_config import StudyConfigModule
-import capsul.engine.module.nipype as ce_nipype
-
-
-
-[docs] -class NipypeConfig(StudyConfigModule): - """ Nipype configuration. - - In order to use nipype spm, fsl and freesurfer interfaces, we need to - configure the nipype module. - """ - - dependencies = [] - - def __init__(self, study_config, configuration): - """ Initialize the NipypeConfig class. - """ - super(NipypeConfig, self).__init__(study_config, configuration) - study_config.add_trait("use_nipype", Bool( - Undefined, - desc="If True, Nipype configuration is set up on startup.", - groups=['nipype'])) - study_config.add_trait("add_to_default_matlab_path", List( - Directory, - default=[], - desc="Paths that are added to Matlab default path.", - groups=['nipype'])) - self.has_nipype = has_nipype - -
-[docs] - def initialize_module(self): - """ Set up Nipype environment variables according to current - configuration. - """ - if 'capsul.engine.module.nipype' \ - not in self.study_config.engine._loaded_modules: - self.study_config.engine.load_module( - 'capsul.engine.module.nipype') - ce_nipype.ensure_config_exists(self.study_config.engine) - if not self.has_nipype: - self.study_config.use_nipype = False - return - if self.study_config.use_nipype is False: - # Configuration is explicitly asking not to use Nipype - return - elif self.study_config.use_nipype is True: - # If use_nipype is True configuration must be valid otherwise - # an EnvironmentError is raised - force_configuration = True - else: - # If use_nipype is not defined, Nipype configuration will - # be done if possible but there will be no error if it cannot be - # done. - force_configuration = False - - # Configure matlab for nipype - if self.study_config.use_matlab: - matlab.MatlabCommand.set_default_matlab_cmd( - self.study_config.matlab_exec + " -nodesktop -nosplash") - - # Configure spm for nipype - if self.study_config.use_spm is True: - - # Standalone spm version - if self.study_config.spm_standalone is True: - spm.SPMCommand.set_mlab_paths( - matlab_cmd=self.study_config.spm_exec + " " \ - + glob.glob(os.path.join( - self.study_config.spm_directory, 'mcr', 'v*'))[0] \ - + " script", - use_mcr=True) - # Matlab spm version - else: - matlab.MatlabCommand.set_default_paths( - [self.study_config.spm_directory] + - self.study_config.add_to_default_matlab_path) - spm.SPMCommand.set_mlab_paths(matlab_cmd="", use_mcr=False) - - self.study_config.use_nipype = True
- - -
-[docs] - def initialize_callbacks(self): - """ When the 'use_nipype' trait changes, configure nipype with the new - setting. - """ - self.study_config.on_trait_change(self.initialize_module, "use_nipype")
-
- -
- -
-
-
-
- -
-
- - - - \ No newline at end of file diff --git a/_modules/capsul/study_config/config_modules/spm_config.html b/_modules/capsul/study_config/config_modules/spm_config.html deleted file mode 100644 index 9be35d7d5..000000000 --- a/_modules/capsul/study_config/config_modules/spm_config.html +++ /dev/null @@ -1,380 +0,0 @@ - - - - - - - - CAPSUL — CAPSUL - Chain algorithm in pipelines and execute in many contexts - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - Capsul logo - - -
- - - - - -
-
-
-
- -

Source code for capsul.study_config.config_modules.spm_config

-# -*- coding: utf-8 -*-
-'''
-SPM configuration module
-
-Classes
-=======
-:class:`SPMConfig`
-------------------
-'''
-
-from __future__ import absolute_import
-
-from traits.api import Directory, File, Bool, Enum, Undefined, Str
-from capsul.study_config.study_config import StudyConfigModule
-from capsul.subprocess.spm import check_spm_configuration
-from capsul.engine import CapsulEngine
-import glob
-import os
-import os.path as osp
-
-
-
-[docs] -class SPMConfig(StudyConfigModule): - """ SPM configuration. - - There is two ways to configure SPM: - * the first one requires to configure matlab and then to set the spm - directory. - * the second one is based on a standalone version of spm and requires - to set the spm executable directory. - """ - - dependencies = ["MatlabConfig"] - - def __init__(self, study_config, configuration): - super(SPMConfig, self).__init__(study_config, configuration) - self.study_config.add_trait("spm_directory", Directory( - Undefined, - output=False, - desc="Directory containing SPM.", - groups=['spm'])) - self.study_config.add_trait("spm_standalone", Bool( - Undefined, - desc="If True, use the standalone version of SPM.", - groups=['spm'])) - self.study_config.add_trait('spm_version', Str( - Undefined, output=False, - desc='Version string for SPM: "12", "8", etc.', - groups=['spm'])) - self.study_config.add_trait("spm_exec", File( - Undefined, - output=False, - desc="SPM standalone (MCR) command path (run_spm12.sh file).", - groups=['spm'])) - self.study_config.add_trait( - 'spm_mcr_directory', - Directory(Undefined, output=False, - desc='Matlab MCR directory for standalone version', - groups=['spm'])) - self.study_config.add_trait("use_spm", Bool( - Undefined, - desc="If True, SPM configuration is checked on module " - "initialization.", - groups=['spm'])) - -
-[docs] - def initialize_module(self): - if 'capsul.engine.module.spm' \ - not in self.study_config.engine._loaded_modules: - self.study_config.engine.load_module('capsul.engine.module.spm') - - if type(self.study_config.engine) is not CapsulEngine: - # engine is a proxy, thus we are initialized from a real - # CapsulEngine, which holds the reference values - self.sync_from_engine() - else: - self.sync_to_engine() - # this test aims to raise an exception in case of incorrect setting, - # complying to capsul 2.x behavior. - if self.study_config.use_spm is True: - check_spm_configuration(self.study_config)
- - -
-[docs] - def initialize_callbacks(self): - self.study_config.on_trait_change(self.sync_to_engine, - "[use_spm, spm_+]") - # WARNING ref to self in callback - self.study_config.engine.settings.module_notifiers[ - 'capsul.engine.module.spm'] = [self.sync_from_engine] - self.study_config.engine.settings.module_notifiers[ - 'capsul.engine.module.matlab'] = [self.sync_from_engine]
- - - def sync_from_engine(self, param=None, value=None): - if getattr(self, '_syncing', False): - # manage recursive calls - return - self._syncing = True - try: - if 'SPMConfig' in self.study_config.modules \ - and 'capsul.engine.module.spm' \ - in self.study_config.engine._loaded_modules: - with self.study_config.engine.settings as session: - configs = list(session.configs('spm', 'global')) - configs = sorted( - configs, - key=lambda x: ( - -int(x.version) - if x.version not in ('', None) - else 0) - * 1000 - int(bool(x.standalone))) - mlconfigs = list(session.configs('matlab', 'global')) - mlconfig = None - if len(mlconfigs) != 0: - mlconfig = mlconfigs[0] - if len(configs) != 0: - config = configs[0] - directory = config.directory \ - if config.directory not in (None, '') \ - else Undefined - self.study_config.spm_directory = directory - if mlconfig and mlconfig.mcr_directory: - self.study_config.spm_mcr_directory \ - = mlconfig.mcr_directory - self.study_config.spm_standalone \ - = bool(config.standalone) - if config.version is not None: - self.study_config.spm_version = config.version - else: - self.study_config.spm_version = '0' - if directory not in (None, Undefined): - if config.version: - spm_exec = \ - osp.join(directory, - 'run_spm%s.sh' % config.version) - if os.path.exists(spm_exec): - spm_exec = [spm_exec] - else: - spm_exec = [] - else: - spm_exec = glob.glob(osp.join( - directory, - 'run_spm*.sh')) - if len(spm_exec) != 0: - self.study_config.spm_exec = spm_exec[0] - else: - self.study_config.spm_exec = Undefined - if self.study_config.spm_directory \ - not in (None, Undefined) \ - and self.study_config.spm_exec \ - not in (None, Undefined) \ - and (not self.study_config.spm_standalone - or self.study_config.spm_mcr_directory - not in (None, Undefined)): - self.study_config.use_spm = True - else: - self.study_config.use_spm = False - - finally: - del self._syncing - - def sync_to_engine(self): - if getattr(self, '_syncing', False): - # manage recursive calls - return - self._syncing = True - try: - if 'SPMConfig' in self.study_config.modules \ - and 'capsul.engine.module.spm' \ - in self.study_config.engine._loaded_modules: - with self.study_config.engine.settings as session: - cif = self.study_config.engine.settings.config_id_field - version = self.study_config.spm_version - if version in (None, Undefined): - version = '12' - standalone = (self.study_config.spm_standalone is True) - id = 'spm%s%s' % (version, - '-standalone' if standalone else '') - query = '%s == "%s"' % (cif, id) - config = session.config('spm', 'global', selection=query) - if config is None: - # FIXME: do we keep only one config ? yes for now. - config_ids = [getattr(conf, cif) - for conf in session.configs('spm', - 'global') - if getattr(conf, cif) != id] - for config_id in config_ids: - session.remove_config('spm', 'global', config_id) - sconf = { - 'directory': - self.study_config.spm_directory - if self.study_config.spm_directory - is not Undefined - else None, - 'version': version, - 'standalone': standalone, - cif: id} - session.new_config('spm', 'global', sconf) - else: - tparam = {'spm_directory': 'directory', - 'spm_standalone': 'standalone', - 'spm_version': 'version'} - params = ['spm_directory', - 'spm_standalone', - 'spm_version'] - defaults = {'directory': None, 'standalone': False, - 'version': '12'} - for p in params: - val = getattr(self.study_config, p) - ceparam = tparam[p] - if val is Undefined: - val = defaults.get(ceparam, None) - setattr(config, ceparam, val) - val = self.study_config.spm_exec - if val is Undefined: - val = None - else: - val = osp.dirname(self.study_config.spm_exec) - config.directory = val - - if self.study_config.spm_mcr_directory \ - and self.study_config.spm_standalone: - config = session.config('matlab', 'global', - selection='%s == "matlab"' - % cif) - mcr_dir = self.study_config.spm_mcr_directory - if mcr_dir is Undefined: - mcr_dir = None - if config is None: - session.new_config( - 'matlab', 'global', - {'mcr_directory': mcr_dir, - 'config_id': 'matlab'}) - else: - config.mcr_directory = mcr_dir - finally: - del self._syncing
- -
- -
-
-
-
- -
-
- - - - \ No newline at end of file diff --git a/_modules/capsul/subprocess/fsl.html b/_modules/capsul/subprocess/fsl.html deleted file mode 100644 index 008b146f3..000000000 --- a/_modules/capsul/subprocess/fsl.html +++ /dev/null @@ -1,344 +0,0 @@ - - - - - - - - CAPSUL — CAPSUL - Chain algorithm in pipelines and execute in many contexts - - - - - - - - - - - - - - - - - - - - - - - - - - - -
- - Capsul logo - - -
- - - - - -
-
-
-
- -

Source code for capsul.subprocess.fsl

-# -*- coding: utf-8 -*-
-'''
-Specific subprocess-like functions to call FSL taking into account a 
-potential configuration done in StudyConfig. If a StudyConfig is not
-configured to use FSL, it may be automatically configured. Automatic
-configuration had been tested in the two following cases:
-
-- FSL was installed from the FMRIB site and, at least, FSLDIR 
-  environment variable is set (fsl.sh can be sourced or not)
-- FSL was installed from Neurodebian packages
-
-For calling FSL command with this module, the first argument of
-command line must be the FSL executable without any path nor prefix. 
-Prefix areused  in Neurodebian install. For instance on Ubuntu 16.04 
-Neurodebian FSL commands are prefixed with "fsl5.0-".
-The appropriate path and eventually prefix are added from the configuration
-of the StudyConfig instance.
-
-Classes
-=======
-:class:`Popen`
---------------
-
-Functions
-=========
-:func:`fsl_command_with_environment`
-------------------------------------
-:func:`check_fsl_configuration`
--------------------------------
-:func:`check_configuration_values`
-----------------------------------
-:func:`auto_configuration`
---------------------------
-:func:`call`
-------------
-:func:`check_call`
-------------------
-:func:`check_output`
---------------------
-
-'''
-
-from __future__ import absolute_import
-
-import os
-import os.path as osp
-import soma.subprocess
-
-from traits.api import Undefined
-
-from soma.path import find_in_path
-from capsul.engine.module import fsl as fsl_engine
-
-
-
-[docs] -def fsl_command_with_environment(study_config, command): - ''' - Given an FSL command where first element is a command name without - any path or prefix (e.g. "bet"). Returns the appropriate command to - call taking into account the study_config FSL configuration. - ''' - fsl_dir = os.environ.get('FSLDIR') - if fsl_dir: - dir_prefix = '%s/bin/' % fsl_dir - else: - dir_prefix = '' - fsl_prefix = getattr(study_config, 'fsl_prefix', '') - if fsl_prefix is Undefined: - fsl_prefix = '' - if getattr(study_config, 'fsl_config', Undefined) is Undefined: - cmd = ['%s%s%s' % (dir_prefix, - fsl_prefix, - command[0])] + command[1:] - else: - fsldir = osp.dirname(osp.dirname(osp.dirname(study_config.fsl_config))) - shell = os.environ.get('SHELL', '/bin/sh') - if shell.endswith('csh'): - cmd = [shell, '-c', - 'setenv FSLDIR "{0}";source {0}/etc/fslconf/fsl.csh;exec {0}/bin/{1}{2} '.format(fsldir, fsl_prefix, command[0]) + \ - ' '.join("'%s'" % i.replace("'", "\\'") for i in command[1:])] - else: - cmd = [shell, '-c', - 'export FSLDIR="{0}";. {0}/etc/fslconf/fsl.sh;exec {0}/bin/{1}{2} '.format(fsldir, fsl_prefix, command[0]) + \ - ' '.join("'%s'" % i.replace("'", "\\'") for i in command[1:])] - return cmd
- - -
-[docs] -def check_fsl_configuration(study_config): - ''' - Check thas study_config configuration is valid to call FSL commands. - If not, try to automatically configure FSL. Finally raises an - EnvironmentError if configuration is still wrong. - ''' - - if getattr(study_config, '_fsl_config_checked', False): - # Check FLS configuration only once - return - if 'FSLConfig' not in study_config.modules: - raise EnvironmentError('FSLConfig module is missing in StudyConfig.') - if study_config.use_fsl is False: - raise EnvironmentError('Configuration is set not to use FLS. Set use_fsl to True in order to use FSL.') - # Configuration must be valid otherwise - # try to update configuration and recheck is validity - if check_configuration_values(study_config) is not None: - auto_configuration(study_config) - error_message = check_configuration_values(study_config) - if error_message: - raise EnvironmentError(error_message) - study_config.use_fsl = True - study_config._fsl_config_checked = True
- - -
-[docs] -def check_configuration_values(study_config): - ''' - Check if the configuration is valid to run FLS and returns an error - message if there is an error or None if everything is good. - ''' - - fsl_prefix = getattr(study_config, 'fsl_prefix', '') - if fsl_prefix is Undefined: - fsl_prefix = '' - if study_config.fsl_config is Undefined: - if not find_in_path('%sbet' % fsl_prefix): - return 'FSL command "%sbet" cannot be found in PATH' % fsl_prefix - else: - if fsl_prefix: - return 'FSL configuration must either use fsl_config or fsl_prefix but not both' - if not osp.exists(study_config.fsl_config): - return 'File "%s" does not exist' % study_config.fsl_config - if not study_config.fsl_config.endswith('fsl.sh'): - return 'File "%s" is not a path to fsl.sh script' % study_config.fsl_config - return None
- - -
-[docs] -def auto_configuration(study_config): - ''' - Try to automatically set the study_config configuration for FSL. - ''' - fsl_dir = os.environ.get('FSLDIR') - fsl_prefix = getattr(study_config, 'fsl_prefix', '') - if fsl_prefix is Undefined: - fsl_prefix = '' - if fsl_dir and not fsl_prefix: - # Try to set fsl_config from FSLDIR environment variable - fsl_config = '%s/etc/fslconf/fsl.sh' % fsl_dir - if osp.exists(fsl_config): - study_config.fsl_config = fsl_config - elif not fsl_prefix: - # Try to set fsl_prefix by searching fsl-*bet in PATH - bet = find_in_path('fsl*-bet') - if bet: - study_config.fsl_prefix = osp.basename(bet)[:-3]
- - -
-[docs] -class Popen(soma.subprocess.Popen): - ''' - Equivalent to Python subprocess.Popen for FSL commands - ''' - def __init__(self, study_config, command, **kwargs): - check_fsl_configuration(study_config) - cmd = fsl_command_with_environment(study_config, command) - super(Popen, self).__init__(cmd, **kwargs)
- - -
-[docs] -def call(study_config, command, **kwargs): - ''' - Equivalent to Python subprocess.call for FSL commands - ''' - check_fsl_configuration(study_config) - cmd = fsl_command_with_environment(study_config, command) - return soma.subprocess.call(cmd, **kwargs)
- - -
-[docs] -def check_call(study_config, command, **kwargs): - ''' - Equivalent to Python subprocess.check_call for FSL commands - ''' - check_fsl_configuration(study_config) - cmd = fsl_command_with_environment(study_config, command) - return soma.subprocess.check_call(cmd, **kwargs)
- - - -
-[docs] -def check_output(study_config, command, **kwargs): - ''' - Equivalent to Python subprocess.check_output for FSL commands - ''' - check_fsl_configuration(study_config) - cmd = fsl_command_with_environment(study_config, command) - return soma.subprocess.check_output(cmd, **kwargs)
- -
- -
-
-
-
- -
-
- - - - \ No newline at end of file diff --git a/_modules/index.html b/_modules/index.html index 55685b21b..264b4675f 100644 --- a/_modules/index.html +++ b/_modules/index.html @@ -103,27 +103,14 @@

Navigation

All modules for which code is available

-

_

- +