diff --git a/neuroscout_cli/cli.py b/neuroscout_cli/cli.py
index 8cc1c4d..4294a6c 100644
--- a/neuroscout_cli/cli.py
+++ b/neuroscout_cli/cli.py
@@ -4,6 +4,7 @@
Usage:
neuroscout run [-dfuv -i
-s -w -c -n ] ...
neuroscout install [-ui ] ...
+ neuroscout upload [-f -n ] ...
neuroscout ls
neuroscout -h | --help
neuroscout --version
@@ -25,6 +26,7 @@
Commands:
run Runs analysis.
install Installs a bundle and/or dataset.
+ upload Upload existing analysis results to Neurovault.
ls Lists the available files in a bundle's dataset.
Examples:
@@ -54,11 +56,11 @@ def main():
if hasattr(ncl, k) and val:
k = k[0].upper() + k[1:]
command = getattr(ncl, k)
- if k in ['Run', 'Install']:
+ if k in ['Run', 'Install', 'Upload']:
bundles = args.pop('')
# Loop over bundles
for bundle in bundles:
- logging.info("Running analysis : {}".format(bundle))
+ logging.info("Analysis ID : {}".format(bundle))
args[''] = bundle
command(deepcopy(args)).run()
sys.exit(0)
diff --git a/neuroscout_cli/commands/__init__.py b/neuroscout_cli/commands/__init__.py
index 8881f59..8dfb750 100644
--- a/neuroscout_cli/commands/__init__.py
+++ b/neuroscout_cli/commands/__init__.py
@@ -1,9 +1,11 @@
from .install import Install
from .ls import Ls
from .run import Run
+from .upload import Upload
__all__ = [
'Install',
'Ls',
- 'Run'
+ 'Run',
+ 'Upload'
]
diff --git a/neuroscout_cli/commands/install.py b/neuroscout_cli/commands/install.py
index 4ccbd52..88d17cf 100644
--- a/neuroscout_cli/commands/install.py
+++ b/neuroscout_cli/commands/install.py
@@ -109,5 +109,8 @@ def _check_version(self):
)
sys.exit(1)
- def run(self):
- return self.download_data()
+ def run(self, download_data=True):
+ if download_data:
+ return self.download_data()
+ else:
+ return self.download_bundle()
diff --git a/neuroscout_cli/commands/run.py b/neuroscout_cli/commands/run.py
index 44bbc45..a147c03 100644
--- a/neuroscout_cli/commands/run.py
+++ b/neuroscout_cli/commands/run.py
@@ -15,95 +15,98 @@
class Run(Command):
''' Command for running neuroscout workflows. '''
- def run(self):
+ def run(self, upload_only=False):
# Download bundle and install dataset if necessary
install = Install(self.options.copy())
- bundle_path = install.run()
- preproc_path = str(install.preproc_dir.absolute())
+ bundle_path = install.run(download_data=(not upload_only))
+
out_dir = Path(self.options.pop('')) / install.bundle_id
- smoothing = self.options.pop('--smoothing')
model_path = (bundle_path / 'model.json').absolute()
- fitlins_args = [
- preproc_path,
- str(out_dir),
- 'dataset',
- f'--model={model_path}',
- '--ignore=/(.*desc-confounds_regressors.tsv)/',
- f'--derivatives={bundle_path} {preproc_path}',
- f'--smoothing={smoothing}:Dataset'
- ]
-
- verbose = self.options.pop('--verbose')
- if verbose:
- fitlins_args.append('-vvv')
- work_dir = self.options.pop('--work-dir', None)
- if work_dir:
- work_dir = str(Path(work_dir).absolute() / self.bundle_id)
- fitlins_args.append(f"--work-dir={work_dir}")
-
neurovault = self.options.pop('--neurovault', 'group')
nv_force = self.options.pop('--force-neurovault', False)
if neurovault not in ['disable', 'group', 'all']:
raise ValueError("Invalid neurovault option.")
- # Fitlins invalid keys
- for k in INVALID:
- self.options.pop(k, None)
-
- # Add remaining optional arguments
- for name, value in self.options.items():
- if name.startswith('--'):
- if value is True:
- fitlins_args.append(f'{name}')
- elif value is not None and value is not False:
- fitlins_args.append(f'{name}={value}')
- else:
- if value is not False and value is not None:
- fitlins_args.append(f'{name} {value}')
-
- # Call fitlins as if CLI
- retcode = run_fitlins(fitlins_args)
-
- if retcode == 0:
- if neurovault != 'disable':
-
- model = json.load(open(model_path, 'r'))
- n_subjects = len(model['Input']['Subject'])
-
- logging.info("Uploading results to NeuroVault...")
-
- # Find files
- images = out_dir / 'fitlins'
-
- ses_dirs = [a for a in images.glob('ses*') if a.is_dir()]
- if ses_dirs: # If session, look for stat files in session fld
- images = images / ses_dirs[0]
-
- group = [i for i in images.glob('task*statmap.nii.gz')
- if re.match(
- '.*stat-[t|F|variance|effect]+.*', i.name)]
-
- if neurovault == 'all':
- sub = [i for i in images.glob('sub*/*statmap.nii.gz')
- if re.match('.*stat-[variance|effect]+.*', i.name)]
+ if not upload_only:
+ preproc_path = str(install.preproc_dir.absolute())
+ smoothing = self.options.pop('--smoothing')
+
+ fitlins_args = [
+ preproc_path,
+ str(out_dir),
+ 'dataset',
+ f'--model={model_path}',
+ '--ignore=/(.*desc-confounds_regressors.tsv)/',
+ f'--derivatives={bundle_path} {preproc_path}',
+ f'--smoothing={smoothing}:Dataset'
+ ]
+
+ verbose = self.options.pop('--verbose')
+ if verbose:
+ fitlins_args.append('-vvv')
+ work_dir = self.options.pop('--work-dir', None)
+ if work_dir:
+ work_dir = str(Path(work_dir).absolute() / self.bundle_id)
+ fitlins_args.append(f"--work-dir={work_dir}")
+
+ # Fitlins invalid keys
+ for k in INVALID:
+ self.options.pop(k, None)
+
+ # Add remaining optional arguments
+ for name, value in self.options.items():
+ if name.startswith('--'):
+ if value is True:
+ fitlins_args.append(f'{name}')
+ elif value is not None and value is not False:
+ fitlins_args.append(f'{name}={value}')
else:
- sub = None
-
- # Upload results NeuroVault
- self.api.analyses.upload_neurovault(
- id=self.bundle_id,
- validation_hash=install.resources['validation_hash'],
- group_paths=group, subject_paths=sub,
- force=nv_force,
- n_subjects=n_subjects)
- else:
- logging.error(
- "\n"
- "-----------------------------------------------------------\n"
- "Model execution failed! \n"
- f"neuroscout-cli version: {VERSION}\n"
- "Update this program or revise your model, and try again.\n"
- "If you believe there is a bug, please report it:\n"
- "https://github.com/neuroscout/neuroscout-cli/issues\n"
- "-----------------------------------------------------------\n"
- )
+ if value is not False and value is not None:
+ fitlins_args.append(f'{name} {value}')
+
+ # Call fitlins as if CLI
+ retcode = run_fitlins(fitlins_args)
+
+ if retcode != 0:
+ logging.error(
+ "\n"
+ "-------------------------------------------------------\n"
+ "Model execution failed! \n"
+ f"neuroscout-cli version: {VERSION}\n"
+ "Update neuroscout-cli or revise your model, "
+ "and try again \n"
+ "If you believe there is a bug, please report it:\n"
+ "https://github.com/neuroscout/neuroscout-cli/issues\n"
+ "-------------------------------------------------------\n"
+ )
+
+ if neurovault != 'disable':
+ model = json.load(open(model_path, 'r'))
+ n_subjects = len(model['Input']['Subject'])
+
+ logging.info("Uploading results to NeuroVault...")
+
+ # Find files
+ images = out_dir / 'fitlins'
+
+ ses_dirs = [a for a in images.glob('ses*') if a.is_dir()]
+ if ses_dirs: # If session, look for stat files in session fld
+ images = images / ses_dirs[0]
+
+ group = [i for i in images.glob('task*statmap.nii.gz')
+ if re.match(
+ '.*stat-[t|F|variance|effect]+.*', i.name)]
+
+ if neurovault == 'all':
+ sub = [i for i in images.glob('sub*/*statmap.nii.gz')
+ if re.match('.*stat-[variance|effect]+.*', i.name)]
+ else:
+ sub = None
+
+ # Upload results NeuroVault
+ self.api.analyses.upload_neurovault(
+ id=self.bundle_id,
+ validation_hash=install.resources['validation_hash'],
+ group_paths=group, subject_paths=sub,
+ force=nv_force,
+ n_subjects=n_subjects)
diff --git a/neuroscout_cli/commands/upload.py b/neuroscout_cli/commands/upload.py
new file mode 100644
index 0000000..c15664d
--- /dev/null
+++ b/neuroscout_cli/commands/upload.py
@@ -0,0 +1,8 @@
+from neuroscout_cli.commands.run import Run
+
+
+class Upload(Run):
+ ''' Command for running neuroscout workflows. '''
+
+ def run(self):
+ return super().run(upload_only=True)