most figures for the paper created and added to git. code is in the thunderfish git.
This commit is contained in:
		
							parent
							
								
									f9718877bc
								
							
						
					
					
						commit
						e2ce32ed2b
					
				
							
								
								
									
										
											BIN
										
									
								
								bsp_data/2016-04-10-22:14/ident_v.npy
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								bsp_data/2016-04-10-22:14/ident_v.npy
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								bsp_data/2016-04-10-22:14/ident_v2.npy
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								bsp_data/2016-04-10-22:14/ident_v2.npy
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										695
									
								
								code/visualize_algo.py
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										695
									
								
								code/visualize_algo.py
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,695 @@ | ||||
| import numpy as np | ||||
| import matplotlib.pyplot as plt | ||||
| from thunderfish.tracker_v2 import include_progress_bar | ||||
| from IPython import embed | ||||
| import scipy.stats as scp | ||||
| from tqdm import tqdm | ||||
| 
 | ||||
| def estimate_error(a_error, f_error, t_error, a_error_distribution, f_error_distribution, | ||||
|                    min_f_weight=0.4, max_f_weight=0.9, t_of_max_f_weight=5.): | ||||
|     """ | ||||
|     Cost function estimating the error between two fish signals at two different times using realative frequency | ||||
|     difference and relative signal amplitude difference on n electrodes (relative because the values are compared to a | ||||
|     given distribution of these values). With increasing time difference between the signals the impact of frequency | ||||
|     error increases and the influence of amplitude error decreases due to potential changes caused by fish movement. | ||||
| 
 | ||||
|     Parameters | ||||
|     ---------- | ||||
|     a_error: float | ||||
|         MSE of amplitude difference of two electric signals recorded with n electodes. | ||||
|     f_error: float | ||||
|         absolute frequency difference between two electric signals. | ||||
|     t_error: float | ||||
|         temporal difference between two measured signals in s. | ||||
|     a_error_distribution: list | ||||
|         distribution of possible MSE of the amplitudes between random data points in the dataset. | ||||
|     f_error_distribution: list | ||||
|         distribution of possible frequency differences between random data points in the dataset. | ||||
|     min_f_weight: float | ||||
|         minimum proportion of the frequency impact to the error value. | ||||
|     max_f_weight: float | ||||
|         maximum proportion of the frequency impact to the error value. | ||||
|     t_of_max_f_weight: float | ||||
|         error value between two electric signals at two time points. | ||||
| 
 | ||||
|     Returns | ||||
|     ------- | ||||
|     float | ||||
|         error value between two electric signals at two time points | ||||
|     """ | ||||
|     def boltzmann(t, alpha= 0.25, beta = 0.0, x0 = 4, dx = 0.85): | ||||
|         """ | ||||
|         Calulates a boltzmann function. | ||||
| 
 | ||||
|         Parameters | ||||
|         ---------- | ||||
|         t: array | ||||
|             time vector. | ||||
|         alpha: float | ||||
|             max value of the boltzmann function. | ||||
|         beta: float | ||||
|             min value of the boltzmann function. | ||||
|         x0: float | ||||
|             time where the turning point of the boltzmann function occurs. | ||||
|         dx: float | ||||
|             slope of the boltzman function. | ||||
| 
 | ||||
|         Returns | ||||
|         ------- | ||||
|         array | ||||
|             boltzmann function of the given time array base on the other parameters given. | ||||
|         """ | ||||
| 
 | ||||
|         boltz = (alpha - beta) / (1. + np.exp(- (t - x0 ) / dx)  ) + beta | ||||
|         return boltz | ||||
| 
 | ||||
|     a_error_distribution = np.array(a_error_distribution) | ||||
|     f_error_distribution = np.array(f_error_distribution) | ||||
| 
 | ||||
|     if t_error >= 2.: | ||||
|         f_weight = max_f_weight | ||||
|     else: | ||||
|         f_weight = 1. * (max_f_weight - min_f_weight) / t_of_max_f_weight * t_error + min_f_weight | ||||
|     a_weight = 1. - f_weight | ||||
| 
 | ||||
|     a_e = a_weight * len(a_error_distribution[a_error_distribution < a_error]) / len(a_error_distribution) | ||||
|     f_e = f_weight * len(f_error_distribution[f_error_distribution < f_error]) / len(f_error_distribution) | ||||
|     t_e = boltzmann(t_error) | ||||
|     # t_e = 0.5 * (1. * t_error / max_t_error) ** (1. / 3)  # when weight is 0.1 I end up in an endless loop somewhere | ||||
| 
 | ||||
|     return a_e + f_e + t_e | ||||
| 
 | ||||
| 
 | ||||
