-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
9 changed files
with
2,391 additions
and
0 deletions.
There are no files selected for viewing
Binary file not shown.
Large diffs are not rendered by default.
Oops, something went wrong.
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
"""default values for each data type""" | ||
|
||
default_values_HF = { | ||
'Downsampling rate': '30', | ||
'Butterworth filter degree': '4', | ||
'Cut-off frequency': '0.005', | ||
'Force threshold, pN': '5', | ||
'Z-score': '3', | ||
'Step d': '10', | ||
'Moving median window size': '800', | ||
'STD difference threshold': '0.05', | ||
'Data frequency, Hz': '1000' | ||
} | ||
|
||
default_values_LF = { | ||
'Downsampling rate': '1', | ||
'Butterworth filter degree': '2', | ||
'Cut-off frequency': '0.5', | ||
'Force threshold, pN': '5', | ||
'Z-score': '3', | ||
'Step d': '3', | ||
'Moving median window size': '20', | ||
'STD difference threshold': '0.05', | ||
'Data frequency, Hz': '1000' | ||
} | ||
|
||
default_values_CSV = { | ||
'Downsampling rate': '2', | ||
'Butterworth filter degree': '4', | ||
'Cut-off frequency': '0.005', | ||
'Force threshold, pN': '5', | ||
'Z-score': '3', | ||
'Step d': '10', | ||
'Moving median window size': '250', | ||
'STD difference threshold': '0.05', | ||
'Data frequency, Hz': '1000' | ||
} | ||
|
||
default_values_FIT = { | ||
'Persistance-Length ds, nm': '40', | ||
'Persistance-Length ds, upper bound, nm': '80', | ||
'Persistance-Length ds, lower bound, nm': '12', | ||
'Persistance-Length ss, nm': '1', | ||
'Contour-Length ds, nm': '1256', | ||
'Contour-Length ss, nm': '0', | ||
'Stiffness ds, pN': '500', | ||
'Stiffness ds, upper bound, pN': '600', | ||
'Stiffness ds, lower bound, pN': '400', | ||
'Stiffness ss, pN': '800', | ||
'Force offset, pN': '0', | ||
'Force offset, upper bound, pN': '3', | ||
'Force offset, lower bound, pN': '-3', | ||
'Distance offset, nm': '0', | ||
'Distance offset, upper bound, nm': '300', | ||
'Distance offset, lower bound, nm': '-300' | ||
} | ||
|
||
default_values_constantF = { | ||
'x min': '0', | ||
'x max': '180', | ||
'y min': '1290', | ||
'y max': '1320', | ||
'Number gauss': '3', | ||
'Mean': '1295,1310,1317', | ||
'STD': '1,1,1', | ||
'Amplitude': '10000,5000,10000' | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,221 @@ | ||
|
||
from tkinter import filedialog | ||
import matplotlib.pyplot as plt | ||
import h5py | ||
import numpy as np | ||
import time | ||
import pylab | ||
from scipy.optimize import curve_fit | ||
from scipy.integrate import simps | ||
import pandas as pd | ||
|
||
from POTATO_preprocessing import preprocess_RAW | ||
|
||
|
||
# asks for a constant force file, opens and preprocesses the data | ||
def get_constantF(input_settings, input_format, input_constantF): | ||
global analysis_folder | ||
|
||
# open constant force data in csv or h5 format | ||
file = filedialog.askopenfilename() | ||
# get the directory of the selected file and create a path for the analysis folder | ||
timestamp = time.strftime("%Y%m%d-%H%M%S") | ||
path_split = file.split('/') | ||
directory = '/'.join(path_split[:-1]) | ||
|
||
# check selected input format | ||
if input_format['CSV'] == 1: | ||
with open(file, "r") as f: | ||
df = pd.read_csv(file) | ||
# access the raw data | ||
Force_1x = df.to_numpy()[:, 0] | ||
Distance_1x = df.to_numpy()[:, 1] | ||
# accessing the data frequency from user input | ||
Frequency_value = input_settings['data_frequency'] | ||
Force_Distance, Force_Distance_um = preprocess_RAW(Force_1x, Distance_1x, input_settings) | ||
|
||
filename = path_split[-1][:-4] | ||
analysis_folder = str(directory + '/Analysis_constantF_' + filename + '_' + timestamp) | ||
|
||
else: | ||
with h5py.File(file, "r") as f: | ||
filename = path_split[-1][:-3] | ||
analysis_folder = str(directory + '/Analysis_constantF_' + filename + '_' + timestamp) | ||
|
||
if input_format['HF'] == 1: | ||
# opening file and get the raw h5 values | ||
Force_1x = f.get("Force HF/Force 1x") | ||
Distance_1x = f.get("Distance/Piezo Distance") | ||
# accessing the data frequency from the h5 file | ||
Frequency_value = Force_1x.attrs['Sample rate (Hz)'] | ||
Force_Distance, Force_Distance_um = preprocess_RAW(Force_1x, Distance_1x, input_settings) | ||
|
||
elif input_format['LF'] == 1: | ||
load_force = f.get("Force LF/Force 1x") | ||
Force_1x = load_force[:]['Value'][:] | ||
load_distance = f.get("Distance/Distance 1")[:] | ||
Distance_1x = load_distance['Value'][:] | ||
Force_Distance = np.column_stack((Force_1x, Distance_1x)) | ||
|
||
# calculating the data frequency based on start- and end-time of the measurement | ||
size_F_LF = len(Force_1x) | ||
stop_time_F_LF = load_force.attrs['Stop time (ns)'] | ||
start_time_F_LF = load_force.attrs['Start time (ns)'] | ||
Frequency_value = size_F_LF / ((stop_time_F_LF - start_time_F_LF) / 10**9) | ||
|
||
Force_Distance, Force_Distance_um = preprocess_RAW(Force_1x, Distance_1x, input_settings) | ||
|
||
return Force_Distance, Force_Distance_um, Frequency_value, filename, analysis_folder, timestamp | ||
|
||
|
||
# function for a gaussian to fit onto the constant force data | ||
def gauss(x, mu, sigma, A): | ||
return A * pylab.exp(-(x - mu)**2 / 2 / sigma**2) | ||
|
||
|
||
# depending on how many gaussians should be fitted, this function summs them | ||
def sum_gauss(x, *args): | ||
sum = 0 | ||
fit_number = int(len(args) / 3) | ||
for i in range(fit_number): | ||
sum = sum + gauss(x, args[i], args[i + fit_number], args[i + 2 * fit_number]) | ||
return sum | ||
|
||
|
||
# for the fit, values have to be guessed so that the fit can be optimized easily | ||
def expected_modal(input_constantF): | ||
# get the input values for the fit guesses (specified in POTATO_config and the GUI) | ||
mu = input_constantF['Mean'].split(',') | ||
mu_map = map(int, mu) | ||
mu = list(mu_map) | ||
sigma = input_constantF['STD'].split(',') | ||
sigma_map = map(int, sigma) | ||
sigma = list(sigma_map) | ||
A = input_constantF['Amplitude'].split(',') | ||
A_map = map(int, A) | ||
A = list(A_map) | ||
|
||
return mu, sigma, A | ||
|
||
|
||
# display constant force data in the GUI to perform guesses on the fit | ||
def display_constantF(FD, FD_um, frequency, input_settings, input_constantF): | ||
global Figure_constantF | ||
|
||
"""set constant axes-values""" | ||
x_min = input_constantF['x min'] | ||
x_max = input_constantF['x max'] | ||
y_min = input_constantF['y min'] | ||
y_max = input_constantF['y max'] | ||
|
||
filteredDistance = FD_um[:, 1] | ||
time_Distance = range(0, len(filteredDistance) * input_settings['downsample_value'], input_settings['downsample_value']) | ||
time_vector_D = range(0, len(filteredDistance) * input_settings['downsample_value'], input_settings['downsample_value']) | ||
|
||
time_D = [] | ||
for t in time_vector_D: | ||
time_D.append(t / int(frequency)) | ||
|
||
Distance_time = [] | ||
for t in time_Distance: | ||
Distance_time.append(t / int(frequency)) | ||
|
||
# create a Figure | ||
Figure_constantF, (ax_scatter, ax_histy) = plt.subplots(1, 2, gridspec_kw={'width_ratios': [3, 1]}, sharey=True) | ||
|
||
ax_scatter.set_xlabel('time, s') | ||
ax_scatter.set_ylabel('Distance, nm') | ||
ax_scatter.tick_params(direction='in', top=True, right=True) | ||
ax_scatter.set_xlim(x_min, x_max) | ||
ax_scatter.set_ylim(y_min, y_max) | ||
|
||
# the scatter plot: | ||
filteredDistance_ready = FD[:, 1] | ||
ax_scatter.plot(time_D, filteredDistance_ready) | ||
|
||
binwidth = 0.1 | ||
bins = np.arange(min(filteredDistance_ready), max(filteredDistance_ready), binwidth) | ||
|
||
ax_histy.tick_params(direction='in', labelleft=False) | ||
ax_histy.set_xlabel('counts') | ||
ax_histy.set_ylim(y_min, y_max) | ||
hist_D = ax_histy.hist(filteredDistance_ready, bins=bins, orientation='horizontal', color='k') | ||
|
||
return Figure_constantF, hist_D, filteredDistance_ready | ||
|
||
|
||
# open constant force data and try to fit gaussians on the distance distribution | ||
def fit_constantF(hist_D, FD, filteredDistance_ready, frequency, input_settings, input_constantF, filename_i, timestamp): | ||
|
||
hist_der_value = [] | ||
hist_der_position = [] | ||
|
||
for i in range(1, len(hist_D[0])): | ||
der = (hist_D[0][i] - hist_D[0][i - 1]) / (hist_D[1][i] - hist_D[1][i - 1]) | ||
hist_der_value.append(der) | ||
hist_der_position.append((hist_D[1][i] + hist_D[1][i - 1]) / 2) | ||
|
||
mu, sig, A = expected_modal(input_constantF) | ||
p0 = np.array([mu, sig, A]) | ||
params, cov = curve_fit(sum_gauss, hist_D[1][0:-1], hist_D[0], p0) | ||
fit_number = int(len(params) / 3) | ||
peak_means = [] | ||
sigmas = [] | ||
peak_amplitudes = [] | ||
G = [] | ||
|
||
for i in range(0, fit_number): | ||
peak_means.append(params[i]) | ||
sigmas.append(params[i + fit_number]) | ||
peak_amplitudes.append(params[i + 2 * fit_number]) | ||
G_x = gauss(hist_D[1][0:-1], params[i], params[i + fit_number], params[i + 2 * fit_number]) | ||
G.append(G_x) | ||
|
||
all_param = peak_means + sigmas + peak_amplitudes | ||
tpl_all_param = tuple(all_param) | ||
Gsum = sum_gauss(hist_D[1][0:-1], *tpl_all_param) | ||
|
||
figure2, subplot2 = plt.subplots(1, 1) | ||
|
||
binwidth = 0.1 | ||
bins = np.arange(min(filteredDistance_ready), max(filteredDistance_ready), binwidth) | ||
subplot2.hist(filteredDistance_ready, bins=bins) | ||
|
||
subplot2.plot(hist_D[1][0:-1], Gsum, 'r') | ||
subplot2.plot(peak_means, peak_amplitudes, color='k', linewidth=0, marker='.', markersize=10) | ||
|
||
Areas = [] | ||
for i in G: | ||
subplot2.plot(hist_D[1][0:-1], i, 'k', linestyle='dashed') | ||
Area_gauss = simps(i, hist_D[1][0:-1]) | ||
Areas.append(Area_gauss) | ||
|
||
fractions = [] | ||
for i in range(len(Areas)): | ||
Area_x = Areas[i] | ||
# Area_rest = sum(Areas[:i]) + sum(Areas[i + 1:]) | ||
Area_all = sum(Areas[:]) | ||
A_fraction = Area_x / Area_all | ||
|
||
fractions.append(A_fraction) | ||
|
||
# export csv containing all the computed values | ||
# total_results_export=pd.DataFrame(zip(X_step_data,F_step_data, F, x_WLC, X, x_FJC), columns=['Distance data','Force with step','Force model','WLC distance','WLC + FJC distance', 'FJC distance']) | ||
smooth_export = pd.DataFrame(zip(FD[:, 0], filteredDistance_ready), columns=['Force [pN]', 'Distance [nm]']) | ||
smooth_export.to_csv((analysis_folder + "/" + filename_i + "_" + timestamp + '_smooth.csv'), index=False, header=True) | ||
|
||
# histogram & gaussians | ||
histogram_export = pd.DataFrame(zip(hist_D[1][0:-1], hist_D[0], Gsum, G), columns=['Distance, nm', 'Counts', 'Gaussian sum', 'Gaussians']) | ||
histogram_export.to_csv((analysis_folder + "/" + filename_i + "_" + timestamp + '_histogram.csv'), index=False, header=True) | ||
|
||
# gaussian parameters + areas | ||
table_export = pd.DataFrame(zip(peak_means, sigmas, peak_amplitudes, Areas, fractions), columns=['mean', 'sigma', 'amplitude', 'Area', 'fraction']) | ||
table_export.to_csv((analysis_folder + "/" + filename_i + "_" + timestamp + '_table.csv'), index=False, header=True) | ||
# plots | ||
plotname2 = analysis_folder + "/" + filename_i + "_histogram_fitted" + ".png" | ||
figure2.savefig(plotname2) | ||
|
||
plotname_figure_constant_f = analysis_folder + "/" + filename_i + "_visualization" + ".png" | ||
Figure_constantF.savefig(plotname_figure_constant_f) | ||
|
||
return figure2 |
Oops, something went wrong.