Skip to content

Commit 8029735

Browse files
committed
Merge branch 'main-master' into maint/1.2.x
* main-master: BF: use smaller float type for rounding error test RF: followlinks optional for dicom file system RF+TST: make big_bad_ulp less likely to / 0 error RF: rename orientation_affine to inv_ornt_aff RF+DOC: remove unused _ornt_affine function BF: fix nasty bug for orientations and 0 columns BF: add missing scripts to setup.py RF: refactor, rename nifti diagnostic script RF: use map instead of list comprehensions DOC: point to nipy organization's nibabel instead of the original Michael's for issues and changes BF: make compatible with pydicom 0.9.7 RF: add informative message when check-files is OK DOC: add/expand docstrings, move code for testers RF: refactor installation checks to check scripts RF: move dicomfs script to nib- naming convention TEST: make travis test with latest pydicom ENH: use logging in dicomfs + optparse to provide control over logging etc ENH: use Python's logging (nibabel.dft level) instead of print statements DOC: add pypirc note for uploading release MISC: start next development series 1.3.x Conflicts: nibabel/info.py
2 parents 7ad90fe + 98c6fdf commit 8029735

File tree

16 files changed

+551
-341
lines changed

16 files changed

+551
-341
lines changed

.travis.yml

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,18 @@ before_install:
1717
- popd
1818
# command to install dependencies, e.g. pip install -r requirements.txt --use-mirrors
1919
install:
20+
# This has to be on a single "virtual line" because of how Travis
21+
# munges each line before executing it to print out the exit status.
22+
# It's okay for it to be on multiple physical lines, so long as you remember:
23+
# - There can't be any leading "-"s
24+
# - All newlines will be removed, so use ";"s
25+
- if [ "${TRAVIS_PYTHON_VERSION:0:1}" \< "3" ]; then
26+
easy_install -U pydicom;
27+
fi
2028
- python setup.py install
2129
# command to run tests, e.g. python setup.py test
2230
script:
2331
# Change into an innocuous directory and find tests from installation
24-
- cd doc
32+
- mkdir for_testing
33+
- cd for_testing
2534
- nosetests `python -c "import os; import nibabel; print(os.path.dirname(nibabel.__file__))"`

Changelog

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@ releases for both packages.
1111

1212
'Close gh-' statements refer to GitHub issues that are available at::
1313

14-
http://github.com/hanke/nibabel/issues
14+
http://github.com/nipy/nibabel/issues
1515

1616
The full VCS changelog is available here:
1717

18-
http://github.com/hanke/nibabel/commits/master
18+
http://github.com/nipy/nibabel/commits/master
1919

2020
Releases
2121
~~~~~~~~

Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -229,6 +229,9 @@ bdist_rpm:
229229
bdist_mpkg:
230230
$(PYTHON) tools/mpkg_wrapper.py setup.py install
231231

232+
# Check for files not installed
233+
check-files:
234+
$(PYTHON) -c 'from nisext.testers import check_files; check_files("nibabel")'
232235

233236
# Print out info for possible install methods
234237
check-version-info:

bin/dicomfs renamed to bin/nib-dicomfs

Lines changed: 69 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -15,15 +15,21 @@ import stat
1515
import errno
1616
import time
1717
import locale
18+
import logging
1819
import fuse
20+
import nibabel as nib
1921
import nibabel.dft as dft
2022

23+
from optparse import OptionParser, Option
24+
2125
uid = os.getuid()
2226
gid = os.getgid()
2327
encoding = locale.getdefaultlocale()[1]
2428

2529
fuse.fuse_python_api = (0, 2)
2630

31+
logger = logging.getLogger('nibabel.dft')
32+
2733
class FileHandle:
2834

2935
def __init__(self, fno):
@@ -38,13 +44,14 @@ class FileHandle:
3844
class DICOMFS(fuse.Fuse):
3945

4046
def __init__(self, *args, **kwargs):
47+
self.followlinks = kwargs.pop('followlinks', False)
4148
fuse.Fuse.__init__(self, *args, **kwargs)
4249
self.fhs = {}
4350
return
4451

4552
def get_paths(self):
4653
paths = {}
47-
for study in dft.get_studies(self.dicom_path):
54+
for study in dft.get_studies(self.dicom_path, self.followlinks):
4855
pd = paths.setdefault(study.patient_name_or_uid(), {})
4956
patient_info = 'patient information\n'
5057
patient_info = 'name: %s\n' % study.patient_name
@@ -78,33 +85,31 @@ class DICOMFS(fuse.Fuse):
7885
def match_path(self, path):
7986
wd = self.get_paths()
8087
if path == '/':
81-
print 'return root'
88+
logger.debug('return root')
8289
return wd
8390
for part in path.lstrip('/').split('/'):
84-
print path, part
91+
logger.debug("path:%s part:%s" % (path, part))
8592
if part not in wd:
8693
return None
8794
wd = wd[part]
88-
print 'return'
95+
logger.debug('return')
8996
return wd
9097