| def freq_tracking_v3(fund_v, idx_v, sign_v, times, freq_tolerance, n_channels, return_tmp_idenities=False, | ||||
|                      ioi_fti=False, a_error_distribution=False, f_error_distribution=False, freq_lims=(400, 1200)): | ||||
|     """ | ||||
|     Sorting algorithm which sorts fundamental EOD frequnecies detected in consecutive powespectra of single or | ||||
|     multielectrode recordings using frequency difference and frequnency-power amplitude difference on the electodes. | ||||
| 
 | ||||
|     Signal tracking and identity assiginment is accomplished in four steps: | ||||
|     1) Extracting possible frequency and amplitude difference distributions. | ||||
|     2) Esitmate relative error between possible datapoint connections (relative amplitude and frequency error based on | ||||
|     frequency and amplitude error distribution). | ||||
|     3) For a data window covering the EOD frequencies detected 10 seconds before the accual datapoint to assigne | ||||
|     identify temporal identities based on overall error between two datapoints from smalles to largest. | ||||
|     4) Form tight connections between datapoints where one datapoint is in the timestep that is currently of interest. | ||||
| 
 | ||||
|     Repeat these steps until the end of the recording. | ||||
|     The temporal identities are only updated when the timestep of current interest reaches the middle (5 sec.) of the | ||||
|     temporal identities. This is because no tight connection shall be made without checking the temporal identities. | ||||
|     The temnporal identities are used to check if the potential connection from the timestep of interest to a certain | ||||
|     datsapoint is the possibly best or if a connection in the futur will be better. If a future connection is better | ||||
|     the thight connection is not made. | ||||
| 
 | ||||
|     Parameters | ||||
|     ---------- | ||||
|     fundamentals: 2d-arraylike / list | ||||
|         list of arrays of fundemantal EOD frequnecies. For each timestep/powerspectrum contains one list with the | ||||
|         respectivly detected fundamental EOD frequnecies. | ||||
|     signatures: 3d-arraylike / list | ||||
|         same as fundamentals but for each value in fundamentals contains a list of powers of the respective frequency | ||||
|         detected of n electrodes used. | ||||
|     times: array | ||||
|         respective time vector. | ||||
|     freq_tolerance: float | ||||
|         maximum frequency difference between two datapoints to be connected in Hz. | ||||
|     n_channels: int | ||||
|         number of channels/electodes used in the analysis., | ||||
|     return_tmp_idenities: bool | ||||
|         only returne temporal identities at a certain timestep. Dependent on ioi_fti and only used to check algorithm. | ||||
|     ioi_fti: int | ||||
|         Index Of Interest For Temporal Identities: respective index in fund_v to calculate the temporal identities for. | ||||
|     a_error_distribution: array | ||||
|         possible amplitude error distributions for the dataset. | ||||
|     f_error_distribution: array | ||||
|         possible frequency error distribution for the dataset. | ||||
|     fig: mpl.figure | ||||
|         figure to plot the tracking progress life. | ||||
|     ax: mpl.axis | ||||
|         axis to plot the tracking progress life. | ||||
|     freq_lims: double | ||||
|         minimum/maximum frequency to be tracked. | ||||
| 
 | ||||
|     Returns | ||||
|     ------- | ||||
|     fund_v: array | ||||
|         flattened fundamtantals array containing all detected EOD frequencies in the recording. | ||||
|     ident_v: array | ||||
|         respective assigned identites throughout the tracking progress. | ||||
|     idx_v: array | ||||
|         respective index vectro impliing the time of the detected frequency. | ||||
|     sign_v: 2d-array | ||||
|         for each fundamental frequency the power of this frequency on the used electodes. | ||||
|     a_error_distribution: array | ||||
|         possible amplitude error distributions for the dataset. | ||||
|     f_error_distribution: array | ||||
|         possible frequency error distribution for the dataset. | ||||
|     idx_of_origin_v: array | ||||
|         for each assigned identity the index of the datapoint on which basis the assignement was made. | ||||
|     """ | ||||
|     def clean_up(fund_v, ident_v, idx_v, times): | ||||
|         """ | ||||
|         deletes/replaces with np.nan those identities only consisting from little data points and thus are tracking | ||||
|         artefacts. Identities get deleted when the proportion of the trace (slope, ratio of detected datapoints, etc.) | ||||
|         does not fit a real fish. | ||||
| 
 | ||||
|         Parameters | ||||
|         ---------- | ||||
|         fund_v: array | ||||
|             flattened fundamtantals array containing all detected EOD frequencies in the recording. | ||||
|         ident_v: array | ||||
|             respective assigned identites throughout the tracking progress. | ||||
|         idx_v: array | ||||
|             respective index vectro impliing the time of the detected frequency. | ||||
|         times: array | ||||
|             respective time vector. | ||||
| 
 | ||||
|         Returns | ||||
|         ------- | ||||
|         ident_v: array | ||||
|             cleaned up identities vector. | ||||
| 
 | ||||
|         """ | ||||
|         # print('clean up') | ||||
|         for ident in np.unique(ident_v[~np.isnan(ident_v)]): | ||||
|             if np.median(np.abs(np.diff(fund_v[ident_v == ident]))) >= 0.25: | ||||
|                 ident_v[ident_v == ident] = np.nan | ||||
|                 continue | ||||
| 
 | ||||
|             if len(ident_v[ident_v == ident]) <= 10: | ||||
|                 ident_v[ident_v == ident] = np.nan | ||||
|                 continue | ||||
| 
 | ||||
|         return ident_v | ||||
| 
 | ||||
|     def get_a_and_f_error_dist(fund_v, idx_v, sign_v, ): | ||||
|         """ | ||||
|         get the distribution of possible frequency and amplitude errors for the tracking. | ||||
| 
 | ||||
|         Parameters | ||||
|         ---------- | ||||
|         fund_v: array | ||||
|             flattened fundamtantals array containing all detected EOD frequencies in the recording. | ||||
|         idx_v: array | ||||
|             respective index vectro impliing the time of the detected frequency. | ||||
|         sign_v: 2d-array | ||||
|             for each fundamental frequency the power of this frequency on the used electodes. | ||||
| 
 | ||||
|         Returns | ||||
|         ------- | ||||
|         f_error_distribution: array | ||||
|             possible frequency error distribution for the dataset. | ||||
|         a_error_distribution: array | ||||
|             possible amplitude error distributions for the dataset. | ||||
|         """ | ||||
|         # get f and amp signature distribution ############### BOOT ####################### | ||||
|         a_error_distribution = np.zeros(20000)  # distribution of amplitude errors | ||||
|         f_error_distribution = np.zeros(20000)  # distribution of frequency errors | ||||
|         idx_of_distribution = np.zeros(20000)  # corresponding indices | ||||
| 
 | ||||
|         b = 0  # loop varialble | ||||
|         next_message = 0.  # feedback | ||||
| 
 | ||||
|         while b < 20000: | ||||
|             next_message = include_progress_bar(b, 20000, 'get f and sign dist', next_message)  # feedback | ||||
| 
 | ||||
