From dd37b51c088894fa9436762ba428204b96cd3137 Mon Sep 17 00:00:00 2001
From: Paul McCarthy <pauldmccarthy@gmail.com>
Date: Fri, 31 Jan 2025 12:37:05 +0000
Subject: [PATCH 1/8] BF:: copy+paste typo

---
 pyfeeds/evaluate.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/pyfeeds/evaluate.py b/pyfeeds/evaluate.py
index 3f9bc3c..287a060 100644
--- a/pyfeeds/evaluate.py
+++ b/pyfeeds/evaluate.py
@@ -413,8 +413,8 @@ def loadImage(pyf, filename):
         return pyf.imageCache[filename]
     else:
         img = nib.load(filename)
-        if isinstance(image, nib.Nifti1Image):
-            data = np.asanyarray(image.dataobj)
+        if isinstance(img, nib.Nifti1Image):
+            data = np.asanyarray(img.dataobj)
         else:
             data = None
         return img, data
-- 
GitLab


From 4708e507ab1ebdb1476680ce75ea77f2cc9f822c Mon Sep 17 00:00:00 2001
From: Paul McCarthy <pauldmccarthy@gmail.com>
Date: Fri, 31 Jan 2025 12:37:17 +0000
Subject: [PATCH 2/8] MNT: Accept pathlib.Path, normalise to string for image
 cache keys. All other eval routines should already be compatible

---
 pyfeeds/imagecache.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/pyfeeds/imagecache.py b/pyfeeds/imagecache.py
index aefca31..c101fc0 100644
--- a/pyfeeds/imagecache.py
+++ b/pyfeeds/imagecache.py
@@ -77,7 +77,7 @@ class ImageCache:
         returned value will be ``None``.
         """
 
-        imagefile = op.realpath(op.abspath(imagefile))
+        imagefile = str(op.realpath(op.abspath(imagefile)))
         image     = self.__images.get(imagefile, None)
 
         if image is not None:
@@ -108,7 +108,7 @@ class ImageCache:
         # it in this way because all keys
         # passed to __getitem__ get
         # transformed in the same way.
-        imagefile                    = op.realpath(op.abspath(imagefile))
+        imagefile                    = str(op.realpath(op.abspath(imagefile)))
         imagesize                    = size(image)
         self.__images[    imagefile] = image, data
         self.__imagesizes[imagefile] = imagesize
-- 
GitLab


From 80c380c802b1b031badb8e25037d58ab11ab0a75 Mon Sep 17 00:00:00 2001
From: Paul McCarthy <pauldmccarthy@gmail.com>
Date: Fri, 31 Jan 2025 12:38:02 +0000
Subject: [PATCH 3/8] RF: Adjust evalHeader so it compares all valid
 dimensions. Replace alldims arg with ndims for comparing 3D

---
 pyfeeds/evaluate.py | 27 +++++++++++++--------------
 1 file changed, 13 insertions(+), 14 deletions(-)

diff --git a/pyfeeds/evaluate.py b/pyfeeds/evaluate.py
index 287a060..e4eb575 100644
--- a/pyfeeds/evaluate.py
+++ b/pyfeeds/evaluate.py
@@ -420,9 +420,11 @@ def loadImage(pyf, filename):
         return img, data
 
 
-def evalHeader(testfile, benchmark, alldims=True, pyf=None):
+def evalHeader(testfile, benchmark, ndims=None, pyf=None):
     """Evaluation routine which compares the header fields of two NIFTI
