-
-
Notifications
You must be signed in to change notification settings - Fork 101
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Second pass at image refactoring #1948
Conversation
@jcohenadad 's points on #1943 are valid for this:
|
@@ -446,17 +440,13 @@ def register_data(im_src, im_dest, param_reg, path_copy_warp=None, rm_tmp=True): | |||
os.chdir(tmp_dir) | |||
# save image and seg | |||
fname_src = 'src.nii.gz' | |||
im_src.setFileName(fname_src) | |||
im_src.save() | |||
im_src.save(fname_src) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i really like this feature. i've been dreaming about it for months
@@ -23,10 +23,10 @@ | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe don't spend too much time cleaning this function because i've slaughtered it quite a lot already: https://github.com/neuropoly/spinalcordtoolbox/blob/jca/1920-process_seg-csa-perslice/scripts/msct_shape.py
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no worries, I'll arrange that after your branch is merged
@@ -639,8 +639,7 @@ def save_centerline(self, image=None, fname_output='centerline.sct'): | |||
coord_pix = image.transfo_phys2pix([current_coord])[0] | |||
image_output.data[int(coord_pix[0]), int(coord_pix[1]), int(coord_pix[2])] = float(self.labels_regions[current_label]) + current_dist_rel | |||
|
|||
image_output.setFileName(fname_output) | |||
image_output.save(type='float32') | |||
image_output.save(fname_output, dtype='float32') |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also a very cool feature
return im_out | ||
|
||
|
||
def orientation(im, ori=None, set=False, get=False, set_data=False, verbose=1, fname_out=None): | ||
def change_orientation_nd(src, orientation, dst=None, inverse=False): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i would suggest to use our conventions for input name, to explicit if this is a file name, an Image object or a nibabel object. So in that case i would replace src
with im_src
for example.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
wilco
scripts/sct_image.py
Outdated
im_out = None | ||
nx, ny, nz, nt, px, py, pz, pt = src.dim | ||
|
||
if dst is None: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same comment, suggestion: im_dst
sct.printv('sct_convert -i ' + fname_in + ' -o ' + fname_out, verbose, 'code') | ||
im = msct_image.Image(fname_in) | ||
if squeeze_data: | ||
im.data = np.squeeze(im.data) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i'm still puzzled as to why in this function squeeze
is on by default. We probably had some issues in the past but i don't remember what. Maybe looking at old closed issues.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We don't remember because no reference to issues or useful comment was left in the code... anyway, we'll see what happens when running tests.
if method_type == 'centerline': | ||
convert(method_val, os.path.join(path_tmp, "centerline.nii.gz")) | ||
Image(method_val).change_orientation("RPI").save(os.path.join(path_tmp, "centerline_RPI.nii")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
any reason to choose nii over nii.gz? i usually prefer nii.gz for sparse data (centerline, seg) because it compresses amazingly well and for extremely large matrix size it speeds up i/o quite a bit
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only for temporary objects.
Here's the rationale:
Today a typical computer
- performs gzip compression at 100 MB/s
- writes to mass storage at > 300 MB/s (ssd) or > 150 MB/s (hdd)
- reads from mass storage at > 500 MB/s (ssd) or > 150 MB/s (hdd)
So using .nii makes the most sense from a speed perspective.
Also, arrays from nii are memory-mapped (whereas those from nii.gz are obviously not).
>>> img1 = nibabel.load("pouet.nii.gz")
>>> type(img1.get_data())
<class 'numpy.ndarray'>
>>> img0 = nibabel.load("pouet.nii")
>>> type(img0.get_data())
<class 'numpy.core.memmap.memmap'>
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cool, i'm convinced. Only for temporary objects though. Storage is still $$$
if method_type == 'point': | ||
convert(method_val, os.path.join(path_tmp, "point.nii.gz")) | ||
Image(method_val).change_orientation("RPI").save(os.path.join(path_tmp, "point_RPI.nii")) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same comment about nii
@@ -174,7 +165,7 @@ def create_mask(param): | |||
|
|||
if method_type == 'centerline': | |||
# get name of centerline from user argument | |||
fname_centerline = 'centerline_RPI.nii.gz' | |||
fname_centerline = 'centerline_RPI.nii' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
same comment about nii
@@ -217,11 +211,10 @@ def extract_sagital_slice(self): | |||
def orient2pir(self): | |||
"""Orient input data to PIR orientation.""" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not sure why this "PIR" suddenly comes in, but it has nothing to do with this PR anyways...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because each person has their own frame of reference ;)
dst.data[:] = 0 | ||
return dst | ||
|
||
def empty_like(img, dtype=None): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
not sure i understand the origin of the name empty_like
. I find it might get confused with zeros_like
. It just does a copy of an Image object, right? so why not calling it copy()
? Or maybe i am missing something
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The implementation of empty_like()
is indeed performing a copy for now, but empty_like is a standard function of numpy which just allocates but doesn't initialize storage. Using this over zeros_like() or copy() makes the intent clearer.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i see. so, what would be example cases where one would prefer to use empty_like() vs. copy()?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I used it for things like:
scripts/sct_compute_hausdorff_distance.py: self.thinned_image = msct_image.empty_like(self.image)
scripts/sct_compute_hausdorff_distance.py- self.thinned_image.data = self.zhang_suen(self.image.data)
scripts/sct_compute_hausdorff_distance.py- self.thinned_image.absolutepath = sct.add_suffix(self.image.absolutepath, "_thinned")
@@ -22,8 +22,8 @@ | |||
import pandas as pd | |||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i'm also doing quite a lot of modifications on this function currently, so many of these modifications might become obsolete.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fantastic work! i added a few single comments. mostly minor.
(not ready yet, afraid I'd merge by mistake)
d2fe5da
to
71d2c44
Compare
As I'm reviewing a lot of code and I'm currently facing issues:
|
I was comparing testing results of the new
|
in response to #1948 (comment), i agree, let's not debug |
Apart from the weird stuff above, some progress...
Failures are due to undiagnosed "different translations" caused by newly introduced orientation and phys-pix code. |
The "different translations" problem was due to a mistake when handling in-place orientation changes (which weren't covered by unit tests). Problem solved. |
tested 38cd048 on
NOT THE SAME --> FAIL 👎
THE SAME --> PASS 👍
THE SAME --> EXPECTED At least with this image, this PR seems to fix this issue, which is pretty awesome. I'll do more testing on this PR. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
testing this PR using batch_processing
. I got this:
UserWarning: Deprecated, this function has no value over msct_image.change_orientation()
jcohen@joplin:~$ code/sct/batch_processing.sh
Removing /home/jcohen/qc_batch_processing folder.
Started at: 2018-08-06_05:54:57 PM
--
Spinal Cord Toolbox ((HEAD/38cd048f5f86db70ad12e67ebd5e5156f1ea1bf2)
Running /home/jcohen/code/sct/scripts/sct_download_data.py -d sct_example_data
Trying URL: https://osf.io/kjcgs/?action=download
Downloading 20180525_sct_example_data.zip...
Status: 100%|#######################################################################################################################################| 44.3M/44.3M [00:00<00:00, 48.1MB/s]
Check if folder already exists...
WARNING: Folder sct_example_data already exists. Removing it...
rm -rf sct_example_data
Unzip data to: /home/jcohen
Remove temporary file...
Done!
Total processing time: 0 min 3 s
--
Spinal Cord Toolbox ((HEAD/38cd048f5f86db70ad12e67ebd5e5156f1ea1bf2)
Running /home/jcohen/code/sct/scripts/sct_propseg.py -i t2.nii.gz -c t2
Loaded /home/jcohen/sct_example_data/t2/t2.nii.gz orientation LPI shape (64, 320, 320)
Loaded /home/jcohen/sct_example_data/t2/t2.nii.gz orientation LPI shape (64, 320, 320)
Loaded /home/jcohen/sct_example_data/t2/t2.nii.gz orientation LPI shape (64, 320, 320)
Detecting the spinal cord using OptiC
cp /home/jcohen/sct_example_data/t2/t2.nii.gz /tmp/sct-20180806175503.328997-8sa4WR
Loaded /home/jcohen/sct_example_data/t2/t2.nii.gz orientation LPI shape (64, 320, 320)
Saving image to t2_int16.nii.gz (/tmp/sct-20180806175503.328997-8sa4WR/t2_int16.nii.gz) orientation LPI shape (64, 320, 320)
Loaded t2_int16_RPI.nii (/tmp/sct-20180806175503.328997-8sa4WR/t2_int16_RPI.nii) orientation RPI shape (64, 320, 320)
cp t2_centerline_optic.nii.gz /home/jcohen/sct_example_data/t2/./
rm -rf /tmp/sct-20180806175503.328997-8sa4WR
isct_propseg -t t2 -o ./ -verbose -i /home/jcohen/sct_example_data/t2/t2.nii.gz -init-centerline ./t2_centerline_optic.nii.gz -centerline-binary # in /home/jcohen/sct_example_data/t2
Initialization - using given centerline
Total propagation length = 208.344 mm
Segmentation finished. To view results, type:
fslview /home/jcohen/sct_example_data/t2/t2.nii.gz ./t2_seg.nii.gz &
Check consistency of segmentation...
Create temporary folder (/tmp/sct-20180806175518.562257-propseg-Y3GC4L)...
Loaded ./t2_seg.nii.gz (/home/jcohen/sct_example_data/t2/t2_seg.nii.gz) orientation LPI shape (64, 320, 320)
Saving image to /tmp/sct-20180806175518.562257-propseg-Y3GC4L/tmp.segmentation.nii.gz orientation LPI shape (64, 320, 320)
Loaded ./t2_centerline.nii.gz (/home/jcohen/sct_example_data/t2/t2_centerline.nii.gz) orientation LPI shape (64, 320, 320)
Saving image to /tmp/sct-20180806175518.562257-propseg-Y3GC4L/tmp.centerline.nii.gz orientation LPI shape (64, 320, 320)
Loaded tmp.segmentation.nii.gz (/tmp/sct-20180806175518.562257-propseg-Y3GC4L/tmp.segmentation.nii.gz) orientation LPI shape (64, 320, 320)
tmp.segmentation.nii.gz
Loaded tmp.segmentation.nii.gz (/tmp/sct-20180806175518.562257-propseg-Y3GC4L/tmp.segmentation.nii.gz) orientation LPI shape (64, 320, 320)
/home/jcohen/code/sct/scripts/sct_image.py:556: UserWarning: Deprecated, this function has no value over msct_image.change_orientation()
warnings.warn("Deprecated, this function has no value over msct_image.change_orientation()")
Saving image to tmp.segmentation_RPI.nii.gz (/tmp/sct-20180806175518.562257-propseg-Y3GC4L/tmp.segmentation_RPI.nii.gz) orientation RPI shape (64, 320, 320)
Saving image to tmp.segmentation_RPI.nii.gz (/tmp/sct-20180806175518.562257-propseg-Y3GC4L/tmp.segmentation_RPI.nii.gz) orientation RPI shape (64, 320, 320)
tmp.centerline.nii.gz
Loaded tmp.centerline.nii.gz (/tmp/sct-20180806175518.562257-propseg-Y3GC4L/tmp.centerline.nii.gz) orientation LPI shape (64, 320, 320)
Saving image to tmp.centerline_RPI.nii.gz (/tmp/sct-20180806175518.562257-propseg-Y3GC4L/tmp.centerline_RPI.nii.gz) orientation RPI shape (64, 320, 320)
Saving image to tmp.centerline_RPI.nii.gz (/tmp/sct-20180806175518.562257-propseg-Y3GC4L/tmp.centerline_RPI.nii.gz) orientation RPI shape (64, 320, 320)
Loaded tmp.segmentation_RPI.nii.gz (/tmp/sct-20180806175518.562257-propseg-Y3GC4L/tmp.segmentation_RPI.nii.gz) orientation RPI shape (64, 320, 320)
Loaded tmp.centerline_RPI.nii.gz (/tmp/sct-20180806175518.562257-propseg-Y3GC4L/tmp.centerline_RPI.nii.gz) orientation RPI shape (64, 320, 320)
I've left the function around for the next refactoring pass. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i got the following bug when running batch_processing
:
--
Spinal Cord Toolbox (cJ/more-image/38cd048f5f86db70ad12e67ebd5e5156f1ea1bf2)
Running /Users/julien/code/sct/scripts/sct_create_mask.py -i mt1.nii.gz -p center -size 45mm
Create temporary folder (/var/folders/6f/wy6ljmx9453cgth2qwv5l1s80000gn/T/sct-20180807151636.362374-create_mask-W2d6Xe)...
Check orientation...
Loaded mt1.nii.gz (/Users/julien/sct_example_data/mt/mt1.nii.gz) orientation LPI shape (192, 192, 22)
.. LPI
Loaded mt1.nii.gz (/Users/julien/sct_example_data/mt/mt1.nii.gz) orientation LPI shape (192, 192, 22)
Saving image to /var/folders/6f/wy6ljmx9453cgth2qwv5l1s80000gn/T/sct-20180807151636.362374-create_mask-W2d6Xe/data_RPI.nii orientation RPI shape (192, 192, 22)
Get dimensions of data...
Loaded data_RPI.nii (/private/var/folders/6f/wy6ljmx9453cgth2qwv5l1s80000gn/T/sct-20180807151636.362374-create_mask-W2d6Xe/data_RPI.nii) orientation RPI shape (192, 192, 22)
192 x 192 x 22 x 1
Create line...
cp data_RPI.nii line.nii
sct_maths -i line.nii -mul 0 -o line.nii # in /private/var/folders/6f/wy6ljmx9453cgth2qwv5l1s80000gn/T/sct-20180807151636.362374-create_mask-W2d6Xe
sct_label_utils -i line.nii -o line.nii -create-add 96,96,0,1: 96,96,1,1: 96,96,2,1: 96,96,3,1: 96,96,4,1: 96,96,5,1: 96,96,6,1: 96,96,7,1: 96,96,8,1: 96,96,9,1: 96,96,10,1: 96,96,11,1: 96,96,12,1: 96,96,13,1: 96,96,14,1: 96,96,15,1: 96,96,16,1: 96,96,17,1: 96,96,18,1: 96,96,19,1: 96,96,20,1: 96,96,21,1 # in /private/var/folders/6f/wy6ljmx9453cgth2qwv5l1s80000gn/T/sct-20180807151636.362374-create_mask-W2d6Xe
Create mask...
Loaded data_mask0.nii (/private/var/folders/6f/wy6ljmx9453cgth2qwv5l1s80000gn/T/sct-20180807151636.362374-create_mask-W2d6Xe/data_mask0.nii) orientation RPI shape (192, 192)
Loaded data_mask1.nii (/private/var/folders/6f/wy6ljmx9453cgth2qwv5l1s80000gn/T/sct-20180807151636.362374-create_mask-W2d6Xe/data_mask1.nii) orientation RPI shape (192, 192)
Loaded data_mask2.nii (/private/var/folders/6f/wy6ljmx9453cgth2qwv5l1s80000gn/T/sct-20180807151636.362374-create_mask-W2d6Xe/data_mask2.nii) orientation RPI shape (192, 192)
Loaded data_mask3.nii (/private/var/folders/6f/wy6ljmx9453cgth2qwv5l1s80000gn/T/sct-20180807151636.362374-create_mask-W2d6Xe/data_mask3.nii) orientation RPI shape (192, 192)
Loaded data_mask4.nii (/private/var/folders/6f/wy6ljmx9453cgth2qwv5l1s80000gn/T/sct-20180807151636.362374-create_mask-W2d6Xe/data_mask4.nii) orientation RPI shape (192, 192)
Loaded data_mask5.nii (/private/var/folders/6f/wy6ljmx9453cgth2qwv5l1s80000gn/T/sct-20180807151636.362374-create_mask-W2d6Xe/data_mask5.nii) orientation RPI shape (192, 192)
Loaded data_mask6.nii (/private/var/folders/6f/wy6ljmx9453cgth2qwv5l1s80000gn/T/sct-20180807151636.362374-create_mask-W2d6Xe/data_mask6.nii) orientation RPI shape (192, 192)
Loaded data_mask7.nii (/private/var/folders/6f/wy6ljmx9453cgth2qwv5l1s80000gn/T/sct-20180807151636.362374-create_mask-W2d6Xe/data_mask7.nii) orientation RPI shape (192, 192)
Loaded data_mask8.nii (/private/var/folders/6f/wy6ljmx9453cgth2qwv5l1s80000gn/T/sct-20180807151636.362374-create_mask-W2d6Xe/data_mask8.nii) orientation RPI shape (192, 192)
Loaded data_mask9.nii (/private/var/folders/6f/wy6ljmx9453cgth2qwv5l1s80000gn/T/sct-20180807151636.362374-create_mask-W2d6Xe/data_mask9.nii) orientation RPI shape (192, 192)
Loaded data_mask10.nii (/private/var/folders/6f/wy6ljmx9453cgth2qwv5l1s80000gn/T/sct-20180807151636.362374-create_mask-W2d6Xe/data_mask10.nii) orientation RPI shape (192, 192)
Loaded data_mask11.nii (/private/var/folders/6f/wy6ljmx9453cgth2qwv5l1s80000gn/T/sct-20180807151636.362374-create_mask-W2d6Xe/data_mask11.nii) orientation RPI shape (192, 192)
Loaded data_mask12.nii (/private/var/folders/6f/wy6ljmx9453cgth2qwv5l1s80000gn/T/sct-20180807151636.362374-create_mask-W2d6Xe/data_mask12.nii) orientation RPI shape (192, 192)
Loaded data_mask13.nii (/private/var/folders/6f/wy6ljmx9453cgth2qwv5l1s80000gn/T/sct-20180807151636.362374-create_mask-W2d6Xe/data_mask13.nii) orientation RPI shape (192, 192)
Loaded data_mask14.nii (/private/var/folders/6f/wy6ljmx9453cgth2qwv5l1s80000gn/T/sct-20180807151636.362374-create_mask-W2d6Xe/data_mask14.nii) orientation RPI shape (192, 192)
Loaded data_mask15.nii (/private/var/folders/6f/wy6ljmx9453cgth2qwv5l1s80000gn/T/sct-20180807151636.362374-create_mask-W2d6Xe/data_mask15.nii) orientation RPI shape (192, 192)
Loaded data_mask16.nii (/private/var/folders/6f/wy6ljmx9453cgth2qwv5l1s80000gn/T/sct-20180807151636.362374-create_mask-W2d6Xe/data_mask16.nii) orientation RPI shape (192, 192)
Loaded data_mask17.nii (/private/var/folders/6f/wy6ljmx9453cgth2qwv5l1s80000gn/T/sct-20180807151636.362374-create_mask-W2d6Xe/data_mask17.nii) orientation RPI shape (192, 192)
Loaded data_mask18.nii (/private/var/folders/6f/wy6ljmx9453cgth2qwv5l1s80000gn/T/sct-20180807151636.362374-create_mask-W2d6Xe/data_mask18.nii) orientation RPI shape (192, 192)
Loaded data_mask19.nii (/private/var/folders/6f/wy6ljmx9453cgth2qwv5l1s80000gn/T/sct-20180807151636.362374-create_mask-W2d6Xe/data_mask19.nii) orientation RPI shape (192, 192)
Loaded data_mask20.nii (/private/var/folders/6f/wy6ljmx9453cgth2qwv5l1s80000gn/T/sct-20180807151636.362374-create_mask-W2d6Xe/data_mask20.nii) orientation RPI shape (192, 192)
Loaded data_mask21.nii (/private/var/folders/6f/wy6ljmx9453cgth2qwv5l1s80000gn/T/sct-20180807151636.362374-create_mask-W2d6Xe/data_mask21.nii) orientation RPI shape (192, 192)
Loaded data_mask0.nii (/private/var/folders/6f/wy6ljmx9453cgth2qwv5l1s80000gn/T/sct-20180807151636.362374-create_mask-W2d6Xe/data_mask0.nii) orientation RPI shape (192, 192)
Saving image to mask_RPI.nii.gz (/private/var/folders/6f/wy6ljmx9453cgth2qwv5l1s80000gn/T/sct-20180807151636.362374-create_mask-W2d6Xe/mask_RPI.nii.gz) orientation RPI shape (192, 192, 22)
Traceback (most recent call last):
File "/Users/julien/code/sct/scripts/sct_create_mask.py", line 383, in <module>
main()
File "/Users/julien/code/sct/scripts/sct_create_mask.py", line 83, in main
create_mask(param)
File "/Users/julien/code/sct/scripts/sct_create_mask.py", line 233, in create_mask
im_out.header = Image(param.fname_data).header
File "/Users/julien/code/sct/scripts/msct_image.py", line 371, in __init__
self.loadFromPath(param, verbose)
File "/Users/julien/code/sct/scripts/msct_image.py", line 456, in loadFromPath
self.im_file = nibabel.load(path)
File "/Users/julien/code/sct/python/lib/python2.7/site-packages/nibabel/loadsave.py", line 40, in load
raise FileNotFoundError("No such file: '%s'" % filename)
nibabel.py3k.FileNotFoundError: No such file: 'mt1.nii.gz'
Sentry is attempting to send 1 pending error messages
Waiting up to 10 seconds
Press Ctrl-C to quit
No handlers could be found for logger "sentry.errors"
Note: you can opt out of Sentry reporting by editing the file ${SCT_DIR}/bin/sct_launcher and delete the line starting with "export SENTRY_DSN"
Total processing time: 0 min 4 s
to reproduce:
cd sct_example_data/mt
sct_create_mask -i mt1.nii.gz -p center -size 45mm
bug on
|
output of batch_processing on 374e8d0 (
master
v3.2.3:
Results are slightly different between Note: the issue with output formatting will be addressed in #1987 |
Orientation changes and physical coordinate computation is done differently (correctly?) now and that could explain slightly different results. I don't see how they would be less accurate than before, so if numbers change, I'd trust the new ones. The locus of these changes is the phys2pix, pix2phys and change_orientation functions, whose diff you could review (and I bet that you'll favor the new versions). |
yeah, i also suspect that results could be more trustable now. I'd still be curious to compare results of |
added tags/milestone because since the produced results are slightly different, we need to justify where those changes come from (hence listing this PR in the changelog). |
results of master-4208eff65079fe7ee3626e0099c5fc54b1c01abe:
cJ/more-image-9b6cdfc0d2967905411c9f1e05987fa4e8fb7aa9:
conclusion: negligible changes. |
Second pass at image refactoring Former-commit-id: d200d8b
A set of change which:
set_orientation()
can be deprecated in favor of an updatedchange_orientation()
. #1944)Done:
.dim
is computed)msct_image
:change_{type,orientation}()
, which can operate in-place or make copiesto_dtype()
, which convets type names or dtype tonp.dtype
change_orientation()
, does what it's supposed to dozeros_like()
which is often used for creating label images or other images with same shape/header but zero dataspatial_crop()
which crops images and replaces somesct_crop_image
internal calls.change_{type,orientation}()
can generate new file names but by default they just void the original one (to prevent overwriting of original data).save()
can modify or not the image contents.save()
can save with the current basename to a new directory (typically used in the scenario of copying to tmp.dir, then changing orientation, then saving)self
so calls can be chainedmsct_image
unit testsset_orientation()
can be deprecated in favor of an updatedchange_orientation()
. #1944 (undocumented reference spaces)