|             while True:  # finding compare indices to create initial amp and freq distribution | ||||
|                 # r_idx0 = np.random.randint(np.max(idx_v[~np.isnan(idx_v)])) | ||||
|                 r_idx0 = np.random.randint(np.max(idx_v[~np.isnan(idx_v)])) | ||||
|                 r_idx1 = r_idx0 + 1 | ||||
|                 if len(sign_v[idx_v == r_idx0]) != 0 and len(sign_v[idx_v == r_idx1]) != 0: | ||||
|                     break | ||||
| 
 | ||||
|             r_idx00 = np.random.randint(len(sign_v[idx_v == r_idx0])) | ||||
|             r_idx11 = np.random.randint(len(sign_v[idx_v == r_idx1])) | ||||
| 
 | ||||
|             s0 = sign_v[idx_v == r_idx0][r_idx00]  # amplitude signatures | ||||
|             s1 = sign_v[idx_v == r_idx1][r_idx11] | ||||
| 
 | ||||
|             f0 = fund_v[idx_v == r_idx0][r_idx00]  # fundamentals | ||||
|             f1 = fund_v[idx_v == r_idx1][r_idx11] | ||||
| 
 | ||||
|             # if np.abs(f0 - f1) > freq_tolerance:  # frequency threshold | ||||
|             if np.abs(f0 - f1) > 10.:  # frequency threshold | ||||
|                 continue | ||||
| 
 | ||||
|             idx_of_distribution[b] = r_idx0 | ||||
|             a_error_distribution[b] = np.sqrt(np.sum([(s0[k] - s1[k]) ** 2 for k in range(len(s0))])) | ||||
|             f_error_distribution[b] = np.abs(f0 - f1) | ||||
|             b += 1 | ||||
| 
 | ||||
|         return f_error_distribution, a_error_distribution | ||||
| 
 | ||||
|     def get_tmp_identities(i0_m, i1_m, error_cube, fund_v, idx_v, i, ioi_fti, dps, idx_comp_range): | ||||
|         """ | ||||
|         extract temporal identities for a datasnippted of 2*index compare range of the original tracking algorithm. | ||||
|         for each data point in the data window finds the best connection within index compare range and, thus connects | ||||
|         the datapoints based on their minimal error value until no connections are left or possible anymore. | ||||
| 
 | ||||
|         Parameters | ||||
|         ---------- | ||||
|         i0_m: 2d-array | ||||
|             for consecutive timestamps contains for each the indices of the origin EOD frequencies. | ||||
|         i1_m: 2d-array | ||||
|             respectively contains the indices of the targen EOD frequencies, laying within index compare range. | ||||
|         error_cube: 3d-array | ||||
|             error values for each combination from i0_m and the respective indices in i1_m. | ||||
|         fund_v: array | ||||
|             flattened fundamtantals array containing all detected EOD frequencies in the recording. | ||||
|         idx_v: array | ||||
|             respective index vectro impliing the time of the detected frequency. | ||||
|         i: int | ||||
|             loop variable and current index of interest for the assignment of tight connections. | ||||
|         ioi_fti: int | ||||
|             index of interest for temporal identities. | ||||
|         dps: float | ||||
|             detections per second. 1. / 'temporal resolution of the tracking' | ||||
|         idx_comp_range: int | ||||
|             index compare range for the assignment of two data points to each other. | ||||
| 
 | ||||
|         Returns | ||||
|         ------- | ||||
|         tmp_ident_v: array | ||||
|             for each EOD frequencies within the index compare range for the current time step of interest contains the | ||||
|             temporal identity. | ||||
|         errors_to_v: array | ||||
|             for each assigned temporal identity contains the error value based on which this connection was made. | ||||
| 
 | ||||
|         """ | ||||
|         next_tmp_identity = 0 | ||||
|         # mask_cube = [np.ones(np.shape(error_cube[n]), dtype=bool) for n in range(len(error_cube))] | ||||
| 
 | ||||
|         max_shape = np.max([np.shape(layer) for layer in error_cube[1:]], axis=0) | ||||
|         cp_error_cube = np.full((len(error_cube)-1, max_shape[0], max_shape[1]), np.nan) | ||||
|         for enu, layer in enumerate(error_cube[1:]): | ||||
|             cp_error_cube[enu, :np.shape(error_cube[enu+1])[0], :np.shape(error_cube[enu+1])[1]] = layer | ||||
| 
 | ||||
|         try: | ||||
|             tmp_ident_v = np.full(len(fund_v), np.nan) | ||||
|             errors_to_v = np.full(len(fund_v), np.nan) | ||||
|         except: | ||||
|             tmp_ident_v = np.zeros(len(fund_v)) / 0. | ||||
|             errors_to_v = np.zeros(len(fund_v)) / 0. | ||||
| 
 | ||||
|         layers, idx0s, idx1s = np.unravel_index(np.argsort(cp_error_cube, axis=None), np.shape(cp_error_cube)) | ||||
| 
 | ||||
|         layers = layers+1 | ||||
|         # embed() | ||||
|         # quit() | ||||
| 
 | ||||
| 
 | ||||
|         for layer, idx0, idx1 in zip(layers, idx0s, idx1s): | ||||
|             # embed() | ||||
|             # quit() | ||||
|             if np.isnan(cp_error_cube[layer-1, idx0, idx1]): | ||||
|                 break | ||||
| 
 | ||||
|             # _____ some control functions _____ ### | ||||
|             if not ioi_fti: | ||||
|                 if idx_v[i1_m[layer][idx1]] - i > idx_comp_range*2: | ||||
|                     continue | ||||
|             else: | ||||
|                 if idx_v[i1_m[layer][idx1]] - idx_v[ioi_fti] > idx_comp_range*2: | ||||
|                     continue | ||||
| 
 | ||||
|             if fund_v[i0_m[layer][idx0]] > fund_v[i1_m[layer][idx1]]: | ||||
|                 if 1. * np.abs(fund_v[i0_m[layer][idx0]] - fund_v[i1_m[layer][idx1]]) / ((idx_v[i1_m[layer][idx1]] - idx_v[i0_m[layer][idx0]]) / dps) > 2.: | ||||
|                     continue | ||||
|             else: | ||||
|                 if 1. * np.abs(fund_v[i0_m[layer][idx0]] - fund_v[i1_m[layer][idx1]]) / ((idx_v[i1_m[layer][idx1]] - idx_v[i0_m[layer][idx0]]) / dps) > 2.: | ||||
|                     continue | ||||
| 
 | ||||