9198
def readdir(self, path, fh):
92-
print 'readdir'
93-
print path
99+
logger.info('readdir %s' % (path,))
94100
matched_path = self.match_path(path)
95101
if matched_path is None:
96102
return -errno.ENOENT
97-
print 'match', matched_path
103+
logger.debug('matched %s' % (matched_path,))
98104
fnames = [ k.encode('ascii', 'replace') for k in matched_path.keys() ]
99105
fnames.append('.')
100106
fnames.append('..')
101107
return [ fuse.Direntry(f) for f in fnames ]
102-
108+
103109
def getattr(self, path):
104-
print 'getattr'
105-
print 'path:', path
110+
logger.debug('getattr %s' % path)
106111
matched_path = self.match_path(path)
107-
print matched_path
112+
logger.debug('matched: %s' % (matched_path,))
108113
now = time.time()
109114
st = fuse.Stat()
110115
if isinstance(matched_path, dict):
@@ -137,10 +142,9 @@ class DICOMFS(fuse.Fuse):
137142
st.st_nlink = 1
138143
return st
139144
return -errno.ENOENT
140-
145+
141146
def open(self, path, flags):
142-
print 'open'
143-
print path
147+
logger.debug('open %s' % (path,))
144148
matched_path = self.match_path(path)
145149
if matched_path is None:
146150
return -errno.ENOENT
@@ -157,34 +161,61 @@ class DICOMFS(fuse.Fuse):
157161

158162
# not done
159163
def read(self, path, size, offset, fh):
160-
print 'read'
161-
print path
162-
print size
163-
print offset
164-
print fh
164+
logger.debug('read')
165+
logger.debug(path)
166+
logger.debug(size)
167+
logger.debug(offset)
168+
logger.debug(fh)
165169
return self.fhs[fh.fno][offset:offset+size]
166170

167171
def release(self, path, flags, fh):
168-
print 'release'
169-
print path
170-
print fh
172+
logger.debug('release')
173+
logger.debug(path)
174+
logger.debug(fh)
171175
del self.fhs[fh.fno]
172176
return
173-
174-
progname = os.path.basename(sys.argv[0])
175-
if len(sys.argv) != 3:
176-
sys.stderr.write('usage: %s <directory containing DICOMs> <mount point>\n' % progname)
177-
sys.exit(1)
178-
179-
fs = DICOMFS(dash_s_do='setsingle')
180-
fs.parse(['-f', '-s', sys.argv[2]])
181-
fs.dicom_path = sys.argv[1].decode(encoding)
182-
try:
183-
fs.main()
184-
except fuse.FuseError:
185-
# fuse prints the error message
186-
sys.exit(1)
187-
188-
sys.exit(0)
177+
178+
def get_opt_parser():
179+
# use module docstring for help output
180+
p = OptionParser(
181+
usage="%s [OPTIONS] <DIRECTORY CONTAINING DICOMSs> <mount point>"
182+
% os.path.basename(sys.argv[0]),
183+
version="%prog " + nib.__version__)
184+
185+
p.add_options([
186+
Option("-v", "--verbose", action="count",
187+
dest="verbose", default=0,
188+
help="make noise. Could be specified multiple times"),
189+
])
190+
191+
p.add_options([
192+
Option("-L", "--follow-links", action="store_true",
193+
dest="followlinks", default=False,
194+
help="Follow symbolic links in DICOM directory"),
195+
])
196+
return p
197+
198+
if __name__ == '__main__':
199+
parser = get_opt_parser()
200+
(opts, files) = parser.parse_args()
201+
202+
if opts.verbose:
203+
logger.addHandler(logging.StreamHandler(sys.stdout))
204+
logger.setLevel(opts.verbose > 1 and logging.DEBUG or logging.INFO)
205+
206+
if len(files) != 2:
207+
sys.stderr.write("Please provide two arguments:\n%s\n" % parser.usage)
208+
sys.exit(1)
209+
210+
fs = DICOMFS(dash_s_do='setsingle', followlinks=opts.followlinks)
211+
fs.parse(['-f', '-s', files[1]])
212+
fs.dicom_path = files[0].decode(encoding)
213+
try:
214+
fs.main()
215+
except fuse.FuseError:
216+
# fuse prints the error message
217+
sys.exit(1)
218+
219+
sys.exit(0)
189220

190221
# eof

