from dataclasses import dataclass import numpy as np import scipy.linalg as la from scipy.signal import find_peaks from math import ceil def thin_points(point_list, dmin=10, voxel_size=(1,1,1)): """ Remove points within a specified distance of each other, retaining the point with the highest intensity. Args: - point_list (list of tuples): Each tuple contains: - x (list of float): 3D coordinates of the point. - intensity (float): The intensity value of the point. - idx (int): A unique identifier or index for the point. - dmin (float, optional): Minimum distance between points. Points closer than this threshold will be thinned. Defaults to 10. Returns: - list of int: A list containing indices of the removed points. Notes: - The function uses the L2 norm (Euclidean distance) to compute the distance between points. - When two points are within `dmin` distance, the point with the lower intensity is removed. """ removed_points = [] for i in range(len(point_list)): if point_list[i][2] in removed_points: continue for j in range(len(point_list)): if i==j: continue if point_list[j][2] in removed_points: continue d = (np.array(point_list[i][0]) - np.array(point_list[j][0]))*np.array(voxel_size) d = la.norm(d) if d=alpha*np.max(v)) return np.array(pos[idx]) def analyse_celldata(cell_data, config): """ Analyse the provided cell data to extract focus-related information. Args: cd (CellData): An instance of the CellData class containing path data information. config (dictionary): Configuration dictionary containing 'peak_threshold' and 'threshold_type' 'peak_threshold' (float) - threshold for calling peaks as foci 'threshold_type' (str) = 'per-trace', 'per-foci' Returns: tuple: A tuple containing three lists: - foci_rel_intensity (list): List of relative intensities for the detected foci. - foci_pos (list): List of absolute positions of the detected foci. - foci_pos_index (list): List of indices of the detected foci. """ foci_abs_intensity = [] foci_pos = [] foci_pos_index = [] trace_median_intensities = [] trace_thresholds = [] peak_threshold = config['peak_threshold'] threshold_type = config['threshold_type'] if threshold_type == 'per-trace': """ Call extracted peaks as foci if intensity - trace_mean > peak_threshold * (trace_max_foci_intensity - trace_mean) """ for path_data in cell_data.pathdata_list: peaks = np.array(path_data.peaks, dtype=np.int32) # Normalize extracted fluorescent intensities by subtracting mean (and dividing # by standard deviation - note that the latter should have no effect on the results). h = np.array(path_data.o_hei10) h = h - np.mean(h) h = h/np.std(h) # Extract peaks according to criterion sig_peak_idx = pc(peaks, h[peaks], peak_threshold) trace_thresholds.append((1-peak_threshold)*np.mean(path_data.o_hei10) + peak_threshold*np.max(np.array(path_data.o_hei10)[peaks])) pos_abs = (sig_peak_idx/len(path_data.points))*path_data.SC_length foci_pos.append(pos_abs) foci_abs_intensity.append(np.array(path_data.o_hei10)[sig_peak_idx]) foci_pos_index.append(sig_peak_idx) trace_median_intensities.append(np.median(path_data.o_hei10)) elif threshold_type == 'per-cell': """ Call extracted peaks as foci if intensity - trace_mean > peak_threshold * max(intensity - trace_mean) """ max_cell_intensity = float("-inf") for path_data in cell_data.pathdata_list: # Normalize extracted fluorescent intensities by subtracting mean (and dividing # by standard deviation - note that the latter should have no effect on the results). h = np.array(path_data.o_hei10) h = h - np.mean(h) max_cell_intensity = max(max_cell_intensity, np.max(h)) for path_data in cell_data.pathdata_list: peaks = np.array(path_data.peaks, dtype=np.int32) # Normalize extracted fluorescent intensities by subtracting mean (and dividing # by standard deviation - note that the latter should have no effect on the results). h = np.array(path_data.o_hei10) h = h - np.mean(h) sig_peak_idx = peaks[h[peaks]>peak_threshold*max_cell_intensity] trace_thresholds.append(np.mean(path_data.o_hei10) + peak_threshold*max_cell_intensity) pos_abs = (sig_peak_idx/len(path_data.points))*path_data.SC_length foci_pos.append(pos_abs) foci_abs_intensity.append(np.array(path_data.o_hei10)[sig_peak_idx]) foci_pos_index.append(sig_peak_idx) trace_median_intensities.append(np.median(path_data.o_hei10)) else: raise NotImplementedError return foci_abs_intensity, foci_pos, foci_pos_index, trace_median_intensities, trace_thresholds def analyse_traces(all_paths, path_lengths, measured_trace_fluorescence, config): cd = process_cell_traces(all_paths, path_lengths, measured_trace_fluorescence) return analyse_celldata(cd, config)