|             if np.isnan(tmp_ident_v[i0_m[layer][idx0]]): | ||||
|                 if np.isnan(tmp_ident_v[i1_m[layer][idx1]]): | ||||
|                     tmp_ident_v[i0_m[layer][idx0]] = next_tmp_identity | ||||
|                     tmp_ident_v[i1_m[layer][idx1]] = next_tmp_identity | ||||
|                     errors_to_v[i1_m[layer][idx1]] = cp_error_cube[layer-1][idx0, idx1] | ||||
|                     # errors_to_v[i0_m[layer][idx0]] = error_cube[layer][idx0, idx1] | ||||
| 
 | ||||
|                     # errors_to_v[(tmp_ident_v == tmp_ident_v[i1_m[layer][idx1]]) & (np.isnan(errors_to_v))] = error_cube[layer][idx0, idx1] | ||||
|                     next_tmp_identity += 1 | ||||
|                 else: | ||||
|                     if idx_v[i0_m[layer][idx0]] in idx_v[tmp_ident_v == tmp_ident_v[i1_m[layer][idx1]]]: | ||||
|                         continue | ||||
|                     tmp_ident_v[i0_m[layer][idx0]] = tmp_ident_v[i1_m[layer][idx1]] | ||||
|                     errors_to_v[i1_m[layer][idx1]] = cp_error_cube[layer-1][idx0, idx1] | ||||
| 
 | ||||
|                     # errors_to_v[(tmp_ident_v == tmp_ident_v[i1_m[layer][idx1]]) & (np.isnan(errors_to_v))] = error_cube[layer][idx0, idx1] | ||||
|                     # errors_to_v[tmp_ident_v == tmp_ident_v[i1_m[layer][idx1]]][0] = np.nan | ||||
| 
 | ||||
|             else: | ||||
|                 if np.isnan(tmp_ident_v[i1_m[layer][idx1]]): | ||||
|                     if idx_v[i1_m[layer][idx1]] in idx_v[tmp_ident_v == tmp_ident_v[i0_m[layer][idx0]]]: | ||||
|                         continue | ||||
|                     tmp_ident_v[i1_m[layer][idx1]] = tmp_ident_v[i0_m[layer][idx0]] | ||||
|                     errors_to_v[i1_m[layer][idx1]] = cp_error_cube[layer-1][idx0, idx1] | ||||
| 
 | ||||
|                     # errors_to_v[(tmp_ident_v == tmp_ident_v[i1_m[layer][idx1]]) & (np.isnan(errors_to_v))] = error_cube[layer][idx0, idx1] | ||||
|                     # errors_to_v[tmp_ident_v == tmp_ident_v[i1_m[layer][idx1]]][0] = np.nan | ||||
| 
 | ||||
|                 else: | ||||
|                     if tmp_ident_v[i0_m[layer][idx0]] == tmp_ident_v[i1_m[layer][idx1]]: | ||||
|                         if np.isnan(errors_to_v[i1_m[layer][idx1]]): | ||||
|                             errors_to_v[i1_m[layer][idx1]] = cp_error_cube[layer-1][idx0, idx1] | ||||
|                         continue | ||||
| 
 | ||||
|                     idxs_i0 = idx_v[tmp_ident_v == tmp_ident_v[i0_m[layer][idx0]]] | ||||
|                     idxs_i1 = idx_v[tmp_ident_v == tmp_ident_v[i1_m[layer][idx1]]] | ||||
| 
 | ||||
|                     if np.any(np.diff(sorted(np.concatenate((idxs_i0, idxs_i1)))) == 0): | ||||
|                         continue | ||||
|                     tmp_ident_v[tmp_ident_v == tmp_ident_v[i0_m[layer][idx0]]] = tmp_ident_v[i1_m[layer][idx1]] | ||||
| 
 | ||||
|                     if np.isnan(errors_to_v[i1_m[layer][idx1]]): | ||||
|                         errors_to_v[i1_m[layer][idx1]] = cp_error_cube[layer-1][idx0, idx1] | ||||
| 
 | ||||
|         return tmp_ident_v, errors_to_v | ||||
| 
 | ||||
|     # _____ parameters and vectors _____ ### | ||||
| 
 | ||||
|     detection_time_diff = times[1] - times[0] | ||||
|     dps = 1. / detection_time_diff | ||||
| 
 | ||||
|     try: | ||||
|         ident_v = np.full(len(fund_v), np.nan)  # fish identities of frequencies | ||||
|         idx_of_origin_v = np.full(len(fund_v), np.nan) | ||||
|     except: | ||||
|         ident_v = np.zeros(len(fund_v)) / 0.  # fish identities of frequencies | ||||
|         idx_of_origin_v = np.zeros(len(fund_v)) / 0. | ||||
| 
 | ||||
|     idx_comp_range = int(np.floor(dps * 5.))  # maximum compare range backwards for amplitude signature comparison | ||||
|     # idx_comp_range = int(np.floor(dps * 15.))  # maximum compare range backwards for amplitude signature comparison | ||||
|     low_freq_th = 400.  # min. frequency tracked | ||||
|     high_freq_th = 1050.  # max. frequency tracked | ||||
| 
 | ||||
|     # _____ get amp and freq error distribution | ||||
|     # if hasattr(a_error_distribution, '__len__') and hasattr(f_error_distribution, '__len__'): | ||||
|     #     pass | ||||
|     # else: | ||||
|     #     f_error_distribution, a_error_distribution = get_a_and_f_error_dist(fund_v, idx_v, sign_v) | ||||
| 
 | ||||
|     # _____ create initial error cube _____ ### | ||||
|     error_cube = []  # [fundamental_list_idx, freqs_to_assign, target_freqs] | ||||
|     i0_m = [] | ||||
|     i1_m = [] | ||||
| 
 | ||||
|     next_message = 0. | ||||
|     start_idx = idx_v[0] | ||||
| 
 | ||||
|     f_error_distribution = [] | ||||
|     a_error_distribution = [] | ||||
|     idx_of_error = [] | ||||
| 
 | ||||
|     fig1, ax1 = plt.subplots() | ||||
|     ax1.plot(times[idx_v], fund_v, 'o', color='grey', alpha=.1) | ||||
|     tmp_ident_handle = [] | ||||
|     ident_handles = [] | ||||
| 
 | ||||
|     plt.show(block=False) | ||||
| 
 | ||||
| 
 | ||||
|     # # start_idx = 0 if not ioi_fti else idx_v[ioi_fti] # Index Of Interest for temporal identities | ||||
|     # distributions NEW | ||||
|     for i in range(start_idx, int(start_idx + idx_comp_range*2)): | ||||
|         next_message = include_progress_bar(i - start_idx, int(idx_comp_range*2), 'error dist init', next_message) | ||||
|         i0_v = np.arange(len(idx_v))[(idx_v == i) & (fund_v >= freq_lims[0]) & (fund_v <= freq_lims[1])]  # indices of fundamtenals to assign | ||||
|         i1_v = np.arange(len(idx_v))[(idx_v > i) & (idx_v <= (i + int(idx_comp_range))) & (fund_v >= freq_lims[0]) & (fund_v <= freq_lims[1])]  # indices of possible targets | ||||
| 
 | ||||
|         # i0_m.append(i0_v) | ||||
|         # i1_m.append(i1_v) | ||||
|         if len(i0_v) == 0 or len(i1_v) == 0:  # if nothing to assign or no targets continue | ||||
|             continue | ||||
| 
 | ||||
|         for enu0 in range(len(fund_v[i0_v])): | ||||
|             if fund_v[i0_v[enu0]] < low_freq_th or fund_v[i0_v[enu0]] > high_freq_th: | ||||
|                 continue | ||||
|             for enu1 in range(len(fund_v[i1_v])): | ||||
|                 if fund_v[i1_v[enu1]] < low_freq_th or fund_v[i1_v[enu1]] > high_freq_th: | ||||
|                     continue | ||||
|                 if np.abs(fund_v[i0_v[enu0]] - fund_v[i1_v[enu1]]) >= freq_tolerance:  # freq difference to high | ||||
|                     continue | ||||
|                 a_error_distribution.append(np.sqrt(np.sum([(sign_v[i0_v[enu0]][k] - sign_v[i1_v[enu1]][k]) ** 2 for k in range(len(sign_v[i0_v[enu0]]))]))) | ||||
|                 f_error_distribution.append(np.abs(fund_v[i0_v[enu0]] - fund_v[i1_v[enu1]])) | ||||
|                 idx_of_error.append(idx_v[i1_v[enu1]]) | ||||
| 
 | ||||
|     # Initial error cube | ||||
|     for i in range(start_idx, int(start_idx + idx_comp_range*2)): | ||||
|         next_message = include_progress_bar(i - start_idx, int(idx_comp_range*2), 'initial error cube', next_message) | ||||
|         i0_v = np.arange(len(idx_v))[(idx_v == i) & (fund_v >= freq_lims[0]) & (fund_v <= freq_lims[1])]  # indices of fundamtenals to assign | ||||
|         i1_v = np.arange(len(idx_v))[(idx_v > i) & (idx_v <= (i + int(idx_comp_range))) & (fund_v >= freq_lims[0]) & (fund_v <= freq_lims[1])]  # indices of possible targets | ||||
| 
 | ||||
|         i0_m.append(i0_v) | ||||
|         i1_m.append(i1_v) | ||||
| 
 | ||||
|         if len(i0_v) == 0 or len(i1_v) == 0:  # if nothing to assign or no targets continue | ||||
|             error_cube.append(np.array([[]])) | ||||
|             continue | ||||
|         try: | ||||
|             error_matrix = np.full((len(i0_v), len(i1_v)), np.nan) | ||||
|         except: | ||||
|             error_matrix = np.zeros((len(i0_v), len(i1_v))) / 0. | ||||
| 
 | ||||
|         for enu0 in range(len(fund_v[i0_v])): | ||||
|             if fund_v[i0_v[enu0]] < low_freq_th or fund_v[i0_v[enu0]] > high_freq_th:  # freq to assigne out of tracking range | ||||
|                 continue | ||||
|             for enu1 in range(len(fund_v[i1_v])): | ||||
|                 if fund_v[i1_v[enu1]] < low_freq_th or fund_v[i1_v[enu1]] > high_freq_th:  # target freq out of tracking range | ||||
|                     continue | ||||
|                 if np.abs(fund_v[i0_v[enu0]] - fund_v[i1_v[enu1]]) >= freq_tolerance:  # freq difference to high | ||||
|                     continue | ||||
| 
 | ||||
|                 a_error = np.sqrt(np.sum([(sign_v[i0_v[enu0]][j] - sign_v[i1_v[enu1]][j]) ** 2 for j in range(n_channels)])) | ||||
|                 f_error = np.abs(fund_v[i0_v[enu0]] - fund_v[i1_v[enu1]]) | ||||
|                 t_error = 1. * np.abs(idx_v[i0_v[enu0]] - idx_v[i1_v[enu1]]) / dps | ||||
| 
 | ||||
|                 error_matrix[enu0, enu1] = estimate_error(a_error, f_error, t_error, a_error_distribution, f_error_distribution) | ||||
|         error_cube.append(error_matrix) | ||||
| 
 | ||||
| 
 | ||||
|     cube_app_idx = idx_v[0] + len(error_cube) | ||||
| 
 | ||||
|     # _____ accual tracking _____ ### | ||||
|     next_identity = 0 | ||||
|     next_message = 0.00 | ||||
|     # for enu, i in enumerate(np.arange(len(fundamentals))): | ||||
|     for enu, i in enumerate(np.unique(idx_v)): | ||||
|         if enu == 0: | ||||
|             fig, ax = plt.subplots(1, 2) | ||||
|             n, h = np.histogram(f_error_distribution, 1000) | ||||
|             # a0, = ax[0].plot(h[1:], np.cumsum(n) / np.sum(n), color='cornflowerblue', linewidth=2) | ||||
|             ax[0].plot(h[:-1], np.cumsum(n) / np.sum(n), color='k', linewidth=2) | ||||
|             n, h = np.histogram(a_error_distribution, 1000) | ||||
|             # a1, = ax[1].plot(h[1:], np.cumsum(n) / np.sum(n), color='cornflowerblue', linewidth=2) | ||||
|             ax[1].plot(h[:-1], np.cumsum(n) / np.sum(n), color='k', linewidth=2) | ||||
|             plt.show(block=False) | ||||
|         else: | ||||
|             if len(f_error_distribution) >= 5000: | ||||
|                 f_error_distribution = f_error_distribution[-4000:] | ||||
|                 a_error_distribution = a_error_distribution[-4000:] | ||||
|                 idx_of_error = idx_of_error[-4000:] | ||||
|                 n, h = np.histogram(f_error_distribution, 1000) | ||||
|                 # a0.set_data(h[1:], np.cumsum(n) / np.sum(n)) | ||||
|                 c = np.random.rand(3) | ||||
|                 ax[0].plot(h[:-1], np.cumsum(n) / np.sum(n), color=c) | ||||
|                 n, h = np.histogram(a_error_distribution, 1000) | ||||
|                 ax[1].plot(h[:-1], np.cumsum(n) / np.sum(n), color=c) | ||||
|                 # a1.set_data(h[1:], np.cumsum(n) / np.sum(n)) | ||||
|                 fig.canvas.draw() | ||||
| 
 | ||||
|         # print(i, idx_v[-1]) | ||||
|         if i != 0 and (i % int(idx_comp_range * 120)) == 0: # clean up every 10 minutes | ||||
|             ident_v = clean_up(fund_v, ident_v, idx_v, times) | ||||
| 
 | ||||
|         if not return_tmp_idenities: | ||||
|             next_message = include_progress_bar(enu, len(np.unique(idx_v)), 'tracking', next_message)  # feedback | ||||
| 
 | ||||
|         if enu % idx_comp_range == 0: | ||||
|             # t0 = time.time() | ||||
|             tmp_ident_v, errors_to_v = get_tmp_identities(i0_m, i1_m, error_cube, fund_v, idx_v, i, ioi_fti, dps, idx_comp_range) | ||||
|             tmp_ident_regress = {} | ||||
|             for ident in np.unique(tmp_ident_v[~np.isnan(tmp_ident_v)]): | ||||
|                 slope, intercept, _, _, _ = scp.linregress(idx_v[tmp_ident_v == ident], fund_v[tmp_ident_v == ident]) | ||||
|                 tmp_ident_regress.update({'%.0f' %ident: [slope, intercept]}) | ||||
|                 # embed() | ||||
|                 # quit() | ||||
| 
 | ||||
|             # for hand in tmp_ident_handle: | ||||
|             #     hand.remove() | ||||
|             # tmp_ident_handle = [] | ||||
|             # for ident in np.unique(tmp_ident_v[~np.isnan(tmp_ident_v)]): | ||||
|             #     handle, = ax1.plot(times[idx_v][tmp_ident_v == ident], fund_v[tmp_ident_v == ident], color='red') | ||||
|             #     tmp_ident_handle.append(handle) | ||||
|             # fig1.canvas.draw() | ||||
| 
 | ||||
| 
 | ||||
|         idx0s, idx1s = np.unravel_index(np.argsort(error_cube[0], axis=None), np.shape(error_cube[0])) | ||||
| 
 | ||||
|         for idx0, idx1 in zip(idx0s, idx1s): | ||||
|             if np.isnan(error_cube[0][idx0, idx1]): | ||||
|                 break | ||||
| 
 | ||||
|             if freq_lims: | ||||
|                 if fund_v[i0_m[0][idx0]] > freq_lims[1] or fund_v[i0_m[0][idx0]] < freq_lims[0]: | ||||
|                     continue | ||||
|                 if fund_v[i1_m[0][idx1]] > freq_lims[1] or fund_v[i1_m[0][idx1]] < freq_lims[0]: | ||||
|                     continue | ||||
| 
 | ||||
|             if not np.isnan(ident_v[i1_m[0][idx1]]): | ||||
|                 continue | ||||
| 
 | ||||
|             if not np.isnan(errors_to_v[i1_m[0][idx1]]): | ||||
|                 if errors_to_v[i1_m[0][idx1]] < error_cube[0][idx0, idx1]: | ||||
|                     continue | ||||
| 
 | ||||
|             if np.isnan(ident_v[i0_m[0][idx0]]):  # i0 doesnt have identity | ||||
|                 if 1. * np.abs(fund_v[i0_m[0][idx0]] - fund_v[i1_m[0][idx1]]) / ((idx_v[i1_m[0][idx1]] - idx_v[i0_m[0][idx0]]) / dps) > 2.: | ||||
|                     continue | ||||
| 
 | ||||
|                 if np.isnan(ident_v[i1_m[0][idx1]]):  # i1 doesnt have identity | ||||
|                     ident_v[i0_m[0][idx0]] = next_identity | ||||
|                     ident_v[i1_m[0][idx1]] = next_identity | ||||
|                     next_identity += 1 | ||||
|                     a_error_distribution.append(np.sqrt(np.sum([(sign_v[i0_m[0][idx0]][k] - sign_v[i1_m[0][idx1]][k]) ** 2 for k in range(len(sign_v[i0_m[0][idx0]]))]))) | ||||
|                     f_error_distribution.append(np.abs(fund_v[i0_m[0][idx0]] - fund_v[i1_m[0][idx1]])) | ||||
|                     idx_of_error.append(idx_v[i1_m[0][idx1]]) | ||||
| 
 | ||||
