Repository: nipy/heudiconv

Issue:
Cached heuristic name discrepancy
<!-- DO NOT DELETE THIS! 
This template is used to facilitate issue resolution.
All text in <!-> tags will not be displayed.
-->

### Summary
When reconverting and using a different heuristic filename from the cache, the conversion table (`filegroup.json`) is still reused. This results in `heudiconv` ignoring the new heuristic and defaulting to the grouping from the previous heuristic. Relevant code excerpt:

https://github.com/nipy/heudiconv/blob/312cd2e5db4968b1d71920aa681ff2795efc3fab/heudiconv/convert.py#L125-L133
...and saving...
https://github.com/nipy/heudiconv/blob/312cd2e5db4968b1d71920aa681ff2795efc3fab/heudiconv/convert.py#L154

**Proposed solution** - save used heuristic in cache simply as `heuristic.py` to avoid any naming discrepancies.




Discussion:

Patch:
diff --git a/heudiconv/convert.py b/heudiconv/convert.py
index 73210c1..5d31b19 100644
--- a/heudiconv/convert.py
+++ b/heudiconv/convert.py
@@ -122,13 +122,21 @@ def prep_conversion(sid, dicoms, outdir, heuristic, converter, anon_sid,
     # detected
     # ref: https://github.com/nipy/heudiconv/issues/84#issuecomment-330048609
     # for more automagical wishes
-    target_heuristic_filename = op.join(idir, op.basename(heuristic.filename))
+    target_heuristic_filename = op.join(idir, 'heuristic.py')
+    # faciliates change - TODO: remove in 1.0
+    old_heuristic_filename = op.join(idir, op.basename(heuristic.filename))
+    if op.exists(old_heuristic_filename):
+        assure_no_file_exists(target_heuristic_filename)
+        safe_copyfile(old_heuristic_filename, target_heuristic_filename)
+        assure_no_file_exists(old_heuristic_filename)
     # TODO:
     #  1. add a test
     #  2. possibly extract into a dedicated function for easier logic flow here
     #     and a dedicated unittest
-    if (op.exists(target_heuristic_filename) and
-        file_md5sum(target_heuristic_filename) != file_md5sum(heuristic.filename)):
+    if (
+        op.exists(target_heuristic_filename) and
+        file_md5sum(target_heuristic_filename) != file_md5sum(heuristic.filename)
+    ):
         # remake conversion table
         reuse_conversion_table = False
         lgr.info(
@@ -151,7 +159,7 @@ def prep_conversion(sid, dicoms, outdir, heuristic, converter, anon_sid,
         # TODO -- might have been done outside already!
         # MG -- will have to try with both dicom template, files
         assure_no_file_exists(target_heuristic_filename)
-        safe_copyfile(heuristic.filename, idir)
+        safe_copyfile(heuristic.filename, target_heuristic_filename)
         if dicoms:
             seqinfo = group_dicoms_into_seqinfos(
                 dicoms,


Test patch:
diff --git a/heudiconv/tests/test_main.py b/heudiconv/tests/test_main.py
index 4656510..7dcd32e 100644
--- a/heudiconv/tests/test_main.py
+++ b/heudiconv/tests/test_main.py
@@ -250,3 +250,22 @@ def test_make_readonly(tmpdir):
         # and it should go back if we set it back to non-read_only
         assert set_readonly(pathname, read_only=False) == rw
         assert not is_readonly(pathname)
+
+
+def test_cache(tmpdir):
+    tmppath = tmpdir.strpath
+    args = (
+        "-f convertall --files %s/axasc35.dcm -s S01"
+        % (TESTS_DATA_PATH)
+    ).split(' ') + ['-o', tmppath]
+    runner(args)
+
+    cachedir = (tmpdir / '.heudiconv' / 'S01' / 'info')
+    assert cachedir.exists()
+
+    # check individual files
+    assert (cachedir / 'heuristic.py').exists()
+    assert (cachedir / 'filegroup.json').exists()
+    assert (cachedir / 'dicominfo.tsv').exists()
+    assert (cachedir / 'S01.auto.txt').exists()
+    assert (cachedir / 'S01.edit.txt').exists()