nanopyx.core.transform.sr_temporal_correlations
1import numpy as np 2 3 4def calculate_SRRF_temporal_correlations(im: np.array, order: int = 1, do_integrate_lag_times: bool = 0): 5 """ 6 Calculate temporal correlations for Super-Resolution Radial Fluctuations (SRRF). 7 8 Args: 9 im (np.array): Input 3D numpy array containing temporal data. 10 order (int, optional): Order of temporal correlation. Should be 0, 1, -1, 2, 3, or 4. 11 Defaults to 1. 12 do_integrate_lag_times (bool, optional): Whether to integrate lag times. 13 Defaults to False (0). 14 15 Returns: 16 np.array: Calculated temporal correlations based on the specified order and integration. 17 18 Raises: 19 AssertionError: If the input array doesn't have 3 dimensions or if the order is greater than 4. 20 21 Note: 22 - If `order` is 0, the maximum value over time is calculated. 23 - If `order` is 1, the mean value over time is calculated. 24 - If `order` is -1, the pairwise product sum is calculated. 25 - If `order` is 2, 3, or 4, more advanced calculations are performed based on `do_integrate_lag_times`. 26 27 """ 28 im = np.array(im, dtype="float32") 29 assert im.ndim == 3 and order <= 4 30 31 if order == 0: # TODO: check order number in NanoJ 32 out_array = np.amax(im, axis=0) 33 34 elif order == 1: 35 out_array = np.mean(im, axis=0) 36 37 elif order == -1: 38 out_array = calculate_pairwise_product_sum(im) 39 40 else: # order = 2 or order = 3 or order = 4 41 out_array = calculate_acrf_(im, order, do_integrate_lag_times) 42 43 return out_array 44 45 46def calculate_eSRRF_temporal_correlations(im: np.array, correlation: str): 47 """ 48 Calculate temporal correlations for enhanced Super-Resolution Radial Fluctuations (eSRRF). 49 50 Args: 51 im (np.array): Input 3D numpy array containing temporal data. 52 correlation (str): Type of correlation to calculate. Should be "AVG", "VAR", or "TAC2". 53 54 Returns: 55 np.array: Calculated temporal correlations based on the specified correlation type. 56 57 Raises: 58 ValueError: If the specified correlation type is not "AVG", "VAR", or "TAC2". 59 60 """ 61 im = np.array(im, dtype="float32") 62 63 if correlation == "AVG": 64 out_array = np.mean(im, axis=0) 65 66 elif correlation == "VAR": 67 out_array = np.var(im, axis=0) 68 69 elif correlation == "TAC2": 70 out_array = calculate_tac2(im) 71 72 else: 73 raise ValueError(f"Type of correlation must be AVG, VAR or TAC2") 74 75 return out_array 76 77 78def calculate_pairwise_product_sum(rad_array): 79 """ 80 Calculate pairwise product sum of a 3D numpy array. 81 82 Args: 83 rad_array (np.array): Input 3D numpy array. 84 85 Returns: 86 np.array: Pairwise product sum of the input array. 87 88 """ 89 n_time_points, height_m, width_m = rad_array.shape 90 91 out_array = np.zeros((height_m, width_m), dtype=np.float32) 92 # max_array = np.max(rad_array, axis=0) 93 counter = 0 94 pps = 0 95 96 for t0 in range(n_time_points): 97 r0 = np.maximum(rad_array[t0], 0) 98 if np.any(r0) > 0: 99 for t1 in range(t0, n_time_points): 100 r1 = np.maximum(rad_array[t1], 0) 101 pps += r0 * r1 102 counter += 1 103 else: 104 counter += n_time_points - t0 105 pps = pps / max(counter, 1) 106 out_array = pps 107 108 return out_array 109 110 111def calculate_acrf_(rad_array, order, do_integrate_lag_times): 112 """ 113 Calculate Auto-Correlation Radial Fluctuations (ACRF) for temporal data. 114 115 Args: 116 rad_array (np.array): Input 3D numpy array containing temporal data. 117 order (int): Order of ACRF calculation. 118 do_integrate_lag_times (bool): Whether to integrate lag times. 119 120 Returns: 121 np.array: Calculated ACRF based on the specified order and integration. 122 123 """ 124 im = rad_array.copy() 125 n_time_points, height_m, width_m = im.shape 126 mean = np.mean(im, axis=0) 127 128 out_array = np.zeros((height_m, width_m), dtype=np.float32) 129 130 abcd = np.zeros((height_m, width_m), dtype=np.float32) 131 abc = np.zeros((height_m, width_m), dtype=np.float32) 132 ab = np.zeros((height_m, width_m), dtype=np.float32) 133 cd = np.zeros((height_m, width_m), dtype=np.float32) 134 ac = np.zeros((height_m, width_m), dtype=np.float32) 135 bd = np.zeros((height_m, width_m), dtype=np.float32) 136 ad = np.zeros((height_m, width_m), dtype=np.float32) 137 bc = np.zeros((height_m, width_m), dtype=np.float32) 138 139 if do_integrate_lag_times != 1: 140 t = 0 141 while t < n_time_points - order: 142 ab = ab + (im[t] - mean) * (im[t + 1] - mean) 143 if order == 3: 144 abc = abc + (im[t] - mean) * (im[t + 1] - mean) + (im[t + 2] - mean) 145 if order == 4: 146 a = im[t] - mean 147 b = im[t + 1] - mean 148 c = im[t + 2] - mean 149 d = im[t + 3] - mean 150 abcd = abcd + np.multiply(np.multiply(np.multiply(a, b), c), d) 151 cd = cd + np.multiply(c, d) 152 ac = ac + np.multiply(a, c) 153 bd = bd + np.multiply(b, d) 154 ad = ad + np.multiply(a, d) 155 bc = bc + np.multiply(b, c) 156 t = t + 1 157 if order == 3: 158 out_array = np.absolute(abc) / n_time_points 159 elif order == 4: 160 out_array = np.absolute(abcd - ab * cd - ac * bd - ad * bc) / n_time_points 161 else: 162 out_array = np.absolute(ab) / n_time_points 163 164 else: 165 n_binned_time_points = n_time_points 166 tbin = 0 167 while n_binned_time_points > order: 168 t = 0 169 ab = np.zeros((height_m, width_m), dtype=np.float32) 170 while t < n_binned_time_points - order: 171 tbin = t * order 172 ab = ab + (im[t] - mean) * (im[t + 1] - mean) 173 if order == 3: 174 abc = abc + (im[t] - mean) * (im[t + 1] - mean) + (im[t + 2] - mean) 175 if order == 4: 176 a = im[t] - mean 177 b = im[t + 1] - mean 178 c = im[t + 2] - mean 179 d = im[t + 3] - mean 180 abcd = abcd + np.multiply(np.multiply(np.multiply(a, b), c), d) 181 cd = cd + np.multiply(c, d) 182 ac = ac + np.multiply(a, c) 183 bd = bd + np.multiply(b, d) 184 ad = ad + np.multiply(a, d) 185 bc = bc + np.multiply(b, c) 186 187 im[t] = np.zeros((height_m, width_m), dtype=np.float32) 188 189 if tbin < n_binned_time_points: 190 for _t in range(order - 1): 191 im[t] = im[t] + np.divide(im[tbin + _t], order) 192 t = t + 1 193 if order == 3: 194 out_array = np.absolute(abc) / n_binned_time_points 195 elif order == 4: 196 out_array = np.absolute(abcd - ab * cd - ac * bd - ad * bc) / n_binned_time_points 197 else: 198 out_array = np.absolute(ab) / n_binned_time_points 199 200 n_binned_time_points = n_binned_time_points / order 201 202 return out_array 203 204 205def calculate_tac2(rad_array): 206 """ 207 Calculate Temporal Autocorrelation 2 (TAC2) for temporal data. 208 209 Args: 210 rad_array (np.array): Input 3D numpy array containing temporal data. 211 212 Returns: 213 np.array: Calculated TAC2. 214 215 """ 216 mean = np.mean(rad_array, axis=0) 217 centered = rad_array - mean # center data around the mean 218 nlag = 1 # number of lags to compute TAC2 for 219 out_array = np.mean(centered[:-nlag] * centered[nlag:], axis=0) 220 221 return out_array 222 223 224def calculate_eSRRF3d_temporal_correlations( 225 rgc_map, correlation: str = "AVG", framewindow: float = 5, rollingoverlap: float = 2 226): 227 # correlation (str): Type of correlation to calculate. Should be "AVG", "VAR", or "TAC2" 228 n_frames, n_slices, n_rows, n_cols = rgc_map.shape[0], rgc_map.shape[1], rgc_map.shape[2], rgc_map.shape[3] 229 230 if n_frames == 1: 231 print("Only one frame, no temporal correlations can be calculated") 232 return rgc_map 233 234 else: 235 if framewindow > 0: 236 if rollingoverlap: 237 n_windows = int(n_frames / (framewindow - rollingoverlap)) 238 else: 239 n_windows = int(n_frames / framewindow) 240 rollingoverlap = 0 241 else: 242 n_windows = 1 243 framewindow = n_frames - 1 244 245 avg_rgc_map = np.zeros((n_windows, n_slices, n_rows, n_cols), dtype=np.float32) 246 247 for w in range(n_windows): 248 start_frame = w * (int(framewindow) - int(rollingoverlap)) 249 end_frame = start_frame + int(framewindow) 250 avg_rgc_map[w, :, :, :] = calculate_eSRRF_temporal_correlations( 251 rgc_map[start_frame:end_frame, :, :, :], correlation 252 ) 253 254 return avg_rgc_map
5def calculate_SRRF_temporal_correlations(im: np.array, order: int = 1, do_integrate_lag_times: bool = 0): 6 """ 7 Calculate temporal correlations for Super-Resolution Radial Fluctuations (SRRF). 8 9 Args: 10 im (np.array): Input 3D numpy array containing temporal data. 11 order (int, optional): Order of temporal correlation. Should be 0, 1, -1, 2, 3, or 4. 12 Defaults to 1. 13 do_integrate_lag_times (bool, optional): Whether to integrate lag times. 14 Defaults to False (0). 15 16 Returns: 17 np.array: Calculated temporal correlations based on the specified order and integration. 18 19 Raises: 20 AssertionError: If the input array doesn't have 3 dimensions or if the order is greater than 4. 21 22 Note: 23 - If `order` is 0, the maximum value over time is calculated. 24 - If `order` is 1, the mean value over time is calculated. 25 - If `order` is -1, the pairwise product sum is calculated. 26 - If `order` is 2, 3, or 4, more advanced calculations are performed based on `do_integrate_lag_times`. 27 28 """ 29 im = np.array(im, dtype="float32") 30 assert im.ndim == 3 and order <= 4 31 32 if order == 0: # TODO: check order number in NanoJ 33 out_array = np.amax(im, axis=0) 34 35 elif order == 1: 36 out_array = np.mean(im, axis=0) 37 38 elif order == -1: 39 out_array = calculate_pairwise_product_sum(im) 40 41 else: # order = 2 or order = 3 or order = 4 42 out_array = calculate_acrf_(im, order, do_integrate_lag_times) 43 44 return out_array
Calculate temporal correlations for Super-Resolution Radial Fluctuations (SRRF).
Args: im (np.array): Input 3D numpy array containing temporal data. order (int, optional): Order of temporal correlation. Should be 0, 1, -1, 2, 3, or 4. Defaults to 1. do_integrate_lag_times (bool, optional): Whether to integrate lag times. Defaults to False (0).
Returns: np.array: Calculated temporal correlations based on the specified order and integration.
Raises: AssertionError: If the input array doesn't have 3 dimensions or if the order is greater than 4.
Note:
- If order
is 0, the maximum value over time is calculated.
- If order
is 1, the mean value over time is calculated.
- If order
is -1, the pairwise product sum is calculated.
- If order
is 2, 3, or 4, more advanced calculations are performed based on do_integrate_lag_times
.
47def calculate_eSRRF_temporal_correlations(im: np.array, correlation: str): 48 """ 49 Calculate temporal correlations for enhanced Super-Resolution Radial Fluctuations (eSRRF). 50 51 Args: 52 im (np.array): Input 3D numpy array containing temporal data. 53 correlation (str): Type of correlation to calculate. Should be "AVG", "VAR", or "TAC2". 54 55 Returns: 56 np.array: Calculated temporal correlations based on the specified correlation type. 57 58 Raises: 59 ValueError: If the specified correlation type is not "AVG", "VAR", or "TAC2". 60 61 """ 62 im = np.array(im, dtype="float32") 63 64 if correlation == "AVG": 65 out_array = np.mean(im, axis=0) 66 67 elif correlation == "VAR": 68 out_array = np.var(im, axis=0) 69 70 elif correlation == "TAC2": 71 out_array = calculate_tac2(im) 72 73 else: 74 raise ValueError(f"Type of correlation must be AVG, VAR or TAC2") 75 76 return out_array
Calculate temporal correlations for enhanced Super-Resolution Radial Fluctuations (eSRRF).
Args: im (np.array): Input 3D numpy array containing temporal data. correlation (str): Type of correlation to calculate. Should be "AVG", "VAR", or "TAC2".
Returns: np.array: Calculated temporal correlations based on the specified correlation type.
Raises: ValueError: If the specified correlation type is not "AVG", "VAR", or "TAC2".
79def calculate_pairwise_product_sum(rad_array): 80 """ 81 Calculate pairwise product sum of a 3D numpy array. 82 83 Args: 84 rad_array (np.array): Input 3D numpy array. 85 86 Returns: 87 np.array: Pairwise product sum of the input array. 88 89 """ 90 n_time_points, height_m, width_m = rad_array.shape 91 92 out_array = np.zeros((height_m, width_m), dtype=np.float32) 93 # max_array = np.max(rad_array, axis=0) 94 counter = 0 95 pps = 0 96 97 for t0 in range(n_time_points): 98 r0 = np.maximum(rad_array[t0], 0) 99 if np.any(r0) > 0: 100 for t1 in range(t0, n_time_points): 101 r1 = np.maximum(rad_array[t1], 0) 102 pps += r0 * r1 103 counter += 1 104 else: 105 counter += n_time_points - t0 106 pps = pps / max(counter, 1) 107 out_array = pps 108 109 return out_array
Calculate pairwise product sum of a 3D numpy array.
Args: rad_array (np.array): Input 3D numpy array.
Returns: np.array: Pairwise product sum of the input array.
112def calculate_acrf_(rad_array, order, do_integrate_lag_times): 113 """ 114 Calculate Auto-Correlation Radial Fluctuations (ACRF) for temporal data. 115 116 Args: 117 rad_array (np.array): Input 3D numpy array containing temporal data. 118 order (int): Order of ACRF calculation. 119 do_integrate_lag_times (bool): Whether to integrate lag times. 120 121 Returns: 122 np.array: Calculated ACRF based on the specified order and integration. 123 124 """ 125 im = rad_array.copy() 126 n_time_points, height_m, width_m = im.shape 127 mean = np.mean(im, axis=0) 128 129 out_array = np.zeros((height_m, width_m), dtype=np.float32) 130 131 abcd = np.zeros((height_m, width_m), dtype=np.float32) 132 abc = np.zeros((height_m, width_m), dtype=np.float32) 133 ab = np.zeros((height_m, width_m), dtype=np.float32) 134 cd = np.zeros((height_m, width_m), dtype=np.float32) 135 ac = np.zeros((height_m, width_m), dtype=np.float32) 136 bd = np.zeros((height_m, width_m), dtype=np.float32) 137 ad = np.zeros((height_m, width_m), dtype=np.float32) 138 bc = np.zeros((height_m, width_m), dtype=np.float32) 139 140 if do_integrate_lag_times != 1: 141 t = 0 142 while t < n_time_points - order: 143 ab = ab + (im[t] - mean) * (im[t + 1] - mean) 144 if order == 3: 145 abc = abc + (im[t] - mean) * (im[t + 1] - mean) + (im[t + 2] - mean) 146 if order == 4: 147 a = im[t] - mean 148 b = im[t + 1] - mean 149 c = im[t + 2] - mean 150 d = im[t + 3] - mean 151 abcd = abcd + np.multiply(np.multiply(np.multiply(a, b), c), d) 152 cd = cd + np.multiply(c, d) 153 ac = ac + np.multiply(a, c) 154 bd = bd + np.multiply(b, d) 155 ad = ad + np.multiply(a, d) 156 bc = bc + np.multiply(b, c) 157 t = t + 1 158 if order == 3: 159 out_array = np.absolute(abc) / n_time_points 160 elif order == 4: 161 out_array = np.absolute(abcd - ab * cd - ac * bd - ad * bc) / n_time_points 162 else: 163 out_array = np.absolute(ab) / n_time_points 164 165 else: 166 n_binned_time_points = n_time_points 167 tbin = 0 168 while n_binned_time_points > order: 169 t = 0 170 ab = np.zeros((height_m, width_m), dtype=np.float32) 171 while t < n_binned_time_points - order: 172 tbin = t * order 173 ab = ab + (im[t] - mean) * (im[t + 1] - mean) 174 if order == 3: 175 abc = abc + (im[t] - mean) * (im[t + 1] - mean) + (im[t + 2] - mean) 176 if order == 4: 177 a = im[t] - mean 178 b = im[t + 1] - mean 179 c = im[t + 2] - mean 180 d = im[t + 3] - mean 181 abcd = abcd + np.multiply(np.multiply(np.multiply(a, b), c), d) 182 cd = cd + np.multiply(c, d) 183 ac = ac + np.multiply(a, c) 184 bd = bd + np.multiply(b, d) 185 ad = ad + np.multiply(a, d) 186 bc = bc + np.multiply(b, c) 187 188 im[t] = np.zeros((height_m, width_m), dtype=np.float32) 189 190 if tbin < n_binned_time_points: 191 for _t in range(order - 1): 192 im[t] = im[t] + np.divide(im[tbin + _t], order) 193 t = t + 1 194 if order == 3: 195 out_array = np.absolute(abc) / n_binned_time_points 196 elif order == 4: 197 out_array = np.absolute(abcd - ab * cd - ac * bd - ad * bc) / n_binned_time_points 198 else: 199 out_array = np.absolute(ab) / n_binned_time_points 200 201 n_binned_time_points = n_binned_time_points / order 202 203 return out_array
Calculate Auto-Correlation Radial Fluctuations (ACRF) for temporal data.
Args: rad_array (np.array): Input 3D numpy array containing temporal data. order (int): Order of ACRF calculation. do_integrate_lag_times (bool): Whether to integrate lag times.
Returns: np.array: Calculated ACRF based on the specified order and integration.
206def calculate_tac2(rad_array): 207 """ 208 Calculate Temporal Autocorrelation 2 (TAC2) for temporal data. 209 210 Args: 211 rad_array (np.array): Input 3D numpy array containing temporal data. 212 213 Returns: 214 np.array: Calculated TAC2. 215 216 """ 217 mean = np.mean(rad_array, axis=0) 218 centered = rad_array - mean # center data around the mean 219 nlag = 1 # number of lags to compute TAC2 for 220 out_array = np.mean(centered[:-nlag] * centered[nlag:], axis=0) 221 222 return out_array
Calculate Temporal Autocorrelation 2 (TAC2) for temporal data.
Args: rad_array (np.array): Input 3D numpy array containing temporal data.
Returns: np.array: Calculated TAC2.
225def calculate_eSRRF3d_temporal_correlations( 226 rgc_map, correlation: str = "AVG", framewindow: float = 5, rollingoverlap: float = 2 227): 228 # correlation (str): Type of correlation to calculate. Should be "AVG", "VAR", or "TAC2" 229 n_frames, n_slices, n_rows, n_cols = rgc_map.shape[0], rgc_map.shape[1], rgc_map.shape[2], rgc_map.shape[3] 230 231 if n_frames == 1: 232 print("Only one frame, no temporal correlations can be calculated") 233 return rgc_map 234 235 else: 236 if framewindow > 0: 237 if rollingoverlap: 238 n_windows = int(n_frames / (framewindow - rollingoverlap)) 239 else: 240 n_windows = int(n_frames / framewindow) 241 rollingoverlap = 0 242 else: 243 n_windows = 1 244 framewindow = n_frames - 1 245 246 avg_rgc_map = np.zeros((n_windows, n_slices, n_rows, n_cols), dtype=np.float32) 247 248 for w in range(n_windows): 249 start_frame = w * (int(framewindow) - int(rollingoverlap)) 250 end_frame = start_frame + int(framewindow) 251 avg_rgc_map[w, :, :, :] = calculate_eSRRF_temporal_correlations( 252 rgc_map[start_frame:end_frame, :, :, :], correlation 253 ) 254 255 return avg_rgc_map