bin/nib-nifti-dx

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#!/usr/bin/env python
2+
# emacs: -*- mode: python-mode; py-indent-offset: 4; indent-tabs-mode: nil -*-
3+
# vi: set ft=python sts=4 ts=4 sw=4 et:
4+
### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##
5+
#
6+
# See COPYING file distributed along with the NiBabel package for the
7+
# copyright and license terms.
8+
#
9+
### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ### ##
10+
''' Print nifti diagnostics for header files '''
11+
12+
import sys
13+
14+
from optparse import OptionParser
15+
16+
import nibabel as nib
17+
18+
19+
def main():
20+
""" Go go team """
21+
parser = OptionParser(
22+
usage="%s [FILE ...]\n\n" % sys.argv[0] + __doc__,
23+
version="%prog " + nib.__version__)
24+
(opts, files) = parser.parse_args()
25+
26+
for fname in files:
27+
fobj = nib.volumeutils.allopen(fname)
28+
hdr = fobj.read(nib.nifti1.header_dtype.itemsize)
29+
result = nib.Nifti1Header.diagnose_binaryblock(hdr)
30+
if len(result):
31+
print 'Picky header check output for "%s"\n' % fname
32+
print result
33+
print
34+
else:
35+
print 'Header for "%s" is clean' % fname
36+
37+
38+
if __name__ == '__main__':
39+
main()

bin/nifti1_diagnose.py

Lines changed: 0 additions & 21 deletions
This file was deleted.

doc/source/devel/make_release.rst

Lines changed: 28 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -96,11 +96,20 @@ Release checklist
9696
{'sys_version': '2.6.6 (r266:84374, Aug 31 2010, 11:00:51) \n[GCC 4.0.1 (Apple Inc. build 5493)]', 'commit_source': 'archive substitution', 'np_version': '1.5.0', 'commit_hash': '25b4125', 'pkg_path': '/var/folders/jg/jgfZ12ZXHwGSFKD85xLpLk+++TI/-Tmp-/tmpGPiD3E/pylib/nibabel', 'sys_executable': '/Library/Frameworks/Python.framework/Versions/2.6/Resources/Python.app/Contents/MacOS/Python', 'sys_platform': 'darwin'}
9797
/var/folders/jg/jgfZ12ZXHwGSFKD85xLpLk+++TI/-Tmp-/tmpGPiD3E/pylib/nibabel/__init__.pyc
9898
{'sys_version': '2.6.6 (r266:84374, Aug 31 2010, 11:00:51) \n[GCC 4.0.1 (Apple Inc. build 5493)]', 'commit_source': 'installation', 'np_version': '1.5.0', 'commit_hash': '25b4125', 'pkg_path': '/var/folders/jg/jgfZ12ZXHwGSFKD85xLpLk+++TI/-Tmp-/tmpGPiD3E/pylib/nibabel', 'sys_executable': '/Library/Frameworks/Python.framework/Versions/2.6/Resources/Python.app/Contents/MacOS/Python', 'sys_platform': 'darwin'}
99-
Files not taken across by the installation:
100-
[]
10199
/Users/mb312/dev_trees/nibabel/nibabel/__init__.pyc
102100
{'sys_version': '2.6.6 (r266:84374, Aug 31 2010, 11:00:51) \n[GCC 4.0.1 (Apple Inc. build 5493)]', 'commit_source': 'repository', 'np_version': '1.5.0', 'commit_hash': '25b4125', 'pkg_path': '/Users/mb312/dev_trees/nibabel/nibabel', 'sys_executable': '/Library/Frameworks/Python.framework/Versions/2.6/Resources/Python.app/Contents/MacOS/Python', 'sys_platform': 'darwin'}
103101

102+
* Check the ``setup.py`` file is picking up all the library code and scripts,
103+
with::
104+
105+
make check-files
106+
107+
Look for output at the end about missed files, such as::
108+
109+
Missed script files: /Users/mb312/dev_trees/nibabel/bin/nib-dicomfs, /Users/mb312/dev_trees/nibabel/bin/nifti1_diagnose.py
110+
111+
Fix ``setup.py`` to carry across any files that should be in the distribution.
112+
104113
* You probably have virtualenvs for different python versions. Check the tests
105114
pass for different configurations. If you have pytox_ and a network
106115
connnection, and lots of pythons installed, you might be able to do::
@@ -163,8 +172,23 @@ Release checklist
163172

164173
make source-release
165174

166-
* Once everything looks good, upload the source release to PyPi. See
167-
`setuptools intro`_::
175+
* Once everything looks good, you are ready to upload the source release to
176+
PyPi. See `setuptools intro`_. Make sure you have a file ``\$HOME/.pypirc``,
177+
of form::
178+
179+
[distutils]
180+
index-servers =
181+
pypi
182+
183+
[pypi]
184+
username:your.pypi.username
185+
password:your-password
186+
187+
[server-login]
188+
username:your.pypi.username
189+
password:your-password
190+
191+
* When ready::
168192

169193
python setup.py register
170194
python setup.py sdist --formats=gztar,zip upload

0 commit comments

Comments
 (0)