-    images.
+    images. By default the dim/pixdim values for every dimension are compared,
+    but the ``ndims`` argument can be used if you only want to compare the
+    first three dimensions for instance.
 
     Returns 0 if they all match, 1 otherwise.
     """
@@ -437,14 +439,17 @@ def evalHeader(testfile, benchmark, alldims=True, pyf=None):
               'qoffset_x', 'qoffset_y',  'qoffset_z',
               'srow_x',    'srow_y',     'srow_z']
 
+    if ndims is None:
+        ndims = max(img1.header['dim'][0],
+                    img2.header['dim'][0])
+
     for f in fields:
         f1 = hdr1[f]
         f2 = hdr2[f]
 
-        if (not alldims) and (f in ('dim', 'pixdim')):
-            ndim = img1.header['dim'][0]
-            f1   = f1[:ndim + 1]
-            f2   = f2[:ndim + 1]
+        if f in ('dim', 'pixdim'):
+            f1 = f1[:ndims + 1]
+            f2 = f2[:ndims + 1]
 
         if not np.all(np.isclose(f1, f2)):
             return 1
@@ -453,14 +458,8 @@ def evalHeader(testfile, benchmark, alldims=True, pyf=None):
 
 
 def evalHeaderRestrictDims(testfile, benchmark, pyf=None):
-    """Evaluation routine which compares the header fields of two NIFTI
-    images. For the `dim` and `pixdim` fields, only the entries which
-    are expected to be valid (e.g. `dim1`, `dim2`, and `dim3` for a 3D image)
-    are compared.
-
-    Returns 0 if they all match, 1 otherwise.
-    """
-    return evalHeader(testfile, benchmark, alldims=False, pyf=pyf)
+    """Legacy alias for ``evalHeader``. """
+    return evalHeader(testfile, benchmark, pyf=pyf)
 
 
 def evalImage(testfile, benchmark, pyf=None):
-- 
GitLab


From c4c97158cfce152b644a0f78d906949d8f1140b1 Mon Sep 17 00:00:00 2001
From: Paul McCarthy <pauldmccarthy@gmail.com>
Date: Fri, 31 Jan 2025 12:42:08 +0000
Subject: [PATCH 4/8] BF: Not passing pyfeeds object to loadImage

---
 pyfeeds/evaluate.py | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/pyfeeds/evaluate.py b/pyfeeds/evaluate.py
index e4eb575..d7d8e6d 100644
--- a/pyfeeds/evaluate.py
+++ b/pyfeeds/evaluate.py
@@ -429,8 +429,8 @@ def evalHeader(testfile, benchmark, ndims=None, pyf=None):
     Returns 0 if they all match, 1 otherwise.
     """
 
