Skip to content

Commit

Permalink
Merge pull request #476 from matthew-brett/to-entry-points
Browse files Browse the repository at this point in the history
MRG: refactor scripts into entry points

Now we depend on setuptools, use entry points for scripts.

Thanks @effigies for the suggestion.
  • Loading branch information
matthew-brett committed Feb 24, 2021
2 parents 278d1e6 + b5e9fad commit 4188fb3
Show file tree
Hide file tree
Showing 15 changed files with 77 additions and 143 deletions.
3 changes: 3 additions & 0 deletions .appveyor.yml
Expand Up @@ -15,7 +15,10 @@ environment:
- PYTHON: C:\Python37
- PYTHON: C:\Python37-x64
- PYTHON: C:\Python38
# https://stackoverflow.com/a/58582651/1939576
EXTRA_FLAGS: "--traverse-namespace"
- PYTHON: C:\Python38-x64
EXTRA_FLAGS: "--traverse-namespace"

install:
# Prepend newly installed Python to the PATH of this build (this cannot be
Expand Down
6 changes: 3 additions & 3 deletions .travis.yml
Expand Up @@ -113,12 +113,12 @@ install:
elif [ "$INSTALL_TYPE" == "setup" ]; then
python setup.py install
elif [ "$INSTALL_TYPE" == "sdist" ]; then
python setup_egg.py egg_info # check egg_info while we're here
python setup_egg.py sdist
python setup.py egg_info # check egg_info while we're here
python setup.py sdist
pip install $EXTRA_PIP_FLAGS dist/*.tar.gz
elif [ "$INSTALL_TYPE" == "wheel" ]; then
pip install wheel
python setup_egg.py bdist_wheel
python setup.py bdist_wheel
pip install $EXTRA_PIP_FLAGS dist/*.whl
elif [ "$INSTALL_TYPE" == "requirements" ]; then
pip install $EXTRA_PIP_FLAGS -r requirements.txt
Expand Down
4 changes: 4 additions & 0 deletions nipy/algorithms/registration/tests/test_scripting.py
Expand Up @@ -4,6 +4,7 @@
from __future__ import absolute_import

from os.path import split as psplit
import gc

import numpy as np

Expand Down Expand Up @@ -36,6 +37,9 @@ def test_space_time_realign():
assert_false(np.allclose(xforms[-1].as_affine(), np.eye(4), atol=1e-3))
img = load_image(out_fname)
npt.assert_almost_equal(original_affine, img.affine)
# To avoid Windows "file ... used by another process" error when
# removing temporary directory.
gc.collect()


def test_aff2euler():
Expand Down
2 changes: 2 additions & 0 deletions nipy/cli/__init__.py
@@ -0,0 +1,2 @@
""" Logic for command line scripts.
"""
11 changes: 3 additions & 8 deletions scripts/nipy_diagnose → nipy/cli/diagnose.py
@@ -1,4 +1,3 @@
#!python
# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
# vi: set ft=python sts=4 ts=4 sw=4 et:
DESCRIP = 'Calculate and write results for diagnostic screen'
Expand Down Expand Up @@ -29,15 +28,15 @@
/some/path/max_fname.img`` etc.
'''

import matplotlib
matplotlib.use('Agg')

from nipy.externals.argparse import (ArgumentParser,
RawDescriptionHelpFormatter)
import nipy.algorithms.diagnostics.commands as nadc


def main():
import matplotlib
matplotlib.use('Agg')

parser = ArgumentParser(description=DESCRIP,
epilog=EPILOG,
formatter_class=RawDescriptionHelpFormatter)
Expand All @@ -56,7 +55,3 @@ def main():
# parse the command line
args = parser.parse_args()
nadc.diagnose(args)


if __name__ == '__main__':
main()
5 changes: 0 additions & 5 deletions scripts/nipy_3dto4d → nipy/cli/img3dto4d.py
@@ -1,4 +1,3 @@
#!python
# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
# vi: set ft=python sts=4 ts=4 sw=4 et:
DESCRIP = 'Read 3D image files and write a 4D file'
Expand Down Expand Up @@ -60,7 +59,3 @@ def main():
out_fname = pjoin(pth, froot + '_4d' + ext + gz)
img4d = do_3d_to_4d(filenames, check_affines=check_affines)
nib.save(img4d, out_fname)


if __name__ == '__main__':
main()
5 changes: 0 additions & 5 deletions scripts/nipy_4dto3d → nipy/cli/img4dto3d.py
@@ -1,4 +1,3 @@
#!python
# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
# vi: set ft=python sts=4 ts=4 sw=4 et:
DESCRIP = 'Read 4D image file and write 3D nifti file for each volume'
Expand Down Expand Up @@ -35,7 +34,3 @@ def main():
for i, img3d in enumerate(imgs):
fname3d = '%s_%04d.nii' % (froot, i)
nib.save(img3d, fname3d)


if __name__ == '__main__':
main()
34 changes: 16 additions & 18 deletions scripts/nipy_4d_realign → nipy/cli/realign4d.py
@@ -1,15 +1,14 @@
#!python
# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
# vi: set ft=python sts=4 ts=4 sw=4 et:

"""This is a wrapper of SpaceTimeRealign
"""Command line wrapper of SpaceTimeRealign
Based on:
Alexis Roche (2011) A Four-Dimensional Registration Algorithm With Application to Joint Correction of Motion and Slice Timing in fMRI. IEEE Trans. Med. Imaging 30(8): 1546-1554
Alexis Roche (2011) A Four-Dimensional Registration Algorithm With Application
to Joint Correction of Motion and Slice Timing in fMRI. IEEE Trans. Med.
Imaging 30(8): 1546-1554
"""
import os

import os.path as op
import nipy.algorithms.registration as reg
import nipy.externals.argparse as argparse
Expand Down Expand Up @@ -42,26 +41,25 @@
help="""Whether to save the motion corrections parameters (3 rotations, 3 translations). {True, False}. Default: False. NOTE: The rotations are not Euler angles, but a rotation vector. Use `nipy.algorithms.registration.to_matrix44` to convert to a 4-by-4 affine matrix""", default=False)


# parse the command line
args = parser.parse_args()
def main():
args = parser.parse_args()

if __name__ == '__main__':
if args.save_path == 'none':
save_path = op.split(args.input)[0]
else:
save_path = args.save_path

xform = reg.space_time_realign(args.input, float(args.TR),
slice_order=args.slice_order,
slice_dim=int(args.slice_dim),
slice_dir=int(args.slice_dir),
apply=True, # We always apply the xform in the cli
make_figure=args.make_figure,
out_name=save_path)
slice_order=args.slice_order,
slice_dim=int(args.slice_dim),
slice_dir=int(args.slice_dir),
# We always apply the xform in the cli
apply=True,
make_figure=args.make_figure,
out_name=save_path)

if args.save_params:

f = file(op.join(save_path, 'mc.par'), 'w')
f = open(op.join(save_path, 'mc.par'), 'w')
for x in xform:
euler_rot = reg.aff2euler(x.as_affine())
for r in euler_rot:
Expand Down
13 changes: 13 additions & 0 deletions nipy/cli/setup.py
@@ -0,0 +1,13 @@
from __future__ import absolute_import
# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
# vi: set ft=python sts=4 ts=4 sw=4 et:
def configuration(parent_package='',top_path=None):
from numpy.distutils.misc_util import Configuration

config = Configuration('cli', parent_package, top_path)

return config

if __name__ == '__main__':
from numpy.distutils.core import setup
setup(**configuration(top_path='').todict())
9 changes: 2 additions & 7 deletions scripts/nipy_tsdiffana → nipy/cli/tsdiffana.py
@@ -1,10 +1,9 @@
#!python
# emacs: -*- mode: python; py-indent-offset: 4; indent-tabs-mode: nil -*-
# vi: set ft=python sts=4 ts=4 sw=4 et:
DESCRIP = ' Analyze, plot time series difference metrics'
EPILOG = \
'''nipy_tsdiffana runs the time series diference algorithm over a 4D
image volume, often and FMRI volume.
'''Runs the time series difference algorithm over a 4D image volume, often an
FMRI volume.
It works in one of three modes:
Expand Down Expand Up @@ -97,7 +96,3 @@ def main():
tsdiffana(args)
if show:
plt.show()


if __name__ == '__main__':
main()
1 change: 1 addition & 0 deletions nipy/setup.py
Expand Up @@ -55,6 +55,7 @@ def configuration(parent_package='',top_path=None):
config.add_subpackage('utils')
config.add_subpackage('tests')
config.add_subpackage('externals')
config.add_subpackage('cli')
config.add_subpackage('testing')

# Note: this is a special subpackage containing that will later be
Expand Down
3 changes: 0 additions & 3 deletions nipy/tests/scriptrunner.py
Expand Up @@ -128,9 +128,6 @@ def run_command(self, cmd, check_code=True):
# the script through the Python interpreter
cmd = [sys.executable,
pjoin(self.local_script_dir, cmd[0])] + cmd[1:]
elif os.name == 'nt':
# Need .bat file extension for windows
cmd[0] += '.bat'
if os.name == 'nt':
# Quote any arguments with spaces. The quotes delimit the arguments
# on Windows, and the arguments might be files paths with spaces.
Expand Down
42 changes: 27 additions & 15 deletions setup.py
Expand Up @@ -10,6 +10,9 @@
# update it when the contents of directories change.
if exists('MANIFEST'): os.remove('MANIFEST')

# Always use setuptools
import setuptools

from setup_helpers import (generate_a_pyrex_source, get_comrec_build,
cmdclass, INFO_VARS)

Expand Down Expand Up @@ -39,20 +42,19 @@ def configuration(parent_package='',top_path=None):
return config

################################################################################
# Use setuptools
from setup_egg import extra_setuptools_args

# Hard and soft dependency checking
DEPS = (
('numpy', INFO_VARS['NUMPY_MIN_VERSION'], 'setup_requires', True),
('scipy', INFO_VARS['SCIPY_MIN_VERSION'], 'install_requires', True),
('nibabel', INFO_VARS['NIBABEL_MIN_VERSION'], 'install_requires', False),
('sympy', INFO_VARS['SYMPY_MIN_VERSION'], 'install_requires', False))

for name, min_ver, req_type, heavy in DEPS:
('numpy', INFO_VARS['NUMPY_MIN_VERSION'], 'setup_requires'),
('scipy', INFO_VARS['SCIPY_MIN_VERSION'], 'install_requires'),
('nibabel', INFO_VARS['NIBABEL_MIN_VERSION'], 'install_requires'),
('sympy', INFO_VARS['SYMPY_MIN_VERSION'], 'install_requires'),
)

requirement_kwargs = {'setup_requires': [], 'install_requires': []}
for name, min_ver, req_type in DEPS:
new_req = '{0}>={1}'.format(name, min_ver)
old_reqs = extra_setuptools_args.get(req_type, [])
extra_setuptools_args[req_type] = old_reqs + [new_req]
requirement_kwargs[req_type].append(new_req)


################################################################################
Expand Down Expand Up @@ -100,7 +102,7 @@ def run(self):
################################################################################


def main(**extra_args):
def main():
from numpy.distutils.core import setup

setup(name=INFO_VARS['NAME'],
Expand All @@ -116,12 +118,22 @@ def main(**extra_args):
author_email=INFO_VARS['AUTHOR_EMAIL'],
platforms=INFO_VARS['PLATFORMS'],
# version set by config.get_version() above
requires=INFO_VARS['REQUIRES'],
configuration = configuration,
cmdclass = cmdclass,
scripts = glob('scripts/*'),
**extra_args)
tests_require=['nose>=1.0'],
test_suite='nose.collector',
zip_safe=False,
entry_points={
'console_scripts': [
'nipy_3dto4d = nipy.cli.img3dto4d:main',
'nipy_4dto3d = nipy.cli.img4dto3d:main',
'nipy_4d_realign = nipy.cli.realign4d:main',
'nipy_tsdiffana = nipy.cli.tsdiffana:main',
'nipy_diagnose = nipy.cli.diagnose:main',
],
},
**requirement_kwargs)


if __name__ == "__main__":
main(**extra_setuptools_args)
main()
20 changes: 0 additions & 20 deletions setup_egg.py

This file was deleted.

0 comments on commit 4188fb3

Please sign in to comment.