def HighPassFilter(t, px, py, moco_kernel, central_fix): ''' Slow drift correction by robust high-pass filtering Effectively forces long-term average pupil fixation to be centrally fixated in video space. Arguments ---- t : 1D float array Video soft timestamps in seconds px : 1D float array Video space pupil center x py : 1D float array Video space pupil center y moco_kernel : integer Temporal kernel width in samples [31] central_fix : float tuple (x,y) coordinate in video space of central fixation Returns ---- px_filt : 1D float array Drift corrected video space pupil center x py_filt : 1D float array Drift corrected video space pupil center y ''' # Force odd-valued kernel width moco_kernel = utils._forceodd(moco_kernel) print(' Highpass filtering with %d sample kernel' % moco_kernel) # Infill NaN regions # Replace NaNs with unreasonable but finite value for median filtering nan_idx = np.isnan(px) px[nan_idx] = -1e9 py[nan_idx] = -1e9 # Moving median filter to estimate baseline px_bline = medfilt(px, moco_kernel) py_bline = medfilt(py, moco_kernel) # Restore NaNs to vectors px_bline[nan_idx] = np.nan py_bline[nan_idx] = np.nan # Subtract baseline and add central fixation offset px_filt = px - px_bline + central_fix[0] py_filt = py - py_bline + central_fix[1] return px_filt, py_filt, px_bline, py_bline
def HighPassFilter(t, px, py, moco_kernel, central_fix): """ Slow drift correction by robust high-pass filtering Effectively forces long-term average pupil fixation to be centrally fixated in video space. Arguments ---- t : 1D float array Video soft timestamps in seconds px : 1D float array Video space pupil center x py : 1D float array Video space pupil center y moco_kernel : integer Temporal kernel width in samples [31] central_fix : float tuple (x,y) coordinate in video space of central fixation Returns ---- px_filt : 1D float array Drift corrected video space pupil center x py_filt : 1D float array Drift corrected video space pupil center y """ # Force odd-valued kernel width moco_kernel = utils._forceodd(moco_kernel) print(" Highpass filtering with %d sample kernel" % moco_kernel) # Infill NaN regions # Replace NaNs with unreasonable but finite value for median filtering nan_idx = np.isnan(px) px[nan_idx] = -1e9 py[nan_idx] = -1e9 # Moving median filter to estimate baseline px_bline = medfilt(px, moco_kernel) py_bline = medfilt(py, moco_kernel) # Restore NaNs to vectors px_bline[nan_idx] = np.nan py_bline[nan_idx] = np.nan # Subtract baseline and add central fixation offset px_filt = px - px_bline + central_fix[0] py_filt = py - py_bline + central_fix[1] return px_filt, py_filt, px_bline, py_bline
def FilterPupilometry(pupils_csv, pupils_filt_csv): ''' DEPRECATED: Temporally filter all pupilometry timeseries ''' if not os.path.isfile(pupils_csv): print('* Raw pupilometry CSV file missing - returning') return False # Read raw pupilometry data p = ReadPupilometry(pupils_csv) # Sampling time (s) dt = p[1,0] - p[0,0] # Kernel widths for each metric k_area = utils._forceodd(0.25 / dt) k_pupil = 3 k_blink = utils._forceodd(0.25 / dt) k_art = utils._forceodd(1.0 / dt) # Moving median filter pf = p.copy() pf[:,1] = utils._nanmedfilt(p[:,1], k_area) pf[:,2] = utils._nanmedfilt(p[:,2], k_pupil) # Pupil x pf[:,3] = utils._nanmedfilt(p[:,3], k_pupil) # Pupil y # Blink filter pf[:,4] = utils._nanmedfilt(p[:,8], k_blink) # Artifact power pf[:,5] = utils._nanmedfilt(pf[:,9], k_art) # Write filtered timeseries to new CSV file in results directory np.savetxt(pupils_filt_csv, pf, fmt='%.6f', delimiter=',') # Clean return return True
def FilterPupilometry(pupils_csv, pupils_filt_csv): ''' DEPRECATED: Temporally filter all pupilometry timeseries ''' if not os.path.isfile(pupils_csv): print('* Raw pupilometry CSV file missing - returning') return False # Read raw pupilometry data p = ReadPupilometry(pupils_csv) # Sampling time (s) dt = p[1, 0] - p[0, 0] # Kernel widths for each metric k_area = utils._forceodd(0.25 / dt) k_pupil = 3 k_blink = utils._forceodd(0.25 / dt) k_art = utils._forceodd(1.0 / dt) # Moving median filter pf = p.copy() pf[:, 1] = utils._nanmedfilt(p[:, 1], k_area) pf[:, 2] = utils._nanmedfilt(p[:, 2], k_pupil) # Pupil x pf[:, 3] = utils._nanmedfilt(p[:, 3], k_pupil) # Pupil y # Blink filter pf[:, 4] = utils._nanmedfilt(p[:, 8], k_blink) # Artifact power pf[:, 5] = utils._nanmedfilt(pf[:, 9], k_art) # Write filtered timeseries to new CSV file in results directory np.savetxt(pupils_filt_csv, pf, fmt='%.6f', delimiter=',') # Clean return return True
def EstimateBias(fr): ''' Estimate illumination bias field Arguments ---- fr : 2D numpy uint8 array Uncorrected image with biased illumination Returns ---- bias_field : 2D numpy float array Estimated bias multiplier field ''' # Target downsampled matrix size nd = 32; # Get image dimensions ny, nx, nz = fr.shape # Target maximum dimension is 32 # Apect ratio preserved approximately if nx > ny: nxd = nd nyd = int(nx/32.0 * ny) else: nxd = int(ny/32.0 * nx) nyd = nd # Downsample frame fr_d = cv2.resize(fr, (nxd, nyd)) # 2D baseline estimation # Use large kernel relative to image size k = utils._forceodd(nd/2) bias_field_d = cv2.medianBlur(fr_d, k) # Bias correction bias_corr_d = 1 - (bias_field_d - np.mean(fr_d)) / fr_d # Upsample biasfield to same size as original frame bias_corr = cv2.resize(bias_corr_d, (nx, ny)) # DEBUG: Flat bias correction bias_corr = np.ones_like(fr) return bias_corr
def EstimateBias(fr): ''' Estimate illumination bias field Arguments ---- fr : 2D numpy uint8 array Uncorrected image with biased illumination Returns ---- bias_field : 2D numpy float array Estimated bias multiplier field ''' # Target downsampled matrix size nd = 32 # Get image dimensions ny, nx, nz = fr.shape # Target maximum dimension is 32 # Apect ratio preserved approximately if nx > ny: nxd = nd nyd = int(nx / 32.0 * ny) else: nxd = int(ny / 32.0 * nx) nyd = nd # Downsample frame fr_d = cv2.resize(fr, (nxd, nyd)) # 2D baseline estimation # Use large kernel relative to image size k = utils._forceodd(nd / 2) bias_field_d = cv2.medianBlur(fr_d, k) # Bias correction bias_corr_d = 1 - (bias_field_d - np.mean(fr_d)) / fr_d # Upsample biasfield to same size as original frame bias_corr = cv2.resize(bias_corr_d, (nx, ny)) # DEBUG: Flat bias correction bias_corr = np.ones_like(fr) return bias_corr