From 481538195f8fe872d3ed2caab97079202e0ceac7 Mon Sep 17 00:00:00 2001 From: Jan Valosek <39456460+valosekj@users.noreply.github.com> Date: Wed, 14 Feb 2024 14:54:29 -0500 Subject: [PATCH] Add `"Name"` and `"SpatialReference"` key-value pair to JSON sidecar (#76) * Add 'SpatialReference': 'orig' key-value pair based on https://github.com/spinalcordtoolbox/manual-correction/pull/76#issuecomment-1912384077 * Change 'Author' to 'Name' based on https://github.com/spinalcordtoolbox/manual-correction/pull/76#issuecomment-1912384077. Move 'Name' to be first key. * Update tests with 'SpatialReference' and 'Name' keys * Remove the difference between modified and visually verified -- remove the `check_if_modified` function --------- Co-authored-by: Nathan Molinier --- manual_correction.py | 73 ++++++++++++++++++--------------------- tests/test_create_json.py | 27 ++++++++++----- 2 files changed, 52 insertions(+), 48 deletions(-) diff --git a/manual_correction.py b/manual_correction.py index 672b460..bb827fa 100644 --- a/manual_correction.py +++ b/manual_correction.py @@ -485,50 +485,44 @@ def get_modification_time(fname): return datetime.datetime.fromtimestamp(os.path.getmtime(fname)) -def check_if_modified(time_one, time_two): - """ - Check if the file was modified by the user. Return True if the file was modified, False otherwise. - :param time_one: modification time of the file before viewing - :param time_two: modification time of the file after viewing - :return: - """ - if time_one != time_two: - print("The label file was modified.") - return True - else: - print("The label file was not modified.") - return False - - -def update_json(fname_nifti, name_rater, modified): +def update_json(fname_nifti, name_rater): """ Create/update JSON sidecar with meta information :param fname_nifti: str: File name of the nifti image to associate with the JSON sidecar :param name_rater: str: Name of the expert rater - :param modified: bool: True if the file was modified by the user :return: """ fname_json = fname_nifti.replace('.gz', '').replace('.nii', '.json') - if modified: - if os.path.exists(fname_json): - # Read already existing json file - with open(fname_json, "r") as outfile: # r to read - json_dict = json.load(outfile) - - # Special check to fix all of our current json files (Might be deleted later) - if 'GeneratedBy' not in json_dict.keys(): - json_dict = {'GeneratedBy': [json_dict]} - else: - # Init new json dict - json_dict = {'GeneratedBy': []} - - # Add new author with time and date - json_dict['GeneratedBy'].append({'Author': name_rater, 'Date': time.strftime('%Y-%m-%d %H:%M:%S')}) - with open(fname_json, 'w') as outfile: # w to overwrite the file - json.dump(json_dict, outfile, indent=4) - # Add last newline - outfile.write("\n") - print("JSON sidecar was updated: {}".format(fname_json)) + + # Check if the json file already exists, if so, open it + if os.path.exists(fname_json): + # Read already existing json file + with open(fname_json, "r") as outfile: # r to read + json_dict = json.load(outfile) + + # Special checks to fix all of our current json files (Might be deleted later) + if 'GeneratedBy' not in json_dict.keys(): + json_dict = {'GeneratedBy': [json_dict]} + if 'SpatialReference' not in json_dict.keys(): + json_dict['SpatialReference'] = 'orig' + + # If the json file does not exist, initialize a new one + else: + # Init new json dict + json_dict = {'SpatialReference': 'orig', + 'GeneratedBy': []} + + # If the label was modified or just checked, add "Name": "Manual" to the JSON sidecar + json_dict['GeneratedBy'].append({'Name': 'Manual', + 'Author': name_rater, + 'Date': time.strftime('%Y-%m-%d %H:%M:%S')}) + + # Write the data to the JSON file + with open(fname_json, 'w') as outfile: # w to overwrite the file + json.dump(json_dict, outfile, indent=4) + # Add last newline + outfile.write("\n") + print("JSON sidecar was updated: {}".format(fname_json)) def ask_if_modify(fname_out, fname_label, do_labeling_always=False): @@ -884,11 +878,10 @@ def main(): if args.add_seg_only: # We are passing modified=True because we are adding a new segmentation and we want # to create a JSON file - update_json(fname_out, name_rater, modified=True) + update_json(fname_out, name_rater) # Generate QC report else: - modified = check_if_modified(time_one, time_two) - update_json(fname_out, name_rater, modified) + update_json(fname_out, name_rater) # Generate QC report generate_qc(fname, fname_out, task, fname_qc, subject, args.config, args.qc_lesion_plane, suffix_dict) diff --git a/tests/test_create_json.py b/tests/test_create_json.py index b33bc92..246d7c5 100644 --- a/tests/test_create_json.py +++ b/tests/test_create_json.py @@ -13,7 +13,7 @@ def test_create_json(tmp_path): """ - Test that the function update_json() creates a JSON file with the expected metadata if modified=True. + Test that the function update_json() creates a JSON file with the expected metadata """ # Create a temporary file for testing fname_label = "sub-001_ses-01_T1w_seg-manual.nii.gz" @@ -21,10 +21,13 @@ def test_create_json(tmp_path): nifti_file.touch() # Call the function with modified=True - update_json(str(nifti_file), "Test Rater", modified=True) + update_json(str(nifti_file), "Test Rater") # Check that the JSON file was created and contains the expected metadata - expected_metadata = {'GeneratedBy': [{'Author': "Test Rater", 'Date': time.strftime('%Y-%m-%d %H:%M:%S')}]} + expected_metadata = {'SpatialReference': 'orig', + 'GeneratedBy': [{'Name': 'Manual', + 'Author': "Test Rater", + 'Date': time.strftime('%Y-%m-%d %H:%M:%S')}]} json_file = tmp_path / fname_label.replace(".nii.gz", ".json") assert json_file.exists() with open(str(json_file), "r") as f: @@ -34,7 +37,7 @@ def test_create_json(tmp_path): def test_update_json(tmp_path): """ - Test that the function update_json() updates (appends to) the JSON file with the expected metadata if modified=True. + Test that the function update_json() updates (appends to) the JSON file with the expected metadata. """ # Create a temporary file for testing fname_label = "sub-001_ses-01_T1w_seg-manual.nii.gz" @@ -43,14 +46,22 @@ def test_update_json(tmp_path): # Create JSON file with some metadata json_file = tmp_path / fname_label.replace(".nii.gz", ".json") with open(str(json_file), "w") as f: - json.dump({'GeneratedBy': [{'Author': "Test Rater 1", 'Date': "2023-01-01 00:00:00"}]}, f) + json.dump({'SpatialReference': 'orig', + 'GeneratedBy': [{'Name': 'Manual', + 'Author': "Test Rater 1", + 'Date': "2023-01-01 00:00:00"}]}, f) # Call the function with modified=True - update_json(str(nifti_file), "Test Rater 2", modified=True) + update_json(str(nifti_file), "Test Rater 2") # Check that the JSON file was created and contains the expected metadata - expected_metadata = {'GeneratedBy': [{'Author': "Test Rater 1", 'Date': "2023-01-01 00:00:00"}, - {'Author': "Test Rater 2", 'Date': time.strftime('%Y-%m-%d %H:%M:%S')}]} + expected_metadata = {'SpatialReference': 'orig', + 'GeneratedBy': [{'Name': 'Manual', + 'Author': "Test Rater 1", + 'Date': "2023-01-01 00:00:00"}, + {'Name': 'Manual', + 'Author': "Test Rater 2", + 'Date': time.strftime('%Y-%m-%d %H:%M:%S')}]} json_file = tmp_path / fname_label.replace(".nii.gz", ".json") assert json_file.exists() with open(str(json_file), "r") as f: