fmriprep-docker 0.3.2__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,18 @@
1
+ Metadata-Version: 1.1
2
+ Name: fmriprep-docker
3
+ Version: 0.3.2
4
+ Summary: fMRIprep is a functional magnetic resonance image pre-processing pipeline that is designed to provide an easily accessible, state-of-the-art interface that is robust to differences in scan acquisition protocols and that requires minimal user input, while providing easily interpretable and comprehensive error and output reporting.
5
+ Home-page: https://github.com/poldracklab/fmriprep
6
+ Author: Christopher J. Markiewicz
7
+ Author-email: crn.poldracklab@gmail.com
8
+ License: 3-clause BSD
9
+ Description: This package is a basic wrapper for fMRIprep that generates the appropriate
10
+ Docker commands, providing an intuitive interface to running the fMRIprep
11
+ workflow in a Docker environment.
12
+ Platform: UNKNOWN
13
+ Classifier: Development Status :: 3 - Alpha
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: License :: OSI Approved :: BSD License
16
+ Classifier: Programming Language :: Python :: 2.7
17
+ Classifier: Programming Language :: Python :: 3.5
18
+ Classifier: Programming Language :: Python :: 3.6
@@ -0,0 +1,18 @@
1
+ Metadata-Version: 1.1
2
+ Name: fmriprep-docker
3
+ Version: 0.3.2
4
+ Summary: fMRIprep is a functional magnetic resonance image pre-processing pipeline that is designed to provide an easily accessible, state-of-the-art interface that is robust to differences in scan acquisition protocols and that requires minimal user input, while providing easily interpretable and comprehensive error and output reporting.
5
+ Home-page: https://github.com/poldracklab/fmriprep
6
+ Author: Christopher J. Markiewicz
7
+ Author-email: crn.poldracklab@gmail.com
8
+ License: 3-clause BSD
9
+ Description: This package is a basic wrapper for fMRIprep that generates the appropriate
10
+ Docker commands, providing an intuitive interface to running the fMRIprep
11
+ workflow in a Docker environment.
12
+ Platform: UNKNOWN
13
+ Classifier: Development Status :: 3 - Alpha
14
+ Classifier: Intended Audience :: Science/Research
15
+ Classifier: License :: OSI Approved :: BSD License
16
+ Classifier: Programming Language :: Python :: 2.7
17
+ Classifier: Programming Language :: Python :: 3.5
18
+ Classifier: Programming Language :: Python :: 3.6
@@ -0,0 +1,9 @@
1
+ fmriprep_docker.py
2
+ setup.py
3
+ fmriprep_docker.egg-info/PKG-INFO
4
+ fmriprep_docker.egg-info/SOURCES.txt
5
+ fmriprep_docker.egg-info/dependency_links.txt
6
+ fmriprep_docker.egg-info/entry_points.txt
7
+ fmriprep_docker.egg-info/not-zip-safe
8
+ fmriprep_docker.egg-info/requires.txt
9
+ fmriprep_docker.egg-info/top_level.txt
@@ -0,0 +1,3 @@
1
+ [console_scripts]
2
+ fmriprep-docker = fmriprep_docker:main
3
+
@@ -0,0 +1 @@
1
+ fmriprep_docker
@@ -0,0 +1,351 @@
1
+ #!/usr/bin/env python
2
+ from __future__ import print_function, unicode_literals, division, absolute_import
3
+ from builtins import int, map, input, zip
4
+ from future import standard_library
5
+ import sys
6
+ import os
7
+ import re
8
+ import argparse
9
+ import subprocess
10
+
11
+ standard_library.install_aliases()
12
+
13
+ __version__ = '0.3.2'
14
+ __packagename__ = 'fmriprep-docker'
15
+ __author__ = 'The CRN developers'
16
+ __copyright__ = 'Copyright 2017, Center for Reproducible Neuroscience, Stanford University'
17
+ __credits__ = ['Craig Moodie', 'Ross Blair', 'Oscar Esteban', 'Chris Gorgolewski',
18
+ 'Shoshana Berleant', 'Christopher J. Markiewicz', 'Russell A. Poldrack']
19
+ __license__ = '3-clause BSD'
20
+ __maintainer__ = 'Christopher J. Markiewicz'
21
+ __email__ = 'crn.poldracklab@gmail.com'
22
+ __url__ = 'https://github.com/poldracklab/fmriprep'
23
+ __bugreports__ = 'https://github.com/poldracklab/fmriprep/issues'
24
+
25
+ __description__ = """\
26
+ fMRIprep is a functional magnetic resonance image pre-processing pipeline \
27
+ that is designed to provide an easily accessible, state-of-the-art interface \
28
+ that is robust to differences in scan acquisition protocols and that requires \
29
+ minimal user input, while providing easily interpretable and comprehensive \
30
+ error and output reporting."""
31
+ __longdesc__ = """\
32
+ This package is a basic wrapper for fMRIprep that generates the appropriate
33
+ Docker commands, providing an intuitive interface to running the fMRIprep
34
+ workflow in a Docker environment."""
35
+
36
+ DOWNLOAD_URL = (
37
+ 'https://pypi.python.org/packages/source/{name[0]}/{name}/{name}-{ver}.tar.gz'.format(
38
+ name=__packagename__, ver=__version__))
39
+
40
+ CLASSIFIERS = [
41
+ 'Development Status :: 3 - Alpha',
42
+ 'Intended Audience :: Science/Research',
43
+ 'License :: OSI Approved :: BSD License',
44
+ 'Programming Language :: Python :: 2.7',
45
+ 'Programming Language :: Python :: 3.5',
46
+ 'Programming Language :: Python :: 3.6',
47
+ ]
48
+
49
+
50
+ MISSING = """
51
+ Image '{}' is missing
52
+ Would you like to download? [Y/n] """
53
+ PKG_PATH = '/usr/local/miniconda/lib/python3.6/site-packages'
54
+
55
+ # Monkey-patch Py2 subprocess
56
+ if not hasattr(subprocess, 'DEVNULL'):
57
+ subprocess.DEVNULL = -3
58
+
59
+ if not hasattr(subprocess, 'run'):
60
+ # Reimplement minimal functionality for usage in this file
61
+ def _run(args, stdout=None, stderr=None):
62
+ from collections import namedtuple
63
+ result = namedtuple('CompletedProcess', 'stdout stderr returncode')
64
+
65
+ devnull = None
66
+ if subprocess.DEVNULL in (stdout, stderr):
67
+ devnull = open(os.devnull, 'r+')
68
+ if stdout == subprocess.DEVNULL:
69
+ stdout = devnull
70
+ if stderr == subprocess.DEVNULL:
71
+ stderr = devnull
72
+
73
+ proc = subprocess.Popen(args, stdout=stdout, stderr=stderr)
74
+ stdout, stderr = proc.communicate()
75
+ res = result(stdout, stderr, proc.returncode)
76
+
77
+ if devnull is not None:
78
+ devnull.close()
79
+
80
+ return res
81
+ subprocess.run = _run
82
+
83
+
84
+ def check_docker():
85
+ """Verify that docker is installed and the user has permission to
86
+ run docker images.
87
+
88
+ Returns
89
+ -------
90
+ -1 Docker can't be found
91
+ 0 Docker found, but user can't connect to daemon
92
+ 1 Test run OK
93
+ """
94
+ try:
95
+ ret = subprocess.run(['docker', 'version'], stdout=subprocess.PIPE,
96
+ stderr=subprocess.PIPE)
97
+ except OSError as e:
98
+ from errno import ENOENT
99
+ if e.errno == ENOENT:
100
+ return -1
101
+ raise e
102
+ if ret.stderr.startswith(b"Cannot connect to the Docker daemon."):
103
+ return 0
104
+ return 1
105
+
106
+
107
+ def check_image(image):
108
+ """Check whether image is present on local system"""
109
+ ret = subprocess.run(['docker', 'images', '-q', image],
110
+ stdout=subprocess.PIPE)
111
+ return bool(ret.stdout)
112
+
113
+
114
+ def check_memory(image):
115
+ """Check total memory from within a docker container"""
116
+ ret = subprocess.run(['docker', 'run', '--rm', '--entrypoint=free',
117
+ image, '-m'],
118
+ stdout=subprocess.PIPE,
119
+ stderr=subprocess.DEVNULL)
120
+ mem = [line.decode().split()[1]
121
+ for line in ret.stdout.splitlines()
122
+ if line.startswith(b'Mem:')][0]
123
+ return int(mem)
124
+
125
+
126
+ def merge_help(wrapper_help, target_help):
127
+ # Matches all flags with up to one nested square bracket
128
+ opt_re = re.compile(r'(\[--?[\w-]+(?:[^\[\]]+(?:\[[^\[\]]+\])?)?\])')
129
+ # Matches flag name only
130
+ flag_re = re.compile(r'\[--?([\w-]+)[ \]]')
131
+
132
+ # Normalize to Unix-style line breaks
133
+ w_help = wrapper_help.rstrip().replace('\r', '')
134
+ t_help = target_help.rstrip().replace('\r', '')
135
+
136
+ w_usage, w_details = w_help.split('\n\n', 1)
137
+ w_groups = w_details.split('\n\n')
138
+ t_usage, t_details = t_help.split('\n\n', 1)
139
+ t_groups = t_details.split('\n\n')
140
+
141
+ w_posargs = w_usage.split('\n')[-1].lstrip()
142
+ t_posargs = t_usage.split('\n')[-1].lstrip()
143
+
144
+ w_options = opt_re.findall(w_usage)
145
+ w_flags = sum(map(flag_re.findall, w_options), [])
146
+ t_options = opt_re.findall(t_usage)
147
+ t_flags = sum(map(flag_re.findall, t_options), [])
148
+
149
+ # The following code makes this assumption
150
+ assert w_flags[:2] == ['h', 'v']
151
+ assert w_posargs.replace(']', '').replace('[', '') == t_posargs
152
+
153
+ # Make sure we're not clobbering options we don't mean to
154
+ overlap = set(w_flags).intersection(t_flags)
155
+ assert overlap == set('hvw'), "Clobbering options: {}".format(
156
+ ', '.join(overlap - set('hvw')))
157
+
158
+ sections = []
159
+
160
+ # Construct usage
161
+ start = w_usage[:w_usage.index(' [')]
162
+ indent = ' ' * len(start)
163
+ new_options = sum((
164
+ w_options[:2],
165
+ [opt for opt, flag in zip(t_options, t_flags) if flag not in overlap],
166
+ w_options[2:]
167
+ ), [])
168
+ opt_line_length = 79 - len(start)
169
+ length = 0
170
+ opt_lines = [start]
171
+ for opt in new_options:
172
+ opt = ' ' + opt
173
+ olen = len(opt)
174
+ if length + olen <= opt_line_length:
175
+ opt_lines[-1] += opt
176
+ length += olen
177
+ else:
178
+ opt_lines.append(indent + opt)
179
+ length = olen
180
+ opt_lines.append(indent + ' ' + t_posargs)
181
+ sections.append('\n'.join(opt_lines))
182
+
183
+ # Use target description and positional args
184
+ sections.extend(t_groups[:2])
185
+
186
+ for line in t_groups[2].split('\n')[1:]:
187
+ content = line.lstrip().split(',', 1)[0]
188
+ if content[1:] not in overlap:
189
+ w_groups[2] += '\n' + line
190
+
191
+ sections.append(w_groups[2])
192
+
193
+ # All remaining sections, show target then wrapper (skipping duplicates)
194
+ sections.extend(t_groups[3:] + w_groups[5:])
195
+ return '\n\n'.join(sections)
196
+
197
+
198
+ def main():
199
+ parser = argparse.ArgumentParser(
200
+ description='fMRI Preprocessing workflow',
201
+ formatter_class=argparse.ArgumentDefaultsHelpFormatter,
202
+ add_help=False)
203
+
204
+ # Standard FMRIPREP arguments
205
+ parser.add_argument('bids_dir', nargs='?', type=str, default='')
206
+ parser.add_argument('output_dir', nargs='?', type=str, default='')
207
+ parser.add_argument('analysis_level', nargs='?', choices=['participant'],
208
+ default='participant')
209
+
210
+ parser.add_argument('-h', '--help', action='store_true',
211
+ help="show this help message and exit")
212
+ parser.add_argument('-v', '--version', action='store_true',
213
+ help="show program's version number and exit")
214
+
215
+ # Allow alternative images (semi-developer)
216
+ parser.add_argument('-i', '--image', metavar='IMG', type=str,
217
+ default='poldracklab/fmriprep:{}'.format(__version__),
218
+ help='image name')
219
+
220
+ g_wrap = parser.add_argument_group(
221
+ 'Wrapper options',
222
+ 'Standard options that require mapping files into the container')
223
+ g_wrap.add_argument('-w', '--work-dir', action='store',
224
+ help='path where intermediate results should be stored')
225
+
226
+ # Developer patch/shell options
227
+ g_dev = parser.add_argument_group(
228
+ 'Developer options',
229
+ 'Tools for testing and debugging FMRIPREP')
230
+ g_dev.add_argument('-f', '--patch-fmriprep', metavar='PATH',
231
+ type=os.path.abspath,
232
+ help='working fmriprep repository')
233
+ g_dev.add_argument('-n', '--patch-niworkflows', metavar='PATH',
234
+ type=os.path.abspath,
235
+ help='working niworkflows repository')
236
+ g_dev.add_argument('-p', '--patch-nipype', metavar='PATH',
237
+ type=os.path.abspath,
238
+ help='working nipype repository')
239
+ g_dev.add_argument('--shell', action='store_true',
240
+ help='open shell in image instead of running FMRIPREP')
241
+ g_dev.add_argument('--config', metavar='PATH', action='store',
242
+ type=os.path.abspath, help='Use custom nipype.cfg file')
243
+
244
+ # Capture additional arguments to pass inside container
245
+ opts, unknown_args = parser.parse_known_args()
246
+
247
+ # Set help if no directories set
248
+ if (opts.bids_dir, opts.output_dir) == ('', ''):
249
+ opts.help = True
250
+
251
+ # Stop if no docker / docker fails to run
252
+ check = check_docker()
253
+ if check < 1:
254
+ if opts.version:
255
+ print('fmriprep wrapper {!s}'.format(__version__))
256
+ if opts.help:
257
+ parser.print_help()
258
+ print("fmriprep: ", end='')
259
+ if check == -1:
260
+ print("Could not find docker command... Is it installed?")
261
+ else:
262
+ print("Make sure you have permission to run 'docker'")
263
+ return 1
264
+
265
+ # For --help or --version, ask before downloading an image
266
+ if not check_image(opts.image):
267
+ resp = 'Y'
268
+ if opts.version:
269
+ print('fmriprep wrapper {!s}'.format(__version__))
270
+ if opts.help:
271
+ parser.print_help()
272
+ if opts.version or opts.help:
273
+ try:
274
+ resp = input(MISSING.format(opts.image))
275
+ except KeyboardInterrupt:
276
+ print()
277
+ return 1
278
+ if resp not in ('y', 'Y', ''):
279
+ return 0
280
+
281
+ # Warn on low memory allocation
282
+ mem_total = check_memory(opts.image)
283
+ if mem_total < 8000:
284
+ print('Warning: <8GB of RAM is available within your Docker '
285
+ 'environment.\nSome parts of fMRIprep may fail to complete.')
286
+ resp = 'N'
287
+ try:
288
+ resp = input('Continue anyway? [y/N]')
289
+ except KeyboardInterrupt:
290
+ print()
291
+ return 1
292
+ if resp not in ('y', 'Y', ''):
293
+ return 0
294
+
295
+ command = ['docker', 'run', '--rm', '-it']
296
+
297
+ # Patch working repositories into installed package directories
298
+ for pkg in ('fmriprep', 'niworkflows', 'nipype'):
299
+ repo_path = getattr(opts, 'patch_' + pkg)
300
+ pkg_path = '{}/{}'.format(PKG_PATH, pkg) # Always POSIX path
301
+ if repo_path is not None:
302
+ command.extend(['-v', '{}:{}:ro'.format(repo_path, pkg_path)])
303
+
304
+ main_args = []
305
+ if opts.bids_dir:
306
+ command.extend(['-v', ':'.join((opts.bids_dir, '/data', 'ro'))])
307
+ main_args.append('/data')
308
+ if opts.output_dir:
309
+ command.extend(['-v', ':'.join((opts.output_dir, '/out'))])
310
+ main_args.append('/out')
311
+ main_args.append(opts.analysis_level)
312
+
313
+ if opts.work_dir:
314
+ command.extend(['-v', ':'.join((opts.work_dir, '/scratch'))])
315
+ unknown_args.extend(['-w', '/scratch'])
316
+
317
+ if opts.config:
318
+ command.extend(['-v', ':'.join((opts.config,
319
+ '/root/.nipype/nipype.cfg', 'ro'))])
320
+
321
+ if opts.shell:
322
+ command.append('--entrypoint=bash')
323
+
324
+ command.append(opts.image)
325
+
326
+ # Override help and version to describe underlying program
327
+ # Respects '-i' flag, so will retrieve information from any image
328
+ if opts.help:
329
+ command.append('-h')
330
+ targethelp = subprocess.check_output(command).decode()
331
+ print(merge_help(parser.format_help(), targethelp))
332
+ return 0
333
+ elif opts.version:
334
+ # Get version to be run and exit
335
+ command.append('-v')
336
+ ret = subprocess.run(command)
337
+ return ret.returncode
338
+
339
+ if not opts.shell:
340
+ command.extend(main_args)
341
+ command.extend(unknown_args)
342
+
343
+ print("RUNNING: " + ' '.join(command))
344
+ ret = subprocess.run(command)
345
+ if ret.returncode:
346
+ print("fmriprep: Please report errors to {}".format(__bugreports__))
347
+ return ret.returncode
348
+
349
+
350
+ if __name__ == '__main__':
351
+ sys.exit(main())
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,43 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+ """ fmriprep wrapper setup script """
4
+
5
+ from setuptools import setup, find_packages
6
+ from os import path as op
7
+ import runpy
8
+
9
+
10
+ def main():
11
+ """ Install entry-point """
12
+ this_path = op.abspath(op.dirname(__file__))
13
+
14
+ info = runpy.run_path(op.join(this_path, 'fmriprep_docker.py'))
15
+
16
+ setup(
17
+ name=info['__packagename__'],
18
+ version=info['__version__'],
19
+ description=info['__description__'],
20
+ long_description=info['__longdesc__'],
21
+ author=info['__author__'],
22
+ author_email=info['__email__'],
23
+ maintainer=info['__maintainer__'],
24
+ maintainer_email=info['__email__'],
25
+ url=info['__url__'],
26
+ license=info['__license__'],
27
+ classifiers=info['CLASSIFIERS'],
28
+ # Dependencies handling
29
+ setup_requires=[],
30
+ install_requires=['future'],
31
+ tests_require=[],
32
+ extras_require={},
33
+ dependency_links=[],
34
+ package_data={},
35
+ py_modules=["fmriprep_docker"],
36
+ entry_points={'console_scripts': ['fmriprep-docker=fmriprep_docker:main']},
37
+ packages=find_packages(),
38
+ zip_safe=False
39
+ )
40
+
41
+
42
+ if __name__ == '__main__':
43
+ main()