From b5e21e1f1338854574c0e9f6b41f18ec4c3003a6 Mon Sep 17 00:00:00 2001 From: alex-l-kong Date: Mon, 28 Mar 2022 13:15:09 -0700 Subject: [PATCH 1/3] Add ROI prefix to FOV names generated for tiling ROIs --- toffy/settings.py | 4 +-- toffy/tiling_utils.py | 6 +++- toffy/tiling_utils_test.py | 48 ++++++++++++++++++++++++++------ toffy/tiling_utils_test_cases.py | 18 +++++++----- 4 files changed, 58 insertions(+), 18 deletions(-) diff --git a/toffy/settings.py b/toffy/settings.py index efe83e29..f51bca5f 100644 --- a/toffy/settings.py +++ b/toffy/settings.py @@ -1,6 +1,6 @@ # tiled regions -REGION_PARAM_FIELDS = ['region_start_row', 'region_start_col', 'fov_num_row', 'fov_num_col', - 'row_fov_size', 'col_fov_size', 'region_rand'] +REGION_PARAM_FIELDS = ['roi_name', 'region_start_row', 'region_start_col', + 'fov_num_row', 'fov_num_col', 'row_fov_size', 'col_fov_size', 'region_rand'] # mibitracker MIBITRACKER_BACKEND = 'https://backend-dot-mibitracker-angelolab.appspot.com' diff --git a/toffy/tiling_utils.py b/toffy/tiling_utils.py index 8177ac33..9bdbf7c6 100644 --- a/toffy/tiling_utils.py +++ b/toffy/tiling_utils.py @@ -280,6 +280,9 @@ def read_tiled_region_inputs(region_corners, region_params): # read in the data for each fov (region_start from region_corners_path, all others from user) for fov in region_corners['fovs']: + # append the name of the ROI + region_params['roi_name'].append(fov['name']) + # append the starting row and column coordinates region_params['region_start_row'].append(fov['centerPointMicrons']['y']) region_params['region_start_col'].append(fov['centerPointMicrons']['x']) @@ -547,7 +550,8 @@ def generate_tiled_region_fov_list(tiling_params, moly_path): row_col_pairs = generate_x_y_fov_pairs(row_range, col_range) # name the FOVs according to MIBI conventions - fov_names = ['R%dC%d' % (y + 1, x + 1) for x in range(region_info['fov_num_row']) + fov_names = ['%s_R%dC%d' % (region_info['roi_name'], y + 1, x + 1) + for x in range(region_info['fov_num_row']) for y in range(region_info['fov_num_col'])] # randomize pairs list if specified diff --git a/toffy/tiling_utils_test.py b/toffy/tiling_utils_test.py index 67adad53..747af908 100644 --- a/toffy/tiling_utils_test.py +++ b/toffy/tiling_utils_test.py @@ -359,11 +359,12 @@ def test_generate_tiled_region_fov_list(moly_path, moly_region_setting, moly_interval_setting, moly_interval_value, moly_insert_indices, fov_1_end_pos, randomize_setting): sample_fovs_list = test_utils.generate_sample_fovs_list( - fov_coords=[(0, 0), (100, 100)], fov_names=["TheFirstFOV", "TheSecondFOV"], + fov_coords=[(0, 0), (100, 100)], fov_names=['TheFirstFOV', 'TheSecondFOV'], fov_sizes=[5, 10] ) sample_region_inputs = { + 'roi_name': ['TheFirstFOV', 'TheSecondFOV'], 'region_start_row': [100, 150], 'region_start_col': [0, 50], 'fov_num_row': [2, 4], @@ -412,6 +413,11 @@ def test_generate_tiled_region_fov_list(moly_path, moly_region_setting, for fov in fov_regions['fovs'] ] + # retrieve the fov names + fov_names = [ + fov['name'] for fov in fov_regions['fovs'] + ] + # define the center points sorted actual_center_points_sorted = [ (x, y) for x in np.arange(0, 10, 5) for y in list(reversed(np.arange(85, 105, 5))) @@ -419,47 +425,73 @@ def test_generate_tiled_region_fov_list(moly_path, moly_region_setting, (x, y) for x in np.arange(50, 90, 10) for y in list(reversed(np.arange(140, 160, 10))) ] + # define the corresponding FOV names + actual_fov_names = [ + 'TheFirstFOV_R%dC%d' % (x, y) for y in np.arange(1, 3) for x in np.arange(1, 5) + ] + [ + 'TheSecondFOV_R%dC%d' % (x, y) for y in np.arange(1, 5) for x in np.arange(1, 3) + ] + for mi in moly_insert_indices: actual_center_points_sorted.insert(mi, (14540, -10830)) + actual_fov_names.insert(mi, 'MoQC') - # easiest case: the center points should be sorted + # easiest case: the center points and FOV names should be sorted if randomize_setting == ['N', 'N']: assert center_points == actual_center_points_sorted + assert fov_names == actual_fov_names + # if only the second fov is randomized elif randomize_setting == ['N', 'Y']: - # ensure the fov 1 center points are the same for both sorted and random + # ensure the fov 1 center points and FOV names are the same for both sorted and random assert center_points[:fov_1_end_pos] == actual_center_points_sorted[:fov_1_end_pos] + assert fov_names[:fov_1_end_pos] == actual_fov_names[:fov_1_end_pos] - # ensure the random center points for fov 2 contain the same elements + # ensure the random center points and fov names for roi 2 contain the same elements # as its sorted version misc_utils.verify_same_elements( computed_center_points=center_points[fov_1_end_pos:], actual_center_points=actual_center_points_sorted[fov_1_end_pos:] ) + misc_utils.verify_same_elements( + computed_fov_names=fov_names[fov_1_end_pos:], + actual_fov_names=actual_fov_names[fov_1_end_pos:] + ) - # however, fov 2 sorted entries should NOT equal fov 2 random entries + # however, roi 2 sorted entries should NOT equal roi 2 random entries assert center_points[fov_1_end_pos:] != actual_center_points_sorted[fov_1_end_pos:] + assert fov_names[fov_1_end_pos:] != actual_fov_names[fov_1_end_pos:] # if both fovs are randomized elif randomize_setting == ['Y', 'Y']: - # ensure the random center points for fov 1 contain the same elements + # ensure the random center points and fov names for roi 1 contain the same elements # as its sorted version misc_utils.verify_same_elements( computed_center_points=center_points[:fov_1_end_pos], actual_center_points=actual_center_points_sorted[:fov_1_end_pos] ) + misc_utils.verify_same_elements( + computed_fov_names=fov_names[:fov_1_end_pos], + actual_fov_names=actual_fov_names[:fov_1_end_pos] + ) - # however, fov 1 sorted entries should NOT equal fov 1 random entries + # however, roi 1 sorted entries should NOT equal roi 1 random entries assert center_points[:fov_1_end_pos] != actual_center_points_sorted[:fov_1_end_pos] + assert fov_names[:fov_1_end_pos] != actual_fov_names[:fov_1_end_pos] - # ensure the random center points for fov 2 contain the same elements + # ensure the random center points for roi 2 contain the same elements # as its sorted version misc_utils.verify_same_elements( computed_center_points=center_points[fov_1_end_pos:], actual_center_points=actual_center_points_sorted[fov_1_end_pos:] ) + misc_utils.verify_same_elements( + computed_fov_names=fov_names[fov_1_end_pos:], + actual_fov_names=actual_fov_names[fov_1_end_pos:] + ) # however, fov 2 sorted entries should NOT equal fov 2 random entries assert center_points[fov_1_end_pos:] != actual_center_points_sorted[fov_1_end_pos:] + assert fov_names[fov_1_end_pos:] != actual_fov_names[fov_1_end_pos:] @parametrize_with_cases('top_left, top_right, bottom_left, bottom_right', diff --git a/toffy/tiling_utils_test_cases.py b/toffy/tiling_utils_test_cases.py index 657b0103..34754b67 100644 --- a/toffy/tiling_utils_test_cases.py +++ b/toffy/tiling_utils_test_cases.py @@ -40,11 +40,18 @@ def case_reentry_different_type(self): return generate_fiducial_read_vals(user_input_type='diff_types') +# define the list of region start coords and names +_TILED_REGION_FOV_COORDS = [(50, 150), (100, 300)] +_TILED_REGION_FOV_NAMES = ["TheFirstFOV", "TheSecondFOV"] +_TILED_REGION_FOV_SIZES = [1000, 2000] + + # this function assumes that FOV 2's corresponding values are linearly spaced from FOV 1's # NOTE: x and y correspond to column and row index respectively as specified in the JSON spec file def generate_tiled_region_params(start_x_fov_1=50, start_y_fov_1=150, num_row_fov_1=4, num_col_fov_1=2, - row_size_fov_1=2, col_size_fov_1=1, num_fovs=2): + row_size_fov_1=2, col_size_fov_1=1, num_fovs=2, + fov_names=deepcopy(_TILED_REGION_FOV_NAMES)): # define this dictionary for testing purposes to ensure that function calls # equal what would be placed in param_set_values base_param_values = { @@ -67,6 +74,9 @@ def generate_tiled_region_params(start_x_fov_1=50, start_y_fov_1=150, for param in base_param_values } + # set the names for each region + full_param_set['roi_name'] = fov_names + # TODO: might want to return just one and have the test function generate the other return base_param_values, full_param_set @@ -107,12 +117,6 @@ def generate_tiled_region_cases(fov_coord_list, fov_name_list, fov_sizes, return fov_coord_list, fov_name_list, fov_sizes, user_inputs, base_param_values, full_param_set -# define the list of region start coords and names -_TILED_REGION_FOV_COORDS = [(50, 150), (100, 300)] -_TILED_REGION_FOV_NAMES = ["TheFirstFOV", "TheSecondFOV"] -_TILED_REGION_FOV_SIZES = [1000, 2000] - - # NOTE: because of the way the moly_interval param is handled # it is generated directly in the tiling_utils_test test function class TiledRegionReadCases: From 2049e6982dec26f6d73f107ecf19e9b7b95fe7f4 Mon Sep 17 00:00:00 2001 From: alex-l-kong Date: Mon, 28 Mar 2022 15:19:48 -0700 Subject: [PATCH 2/3] Standardize user-facing prompts to display ROI instead of region --- toffy/tiling_utils.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/toffy/tiling_utils.py b/toffy/tiling_utils.py index 9bdbf7c6..67671213 100644 --- a/toffy/tiling_utils.py +++ b/toffy/tiling_utils.py @@ -287,15 +287,15 @@ def read_tiled_region_inputs(region_corners, region_params): region_params['region_start_row'].append(fov['centerPointMicrons']['y']) region_params['region_start_col'].append(fov['centerPointMicrons']['x']) - print("Using start coordinates of (%d, %d) in microns for region %s" + print("Using start coordinates of (%d, %d) in microns for ROI %s" % (fov['centerPointMicrons']['x'], fov['centerPointMicrons']['y'], fov['name'])) # verify that the micron size specified is valid if fov['fovSizeMicrons'] <= 0: - raise ValueError("The fovSizeMicrons field for region %s must be positive" + raise ValueError("The fovSizeMicrons field for ROI %s must be positive" % fov['name']) - print("Using FOV step size of %d microns for both row (y) and column (x) axis of region %s" + print("Using FOV step size of %d microns for both row (y) and column (x) axis of ROI %s" % (fov['fovSizeMicrons'], fov['name'])) # use fovSizeMicrons as the step size along both axes @@ -304,14 +304,14 @@ def read_tiled_region_inputs(region_corners, region_params): # allow the user to specify the number of fovs along each dimension num_row = read_tiling_param( - "Enter the number of FOVs per row for region %s: " % fov['name'], + "Enter the number of FOVs per row for ROI %s: " % fov['name'], "Error: number of FOVs per row must be a positive integer", lambda nx: nx >= 1, dtype=int ) num_col = read_tiling_param( - "Enter the number of FOVs per column for region %s: " % fov['name'], + "Enter the number of FOVs per column for ROI %s: " % fov['name'], "Error: number of FOVs per column must be a positive integer", lambda ny: ny >= 1, dtype=int @@ -322,7 +322,7 @@ def read_tiled_region_inputs(region_corners, region_params): # allow the user to specify if the FOVs should be randomized randomize = read_tiling_param( - "Randomize FOVs for region %s? Y/N: " % fov['name'], + "Randomize FOVs for ROI %s? Y/N: " % fov['name'], "Error: randomize parameter must Y or N", lambda r: r in ['Y', 'N', 'y', 'n'], dtype=str @@ -378,8 +378,8 @@ def set_tiled_region_params(region_corners_path): # whether to insert moly points between regions moly_region_insert = read_tiling_param( - "Insert a moly point between each tiled region? Y/N: ", - "Error: moly point region parameter must be either Y or N", + "Insert a moly point between each tiled ROI? Y/N: ", + "Error: moly point ROI parameter must be either Y or N", lambda mri: mri in ['Y', 'N', 'y', 'n'], dtype=str ) From d702a8cf93b653a0654bdbe32b9b733994580d03 Mon Sep 17 00:00:00 2001 From: alex-l-kong Date: Mon, 28 Mar 2022 16:06:36 -0700 Subject: [PATCH 3/3] Make sure ROI is used instead of FOV where needed --- toffy/settings.py | 2 +- toffy/tiling_utils.py | 26 ++++----- toffy/tiling_utils_test.py | 95 ++++++++++++++++---------------- toffy/tiling_utils_test_cases.py | 72 ++++++++++++------------ 4 files changed, 98 insertions(+), 97 deletions(-) diff --git a/toffy/settings.py b/toffy/settings.py index f51bca5f..beae614f 100644 --- a/toffy/settings.py +++ b/toffy/settings.py @@ -1,5 +1,5 @@ # tiled regions -REGION_PARAM_FIELDS = ['roi_name', 'region_start_row', 'region_start_col', +REGION_PARAM_FIELDS = ['region_name', 'region_start_row', 'region_start_col', 'fov_num_row', 'fov_num_col', 'row_fov_size', 'col_fov_size', 'region_rand'] # mibitracker diff --git a/toffy/tiling_utils.py b/toffy/tiling_utils.py index 67671213..623194cf 100644 --- a/toffy/tiling_utils.py +++ b/toffy/tiling_utils.py @@ -278,24 +278,24 @@ def read_tiled_region_inputs(region_corners, region_params): A `dict` mapping each region-specific parameter to a list of values per FOV """ - # read in the data for each fov (region_start from region_corners_path, all others from user) + # read in the data for each region (region_start from region_corners_path, others from user) for fov in region_corners['fovs']: - # append the name of the ROI - region_params['roi_name'].append(fov['name']) + # append the name of the region + region_params['region_name'].append(fov['name']) # append the starting row and column coordinates region_params['region_start_row'].append(fov['centerPointMicrons']['y']) region_params['region_start_col'].append(fov['centerPointMicrons']['x']) - print("Using start coordinates of (%d, %d) in microns for ROI %s" + print("Using start coordinates of (%d, %d) in microns for region %s" % (fov['centerPointMicrons']['x'], fov['centerPointMicrons']['y'], fov['name'])) # verify that the micron size specified is valid if fov['fovSizeMicrons'] <= 0: - raise ValueError("The fovSizeMicrons field for ROI %s must be positive" + raise ValueError("The fovSizeMicrons field for FOVs in region %s must be positive" % fov['name']) - print("Using FOV step size of %d microns for both row (y) and column (x) axis of ROI %s" + print("Using FOV step size of %d microns for both row (y) and column (x) axis of region %s" % (fov['fovSizeMicrons'], fov['name'])) # use fovSizeMicrons as the step size along both axes @@ -304,14 +304,14 @@ def read_tiled_region_inputs(region_corners, region_params): # allow the user to specify the number of fovs along each dimension num_row = read_tiling_param( - "Enter the number of FOVs per row for ROI %s: " % fov['name'], + "Enter the number of FOVs per row for region %s: " % fov['name'], "Error: number of FOVs per row must be a positive integer", lambda nx: nx >= 1, dtype=int ) num_col = read_tiling_param( - "Enter the number of FOVs per column for ROI %s: " % fov['name'], + "Enter the number of FOVs per column for region %s: " % fov['name'], "Error: number of FOVs per column must be a positive integer", lambda ny: ny >= 1, dtype=int @@ -322,7 +322,7 @@ def read_tiled_region_inputs(region_corners, region_params): # allow the user to specify if the FOVs should be randomized randomize = read_tiling_param( - "Randomize FOVs for ROI %s? Y/N: " % fov['name'], + "Randomize FOVs for region %s? Y/N: " % fov['name'], "Error: randomize parameter must Y or N", lambda r: r in ['Y', 'N', 'y', 'n'], dtype=str @@ -334,7 +334,7 @@ def read_tiled_region_inputs(region_corners, region_params): def set_tiled_region_params(region_corners_path): - """Given a file specifying FOV regions, set the MIBI tiling parameters. + """Given a file specifying top-left FOVs for a set of regions, set the MIBI tiling parameters. User inputs will be required for many values. Units used are microns. @@ -378,8 +378,8 @@ def set_tiled_region_params(region_corners_path): # whether to insert moly points between regions moly_region_insert = read_tiling_param( - "Insert a moly point between each tiled ROI? Y/N: ", - "Error: moly point ROI parameter must be either Y or N", + "Insert a moly point between each tiled region? Y/N: ", + "Error: moly point region parameter must be either Y or N", lambda mri: mri in ['Y', 'N', 'y', 'n'], dtype=str ) @@ -550,7 +550,7 @@ def generate_tiled_region_fov_list(tiling_params, moly_path): row_col_pairs = generate_x_y_fov_pairs(row_range, col_range) # name the FOVs according to MIBI conventions - fov_names = ['%s_R%dC%d' % (region_info['roi_name'], y + 1, x + 1) + fov_names = ['%s_R%dC%d' % (region_info['region_name'], y + 1, x + 1) for x in range(region_info['fov_num_row']) for y in range(region_info['fov_num_col'])] diff --git a/toffy/tiling_utils_test.py b/toffy/tiling_utils_test.py index 747af908..d4c0cc31 100644 --- a/toffy/tiling_utils_test.py +++ b/toffy/tiling_utils_test.py @@ -210,12 +210,12 @@ def test_save_coreg_params(): cases=test_cases.TiledRegionReadCases, glob='*_no_moly_param') def test_read_tiled_region_inputs(monkeypatch, fov_coords, fov_names, fov_sizes, user_inputs, base_param_values, full_param_set): - # define a sample fovs list + # define a sample fovs list to define the top-left corners of each tiled region sample_fovs_list = test_utils.generate_sample_fovs_list( fov_coords=fov_coords, fov_names=fov_names, fov_sizes=fov_sizes ) - # define sample region_params to read data into + # define sample_region_params to read data into sample_region_params = {rpf: [] for rpf in settings.REGION_PARAM_FIELDS} # generate the user inputs @@ -269,14 +269,14 @@ def test_generate_region_info(): @parametrize('region_corners_file', [param('bad_region_corners.json', marks=file_missing_err), param('tiled_region_corners.json')]) @parametrize_with_cases( - 'fov_coords, fov_names, fov_sizes, user_inputs, base_param_values,full_param_set', + 'fov_coords, fov_names, fov_sizes, user_inputs, base_param_values, full_param_set', cases=test_cases.TiledRegionReadCases, glob='*_with_moly_param' ) @parametrize('moly_interval_val', [0, 1]) def test_set_tiled_region_params(monkeypatch, region_corners_file, fov_coords, fov_names, fov_sizes, user_inputs, base_param_values, full_param_set, moly_interval_val): - # define a sample set of fovs + # define a sample set of fovs to define the top-left corners of each tiled region sample_fovs_list = test_utils.generate_sample_fovs_list( fov_coords=fov_coords, fov_names=fov_names, fov_sizes=fov_sizes ) @@ -351,20 +351,21 @@ def test_generate_x_y_fov_pairs_rhombus(coords, actual_pairs): @parametrize_with_cases( - 'moly_path, moly_region_setting, moly_interval_setting, moly_interval_value, ' - 'moly_insert_indices, fov_1_end_pos', cases=test_cases.TiledRegionMolySettingCases + 'moly_path, moly_roi_setting, moly_interval_setting, moly_interval_value, ' + 'moly_insert_indices, roi_1_end_pos', cases=test_cases.TiledRegionMolySettingCases ) @parametrize('randomize_setting', [['N', 'N'], ['N', 'Y'], ['Y', 'Y']]) -def test_generate_tiled_region_fov_list(moly_path, moly_region_setting, +def test_generate_tiled_region_fov_list(moly_path, moly_roi_setting, moly_interval_setting, moly_interval_value, - moly_insert_indices, fov_1_end_pos, randomize_setting): - sample_fovs_list = test_utils.generate_sample_fovs_list( - fov_coords=[(0, 0), (100, 100)], fov_names=['TheFirstFOV', 'TheSecondFOV'], + moly_insert_indices, roi_1_end_pos, randomize_setting): + # define a set of fovs defining the upper-left corners of each region + sample_roi_fovs_list = test_utils.generate_sample_fovs_list( + fov_coords=[(0, 0), (100, 100)], fov_names=['TheFirstROI', 'TheSecondROI'], fov_sizes=[5, 10] ) sample_region_inputs = { - 'roi_name': ['TheFirstFOV', 'TheSecondFOV'], + 'region_name': ['TheFirstROI', 'TheSecondROI'], 'region_start_row': [100, 150], 'region_start_col': [0, 50], 'fov_num_row': [2, 4], @@ -378,7 +379,7 @@ def test_generate_tiled_region_fov_list(moly_path, moly_region_setting, sample_tiling_params = { 'fovFormatVersion': '1.5', - 'fovs': sample_fovs_list['fovs'], + 'fovs': sample_roi_fovs_list['fovs'], 'region_params': sample_region_params } @@ -391,7 +392,7 @@ def test_generate_tiled_region_fov_list(moly_path, moly_region_setting, with open(sample_moly_path, 'w') as smp: json.dump(sample_moly_point, smp) - sample_tiling_params['moly_region'] = moly_region_setting + sample_tiling_params['moly_region'] = moly_roi_setting sample_tiling_params['region_params'][0]['region_rand'] = randomize_setting[0] sample_tiling_params['region_params'][1]['region_rand'] = randomize_setting[1] @@ -399,23 +400,23 @@ def test_generate_tiled_region_fov_list(moly_path, moly_region_setting, if moly_interval_setting: sample_tiling_params['moly_interval'] = moly_interval_value - fov_regions = tiling_utils.generate_tiled_region_fov_list( + fov_list = tiling_utils.generate_tiled_region_fov_list( sample_tiling_params, os.path.join(td, moly_path) ) # assert none of the metadata keys explicitly added by set_tiling_params appear for k in ['region_params', 'moly_region', 'moly_interval']: - assert k not in fov_regions + assert k not in fov_list # retrieve the center points center_points = [ (fov['centerPointMicrons']['x'], fov['centerPointMicrons']['y']) - for fov in fov_regions['fovs'] + for fov in fov_list['fovs'] ] # retrieve the fov names fov_names = [ - fov['name'] for fov in fov_regions['fovs'] + fov['name'] for fov in fov_list['fovs'] ] # define the center points sorted @@ -427,9 +428,9 @@ def test_generate_tiled_region_fov_list(moly_path, moly_region_setting, # define the corresponding FOV names actual_fov_names = [ - 'TheFirstFOV_R%dC%d' % (x, y) for y in np.arange(1, 3) for x in np.arange(1, 5) + 'TheFirstROI_R%dC%d' % (x, y) for y in np.arange(1, 3) for x in np.arange(1, 5) ] + [ - 'TheSecondFOV_R%dC%d' % (x, y) for y in np.arange(1, 5) for x in np.arange(1, 3) + 'TheSecondROI_R%dC%d' % (x, y) for y in np.arange(1, 5) for x in np.arange(1, 3) ] for mi in moly_insert_indices: @@ -441,57 +442,57 @@ def test_generate_tiled_region_fov_list(moly_path, moly_region_setting, assert center_points == actual_center_points_sorted assert fov_names == actual_fov_names - # if only the second fov is randomized + # if only the second ROI is randomized elif randomize_setting == ['N', 'Y']: - # ensure the fov 1 center points and FOV names are the same for both sorted and random - assert center_points[:fov_1_end_pos] == actual_center_points_sorted[:fov_1_end_pos] - assert fov_names[:fov_1_end_pos] == actual_fov_names[:fov_1_end_pos] + # ensure the ROI 1 center points and FOV names are the same for both sorted and random + assert center_points[:roi_1_end_pos] == actual_center_points_sorted[:roi_1_end_pos] + assert fov_names[:roi_1_end_pos] == actual_fov_names[:roi_1_end_pos] - # ensure the random center points and fov names for roi 2 contain the same elements + # ensure the random center points and fov names for ROI 2 contain the same elements # as its sorted version misc_utils.verify_same_elements( - computed_center_points=center_points[fov_1_end_pos:], - actual_center_points=actual_center_points_sorted[fov_1_end_pos:] + computed_center_points=center_points[roi_1_end_pos:], + actual_center_points=actual_center_points_sorted[roi_1_end_pos:] ) misc_utils.verify_same_elements( - computed_fov_names=fov_names[fov_1_end_pos:], - actual_fov_names=actual_fov_names[fov_1_end_pos:] + computed_fov_names=fov_names[roi_1_end_pos:], + actual_fov_names=actual_fov_names[roi_1_end_pos:] ) - # however, roi 2 sorted entries should NOT equal roi 2 random entries - assert center_points[fov_1_end_pos:] != actual_center_points_sorted[fov_1_end_pos:] - assert fov_names[fov_1_end_pos:] != actual_fov_names[fov_1_end_pos:] + # however, ROI 2 sorted entries should NOT equal ROI 2 random entries + assert center_points[roi_1_end_pos:] != actual_center_points_sorted[roi_1_end_pos:] + assert fov_names[roi_1_end_pos:] != actual_fov_names[roi_1_end_pos:] # if both fovs are randomized elif randomize_setting == ['Y', 'Y']: - # ensure the random center points and fov names for roi 1 contain the same elements + # ensure the random center points and fov names for ROI 1 contain the same elements # as its sorted version misc_utils.verify_same_elements( - computed_center_points=center_points[:fov_1_end_pos], - actual_center_points=actual_center_points_sorted[:fov_1_end_pos] + computed_center_points=center_points[:roi_1_end_pos], + actual_center_points=actual_center_points_sorted[:roi_1_end_pos] ) misc_utils.verify_same_elements( - computed_fov_names=fov_names[:fov_1_end_pos], - actual_fov_names=actual_fov_names[:fov_1_end_pos] + computed_fov_names=fov_names[:roi_1_end_pos], + actual_fov_names=actual_fov_names[:roi_1_end_pos] ) - # however, roi 1 sorted entries should NOT equal roi 1 random entries - assert center_points[:fov_1_end_pos] != actual_center_points_sorted[:fov_1_end_pos] - assert fov_names[:fov_1_end_pos] != actual_fov_names[:fov_1_end_pos] + # however, ROI 1 sorted entries should NOT equal ROI 1 random entries + assert center_points[:roi_1_end_pos] != actual_center_points_sorted[:roi_1_end_pos] + assert fov_names[:roi_1_end_pos] != actual_fov_names[:roi_1_end_pos] - # ensure the random center points for roi 2 contain the same elements + # ensure the random center points for ROI 2 contain the same elements # as its sorted version misc_utils.verify_same_elements( - computed_center_points=center_points[fov_1_end_pos:], - actual_center_points=actual_center_points_sorted[fov_1_end_pos:] + computed_center_points=center_points[roi_1_end_pos:], + actual_center_points=actual_center_points_sorted[roi_1_end_pos:] ) misc_utils.verify_same_elements( - computed_fov_names=fov_names[fov_1_end_pos:], - actual_fov_names=actual_fov_names[fov_1_end_pos:] + computed_fov_names=fov_names[roi_1_end_pos:], + actual_fov_names=actual_fov_names[roi_1_end_pos:] ) - # however, fov 2 sorted entries should NOT equal fov 2 random entries - assert center_points[fov_1_end_pos:] != actual_center_points_sorted[fov_1_end_pos:] - assert fov_names[fov_1_end_pos:] != actual_fov_names[fov_1_end_pos:] + # however, ROI 2 sorted entries should NOT equal ROI 2 random entries + assert center_points[roi_1_end_pos:] != actual_center_points_sorted[roi_1_end_pos:] + assert fov_names[roi_1_end_pos:] != actual_fov_names[roi_1_end_pos:] @parametrize_with_cases('top_left, top_right, bottom_left, bottom_right', diff --git a/toffy/tiling_utils_test_cases.py b/toffy/tiling_utils_test_cases.py index 34754b67..2584efc3 100644 --- a/toffy/tiling_utils_test_cases.py +++ b/toffy/tiling_utils_test_cases.py @@ -41,65 +41,65 @@ def case_reentry_different_type(self): # define the list of region start coords and names -_TILED_REGION_FOV_COORDS = [(50, 150), (100, 300)] -_TILED_REGION_FOV_NAMES = ["TheFirstFOV", "TheSecondFOV"] -_TILED_REGION_FOV_SIZES = [1000, 2000] +_TILED_REGION_ROI_COORDS = [(50, 150), (100, 300)] +_TILED_REGION_ROI_NAMES = ["TheFirstROI", "TheSecondROI"] +_TILED_REGION_ROI_SIZES = [1000, 2000] -# this function assumes that FOV 2's corresponding values are linearly spaced from FOV 1's +# this function assumes that ROI 2's corresponding values are linearly spaced from ROI 1's # NOTE: x and y correspond to column and row index respectively as specified in the JSON spec file -def generate_tiled_region_params(start_x_fov_1=50, start_y_fov_1=150, - num_row_fov_1=4, num_col_fov_1=2, - row_size_fov_1=2, col_size_fov_1=1, num_fovs=2, - fov_names=deepcopy(_TILED_REGION_FOV_NAMES)): +def generate_tiled_region_params(start_x_roi_1=50, start_y_roi_1=150, + num_row_roi_1=4, num_col_roi_1=2, + row_size_roi_1=2, col_size_roi_1=1, num_rois=2, + roi_names=deepcopy(_TILED_REGION_ROI_NAMES)): # define this dictionary for testing purposes to ensure that function calls # equal what would be placed in param_set_values base_param_values = { - 'region_start_row': start_y_fov_1, - 'region_start_col': start_x_fov_1, - 'fov_num_row': num_row_fov_1, - 'fov_num_col': num_col_fov_1, - 'row_fov_size': row_size_fov_1, - 'col_fov_size': col_size_fov_1 + 'region_start_row': start_y_roi_1, + 'region_start_col': start_x_roi_1, + 'fov_num_row': num_row_roi_1, + 'fov_num_col': num_col_roi_1, + 'row_fov_size': row_size_roi_1, + 'col_fov_size': col_size_roi_1 } - # define the values for each param that should be contained for each FOV + # define the values for each param that should be contained for each ROI full_param_set = { param: list(np.arange( base_param_values[param], - base_param_values[param] * (num_fovs + 1), + base_param_values[param] * (num_rois + 1), base_param_values[param] )) for param in base_param_values } - # set the names for each region - full_param_set['roi_name'] = fov_names + # set the names for each ROI + full_param_set['region_name'] = roi_names # TODO: might want to return just one and have the test function generate the other return base_param_values, full_param_set # test tiled region parameter setting and FOV generation -# a helper function for generating params specific to each FOV for TiledRegionReadCases -# NOTE: the param moly_region applies across all FOVs, so it's not set here -def generate_tiled_region_cases(fov_coord_list, fov_name_list, fov_sizes, - user_input_type='none', num_row_fov_1=4, num_col_fov_1=2, - random_fov_1='n', random_fov_2='Y'): +# a helper function for generating params specific to each ROI for TiledRegionReadCases +# NOTE: the param moly_roi applies across all ROIs, so it's not set here +def generate_tiled_region_cases(roi_coord_list, roi_name_list, roi_sizes, + user_input_type='none', num_row_roi_1=4, num_col_roi_1=2, + random_roi_1='n', random_roi_2='Y'): # define the base value for each parameter to use for testing # as well as the full set of parameters for each FOV base_param_values, full_param_set = generate_tiled_region_params( - fov_coord_list[0][0], fov_coord_list[0][1], num_row_fov_1, num_col_fov_1, - fov_sizes[0], fov_sizes[0], len(fov_coord_list) + roi_coord_list[0][0], roi_coord_list[0][1], num_row_roi_1, num_col_roi_1, + roi_sizes[0], roi_sizes[0], len(roi_coord_list) ) full_param_set['region_rand'] = ['N', 'Y'] # define the list of user inputs to pass into the input functions for tiled regions user_inputs = [ - num_row_fov_1, num_col_fov_1, random_fov_1, - num_row_fov_1 * 2, num_col_fov_1 * 2, random_fov_2 + num_row_roi_1, num_col_roi_1, random_roi_1, + num_row_roi_1 * 2, num_col_roi_1 * 2, random_roi_2 ] # insert some bad inputs for the desire test type @@ -114,7 +114,7 @@ def generate_tiled_region_cases(fov_coord_list, fov_name_list, fov_sizes, for i in np.arange(0, len(user_inputs), 2): user_inputs.insert(int(i), bad_inputs_to_insert[int(i / 2)]) - return fov_coord_list, fov_name_list, fov_sizes, user_inputs, base_param_values, full_param_set + return roi_coord_list, roi_name_list, roi_sizes, user_inputs, base_param_values, full_param_set # NOTE: because of the way the moly_interval param is handled @@ -122,25 +122,25 @@ def generate_tiled_region_cases(fov_coord_list, fov_name_list, fov_sizes, class TiledRegionReadCases: def case_no_reentry_no_moly_param(self): return generate_tiled_region_cases( - _TILED_REGION_FOV_COORDS, _TILED_REGION_FOV_NAMES, deepcopy(_TILED_REGION_FOV_SIZES) + _TILED_REGION_ROI_COORDS, _TILED_REGION_ROI_NAMES, deepcopy(_TILED_REGION_ROI_SIZES) ) def case_no_reentry_with_moly_param(self): fcl, fnl, fs, ui, bpv, fps = generate_tiled_region_cases( - _TILED_REGION_FOV_COORDS, _TILED_REGION_FOV_NAMES, deepcopy(_TILED_REGION_FOV_SIZES) + _TILED_REGION_ROI_COORDS, _TILED_REGION_ROI_NAMES, deepcopy(_TILED_REGION_ROI_SIZES) ) return fcl, fnl, fs, ui + ['Y'], bpv, fps def case_reentry_same_type_no_moly_param(self): return generate_tiled_region_cases( - _TILED_REGION_FOV_COORDS, _TILED_REGION_FOV_NAMES, deepcopy(_TILED_REGION_FOV_SIZES), + _TILED_REGION_ROI_COORDS, _TILED_REGION_ROI_NAMES, deepcopy(_TILED_REGION_ROI_SIZES), user_input_type='same_types' ) def case_reentry_same_type_with_moly_param(self): fcl, fnl, fs, ui, bpv, fps = generate_tiled_region_cases( - _TILED_REGION_FOV_COORDS, _TILED_REGION_FOV_NAMES, deepcopy(_TILED_REGION_FOV_SIZES), + _TILED_REGION_ROI_COORDS, _TILED_REGION_ROI_NAMES, deepcopy(_TILED_REGION_ROI_SIZES), user_input_type='same_types' ) @@ -148,13 +148,13 @@ def case_reentry_same_type_with_moly_param(self): def case_reentry_different_type_no_moly_param(self): return generate_tiled_region_cases( - _TILED_REGION_FOV_COORDS, _TILED_REGION_FOV_NAMES, deepcopy(_TILED_REGION_FOV_SIZES), + _TILED_REGION_ROI_COORDS, _TILED_REGION_ROI_NAMES, deepcopy(_TILED_REGION_ROI_SIZES), user_input_type='diff_types' ) def case_reentry_different_type_with_moly_param(self): fcl, fnl, fs, ui, bpv, fps = generate_tiled_region_cases( - _TILED_REGION_FOV_COORDS, _TILED_REGION_FOV_NAMES, deepcopy(_TILED_REGION_FOV_SIZES), + _TILED_REGION_ROI_COORDS, _TILED_REGION_ROI_NAMES, deepcopy(_TILED_REGION_ROI_SIZES), user_input_type='diff_types' ) @@ -163,7 +163,7 @@ def case_reentry_different_type_with_moly_param(self): @xfail(raises=ValueError, strict=True) def case_bad_fov_size_value_no_moly_param(self): fcl, fnl, fs, ui, bpv, fps = generate_tiled_region_cases( - _TILED_REGION_FOV_COORDS, _TILED_REGION_FOV_NAMES, deepcopy(_TILED_REGION_FOV_SIZES) + _TILED_REGION_ROI_COORDS, _TILED_REGION_ROI_NAMES, deepcopy(_TILED_REGION_ROI_SIZES) ) fs[0] = -5 @@ -173,7 +173,7 @@ def case_bad_fov_size_value_no_moly_param(self): @xfail(raises=ValueError, strict=True) def case_bad_fov_size_value_moly_param(self): fcl, fnl, fs, ui, bpv, fps = generate_tiled_region_cases( - _TILED_REGION_FOV_COORDS, _TILED_REGION_FOV_NAMES, deepcopy(_TILED_REGION_FOV_SIZES) + _TILED_REGION_ROI_COORDS, _TILED_REGION_ROI_NAMES, deepcopy(_TILED_REGION_ROI_SIZES) ) fs[0] = -5