|                 else:  # i1 does have identity | ||||
|                     continue | ||||
| 
 | ||||
|             else:  # i0 does have identity | ||||
|                 if np.isnan(ident_v[i1_m[0][idx1]]):  # i1 doesnt have identity | ||||
|                     if idx_v[i1_m[0][idx1]] in idx_v[ident_v == ident_v[i0_m[0][idx0]]]: | ||||
|                         continue | ||||
|                     # _____ if either idx0-idx1 is not a direct connection or ... | ||||
|                     # _____ idx1 is not the new last point of ident[idx0] check ... | ||||
|                     if not idx_v[i0_m[0][idx0]] == idx_v[ident_v == ident_v[i0_m[0][idx0]]][-1]:  # if i0 is not the last ... | ||||
|                         if len(ident_v[(ident_v == ident_v[i0_m[0][idx0]]) & (idx_v > idx_v[i0_m[0][idx0]]) & (idx_v < idx_v[i1_m[0][idx1]])]) == 0:  # zwischen i0 und i1 keiner | ||||
|                             next_idx_after_new = np.arange(len(ident_v))[(ident_v == ident_v[i0_m[0][idx0]]) & (idx_v > idx_v[i1_m[0][idx1]])][0] | ||||
|                             if tmp_ident_v[next_idx_after_new] != tmp_ident_v[i1_m[0][idx1]]: | ||||
|                                 continue | ||||
|                         elif len(ident_v[(ident_v == ident_v[i0_m[0][idx0]]) & (idx_v > idx_v[i1_m[0][idx1]])]) == 0:  # keiner nach i1 | ||||
|                             last_idx_before_new = np.arange(len(ident_v))[(ident_v == ident_v[i0_m[0][idx0]]) & (idx_v < idx_v[i1_m[0][idx1]])][-1] | ||||
|                             if tmp_ident_v[last_idx_before_new] != tmp_ident_v[i1_m[0][idx1]]: | ||||
|                                 continue | ||||
|                         else:  # sowohl als auch | ||||
|                             next_idx_after_new = np.arange(len(ident_v))[(ident_v == ident_v[i0_m[0][idx0]]) & (idx_v > idx_v[i1_m[0][idx1]])][0] | ||||
|                             last_idx_before_new = np.arange(len(ident_v))[(ident_v == ident_v[i0_m[0][idx0]]) & (idx_v < idx_v[i1_m[0][idx1]])][-1] | ||||
|                             if tmp_ident_v[last_idx_before_new] != tmp_ident_v[i1_m[0][idx1]] or tmp_ident_v[next_idx_after_new] != tmp_ident_v[i1_m[0][idx1]]: | ||||
|                                 continue | ||||
| 
 | ||||
|                     ident_v[i1_m[0][idx1]] = ident_v[i0_m[0][idx0]] | ||||
|                     a_error_distribution.append(np.sqrt(np.sum([(sign_v[i0_m[0][idx0]][k] - sign_v[i1_m[0][idx1]][k]) ** 2 for k in range(len(sign_v[i0_m[0][idx0]]))]))) | ||||
|                     f_error_distribution.append(np.abs(fund_v[i0_m[0][idx0]] - fund_v[i1_m[0][idx1]])) | ||||
|                     idx_of_error.append(idx_v[i1_m[0][idx1]]) | ||||
|                 else: | ||||
|                     continue | ||||
| 
 | ||||
|             idx_of_origin_v[i1_m[0][idx1]] = i0_m[0][idx0] | ||||
|         # | ||||
|         # for hand in ident_handles: | ||||
|         #     hand.remove() | ||||
|         # ident_handles = [] | ||||
|         # for ident in np.unique(ident_v[~np.isnan(ident_v)]): | ||||
|         #     hand, = ax1.plot(times[idx_v][ident_v == ident], fund_v[ident_v == ident], color='green', lw=2) | ||||
|         #     ident_handles.append(hand) | ||||
|         # | ||||
|         # ax1.set_xlim([times[idx_v[~np.isnan(tmp_ident_v)][0]] - 10, times[idx_v[~np.isnan(tmp_ident_v)][-1]] + 10 ]) | ||||
|         # fig1.canvas.draw() | ||||
| 
 | ||||
|         # plt.waitforbuttonpress() | ||||
| 
 | ||||
|         # sort_time += time.time()-t0 | ||||
|         i0_m.pop(0) | ||||
|         i1_m.pop(0) | ||||
|         error_cube.pop(0) | ||||
| 
 | ||||
|         i0_v = np.arange(len(idx_v))[(idx_v == cube_app_idx) & (fund_v >= freq_lims[0]) & (fund_v <= freq_lims[1])]  # indices of fundamtenals to assign | ||||
|         i1_v = np.arange(len(idx_v))[(idx_v > cube_app_idx) & (idx_v <= (cube_app_idx + idx_comp_range)) & (fund_v >= freq_lims[0]) & (fund_v <= freq_lims[1])]  # indices of possible targets | ||||
| 
 | ||||
|         i0_m.append(i0_v) | ||||
|         i1_m.append(i1_v) | ||||
| 
 | ||||
|         # embed() | ||||
|         # quit() | ||||
|         if len(i0_v) == 0 or len(i1_v) == 0:  # if nothing to assign or no targets continue | ||||
|             error_cube.append(np.array([[]])) | ||||
| 
 | ||||
|         else: | ||||
|             try: | ||||
|                 error_matrix = np.full((len(i0_v), len(i1_v)), np.nan) | ||||
|             except: | ||||
|                 error_matrix = np.zeros((len(i0_v), len(i1_v))) / 0. | ||||
| 
 | ||||
|             for enu0 in range(len(fund_v[i0_v])): | ||||
|                 if fund_v[i0_v[enu0]] < low_freq_th or fund_v[i0_v[enu0]] > high_freq_th:  # freq to assigne out of tracking range | ||||
|                     continue | ||||
| 
 | ||||
