def execute(self, namespace): inp = namespace[self.inputName] # generate LineProfileHandler from tables handler = LineProfileHandler() handler._load_profiles_from_list(inp) fit_class = profile_fitters.ensemble_fitters[self.fit_type] self.fitter = fit_class(handler) if self.hold_ensemble_parameter_constant: self.fitter.fit_profiles(self.ensemble_parameter_guess) else: self.fitter.ensemble_fit(self.ensemble_parameter_guess) res = tabular.RecArraySource(self.fitter.results) # propagate metadata, if present res.mdh = MetaDataHandler.NestedClassMDHandler( getattr(inp, 'mdh', None)) res.mdh['EnsembleFitProfiles.FitType'] = self.fit_type res.mdh[ 'EnsembleFitProfiles.EnsembleParameterGuess'] = self.ensemble_parameter_guess res.mdh[ 'EnsembleFitProfiles.HoldEnsembleParamConstant'] = self.hold_ensemble_parameter_constant namespace[self.outputName] = res
def execute(self, namespace): #from PYME.localization.FitFactories import DumbellFitR from PYME.IO import MetaDataHandler img = namespace[self.inputImage] md = MetaDataHandler.NestedClassMDHandler() #set metadata entries needed for fitting to suitable defaults md['Camera.ADOffset'] = img.data[:, :, 0].min() md['Camera.TrueEMGain'] = 1.0 md['Camera.ElectronsPerCount'] = 1.0 md['Camera.ReadNoise'] = 1.0 md['Camera.NoiseFactor'] = 1.0 #copy across the entries from the real image, replacing the defaults #if necessary md.copyEntriesFrom(img.mdh) inp = namespace[self.inputPositions] res = np.zeros(len(inp['x']), dtype=[('r%d' % r, 'f4') for r in self.radii]) ff_t = -1 aggFunc = getattr(self, '_get_%s' % self.mode) ps = img.pixelSize print('pixel size: %s' % ps) for x, y, t, i in zip(inp['x'], inp['y'], inp['t'], range(len(inp['x']))): for r in self.radii: res[i]['r%d' % r] = aggFunc(img.data, np.round(x / ps), np.round(y / ps), t, r) res = tabular.RecArraySource(res) res.mdh = md namespace[self.outputName] = res
def execute(self, namespace): from PYME.IO.FileUtils import readSpeckle from PYME.IO import MetaDataHandler import os fileInfo = {'SEP': os.sep} seriesLength = 100000 mdh = MetaDataHandler.NestedClassMDHandler() mdh['voxelsize.x'] = .001 # default pixel size - FIXME mdh['voxelsize.y'] = .001 #use a default sensor size of 512 #this gets over-ridden below if we supply an image clip_region = [ self.edgeRejectionPixels, self.edgeRejectionPixels, 512 - self.edgeRejectionPixels, 512 - self.edgeRejectionPixels ] if not self.inputImage == '': inp = namespace[self.inputImage] mdh.update(inp.mdh) seriesLength = inp.data.shape[2] clip_region = [ self.edgeRejectionPixels, self.edgeRejectionPixels, inp.data.shape[0] - self.edgeRejectionPixels, inp.data.shape[1] - self.edgeRejectionPixels ] try: fileInfo['DIRNAME'], fileInfo['IMAGENAME'] = os.path.split( inp.filename) fileInfo['IMAGESTUB'] = fileInfo['IMAGENAME'].split('MM')[0] except: pass speckleFN = self.speckleFilename.format(**fileInfo) specks = readSpeckle.readSpeckles(speckleFN) traces = readSpeckle.gen_traces_from_speckles( specks, leadFrames=self.leadFrames, followFrames=self.followFrames, seriesLength=seriesLength, clipRegion=clip_region) #turn this into an inputFilter object inp = tabular.RecArraySource(traces) #create a mapping to covert the co-ordinates in pixels to co-ordinates in nm vs = mdh.voxelsize_nm map = tabular.MappingFilter(inp, x='x_pixels*%3.2f' % vs.x, y='y_pixels*%3.2f' % vs.y) map.mdh = mdh namespace[self.outputName] = map
def execute(self, namespace): import PYME.Analysis.points.spherical_harmonics as spharm from PYME.IO import MetaDataHandler inp = namespace[self.input_name] modes, coefficients, centre = spharm.sphere_expansion_clean( inp['x'], inp['y'], inp['z'] * self.z_scale, mmax=self.max_m_mode, centre_points=True, nIters=self.n_iterations, tol_init=self.init_tolerance) mdh = MetaDataHandler.NestedClassMDHandler() try: mdh.copyEntriesFrom(namespace[self.input_name].mdh) except AttributeError: pass mdh['Processing.SphericalHarmonicShell.ZScale'] = self.z_scale mdh['Processing.SphericalHarmonicShell.MaxMMode'] = self.max_m_mode mdh['Processing.SphericalHarmonicShell.NIterations'] = self.n_iterations mdh['Processing.SphericalHarmonicShell.InitTolerance'] = self.init_tolerance mdh['Processing.SphericalHarmonicShell.Centre'] = centre output_dtype = [('modes', '<2i4'), ('coefficients', '<f4')] out = np.zeros(len(coefficients), dtype=output_dtype) out['modes'] = modes out['coefficients'] = coefficients out = tabular.RecArraySource(out) out.mdh = mdh namespace[self.output_name] = out
def execute(self, namespace): from PYME.Analysis.points import cluster_morphology as cmorph import numpy as np inp = namespace[self.inputName] # make sure labeling scheme is consistent with what pyme conventions if np.min(inp[self.labelKey]) < 0: raise UserWarning( 'This module expects 0-label for unclustered points, and no negative labels' ) labels = inp[self.labelKey].astype(np.int) I = np.argsort(labels) I = I[labels[I] > 0] x_vals, y_vals, z_vals = inp['x'][I], inp['y'][I], inp['z'][I] labels = labels[I] maxLabel = labels[-1] #find the unique labels, and their separation in the sorted list of points unique_labels, counts = np.unique(labels, return_counts=True) #allocate memory to store results in measurements = np.zeros(maxLabel, cmorph.measurement_dtype) # loop over labels, recalling that input is now sorted, and we know how many points are in each label. # Note that missing labels result in zeroed entries (i.e. the initial values are not changed). # Missing values can be filtered out later, if desired, by filtering on the 'counts' column, but having a dense # array where index == label number makes any postprocessing in which we might want to find the data # corresponding to a particular label MUCH easier and faster. indi = 0 for label_num, ct in zip(unique_labels, counts): indf = indi + ct # create x,y,z arrays for this cluster, and calculate center of mass x, y, z = x_vals[indi:indf], y_vals[indi:indf], z_vals[indi:indf] cluster_index = label_num - 1 # we ignore the unclustered points, and start labeling at 1 cmorph.measure_3d(x, y, z, output=measurements[cluster_index]) indi = indf meas = tabular.RecArraySource(measurements) try: meas.mdh = namespace[self.inputName].mdh except AttributeError: pass namespace[self.outputName] = meas
def OnSave(self, event): filename = wx.SaveFileSelector( "Save data as ...", 'HDF (*.hdf)|*.hdf|Comma separated text (*.csv)|*.csv') if not filename == '': if isinstance(self.data, tabular.TabularBase): data = self.data else: data = tabular.RecArraySource(self.data) if filename.endswith('.hdf'): data.to_hdf(filename) else: data.to_csv(filename)
def test_thickness(self, ensemble_parameter={'psf_fwhm': np.arange(35, 105, 5)}, annulus_thicknesses=None, outdir=None): from PYME.IO import tabular import matplotlib.pyplot as plt psfs = ensemble_parameter['psf_fwhm'] num_psfs = len(psfs) num_annuli = len(annulus_thicknesses) mmse = np.zeros((num_psfs, num_annuli)) diameters = np.zeros_like(mmse) for pi in range(num_psfs): for ai in range(num_annuli): self.annulus_thickness = annulus_thicknesses[ai] mmse[pi, ai] = self.fit_profiles_mean(psfs[pi]) if outdir is not None: res = tabular.RecArraySource(self.results) res.to_hdf(outdir + 'ensemble_fit_results_psf%f_annulus%f.hdf' % (psfs[pi], self.annulus_thickness)) plt.figure() diameter_bins = np.arange(0, 200, 10) mean_diameter = np.mean(res['fitResults']['diameter']) diameters[pi, ai] = mean_diameter plt.hist(res['fitResults']['diameter'], bins=diameter_bins, color='gray') plt.xlabel('Tubule Diameter [nm]', size=26) plt.ylabel('Counts', size=26) plt.title( 'mean = %.1f +- %f.1 nm' % (mean_diameter, np.std(res['fitResults']['diameter']))) plt.tight_layout() plt.savefig(outdir + 'diameter_histogram_psf%f_annulus%f.pdf' % (psfs[pi], self.annulus_thickness)) return mmse, diameters
def execute(self, namespace): inp = namespace[self.inputName] # generate LineProfileHandler from tables handler = LineProfileHandler() handler._load_profiles_from_list(inp) fit_class = profile_fitters.non_ensemble_fitters[self.fit_type] self.fitter = fit_class(handler) self.fitter.fit_profiles() res = tabular.RecArraySource(self.fitter.results) # propagate metadata, if present res.mdh = MetaDataHandler.NestedClassMDHandler( getattr(inp, 'mdh', None)) res.mdh['FitProfiles.FitType'] = self.fit_type namespace[self.outputName] = res
def execute(self, namespace): from PYME.IO.image import ImageStack series = namespace[self.input_series] positions = namespace[self.input_positions] ox_nm, oy_nm, oz = series.origin vs_nm = np.array([series.voxelsize_nm.x, series.voxelsize_nm.y]) roi_half_nm = (self.roi_half_size + 1) * vs_nm x_max, y_max = (series.data.shape[:2] * vs_nm) - roi_half_nm edge_filtered = tabular.ResultsFilter(positions, x=[ox_nm + roi_half_nm[0], x_max], y=[oy_nm + roi_half_nm[1], y_max]) n_filtered = len(positions) - len(edge_filtered) if n_filtered > 0: logger.error('%d positions too close to edge, filtering.' % n_filtered) extracted = FitPoints(fitModule='ROIExtractNR', roiHalfSize=self.roi_half_size, channel=0).apply_simple(inputImage=series, inputPositions=edge_filtered) # get roi edge position. FFBase._get_roi rounds before extracting relative_positions = edge_filtered.to_recarray() x_edge = np.round(edge_filtered['x'] / series.voxelsize_nm.x) - self.roi_half_size y_edge = np.round(edge_filtered['y'] / series.voxelsize_nm.y) - self.roi_half_size # subtract off ofset to ROI edge relative_positions['x'] = edge_filtered['x'] - (x_edge * series.voxelsize_nm.x) relative_positions['y'] = edge_filtered['y'] - (y_edge * series.voxelsize_nm.y) relative_positions['fitResults_x0'] = relative_positions['x'] relative_positions['fitResults_y0'] = relative_positions['y'] relative_positions = tabular.RecArraySource(relative_positions) relative_positions.mdh = MetaDataHandler.NestedClassMDHandler(positions.mdh) relative_positions.mdh['ExtractROIs.RoiHalfSize'] = self.roi_half_size namespace[self.output_rois] = ImageStack(data=np.moveaxis(extracted['data'], 0, 2), mdh=series.mdh) namespace[self.output_relative_positions] = relative_positions
def execute(self, namespace): inp = namespace[self.inputName] # generate LineProfileHandler from tables handler = LineProfileHandler() handler._load_profiles_from_list(inp) fit_class = profile_fitters.ensemble_fitters[self.fit_type] fitter = fit_class(handler) results = fitter.ensemble_test(self.ensemble_test_values) res = tabular.RecArraySource(results) # propagate metadata, if present res.mdh = MetaDataHandler.NestedClassMDHandler( getattr(inp, 'mdh', None)) res.mdh['TestEnsembleParameters.FitType'] = self.fit_type res.mdh[ 'TestEnsembleParameters.EnsembleTestValues'] = self.ensemble_test_values namespace[self.outputName] = res
def execute(self, namespace): from PYME.Analysis.points import twoColour from PYME.Analysis.points import multiview from PYME.IO.MetaDataHandler import NestedClassMDHandler inp = namespace[self.input_name] try: # make sure we're looking at multiview data n_chan = inp.mdh['Multiview.NumROIs'] except AttributeError: raise AttributeError('multiview metadata is missing or incomplete') # sort in frame order I = inp['tIndex'].argsort() x_sort, y_sort = inp['x'][I], inp['y'][I] chan_sort = inp['multiviewChannel'][I] clump_id, keep = multiview.pair_molecules( inp['tIndex'][I], x_sort, y_sort, chan_sort, self.search_radius_nm * np.ones_like(x_sort), appear_in=np.arange(n_chan), n_frame_sep=inp['tIndex'].max(), pix_size_nm=1e3 * inp.mdh['voxelsize.x']) # only look at the clumps which showed up in all channels x = x_sort[keep] y = y_sort[keep] chan = chan_sort[keep] clump_id = clump_id[keep] # Generate raw shift vectors (map of displacements between channels) for each channel mol_list = np.unique(clump_id) n_mols = len(mol_list) dx = np.zeros((n_chan - 1, n_mols)) dy = np.zeros_like(dx) dx_err = np.zeros_like(dx) dy_err = np.zeros_like(dx) x_clump, y_clump, x_std, y_std, x_shifted, y_shifted = [], [], [], [], [], [] shift_map_dtype = [ ('mx', '<f4'), ('mx2', '<f4'), ('mx3', '<f4'), # x terms ('my', '<f4'), ('my2', '<f4'), ('my3', '<f4'), # y terms ('mxy', '<f4'), ('mx2y', '<f4'), ('mxy2', '<f4'), # cross terms ('x0', '<f4') ] # 0th order shift shift_maps = np.zeros(2 * (n_chan - 1), dtype=shift_map_dtype) mdh = NestedClassMDHandler(inp.mdh) mdh['Multiview.shift_map.legend'] = {} for ii in range(n_chan): chan_mask = (chan == ii) x_chan = np.zeros(n_mols) y_chan = np.zeros(n_mols) x_chan_std = np.zeros(n_mols) y_chan_std = np.zeros(n_mols) for ind in range(n_mols): # merge clumps within channels clump_mask = np.where( np.logical_and(chan_mask, clump_id == mol_list[ind])) x_chan[ind] = x[clump_mask].mean() y_chan[ind] = y[clump_mask].mean() x_chan_std[ind] = x[clump_mask].std() y_chan_std[ind] = y[clump_mask].std() x_clump.append(x_chan) y_clump.append(y_chan) x_std.append(x_chan_std) y_std.append(y_chan_std) if ii > 0: dx[ii - 1, :] = x_clump[0] - x_clump[ii] dy[ii - 1, :] = y_clump[0] - y_clump[ii] dx_err[ii - 1, :] = np.sqrt(x_std[ii]**2 + x_std[0]**2) dy_err[ii - 1, :] = np.sqrt(y_std[ii]**2 + y_std[0]**2) # generate shiftmap between ii-th channel and the 0th channel dxx, dyy, spx, spy, good = twoColour.genShiftVectorFieldQ( x_clump[0], y_clump[0], dx[ii - 1, :], dy[ii - 1, :], dx_err[ii - 1, :], dy_err[ii - 1, :]) # store shiftmaps in structured array mdh['Multiview.shift_map.legend']['Chan0%s.X' % ii] = 2 * (ii - 1) mdh['Multiview.shift_map.legend']['Chan0%s.Y' % ii] = 2 * (ii - 1) + 1 for ki in range(len(shift_map_dtype)): k = shift_map_dtype[ki][0] shift_maps[2 * (ii - 1)][k] = spx.__getattribute__(k) shift_maps[2 * (ii - 1) + 1][k] = spy.__getattribute__(k) # shift_maps['Chan0%s.X' % ii], shift_maps['Chan0%s.Y' % ii] = spx.__dict__, spy.__dict__ mdh['Multiview.shift_map.model'] = '.'.join( [spx.__class__.__module__, spx.__class__.__name__]) namespace[self.output_name] = tabular.RecArraySource(shift_maps) namespace[self.output_name].mdh = mdh
def execute(self, namespace): from PYME.Analysis.points import surfit data_source = namespace[self.input] # arrange point data in the format we expect points = np.vstack([ data_source['x'].astype('f'), data_source['y'].astype('f'), data_source['z'].astype('f') ]) # do the actual fitting - this fits one surface for every point in the dataset results = surfit.fit_quad_surfaces_Pr( points.T, self.fit_influence_radius, fitPos=(not self.constrain_surface_to_point)) # calculate a radius of curvature from our polynomials raw_fits = tabular.MappingFilter(tabular.RecArraySource(results)) raw_fits.setMapping('r_curve', '1./(np.abs(A) + np.abs(B) + 1e-6)' ) # cap max at 1e6 instead of inf raw_fits.mdh = data_source.mdh namespace[self.output_fits_raw] = raw_fits # filter surfaces and throw out patches with normals that don't point approx. the same way as their neighbors results = surfit.filter_quad_results(results, points.T, self.fit_influence_radius, self.alignment_threshold) # again, add radius of curvature calculation with lazy evaluation filtered_fits = tabular.MappingFilter( tabular.RecArraySource(results.view(surfit.SURF_PATCH_DTYPE_FLAT))) filtered_fits.setMapping('r_curve', '1./(np.abs(A) + np.abs(B) + 1e-6)') filtered_fits.mdh = data_source.mdh namespace[self.output_fits_filtered] = filtered_fits # reconstruct the surface by generating an augmented point data set for each surface, adding virtual # localizations spread evenly across each surface patch. Note this is done on the filtered fits. if self.limit_reconstruction_to_support_hull: xs, ys, zs, xn, yn, zn, N, j = surfit.reconstruct_quad_surfaces_Pr_region_cropped( results, self.reconstruction_radius, points.T, fit_radius=self.fit_influence_radius, step=self.reconstruction_point_spacing) else: xs, ys, zs, xn, yn, zn, N, j = surfit.reconstruct_quad_surfaces_Pr( results, self.reconstruction_radius, step=self.reconstruction_point_spacing) j = j.astype(int) try: # duck-type probe; note we assume surface was fit to single-color data probe = np.ones_like(xs) * data_source['probe'][0] except KeyError: probe = np.zeros_like(xs) # construct a new datasource with our augmented points reconstruction = tabular.MappingFilter({ 'x': xs, 'y': ys, 'z': zs, 'xn': xn, 'yn': yn, 'zn': zn, 'probe': probe, 'n_points_fit': N, 'patch_id': j, 'r_curve': filtered_fits['r_curve'][j] }) reconstruction.mdh = data_source.mdh namespace[self.output_surface_reconstruction] = reconstruction
def OnMeasure(self, event): from PYME.Analysis.points import objectMeasure pipeline = self.visFr.pipeline chans = pipeline.colourFilter.getColourChans() # If we're not using objectIDs from an image, look for other clustering labels # TODO - rather than trying a few pre-set objectID alternatives, make this a dialog instead # - look for objectID and carry on if present # - if not present, display a dialog "No objectID found - did you segment objects? Either cancel, # segment, and come back, or choose an alternative column to use as an ID. keys = ['objectID', 'dbscanClumpID', 'clumpIndex'] key = 'objectID' for k in keys: try: ids = set(pipeline.mapping[k].astype('i')) key = k break except (KeyError): continue # ids = set(pipeline.mapping['objectID'].astype('i')) pipeline.objectMeasures = {} if len(chans) == 0: pipeline.objectMeasures[ 'Everything'] = objectMeasure.measureObjectsByID( pipeline.colourFilter, 10, ids, key) from PYME.ui import recArrayView f = recArrayView.ArrayFrame(pipeline.objectMeasures['Everything'], parent=self.visFr, title='Object Measurements') f.Show() else: curChan = pipeline.colourFilter.currentColour chanNames = chans[:] # if 'Sample.Labelling' in metadata.getEntryNames(): # lab = metadata.getEntry('Sample.Labelling') # # for i in range(len(lab)): # if lab[i][0] in chanNames: # chanNames[chanNames.index(lab[i][0])] = lab[i][1] for ch, i in zip(chans, range(len(chans))): pipeline.colourFilter.setColour(ch) #fitDecayChan(colourFilter, metadata, chanNames[i], i) pipeline.objectMeasures[ chanNames[i]] = objectMeasure.measureObjectsByID( pipeline.colourFilter, 10, ids, key) pipeline.colourFilter.setColour(curChan) from PYME.ui import recArrayView from PYME.IO import tabular from PYME.recipes.tablefilters import AggregateMeasurements om = { k: tabular.RecArraySource(v) for k, v in pipeline.objectMeasures.items() } args = {} for i, name in enumerate(chanNames): args['inputMeasurements%d' % (i + 1)] = name args['suffix%d' % (i + 1)] = ('_' + name) args['outputName'] = 'aggregated' agg = AggregateMeasurements(**args) agg.execute(om) f = recArrayView.ArrayFrame(om['aggregated'], parent=self.visFr, title='Object Measurements') f.Show()
def histfitting(colourFilter, metadata, cluster_idxs, fit_order, num_bins, blink_on_label, blink_off_label, to_json=False, log_bins=False, n_on_bins=1, n_off_bins=1, fixed_on_max=-1, fixed_off_max=-1): import matplotlib as plt from PYME.IO import tabular # for best number of bins, find number of different on duration times, set as number of bins # should probably include this as an option in traits ui, I.E. do you want to manually set num bins or set to # max number of unique states (blink duration, time to next blink, etc) N = fit_order """ should add traits thing where this line can be used or set to 1 """ frame_duration = metadata.getEntry('Camera.IntegrationTime') on_times = colourFilter[blink_on_label].astype('f') #* frame_duration on_times = [np.int(i) for i in on_times] # print('is it being loaded correctly 1?', on_times) """ setting up binning for histogram(s) this might not be correct, check again """ # max_on = np.max(on_times) + frame_duration # if fixed_on_max == -1: # fixed_on_max = on_times.max() # if log_bins: # binning = np.logspace(0.5, fixed_on_max + 1, num=n_on_bins) # else: binning = np.arange(frame_duration, max(on_times), 1) print('max on time', max(on_times)) # if len(binning) < 20 # binning = np.linspace(0, 30, 30) vals, bin_edges = np.histogram( on_times, bins=binning) #here, take 2-ed vals = vals[2:] np.set_printoptions(threshold=100000, suppress=True) # print('on y hist', len(vals), vals) logonbins = np.logspace(0, 1.49136169383, num=max(on_times)) logvals, logbinedges = np.histogram(on_times, bins=logonbins) np.set_printoptions(threshold=100000, suppress=True) print('log scale on vals', logvals) # logoff_vals, log_bin_edges_off = np.histogram() bin_edges *= frame_duration """ clip vectors here """ y_hist = vals bin_starts = bin_edges[:-1] x_hist = bin_starts max_xaxis = max(bin_edges) off_times = colourFilter[blink_off_label].astype('f') # print('is it being loaded right 2?', off_times) # min_off = min(off_times) # max_off = max(off_times) + frame_duratio logoffbins = np.logspace(0, 4.92471852852, num=30) logoff_vals, log_bin_edges_off = np.histogram(off_times, bins=logoffbins) print('log scale off vals', logoff_vals) if fixed_off_max == -1: fixed_off_max = off_times.max() # if log_bins: # binning_off = np.logspace(frame_duration, fixed_off_max + 1, num=30) # binning_off = np.logspace(-.60205999132, 4.92471852852, num=30) # # print(binning_off) # else: binning_off = np.arange(0.5, fixed_off_max + 1, n_off_bins) vals_off, bin_edges_off = np.histogram(off_times, bins=binning_off) """ brute force print statement for getting sims going before retreat """ np.set_printoptions(threshold=100000, suppress=True) # print('off y hist vals', len(vals_off), vals_off) bin_edges_off *= frame_duration y_hist_off = vals_off bin_starts_off = bin_edges_off[:-1] x_hist_off = bin_starts_off max_xaxis_off = max(bin_edges_off) # getting start params from integrated fit vals = np.array(vals) on_t_in_t = [i * frame_duration for i in on_times] off_t_in_t = [i * frame_duration for i in off_times] if N == 1: res_fxn = tfoef fit_fxn = sefm # print('what is going wrong here?') # print(max(vals), vals) # print(on_times, frame_duration) # print(np.mean(on_t_in_t)) start_params = [max(vals), 1.0 / np.mean(on_t_in_t)] # start_params = [40417, 5.608, 0] start_params_off = [max(vals_off), 1.0 / np.mean(off_t_in_t)] fit_eqn = 'A*e^(-B*x)' if N == 2: res_fxn = tsoef fit_fxn = defm start_params = [(np.max(vals), 1.0 / np.mean(on_t_in_t), np.max(vals), 5.0 / np.mean(on_t_in_t))] start_params_off = [(np.max(vals_off), 1.0 / np.mean(off_t_in_t), np.max(vals_off), 5.0 / np.mean(off_t_in_t))] fit_eqn = 'A*e^(-B*x) + C*e^(-D*x)' params = start_params fit_results = FitModel_N(res_fxn, params, x_hist[1:], y_hist[1:]) # # plt.figure() # plt.plot(x_hist_off[1:], y_hist[1:]) fit_results_off = FitModel_N(res_fxn, start_params_off, x_hist_off[1:], y_hist_off[1:]) cov = np.linalg.inv(np.matmul( fit_results.jac.T, fit_results.jac)) * np.mean( (fit_results.fun * fit_results.fun).sum()) # print('test 1', fit_results_off.jac.T) # print('test 2', fit_results_off.jac) # print(np.matmul(fit_results_off.jac.T, fit_results_off.jac)) # print(np.linalg.inv(np.matmul(fit_results_off.jac.T, fit_results_off.jac))) cov_off = np.linalg.inv( np.matmul(fit_results_off.jac.T, fit_results_off.jac)) * np.mean( (fit_results_off.fun * fit_results_off.fun).sum()) fitErrors_on = np.sqrt(np.diag(cov)) fitErrors_off = np.sqrt(np.diag(cov_off)) # fitErrors_off = 1.1 x_on_fit = np.linspace(0, max_xaxis, 100) y_on_fit = fit_fxn(x_on_fit, *fit_results.x) x_off_fit = np.linspace(0, max_xaxis_off, 100) y_off_fit = fit_fxn(x_off_fit, *fit_results_off.x) on_hist_datasource = np.rec.fromarrays((y_hist, bin_edges[1:]), dtype=[('y_hist', '<f4'), ('x_hist', '<f4')]) off_hist_datasource = np.rec.fromarrays((y_hist_off, bin_edges_off[1:]), dtype=[('y_hist', '<f4'), ('x_hist', '<f4')]) filt_on = tabular.RecArraySource(on_hist_datasource.view(np.recarray)) filt_off = tabular.RecArraySource(off_hist_datasource.view(np.recarray)) """ trying to get relevant files into metadata """ if USE_GUI: plt.figure() plt.bar(bin_starts, vals, width=bin_starts[1] - bin_starts[0], alpha=.4) # plt.scatter(x_hist[1:], y_hist[1:]) plt.plot(x_on_fit, y_on_fit) # plt.xscale('') xx = max(plt.xlim()) yy = max(plt.ylim()) if N == 1: plt.text(xx * .3, yy * .5, r'$y = Ae ^{-Bx} + C$') #, transform=plt.gca()) plt.text( xx * .3, yy * .45, 'A= %5.2f +/- %5.2f' % (fit_results.x[0], fitErrors_on[0])) plt.text( xx * .3, yy * .40, 'B= %5.2f +/- %5.2f' % (fit_results.x[1], fitErrors_on[1])) # plt.text(xx * .3, yy * .35, 'C= %5.2f +/- %5.2f' % (fit_results.x[2], fitErrors_on[2])) elif N == 2: plt.text(xx * .3, yy * .6, r'$y = Ae^{-B*x} + C e^{-D*x}$') plt.text( xx * .3, yy * .55, 'A= %5.2f +/- %5.2f' % (fit_results.x[0], fitErrors_on[0])) plt.text( xx * .3, yy * .5, 'B= %5.2f +/- %5.2f' % (fit_results.x[1], fitErrors_on[1])) plt.text( xx * .3, yy * .45, 'C= %5.2f +/- %5.2f' % (fit_results.x[2], fitErrors_on[2])) plt.text( xx * .3, yy * .4, 'D= %5.2f +/- %5.2f' % (fit_results.x[3], fitErrors_on[3])) # plt.text(xx * .3, yy * .35, 'E= %5.2f +/- %5.2f' % (fit_results.x[4], fitErrors_on[2])) plt.ylabel('Events') plt.xlabel('Blink duration') plt.title('Blink On Duration') fig, ax = plt.subplots(1, 1) ax.scatter(x_hist, y_hist - fit_fxn(x_hist, *fit_results.x)) ax.set_ylabel('Residual') ax.set_xlabel('Blink duration') ax.set_title('Blink On Duration residuals') # now, this is getting hists & fits for time to next blink values plt.figure() plt.bar(bin_starts_off, vals_off, width=bin_starts_off[1] - bin_starts_off[0], alpha=.4) # plt.scatter(x_hist_off[1:], y_hist_off[1:]) plt.plot(x_off_fit, y_off_fit) xx2 = max(plt.xlim()) yy2 = max(plt.ylim()) if N == 1: plt.text(xx2 * .3, yy2 * .6, r'$y = Ae ^{-Bx} + C$') plt.text( xx2 * .3, yy2 * .55, 'A= %5.2f +/- %5.2f' % (fit_results_off.x[0], fitErrors_off[0])) plt.text( xx2 * .3, yy2 * .50, 'B= %5.2f +/- %5.2f' % (fit_results_off.x[1], fitErrors_off[1])) # plt.text(xx2 * .3, yy2 * .35, 'C= %5.2f +/- %5.2f' % (fit_results_off.x[2], fitErrors_off[2])) elif N == 2: plt.text(xx2 * .3, yy2 * .6, r'$y = Ae^{-B*x} + C e^{-D*x}$') plt.text( xx2 * .3, yy2 * .55, 'A= %5.2f +/- %5.2f' % (fit_results_off.x[0], fitErrors_off[0])) plt.text( xx2 * .3, yy2 * .5, 'B= %5.2f +/- %5.2f' % (fit_results_off.x[1], fitErrors_off[1])) plt.text( xx2 * .3, yy2 * .45, 'C= %5.2f +/- %5.2f' % (fit_results_off.x[2], fitErrors_off[2])) plt.text( xx2 * .3, yy2 * .4, 'D= %5.2f +/- %5.2f' % (fit_results_off.x[3], fitErrors_off[3])) # plt.text(xx2 * .3, yy2 * .35, 'E= %5.2f +/- %5.2f' % (fit_results_off.x[4], fitErrors_off[2])) plt.ylabel('Events') plt.xlabel('Time to next blink') plt.title('Time to next blink in the same cluster') fig, ax = plt.subplots(1, 1) ax.scatter(x_hist_off, y_hist_off - fit_fxn(x_hist_off, *fit_results_off.x)) ax.set_ylabel('Residual') ax.set_xlabel('Time to next blink') ax.set_title('Time to next blink residuals') if to_json == True: import io import time import json try: to_unicode = unicode except NameError: to_unicode = str # Generate dye kinetics structure for JSON file dk = {} dk['plog'] = [0, 0] if log_bins: dk['tlog'] = [1, 1] else: dk['tlog'] = [0, 0] dk['tmin'] = [bin_edges[0], bin_edges_off[0]] dk['tmax'] = [bin_edges[-1], bin_edges_off[-1]] dk['off'] = y_hist_off.tolist() dk['on'] = y_hist.tolist() # Write JSON file timestr = time.strftime("%Y%m%d-%H%M%S") with io.open('empirical_histograms_' + timestr + '.json', 'w', encoding='utf8') as outfile: str_ = '{"dk": ' + json.dumps(dk) + '}' outfile.write(to_unicode(str_)) params_on = fit_results.x params_off = fit_results_off.x return filt_on, filt_off, params_on, params_off, fitErrors_on, fitErrors_off, fit_eqn
def g_histfitting(colourFilter, metadata, cluster_ids, blink_ids, N_bins): #geometric and negative binomial fitting from PYME.IO import tabular # N_bins = # frame_duration = metadata.getEntry('Camera.IntegrationTime') # frame_duration = metadata.getEntry('Camera.CycleTime') """ Important to note: blinks per cluster does nto exist as callable value in pipeline, have to create in this fxn call data from pipeline needed: dbscabcluster, blink id? """ # I = np.argsort(colourFilter[cluster_ids]) # print(pl['dbscanClustered'][I]) # bpc = np.zeros_like(np.unique(colourFilter[cluster_ids]))# blinks per cluster # cid = np.arange(1, max(colourFilter[cluster_ids])+1, 1) # print('cid vec', cid) # print('just before loop', len(np.unique(colourFilter[cluster_ids]))) # for i in range(1, len(np.unique(colourFilter[cluster_ids])) + 1): # nblinks = len(colourFilter[blink_ids][I][colourFilter[cluster_ids] == i]) # bpc[i-1] = nblinks # print(i, nblinks) _, bpc_2 = np.unique(colourFilter[cluster_ids], return_counts=True) print('any points where bps = 0?', np.where(bpc_2 == 0)) plt.hist(bpc_2, bins=20) plt.figure() # plt.hist(bpc, bins=20) # binning = np.linspace(1, np.max(bpc_2), np.max(bpc_2)) vals, bin_edges = np.histogram(bpc_2, bins=np.max(bpc_2) / 5, density=True) print('hist stuff', vals, bin_edges) # x_data = on_times y_hist = vals bin_starts = bin_edges[:-1] bin_ends = bin_edges[1:] x_hist = (bin_starts + bin_ends) / 2 params_on = np.array([.1]) geofit = FitModel_N(grff, params_on, x_hist, y_hist) # print('p value from geo fit', geofit.x) # plt.figure() # plt.plot(np.linspace(min(x_hist), max(x_hist), 100), gfm(np.linspace(min(x_hist), max(x_hist), 100), geofit.x)) # nb_params = np.array([2.0, geofit.x[0]]) # print('nb_params: ', nb_params) # nbfit = FitModel_N(nbrff, nb_params, x_hist, y_hist) # N = nbfit.x[0] # p = nbfit.x[1] x_fit = np.linspace(min(bin_edges), max(bin_edges), max(bin_edges) * 10) y_fit = gfm(x_fit, geofit.x) # hist_datasource = np.rec.fromarrays((y_hist, x_hist), dtype=[('y_hist', '<f4'), ('x_hist', '<f4')]) # hist_data = tabular.RecArraySource(hist_datasource.view(np.recarray)) # filt_off = tabular.recArrayInput(off_hist_datasource.view(np.recarray)) """ have fit for both N and p simultaneously, also want to make one that fits based on p as found in geo fit maybe make a button to determine which one? """ geo_cov = np.linalg.inv(np.matmul(geofit.jac.T, geofit.jac)) * np.mean( (geofit.fun * geofit.fun).sum()) # nb_cov = np.linalg.inv(np.matmul(nbfit.jac.T, nbfit.jac)) * np.mean( # (nbfit.fun * nbfit.fun).sum()) fitErrors_geo = np.sqrt(np.diag(geo_cov)) # fitErrors_nb = np.sqrt(np.diag(nb_cov)) # print('bpc', len(bpc), max(bpc), min(bpc), len(np.unique(bpc)), bpc) if USE_GUI: plt.bar(bin_starts, vals, width=bin_starts[1] - bin_starts[0], alpha=.4) plt.plot(x_fit, y_fit) plt.xlim([0, 200]) xx3 = max(plt.xlim()) yy3 = max(plt.ylim()) cv = min(plt.xlim()) # r'$y = Ae ^{-Bx} + C$' r'$y = p(1-p)^{x}$' plt.text(((xx3 - cv) * .3) + cv, yy3 * .7, r'$y = p(1-p)^{x}$') plt.text(((xx3 - cv) * .3) + cv, yy3 * .6, 'p= %5.2f +/- %5.2f' % (geofit.x, fitErrors_geo)) # plt.text(xx3 * .3, yy3 * .45, 'p= %5.2f' % (geofit.x)) plt.title(r'$mE0s3.2-CAAX$') plt.xlabel('Number of blinks per molecule') plt.ylabel('Probability') # negative binomial fitting # plt.figure() # plt.bar(bin_starts, vals, width=bin_starts[1] - bin_starts[0], alpha=.4) # plt.plot(x_fit, nbmf(x_fit, N, p)) # xx4 = max(plt.xlim()) # yy4 = max(plt.ylim()) # cv2 = min(plt.xlim()) # plt.text(((xx4-cv2)*.1) + cv2, yy4 * .9, 'Number of molecules N = %5.2f, off probability = %5.2f' % (N, p)) # plt.title('Negative Binomial fit for both N and p') # plt.text(xx2 * .3, yy2 * .45, ) """ hist_data = hist_data params_geo = geofit.x params_nb = nbfit.x fitErrors_geo = fitErrors_nb = fit_eqn_geo = fit_eqn_nb = """ return hist_data, geofit.x, fitErrors_geo, #, fit_eqn_geo, fit_eqn_nb
def execute(self, namespace): from scipy.ndimage import center_of_mass from PYME.IO.MetaDataHandler import DictMDHandler from PYME.IO import tabular chan0 = namespace[self.input_chan0] mdh = DictMDHandler() mdh.copyEntriesFrom(chan0.mdh) vx, vy, vz = chan0.voxelsize chan0 = np.stack([ chan0.data[:, :, t, 0].squeeze() for t in range(chan0.data.shape[2]) ], axis=2) mask0 = namespace[self.input_mask0] mask0 = np.stack([ mask0.data[:, :, t, 0].squeeze() for t in range(mask0.data.shape[2]) ], axis=2) mask0 = mask0 > 0 chan1 = namespace[self.input_chan1] chan1 = np.stack([ chan1.data[:, :, t, 0].squeeze() for t in range(chan1.data.shape[2]) ], axis=2) mask1 = namespace[self.input_mask1] mask1 = np.stack([ mask1.data[:, :, t, 0].squeeze() for t in range(mask1.data.shape[2]) ], axis=2) mask1 = mask1 > 0 com0 = center_of_mass(chan0, mask0) # [px] com1 = center_of_mass(chan1, mask1) ox = vx * (com0[0] - com1[0]) # [nm] oy = vy * (com0[1] - com1[1]) oz = vz * (com0[2] - com1[2]) offset = np.sqrt((ox**2) + (oy**2) + (oz**2)) n0 = mask0.sum() n1 = mask1.sum() n_total = n0 + n1 mask_both = mask0 * mask1 intensity_overlap = (mask_both * (chan0 + chan1)).sum() intensity0 = (chan0 * mask0).sum() intensity1 = (chan1 * mask1).sum() intensity_total = intensity0 + intensity1 n_overlapping = np.sum(mask0 * mask1) out = np.empty((1, ), dtype=self._dtype) out[0]['offset'] = offset out[0]['com0'] = com0 out[0]['com1'] = com1 out[0]['n_overlapping'] = n_overlapping out[0]['n_0'] = n0 out[0]['n_1'] = n1 out[0]['n_total'] = n_total out[0]['fractional_volume_overlap'] = n_overlapping / n_total out[0][ 'fractional_intensity_overlap'] = intensity_overlap / intensity_total out[0]['intensity_total'] = intensity_total out[0]['intensity0'] = intensity0 out[0]['intensity1'] = intensity1 out = tabular.RecArraySource(out) out.mdh = mdh namespace[self.output_name] = out