diff --git a/cubids/tests/test_bond.py b/cubids/tests/test_bond.py index 26a44b0a..f101a7c2 100644 --- a/cubids/tests/test_bond.py +++ b/cubids/tests/test_bond.py @@ -508,45 +508,47 @@ def test_tsv_merge_changes(tmp_path): assert str(orig.loc[row, "RenameEntitySet"]) != "nan" # TESTING RENAMES GOT APPLIED - applied = pd.read_table(str(tmp_path / "unmodified_summary.tsv")) - applied_f = pd.read_table(str(tmp_path / "unmodified_files.tsv")) + applied_summary_df = pd.read_table(str(tmp_path / "unmodified_summary.tsv")) + applied_files_df = pd.read_table(str(tmp_path / "unmodified_files.tsv")) # Check for inconsistencies between FilePath and KeyParamGroup odd = [] - for row in range(len(applied_f)): - if ( - "VARIANT" in applied_f.loc[row, "FilePath"] - and "VARIANT" not in applied_f.loc[row, "KeyParamGroup"] - ): - odd.append((applied_f.loc[row, "FilePath"])) + for _, row in applied_files_df.iterrows(): + if "VARIANT" in row["FilePath"] and "VARIANT" not in row["KeyParamGroup"]: + odd.append(row["FilePath"]) # Track KeyParamGroups for files with inconsistencies occurrences = {} - for row in range(len(applied_f)): - if applied_f.loc[row, "FilePath"] in odd: - if applied_f.loc[row, "FilePath"] in occurrences.keys(): - occurrences[applied_f.loc[row, "FilePath"]].append( - applied_f.loc[row, "KeyParamGroup"] - ) + for _, row in applied_files_df.iterrows(): + fp = row["FilePath"] + if fp in odd: + if fp in occurrences.keys(): + occurrences[fp].append(row["KeyParamGroup"]) else: - occurrences[applied_f.loc[row, "FilePath"]] = [applied_f.loc[row, "KeyParamGroup"]] + occurrences[fp] = [row["KeyParamGroup"]] # Ensure no rows were lost - assert len(orig) == len(applied) + assert len(orig) == len(applied_summary_df) - # Check for exact matches in EntitySet + # Check that all the RenameEntitySet values are in the renamed entity sets renamed = True - new_keys = applied["EntitySet"].tolist() - for row in range(len(orig)): - if orig.loc[row, "Modality"] != "fmap": - if ( - str(orig.loc[row, "RenameEntitySet"]) != "nan" - and str(orig.loc[row, "RenameEntitySet"]) not in new_keys - ): - print(orig.loc[row, "RenameEntitySet"]) - renamed = False - - assert renamed + new_keys = applied_summary_df["EntitySet"].tolist() + for _, row in orig.iterrows(): + if row["Modality"] == "fmap": + # Ignore field map renaming + continue + + res = row["RenameEntitySet"] + if isinstance(res, str) and (res != "nan") and (res not in new_keys): + print("HI") + print(res) + print("DONE") + renamed = False + + print("\n".join(new_keys)) + print("DONE2") + + assert renamed, orig["RenameEntitySet"].tolist() # will no longer be equal because of auto rename! assert file_hash(original_summary_tsv) != file_hash(tmp_path / "unmodified_summary.tsv") diff --git a/cubids/tests/test_variants.py b/cubids/tests/test_variants.py index c7f2b648..6854bd92 100644 --- a/cubids/tests/test_variants.py +++ b/cubids/tests/test_variants.py @@ -49,8 +49,8 @@ def test_assign_variants_with_cluster_values(base_df): result = assign_variants(base_df, ["EchoTime"]) # Check that variant names include cluster values - assert "acquisition-VARIANTEchoTimeC2_" in result.loc[1, "RenameEntitySet"] - assert "acquisition-VARIANTEchoTimeC3_" in result.loc[2, "RenameEntitySet"] + assert "acquisition-VARIANT+EchoTimeC2_" in result.loc[1, "RenameEntitySet"] + assert "acquisition-VARIANT+EchoTimeC3_" in result.loc[2, "RenameEntitySet"] def test_assign_variants_mixed_parameters(base_df): @@ -64,8 +64,8 @@ def test_assign_variants_mixed_parameters(base_df): result = assign_variants(base_df, ["EchoTime", "FlipAngle"]) # Check variant names include both cluster values and actual values - assert "acquisition-VARIANTEchoTimeC2FlipAngle75_" in result.loc[1, "RenameEntitySet"] - assert "acquisition-VARIANTEchoTimeC3FlipAngle60_" in result.loc[2, "RenameEntitySet"] + assert "acquisition-VARIANT+EchoTimeC2+FlipAngle75_" in result.loc[1, "RenameEntitySet"] + assert "acquisition-VARIANT+EchoTimeC3+FlipAngle60_" in result.loc[2, "RenameEntitySet"] def test_assign_variants_special_parameters(base_df): @@ -78,6 +78,6 @@ def test_assign_variants_special_parameters(base_df): result = assign_variants(base_df, ["HasFieldmap", "UsedAsFieldmap"]) # Check special parameter handling - assert "acquisition-VARIANTOther_" in result.loc[0, "RenameEntitySet"] - assert "acquisition-VARIANTNoFmapIsUsed_" in result.loc[1, "RenameEntitySet"] - assert "acquisition-VARIANTNoFmap_" in result.loc[2, "RenameEntitySet"] + assert "acquisition-VARIANT+Other_" in result.loc[0, "RenameEntitySet"] + assert "acquisition-VARIANT+NoFmap+IsUsed_" in result.loc[1, "RenameEntitySet"] + assert "acquisition-VARIANT+NoFmap_" in result.loc[2, "RenameEntitySet"] diff --git a/cubids/utils.py b/cubids/utils.py index c0f1ab56..ce42d467 100644 --- a/cubids/utils.py +++ b/cubids/utils.py @@ -144,6 +144,10 @@ def _file_to_entity_set(filename): Field maps will have an extraneous "fmap" entity. >>> _file_to_entity_set("sub-01_ses-01_dir-AP_epi.nii.gz") 'direction-AP_fmap-epi_session-01_suffix-epi' + + Plus signs are supported. + >>> _file_to_entity_set("sub-01_ses-01_acq-VARIANT+EchoTimeC1_epi.nii.gz") + 'acquisition-VARIANT+EchoTimeC1_session-01_suffix-epi' """ entities = parse_file_entities(str(filename)) return _entities_to_entity_set(entities) @@ -934,7 +938,11 @@ def assign_variants(summary, rename_cols): renamed = True if summary.loc[row, "ParamGroup"] != 1 and not renamed: - acq_str = "VARIANT" + orig_acq = entities.get("acquisition", "") + if orig_acq == "": + acq_str = "VARIANT" + else: + acq_str = f"{orig_acq}+VARIANT" # now we know we have a deviant param group # check if TR is same as param group 1 entity_set = summary.loc[row, "EntitySet"] @@ -951,19 +959,19 @@ def assign_variants(summary, rename_cols): cluster_val = 0 if cluster_val != dom_entity_set[f"Cluster_{col}"]: - acq_str += f"{col}C{int(cluster_val)}" + acq_str += f"+{col}C{int(cluster_val)}" elif summary.loc[row, col] != dom_entity_set[col]: if col == "HasFieldmap": if dom_entity_set[col] == "True": - acq_str += "NoFmap" + acq_str += "+NoFmap" else: - acq_str += "HasFmap" + acq_str += "+HasFmap" elif col == "UsedAsFieldmap": if dom_entity_set[col] == "True": - acq_str += "Unused" + acq_str += "+Unused" else: - acq_str += "IsUsed" + acq_str += "+IsUsed" else: val = summary.loc[row, col] # If the value is a string float (contains decimal point) @@ -972,18 +980,15 @@ def assign_variants(summary, rename_cols): # If the value is an actual float elif isinstance(val, float): val = str(val).replace(".", "p") - acq_str += f"{col}{val}" + acq_str += f"+{col}{val}" if acq_str == "VARIANT": - acq_str += "Other" + acq_str += "+Other" + acq = f"acquisition-{acq_str}" if "acquisition" in entities.keys(): - acq = f"acquisition-{entities['acquisition'] + acq_str}" - new_name = summary.loc[row, "EntitySet"].replace( - f"acquisition-{entities['acquisition']}", acq - ) + new_name = summary.loc[row, "EntitySet"].replace(f"acquisition-{orig_acq}", acq) else: - acq = f"acquisition-{acq_str}" new_name = acq + "_" + summary.loc[row, "EntitySet"] summary.at[row, "RenameEntitySet"] = new_name diff --git a/docs/usage.rst b/docs/usage.rst index 1d8dfa64..379d3acb 100644 --- a/docs/usage.rst +++ b/docs/usage.rst @@ -184,23 +184,23 @@ CuBIDS populates this column for all Variant Groups Specifically, CuBIDS will suggest renaming all non-dominant Parameter Groups to include ``VARIANT*`` in their acquisition field where ``*`` indicates how the Parameter Group varies from the Dominant Group: -1. For clustered parameters (like EchoTime), the cluster number is used (e.g., ``VARIANTEchoTime2``) -2. For regular parameters (like FlipAngle), the actual value is used (e.g., ``VARIANTFlipAngle75``) +1. For clustered parameters (like EchoTime), the cluster number is used (e.g., ``VARIANT+EchoTimeC2``) +2. For regular parameters (like FlipAngle), the actual value is used (e.g., ``VARIANT+FlipAngle75``) 3. For special parameters: - HasFieldmap variations use ``NoFmap`` or ``HasFmap`` - UsedAsFieldmap variations use ``Unused`` or ``IsUsed`` For example, when CuBIDS encounters a Parameter Group with a clustered EchoTime that varies from the one present in the Dominant Group, it will automatically suggest renaming all scans in that -Variant Group to include ``acquisition-VARIANTEchoTime2`` in their filenames (if the scan belongs +Variant Group to include ``acquisition-VARIANT+EchoTimeC2`` in their filenames (if the scan belongs to cluster 2). -When multiple parameters vary, their names are concatenated (e.g., ``VARIANTEchoTime2FlipAngle75``). +When multiple parameters vary, their names are concatenated (e.g., ``VARIANT+EchoTimeC2+FlipAngle75``). When the user runs ``cubids apply``, filenames will get renamed according to the auto-generated names in the "Rename Entity Set" column in the summary.tsv .. note:: - The above behavior is new as of version 1.2.0. Prior to this, the variant name was just ``VARIANT{parameter}``. + The above behavior is new as of version 1.2.0. Prior to this, the variant name was just ``VARIANT+{parameter}``. Deleting a mistake