|                 for enu1 in range(len(fund_v[i1_v])): | ||||
|                     if fund_v[i1_v[enu1]] < low_freq_th or fund_v[i1_v[enu1]] > high_freq_th:  # target freq out of tracking range | ||||
|                         continue | ||||
|                     if np.abs(fund_v[i0_v[enu0]] - fund_v[i1_v[enu1]]) >= freq_tolerance:  # freq difference to high | ||||
|                         continue | ||||
| 
 | ||||
|                     a_error = np.sqrt( | ||||
|                         np.sum([(sign_v[i0_v[enu0]][j] - sign_v[i1_v[enu1]][j]) ** 2 for j in range(n_channels)])) | ||||
|                     if not np.isnan(tmp_ident_v[i0_v[enu0]]): | ||||
|                         a = tmp_ident_regress['%.0f' % tmp_ident_v[i0_v[enu0]]][0] | ||||
|                         b = tmp_ident_regress['%.0f' % tmp_ident_v[i0_v[enu0]]][1] | ||||
|                         f_error = np.abs( (a*idx_v[i1_v[enu1]]+b) - fund_v[i1_v[enu1]]) | ||||
| 
 | ||||
|                     else: | ||||
|                         f_error = np.abs(fund_v[i0_v[enu0]] - fund_v[i1_v[enu1]]) | ||||
|                     t_error = 1. * np.abs(idx_v[i0_v[enu0]] - idx_v[i1_v[enu1]]) / dps | ||||
| 
 | ||||
|                     error_matrix[enu0, enu1] = estimate_error(a_error, f_error, t_error, a_error_distribution, | ||||
|                                                               f_error_distribution) | ||||
|             error_cube.append(error_matrix) | ||||
| 
 | ||||
|         cube_app_idx += 1 | ||||
|     ident_v = clean_up(fund_v, ident_v, idx_v, times) | ||||
| 
 | ||||
|     return fund_v, ident_v, idx_v, sign_v, a_error_distribution, f_error_distribution, idx_of_origin_v | ||||
| 
 | ||||
| if __name__ == '__main__': | ||||
| 
 | ||||
|     fund_v = np.load('/home/raab/paper_create/raab2018_tracking_without_tagging/bsp_data/2016-04-10-22:14/fund_v.npy') | ||||
|     idx_v = np.load('/home/raab/paper_create/raab2018_tracking_without_tagging/bsp_data/2016-04-10-22:14/idx_v.npy') | ||||
|     times = np.load('/home/raab/paper_create/raab2018_tracking_without_tagging/bsp_data/2016-04-10-22:14/times.npy') | ||||
|     sign_v = np.load('/home/raab/paper_create/raab2018_tracking_without_tagging/bsp_data/2016-04-10-22:14/sign_v.npy') | ||||
|     # ident_v = np.load('/home/raab/paper_create/raab2018_tracking_without_tagging/bsp_data/2016-04-10-22:14/ident_v.npy') | ||||
|     ident_v = np.load('/home/raab/paper_create/raab2018_tracking_without_tagging/bsp_data/2016-04-10-22:14/ident_v2.npy') | ||||
| 
 | ||||
|     # embed() | ||||
|     # quit() | ||||
|     # fund_v, ident_v, idx_v, sign_v, a_error_distribution, f_error_distribution, idx_of_origin_v = freq_tracking_v3(fund_v, idx_v, sign_v, times, freq_tolerance=40., n_channels=np.shape(sign_v)[1]) | ||||
| 
 | ||||
|     a_errors_true = [] | ||||
|     a_errors_false = [] # 2 sek | ||||
|     f_errors_true = [] # 5 sek | ||||
|     f_errors_false = [] | ||||
| 
 | ||||
|     # freq tollerance = 2 | ||||
| 
 | ||||
|     for i in tqdm(range(len(fund_v))): | ||||
|         for j in range(i, len(fund_v)): | ||||
|             if idx_v[i] == idx_v[j] or times[idx_v[j]] - times[idx_v[i]] > .5: | ||||
|                 continue | ||||
|             if np.abs(fund_v[i] - fund_v[j]) >2.: | ||||
|                 continue | ||||
| 
 | ||||
|             if ident_v[i] == ident_v[j]: | ||||
|                 f_errors_true.append(np.abs(fund_v[i] - fund_v[j])) | ||||
|                 a_errors_true.append(np.sqrt(np.sum([(sign_v[i][a] - sign_v[j][a]) ** 2 for a in range(len(sign_v[i]))]))) | ||||
|             else: | ||||
|                 f_errors_false.append(np.abs(fund_v[i] - fund_v[j])) | ||||
|                 a_errors_false.append(np.sqrt(np.sum([(sign_v[i][a] - sign_v[j][a]) ** 2 for a in range(len(sign_v[i]))]))) | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
|     fig, ax = plt.subplots() | ||||
|     ax.plot(times[idx_v], fund_v, 'o', color='grey', alpha=.5) | ||||
|     for ident in np.unique(ident_v[~np.isnan(ident_v)]): | ||||
|         ax.plot(times[idx_v[ident_v == ident]], fund_v[ident_v == ident], color = np.random.rand(3), marker ='.') | ||||
|     plt.show() | ||||
|     embed() | ||||
|     quit() | ||||
							
								
								
									
										
											BIN
										
									
								
								figures/1.pdf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								figures/1.pdf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								figures/10.pdf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								figures/10.pdf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								figures/12.pdf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								figures/12.pdf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								figures/2.pdf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								figures/2.pdf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								figures/3.pdf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								figures/3.pdf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								figures/4.pdf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								figures/4.pdf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								figures/6.pdf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								figures/6.pdf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								figures/7.pdf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								figures/7.pdf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								figures/8.pdf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								figures/8.pdf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
							
								
								
									
										
											BIN
										
									
								
								figures/9.pdf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								figures/9.pdf
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							
		Loading…
	
		Reference in New Issue
	
	Block a user