-    img1   = loadImage(testfile)[0]
-    img2   = loadImage(benchmark)[0]
+    img1   = loadImage(pyf, testfile)[0]
+    img2   = loadImage(pyf, benchmark)[0]
     hdr1   = img1.header
     hdr2   = img2.header
     fields = ['dim',       'pixdim',     'intent_code',
-- 
GitLab


From 596657c7a74cce30b2855a78de7e5c212158a682 Mon Sep 17 00:00:00 2001
From: Paul McCarthy <pauldmccarthy@gmail.com>
Date: Fri, 31 Jan 2025 12:46:10 +0000
Subject: [PATCH 5/8] BF: Typos/mistakes in tempdir routine

---
 pyfeeds/common.py | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/pyfeeds/common.py b/pyfeeds/common.py
index 33a49f7..3f02e75 100644
--- a/pyfeeds/common.py
+++ b/pyfeeds/common.py
@@ -45,10 +45,10 @@ def tempdir():
 
     prevdir = os.getcwd()
 
-    with tempfile.TemporaryDirectory(delete=True) as td:
+    with tempfile.TemporaryDirectory() as td:
         try:
-            os.chdir(testdir)
-            yield td.name
+            os.chdir(td)
+            yield td
 
         finally:
             os.chdir(prevdir)
-- 
GitLab


From bb5d2df9b3975dbfe9d5a46c8264af4adc353e16 Mon Sep 17 00:00:00 2001
From: Paul McCarthy <pauldmccarthy@gmail.com>
Date: Fri, 31 Jan 2025 12:53:19 +0000
Subject: [PATCH 6/8] TEST: Tests are useful it turns out. Use
 pyfeeds.common.tempdir instead of pyfeeds.tests.tempdir

---
 pyfeeds/tests/__init__.py      |  13 ----
 pyfeeds/tests/test_config.py   |   2 +-
 pyfeeds/tests/test_evaluate.py | 105 ++++++++++++++++++++++++++++++++-
 pyfeeds/tests/test_hashing.py  |   3 +-
 pyfeeds/tests/test_testing.py  |   3 +-
 5 files changed, 109 insertions(+), 17 deletions(-)

diff --git a/pyfeeds/tests/__init__.py b/pyfeeds/tests/__init__.py
index 7feda33..a3ec65b 100644
--- a/pyfeeds/tests/__init__.py
+++ b/pyfeeds/tests/__init__.py
@@ -9,8 +9,6 @@
 import os
 import sys
 import os.path as op
-import contextlib
-import tempfile
 
 from io import StringIO
 
@@ -61,17 +59,6 @@ class CaptureStdout(object):
         return self.__mock_stderr.read()
 
 
-@contextlib.contextmanager
-def tempdir():
-    prevdir = os.getcwd()
-    with tempfile.TemporaryDirectory() as td:
-        try:
-            os.chdir(td)
-            yield td
-        finally:
-            os.chdir(prevdir)
-
-
 def makepaths(paths):
     for path in paths:
         dirname = op.dirname(path)
diff --git a/pyfeeds/tests/test_config.py b/pyfeeds/tests/test_config.py
index 647201f..02811dc 100644
--- a/pyfeeds/tests/test_config.py
+++ b/pyfeeds/tests/test_config.py
@@ -13,7 +13,7 @@ from   unittest import mock
 
 import pyfeeds.main as main
 
-from pyfeeds.tests import tempdir
+from pyfeeds.common import tempdir
 
 
 def test_loadPyfeedsConfig():
diff --git a/pyfeeds/tests/test_evaluate.py b/pyfeeds/tests/test_evaluate.py
index 4c9b4a0..98ebaf9 100644
--- a/pyfeeds/tests/test_evaluate.py
+++ b/pyfeeds/tests/test_evaluate.py
@@ -11,9 +11,10 @@ import os.path as op
 import numpy as np
 import nibabel as nib
 
-from . import tempdir, makepaths, maketest, makepyfeeds, CaptureStdout
+from . import makepaths, maketest, makepyfeeds, CaptureStdout
 
 from pyfeeds import testing, evaluate
+from pyfeeds.common import tempdir
 
 
 def test_evaluateTestAgainstBenchmark():
@@ -79,6 +80,9 @@ def test_evalVectorImage():
         assert evaluate.evalVectorImage(fname1, fname1, pyf=pyf) == 0
         assert evaluate.evalVectorImage(fname2, fname2, pyf=pyf) == 0
         assert evaluate.evalVectorImage(fname1, fname2, pyf=pyf) != 0
+        assert evaluate.evalVectorImage(fname1, fname1)          == 0
+        assert evaluate.evalVectorImage(fname2, fname2)          == 0
+        assert evaluate.evalVectorImage(fname1, fname2)          != 0
 
 
 def test_evalImage():
@@ -98,3 +102,102 @@ def test_evalImage():
         assert evaluate.evalImage(fname1, fname1, pyf=pyf) == 0
         assert evaluate.evalImage(fname2, fname2, pyf=pyf) == 0
         assert evaluate.evalImage(fname1, fname2, pyf=pyf) != 0
+        assert evaluate.evalImage(fname1, fname1)          == 0
+        assert evaluate.evalImage(fname2, fname2)          == 0
+        assert evaluate.evalImage(fname1, fname2)          != 0
+
+
+def test_evalHeader():
+
+    arr1 = -1 + 2 * np.random.random((10, 10, 10, 10))
+    arr2 = -1 + 2 * np.random.random((10, 10, 10, 10))
+    arr3 = -1 + 2 * np.random.random((10, 10, 10, 20))
+    arr4 = -1 + 2 * np.random.random(( 5,  5,  5, 20))
+
+    with tempdir():
+
+        pyf    = makepyfeeds()
+        fname1 = 'image1.nii.gz'
+        fname2 = 'image2.nii.gz'
+        fname3 = 'image3.nii.gz'
+        fname4 = 'image4.nii.gz'
+
+        nib.Nifti1Image(arr1, np.eye(4)).to_filename(fname1)
+        nib.Nifti1Image(arr2, np.eye(4)).to_filename(fname2)
+        nib.Nifti1Image(arr3, np.eye(4)).to_filename(fname3)
+        nib.Nifti1Image(arr4, np.eye(4)).to_filename(fname4)
+
+        assert evaluate.evalHeader(fname1, fname1, pyf=pyf) == 0
+        assert evaluate.evalHeader(fname2, fname2, pyf=pyf) == 0
+        assert evaluate.evalHeader(fname3, fname3, pyf=pyf) == 0
+        assert evaluate.evalHeader(fname4, fname4, pyf=pyf) == 0
+        assert evaluate.evalHeader(fname1, fname1)          == 0
+        assert evaluate.evalHeader(fname2, fname2)          == 0
+        assert evaluate.evalHeader(fname3, fname3)          == 0
+        assert evaluate.evalHeader(fname4, fname4)          == 0
+
+        assert evaluate.evalHeader(fname1, fname2)          == 0
+        assert evaluate.evalHeader(fname1, fname3)          != 0
+        assert evaluate.evalHeader(fname1, fname4)          != 0
+        assert evaluate.evalHeader(fname1, fname3, ndims=3) == 0
+        assert evaluate.evalHeader(fname3, fname4)          != 0
+        assert evaluate.evalHeader(fname3, fname4, ndims=3) != 0
+
+        assert evaluate.evalHeaderRestrictDims(fname1, fname2, pyf=pyf) == 0
+        assert evaluate.evalHeaderRestrictDims(fname1, fname3, pyf=pyf) != 0
+        assert evaluate.evalHeaderRestrictDims(fname1, fname2)          == 0
+        assert evaluate.evalHeaderRestrictDims(fname1, fname3)          != 0
+
+
+def test_evalImageMaxDiff():
+
+    arr1 = np.zeros((10, 10, 10))
+    arr2 = np.zeros((10, 10, 10))
+
+    arr1[0, 0, 0] = 100
+
+    with tempdir():
+
+        pyf    = makepyfeeds()
+        fname1 = 'image1.nii.gz'
+        fname2 = 'image2.nii.gz'
+        nib.Nifti1Image(arr1, np.eye(4)).to_filename(fname1)
+        nib.Nifti1Image(arr2, np.eye(4)).to_filename(fname2)
+
+        assert evaluate.evalImageMaxDiff(fname1, fname1, pyf=pyf) == 0
+        assert evaluate.evalImageMaxDiff(fname1, fname1)          == 0
+        assert evaluate.evalImageMaxDiff(fname1, fname2)          == 100
+
+def test_evalNumericalText():
+
+    arr1 = np.random.random(100)
+    arr2 = np.random.random(100) * 4
+
+    with tempdir():
+
+        pyf    = makepyfeeds()
+        fname1 = 'data1.txt'
+        fname2 = 'data2.txt'
+        np.savetxt(fname1, arr1)
+        np.savetxt(fname2, arr2)
+
+        assert evaluate.evalNumericalText(fname1, fname1, pyf=pyf) == 0
+        assert evaluate.evalNumericalText(fname1, fname1)          == 0
+        assert evaluate.evalNumericalText(fname1, fname2)          != 0
+
+def test_evalMD5():
+
+    arr1 = np.random.random(100)
+    arr2 = np.random.random(100) * 4
+
+    with tempdir():
+
+        pyf    = makepyfeeds()
+        fname1 = 'data1.txt'
+        fname2 = 'data2.txt'
+        np.savetxt(fname1, arr1)
+        np.savetxt(fname2, arr2)
+
+        assert evaluate.evalMD5(fname1, fname1, pyf=pyf) == 0
+        assert evaluate.evalMD5(fname1, fname1)          == 0
+        assert evaluate.evalMD5(fname1, fname2)          != 0
diff --git a/pyfeeds/tests/test_hashing.py b/pyfeeds/tests/test_hashing.py
index bb303a7..808cab8 100644
--- a/pyfeeds/tests/test_hashing.py
+++ b/pyfeeds/tests/test_hashing.py
@@ -13,8 +13,9 @@ import os.path as op
 import time
 
 from pyfeeds import hashing, testing
+from pyfeeds.common import tempdir
 
-from . import CaptureStdout, makepyfeeds, maketest, makepaths, tempdir
+from . import CaptureStdout, makepyfeeds, maketest, makepaths
 
 
 def test_genHashes():
diff --git a/pyfeeds/tests/test_testing.py b/pyfeeds/tests/test_testing.py
index 3dcadbb..2761aa0 100644
--- a/pyfeeds/tests/test_testing.py
+++ b/pyfeeds/tests/test_testing.py
@@ -10,9 +10,10 @@ import os
 import datetime
 import os.path as op
 
-from . import tempdir, makepaths, maketest, makepyfeeds, CaptureStdout
+from . import makepaths, maketest, makepyfeeds, CaptureStdout
 
 from  pyfeeds import testing
+from  pyfeeds.common import tempdir
 
 
 def test_findTestDirs():
-- 
GitLab


From 477f1738ba8c13f9e0d269fc180a64bcef7783b9 Mon Sep 17 00:00:00 2001
From: Paul McCarthy <pauldmccarthy@gmail.com>
Date: Fri, 31 Jan 2025 12:55:12 +0000
Subject: [PATCH 7/8] DOC: Changelog

---
 CHANGELOG.rst | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/CHANGELOG.rst b/CHANGELOG.rst
index 66c835e..911b6fe 100644
--- a/CHANGELOG.rst
+++ b/CHANGELOG.rst
@@ -2,6 +2,16 @@
 =====================
 
 
+0.14.1 (Friday 31st January 2025)
+---------------------------------
+
+* Fixed a few bugs introduced in the previous release.
+* Adjusted the ``evalHeader`` routine - now it compares ``dim`` and ``pixdim``
+  for all valid dimensions by default. The ``alldims`` parameter has been
+  replaced with a ``ndims`` parameter, allowing the number of dimensions to
+  be set (e.g. when you only want to compare the first three dimensions).
+
+
 0.14.0 (Friday 31st January 2025)
 ---------------------------------
 
-- 
GitLab


From 1f1b86ea085b8f611bb253888289159d3ece51d2 Mon Sep 17 00:00:00 2001
From: Paul McCarthy <pauldmccarthy@gmail.com>
Date: Fri, 31 Jan 2025 12:55:22 +0000
Subject: [PATCH 8/8] MNT: Version

---
 pyfeeds/__init__.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pyfeeds/__init__.py b/pyfeeds/__init__.py
index 5f1fb6a..3171118 100644
--- a/pyfeeds/__init__.py
+++ b/pyfeeds/__init__.py
@@ -5,7 +5,7 @@
 # Author: Paul McCarthy <pauldmccarthy@gmail.com>
 #
 
-__version__ = '0.14.0'
+__version__ = '0.14.1'
 """The pyfeeds version number. """
 
 
-- 
GitLab